@mka-rainmaker/ama 0.1.2 → 0.2.0

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.
Files changed (60) hide show
  1. package/README.md +18 -2
  2. package/dist/analyzers/baseline/analyzer.d.ts +9 -0
  3. package/dist/analyzers/baseline/analyzer.d.ts.map +1 -1
  4. package/dist/analyzers/baseline/analyzer.js +5 -0
  5. package/dist/analyzers/baseline/analyzer.js.map +1 -1
  6. package/dist/analyzers/baseline/go.d.ts.map +1 -1
  7. package/dist/analyzers/baseline/go.js +67 -0
  8. package/dist/analyzers/baseline/go.js.map +1 -1
  9. package/dist/analyzers/baseline/java.d.ts.map +1 -1
  10. package/dist/analyzers/baseline/java.js +84 -0
  11. package/dist/analyzers/baseline/java.js.map +1 -1
  12. package/dist/analyzers/baseline/php.d.ts.map +1 -1
  13. package/dist/analyzers/baseline/php.js +56 -0
  14. package/dist/analyzers/baseline/php.js.map +1 -1
  15. package/dist/analyzers/baseline/python.d.ts.map +1 -1
  16. package/dist/analyzers/baseline/python.js +160 -2
  17. package/dist/analyzers/baseline/python.js.map +1 -1
  18. package/dist/analyzers/baseline/rust.d.ts.map +1 -1
  19. package/dist/analyzers/baseline/rust.js +80 -0
  20. package/dist/analyzers/baseline/rust.js.map +1 -1
  21. package/dist/analyzers/sidecar/protocol.d.ts +22 -22
  22. package/dist/analyzers/typescript/analyzer.d.ts.map +1 -1
  23. package/dist/analyzers/typescript/analyzer.js +51 -1
  24. package/dist/analyzers/typescript/analyzer.js.map +1 -1
  25. package/dist/api.d.ts +34 -0
  26. package/dist/api.d.ts.map +1 -0
  27. package/dist/api.js +38 -0
  28. package/dist/api.js.map +1 -0
  29. package/dist/cli/agents.d.ts +11 -2
  30. package/dist/cli/agents.d.ts.map +1 -1
  31. package/dist/cli/agents.js +39 -0
  32. package/dist/cli/agents.js.map +1 -1
  33. package/dist/cli/commands/install.d.ts.map +1 -1
  34. package/dist/cli/commands/install.js +31 -8
  35. package/dist/cli/commands/install.js.map +1 -1
  36. package/dist/graph/index.d.ts +2 -1
  37. package/dist/graph/index.d.ts.map +1 -1
  38. package/dist/graph/index.js +2 -1
  39. package/dist/graph/index.js.map +1 -1
  40. package/dist/graph/prisma-link.d.ts +9 -4
  41. package/dist/graph/prisma-link.d.ts.map +1 -1
  42. package/dist/graph/prisma-link.js +25 -10
  43. package/dist/graph/prisma-link.js.map +1 -1
  44. package/dist/graph/python-calls.d.ts +14 -0
  45. package/dist/graph/python-calls.d.ts.map +1 -0
  46. package/dist/graph/python-calls.js +0 -0
  47. package/dist/graph/python-calls.js.map +1 -0
  48. package/dist/graph/types.d.ts +1 -1
  49. package/dist/graph/types.d.ts.map +1 -1
  50. package/dist/indexer/indexer.d.ts.map +1 -1
  51. package/dist/indexer/indexer.js +12 -1
  52. package/dist/indexer/indexer.js.map +1 -1
  53. package/dist/mcp/server.d.ts.map +1 -1
  54. package/dist/mcp/server.js +7 -2
  55. package/dist/mcp/server.js.map +1 -1
  56. package/dist/query/service.d.ts +3 -0
  57. package/dist/query/service.d.ts.map +1 -1
  58. package/dist/query/service.js +18 -2
  59. package/dist/query/service.js.map +1 -1
  60. package/package.json +10 -1
package/README.md CHANGED
@@ -18,7 +18,7 @@ Every answer reports **which tier produced it**, so partial coverage never quiet
18
18
  And because it's built for agents:
19
19
 
20
20
  - **100% local.** No external APIs, no API keys, no telemetry. Your code never leaves your machine.
21
- - **Cheaper and faster.** Fewer tool calls and fewer tokens per question, because one graph query replaces a pile of file reads.
21
+ - **Cheaper and faster.** Fewer tool calls and fewer tokens per question, because one graph query replaces a pile of file reads — see [benchmarks](docs/benchmarks/README.md) (a focused, single-call answer vs. grep-then-read; methodology + honest caveats there).
22
22
 
23
23
  ## Install
24
24
 
@@ -37,7 +37,7 @@ npm install -g @mka-rainmaker/ama
37
37
  **Fastest — let Ama wire itself in:**
38
38
 
39
39
  ```bash
40
- ama install # detects Claude Code / Cursor / Windsurf and writes their MCP config
40
+ ama install # detects Claude Code / Cursor / Windsurf / Codex and writes their MCP config
41
41
  ama install --dry-run # preview what it would change, writing nothing
42
42
  ama uninstall # remove it again
43
43
  ```
@@ -102,6 +102,22 @@ ama --help # list commands
102
102
  ama mcp # run the MCP server over stdio (what coding agents spawn)
103
103
  ```
104
104
 
105
+ ### Programmatic API
106
+
107
+ Embed Ama as a library — index a repo and query its graph from your own code (the same surface the MCP server and CLI use):
108
+
109
+ ```ts
110
+ import { index } from "@mka-rainmaker/ama";
111
+
112
+ const ama = await index("/path/to/repo");
113
+ ama.searchSymbol("createServer"); // GraphNode[]
114
+ ama.findCallers("createServer"); // who calls it
115
+ ama.impactAnalysis("AmaSession"); // transitive blast radius
116
+ ama.close(); // release resources when done
117
+ ```
118
+
119
+ `index(root)` returns a transport-free `AmaSession` (aliased `Ama`) with the full query surface; `open(root)` reuses a persisted index. See [`src/api.ts`](src/api.ts) for the exported types.
120
+
105
121
  ## What's in 0.1
106
122
 
107
123
  - **Deep TypeScript analysis** via the TypeScript Compiler API — types, overloads, generics, imports/re-exports, inheritance, interface dispatch, cross-file binding, and call graphs.
@@ -35,6 +35,15 @@ export interface LanguageSpec {
35
35
  nodes: GraphNode[];
36
36
  edges: GraphEdge[];
37
37
  };
38
+ /**
39
+ * Optional call detector: walk the CST for call sites and return heuristic `Calls` edges.
40
+ * Baseline tier — name-based resolution within the file (no types), so callers/callees and
41
+ * blast-radius work for languages without a deep analyzer. (ama-bnj)
42
+ */
43
+ readonly collectCalls?: (root: Parser.SyntaxNode, rel: string) => {
44
+ nodes: GraphNode[];
45
+ edges: GraphEdge[];
46
+ };
38
47
  }
39
48
  /**
40
49
  * A language-agnostic, syntactic (tier `baseline`) analyzer driven by a
@@ -1 +1 @@
1
- {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/analyzer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAU,MAAM,sBAAsB,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5D,OAAO,EAAE,KAAK,UAAU,EAAe,MAAM,WAAW,CAAC;AAEzD,YAAY,EAAE,UAAU,EAAE,CAAC;AAE3B;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,iEAAiE;IACjE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,mDAAmD;IACnD,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IACvD;;;;;;;;OAQG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CACxB,IAAI,EAAE,MAAM,CAAC,UAAU,EACvB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,KACT,MAAM,EAAE,EAAE,GAAG,SAAS,CAAC;IAE5B;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CACvB,IAAI,EAAE,MAAM,CAAC,UAAU,EACvB,GAAG,EAAE,MAAM,KACR;QAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAAC,KAAK,EAAE,SAAS,EAAE,CAAA;KAAE,CAAC;CACjD;AAED;;;;;;GAMG;AACH,qBAAa,gBAAiB,YAAW,QAAQ;IAKnC,OAAO,CAAC,QAAQ,CAAC,IAAI;IAJjC,QAAQ,CAAC,IAAI,cAAc;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;gBAEV,IAAI,EAAE,YAAY;IAKzC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC;IAmDrE;oFACgF;IAChF,OAAO,CAAC,cAAc;CAkBvB"}
1
+ {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/analyzer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAU,MAAM,sBAAsB,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5D,OAAO,EAAE,KAAK,UAAU,EAAe,MAAM,WAAW,CAAC;AAEzD,YAAY,EAAE,UAAU,EAAE,CAAC;AAE3B;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,iEAAiE;IACjE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,mDAAmD;IACnD,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IACvD;;;;;;;;OAQG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CACxB,IAAI,EAAE,MAAM,CAAC,UAAU,EACvB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,KACT,MAAM,EAAE,EAAE,GAAG,SAAS,CAAC;IAE5B;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CACvB,IAAI,EAAE,MAAM,CAAC,UAAU,EACvB,GAAG,EAAE,MAAM,KACR;QAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAAC,KAAK,EAAE,SAAS,EAAE,CAAA;KAAE,CAAC;IAEhD;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,CACtB,IAAI,EAAE,MAAM,CAAC,UAAU,EACvB,GAAG,EAAE,MAAM,KACR;QAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAAC,KAAK,EAAE,SAAS,EAAE,CAAA;KAAE,CAAC;CACjD;AAED;;;;;;GAMG;AACH,qBAAa,gBAAiB,YAAW,QAAQ;IAKnC,OAAO,CAAC,QAAQ,CAAC,IAAI;IAJjC,QAAQ,CAAC,IAAI,cAAc;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;gBAEV,IAAI,EAAE,YAAY;IAKzC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC;IAwDrE;oFACgF;IAChF,OAAO,CAAC,cAAc;CAkBvB"}
@@ -56,6 +56,11 @@ export class BaselineAnalyzer {
56
56
  fileNodes.push(...routes.nodes);
57
57
  fileEdges.push(...routes.edges);
58
58
  }
59
+ if (this.spec.collectCalls) {
60
+ const calls = this.spec.collectCalls(tree.rootNode, rel);
61
+ fileNodes.push(...calls.nodes);
62
+ fileEdges.push(...calls.edges);
63
+ }
59
64
  nodes.push(...fileNodes);
60
65
  edges.push(...fileEdges);
61
66
  }
@@ -1 +1 @@
1
- {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../../src/analyzers/baseline/analyzer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../../src/analyzers/baseline/analyzer.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"go.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/go.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AA6ClD;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,EAAE,YAapB,CAAC"}
1
+ {"version":3,"file":"go.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/go.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAgHlD;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,EAAE,YAcpB,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
+ import { symbolId } from "../../graph/index.js";
3
4
  import { nearestConfig, parentDir } from "./config.js";
4
5
  /** Cache for the nearest `go.mod`'s declared module path, by importer directory. */
5
6
  const goModuleCache = new Map();
@@ -41,6 +42,71 @@ function goImports(node, importerRel, root) {
41
42
  .filter((f) => f.endsWith(".go") && !f.endsWith("_test.go"))
42
43
  .map((f) => [pkgDir ? `${pkgDir}/${f}` : f]);
43
44
  }
45
+ /** Gin/chi/echo HTTP-verb router methods — `r.GET("/x", h)`. (ama-a2r) */
46
+ const GO_ROUTE_METHODS = new Set(["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD"]);
47
+ /** Normalize a Go route path: chi/mux `{id}` → `:id` (Gin's `:id` is already the shared form);
48
+ * ensure a leading slash. (ama-a2r) */
49
+ function normalizeGoRoutePath(p) {
50
+ const s = p.replace(/\{([^}]+)\}/g, ":$1");
51
+ return s.startsWith("/") ? s : `/${s}`;
52
+ }
53
+ /** The first string-literal argument (interpreted or raw) of an argument_list, unquoted. */
54
+ function goStringArg(args) {
55
+ if (!args)
56
+ return undefined;
57
+ for (const a of args.namedChildren) {
58
+ if (a.type === "interpreted_string_literal" || a.type === "raw_string_literal") {
59
+ return a.text.replace(/^[`"]|[`"]$/g, "");
60
+ }
61
+ }
62
+ return undefined;
63
+ }
64
+ function* eachCall(node) {
65
+ if (node.type === "call_expression")
66
+ yield node;
67
+ for (const c of node.namedChildren)
68
+ yield* eachCall(c);
69
+ }
70
+ /** Detect Gin/chi/echo-style routes: `r.GET("/path", handler)` — a call whose function is a
71
+ * selector with an HTTP-verb field and a string first arg — becomes a `METHOD /path` Route,
72
+ * referencing the handler when it's a plain identifier in the same file. (ama-a2r) */
73
+ function goRoutes(root, rel) {
74
+ const nodes = [];
75
+ const edges = [];
76
+ for (const call of eachCall(root)) {
77
+ const fn = call.childForFieldName("function");
78
+ if (fn?.type !== "selector_expression")
79
+ continue;
80
+ const verb = fn.childForFieldName("field")?.text?.toUpperCase();
81
+ if (!verb || !GO_ROUTE_METHODS.has(verb))
82
+ continue;
83
+ const args = call.childForFieldName("arguments");
84
+ const raw = goStringArg(args);
85
+ if (raw === undefined)
86
+ continue;
87
+ const name = `${verb} ${normalizeGoRoutePath(raw)}`;
88
+ const routeId = symbolId({ file: rel, qualifiedName: name });
89
+ nodes.push({
90
+ id: routeId,
91
+ kind: "Route",
92
+ name,
93
+ file: rel,
94
+ qualifiedName: name,
95
+ tier: "baseline",
96
+ range: { startLine: call.startPosition.row + 1, endLine: call.endPosition.row + 1 },
97
+ });
98
+ const handler = args?.namedChildren.find((a, i) => i > 0 && a.type === "identifier");
99
+ if (handler) {
100
+ edges.push({
101
+ from: routeId,
102
+ to: symbolId({ file: rel, qualifiedName: handler.text }),
103
+ kind: "References",
104
+ provenance: "heuristic",
105
+ });
106
+ }
107
+ }
108
+ return { nodes, edges };
109
+ }
44
110
  /**
45
111
  * Baseline (syntactic) spec for Go. Go declares named types with a single
46
112
  * `type_spec` node regardless of whether the body is a struct, interface, or
@@ -62,5 +128,6 @@ export const goSpec = {
62
128
  },
63
129
  },
64
130
  resolveImports: goImports,
131
+ collectRoutes: goRoutes,
65
132
  };
66
133
  //# sourceMappingURL=go.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"go.js","sourceRoot":"","sources":["../../../src/analyzers/baseline/go.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"go.js","sourceRoot":"","sources":["../../../src/analyzers/baseline/go.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"java.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/java.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAiClD;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,EAAE,YAWtB,CAAC"}
1
+ {"version":3,"file":"java.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/java.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AA0HlD;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,EAAE,YAYtB,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { symbolId } from "../../graph/index.js";
1
2
  import { ancestorDirs } from "./paths.js";
2
3
  /** Try a repo-relative file under every ancestor directory of the importer. A
3
4
  * package import gives a *source-root-relative* path (`com/example/Foo.java`)
@@ -29,6 +30,88 @@ function javaImports(node, importerRel) {
29
30
  const file = `${segments.slice(0, classEnd + 1).join("/")}.java`;
30
31
  return [ancestorCandidates(importerRel, file)];
31
32
  }
33
+ /** Spring method-mapping annotations → HTTP verb. `@RequestMapping` is the class-level prefix. */
34
+ const JAVA_MAPPING_VERBS = new Map([
35
+ ["GetMapping", "GET"],
36
+ ["PostMapping", "POST"],
37
+ ["PutMapping", "PUT"],
38
+ ["DeleteMapping", "DELETE"],
39
+ ["PatchMapping", "PATCH"],
40
+ ]);
41
+ function firstOfType(node, type) {
42
+ if (node.type === type)
43
+ return node;
44
+ for (const c of node.namedChildren) {
45
+ const found = firstOfType(c, type);
46
+ if (found)
47
+ return found;
48
+ }
49
+ return undefined;
50
+ }
51
+ function* eachClass(node) {
52
+ if (node.type === "class_declaration")
53
+ yield node;
54
+ for (const c of node.namedChildren)
55
+ yield* eachClass(c);
56
+ }
57
+ /** The string argument of an `@Annotation("x")`, or undefined for a marker annotation. */
58
+ function annotationArg(ann) {
59
+ return firstOfType(ann, "string_fragment")?.text;
60
+ }
61
+ /** Combine a Spring class prefix and a method sub-path into a normalized `:param` route. */
62
+ function joinJavaRoutePath(prefix, sub) {
63
+ const norm = (s) => s.replace(/\{([^}]+)\}/g, ":$1");
64
+ const segs = [norm(prefix), norm(sub)].flatMap((s) => s.split("/")).filter(Boolean);
65
+ return `/${segs.join("/")}`;
66
+ }
67
+ /** Detect Spring MVC routes: a class `@RequestMapping("/prefix")` prefixes each method's
68
+ * `@GetMapping`/`@PostMapping`/… (path or marker) to form a `METHOD /prefix/path` Route that
69
+ * references the method (`Class.method`). (ama-a2r) */
70
+ function javaRoutes(root, rel) {
71
+ const nodes = [];
72
+ const edges = [];
73
+ const annotationsOf = (node) => (node.namedChildren.find((c) => c.type === "modifiers")?.namedChildren ?? []).filter((a) => a.type === "annotation" || a.type === "marker_annotation");
74
+ for (const cls of eachClass(root)) {
75
+ const className = cls.childForFieldName("name")?.text;
76
+ const prefix = annotationsOf(cls).find((a) => a.childForFieldName("name")?.text === "RequestMapping") ??
77
+ null;
78
+ const classPrefix = prefix ? (annotationArg(prefix) ?? "") : "";
79
+ const body = cls.childForFieldName("body");
80
+ for (const member of body?.namedChildren ?? []) {
81
+ if (member.type !== "method_declaration")
82
+ continue;
83
+ const mapping = annotationsOf(member)
84
+ .map((a) => ({
85
+ verb: JAVA_MAPPING_VERBS.get(a.childForFieldName("name")?.text ?? ""),
86
+ ann: a,
87
+ }))
88
+ .find((m) => m.verb);
89
+ if (!mapping?.verb)
90
+ continue;
91
+ const methodName = member.childForFieldName("name")?.text;
92
+ const name = `${mapping.verb} ${joinJavaRoutePath(classPrefix, annotationArg(mapping.ann) ?? "")}`;
93
+ const routeId = symbolId({ file: rel, qualifiedName: name });
94
+ nodes.push({
95
+ id: routeId,
96
+ kind: "Route",
97
+ name,
98
+ file: rel,
99
+ qualifiedName: name,
100
+ tier: "baseline",
101
+ range: { startLine: member.startPosition.row + 1, endLine: member.endPosition.row + 1 },
102
+ });
103
+ if (className && methodName) {
104
+ edges.push({
105
+ from: routeId,
106
+ to: symbolId({ file: rel, qualifiedName: `${className}.${methodName}` }),
107
+ kind: "References",
108
+ provenance: "heuristic",
109
+ });
110
+ }
111
+ }
112
+ }
113
+ return { nodes, edges };
114
+ }
32
115
  /**
33
116
  * Baseline (syntactic) spec for Java. Java gives every kind its own CST node
34
117
  * type — class/interface/enum declarations and methods — so each maps directly
@@ -46,5 +129,6 @@ export const javaSpec = {
46
129
  method_declaration: { kind: "Method" },
47
130
  },
48
131
  resolveImports: javaImports,
132
+ collectRoutes: javaRoutes,
49
133
  };
50
134
  //# sourceMappingURL=java.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"java.js","sourceRoot":"","sources":["../../../src/analyzers/baseline/java.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C;;;;+EAI+E;AAC/E,SAAS,kBAAkB,CAAC,WAAmB,EAAE,IAAY;IAC3D,OAAO,YAAY,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;;8BAM8B;AAC9B,SAAS,WAAW,CAAC,IAAuB,EAAE,WAAmB;IAC/D,IAAI,IAAI,CAAC,IAAI,KAAK,oBAAoB;QAAE,OAAO,SAAS,CAAC;IACzD,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC;QAAE,OAAO,EAAE,CAAC,CAAC,kBAAkB;IACxF,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CACpC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,mBAAmB,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,CACjE,CAAC;IACF,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7D,IAAI,QAAQ,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC,CAAC,oDAAoD;IACjF,MAAM,IAAI,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;IACjE,OAAO,CAAC,kBAAkB,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC;AACjD,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAiB;IACpC,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE,CAAC,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM;IACf,OAAO,EAAE;QACP,iBAAiB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;QACpC,qBAAqB,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;QAC5C,gBAAgB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;QAClC,kBAAkB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;KACvC;IACD,cAAc,EAAE,WAAW;CAC5B,CAAC"}
1
+ {"version":3,"file":"java.js","sourceRoot":"","sources":["../../../src/analyzers/baseline/java.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"php.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/php.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAqDlD;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,EAAE,YAarB,CAAC"}
1
+ {"version":3,"file":"php.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/php.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AA6GlD;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,EAAE,YAcrB,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
+ import { symbolId } from "../../graph/index.js";
3
4
  import { nearestConfig, parentDir } from "./config.js";
4
5
  /** Cache for the nearest composer.json's PSR-4 `[prefix, baseDir]` map, by directory. */
5
6
  const composerCache = new Map();
@@ -51,6 +52,60 @@ function phpImports(node, importerRel, root) {
51
52
  const file = [composer.dir, best.base, `${relPath}.php`].filter(Boolean).join("/");
52
53
  return [[file]];
53
54
  }
55
+ /** Laravel `Route` facade HTTP-verb methods — `Route::get('/x', ...)`. (ama-a2r) */
56
+ const PHP_ROUTE_METHODS = new Set(["get", "post", "put", "delete", "patch", "options", "head"]);
57
+ /** Normalize a Laravel route path: `{id}` → `:id`; ensure a leading slash. (ama-a2r) */
58
+ function normalizePhpRoutePath(p) {
59
+ const s = p.replace(/\{([^}]+)\}/g, ":$1");
60
+ return s.startsWith("/") ? s : `/${s}`;
61
+ }
62
+ function firstOfType(node, type) {
63
+ if (node.type === type)
64
+ return node;
65
+ for (const c of node.namedChildren) {
66
+ const found = firstOfType(c, type);
67
+ if (found)
68
+ return found;
69
+ }
70
+ return undefined;
71
+ }
72
+ function* eachScopedCall(node) {
73
+ if (node.type === "scoped_call_expression")
74
+ yield node;
75
+ for (const c of node.namedChildren)
76
+ yield* eachScopedCall(c);
77
+ }
78
+ /** Detect Laravel routes: `Route::<verb>('/path', handler)` — a static call on the `Route`
79
+ * facade with an HTTP-verb method and a string first arg — becomes a `METHOD /path` Route.
80
+ * Scoped to the `Route` facade so unrelated static calls (`Cache::get`) don't match. The
81
+ * handler is usually a controller reference (array/string), not a same-file function, so no
82
+ * handler edge is emitted. (ama-a2r) */
83
+ function phpRoutes(root, rel) {
84
+ const nodes = [];
85
+ for (const call of eachScopedCall(root)) {
86
+ const scope = call.childForFieldName("scope")?.text ?? call.namedChild(0)?.text;
87
+ const method = call.childForFieldName("name")?.text?.toLowerCase();
88
+ if (scope !== "Route" || !method || !PHP_ROUTE_METHODS.has(method))
89
+ continue;
90
+ const firstArg = call
91
+ .childForFieldName("arguments")
92
+ ?.namedChildren.find((c) => c.type === "argument");
93
+ const raw = firstArg && firstOfType(firstArg, "string_content")?.text;
94
+ if (!raw)
95
+ continue;
96
+ const name = `${method.toUpperCase()} ${normalizePhpRoutePath(raw)}`;
97
+ nodes.push({
98
+ id: symbolId({ file: rel, qualifiedName: name }),
99
+ kind: "Route",
100
+ name,
101
+ file: rel,
102
+ qualifiedName: name,
103
+ tier: "baseline",
104
+ range: { startLine: call.startPosition.row + 1, endLine: call.endPosition.row + 1 },
105
+ });
106
+ }
107
+ return { nodes, edges: [] };
108
+ }
54
109
  /**
55
110
  * Baseline (syntactic) spec for PHP. Each top-level construct has its own CST
56
111
  * node type — class/interface/trait/enum declarations, free functions, and
@@ -72,5 +127,6 @@ export const phpSpec = {
72
127
  method_declaration: { kind: "Method" },
73
128
  },
74
129
  resolveImports: phpImports,
130
+ collectRoutes: phpRoutes,
75
131
  };
76
132
  //# sourceMappingURL=php.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"php.js","sourceRoot":"","sources":["../../../src/analyzers/baseline/php.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"php.js","sourceRoot":"","sources":["../../../src/analyzers/baseline/php.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAkC,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhF,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEvD,yFAAyF;AACzF,MAAM,aAAa,GAAG,IAAI,GAAG,EAA6D,CAAC;AAE3F;0DAC0D;AAC1D,SAAS,gBAAgB,CAAC,MAAc;IACtC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QACrF,MAAM,GAAG,GAAG,IAAI,EAAE,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,OAAO,SAAS,CAAC;QACtD,MAAM,IAAI,GAAuB,EAAE,CAAC;QACpC,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACjD,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,wCAAwC;YAC1F,IAAI,OAAO,GAAG,KAAK,QAAQ;gBAAE,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;QAC5E,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC,CAAC,+DAA+D;IACnF,CAAC;AACH,CAAC;AAED;;;;;yBAKyB;AACzB,SAAS,UAAU,CACjB,IAAuB,EACvB,WAAmB,EACnB,IAAY;IAEZ,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAsB;QAAE,OAAO,SAAS,CAAC;IAC3D,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;IACvE,IAAI,CAAC,EAAE;QAAE,OAAO,EAAE,CAAC;IACnB,MAAM,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,+CAA+C;IACvF,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,EAAE,SAAS,CAAC,WAAW,CAAC,EAAE,gBAAgB,EAAE,aAAa,CAAC,CAAC;IAC9F,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,CAAC;IACzB,IAAI,IAAkD,CAAC;IACvD,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QAC5C,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5E,IAAI,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAC1B,CAAC;IACH,CAAC;IACD,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAClE,MAAM,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,OAAO,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnF,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,oFAAoF;AACpF,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;AAEhG,wFAAwF;AACxF,SAAS,qBAAqB,CAAC,CAAS;IACtC,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IAC3C,OAAO,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;AACzC,CAAC;AAED,SAAS,WAAW,CAAC,IAAuB,EAAE,IAAY;IACxD,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACpC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QACnC,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;IAC1B,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,QAAQ,CAAC,CAAC,cAAc,CAAC,IAAuB;IAC9C,IAAI,IAAI,CAAC,IAAI,KAAK,wBAAwB;QAAE,MAAM,IAAI,CAAC;IACvD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,aAAa;QAAE,KAAK,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED;;;;yCAIyC;AACzC,SAAS,SAAS,CAChB,IAAuB,EACvB,GAAW;IAEX,MAAM,KAAK,GAAgB,EAAE,CAAC;IAC9B,KAAK,MAAM,IAAI,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,EAAE,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;QAChF,MAAM,MAAM,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;QACnE,IAAI,KAAK,KAAK,OAAO,IAAI,CAAC,MAAM,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,SAAS;QAC7E,MAAM,QAAQ,GAAG,IAAI;aAClB,iBAAiB,CAAC,WAAW,CAAC;YAC/B,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;QACrD,MAAM,GAAG,GAAG,QAAQ,IAAI,WAAW,CAAC,QAAQ,EAAE,gBAAgB,CAAC,EAAE,IAAI,CAAC;QACtE,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,MAAM,IAAI,GAAG,GAAG,MAAM,CAAC,WAAW,EAAE,IAAI,qBAAqB,CAAC,GAAG,CAAC,EAAE,CAAC;QACrE,KAAK,CAAC,IAAI,CAAC;YACT,EAAE,EAAE,QAAQ,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;YAChD,IAAI,EAAE,OAAO;YACb,IAAI;YACJ,IAAI,EAAE,GAAG;YACT,aAAa,EAAE,IAAI;YACnB,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,GAAG,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,GAAG,CAAC,EAAE;SACpF,CAAC,CAAC;IACL,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;AAC9B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,OAAO,GAAiB;IACnC,QAAQ,EAAE,KAAK;IACf,UAAU,EAAE,CAAC,MAAM,CAAC;IACpB,OAAO,EAAE,KAAK;IACd,OAAO,EAAE;QACP,iBAAiB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;QACpC,qBAAqB,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;QAC5C,iBAAiB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;QACpC,gBAAgB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;QAClC,mBAAmB,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;QACzC,kBAAkB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;KACvC;IACD,cAAc,EAAE,UAAU;IAC1B,aAAa,EAAE,SAAS;CACzB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"python.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/python.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAsIlD;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,EAAE,YAUxB,CAAC"}
1
+ {"version":3,"file":"python.d.ts","sourceRoot":"","sources":["../../../src/analyzers/baseline/python.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAqSlD;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,EAAE,YAWxB,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import * as path from "node:path";
2
- import { symbolId } from "../../graph/index.js";
2
+ import { CALL_REF_PREFIX, symbolId } from "../../graph/index.js";
3
3
  /**
4
4
  * Resolve a Python relative import (`from .x import y`, `from . import m`,
5
5
  * `from ..pkg import z`) to candidate repo-relative module files. The leading
@@ -141,6 +141,163 @@ function pythonRoutes(root, rel) {
141
141
  }
142
142
  return { nodes, edges };
143
143
  }
144
+ /** Django URL-pattern functions in `urls.py`. */
145
+ const DJANGO_URL_FUNCS = new Set(["path", "re_path"]);
146
+ function* eachCall(node) {
147
+ if (node.type === "call")
148
+ yield node;
149
+ for (const c of node.namedChildren)
150
+ yield* eachCall(c);
151
+ }
152
+ /** Detect Django URL patterns: `path("users/<int:pk>/", view)` / `re_path(...)` in urls.py —
153
+ * method-agnostic (the view handles every verb), so each forms an `ANY /path` Route. The view
154
+ * is a cross-module reference (`views.foo`), not a same-file symbol, so no handler edge. (ama-a2r) */
155
+ function djangoUrlRoutes(root, rel) {
156
+ const nodes = [];
157
+ for (const call of eachCall(root)) {
158
+ const fn = call.childForFieldName("function");
159
+ if (fn?.type !== "identifier" || !DJANGO_URL_FUNCS.has(fn.text))
160
+ continue;
161
+ const raw = firstStringArg(call.childForFieldName("arguments"));
162
+ if (raw === undefined)
163
+ continue;
164
+ const name = `ANY ${normalizeRoutePath(raw)}`;
165
+ nodes.push({
166
+ id: symbolId({ file: rel, qualifiedName: name }),
167
+ kind: "Route",
168
+ name,
169
+ file: rel,
170
+ qualifiedName: name,
171
+ tier: "baseline",
172
+ range: { startLine: call.startPosition.row + 1, endLine: call.endPosition.row + 1 },
173
+ });
174
+ }
175
+ return { nodes, edges: [] };
176
+ }
177
+ /** Python route detection across shapes: Flask/FastAPI decorators + Django urls.py `path()`. */
178
+ function pythonRoutesAll(root, rel) {
179
+ const decorated = pythonRoutes(root, rel);
180
+ const django = djangoUrlRoutes(root, rel);
181
+ return {
182
+ nodes: [...decorated.nodes, ...django.nodes],
183
+ edges: [...decorated.edges, ...django.edges],
184
+ };
185
+ }
186
+ /** The nearest enclosing `function_definition` of a node, or undefined (module-level). */
187
+ function enclosingFunction(node) {
188
+ for (let p = node.parent; p; p = p.parent) {
189
+ if (p.type === "function_definition")
190
+ return p;
191
+ }
192
+ return undefined;
193
+ }
194
+ function* eachFunction(node) {
195
+ if (node.type === "function_definition")
196
+ yield node;
197
+ for (const c of node.namedChildren)
198
+ yield* eachFunction(c);
199
+ }
200
+ /** The simple (last-segment) name a call targets: `foo()` → "foo", `obj.bar()` → "bar". */
201
+ function calleeName(call) {
202
+ const fn = call.childForFieldName("function");
203
+ if (fn?.type === "identifier")
204
+ return fn.text;
205
+ if (fn?.type === "attribute")
206
+ return fn.childForFieldName("attribute")?.text;
207
+ return undefined;
208
+ }
209
+ /** Common Python builtins — not emitted as cross-file call candidates (they resolve to no
210
+ * project function, so they'd only add dangling candidates). (ama-bnj) */
211
+ const PYTHON_BUILTINS = new Set([
212
+ "print",
213
+ "len",
214
+ "range",
215
+ "str",
216
+ "int",
217
+ "float",
218
+ "bool",
219
+ "list",
220
+ "dict",
221
+ "set",
222
+ "tuple",
223
+ "isinstance",
224
+ "issubclass",
225
+ "super",
226
+ "open",
227
+ "enumerate",
228
+ "zip",
229
+ "map",
230
+ "filter",
231
+ "sorted",
232
+ "reversed",
233
+ "sum",
234
+ "min",
235
+ "max",
236
+ "abs",
237
+ "round",
238
+ "getattr",
239
+ "setattr",
240
+ "hasattr",
241
+ "type",
242
+ "repr",
243
+ "format",
244
+ "iter",
245
+ "next",
246
+ "any",
247
+ "all",
248
+ ]);
249
+ /** Heuristic baseline call edges. A call to a function/method defined in the SAME file resolves
250
+ * straight to a `Calls` edge (name-based; an ambiguous name defined more than once, and
251
+ * module-level calls with no enclosing function, are skipped). A call to a name NOT defined
252
+ * locally (and not a builtin) becomes a `call:<name>` candidate that {@link deriveCallEdges}
253
+ * resolves cross-file via the import graph. (ama-bnj) */
254
+ function pythonCalls(root, rel) {
255
+ const byName = new Map(); // simple name → id, or null when ambiguous
256
+ for (const fn of eachFunction(root)) {
257
+ const qn = qualifiedNameOf(fn);
258
+ if (!qn)
259
+ continue;
260
+ const simple = qn.slice(qn.lastIndexOf(".") + 1);
261
+ byName.set(simple, byName.has(simple) ? null : symbolId({ file: rel, qualifiedName: qn }));
262
+ }
263
+ const edges = [];
264
+ const seen = new Set();
265
+ for (const call of eachCall(root)) {
266
+ const enc = enclosingFunction(call);
267
+ const name = calleeName(call);
268
+ if (!enc || !name)
269
+ continue;
270
+ const callerQn = qualifiedNameOf(enc);
271
+ if (!callerQn)
272
+ continue;
273
+ const from = symbolId({ file: rel, qualifiedName: callerQn });
274
+ const local = byName.get(name);
275
+ if (local === null)
276
+ continue; // a name defined more than once locally — don't guess
277
+ if (local) {
278
+ // resolved within this file (slice 1)
279
+ const key = `c ${from} ${local}`;
280
+ if (from === local || seen.has(key))
281
+ continue; // skip self-recursion + duplicate sites
282
+ seen.add(key);
283
+ edges.push({ from, to: local, kind: "Calls", provenance: "heuristic" });
284
+ }
285
+ else if (!PYTHON_BUILTINS.has(name)) {
286
+ // not local — a cross-file candidate deriveCallEdges resolves via the import graph (slice 2)
287
+ const key = `r ${from} ${name}`;
288
+ if (seen.has(key))
289
+ continue;
290
+ seen.add(key);
291
+ edges.push({
292
+ from,
293
+ to: `${CALL_REF_PREFIX}${name}`,
294
+ kind: "References",
295
+ provenance: "call-ref",
296
+ });
297
+ }
298
+ }
299
+ return { nodes: [], edges };
300
+ }
144
301
  /**
145
302
  * Baseline (syntactic) spec for Python. Functions and classes are the symbols
146
303
  * worth a node; methods are `function_definition` too (Python doesn't
@@ -157,6 +314,7 @@ export const pythonSpec = {
157
314
  class_definition: { kind: "Class" },
158
315
  },
159
316
  resolveImports: pythonImports,
160
- collectRoutes: pythonRoutes,
317
+ collectRoutes: pythonRoutesAll,
318
+ collectCalls: pythonCalls,
161
319
  };
162
320
  //# sourceMappingURL=python.js.map