fix: align local and server graph depth semantics
This commit is contained in:
@@ -11119,6 +11119,8 @@ def local_memory_context(args, seed_ids):
|
|||||||
nodes[current_id] = compact
|
nodes[current_id] = compact
|
||||||
level_ids.append(current_id)
|
level_ids.append(current_id)
|
||||||
indexed_at = max(indexed_at, str(current["indexed_at"] or ""))
|
indexed_at = max(indexed_at, str(current["indexed_at"] or ""))
|
||||||
|
if current_depth >= depth:
|
||||||
|
continue
|
||||||
candidates = []
|
candidates = []
|
||||||
if direction in {"outgoing", "both"}:
|
if direction in {"outgoing", "both"}:
|
||||||
candidates.extend(conn.execute(
|
candidates.extend(conn.execute(
|
||||||
@@ -11130,18 +11132,24 @@ def local_memory_context(args, seed_ids):
|
|||||||
"SELECT * FROM local_index_edges WHERE project_id = ? AND (target_node_id = ? OR target_path = ?) ORDER BY relation, source_node_id",
|
"SELECT * FROM local_index_edges WHERE project_id = ? AND (target_node_id = ? OR target_path = ?) ORDER BY relation, source_node_id",
|
||||||
(project_id, current_id, current["full_path"]),
|
(project_id, current_id, current["full_path"]),
|
||||||
).fetchall())
|
).fetchall())
|
||||||
|
resolved_candidates = []
|
||||||
for edge in candidates:
|
for edge in candidates:
|
||||||
if relations and edge["relation"] not in relations:
|
if relations and edge["relation"] not in relations:
|
||||||
continue
|
continue
|
||||||
target = node_row(node_id=edge["target_node_id"]) if edge["target_node_id"] else node_row(path=edge["target_path"])
|
target = node_row(node_id=edge["target_node_id"]) if edge["target_node_id"] else node_row(path=edge["target_path"])
|
||||||
if target is None:
|
if target is None:
|
||||||
continue
|
continue
|
||||||
|
resolved_candidates.append((edge, target))
|
||||||
|
resolved_candidates.sort(key=lambda item: (
|
||||||
|
item[0]["source_node_id"],
|
||||||
|
item[1]["node_id"],
|
||||||
|
item[0]["relation"],
|
||||||
|
))
|
||||||
|
for edge, target in resolved_candidates:
|
||||||
source_id = edge["source_node_id"]
|
source_id = edge["source_node_id"]
|
||||||
target_id = target["node_id"]
|
target_id = target["node_id"]
|
||||||
neighbor_id = target_id if source_id == current_id else source_id
|
neighbor_id = target_id if source_id == current_id else source_id
|
||||||
known_neighbor = neighbor_id in seen or neighbor_id in next_ids
|
known_neighbor = neighbor_id in seen or neighbor_id in next_ids
|
||||||
if current_depth >= depth and not known_neighbor:
|
|
||||||
continue
|
|
||||||
if not known_neighbor:
|
if not known_neighbor:
|
||||||
if len(nodes) + len(next_ids) >= max_nodes:
|
if len(nodes) + len(next_ids) >= max_nodes:
|
||||||
frontier.append(neighbor_id)
|
frontier.append(neighbor_id)
|
||||||
|
|||||||
@@ -150,6 +150,48 @@ def test_hybrid_context_falls_back_until_local_graph_coverage_is_complete(mod):
|
|||||||
assert calls == [["root"]]
|
assert calls == [["root"]]
|
||||||
|
|
||||||
|
|
||||||
|
def test_local_context_does_not_emit_edges_beyond_requested_depth(mod):
|
||||||
|
state = tempfile.TemporaryDirectory()
|
||||||
|
mod._surface_depth_state = state
|
||||||
|
mod.AUTH_DIR = pathlib.Path(state.name)
|
||||||
|
mod.INDEX_PATH = mod.AUTH_DIR / "index.sqlite"
|
||||||
|
mod.INDEX_LOCK_PATH = mod.AUTH_DIR / "index.sqlite.lock"
|
||||||
|
nodes = [
|
||||||
|
{
|
||||||
|
"id": "root", "project_id": "project-1", "full_path": "/docs/root",
|
||||||
|
"folder_path": "/docs", "name": "root", "type": "note", "metadata": {},
|
||||||
|
"tags": [], "links": [
|
||||||
|
{"node_id": "left", "relation": "references"},
|
||||||
|
{"node_id": "right", "relation": "references"},
|
||||||
|
], "content_text": "", "updated_at": "2026-08-16T12:00:00Z",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "left", "project_id": "project-1", "full_path": "/docs/left",
|
||||||
|
"folder_path": "/docs", "name": "left", "type": "note", "metadata": {},
|
||||||
|
"tags": [], "links": [{"node_id": "right", "relation": "explains"}],
|
||||||
|
"content_text": "", "updated_at": "2026-08-16T12:01:00Z",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "right", "project_id": "project-1", "full_path": "/docs/right",
|
||||||
|
"folder_path": "/docs", "name": "right", "type": "note", "metadata": {},
|
||||||
|
"tags": [], "links": [], "content_text": "",
|
||||||
|
"updated_at": "2026-08-16T12:02:00Z",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
for item in nodes:
|
||||||
|
mod.index_node(item)
|
||||||
|
|
||||||
|
result = mod.get_memory_context({
|
||||||
|
"node_id": "root", "mode": "local", "depth": 1, "direction": "both",
|
||||||
|
})
|
||||||
|
|
||||||
|
assert {item["id"] for item in result["nodes"]} == {"root", "left", "right"}
|
||||||
|
assert result["edges"] == [
|
||||||
|
{"source": "root", "target": "left", "relation": "references"},
|
||||||
|
{"source": "root", "target": "right", "relation": "references"},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def test_index_sync_upgrades_pre_graph_index_with_full_reindex(mod):
|
def test_index_sync_upgrades_pre_graph_index_with_full_reindex(mod):
|
||||||
state = tempfile.TemporaryDirectory()
|
state = tempfile.TemporaryDirectory()
|
||||||
mod._surface_upgrade_state = state
|
mod._surface_upgrade_state = state
|
||||||
|
|||||||
Reference in New Issue
Block a user