Run a predefined graph query. Args: pattern: Query pattern. One of: callers_of, callees_of, imports_of, importers_of, children_of, tests_for, inheritors_of, file_summary. target: The node name, qualified name, or file path to query about. repo_root: Repo
(
pattern: str,
target: str,
repo_root: str | None = None,
detail_level: str = "standard",
)
| 143 | |
| 144 | |
| 145 | def query_graph( |
| 146 | pattern: str, |
| 147 | target: str, |
| 148 | repo_root: str | None = None, |
| 149 | detail_level: str = "standard", |
| 150 | ) -> dict[str, Any]: |
| 151 | """Run a predefined graph query. |
| 152 | |
| 153 | Args: |
| 154 | pattern: Query pattern. One of: callers_of, callees_of, imports_of, |
| 155 | importers_of, children_of, tests_for, inheritors_of, file_summary. |
| 156 | target: The node name, qualified name, or file path to query about. |
| 157 | repo_root: Repository root path. Auto-detected if omitted. |
| 158 | detail_level: "standard" (full output) or "minimal" (summary only). |
| 159 | |
| 160 | Returns: |
| 161 | Matching nodes and edges for the query. |
| 162 | """ |
| 163 | store, root = _get_store(repo_root) |
| 164 | try: |
| 165 | if pattern not in _QUERY_PATTERNS: |
| 166 | return { |
| 167 | "status": "error", |
| 168 | "error": ( |
| 169 | f"Unknown pattern '{pattern}'. " |
| 170 | f"Available: {list(_QUERY_PATTERNS.keys())}" |
| 171 | ), |
| 172 | } |
| 173 | |
| 174 | results: list[dict] = [] |
| 175 | edges_out: list[dict] = [] |
| 176 | |
| 177 | # For callers_of, skip common builtins early (bare names only) |
| 178 | # "Who calls .map()?" returns hundreds of useless hits. |
| 179 | # Qualified names (e.g. "utils.py::map") bypass this filter. |
| 180 | if ( |
| 181 | pattern == "callers_of" |
| 182 | and target in _BUILTIN_CALL_NAMES |
| 183 | and "::" not in target |
| 184 | ): |
| 185 | return { |
| 186 | "status": "ok", "pattern": pattern, "target": target, |
| 187 | "description": _QUERY_PATTERNS[pattern], |
| 188 | "summary": ( |
| 189 | f"'{target}' is a common builtin " |
| 190 | "— callers_of skipped to avoid noise." |
| 191 | ), |
| 192 | "results": [], "edges": [], |
| 193 | } |
| 194 | |
| 195 | # Resolve target - try as-is, then as absolute path, then search. |
| 196 | # file_summary targets are paths, so skip broad node search. |
| 197 | node = None |
| 198 | if pattern != "file_summary": |
| 199 | node = store.get_node(target) |
| 200 | if not node: |
| 201 | abs_target = str(root / target) |
| 202 | node = store.get_node(abs_target) |