Skip to content

Commit b0c9ce9

Browse files
DvirDukhanCopilot
andcommitted
bench: fix find_symbol exact-match against nested properties.name
Smoke #3 revealed cg find-symbol --name <exact> returned [] for symbols the graph clearly contained (cg auto-complete --prefix found the same symbol with full file:line+docstring). Root cause: the filter compared item['name'] to the requested name, but the /api/auto_complete payload nests the symbol name under item['properties']['name'] (FalkorDB node properties), so the top-level lookup always returned None and nothing matched. Fix: prefer item['properties']['name'], fall back to item['name'] for flatter shapes the unit tests pass in. Added a regression test that uses the real payload structure. Verified end-to-end against the live FastAPI service: cg find-symbol --repo pytest-dev__pytest-6202__code_graph \ --name getmodpath # -> [{id:2714, labels:[Function], properties:{name,path,doc,...}}] This was the bug that made the smoke #3 code_graph agent burn 3 of 5 cg calls retrying exact-name lookups before falling back to auto-complete. With this fix, an agent doing the natural workflow (find-symbol -> get-neighbors -> note-edit) should land far fewer wasted calls. Also: norecursedirs in [tool.pytest.ini_options] to keep pytest from walking into per-instance bench worktrees that ship their own pytest sources (was breaking host pytest's AST rewriter on import). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 13ac345 commit b0c9ce9

3 files changed

Lines changed: 37 additions & 4 deletions

File tree

bench/agents/code_graph_adapter.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,24 @@ def find_symbol(self, repo: str, name: str) -> list[dict[str, Any]]:
102102
103103
auto_complete returns prefix matches; the agent often wants exact
104104
matches. Doing this client-side keeps the FastAPI surface untouched.
105+
106+
The auto_complete payload nests the symbol name under
107+
`item["properties"]["name"]` (FalkorDB node properties), so we look
108+
there first and only fall back to a top-level `name` for older /
109+
flatter shapes the tests may pass in.
105110
"""
106111
payload = self.auto_complete(repo, name)
107112
results = payload.get("completions") or payload.get("results") or payload
108113
if isinstance(results, dict):
109114
results = results.get("items", [])
110-
return [
111-
item for item in (results or [])
112-
if isinstance(item, dict) and item.get("name") == name
113-
]
115+
out: list[dict[str, Any]] = []
116+
for item in (results or []):
117+
if not isinstance(item, dict):
118+
continue
119+
props = item.get("properties") if isinstance(item.get("properties"), dict) else {}
120+
if props.get("name") == name or item.get("name") == name:
121+
out.append(item)
122+
return out
114123

115124
def note_edit(self, repo: str, path: str) -> dict[str, Any]:
116125
"""Tell code-graph the agent just edited `path`; trigger an

pyproject.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ bench = [
3838
markers = [
3939
"slow: marks tests that spawn external subprocesses (LSP servers, FalkorDB, etc.); skip with -m 'not slow'",
4040
]
41+
# Keep pytest from walking into per-instance bench worktrees that contain
42+
# their own copies of pytest source — collecting from those breaks the
43+
# host pytest's AST rewriter.
44+
norecursedirs = ["bench/cache", ".venv", "node_modules", "build", "dist", "*.egg-info"]
4145

4246
[tool.setuptools.packages.find]
4347
where = ["."]

tests/test_bench_code_graph_adapter.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,26 @@ def test_find_symbol_filters_for_exact_match():
8080
assert all(item["name"] == "Foo" for item in out)
8181

8282

83+
def test_find_symbol_reads_nested_properties_name():
84+
# Regression: the real /api/auto_complete payload nests `name` under
85+
# `properties` (FalkorDB node properties). Before this fix every
86+
# exact-name lookup returned [], so the agent fell back to bash grep.
87+
resp = httpx.Response(
88+
200,
89+
json={"completions": [
90+
{"id": 1, "labels": ["Function"],
91+
"properties": {"name": "FooBar", "path": "/a.py"}},
92+
{"id": 2, "labels": ["Function"],
93+
"properties": {"name": "Foo", "path": "/b.py"}},
94+
{"id": 3, "labels": ["Function"],
95+
"properties": {"name": "Foo", "path": "/c.py"}},
96+
]},
97+
)
98+
with _client_with({"POST /api/auto_complete": resp}) as c:
99+
out = c.find_symbol("r", "Foo")
100+
assert [item["id"] for item in out] == [2, 3]
101+
102+
83103
def test_note_edit_calls_analyze_folder_and_reports_path():
84104
resp = httpx.Response(200, json={"status": "ok"})
85105
with _client_with({"POST /api/analyze_folder": resp}) as c:

0 commit comments

Comments
 (0)