Navegador

navegador / docs / guide / sdk.md
Source Blame History 254 lines
89816aa… lmata 1 # Python SDK
89816aa… lmata 2
89816aa… lmata 3 The navegador Python SDK lets you drive ingestion, query the graph, and load context from your own scripts and tools — without going through the CLI.
89816aa… lmata 4
89816aa… lmata 5 ---
89816aa… lmata 6
89816aa… lmata 7 ## Installation
89816aa… lmata 8
89816aa… lmata 9 ```bash
89816aa… lmata 10 pip install navegador
89816aa… lmata 11 ```
89816aa… lmata 12
89816aa… lmata 13 For Redis (production/team) support:
89816aa… lmata 14
89816aa… lmata 15 ```bash
89816aa… lmata 16 pip install "navegador[redis]"
89816aa… lmata 17 ```
89816aa… lmata 18
89816aa… lmata 19 ---
89816aa… lmata 20
89816aa… lmata 21 ## Connecting to the graph
89816aa… lmata 22
89816aa… lmata 23 === "SQLite (local)"
89816aa… lmata 24
89816aa… lmata 25 ```python
89816aa… lmata 26 from navegador.graph import GraphStore
89816aa… lmata 27
89816aa… lmata 28 store = GraphStore.sqlite(".navegador/navegador.db")
89816aa… lmata 29 ```
89816aa… lmata 30
89816aa… lmata 31 === "Redis (production)"
89816aa… lmata 32
89816aa… lmata 33 ```python
89816aa… lmata 34 from navegador.graph import GraphStore
89816aa… lmata 35
89816aa… lmata 36 store = GraphStore.redis("redis://localhost:6379")
89816aa… lmata 37 ```
89816aa… lmata 38
89816aa… lmata 39 Both backends implement the same interface. All examples below work with either.
89816aa… lmata 40
89816aa… lmata 41 Use the context manager to ensure the connection is closed:
89816aa… lmata 42
89816aa… lmata 43 ```python
89816aa… lmata 44 with GraphStore.sqlite(".navegador/navegador.db") as store:
89816aa… lmata 45 results = store.query("MATCH (n) RETURN count(n) AS total")
89816aa… lmata 46 print(results[0]["total"])
89816aa… lmata 47 ```
89816aa… lmata 48
89816aa… lmata 49 ---
89816aa… lmata 50
89816aa… lmata 51 ## Ingestion
89816aa… lmata 52
89816aa… lmata 53 ### Ingest a repo
89816aa… lmata 54
89816aa… lmata 55 ```python
89816aa… lmata 56 from navegador.graph import GraphStore
89816aa… lmata 57 from navegador.ingest import RepoIngester
89816aa… lmata 58
89816aa… lmata 59 store = GraphStore.sqlite(".navegador/navegador.db")
89816aa… lmata 60 ingester = RepoIngester(store)
89816aa… lmata 61
89816aa… lmata 62 result = ingester.ingest("./src")
89816aa… lmata 63 print(f"{result.nodes_created} nodes, {result.edges_created} edges in {result.duration_seconds:.2f}s")
89816aa… lmata 64 ```
89816aa… lmata 65
89816aa… lmata 66 ### Incremental ingest (single file)
89816aa… lmata 67
89816aa… lmata 68 ```python
89816aa… lmata 69 result = ingester.ingest_file("./src/auth/service.py")
89816aa… lmata 70 ```
89816aa… lmata 71
89816aa… lmata 72 ### Wipe and rebuild
89816aa… lmata 73
89816aa… lmata 74 ```python
89816aa… lmata 75 result = ingester.ingest("./src", clear=True)
89816aa… lmata 76 ```
89816aa… lmata 77
89816aa… lmata 78 ### Add knowledge programmatically
89816aa… lmata 79
89816aa… lmata 80 ```python
89816aa… lmata 81 from navegador.ingest import KnowledgeIngester
89816aa… lmata 82
89816aa… lmata 83 ki = KnowledgeIngester(store)
89816aa… lmata 84
89816aa… lmata 85 ki.add_domain("Payments", description="Payment processing and billing")
89816aa… lmata 86 ki.add_concept("Idempotency", domain="Payments",
89816aa… lmata 87 description="Operations safe to retry without side effects")
89816aa… lmata 88 ki.add_rule("RequireIdempotencyKey",
89816aa… lmata 89 domain="Payments", severity="critical",
89816aa… lmata 90 rationale="Card networks retry on timeout")
89816aa… lmata 91 ki.annotate("process_payment", node_type="Function",
89816aa… lmata 92 concept="Idempotency", rule="RequireIdempotencyKey")
89816aa… lmata 93 ```
89816aa… lmata 94
89816aa… lmata 95 ---
89816aa… lmata 96
89816aa… lmata 97 ## Loading context
89816aa… lmata 98
89816aa… lmata 99 `ContextLoader` builds structured context bundles from the graph. Each method corresponds to a CLI command.
89816aa… lmata 100
89816aa… lmata 101 ```python
89816aa… lmata 102 from navegador.graph import GraphStore
89816aa… lmata 103 from navegador.context import ContextLoader
89816aa… lmata 104
89816aa… lmata 105 store = GraphStore.sqlite(".navegador/navegador.db")
89816aa… lmata 106 loader = ContextLoader(store)
89816aa… lmata 107 ```
89816aa… lmata 108
89816aa… lmata 109 ### File context
89816aa… lmata 110
89816aa… lmata 111 ```python
89816aa… lmata 112 bundle = loader.load_file("src/auth/service.py")
89816aa… lmata 113 print(bundle.to_markdown())
89816aa… lmata 114 ```
89816aa… lmata 115
89816aa… lmata 116 ### Function with call graph
89816aa… lmata 117
89816aa… lmata 118 ```python
89816aa… lmata 119 # depth controls how many hops of callers/callees to include
89816aa… lmata 120 bundle = loader.load_function("validate_token", depth=2)
89816aa… lmata 121 print(bundle.to_json())
89816aa… lmata 122 ```
89816aa… lmata 123
89816aa… lmata 124 ### Class hierarchy
89816aa… lmata 125
89816aa… lmata 126 ```python
89816aa… lmata 127 bundle = loader.load_class("PaymentProcessor", file="src/payments/processor.py")
89816aa… lmata 128 data = bundle.to_dict()
89816aa… lmata 129 ```
89816aa… lmata 130
89816aa… lmata 131 ### Universal explain
89816aa… lmata 132
89816aa… lmata 133 ```python
89816aa… lmata 134 # works for any node type: function, class, file, concept, rule, decision
89816aa… lmata 135 bundle = loader.explain("AuthService")
89816aa… lmata 136 bundle = loader.explain("PaymentsMustBeIdempotent")
89816aa… lmata 137 ```
89816aa… lmata 138
89816aa… lmata 139 ### Concept and domain
89816aa… lmata 140
89816aa… lmata 141 ```python
89816aa… lmata 142 bundle = loader.load_concept("Idempotency")
89816aa… lmata 143 bundle = loader.load_domain("Payments")
89816aa… lmata 144 ```
89816aa… lmata 145
89816aa… lmata 146 ---
89816aa… lmata 147
89816aa… lmata 148 ## Search
89816aa… lmata 149
89816aa… lmata 150 ```python
89816aa… lmata 151 # search function and class names (default)
89816aa… lmata 152 nodes = loader.search("rate limit")
89816aa… lmata 153
89816aa… lmata 154 # search all layers including knowledge and docs
89816aa… lmata 155 nodes = loader.search("rate limit", all_layers=True, limit=50)
89816aa… lmata 156
89816aa… lmata 157 # search docstrings and wiki content only
89816aa… lmata 158 nodes = loader.search_by_docstring("retry logic")
89816aa… lmata 159
89816aa… lmata 160 # find all functions using a specific decorator
89816aa… lmata 161 nodes = loader.decorated_by("login_required")
89816aa… lmata 162
89816aa… lmata 163 for node in nodes:
89816aa… lmata 164 print(f"{node.label}: {node.name} ({node.properties.get('file', '')})")
89816aa… lmata 165 ```
89816aa… lmata 166
89816aa… lmata 167 ---
89816aa… lmata 168
89816aa… lmata 169 ## Knowledge queries
89816aa… lmata 170
89816aa… lmata 171 ```python
89816aa… lmata 172 # everything in the Payments domain
89816aa… lmata 173 bundle = loader.load_domain("Payments")
89816aa… lmata 174 for node in bundle.nodes:
89816aa… lmata 175 print(f" [{node.label}] {node.name}")
89816aa… lmata 176
89816aa… lmata 177 # all code annotated with a concept
89816aa… lmata 178 bundle = loader.load_concept("Idempotency")
89816aa… lmata 179 for node in bundle.nodes:
89816aa… lmata 180 if node.layer == "code":
89816aa… lmata 181 print(f" {node.name} {node.properties.get('file', '')}")
89816aa… lmata 182 ```
89816aa… lmata 183
89816aa… lmata 184 ---
89816aa… lmata 185
89816aa… lmata 186 ## Exporting output
89816aa… lmata 187
89816aa… lmata 188 Every `ContextBundle` supports three output formats:
89816aa… lmata 189
89816aa… lmata 190 ```python
89816aa… lmata 191 bundle = loader.load_function("process_payment")
89816aa… lmata 192
89816aa… lmata 193 # JSON string — for agents, APIs, CI
89816aa… lmata 194 json_str = bundle.to_json()
89816aa… lmata 195
89816aa… lmata 196 # Markdown — readable by humans and LLMs
89816aa… lmata 197 md_str = bundle.to_markdown()
89816aa… lmata 198
89816aa… lmata 199 # Python dict — for further processing
89816aa… lmata 200 data = bundle.to_dict()
89816aa… lmata 201 print(data["root"]["name"])
89816aa… lmata 202 print(len(data["nodes"]))
89816aa… lmata 203 ```
89816aa… lmata 204
89816aa… lmata 205 ---
89816aa… lmata 206
89816aa… lmata 207 ## Raw Cypher queries
89816aa… lmata 208
89816aa… lmata 209 Drop to raw Cypher for anything the built-in methods don't cover:
89816aa… lmata 210
89816aa… lmata 211 ```python
89816aa… lmata 212 results = store.query(
89816aa… lmata 213 "MATCH (f:Function)-[:CALLS]->(g:Function) "
89816aa… lmata 214 "WHERE f.file = $file "
89816aa… lmata 215 "RETURN f.name, g.name",
89816aa… lmata 216 params={"file": "src/payments/processor.py"}
89816aa… lmata 217 )
89816aa… lmata 218 for row in results:
89816aa… lmata 219 print(f"{row['f.name']} -> {row['g.name']}")
89816aa… lmata 220 ```
89816aa… lmata 221
89816aa… lmata 222 !!! warning
89816aa… lmata 223 `store.query()` executes writes as well as reads. Stick to `MATCH` / `RETURN` for inspection queries.
89816aa… lmata 224
89816aa… lmata 225 ---
89816aa… lmata 226
89816aa… lmata 227 ## Wiki ingestion
89816aa… lmata 228
89816aa… lmata 229 ```python
89816aa… lmata 230 import os
89816aa… lmata 231 from navegador.ingest import WikiIngester
89816aa… lmata 232
89816aa… lmata 233 ingester = WikiIngester(store)
89816aa… lmata 234
89816aa… lmata 235 # from GitHub API
89816aa… lmata 236 result = ingester.ingest_repo("myorg/myrepo", token=os.environ["GITHUB_TOKEN"])
89816aa… lmata 237
89816aa… lmata 238 # from a locally cloned wiki directory
89816aa… lmata 239 result = ingester.ingest_dir("./myrepo.wiki")
89816aa… lmata 240 ```
89816aa… lmata 241
89816aa… lmata 242 ---
89816aa… lmata 243
89816aa… lmata 244 ## Error handling
89816aa… lmata 245
89816aa… lmata 246 All ingesters return an `IngestionResult` dataclass. Check `errors` for per-file failures without crashing the whole run:
89816aa… lmata 247
89816aa… lmata 248 ```python
89816aa… lmata 249 result = ingester.ingest("./src")
89816aa… lmata 250 if result.errors:
89816aa… lmata 251 for err in result.errors:
89816aa… lmata 252 print(f"Warning: {err}")
89816aa… lmata 253 print(f"Processed {result.files_processed} files, {result.nodes_created} nodes created")
89816aa… lmata 254 ```

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button