code-review-graph-codeblackwell 2.3.6.post1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- code_review_graph/__init__.py +20 -0
- code_review_graph/__main__.py +4 -0
- code_review_graph/analysis.py +410 -0
- code_review_graph/changes.py +409 -0
- code_review_graph/cli.py +1255 -0
- code_review_graph/communities.py +874 -0
- code_review_graph/constants.py +23 -0
- code_review_graph/context_savings.py +317 -0
- code_review_graph/custom_languages.py +322 -0
- code_review_graph/daemon.py +1009 -0
- code_review_graph/daemon_cli.py +320 -0
- code_review_graph/docs/LLM-OPTIMIZED-REFERENCE.md +71 -0
- code_review_graph/embeddings.py +1006 -0
- code_review_graph/enrich.py +303 -0
- code_review_graph/eval/__init__.py +33 -0
- code_review_graph/eval/benchmarks/__init__.py +1 -0
- code_review_graph/eval/benchmarks/agent_baseline.py +193 -0
- code_review_graph/eval/benchmarks/build_performance.py +60 -0
- code_review_graph/eval/benchmarks/flow_completeness.py +36 -0
- code_review_graph/eval/benchmarks/impact_accuracy.py +220 -0
- code_review_graph/eval/benchmarks/multi_hop_retrieval.py +125 -0
- code_review_graph/eval/benchmarks/search_quality.py +59 -0
- code_review_graph/eval/benchmarks/token_efficiency.py +143 -0
- code_review_graph/eval/configs/code-review-graph.yaml +50 -0
- code_review_graph/eval/configs/express.yaml +45 -0
- code_review_graph/eval/configs/fastapi.yaml +48 -0
- code_review_graph/eval/configs/flask.yaml +50 -0
- code_review_graph/eval/configs/gin.yaml +51 -0
- code_review_graph/eval/configs/httpx.yaml +48 -0
- code_review_graph/eval/reporter.py +301 -0
- code_review_graph/eval/runner.py +211 -0
- code_review_graph/eval/scorer.py +85 -0
- code_review_graph/eval/token_benchmark.py +182 -0
- code_review_graph/exports.py +409 -0
- code_review_graph/flows.py +698 -0
- code_review_graph/graph.py +1427 -0
- code_review_graph/graph_diff.py +122 -0
- code_review_graph/hints.py +384 -0
- code_review_graph/incremental.py +1245 -0
- code_review_graph/jedi_resolver.py +303 -0
- code_review_graph/main.py +1079 -0
- code_review_graph/memory.py +142 -0
- code_review_graph/migrations.py +284 -0
- code_review_graph/parser.py +6957 -0
- code_review_graph/postprocessing.py +134 -0
- code_review_graph/prompts.py +159 -0
- code_review_graph/refactor.py +852 -0
- code_review_graph/registry.py +319 -0
- code_review_graph/rescript_resolver.py +206 -0
- code_review_graph/search.py +447 -0
- code_review_graph/skills.py +1481 -0
- code_review_graph/spring_resolver.py +200 -0
- code_review_graph/temporal_resolver.py +199 -0
- code_review_graph/token_benchmark.py +125 -0
- code_review_graph/tools/__init__.py +156 -0
- code_review_graph/tools/_common.py +176 -0
- code_review_graph/tools/analysis_tools.py +184 -0
- code_review_graph/tools/build.py +541 -0
- code_review_graph/tools/community_tools.py +246 -0
- code_review_graph/tools/context.py +152 -0
- code_review_graph/tools/docs.py +274 -0
- code_review_graph/tools/flows_tools.py +176 -0
- code_review_graph/tools/query.py +692 -0
- code_review_graph/tools/refactor_tools.py +168 -0
- code_review_graph/tools/registry_tools.py +125 -0
- code_review_graph/tools/review.py +477 -0
- code_review_graph/tsconfig_resolver.py +257 -0
- code_review_graph/visualization.py +2184 -0
- code_review_graph/wiki.py +305 -0
- code_review_graph_codeblackwell-2.3.6.post1.dist-info/METADATA +718 -0
- code_review_graph_codeblackwell-2.3.6.post1.dist-info/RECORD +74 -0
- code_review_graph_codeblackwell-2.3.6.post1.dist-info/WHEEL +4 -0
- code_review_graph_codeblackwell-2.3.6.post1.dist-info/entry_points.txt +3 -0
- code_review_graph_codeblackwell-2.3.6.post1.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"""Tools 10, 11: list_flows, get_flow."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from ..flows import get_flow_by_id, get_flows
|
|
9
|
+
from ..hints import generate_hints, get_session
|
|
10
|
+
from ._common import _get_store
|
|
11
|
+
|
|
12
|
+
# ---------------------------------------------------------------------------
|
|
13
|
+
# Tool 10: list_flows [EXPLORE]
|
|
14
|
+
# ---------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def list_flows(
|
|
18
|
+
repo_root: str | None = None,
|
|
19
|
+
sort_by: str = "criticality",
|
|
20
|
+
limit: int = 50,
|
|
21
|
+
kind: str | None = None,
|
|
22
|
+
detail_level: str = "standard",
|
|
23
|
+
) -> dict[str, Any]:
|
|
24
|
+
"""List execution flows in the codebase, sorted by criticality.
|
|
25
|
+
|
|
26
|
+
[EXPLORE] Retrieves stored execution flows from the knowledge graph.
|
|
27
|
+
Each flow represents a call chain starting from an entry point
|
|
28
|
+
(e.g. HTTP handler, CLI command, test function).
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
repo_root: Repository root path. Auto-detected if omitted.
|
|
32
|
+
sort_by: Sort column: criticality, depth, node_count, file_count,
|
|
33
|
+
or name.
|
|
34
|
+
limit: Maximum flows to return (default: 50).
|
|
35
|
+
kind: Optional filter by entry point kind (e.g. "Test", "Function").
|
|
36
|
+
detail_level: "standard" (default) returns full flow data;
|
|
37
|
+
"minimal" returns only name, criticality, and
|
|
38
|
+
node_count per flow.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
List of flows with criticality scores.
|
|
42
|
+
"""
|
|
43
|
+
store, root = _get_store(repo_root)
|
|
44
|
+
try:
|
|
45
|
+
fetch_limit = (
|
|
46
|
+
limit if not kind else limit * 10
|
|
47
|
+
) # fetch more when filtering
|
|
48
|
+
flows = get_flows(store, sort_by=sort_by, limit=fetch_limit)
|
|
49
|
+
|
|
50
|
+
if kind:
|
|
51
|
+
filtered = []
|
|
52
|
+
for f in flows:
|
|
53
|
+
ep_id = f.get("entry_point_id")
|
|
54
|
+
if ep_id is not None:
|
|
55
|
+
node_kind = store.get_node_kind_by_id(ep_id)
|
|
56
|
+
if node_kind == kind:
|
|
57
|
+
filtered.append(f)
|
|
58
|
+
flows = filtered[:limit]
|
|
59
|
+
|
|
60
|
+
if detail_level == "minimal":
|
|
61
|
+
flows = [
|
|
62
|
+
{
|
|
63
|
+
"name": f["name"],
|
|
64
|
+
"criticality": f["criticality"],
|
|
65
|
+
"node_count": f["node_count"],
|
|
66
|
+
}
|
|
67
|
+
for f in flows
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
result: dict[str, object] = {
|
|
71
|
+
"status": "ok",
|
|
72
|
+
"summary": f"Found {len(flows)} execution flow(s)",
|
|
73
|
+
"flows": flows,
|
|
74
|
+
}
|
|
75
|
+
result["_hints"] = generate_hints(
|
|
76
|
+
"list_flows", result, get_session()
|
|
77
|
+
)
|
|
78
|
+
return result
|
|
79
|
+
except Exception as exc:
|
|
80
|
+
return {"status": "error", "error": str(exc)}
|
|
81
|
+
finally:
|
|
82
|
+
store.close()
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
# ---------------------------------------------------------------------------
|
|
86
|
+
# Tool 11: get_flow [EXPLORE]
|
|
87
|
+
# ---------------------------------------------------------------------------
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def get_flow(
|
|
91
|
+
flow_id: int | None = None,
|
|
92
|
+
flow_name: str | None = None,
|
|
93
|
+
include_source: bool = False,
|
|
94
|
+
repo_root: str | None = None,
|
|
95
|
+
) -> dict[str, Any]:
|
|
96
|
+
"""Get details of a single execution flow.
|
|
97
|
+
|
|
98
|
+
[EXPLORE] Retrieves full path details for a flow, including each step's
|
|
99
|
+
function name, file, and line numbers. Optionally includes source
|
|
100
|
+
snippets for every step in the path.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
flow_id: Database ID of the flow (from list_flows).
|
|
104
|
+
flow_name: Name to search for (partial match). Ignored if flow_id
|
|
105
|
+
given.
|
|
106
|
+
include_source: If True, include source code snippets for each step.
|
|
107
|
+
repo_root: Repository root path. Auto-detected if omitted.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
Flow details with steps, or not_found status.
|
|
111
|
+
"""
|
|
112
|
+
store, root = _get_store(repo_root)
|
|
113
|
+
try:
|
|
114
|
+
flow: dict | None = None
|
|
115
|
+
|
|
116
|
+
if flow_id is not None:
|
|
117
|
+
flow = get_flow_by_id(store, flow_id)
|
|
118
|
+
elif flow_name is not None:
|
|
119
|
+
# Search flows by name match
|
|
120
|
+
all_flows = get_flows(
|
|
121
|
+
store, sort_by="criticality", limit=500
|
|
122
|
+
)
|
|
123
|
+
for f in all_flows:
|
|
124
|
+
if flow_name.lower() in f["name"].lower():
|
|
125
|
+
flow = get_flow_by_id(store, f["id"])
|
|
126
|
+
break
|
|
127
|
+
|
|
128
|
+
if flow is None:
|
|
129
|
+
return {
|
|
130
|
+
"status": "not_found",
|
|
131
|
+
"summary": "No flow found matching the given criteria.",
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
# Optionally include source snippets for each step
|
|
135
|
+
if include_source and "steps" in flow:
|
|
136
|
+
for step in flow["steps"]:
|
|
137
|
+
fp = Path(step["file"]) if step.get("file") else None
|
|
138
|
+
if fp is not None and not fp.is_absolute():
|
|
139
|
+
fp = root / fp
|
|
140
|
+
file_path = fp
|
|
141
|
+
if file_path and file_path.is_file():
|
|
142
|
+
try:
|
|
143
|
+
lines = file_path.read_text(
|
|
144
|
+
errors="replace"
|
|
145
|
+
).splitlines()
|
|
146
|
+
start = max(
|
|
147
|
+
0, (step.get("line_start") or 1) - 1
|
|
148
|
+
)
|
|
149
|
+
end = min(
|
|
150
|
+
len(lines),
|
|
151
|
+
step.get("line_end") or len(lines),
|
|
152
|
+
)
|
|
153
|
+
step["source"] = "\n".join(
|
|
154
|
+
f"{i + 1}: {lines[i]}"
|
|
155
|
+
for i in range(start, end)
|
|
156
|
+
)
|
|
157
|
+
except (OSError, UnicodeDecodeError):
|
|
158
|
+
step["source"] = "(could not read file)"
|
|
159
|
+
|
|
160
|
+
result = {
|
|
161
|
+
"status": "ok",
|
|
162
|
+
"summary": (
|
|
163
|
+
f"Flow '{flow['name']}': {flow['node_count']} nodes, "
|
|
164
|
+
f"depth {flow['depth']}, "
|
|
165
|
+
f"criticality {flow['criticality']:.4f}"
|
|
166
|
+
),
|
|
167
|
+
"flow": flow,
|
|
168
|
+
}
|
|
169
|
+
result["_hints"] = generate_hints(
|
|
170
|
+
"get_flow", result, get_session()
|
|
171
|
+
)
|
|
172
|
+
return result
|
|
173
|
+
except Exception as exc:
|
|
174
|
+
return {"status": "error", "error": str(exc)}
|
|
175
|
+
finally:
|
|
176
|
+
store.close()
|