Navegador

navegador / docs / api / graph.md
1
# Graph API
2
3
```python
4
from navegador.graph import GraphStore
5
from navegador.context import ContextLoader, ContextBundle, ContextNode
6
```
7
8
---
9
10
## GraphStore
11
12
The database abstraction layer. Both SQLite and Redis backends implement this interface.
13
14
```python
15
class GraphStore:
16
@classmethod
17
def sqlite(cls, path: str | Path = "navegador.db") -> "GraphStore": ...
18
19
@classmethod
20
def redis(cls, url: str = "redis://localhost:6379") -> "GraphStore": ...
21
22
def query(
23
self,
24
cypher: str,
25
params: dict | None = None,
26
) -> list[dict]: ...
27
28
def create_node(
29
self,
30
label: str,
31
properties: dict,
32
) -> str: ... # returns node ID
33
34
def merge_node(
35
self,
36
label: str,
37
match_properties: dict,
38
set_properties: dict | None = None,
39
) -> str: ... # upsert by match_properties, returns node ID
40
41
def create_edge(
42
self,
43
from_id: str,
44
to_id: str,
45
edge_type: str,
46
properties: dict | None = None,
47
) -> None: ...
48
49
def merge_edge(
50
self,
51
from_label: str,
52
from_match: dict,
53
to_label: str,
54
to_match: dict,
55
edge_type: str,
56
properties: dict | None = None,
57
) -> None: ...
58
59
def clear(self) -> None: ...
60
61
def close(self) -> None: ...
62
63
def export_jsonl(self, fp: IO[str]) -> None: ...
64
"""Write all nodes and edges to a JSONL stream."""
65
66
def import_jsonl(self, fp: IO[str]) -> None: ...
67
"""Read nodes and edges from a JSONL stream and merge into the graph."""
68
```
69
70
### Usage
71
72
```python
73
# SQLite (local dev)
74
store = GraphStore.sqlite(".navegador/navegador.db")
75
76
# Redis (production)
77
store = GraphStore.redis("redis://localhost:6379")
78
79
# raw Cypher query
80
results = store.query(
81
"MATCH (f:Function {name: $name}) RETURN f",
82
params={"name": "validate_token"}
83
)
84
85
# create a node
86
node_id = store.create_node("Concept", {
87
"name": "Idempotency",
88
"description": "Operations safe to retry"
89
})
90
91
# upsert a node (match by name, update description)
92
node_id = store.merge_node(
93
"Concept",
94
match_properties={"name": "Idempotency"},
95
set_properties={"description": "Updated description"}
96
)
97
98
# create an edge
99
store.create_edge(from_id, to_id, "ANNOTATES")
100
101
# wipe the graph
102
store.clear()
103
```
104
105
### Context manager
106
107
`GraphStore` implements the context manager protocol:
108
109
```python
110
with GraphStore.sqlite(".navegador/navegador.db") as store:
111
results = store.query("MATCH (n) RETURN count(n) AS total")
112
```
113
114
---
115
116
## ContextLoader
117
118
Builds structured context bundles from graph queries. Each method corresponds to a CLI command.
119
120
```python
121
class ContextLoader:
122
def __init__(self, store: GraphStore) -> None: ...
123
124
def load_file(self, path: str) -> ContextBundle: ...
125
126
def load_function(
127
self,
128
name: str,
129
*,
130
file: str = "",
131
depth: int = 1,
132
) -> ContextBundle: ...
133
134
def load_class(
135
self,
136
name: str,
137
*,
138
file: str = "",
139
) -> ContextBundle: ...
140
141
def explain(
142
self,
143
name: str,
144
*,
145
file: str = "",
146
) -> ContextBundle: ...
147
148
def load_concept(self, name: str) -> ContextBundle: ...
149
150
def load_domain(self, name: str) -> ContextBundle: ...
151
152
def search(
153
self,
154
query: str,
155
*,
156
all_layers: bool = False,
157
docs_only: bool = False,
158
limit: int = 20,
159
) -> list[ContextNode]: ...
160
161
def search_by_docstring(
162
self,
163
query: str,
164
*,
165
limit: int = 20,
166
) -> list[ContextNode]: ...
167
168
def decorated_by(
169
self,
170
decorator: str,
171
) -> list[ContextNode]: ...
172
```
173
174
### Usage
175
176
```python
177
store = GraphStore.sqlite(".navegador/navegador.db")
178
loader = ContextLoader(store)
179
180
# file context
181
bundle = loader.load_file("src/auth/service.py")
182
183
# function with 2-hop call graph
184
bundle = loader.load_function("validate_token", depth=2)
185
186
# class hierarchy
187
bundle = loader.load_class("PaymentProcessor", file="src/payments/processor.py")
188
189
# universal explain
190
bundle = loader.explain("AuthService")
191
192
# concept with annotated code
193
bundle = loader.load_concept("Idempotency")
194
195
# domain overview
196
bundle = loader.load_domain("Payments")
197
198
# search
199
nodes = loader.search("rate limit", all_layers=True, limit=10)
200
201
# all @login_required functions
202
nodes = loader.decorated_by("login_required")
203
```
204
205
---
206
207
## ContextBundle
208
209
The structured result type returned by `ContextLoader` methods.
210
211
```python
212
@dataclass
213
class ContextBundle:
214
root: ContextNode
215
nodes: list[ContextNode]
216
edges: list[ContextEdge]
217
metadata: dict
218
219
def to_json(self) -> str: ...
220
def to_markdown(self) -> str: ...
221
def to_dict(self) -> dict: ...
222
```
223
224
---
225
226
## ContextNode
227
228
A single node in a context bundle.
229
230
```python
231
@dataclass
232
class ContextNode:
233
id: str
234
label: str # e.g. "Function", "Concept"
235
name: str
236
properties: dict # all node properties
237
layer: str # "code" or "knowledge"
238
```
239
240
---
241
242
## ContextEdge
243
244
```python
245
@dataclass
246
class ContextEdge:
247
from_id: str
248
to_id: str
249
edge_type: str # e.g. "CALLS", "ANNOTATES"
250
properties: dict
251
```
252
253
---
254
255
## Schema migrations
256
257
```python
258
from navegador.graph import migrate
259
260
store = GraphStore.sqlite(".navegador/navegador.db")
261
migrate(store) # applies any pending schema migrations; idempotent
262
```
263
264
The `migrate()` function is safe to call on every startup. It compares the stored migration version against the current schema and applies only missing migrations.
265
266
---
267
268
## Formatting output
269
270
```python
271
bundle = loader.load_function("validate_token")
272
273
# JSON string
274
print(bundle.to_json())
275
276
# Markdown string (for agent consumption)
277
print(bundle.to_markdown())
278
279
# Python dict (for further processing)
280
data = bundle.to_dict()
281
```
282

Keyboard Shortcuts

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