@opentrace/components 0.1.1-rc.47 → 0.1.1-rc.62

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 (111) hide show
  1. package/README.md +306 -0
  2. package/bin/copy-wasm.js +125 -0
  3. package/dist/opentrace-components.cjs +354 -246
  4. package/dist/opentrace-components.cjs.map +1 -1
  5. package/dist/opentrace-components.js +355 -247
  6. package/dist/opentrace-components.js.map +1 -1
  7. package/dist/pipeline-wasm.cjs +58 -0
  8. package/dist/pipeline-wasm.cjs.map +1 -0
  9. package/dist/pipeline-wasm.js +57 -0
  10. package/dist/pipeline-wasm.js.map +1 -0
  11. package/dist/pipeline.cjs +3481 -0
  12. package/dist/pipeline.cjs.map +1 -0
  13. package/dist/pipeline.js +3481 -0
  14. package/dist/pipeline.js.map +1 -0
  15. package/dist/src/GraphCanvas.d.ts +5 -0
  16. package/dist/src/GraphCanvas.d.ts.map +1 -1
  17. package/dist/src/colors/communityColors.d.ts.map +1 -1
  18. package/dist/src/config/graphLayout.d.ts +9 -9
  19. package/dist/src/config/graphLayout.d.ts.map +1 -1
  20. package/dist/src/graph/LayoutPipeline.d.ts +4 -6
  21. package/dist/src/graph/LayoutPipeline.d.ts.map +1 -1
  22. package/dist/src/graph/spacingWorker.d.ts +4 -0
  23. package/dist/src/graph/spacingWorker.d.ts.map +1 -1
  24. package/dist/src/graph/useGraphFilters.d.ts.map +1 -1
  25. package/dist/src/graph/useGraphInstance.d.ts.map +1 -1
  26. package/dist/src/graph/useGraphVisuals.d.ts.map +1 -1
  27. package/dist/src/index.d.ts +1 -1
  28. package/dist/src/index.d.ts.map +1 -1
  29. package/dist/src/pipeline/__tests__/cross-repo.test.d.ts +2 -0
  30. package/dist/src/pipeline/__tests__/cross-repo.test.d.ts.map +1 -0
  31. package/dist/src/pipeline/__tests__/fixture.test.d.ts +2 -0
  32. package/dist/src/pipeline/__tests__/fixture.test.d.ts.map +1 -0
  33. package/dist/src/pipeline/__tests__/github.test.d.ts +2 -0
  34. package/dist/src/pipeline/__tests__/github.test.d.ts.map +1 -0
  35. package/dist/src/pipeline/__tests__/helpers.d.ts +16 -0
  36. package/dist/src/pipeline/__tests__/helpers.d.ts.map +1 -0
  37. package/dist/src/pipeline/__tests__/loading.test.d.ts +2 -0
  38. package/dist/src/pipeline/__tests__/loading.test.d.ts.map +1 -0
  39. package/dist/src/pipeline/__tests__/parsing.test.d.ts +2 -0
  40. package/dist/src/pipeline/__tests__/parsing.test.d.ts.map +1 -0
  41. package/dist/src/pipeline/__tests__/pipeline.test.d.ts +2 -0
  42. package/dist/src/pipeline/__tests__/pipeline.test.d.ts.map +1 -0
  43. package/dist/src/pipeline/index.d.ts +19 -0
  44. package/dist/src/pipeline/index.d.ts.map +1 -0
  45. package/dist/src/pipeline/parser/callResolver.d.ts +52 -0
  46. package/dist/src/pipeline/parser/callResolver.d.ts.map +1 -0
  47. package/dist/src/pipeline/parser/extractors/generic.d.ts +15 -0
  48. package/dist/src/pipeline/parser/extractors/generic.d.ts.map +1 -0
  49. package/dist/src/pipeline/parser/extractors/go.d.ts +8 -0
  50. package/dist/src/pipeline/parser/extractors/go.d.ts.map +1 -0
  51. package/dist/src/pipeline/parser/extractors/python.d.ts +8 -0
  52. package/dist/src/pipeline/parser/extractors/python.d.ts.map +1 -0
  53. package/dist/src/pipeline/parser/extractors/typescript.d.ts +8 -0
  54. package/dist/src/pipeline/parser/extractors/typescript.d.ts.map +1 -0
  55. package/dist/src/pipeline/parser/importAnalyzer.d.ts +25 -0
  56. package/dist/src/pipeline/parser/importAnalyzer.d.ts.map +1 -0
  57. package/dist/src/pipeline/parser/manifestParser.d.ts +42 -0
  58. package/dist/src/pipeline/parser/manifestParser.d.ts.map +1 -0
  59. package/dist/src/pipeline/pipeline.d.ts +10 -0
  60. package/dist/src/pipeline/pipeline.d.ts.map +1 -0
  61. package/dist/src/pipeline/stages/loading.d.ts +6 -0
  62. package/dist/src/pipeline/stages/loading.d.ts.map +1 -0
  63. package/dist/src/pipeline/stages/parsing.d.ts +20 -0
  64. package/dist/src/pipeline/stages/parsing.d.ts.map +1 -0
  65. package/dist/src/pipeline/stages/processing.d.ts +15 -0
  66. package/dist/src/pipeline/stages/processing.d.ts.map +1 -0
  67. package/dist/src/pipeline/stages/resolving.d.ts +11 -0
  68. package/dist/src/pipeline/stages/resolving.d.ts.map +1 -0
  69. package/dist/src/pipeline/stages/saving.d.ts +7 -0
  70. package/dist/src/pipeline/stages/saving.d.ts.map +1 -0
  71. package/dist/src/pipeline/stages/scanning.d.ts +7 -0
  72. package/dist/src/pipeline/stages/scanning.d.ts.map +1 -0
  73. package/dist/src/pipeline/stages/summarizing.d.ts +16 -0
  74. package/dist/src/pipeline/stages/summarizing.d.ts.map +1 -0
  75. package/dist/src/pipeline/store/memory.d.ts +8 -0
  76. package/dist/src/pipeline/store/memory.d.ts.map +1 -0
  77. package/dist/src/pipeline/summarizer/templateSummarizer.d.ts +40 -0
  78. package/dist/src/pipeline/summarizer/templateSummarizer.d.ts.map +1 -0
  79. package/dist/src/pipeline/summarizer/types.d.ts +62 -0
  80. package/dist/src/pipeline/summarizer/types.d.ts.map +1 -0
  81. package/dist/src/pipeline/types.d.ts +119 -0
  82. package/dist/src/pipeline/types.d.ts.map +1 -0
  83. package/dist/src/pipeline/wasm.d.ts +14 -0
  84. package/dist/src/pipeline/wasm.d.ts.map +1 -0
  85. package/dist/src/sigma/useSelectionPulse.d.ts +3 -0
  86. package/dist/src/sigma/useSelectionPulse.d.ts.map +1 -0
  87. package/dist/{useHighlights-DbMfb0-p.js → useHighlights-CmOAWaLE.js} +60 -53
  88. package/dist/{useHighlights-DbMfb0-p.js.map → useHighlights-CmOAWaLE.js.map} +1 -1
  89. package/dist/{useHighlights-fRWg-A_c.cjs → useHighlights-zx7DM4V0.cjs} +60 -53
  90. package/dist/{useHighlights-fRWg-A_c.cjs.map → useHighlights-zx7DM4V0.cjs.map} +1 -1
  91. package/dist/utils.cjs +1 -1
  92. package/dist/utils.js +1 -1
  93. package/package.json +32 -4
  94. package/public/wasm/tree-sitter-bash.wasm +0 -0
  95. package/public/wasm/tree-sitter-c.wasm +0 -0
  96. package/public/wasm/tree-sitter-c_sharp.wasm +0 -0
  97. package/public/wasm/tree-sitter-cpp.wasm +0 -0
  98. package/public/wasm/tree-sitter-go.wasm +0 -0
  99. package/public/wasm/tree-sitter-java.wasm +0 -0
  100. package/public/wasm/tree-sitter-json.wasm +0 -0
  101. package/public/wasm/tree-sitter-kotlin.wasm +0 -0
  102. package/public/wasm/tree-sitter-python.wasm +0 -0
  103. package/public/wasm/tree-sitter-ruby.wasm +0 -0
  104. package/public/wasm/tree-sitter-rust.wasm +0 -0
  105. package/public/wasm/tree-sitter-swift.wasm +0 -0
  106. package/public/wasm/tree-sitter-toml.wasm +0 -0
  107. package/public/wasm/tree-sitter-tsx.wasm +0 -0
  108. package/public/wasm/tree-sitter-typescript.wasm +0 -0
  109. package/public/wasm/web-tree-sitter.wasm +0 -0
  110. package/dist/assets/spacingWorker-hXLGHyRg.js +0 -123
  111. package/dist/assets/spacingWorker-hXLGHyRg.js.map +0 -1
@@ -0,0 +1,3481 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const LANGUAGE_MAP = {
4
+ ".py": "python",
5
+ ".ts": "typescript",
6
+ ".tsx": "typescript",
7
+ ".js": "javascript",
8
+ ".jsx": "javascript",
9
+ ".go": "go",
10
+ ".rs": "rust",
11
+ ".java": "java",
12
+ ".kt": "kotlin",
13
+ ".rb": "ruby",
14
+ ".c": "c",
15
+ ".cpp": "cpp",
16
+ ".h": "c",
17
+ ".hpp": "cpp",
18
+ ".cs": "csharp",
19
+ ".swift": "swift"
20
+ };
21
+ function getExtension(path) {
22
+ const dot = path.lastIndexOf(".");
23
+ if (dot === -1 || dot === path.length - 1) return "";
24
+ return path.slice(dot);
25
+ }
26
+ function parentDir$1(path) {
27
+ const slash = path.lastIndexOf("/");
28
+ if (slash <= 0) return "";
29
+ return path.slice(0, slash);
30
+ }
31
+ function detectLanguage(ext) {
32
+ return LANGUAGE_MAP[ext] ?? null;
33
+ }
34
+ function ensureDirChain(repoId, dirPath, dirNodes, rels) {
35
+ if (!dirPath || dirNodes.has(dirPath)) return;
36
+ const parent = parentDir$1(dirPath);
37
+ ensureDirChain(repoId, parent, dirNodes, rels);
38
+ const dirId = `${repoId}/${dirPath}`;
39
+ const name = dirPath.includes("/") ? dirPath.slice(dirPath.lastIndexOf("/") + 1) : dirPath;
40
+ dirNodes.set(dirPath, {
41
+ id: dirId,
42
+ type: "Directory",
43
+ name,
44
+ properties: { path: dirPath }
45
+ });
46
+ const targetId = parent ? `${repoId}/${parent}` : repoId;
47
+ rels.push({
48
+ id: `${dirId}->DEFINED_IN->${targetId}`,
49
+ type: "DEFINED_IN",
50
+ source_id: dirId,
51
+ target_id: targetId
52
+ });
53
+ }
54
+ const MANIFEST_BASENAMES = /* @__PURE__ */ new Set([
55
+ "package.json",
56
+ "go.mod",
57
+ "requirements.txt",
58
+ "pyproject.toml",
59
+ "Cargo.toml"
60
+ ]);
61
+ const LOCK_BASENAMES = /* @__PURE__ */ new Set([
62
+ "package-lock.json",
63
+ "yarn.lock",
64
+ "pnpm-lock.yaml",
65
+ "go.sum",
66
+ "poetry.lock",
67
+ "Cargo.lock",
68
+ "uv.lock"
69
+ ]);
70
+ function isManifestFile(path) {
71
+ const basename = path.split("/").pop() ?? "";
72
+ if (LOCK_BASENAMES.has(basename)) return false;
73
+ return MANIFEST_BASENAMES.has(basename);
74
+ }
75
+ function parseManifest(path, content) {
76
+ const basename = path.split("/").pop() ?? "";
77
+ switch (basename) {
78
+ case "package.json":
79
+ return parsePackageJson(content, path);
80
+ case "go.mod":
81
+ return parseGoMod(content, path);
82
+ case "requirements.txt":
83
+ return parseRequirementsTxt(content, path);
84
+ case "pyproject.toml":
85
+ return parsePyprojectToml(content, path);
86
+ case "Cargo.toml":
87
+ return parseCargoToml(content, path);
88
+ default:
89
+ return {
90
+ dependencies: [],
91
+ errors: [`Unsupported manifest: ${basename}`]
92
+ };
93
+ }
94
+ }
95
+ function packageId(registry, name) {
96
+ return `pkg:${registry}:${name}`;
97
+ }
98
+ function packageSourceUrl(registry, name) {
99
+ switch (registry) {
100
+ case "npm":
101
+ return `https://www.npmjs.com/package/${name}`;
102
+ case "pypi":
103
+ return `https://pypi.org/project/${name}/`;
104
+ case "go":
105
+ return `https://pkg.go.dev/${name}`;
106
+ case "crates":
107
+ return `https://crates.io/crates/${name}`;
108
+ case "rubygems":
109
+ return `https://rubygems.org/gems/${name}`;
110
+ default:
111
+ return void 0;
112
+ }
113
+ }
114
+ function parsePackageJson(content, source) {
115
+ const errors = [];
116
+ const deps = [];
117
+ let parsed;
118
+ try {
119
+ parsed = JSON.parse(content);
120
+ } catch (e) {
121
+ return { dependencies: [], errors: [`Failed to parse ${source}: ${e}`] };
122
+ }
123
+ const sections = [
124
+ ["dependencies", "runtime"],
125
+ ["devDependencies", "dev"],
126
+ ["peerDependencies", "peer"],
127
+ ["optionalDependencies", "optional"]
128
+ ];
129
+ for (const [key, depType] of sections) {
130
+ const section = parsed[key];
131
+ if (!section || typeof section !== "object") continue;
132
+ for (const [name, version] of Object.entries(
133
+ section
134
+ )) {
135
+ deps.push({
136
+ name,
137
+ version: typeof version === "string" ? version : "",
138
+ registry: "npm",
139
+ source,
140
+ dependencyType: depType
141
+ });
142
+ }
143
+ }
144
+ return { dependencies: deps, errors };
145
+ }
146
+ function parseGoMod(content, source) {
147
+ const deps = [];
148
+ const errors = [];
149
+ const blockRe = /require\s*\(([\s\S]*?)\)/g;
150
+ let match;
151
+ while ((match = blockRe.exec(content)) !== null) {
152
+ const block = match[1];
153
+ for (const line of block.split("\n")) {
154
+ const dep = parseGoRequireLine(line, source);
155
+ if (dep) deps.push(dep);
156
+ }
157
+ }
158
+ const singleRe = /^require\s+(\S+)\s+(\S+)(.*)$/gm;
159
+ while ((match = singleRe.exec(content)) !== null) {
160
+ const depType = match[3]?.includes("// indirect") ? "indirect" : "runtime";
161
+ deps.push({
162
+ name: match[1],
163
+ version: match[2],
164
+ registry: "go",
165
+ source,
166
+ dependencyType: depType
167
+ });
168
+ }
169
+ return { dependencies: deps, errors };
170
+ }
171
+ function parseGoRequireLine(line, source) {
172
+ const trimmed = line.trim();
173
+ if (!trimmed || trimmed.startsWith("//")) return null;
174
+ const parts = trimmed.split(/\s+/);
175
+ if (parts.length < 2) return null;
176
+ const depType = trimmed.includes("// indirect") ? "indirect" : "runtime";
177
+ return {
178
+ name: parts[0],
179
+ version: parts[1],
180
+ registry: "go",
181
+ source,
182
+ dependencyType: depType
183
+ };
184
+ }
185
+ function parseRequirementsTxt(content, source) {
186
+ const deps = [];
187
+ const errors = [];
188
+ for (const rawLine of content.split("\n")) {
189
+ const line = rawLine.trim();
190
+ if (!line || line.startsWith("#") || line.startsWith("-") || line.startsWith("http"))
191
+ continue;
192
+ const match = line.match(
193
+ /^([A-Za-z0-9_.-]+)(?:\[.*?\])?\s*([<>=!~]+\s*\S+)?/
194
+ );
195
+ if (!match) continue;
196
+ const rawName = match[1];
197
+ const version = match[2]?.trim() ?? "*";
198
+ deps.push({
199
+ name: normalizePyName(rawName),
200
+ version,
201
+ registry: "pypi",
202
+ source,
203
+ dependencyType: "runtime"
204
+ });
205
+ }
206
+ return { dependencies: deps, errors };
207
+ }
208
+ function parsePyprojectToml(content, source) {
209
+ const deps = [];
210
+ const errors = [];
211
+ const lines = content.split("\n");
212
+ let i = 0;
213
+ let currentSection = "";
214
+ while (i < lines.length) {
215
+ const line = lines[i].trim();
216
+ if (line.startsWith("[")) {
217
+ currentSection = line;
218
+ i++;
219
+ continue;
220
+ }
221
+ if (currentSection === "[project]" && line.startsWith("dependencies")) {
222
+ const eqIdx = line.indexOf("=");
223
+ if (eqIdx === -1) {
224
+ i++;
225
+ continue;
226
+ }
227
+ const afterEq = line.slice(eqIdx + 1).trim();
228
+ if (afterEq.startsWith("[")) {
229
+ const arrayContent = collectTomlArray(lines, i, eqIdx + 1);
230
+ for (const item of parseTomlStringArray(arrayContent)) {
231
+ const dep = parsePep508(item, source);
232
+ if (dep) deps.push(dep);
233
+ }
234
+ }
235
+ i++;
236
+ continue;
237
+ }
238
+ if (currentSection === "[tool.poetry.dependencies]") {
239
+ const eqIdx = line.indexOf("=");
240
+ if (eqIdx > 0 && !line.startsWith("#") && !line.startsWith("[")) {
241
+ const name = line.slice(0, eqIdx).trim();
242
+ if (name === "python") {
243
+ i++;
244
+ continue;
245
+ }
246
+ const value = line.slice(eqIdx + 1).trim();
247
+ const version = value.replace(/^["']|["']$/g, "");
248
+ deps.push({
249
+ name: normalizePyName(name),
250
+ version,
251
+ registry: "pypi",
252
+ source,
253
+ dependencyType: "runtime"
254
+ });
255
+ }
256
+ }
257
+ if (currentSection.startsWith("[project.optional-dependencies")) {
258
+ if (line.includes("=") && !line.startsWith("#")) {
259
+ const eqIdx = line.indexOf("=");
260
+ const afterEq = line.slice(eqIdx + 1).trim();
261
+ if (afterEq.startsWith("[")) {
262
+ const arrayContent = collectTomlArray(lines, i, eqIdx + 1);
263
+ for (const item of parseTomlStringArray(arrayContent)) {
264
+ const dep = parsePep508(item, source, "optional");
265
+ if (dep) deps.push(dep);
266
+ }
267
+ }
268
+ }
269
+ }
270
+ i++;
271
+ }
272
+ return { dependencies: deps, errors };
273
+ }
274
+ function collectTomlArray(lines, startLine, charOffset) {
275
+ let result = lines[startLine].slice(charOffset).trim();
276
+ if (bracketsClosed(result)) return result;
277
+ for (let i = startLine + 1; i < lines.length; i++) {
278
+ result += "\n" + lines[i];
279
+ if (bracketsClosed(result)) break;
280
+ }
281
+ return result;
282
+ }
283
+ function bracketsClosed(s) {
284
+ let depth = 0;
285
+ for (const ch of s) {
286
+ if (ch === "[") depth++;
287
+ else if (ch === "]") depth--;
288
+ if (depth === 0 && s.indexOf("[") !== -1) return true;
289
+ }
290
+ return false;
291
+ }
292
+ function parseTomlStringArray(raw) {
293
+ const items = [];
294
+ const re = /["']([^"']+)["']/g;
295
+ let m;
296
+ while ((m = re.exec(raw)) !== null) {
297
+ items.push(m[1]);
298
+ }
299
+ return items;
300
+ }
301
+ function parsePep508(spec, source, depType = "runtime") {
302
+ const trimmed = spec.trim();
303
+ if (!trimmed) return null;
304
+ const match = trimmed.match(
305
+ /^([A-Za-z0-9_.-]+)(?:\[.*?\])?\s*([<>=!~]+.*)?$/
306
+ );
307
+ if (!match) return null;
308
+ return {
309
+ name: normalizePyName(match[1]),
310
+ version: match[2]?.trim() ?? "*",
311
+ registry: "pypi",
312
+ source,
313
+ dependencyType: depType
314
+ };
315
+ }
316
+ function normalizePyName(name) {
317
+ return name.toLowerCase().replace(/_/g, "-");
318
+ }
319
+ function parseCargoToml(content, source) {
320
+ const deps = [];
321
+ const errors = [];
322
+ const lines = content.split("\n");
323
+ let currentSection = "";
324
+ const depSections = {
325
+ "[dependencies]": "runtime",
326
+ "[dev-dependencies]": "dev",
327
+ "[build-dependencies]": "dev"
328
+ };
329
+ for (const rawLine of lines) {
330
+ const line = rawLine.trim();
331
+ if (line.startsWith("[")) {
332
+ currentSection = line;
333
+ continue;
334
+ }
335
+ if (line.startsWith("#") || !line) continue;
336
+ const depType = depSections[currentSection];
337
+ if (!depType) continue;
338
+ const eqIdx = line.indexOf("=");
339
+ if (eqIdx <= 0) continue;
340
+ const name = line.slice(0, eqIdx).trim();
341
+ const value = line.slice(eqIdx + 1).trim();
342
+ let version = "*";
343
+ if (value.startsWith('"') || value.startsWith("'")) {
344
+ version = value.replace(/^["']|["']$/g, "");
345
+ } else if (value.startsWith("{")) {
346
+ const verMatch = value.match(/version\s*=\s*["']([^"']+)["']/);
347
+ if (verMatch) version = verMatch[1];
348
+ }
349
+ deps.push({
350
+ name,
351
+ version,
352
+ registry: "crates",
353
+ source,
354
+ dependencyType: depType
355
+ });
356
+ }
357
+ return { dependencies: deps, errors };
358
+ }
359
+ function npmPackageName(specifier) {
360
+ if (specifier.startsWith("@")) {
361
+ const parts = specifier.split("/");
362
+ return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : specifier;
363
+ }
364
+ return specifier.split("/")[0];
365
+ }
366
+ const PARSEABLE_LANGUAGES = /* @__PURE__ */ new Set([
367
+ "python",
368
+ "typescript",
369
+ "javascript",
370
+ "go",
371
+ "rust",
372
+ "java",
373
+ "kotlin",
374
+ "csharp",
375
+ "c",
376
+ "cpp",
377
+ "ruby",
378
+ "swift"
379
+ ]);
380
+ function* execute$3(input, ctx) {
381
+ const { repo } = input;
382
+ const repoId = `${repo.owner}/${repo.repo}`;
383
+ yield {
384
+ kind: "stage_start",
385
+ phase: "scanning",
386
+ message: `Scanning ${repo.files.length} files`
387
+ };
388
+ const repoProps = { ref: repo.ref };
389
+ if (repo.url) repoProps.source_uri = repo.url;
390
+ if (repo.provider) repoProps.provider = repo.provider;
391
+ const repoNode = {
392
+ id: repoId,
393
+ type: "Repository",
394
+ name: repoId,
395
+ properties: repoProps
396
+ };
397
+ const dirNodes = /* @__PURE__ */ new Map();
398
+ const fileNodes = [];
399
+ const structureRels = [];
400
+ const parseableFiles = [];
401
+ const packageNodes = /* @__PURE__ */ new Map();
402
+ const dependencyRels = [];
403
+ let goModulePath;
404
+ const knownPaths = /* @__PURE__ */ new Set();
405
+ const pathToFileId = /* @__PURE__ */ new Map();
406
+ const total = repo.files.length;
407
+ for (let i = 0; i < repo.files.length; i++) {
408
+ if (ctx.cancelled) break;
409
+ const file = repo.files[i];
410
+ const ext = getExtension(file.path);
411
+ const language = detectLanguage(ext);
412
+ const fileId = `${repoId}/${file.path}`;
413
+ const fileName = file.path.includes("/") ? file.path.slice(file.path.lastIndexOf("/") + 1) : file.path;
414
+ const fileProps = {
415
+ path: file.path,
416
+ extension: ext
417
+ };
418
+ if (language) fileProps.language = language;
419
+ if (repo.url) {
420
+ fileProps.source_uri = `${repo.url}/blob/${repo.ref}/${file.path}`;
421
+ }
422
+ fileNodes.push({
423
+ id: fileId,
424
+ type: "File",
425
+ name: fileName,
426
+ properties: fileProps
427
+ });
428
+ const dir = parentDir$1(file.path);
429
+ ensureDirChain(repoId, dir, dirNodes, structureRels);
430
+ const parentId = dir ? `${repoId}/${dir}` : repoId;
431
+ structureRels.push({
432
+ id: `${fileId}->DEFINED_IN->${parentId}`,
433
+ type: "DEFINED_IN",
434
+ source_id: fileId,
435
+ target_id: parentId
436
+ });
437
+ if (language && PARSEABLE_LANGUAGES.has(language)) {
438
+ parseableFiles.push(file);
439
+ }
440
+ knownPaths.add(file.path);
441
+ pathToFileId.set(file.path, fileId);
442
+ if (isManifestFile(file.path)) {
443
+ const manifestResult = parseManifest(file.path, file.content);
444
+ if (file.path.endsWith("go.mod") || file.path.includes("/go.mod")) {
445
+ const moduleMatch = file.content.match(/^module\s+(\S+)/m);
446
+ if (moduleMatch) goModulePath = moduleMatch[1];
447
+ }
448
+ for (const dep of manifestResult.dependencies) {
449
+ const pkgId = packageId(dep.registry, dep.name);
450
+ if (!packageNodes.has(pkgId)) {
451
+ const props = {
452
+ registry: dep.registry,
453
+ version: dep.version
454
+ };
455
+ const sourceUrl = packageSourceUrl(dep.registry, dep.name);
456
+ if (sourceUrl) props.source_uri = sourceUrl;
457
+ packageNodes.set(pkgId, {
458
+ id: pkgId,
459
+ type: "Package",
460
+ name: dep.name,
461
+ properties: props
462
+ });
463
+ }
464
+ dependencyRels.push({
465
+ id: `${repoId}->DEPENDS_ON->${pkgId}`,
466
+ type: "DEPENDS_ON",
467
+ source_id: repoId,
468
+ target_id: pkgId,
469
+ properties: {
470
+ version: dep.version,
471
+ dependency_type: dep.dependencyType,
472
+ source: dep.source
473
+ }
474
+ });
475
+ }
476
+ }
477
+ yield {
478
+ kind: "stage_progress",
479
+ phase: "scanning",
480
+ message: `Scanning ${file.path}`,
481
+ detail: { current: i + 1, total, fileName: file.path }
482
+ };
483
+ }
484
+ const structureNodes = [
485
+ repoNode,
486
+ ...dirNodes.values(),
487
+ ...fileNodes,
488
+ ...packageNodes.values()
489
+ ];
490
+ yield {
491
+ kind: "stage_stop",
492
+ phase: "scanning",
493
+ message: `Scanned ${fileNodes.length} files, ${dirNodes.size} directories, ${packageNodes.size} packages`,
494
+ nodes: structureNodes,
495
+ relationships: [...structureRels, ...dependencyRels]
496
+ };
497
+ return {
498
+ repo,
499
+ repoId,
500
+ repoNode,
501
+ dirNodes,
502
+ fileNodes,
503
+ structureRels,
504
+ parseableFiles,
505
+ packageNodes,
506
+ dependencyRels,
507
+ goModulePath,
508
+ knownPaths,
509
+ pathToFileId
510
+ };
511
+ }
512
+ function extractDocstring(bodyNode) {
513
+ if (!bodyNode) return void 0;
514
+ const first = bodyNode.namedChildren[0];
515
+ if (!first || first.type !== "expression_statement") return void 0;
516
+ const strNode = first.namedChildren[0];
517
+ if (!strNode || strNode.type !== "string") return void 0;
518
+ const raw = strNode.text;
519
+ const stripped = raw.replace(/^("""|''')\s?/, "").replace(/\s?("""|''')$/, "");
520
+ return stripped.trim() || void 0;
521
+ }
522
+ function extractPython(rootNode) {
523
+ const symbols = walkNode$2(rootNode);
524
+ return { symbols, language: "python", rootNode };
525
+ }
526
+ function walkNode$2(node) {
527
+ const symbols = [];
528
+ for (const child of node.children) {
529
+ if (child.type === "class_definition") {
530
+ const sym = extractClass$2(child);
531
+ if (sym) symbols.push(sym);
532
+ } else if (child.type === "function_definition") {
533
+ const sym = extractFunction$3(child);
534
+ if (sym) symbols.push(sym);
535
+ } else if (child.type === "decorated_definition") {
536
+ for (const sub of child.children) {
537
+ if (sub.type === "class_definition") {
538
+ const sym = extractClass$2(sub);
539
+ if (sym) symbols.push(sym);
540
+ } else if (sub.type === "function_definition") {
541
+ const sym = extractFunction$3(sub);
542
+ if (sym) symbols.push(sym);
543
+ }
544
+ }
545
+ }
546
+ }
547
+ return symbols;
548
+ }
549
+ function extractClass$2(node) {
550
+ const nameNode = node.childForFieldName("name");
551
+ if (!nameNode) return null;
552
+ const bodyNode = node.childForFieldName("body");
553
+ const children = walkClassBody$1(node);
554
+ const superclasses = extractBaseClasses(node);
555
+ const docs = extractDocstring(bodyNode);
556
+ return {
557
+ name: nameNode.text,
558
+ kind: "class",
559
+ startLine: node.startPosition.row + 1,
560
+ endLine: node.endPosition.row + 1,
561
+ signature: null,
562
+ children,
563
+ calls: [],
564
+ receiverVar: null,
565
+ receiverType: null,
566
+ paramTypes: null,
567
+ superclasses: superclasses.length > 0 ? superclasses : void 0,
568
+ docs
569
+ };
570
+ }
571
+ function extractBaseClasses(node) {
572
+ const bases = [];
573
+ const argList = node.childForFieldName("superclasses");
574
+ if (!argList) return bases;
575
+ for (const child of argList.children) {
576
+ if (child.type === "identifier") {
577
+ bases.push(child.text);
578
+ } else if (child.type === "attribute") {
579
+ bases.push(child.text);
580
+ } else if (child.type === "keyword_argument") ;
581
+ }
582
+ return bases;
583
+ }
584
+ function walkClassBody$1(node) {
585
+ const body = node.childForFieldName("body");
586
+ if (!body) return [];
587
+ const methods = [];
588
+ for (const child of body.children) {
589
+ if (child.type === "function_definition") {
590
+ const sym = extractFunction$3(child);
591
+ if (sym) methods.push(sym);
592
+ } else if (child.type === "decorated_definition") {
593
+ for (const sub of child.children) {
594
+ if (sub.type === "function_definition") {
595
+ const sym = extractFunction$3(sub);
596
+ if (sym) methods.push(sym);
597
+ }
598
+ }
599
+ }
600
+ }
601
+ return methods;
602
+ }
603
+ function extractFunction$3(node) {
604
+ const nameNode = node.childForFieldName("name");
605
+ if (!nameNode) return null;
606
+ const paramsNode = node.childForFieldName("parameters");
607
+ const signature = paramsNode ? paramsNode.text : null;
608
+ const paramTypes = paramsNode ? extractParamTypes(paramsNode) : null;
609
+ const bodyNode = node.childForFieldName("body");
610
+ const calls = bodyNode ? collectCalls$2(bodyNode) : [];
611
+ const docs = extractDocstring(bodyNode);
612
+ return {
613
+ name: nameNode.text,
614
+ kind: "function",
615
+ startLine: node.startPosition.row + 1,
616
+ endLine: node.endPosition.row + 1,
617
+ signature,
618
+ children: [],
619
+ calls,
620
+ receiverVar: null,
621
+ receiverType: null,
622
+ paramTypes,
623
+ docs
624
+ };
625
+ }
626
+ function extractParamTypes(paramsNode) {
627
+ const types = {};
628
+ for (const child of paramsNode.children) {
629
+ if (child.type === "typed_parameter" || child.type === "typed_default_parameter") {
630
+ let nameNode = null;
631
+ for (const sub of child.children) {
632
+ if (sub.type === "identifier") {
633
+ nameNode = sub;
634
+ break;
635
+ }
636
+ }
637
+ const typeNode = child.childForFieldName("type");
638
+ if (nameNode && typeNode) {
639
+ const paramName = nameNode.text;
640
+ if (paramName === "self" || paramName === "cls") continue;
641
+ const typeText = typeNode.text;
642
+ const leaf = typeText.includes(".") ? typeText.split(".").pop() : typeText;
643
+ types[paramName] = leaf;
644
+ }
645
+ }
646
+ }
647
+ return Object.keys(types).length > 0 ? types : null;
648
+ }
649
+ function collectCalls$2(node) {
650
+ const calls = [];
651
+ for (const child of node.children) {
652
+ if (child.type === "call") {
653
+ const funcNode = child.childForFieldName("function");
654
+ if (funcNode && funcNode.type === "identifier") {
655
+ calls.push({ name: funcNode.text, receiver: null, kind: "bare" });
656
+ } else if (funcNode && funcNode.type === "attribute") {
657
+ const objNode = funcNode.childForFieldName("object");
658
+ const attrNode = funcNode.childForFieldName("attribute");
659
+ if (objNode && attrNode) {
660
+ calls.push({
661
+ name: attrNode.text,
662
+ receiver: objNode.text,
663
+ kind: "attribute"
664
+ });
665
+ }
666
+ }
667
+ }
668
+ calls.push(...collectCalls$2(child));
669
+ }
670
+ return calls;
671
+ }
672
+ const CLASS_TYPES = /* @__PURE__ */ new Set([
673
+ "class_declaration",
674
+ "abstract_class_declaration"
675
+ ]);
676
+ const FUNCTION_TYPES = /* @__PURE__ */ new Set([
677
+ "function_declaration",
678
+ "generator_function_declaration"
679
+ ]);
680
+ const METHOD_TYPES = /* @__PURE__ */ new Set(["method_definition", "public_field_definition"]);
681
+ function extractJSDoc(node) {
682
+ let prev = node.previousNamedSibling;
683
+ if ((!prev || prev.type !== "comment") && node.parent?.type === "export_statement") {
684
+ prev = node.parent.previousNamedSibling;
685
+ }
686
+ if (!prev || prev.type !== "comment") return void 0;
687
+ const text = prev.text;
688
+ if (!text.startsWith("/**")) return void 0;
689
+ const cleaned = text.replace(/^\/\*\*\s*/, "").replace(/\s*\*\/$/, "").split("\n").map((line) => line.replace(/^\s*\*\s?/, "")).join("\n").trim();
690
+ return cleaned || void 0;
691
+ }
692
+ function extractTypeScript(rootNode, language = "typescript") {
693
+ const symbols = walkNode$1(rootNode);
694
+ return { symbols, language, rootNode };
695
+ }
696
+ function walkNode$1(node) {
697
+ const symbols = [];
698
+ for (const child of node.children) {
699
+ if (CLASS_TYPES.has(child.type)) {
700
+ const sym = extractClass$1(child);
701
+ if (sym) symbols.push(sym);
702
+ } else if (FUNCTION_TYPES.has(child.type)) {
703
+ const sym = extractFunction$2(child);
704
+ if (sym) symbols.push(sym);
705
+ } else if (child.type === "lexical_declaration") {
706
+ symbols.push(...extractLexicalDeclaration(child));
707
+ } else if (child.type === "export_statement") {
708
+ symbols.push(...walkNode$1(child));
709
+ }
710
+ }
711
+ return symbols;
712
+ }
713
+ function extractClass$1(node) {
714
+ const nameNode = node.childForFieldName("name");
715
+ if (!nameNode) return null;
716
+ const children = walkClassBody(node);
717
+ const { superclasses, interfaces } = extractClassHeritage(node);
718
+ const docs = extractJSDoc(node);
719
+ return {
720
+ name: nameNode.text,
721
+ kind: "class",
722
+ startLine: node.startPosition.row + 1,
723
+ endLine: node.endPosition.row + 1,
724
+ signature: null,
725
+ children,
726
+ calls: [],
727
+ receiverVar: null,
728
+ receiverType: null,
729
+ paramTypes: null,
730
+ superclasses: superclasses.length > 0 ? superclasses : void 0,
731
+ interfaces: interfaces.length > 0 ? interfaces : void 0,
732
+ docs
733
+ };
734
+ }
735
+ function extractClassHeritage(node) {
736
+ const superclasses = [];
737
+ const interfaces = [];
738
+ for (const child of node.children) {
739
+ if (child.type === "class_heritage") {
740
+ for (const clause of child.children) {
741
+ if (clause.type === "extends_clause") {
742
+ superclasses.push(...collectHeritageNames(clause));
743
+ } else if (clause.type === "implements_clause") {
744
+ interfaces.push(...collectHeritageNames(clause));
745
+ }
746
+ }
747
+ }
748
+ }
749
+ return { superclasses, interfaces };
750
+ }
751
+ function collectHeritageNames(clause) {
752
+ const names = [];
753
+ for (const child of clause.children) {
754
+ if (child.type === "identifier" || child.type === "type_identifier") {
755
+ names.push(child.text);
756
+ } else if (child.type === "generic_type") {
757
+ const nameNode = child.childForFieldName("name");
758
+ if (nameNode) names.push(nameNode.text);
759
+ }
760
+ }
761
+ return names;
762
+ }
763
+ function walkClassBody(node) {
764
+ const body = node.childForFieldName("body");
765
+ if (!body) return [];
766
+ const methods = [];
767
+ for (const child of body.children) {
768
+ if (METHOD_TYPES.has(child.type)) {
769
+ const sym = extractMethod$1(child);
770
+ if (sym) methods.push(sym);
771
+ }
772
+ }
773
+ return methods;
774
+ }
775
+ function extractFunction$2(node) {
776
+ const nameNode = node.childForFieldName("name");
777
+ if (!nameNode) return null;
778
+ const paramsNode = node.childForFieldName("parameters");
779
+ const signature = paramsNode ? paramsNode.text : null;
780
+ const bodyNode = node.childForFieldName("body");
781
+ const calls = bodyNode ? collectCalls$1(bodyNode) : [];
782
+ const docs = extractJSDoc(node);
783
+ return {
784
+ name: nameNode.text,
785
+ kind: "function",
786
+ startLine: node.startPosition.row + 1,
787
+ endLine: node.endPosition.row + 1,
788
+ signature,
789
+ children: [],
790
+ calls,
791
+ receiverVar: null,
792
+ receiverType: null,
793
+ paramTypes: null,
794
+ docs
795
+ };
796
+ }
797
+ function extractMethod$1(node) {
798
+ const nameNode = node.childForFieldName("name");
799
+ if (!nameNode) return null;
800
+ const paramsNode = node.childForFieldName("parameters");
801
+ const signature = paramsNode ? paramsNode.text : null;
802
+ const bodyNode = node.childForFieldName("body");
803
+ const calls = bodyNode ? collectCalls$1(bodyNode) : [];
804
+ const docs = extractJSDoc(node);
805
+ return {
806
+ name: nameNode.text,
807
+ kind: "function",
808
+ startLine: node.startPosition.row + 1,
809
+ endLine: node.endPosition.row + 1,
810
+ signature,
811
+ children: [],
812
+ calls,
813
+ receiverVar: null,
814
+ receiverType: null,
815
+ paramTypes: null,
816
+ docs
817
+ };
818
+ }
819
+ function extractLexicalDeclaration(node) {
820
+ const symbols = [];
821
+ for (const child of node.children) {
822
+ if (child.type === "variable_declarator") {
823
+ const nameNode = child.childForFieldName("name");
824
+ const valueNode = child.childForFieldName("value");
825
+ if (!nameNode || !valueNode) continue;
826
+ const name = nameNode.text;
827
+ if (valueNode.type === "arrow_function" || valueNode.type === "function_expression") {
828
+ const sym = extractArrowFunction(name, node, valueNode);
829
+ if (sym) symbols.push(sym);
830
+ } else if (valueNode.type === "class") {
831
+ const sym = extractClassExpression(name, node, valueNode);
832
+ if (sym) symbols.push(sym);
833
+ }
834
+ }
835
+ }
836
+ return symbols;
837
+ }
838
+ function extractArrowFunction(name, declNode, valueNode) {
839
+ const paramsNode = valueNode.childForFieldName("parameters");
840
+ const signature = paramsNode ? paramsNode.text : null;
841
+ const bodyNode = valueNode.childForFieldName("body");
842
+ const calls = bodyNode ? collectCalls$1(bodyNode) : [];
843
+ const docs = extractJSDoc(declNode);
844
+ return {
845
+ name,
846
+ kind: "function",
847
+ startLine: declNode.startPosition.row + 1,
848
+ endLine: declNode.endPosition.row + 1,
849
+ signature,
850
+ children: [],
851
+ calls,
852
+ receiverVar: null,
853
+ receiverType: null,
854
+ paramTypes: null,
855
+ docs
856
+ };
857
+ }
858
+ function extractClassExpression(name, declNode, valueNode) {
859
+ const children = walkClassBody(valueNode);
860
+ const { superclasses, interfaces } = extractClassHeritage(valueNode);
861
+ const docs = extractJSDoc(declNode);
862
+ return {
863
+ name,
864
+ kind: "class",
865
+ startLine: declNode.startPosition.row + 1,
866
+ endLine: declNode.endPosition.row + 1,
867
+ signature: null,
868
+ children,
869
+ calls: [],
870
+ receiverVar: null,
871
+ receiverType: null,
872
+ paramTypes: null,
873
+ superclasses: superclasses.length > 0 ? superclasses : void 0,
874
+ interfaces: interfaces.length > 0 ? interfaces : void 0,
875
+ docs
876
+ };
877
+ }
878
+ function collectCalls$1(node) {
879
+ const calls = [];
880
+ if (node.type === "call_expression") {
881
+ const funcNode = node.childForFieldName("function");
882
+ if (funcNode && funcNode.type === "identifier") {
883
+ calls.push({ name: funcNode.text, receiver: null, kind: "bare" });
884
+ } else if (funcNode && funcNode.type === "member_expression") {
885
+ const objNode = funcNode.childForFieldName("object");
886
+ const propNode = funcNode.childForFieldName("property");
887
+ if (objNode && propNode) {
888
+ calls.push({
889
+ name: propNode.text,
890
+ receiver: objNode.text,
891
+ kind: "attribute"
892
+ });
893
+ }
894
+ }
895
+ }
896
+ for (const child of node.children) {
897
+ calls.push(...collectCalls$1(child));
898
+ }
899
+ return calls;
900
+ }
901
+ function extractGoDoc(node) {
902
+ const comments = [];
903
+ let prev = node.previousNamedSibling;
904
+ while (prev && prev.type === "comment") {
905
+ comments.push(prev.text);
906
+ prev = prev.previousNamedSibling;
907
+ }
908
+ if (comments.length === 0) return void 0;
909
+ const cleaned = comments.reverse().map((line) => line.replace(/^\/\/\s?/, "")).join("\n").trim();
910
+ return cleaned || void 0;
911
+ }
912
+ function extractGo(rootNode) {
913
+ const symbols = walkNode(rootNode);
914
+ return { symbols, language: "go", rootNode };
915
+ }
916
+ function walkNode(node) {
917
+ const symbols = [];
918
+ for (const child of node.children) {
919
+ let sym = null;
920
+ if (child.type === "type_declaration") {
921
+ sym = extractTypeDecl(child);
922
+ } else if (child.type === "function_declaration") {
923
+ sym = extractFunction$1(child);
924
+ } else if (child.type === "method_declaration") {
925
+ sym = extractMethod(child);
926
+ }
927
+ if (sym) {
928
+ sym.docs = extractGoDoc(child);
929
+ symbols.push(sym);
930
+ }
931
+ }
932
+ return symbols;
933
+ }
934
+ function extractTypeDecl(node) {
935
+ for (const child of node.children) {
936
+ if (child.type === "type_spec") {
937
+ const nameNode = child.childForFieldName("name");
938
+ if (!nameNode) continue;
939
+ const typeNode = child.childForFieldName("type");
940
+ if (typeNode && (typeNode.type === "struct_type" || typeNode.type === "interface_type")) {
941
+ const isInterface = typeNode.type === "interface_type";
942
+ const methods = isInterface ? extractInterfaceMethods(typeNode) : [];
943
+ const subtype = isInterface ? "interface" : "struct";
944
+ const embedded = isInterface ? extractEmbeddedInterfaces(typeNode) : extractEmbeddedStructs(typeNode);
945
+ return {
946
+ name: nameNode.text,
947
+ kind: "class",
948
+ startLine: node.startPosition.row + 1,
949
+ endLine: node.endPosition.row + 1,
950
+ signature: null,
951
+ children: methods,
952
+ calls: [],
953
+ receiverVar: null,
954
+ receiverType: null,
955
+ paramTypes: null,
956
+ subtype,
957
+ interfaces: isInterface && embedded.length > 0 ? embedded : void 0,
958
+ superclasses: !isInterface && embedded.length > 0 ? embedded : void 0
959
+ };
960
+ }
961
+ }
962
+ }
963
+ return null;
964
+ }
965
+ function extractEmbeddedInterfaces(node) {
966
+ const names = [];
967
+ for (const child of node.children) {
968
+ if (child.type === "type_elem") {
969
+ for (const sub of child.children) {
970
+ if (sub.type === "type_identifier") {
971
+ names.push(sub.text);
972
+ } else if (sub.type === "qualified_type") {
973
+ names.push(sub.text);
974
+ }
975
+ }
976
+ }
977
+ }
978
+ return names;
979
+ }
980
+ function extractEmbeddedStructs(node) {
981
+ const names = [];
982
+ for (const child of node.children) {
983
+ if (child.type === "field_declaration_list") {
984
+ for (const field of child.children) {
985
+ if (field.type === "field_declaration") {
986
+ const nameNode = field.childForFieldName("name");
987
+ const typeNode = field.childForFieldName("type");
988
+ if (!nameNode && typeNode) {
989
+ if (typeNode.type === "type_identifier") {
990
+ names.push(typeNode.text);
991
+ } else if (typeNode.type === "pointer_type") {
992
+ for (const sub of typeNode.children) {
993
+ if (sub.type === "type_identifier") {
994
+ names.push(sub.text);
995
+ break;
996
+ }
997
+ }
998
+ } else if (typeNode.type === "qualified_type") {
999
+ names.push(typeNode.text);
1000
+ }
1001
+ }
1002
+ }
1003
+ }
1004
+ }
1005
+ }
1006
+ return names;
1007
+ }
1008
+ function extractInterfaceMethods(node) {
1009
+ const methods = [];
1010
+ for (const child of node.children) {
1011
+ if (child.type === "method_elem") {
1012
+ const nameNode = child.childForFieldName("name");
1013
+ if (nameNode) {
1014
+ const paramsNode = child.childForFieldName("parameters");
1015
+ methods.push({
1016
+ name: nameNode.text,
1017
+ kind: "function",
1018
+ startLine: child.startPosition.row + 1,
1019
+ endLine: child.endPosition.row + 1,
1020
+ signature: paramsNode ? paramsNode.text : null,
1021
+ children: [],
1022
+ calls: [],
1023
+ receiverVar: null,
1024
+ receiverType: null,
1025
+ paramTypes: null
1026
+ });
1027
+ }
1028
+ }
1029
+ }
1030
+ return methods;
1031
+ }
1032
+ function extractFunction$1(node) {
1033
+ const nameNode = node.childForFieldName("name");
1034
+ if (!nameNode) return null;
1035
+ const paramsNode = node.childForFieldName("parameters");
1036
+ const signature = paramsNode ? paramsNode.text : null;
1037
+ const bodyNode = node.childForFieldName("body");
1038
+ const calls = bodyNode ? collectCalls(bodyNode) : [];
1039
+ return {
1040
+ name: nameNode.text,
1041
+ kind: "function",
1042
+ startLine: node.startPosition.row + 1,
1043
+ endLine: node.endPosition.row + 1,
1044
+ signature,
1045
+ children: [],
1046
+ calls,
1047
+ receiverVar: null,
1048
+ receiverType: null,
1049
+ paramTypes: null
1050
+ };
1051
+ }
1052
+ function extractMethod(node) {
1053
+ const nameNode = node.childForFieldName("name");
1054
+ if (!nameNode) return null;
1055
+ const paramsNode = node.childForFieldName("parameters");
1056
+ const receiverNode = node.childForFieldName("receiver");
1057
+ const parts = [];
1058
+ let receiverVar = null;
1059
+ let receiverType = null;
1060
+ if (receiverNode) {
1061
+ parts.push(receiverNode.text);
1062
+ [receiverVar, receiverType] = parseReceiver(receiverNode);
1063
+ }
1064
+ if (paramsNode) {
1065
+ parts.push(paramsNode.text);
1066
+ }
1067
+ const signature = parts.length > 0 ? parts.join(" ") : null;
1068
+ const bodyNode = node.childForFieldName("body");
1069
+ const calls = bodyNode ? collectCalls(bodyNode) : [];
1070
+ return {
1071
+ name: nameNode.text,
1072
+ kind: "function",
1073
+ startLine: node.startPosition.row + 1,
1074
+ endLine: node.endPosition.row + 1,
1075
+ signature,
1076
+ children: [],
1077
+ calls,
1078
+ receiverVar,
1079
+ receiverType,
1080
+ paramTypes: null
1081
+ };
1082
+ }
1083
+ function parseReceiver(receiverNode) {
1084
+ for (const child of receiverNode.children) {
1085
+ if (child.type === "parameter_declaration") {
1086
+ let varName = null;
1087
+ let typeName = null;
1088
+ const nameChild = child.childForFieldName("name");
1089
+ if (nameChild) varName = nameChild.text;
1090
+ const typeChild = child.childForFieldName("type");
1091
+ if (typeChild) {
1092
+ if (typeChild.type === "pointer_type") {
1093
+ for (const sub of typeChild.children) {
1094
+ if (sub.type === "type_identifier") {
1095
+ typeName = sub.text;
1096
+ break;
1097
+ }
1098
+ }
1099
+ } else if (typeChild.type === "type_identifier") {
1100
+ typeName = typeChild.text;
1101
+ }
1102
+ }
1103
+ return [varName, typeName];
1104
+ }
1105
+ }
1106
+ return [null, null];
1107
+ }
1108
+ function collectCalls(node) {
1109
+ const calls = [];
1110
+ for (const child of node.children) {
1111
+ if (child.type === "call_expression") {
1112
+ const funcNode = child.childForFieldName("function");
1113
+ if (funcNode && funcNode.type === "identifier") {
1114
+ calls.push({ name: funcNode.text, receiver: null, kind: "bare" });
1115
+ } else if (funcNode && funcNode.type === "selector_expression") {
1116
+ const operand = funcNode.childForFieldName("operand");
1117
+ const field = funcNode.childForFieldName("field");
1118
+ if (operand && field) {
1119
+ calls.push({
1120
+ name: field.text,
1121
+ receiver: operand.text,
1122
+ kind: "attribute"
1123
+ });
1124
+ }
1125
+ }
1126
+ }
1127
+ calls.push(...collectCalls(child));
1128
+ }
1129
+ return calls;
1130
+ }
1131
+ const SUBTYPE_MAP = {
1132
+ // C/C++
1133
+ struct_specifier: "struct",
1134
+ enum_specifier: "enum",
1135
+ // C#
1136
+ struct_declaration: "struct",
1137
+ interface_declaration: "interface",
1138
+ enum_declaration: "enum",
1139
+ // Kotlin
1140
+ object_declaration: "object",
1141
+ // Ruby
1142
+ module: "module",
1143
+ // Rust
1144
+ struct_item: "struct",
1145
+ enum_item: "enum",
1146
+ trait_item: "trait",
1147
+ // Swift
1148
+ protocol_declaration: "protocol"
1149
+ };
1150
+ const LANGUAGE_CONFIGS = {
1151
+ c: {
1152
+ classTypes: /* @__PURE__ */ new Set(["struct_specifier", "enum_specifier"]),
1153
+ functionTypes: /* @__PURE__ */ new Set(["function_definition"]),
1154
+ containerTypes: /* @__PURE__ */ new Set()
1155
+ },
1156
+ cpp: {
1157
+ classTypes: /* @__PURE__ */ new Set([
1158
+ "class_specifier",
1159
+ "struct_specifier",
1160
+ "enum_specifier"
1161
+ ]),
1162
+ functionTypes: /* @__PURE__ */ new Set(["function_definition"]),
1163
+ containerTypes: /* @__PURE__ */ new Set(["class_specifier", "namespace_definition"])
1164
+ },
1165
+ csharp: {
1166
+ classTypes: /* @__PURE__ */ new Set([
1167
+ "class_declaration",
1168
+ "interface_declaration",
1169
+ "struct_declaration",
1170
+ "enum_declaration"
1171
+ ]),
1172
+ functionTypes: /* @__PURE__ */ new Set(["method_declaration", "local_function_statement"]),
1173
+ containerTypes: /* @__PURE__ */ new Set([
1174
+ "class_declaration",
1175
+ "interface_declaration",
1176
+ "namespace_declaration"
1177
+ ])
1178
+ },
1179
+ java: {
1180
+ classTypes: /* @__PURE__ */ new Set([
1181
+ "class_declaration",
1182
+ "interface_declaration",
1183
+ "enum_declaration"
1184
+ ]),
1185
+ functionTypes: /* @__PURE__ */ new Set(["method_declaration", "constructor_declaration"]),
1186
+ containerTypes: /* @__PURE__ */ new Set(["class_declaration", "interface_declaration"])
1187
+ },
1188
+ kotlin: {
1189
+ classTypes: /* @__PURE__ */ new Set(["class_declaration", "object_declaration"]),
1190
+ functionTypes: /* @__PURE__ */ new Set(["function_declaration"]),
1191
+ containerTypes: /* @__PURE__ */ new Set(["class_declaration", "object_declaration"])
1192
+ },
1193
+ ruby: {
1194
+ classTypes: /* @__PURE__ */ new Set(["class", "module"]),
1195
+ functionTypes: /* @__PURE__ */ new Set(["method", "singleton_method"]),
1196
+ containerTypes: /* @__PURE__ */ new Set(["class", "module"])
1197
+ },
1198
+ rust: {
1199
+ classTypes: /* @__PURE__ */ new Set(["struct_item", "enum_item", "trait_item"]),
1200
+ functionTypes: /* @__PURE__ */ new Set(["function_item", "function_signature_item"]),
1201
+ containerTypes: /* @__PURE__ */ new Set(["impl_item", "trait_item"])
1202
+ },
1203
+ swift: {
1204
+ classTypes: /* @__PURE__ */ new Set([
1205
+ "class_declaration",
1206
+ "protocol_declaration",
1207
+ "struct_declaration",
1208
+ "enum_declaration"
1209
+ ]),
1210
+ functionTypes: /* @__PURE__ */ new Set(["function_declaration", "init_declaration"]),
1211
+ containerTypes: /* @__PURE__ */ new Set([
1212
+ "class_declaration",
1213
+ "protocol_declaration",
1214
+ "struct_declaration"
1215
+ ])
1216
+ }
1217
+ };
1218
+ function extractPrecedingDoc(node) {
1219
+ const prev = node.previousNamedSibling;
1220
+ if (!prev) return void 0;
1221
+ if ((prev.type === "comment" || prev.type === "block_comment") && prev.text.startsWith("/**")) {
1222
+ const cleaned = prev.text.replace(/^\/\*\*\s*/, "").replace(/\s*\*\/$/, "").split("\n").map((line) => line.replace(/^\s*\*\s?/, "")).join("\n").trim();
1223
+ return cleaned || void 0;
1224
+ }
1225
+ if (prev.type === "comment" || prev.type === "line_comment") {
1226
+ const comments = [];
1227
+ let cur = prev;
1228
+ while (cur && (cur.type === "comment" || cur.type === "line_comment")) {
1229
+ comments.push(cur.text);
1230
+ cur = cur.previousNamedSibling;
1231
+ }
1232
+ const cleaned = comments.reverse().map((line) => line.replace(/^\/\/\/?\s?/, "")).join("\n").trim();
1233
+ return cleaned || void 0;
1234
+ }
1235
+ return void 0;
1236
+ }
1237
+ function extractGeneric(rootNode, language) {
1238
+ const config = LANGUAGE_CONFIGS[language];
1239
+ if (!config) {
1240
+ return { symbols: [], language, rootNode };
1241
+ }
1242
+ const symbols = walkTopLevel(rootNode, config);
1243
+ return { symbols, language, rootNode };
1244
+ }
1245
+ function walkTopLevel(node, config) {
1246
+ const symbols = [];
1247
+ for (const child of node.children) {
1248
+ const sym = extractNode(child, config);
1249
+ if (sym) {
1250
+ symbols.push(sym);
1251
+ } else if (config.containerTypes.has(child.type)) {
1252
+ const body = findBody(child);
1253
+ if (body) {
1254
+ symbols.push(...walkTopLevel(body, config));
1255
+ }
1256
+ } else {
1257
+ symbols.push(...walkTopLevel(child, config));
1258
+ }
1259
+ }
1260
+ return symbols;
1261
+ }
1262
+ function extractNode(node, config) {
1263
+ let sym = null;
1264
+ if (config.classTypes.has(node.type)) {
1265
+ sym = extractClass(node, config);
1266
+ } else if (config.functionTypes.has(node.type)) {
1267
+ sym = extractFunction(node);
1268
+ }
1269
+ if (sym) {
1270
+ sym.docs = extractPrecedingDoc(node);
1271
+ }
1272
+ return sym;
1273
+ }
1274
+ function extractClass(node, config) {
1275
+ const name = extractName(node);
1276
+ if (!name) return null;
1277
+ const body = findBody(node);
1278
+ const children = body ? extractMethods(body, config) : [];
1279
+ const subtype = SUBTYPE_MAP[node.type];
1280
+ const { superclasses, interfaces } = extractInheritance(node);
1281
+ return {
1282
+ name,
1283
+ kind: "class",
1284
+ startLine: node.startPosition.row + 1,
1285
+ endLine: node.endPosition.row + 1,
1286
+ signature: null,
1287
+ children,
1288
+ calls: [],
1289
+ receiverVar: null,
1290
+ receiverType: null,
1291
+ paramTypes: null,
1292
+ subtype,
1293
+ superclasses: superclasses.length > 0 ? superclasses : void 0,
1294
+ interfaces: interfaces.length > 0 ? interfaces : void 0
1295
+ };
1296
+ }
1297
+ function extractFunction(node) {
1298
+ const name = extractName(node);
1299
+ if (!name) return null;
1300
+ let paramsNode = node.childForFieldName("parameters");
1301
+ if (!paramsNode) {
1302
+ const decl = node.childForFieldName("declarator");
1303
+ if (decl?.type === "function_declarator") {
1304
+ paramsNode = decl.childForFieldName("parameters");
1305
+ }
1306
+ }
1307
+ const signature = paramsNode ? paramsNode.text : null;
1308
+ return {
1309
+ name,
1310
+ kind: "function",
1311
+ startLine: node.startPosition.row + 1,
1312
+ endLine: node.endPosition.row + 1,
1313
+ signature,
1314
+ children: [],
1315
+ calls: [],
1316
+ receiverVar: null,
1317
+ receiverType: null,
1318
+ paramTypes: null
1319
+ };
1320
+ }
1321
+ function extractInheritance(node) {
1322
+ const superclasses = [];
1323
+ const interfaces = [];
1324
+ const superclassField = node.childForFieldName("superclass");
1325
+ if (superclassField) {
1326
+ for (const child of superclassField.children) {
1327
+ if (child.type === "type_identifier" || child.type === "constant" || child.type === "scope_resolution") {
1328
+ superclasses.push(child.text);
1329
+ }
1330
+ }
1331
+ if (superclasses.length === 0) {
1332
+ const names = collectTypeIdentifiers(superclassField);
1333
+ superclasses.push(...names);
1334
+ }
1335
+ }
1336
+ const interfacesField = node.childForFieldName("interfaces");
1337
+ if (interfacesField) {
1338
+ interfaces.push(...collectTypeIdentifiers(interfacesField));
1339
+ }
1340
+ for (const child of node.children) {
1341
+ if (child.type === "base_class_clause" || child.type === "base_list" || child.type === "delegation_specifiers" || child.type === "type_inheritance_clause") {
1342
+ superclasses.push(...collectTypeIdentifiers(child));
1343
+ }
1344
+ }
1345
+ return { superclasses, interfaces };
1346
+ }
1347
+ function collectTypeIdentifiers(node) {
1348
+ const names = [];
1349
+ for (const child of node.children) {
1350
+ if (child.type === "type_identifier" || child.type === "identifier" || child.type === "simple_identifier") {
1351
+ names.push(child.text);
1352
+ } else if (child.namedChildCount > 0) {
1353
+ names.push(...collectTypeIdentifiers(child));
1354
+ }
1355
+ }
1356
+ return names;
1357
+ }
1358
+ function extractMethods(body, config) {
1359
+ const methods = [];
1360
+ for (const child of body.children) {
1361
+ if (config.functionTypes.has(child.type)) {
1362
+ const sym = extractFunction(child);
1363
+ if (sym) methods.push(sym);
1364
+ } else if (config.classTypes.has(child.type)) {
1365
+ const sym = extractClass(child, config);
1366
+ if (sym) methods.push(sym);
1367
+ }
1368
+ }
1369
+ return methods;
1370
+ }
1371
+ function extractName(node) {
1372
+ const nameNode = node.childForFieldName("name");
1373
+ if (nameNode) {
1374
+ return nameNode.text;
1375
+ }
1376
+ const declarator = node.childForFieldName("declarator");
1377
+ if (declarator) {
1378
+ if (declarator.type === "function_declarator") {
1379
+ const inner = declarator.childForFieldName("declarator");
1380
+ if (inner) return inner.text;
1381
+ }
1382
+ if (declarator.type === "identifier" || declarator.type === "field_identifier") {
1383
+ return declarator.text;
1384
+ }
1385
+ const qName = declarator.childForFieldName("name");
1386
+ if (qName) return qName.text;
1387
+ return declarator.text;
1388
+ }
1389
+ for (const child of node.children) {
1390
+ if (child.type === "identifier" || child.type === "type_identifier" || child.type === "simple_identifier" || child.type === "constant") {
1391
+ return child.text;
1392
+ }
1393
+ }
1394
+ return null;
1395
+ }
1396
+ function findBody(node) {
1397
+ const body = node.childForFieldName("body");
1398
+ if (body) return body;
1399
+ for (const child of node.children) {
1400
+ if (child.type === "field_declaration_list" || child.type === "declaration_list" || child.type === "class_body" || child.type === "enum_body" || child.type === "interface_body" || child.type === "block") {
1401
+ return child;
1402
+ }
1403
+ }
1404
+ return null;
1405
+ }
1406
+ let parsers = /* @__PURE__ */ new Map();
1407
+ function initParsers(map) {
1408
+ parsers = map;
1409
+ }
1410
+ function getExtractor(language) {
1411
+ switch (language) {
1412
+ case "python":
1413
+ return extractPython;
1414
+ case "typescript":
1415
+ case "javascript":
1416
+ return (rootNode) => extractTypeScript(rootNode, language);
1417
+ case "go":
1418
+ return extractGo;
1419
+ case "c":
1420
+ case "cpp":
1421
+ case "csharp":
1422
+ case "java":
1423
+ case "kotlin":
1424
+ case "ruby":
1425
+ case "rust":
1426
+ case "swift":
1427
+ return (rootNode) => extractGeneric(rootNode, language);
1428
+ default:
1429
+ return null;
1430
+ }
1431
+ }
1432
+ function getParserForLanguage(language, ext) {
1433
+ if (language === "typescript" && ext === ".tsx") {
1434
+ return parsers.get("tsx") ?? parsers.get("typescript");
1435
+ }
1436
+ if (language === "javascript" && ext === ".jsx") {
1437
+ return parsers.get("jsx") ?? parsers.get("javascript");
1438
+ }
1439
+ return parsers.get(language);
1440
+ }
1441
+ function parseFile(filePath, fileContent, repoId) {
1442
+ const ext = getExtension(filePath);
1443
+ const language = detectLanguage(ext);
1444
+ if (!language) {
1445
+ return {
1446
+ nodes: [],
1447
+ relationships: [],
1448
+ classesExtracted: 0,
1449
+ functionsExtracted: 0
1450
+ };
1451
+ }
1452
+ const parser = getParserForLanguage(language, ext);
1453
+ if (!parser) {
1454
+ return {
1455
+ nodes: [],
1456
+ relationships: [],
1457
+ classesExtracted: 0,
1458
+ functionsExtracted: 0
1459
+ };
1460
+ }
1461
+ const extractor = getExtractor(language);
1462
+ if (!extractor) {
1463
+ return {
1464
+ nodes: [],
1465
+ relationships: [],
1466
+ classesExtracted: 0,
1467
+ functionsExtracted: 0
1468
+ };
1469
+ }
1470
+ try {
1471
+ const tree = parser.parse(fileContent);
1472
+ if (!tree) {
1473
+ return {
1474
+ nodes: [],
1475
+ relationships: [],
1476
+ classesExtracted: 0,
1477
+ functionsExtracted: 0,
1478
+ error: `${filePath}: parse returned null`
1479
+ };
1480
+ }
1481
+ const result = extractor(tree.rootNode);
1482
+ const fileId = `${repoId}/${filePath}`;
1483
+ const nodes = [];
1484
+ const rels = [];
1485
+ const stats = { classesExtracted: 0, functionsExtracted: 0 };
1486
+ for (const sym of result.symbols) {
1487
+ convertSymbol(sym, fileId, nodes, rels, stats);
1488
+ }
1489
+ return { nodes, relationships: rels, ...stats };
1490
+ } catch (err) {
1491
+ return {
1492
+ nodes: [],
1493
+ relationships: [],
1494
+ classesExtracted: 0,
1495
+ functionsExtracted: 0,
1496
+ error: `${filePath}: ${err instanceof Error ? err.message : String(err)}`
1497
+ };
1498
+ }
1499
+ }
1500
+ function processSymbol(symbol, parentId, language, registries, callInfos, nodes, rels, emittedNodeIds) {
1501
+ const fileId = parentId.split("::")[0];
1502
+ const namePart = symbol.receiverType ? `${symbol.receiverType}.${symbol.name}` : symbol.name;
1503
+ const nodeId = `${parentId}::${namePart}`;
1504
+ if (emittedNodeIds.has(nodeId)) {
1505
+ return null;
1506
+ }
1507
+ emittedNodeIds.add(nodeId);
1508
+ if (symbol.kind === "class") {
1509
+ const props = {
1510
+ language,
1511
+ start_line: symbol.startLine,
1512
+ end_line: symbol.endLine
1513
+ };
1514
+ if (symbol.signature) props.signature = symbol.signature;
1515
+ if (symbol.superclasses) props.superclasses = symbol.superclasses;
1516
+ if (symbol.interfaces) props.interfaces = symbol.interfaces;
1517
+ if (symbol.subtype) props.subtype = symbol.subtype;
1518
+ if (symbol.docs) props.docs = symbol.docs;
1519
+ nodes.push({
1520
+ id: nodeId,
1521
+ type: "Class",
1522
+ name: symbol.name,
1523
+ properties: props
1524
+ });
1525
+ rels.push({
1526
+ id: `${nodeId}->DEFINED_IN->${parentId}`,
1527
+ type: "DEFINED_IN",
1528
+ source_id: nodeId,
1529
+ target_id: parentId
1530
+ });
1531
+ const symbolNode = {
1532
+ id: nodeId,
1533
+ name: symbol.name,
1534
+ kind: "class",
1535
+ fileId,
1536
+ parentId,
1537
+ receiverVar: null,
1538
+ receiverType: null,
1539
+ paramTypes: null,
1540
+ children: []
1541
+ };
1542
+ addToRegistry(registries.nameRegistry, symbol.name, symbolNode);
1543
+ registries.fileRegistry.get(fileId)?.set(symbol.name, symbolNode);
1544
+ addToRegistry(registries.classRegistry, symbol.name, symbolNode);
1545
+ for (const child of symbol.children) {
1546
+ const childSymbolNode = processSymbol(
1547
+ child,
1548
+ nodeId,
1549
+ language,
1550
+ registries,
1551
+ callInfos,
1552
+ nodes,
1553
+ rels,
1554
+ emittedNodeIds
1555
+ );
1556
+ if (childSymbolNode) symbolNode.children.push(childSymbolNode);
1557
+ }
1558
+ return symbolNode;
1559
+ } else {
1560
+ const props = {
1561
+ language,
1562
+ start_line: symbol.startLine,
1563
+ end_line: symbol.endLine
1564
+ };
1565
+ if (symbol.signature) props.signature = symbol.signature;
1566
+ if (symbol.docs) props.docs = symbol.docs;
1567
+ nodes.push({
1568
+ id: nodeId,
1569
+ type: "Function",
1570
+ name: symbol.name,
1571
+ properties: props
1572
+ });
1573
+ rels.push({
1574
+ id: `${nodeId}->DEFINED_IN->${parentId}`,
1575
+ type: "DEFINED_IN",
1576
+ source_id: nodeId,
1577
+ target_id: parentId
1578
+ });
1579
+ const symbolNode = {
1580
+ id: nodeId,
1581
+ name: symbol.name,
1582
+ kind: "function",
1583
+ fileId,
1584
+ parentId,
1585
+ receiverVar: symbol.receiverVar,
1586
+ receiverType: symbol.receiverType,
1587
+ paramTypes: symbol.paramTypes,
1588
+ children: []
1589
+ };
1590
+ addToRegistry(registries.nameRegistry, symbol.name, symbolNode);
1591
+ registries.fileRegistry.get(fileId)?.set(symbol.name, symbolNode);
1592
+ if (symbol.calls.length > 0) {
1593
+ callInfos.push({
1594
+ callerNode: symbolNode,
1595
+ calls: symbol.calls,
1596
+ fileId
1597
+ });
1598
+ }
1599
+ return symbolNode;
1600
+ }
1601
+ }
1602
+ function addToRegistry(registry, name, node) {
1603
+ const existing = registry.get(name);
1604
+ if (existing) {
1605
+ existing.push(node);
1606
+ } else {
1607
+ registry.set(name, [node]);
1608
+ }
1609
+ }
1610
+ function countSymbols(symbols) {
1611
+ let classes = 0;
1612
+ let functions = 0;
1613
+ for (const sym of symbols) {
1614
+ if (sym.kind === "class") {
1615
+ classes++;
1616
+ const childCounts = countSymbols(sym.children);
1617
+ classes += childCounts.classes;
1618
+ functions += childCounts.functions;
1619
+ } else {
1620
+ functions++;
1621
+ }
1622
+ }
1623
+ return { classes, functions };
1624
+ }
1625
+ function convertSymbol(sym, parentId, nodes, rels, stats) {
1626
+ const namePart = sym.receiverType ? `${sym.receiverType}.${sym.name}` : sym.name;
1627
+ const symId = `${parentId}::${namePart}`;
1628
+ const nodeType = sym.kind === "class" ? "Class" : "Function";
1629
+ const props = {
1630
+ start_line: sym.startLine,
1631
+ end_line: sym.endLine
1632
+ };
1633
+ if (sym.signature) props.signature = sym.signature;
1634
+ if (sym.docs) props.docs = sym.docs;
1635
+ if (sym.superclasses) props.superclasses = sym.superclasses;
1636
+ if (sym.interfaces) props.interfaces = sym.interfaces;
1637
+ if (sym.subtype) props.subtype = sym.subtype;
1638
+ nodes.push({
1639
+ id: symId,
1640
+ type: nodeType,
1641
+ name: sym.name,
1642
+ properties: props
1643
+ });
1644
+ rels.push({
1645
+ id: `${symId}->DEFINED_IN->${parentId}`,
1646
+ type: "DEFINED_IN",
1647
+ source_id: symId,
1648
+ target_id: parentId
1649
+ });
1650
+ if (sym.kind === "class") {
1651
+ stats.classesExtracted++;
1652
+ for (const child of sym.children) {
1653
+ if (child.kind === "function" && child.name === sym.name) continue;
1654
+ convertSymbol(child, symId, nodes, rels, stats);
1655
+ }
1656
+ } else {
1657
+ stats.functionsExtracted++;
1658
+ }
1659
+ }
1660
+ function analyzePythonImports(rootNode, filePath, knownFiles) {
1661
+ const internal = {};
1662
+ const external = {};
1663
+ const fileDir = parentDir(filePath);
1664
+ for (const child of rootNode.children) {
1665
+ if (child.type === "import_statement") {
1666
+ parsePythonImport(child, knownFiles, internal, external);
1667
+ } else if (child.type === "import_from_statement") {
1668
+ parsePythonFromImport(child, fileDir, knownFiles, internal, external);
1669
+ }
1670
+ }
1671
+ return { internal, external };
1672
+ }
1673
+ function parsePythonImport(node, knownFiles, internal, external) {
1674
+ for (const child of node.children) {
1675
+ if (child.type === "dotted_name") {
1676
+ const moduleName = child.text;
1677
+ const candidates = moduleToPaths(moduleName);
1678
+ let found = false;
1679
+ for (const candidate of candidates) {
1680
+ if (knownFiles.has(candidate)) {
1681
+ const parts = moduleName.split(".");
1682
+ internal[parts[parts.length - 1]] = candidate;
1683
+ found = true;
1684
+ break;
1685
+ }
1686
+ }
1687
+ if (!found) {
1688
+ const topLevel = moduleName.split(".")[0];
1689
+ const name = normalizePyName(topLevel);
1690
+ external[name] = packageId("pypi", name);
1691
+ }
1692
+ } else if (child.type === "aliased_import") {
1693
+ const nameNode = child.childForFieldName("name");
1694
+ const aliasNode = child.childForFieldName("alias");
1695
+ if (nameNode && aliasNode) {
1696
+ const moduleName = nameNode.text;
1697
+ const alias = aliasNode.text;
1698
+ const candidates = moduleToPaths(moduleName);
1699
+ let found = false;
1700
+ for (const candidate of candidates) {
1701
+ if (knownFiles.has(candidate)) {
1702
+ internal[alias] = candidate;
1703
+ found = true;
1704
+ break;
1705
+ }
1706
+ }
1707
+ if (!found) {
1708
+ const topLevel = moduleName.split(".")[0];
1709
+ const name = normalizePyName(topLevel);
1710
+ external[name] = packageId("pypi", name);
1711
+ }
1712
+ }
1713
+ }
1714
+ }
1715
+ }
1716
+ function parsePythonFromImport(node, fileDir, knownFiles, internal, external) {
1717
+ const moduleNameNode = node.childForFieldName("module_name");
1718
+ if (!moduleNameNode) return;
1719
+ let moduleText = moduleNameNode.text;
1720
+ let isRelative = false;
1721
+ let baseDir = fileDir;
1722
+ for (const child of node.children) {
1723
+ if (child.type === "relative_import") {
1724
+ isRelative = true;
1725
+ for (const sub of child.children) {
1726
+ if (sub.type === "dotted_name") {
1727
+ moduleText = sub.text;
1728
+ } else if (sub.type === "import_prefix") {
1729
+ const dots = sub.text;
1730
+ baseDir = fileDir;
1731
+ for (let i = 0; i < dots.length - 1; i++) {
1732
+ baseDir = parentDir(baseDir);
1733
+ }
1734
+ if (moduleText === moduleNameNode.text && moduleText.startsWith(".")) {
1735
+ moduleText = "";
1736
+ }
1737
+ }
1738
+ }
1739
+ break;
1740
+ }
1741
+ }
1742
+ let candidates;
1743
+ if (isRelative) {
1744
+ const basePath = moduleText ? baseDir ? `${baseDir}/${moduleText.replace(/\./g, "/")}` : moduleText.replace(/\./g, "/") : baseDir;
1745
+ candidates = [`${basePath}.py`, `${basePath}/__init__.py`];
1746
+ } else {
1747
+ candidates = moduleToPaths(moduleText);
1748
+ }
1749
+ let found = false;
1750
+ let resolvedPath = null;
1751
+ for (const candidate of candidates) {
1752
+ if (knownFiles.has(candidate)) {
1753
+ const alias = moduleText ? moduleText.split(".").pop() : "";
1754
+ if (alias) {
1755
+ internal[alias] = candidate;
1756
+ }
1757
+ resolvedPath = candidate;
1758
+ found = true;
1759
+ break;
1760
+ }
1761
+ }
1762
+ if (resolvedPath) {
1763
+ for (const child of node.children) {
1764
+ if (child.type === "dotted_name" && child !== node.childForFieldName("module_name")) {
1765
+ internal[child.text] = resolvedPath;
1766
+ } else if (child.type === "aliased_import") {
1767
+ const nameNode = child.childForFieldName("name");
1768
+ const aliasNode = child.childForFieldName("alias");
1769
+ if (aliasNode) {
1770
+ internal[aliasNode.text] = resolvedPath;
1771
+ } else if (nameNode) {
1772
+ internal[nameNode.text] = resolvedPath;
1773
+ }
1774
+ }
1775
+ }
1776
+ }
1777
+ if (!found && !isRelative && moduleText) {
1778
+ const topLevel = moduleText.split(".")[0];
1779
+ const name = normalizePyName(topLevel);
1780
+ external[name] = packageId("pypi", name);
1781
+ }
1782
+ }
1783
+ function buildDirIndex(knownFiles) {
1784
+ const index = /* @__PURE__ */ new Map();
1785
+ const baseDirs = /* @__PURE__ */ new Map();
1786
+ for (const filePath of knownFiles) {
1787
+ if (!filePath.endsWith(".go")) continue;
1788
+ const dir = parentDir(filePath);
1789
+ if (!dir) continue;
1790
+ if (!index.has(dir)) index.set(dir, filePath);
1791
+ const dirBase = dir.split("/").pop();
1792
+ let dirs = baseDirs.get(dirBase);
1793
+ if (!dirs) {
1794
+ dirs = /* @__PURE__ */ new Set();
1795
+ baseDirs.set(dirBase, dirs);
1796
+ }
1797
+ dirs.add(dir);
1798
+ }
1799
+ for (const [dirBase, dirs] of baseDirs) {
1800
+ if (dirs.size === 1) {
1801
+ const dir = dirs.values().next().value;
1802
+ index.set(dirBase, index.get(dir));
1803
+ }
1804
+ }
1805
+ return index;
1806
+ }
1807
+ let cachedDirIndex = null;
1808
+ let cachedDirIndexSource = null;
1809
+ function getDirIndex(knownFiles) {
1810
+ if (cachedDirIndex && cachedDirIndexSource === knownFiles) {
1811
+ return cachedDirIndex;
1812
+ }
1813
+ cachedDirIndex = buildDirIndex(knownFiles);
1814
+ cachedDirIndexSource = knownFiles;
1815
+ return cachedDirIndex;
1816
+ }
1817
+ function resetDirIndexCache() {
1818
+ cachedDirIndex = null;
1819
+ cachedDirIndexSource = null;
1820
+ }
1821
+ function analyzeGoImports(rootNode, knownFiles, modulePath) {
1822
+ const internal = {};
1823
+ const external = {};
1824
+ const dirIndex = getDirIndex(knownFiles);
1825
+ for (const child of rootNode.children) {
1826
+ if (child.type === "import_declaration") {
1827
+ parseGoImportDecl(child, dirIndex, internal, external, modulePath);
1828
+ }
1829
+ }
1830
+ return { internal, external };
1831
+ }
1832
+ function parseGoImportDecl(node, dirIndex, internal, external, modulePath) {
1833
+ for (const child of node.children) {
1834
+ if (child.type === "import_spec") {
1835
+ parseGoImportSpec(child, dirIndex, internal, external, modulePath);
1836
+ } else if (child.type === "import_spec_list") {
1837
+ for (const spec of child.children) {
1838
+ if (spec.type === "import_spec") {
1839
+ parseGoImportSpec(spec, dirIndex, internal, external, modulePath);
1840
+ }
1841
+ }
1842
+ }
1843
+ }
1844
+ }
1845
+ function parseGoImportSpec(node, dirIndex, internal, external, modulePath) {
1846
+ const pathNode = node.childForFieldName("path");
1847
+ const nameNode = node.childForFieldName("name");
1848
+ if (!pathNode) return;
1849
+ const importPath = pathNode.text.replace(/^["']|["']$/g, "");
1850
+ if (!importPath.includes(".")) return;
1851
+ let alias;
1852
+ if (nameNode) {
1853
+ alias = nameNode.text;
1854
+ if (alias === "_" || alias === ".") return;
1855
+ } else {
1856
+ alias = importPath.split("/").pop();
1857
+ }
1858
+ const fullMatch = dirIndex.get(importPath);
1859
+ if (fullMatch) {
1860
+ internal[alias] = fullMatch;
1861
+ return;
1862
+ }
1863
+ if (modulePath && importPath.startsWith(modulePath + "/")) {
1864
+ const repoRelDir = importPath.slice(modulePath.length + 1);
1865
+ const relMatch = dirIndex.get(repoRelDir);
1866
+ if (relMatch) {
1867
+ internal[alias] = relMatch;
1868
+ return;
1869
+ }
1870
+ }
1871
+ const pkgName = importPath.split("/").pop();
1872
+ const baseMatch = dirIndex.get(pkgName);
1873
+ if (baseMatch) {
1874
+ internal[alias] = baseMatch;
1875
+ return;
1876
+ }
1877
+ const isOwnModule = modulePath && importPath.startsWith(modulePath);
1878
+ if (!isOwnModule) {
1879
+ const goModuleName = goModuleRoot(importPath);
1880
+ external[goModuleName] = packageId("go", goModuleName);
1881
+ }
1882
+ }
1883
+ function goModuleRoot(importPath) {
1884
+ const parts = importPath.split("/");
1885
+ const host = parts[0];
1886
+ if (host === "github.com" || host === "gitlab.com" || host === "bitbucket.org" || host === "golang.org" || host === "google.golang.org" || host === "gopkg.in") {
1887
+ return parts.slice(0, 3).join("/");
1888
+ }
1889
+ return parts.length >= 3 ? parts.slice(0, 3).join("/") : importPath;
1890
+ }
1891
+ function analyzeTypeScriptImports(rootNode, filePath, knownFiles) {
1892
+ const internal = {};
1893
+ const external = {};
1894
+ const fileDir = parentDir(filePath);
1895
+ for (const child of rootNode.children) {
1896
+ if (child.type === "import_statement") {
1897
+ parseTsImport(child, fileDir, knownFiles, internal, external);
1898
+ } else if (child.type === "export_statement") {
1899
+ parseTsReexport(child, fileDir, knownFiles, internal, external);
1900
+ }
1901
+ }
1902
+ return { internal, external };
1903
+ }
1904
+ function parseTsImport(node, fileDir, knownFiles, internal, external) {
1905
+ const sourceNode = node.childForFieldName("source");
1906
+ if (!sourceNode) return;
1907
+ const sourceText = sourceNode.text.replace(/^["']|["']$/g, "");
1908
+ if (!sourceText.startsWith(".")) {
1909
+ const pkgName = npmPackageName(sourceText);
1910
+ external[pkgName] = packageId("npm", pkgName);
1911
+ return;
1912
+ }
1913
+ const resolved = resolveRelativePath(fileDir, sourceText);
1914
+ const extensions = [
1915
+ "",
1916
+ ".ts",
1917
+ ".tsx",
1918
+ ".js",
1919
+ ".jsx",
1920
+ "/index.ts",
1921
+ "/index.tsx",
1922
+ "/index.js"
1923
+ ];
1924
+ for (const ext of extensions) {
1925
+ const candidate = resolved + ext;
1926
+ if (knownFiles.has(candidate)) {
1927
+ const alias = sourceText.split("/").pop();
1928
+ internal[alias] = candidate;
1929
+ break;
1930
+ }
1931
+ }
1932
+ }
1933
+ function parseTsReexport(node, fileDir, knownFiles, internal, external) {
1934
+ const sourceNode = node.childForFieldName("source");
1935
+ if (!sourceNode) return;
1936
+ const sourceText = sourceNode.text.replace(/^["']|["']$/g, "");
1937
+ if (!sourceText.startsWith(".")) {
1938
+ const pkgName = npmPackageName(sourceText);
1939
+ external[pkgName] = packageId("npm", pkgName);
1940
+ return;
1941
+ }
1942
+ const resolved = resolveRelativePath(fileDir, sourceText);
1943
+ const extensions = [
1944
+ "",
1945
+ ".ts",
1946
+ ".tsx",
1947
+ ".js",
1948
+ ".jsx",
1949
+ "/index.ts",
1950
+ "/index.tsx",
1951
+ "/index.js"
1952
+ ];
1953
+ for (const ext of extensions) {
1954
+ const candidate = resolved + ext;
1955
+ if (knownFiles.has(candidate)) {
1956
+ const alias = sourceText.split("/").pop();
1957
+ internal[alias] = candidate;
1958
+ break;
1959
+ }
1960
+ }
1961
+ }
1962
+ function analyzeRustImports(rootNode, filePath, knownFiles) {
1963
+ const internal = {};
1964
+ const external = {};
1965
+ const fileDir = parentDir(filePath);
1966
+ for (const child of rootNode.children) {
1967
+ if (child.type === "mod_item") {
1968
+ const nameNode = child.childForFieldName("name");
1969
+ if (!nameNode) continue;
1970
+ const hasBody = child.children.some((c) => c.type === "declaration_list");
1971
+ if (hasBody) continue;
1972
+ const modName = nameNode.text;
1973
+ const candidates = [
1974
+ fileDir ? `${fileDir}/${modName}.rs` : `${modName}.rs`,
1975
+ fileDir ? `${fileDir}/${modName}/mod.rs` : `${modName}/mod.rs`
1976
+ ];
1977
+ let found = false;
1978
+ for (const candidate of candidates) {
1979
+ if (knownFiles.has(candidate)) {
1980
+ internal[modName] = candidate;
1981
+ found = true;
1982
+ break;
1983
+ }
1984
+ }
1985
+ if (!found) {
1986
+ external[modName] = packageId("crates", modName);
1987
+ }
1988
+ } else if (child.type === "use_declaration") {
1989
+ parseRustUseDecl(child, fileDir, knownFiles, internal, external);
1990
+ }
1991
+ }
1992
+ return { internal, external };
1993
+ }
1994
+ function parseRustUseDecl(node, fileDir, knownFiles, internal, external) {
1995
+ for (const child of node.children) {
1996
+ if (child.type === "scoped_identifier") {
1997
+ const parts = child.text.split("::");
1998
+ const root = parts[0];
1999
+ resolveRustRoot(root, fileDir, knownFiles, internal, external);
2000
+ } else if (child.type === "scoped_use_list") {
2001
+ for (const sub of child.children) {
2002
+ if (sub.type === "identifier" || sub.type === "scoped_identifier") {
2003
+ const root = sub.text.split("::")[0];
2004
+ resolveRustRoot(root, fileDir, knownFiles, internal, external);
2005
+ break;
2006
+ }
2007
+ }
2008
+ } else if (child.type === "identifier") {
2009
+ resolveRustRoot(child.text, fileDir, knownFiles, internal, external);
2010
+ }
2011
+ }
2012
+ }
2013
+ function resolveRustRoot(root, fileDir, knownFiles, internal, external) {
2014
+ if (root === "std" || root === "core" || root === "alloc" || root === "self" || root === "super" || root === "crate") {
2015
+ return;
2016
+ }
2017
+ if (!internal[root]) {
2018
+ const candidates = [
2019
+ fileDir ? `${fileDir}/${root}.rs` : `${root}.rs`,
2020
+ fileDir ? `${fileDir}/${root}/mod.rs` : `${root}/mod.rs`,
2021
+ `src/${root}.rs`,
2022
+ `src/${root}/mod.rs`
2023
+ ];
2024
+ for (const candidate of candidates) {
2025
+ if (knownFiles.has(candidate)) {
2026
+ internal[root] = candidate;
2027
+ return;
2028
+ }
2029
+ }
2030
+ external[root] = packageId("crates", root);
2031
+ }
2032
+ }
2033
+ function analyzeRubyImports(rootNode, filePath, knownFiles) {
2034
+ const internal = {};
2035
+ const external = {};
2036
+ const fileDir = parentDir(filePath);
2037
+ for (const child of rootNode.children) {
2038
+ if (child.type === "call") {
2039
+ const funcNode = child.children[0];
2040
+ if (!funcNode || funcNode.type !== "identifier") continue;
2041
+ const funcName = funcNode.text;
2042
+ if (funcName === "require_relative") {
2043
+ const argNode = child.childForFieldName("arguments") ?? child.children.find((c) => c.type === "argument_list");
2044
+ if (!argNode) continue;
2045
+ const strNode = argNode.children.find((c) => c.type === "string");
2046
+ if (!strNode) continue;
2047
+ const contentNode = strNode.children.find(
2048
+ (c) => c.type === "string_content"
2049
+ );
2050
+ if (!contentNode) continue;
2051
+ const requirePath = contentNode.text;
2052
+ const resolved = resolveRelativePath(fileDir, requirePath);
2053
+ const candidates = [`${resolved}.rb`, resolved, `${resolved}/index.rb`];
2054
+ for (const candidate of candidates) {
2055
+ if (knownFiles.has(candidate)) {
2056
+ const alias = requirePath.split("/").pop();
2057
+ internal[alias] = candidate;
2058
+ break;
2059
+ }
2060
+ }
2061
+ } else if (funcName === "require") {
2062
+ const argNode = child.childForFieldName("arguments") ?? child.children.find((c) => c.type === "argument_list");
2063
+ if (!argNode) continue;
2064
+ const strNode = argNode.children.find((c) => c.type === "string");
2065
+ if (!strNode) continue;
2066
+ const contentNode = strNode.children.find(
2067
+ (c) => c.type === "string_content"
2068
+ );
2069
+ if (!contentNode) continue;
2070
+ const gemName = contentNode.text;
2071
+ const candidates = [
2072
+ `${gemName}.rb`,
2073
+ `lib/${gemName}.rb`,
2074
+ `${gemName}/init.rb`
2075
+ ];
2076
+ let found = false;
2077
+ for (const candidate of candidates) {
2078
+ if (knownFiles.has(candidate)) {
2079
+ internal[gemName] = candidate;
2080
+ found = true;
2081
+ break;
2082
+ }
2083
+ }
2084
+ if (!found) {
2085
+ const name = gemName.split("/")[0];
2086
+ external[name] = packageId("rubygems", name);
2087
+ }
2088
+ }
2089
+ }
2090
+ }
2091
+ return { internal, external };
2092
+ }
2093
+ function parentDir(path) {
2094
+ const parts = path.split("/");
2095
+ return parts.length > 1 ? parts.slice(0, -1).join("/") : "";
2096
+ }
2097
+ function moduleToPaths(moduleName) {
2098
+ const path = moduleName.replace(/\./g, "/");
2099
+ return [`${path}.py`, `${path}/__init__.py`];
2100
+ }
2101
+ function resolveRelativePath(baseDir, relative) {
2102
+ const parts = relative.split("/");
2103
+ const baseParts = baseDir ? baseDir.split("/") : [];
2104
+ for (const part of parts) {
2105
+ if (part === ".") continue;
2106
+ else if (part === "..") {
2107
+ if (baseParts.length > 0) baseParts.pop();
2108
+ } else {
2109
+ baseParts.push(part);
2110
+ }
2111
+ }
2112
+ return baseParts.join("/");
2113
+ }
2114
+ function analyzeImports(rootNode, language, filePath, knownPaths, modulePath) {
2115
+ switch (language) {
2116
+ case "python":
2117
+ return analyzePythonImports(rootNode, filePath, knownPaths);
2118
+ case "go":
2119
+ return analyzeGoImports(rootNode, knownPaths, modulePath);
2120
+ case "typescript":
2121
+ case "javascript":
2122
+ return analyzeTypeScriptImports(rootNode, filePath, knownPaths);
2123
+ case "rust":
2124
+ return analyzeRustImports(rootNode, filePath, knownPaths);
2125
+ case "ruby":
2126
+ return analyzeRubyImports(rootNode, filePath, knownPaths);
2127
+ default:
2128
+ return { internal: {}, external: {} };
2129
+ }
2130
+ }
2131
+ function* execute$2(input, ctx) {
2132
+ const { parseableFiles, repoId, knownPaths, pathToFileId, goModulePath } = input;
2133
+ const total = parseableFiles.length;
2134
+ yield {
2135
+ kind: "stage_start",
2136
+ phase: "processing",
2137
+ message: `Processing ${total} files`
2138
+ };
2139
+ const registries = {
2140
+ nameRegistry: /* @__PURE__ */ new Map(),
2141
+ fileRegistry: /* @__PURE__ */ new Map(),
2142
+ classRegistry: /* @__PURE__ */ new Map(),
2143
+ importRegistry: /* @__PURE__ */ new Map()
2144
+ };
2145
+ const allCallInfo = [];
2146
+ const emittedNodeIds = /* @__PURE__ */ new Set();
2147
+ const packageNodes = new Map(input.packageNodes);
2148
+ const structureNodes = [
2149
+ input.repoNode,
2150
+ ...input.dirNodes.values(),
2151
+ ...input.fileNodes,
2152
+ ...input.packageNodes.values()
2153
+ ];
2154
+ let totalNodes = structureNodes.length;
2155
+ let totalRels = input.structureRels.length + input.dependencyRels.length;
2156
+ let filesProcessed = 0;
2157
+ let classesExtracted = 0;
2158
+ let functionsExtracted = 0;
2159
+ const errors = [];
2160
+ for (let i = 0; i < parseableFiles.length; i++) {
2161
+ if (ctx.cancelled) break;
2162
+ const file = parseableFiles[i];
2163
+ const ext = getExtension(file.path);
2164
+ const language = detectLanguage(ext);
2165
+ const fileId = `${repoId}/${file.path}`;
2166
+ if (!language) {
2167
+ filesProcessed++;
2168
+ continue;
2169
+ }
2170
+ const parser = getParserForLanguage(language, ext);
2171
+ const extractor = getExtractor(language);
2172
+ if (!parser || !extractor) {
2173
+ filesProcessed++;
2174
+ yield {
2175
+ kind: "stage_progress",
2176
+ phase: "processing",
2177
+ message: `Processing ${file.path}`,
2178
+ detail: { current: i + 1, total, fileName: file.path }
2179
+ };
2180
+ continue;
2181
+ }
2182
+ let extraction = null;
2183
+ const nodes = [];
2184
+ const rels = [];
2185
+ try {
2186
+ const tree = parser.parse(file.content);
2187
+ if (!tree) {
2188
+ errors.push(`${file.path}: parse returned null`);
2189
+ } else {
2190
+ extraction = extractor(tree.rootNode);
2191
+ registries.fileRegistry.set(fileId, /* @__PURE__ */ new Map());
2192
+ for (const sym of extraction.symbols) {
2193
+ processSymbol(
2194
+ sym,
2195
+ fileId,
2196
+ language,
2197
+ registries,
2198
+ allCallInfo,
2199
+ nodes,
2200
+ rels,
2201
+ emittedNodeIds
2202
+ );
2203
+ }
2204
+ const symCounts = countSymbols(extraction.symbols);
2205
+ classesExtracted += symCounts.classes;
2206
+ functionsExtracted += symCounts.functions;
2207
+ const rootNode = extraction.rootNode;
2208
+ if (rootNode) {
2209
+ const importResult = analyzeImports(
2210
+ rootNode,
2211
+ language,
2212
+ file.path,
2213
+ knownPaths,
2214
+ goModulePath
2215
+ );
2216
+ const fileImports = {};
2217
+ const seenTargetFiles = /* @__PURE__ */ new Set();
2218
+ for (const [alias, targetPath] of Object.entries(
2219
+ importResult.internal
2220
+ )) {
2221
+ const targetFileId = pathToFileId.get(targetPath);
2222
+ if (targetFileId) {
2223
+ fileImports[alias] = targetFileId;
2224
+ if (!seenTargetFiles.has(targetFileId)) {
2225
+ seenTargetFiles.add(targetFileId);
2226
+ rels.push({
2227
+ id: `${fileId}->IMPORTS->${targetFileId}`,
2228
+ type: "IMPORTS",
2229
+ source_id: fileId,
2230
+ target_id: targetFileId
2231
+ });
2232
+ }
2233
+ }
2234
+ }
2235
+ registries.importRegistry.set(fileId, fileImports);
2236
+ for (const [pkgName, pkgId] of Object.entries(
2237
+ importResult.external
2238
+ )) {
2239
+ if (!packageNodes.has(pkgId)) {
2240
+ const pkgNode = {
2241
+ id: pkgId,
2242
+ type: "Package",
2243
+ name: pkgName,
2244
+ properties: { registry: pkgId.split(":")[1] }
2245
+ };
2246
+ packageNodes.set(pkgId, pkgNode);
2247
+ nodes.push(pkgNode);
2248
+ }
2249
+ rels.push({
2250
+ id: `${fileId}->IMPORTS->${pkgId}`,
2251
+ type: "IMPORTS",
2252
+ source_id: fileId,
2253
+ target_id: pkgId
2254
+ });
2255
+ }
2256
+ }
2257
+ }
2258
+ } catch (err) {
2259
+ errors.push(
2260
+ `${file.path}: ${err instanceof Error ? err.message : String(err)}`
2261
+ );
2262
+ }
2263
+ totalNodes += nodes.length;
2264
+ totalRels += rels.length;
2265
+ filesProcessed++;
2266
+ yield {
2267
+ kind: "stage_progress",
2268
+ phase: "processing",
2269
+ message: `Processing ${file.path}`,
2270
+ detail: { current: i + 1, total, fileName: file.path },
2271
+ nodes: nodes.length > 0 ? nodes : void 0,
2272
+ relationships: rels.length > 0 ? rels : void 0
2273
+ };
2274
+ }
2275
+ yield {
2276
+ kind: "stage_stop",
2277
+ phase: "processing",
2278
+ message: `Processed ${filesProcessed} files`,
2279
+ errors: errors.length > 0 ? errors : void 0
2280
+ };
2281
+ return {
2282
+ scanResult: input,
2283
+ registries,
2284
+ allCallInfo,
2285
+ packageNodes,
2286
+ stats: {
2287
+ nodesCreated: totalNodes,
2288
+ relationshipsCreated: totalRels,
2289
+ filesProcessed,
2290
+ classesExtracted,
2291
+ functionsExtracted
2292
+ }
2293
+ };
2294
+ }
2295
+ function resolveCalls(callInfos, registries) {
2296
+ const results = [];
2297
+ for (const { callerNode, calls, fileId } of callInfos) {
2298
+ const seen = /* @__PURE__ */ new Set();
2299
+ for (const ref of calls) {
2300
+ const dedupKey = `${ref.receiver ?? ""}:${ref.name}`;
2301
+ if (seen.has(dedupKey)) continue;
2302
+ if (ref.name === callerNode.name && ref.receiver === null) continue;
2303
+ const resolved = resolveSingleCall(ref, callerNode, fileId, registries);
2304
+ if (!resolved) continue;
2305
+ seen.add(dedupKey);
2306
+ results.push({
2307
+ sourceId: callerNode.id,
2308
+ targetId: resolved.targetId,
2309
+ confidence: resolved.confidence
2310
+ });
2311
+ }
2312
+ }
2313
+ return results;
2314
+ }
2315
+ function resolveSingleCall(ref, callerNode, fileId, registries) {
2316
+ const { nameRegistry, fileRegistry, classRegistry, importRegistry } = registries;
2317
+ if (ref.kind === "attribute" && (ref.receiver === "self" || ref.receiver === "this")) {
2318
+ const classNode = findEnclosingClass(callerNode, classRegistry);
2319
+ if (classNode) {
2320
+ for (const child of classNode.children) {
2321
+ if (child.name === ref.name) {
2322
+ return { targetId: child.id, confidence: 1 };
2323
+ }
2324
+ }
2325
+ }
2326
+ return null;
2327
+ }
2328
+ if (ref.kind === "attribute") {
2329
+ if (callerNode.receiverVar && ref.receiver === callerNode.receiverVar && callerNode.receiverType) {
2330
+ const candidates = nameRegistry.get(ref.name) ?? [];
2331
+ for (const candidate of candidates) {
2332
+ if (candidate.receiverType === callerNode.receiverType) {
2333
+ return { targetId: candidate.id, confidence: 1 };
2334
+ }
2335
+ }
2336
+ }
2337
+ }
2338
+ if (ref.kind === "attribute" && ref.receiver && callerNode.paramTypes) {
2339
+ const typeName = callerNode.paramTypes[ref.receiver];
2340
+ if (typeName && classRegistry.has(typeName)) {
2341
+ const classCandidates = classRegistry.get(typeName);
2342
+ for (const cls of classCandidates) {
2343
+ for (const child of cls.children) {
2344
+ if (child.name === ref.name) {
2345
+ return { targetId: child.id, confidence: 0.7 };
2346
+ }
2347
+ }
2348
+ }
2349
+ }
2350
+ }
2351
+ if (ref.kind === "attribute" && ref.receiver && classRegistry.has(ref.receiver)) {
2352
+ const classCandidates = classRegistry.get(ref.receiver);
2353
+ const sorted = [...classCandidates].sort(
2354
+ (a, b) => (a.fileId === fileId ? 0 : 1) - (b.fileId === fileId ? 0 : 1)
2355
+ );
2356
+ for (const cls of sorted) {
2357
+ for (const child of cls.children) {
2358
+ if (child.name === ref.name) {
2359
+ const targetFileId = child.id.split("::")[0];
2360
+ const conf = targetFileId === fileId ? 1 : 0.9;
2361
+ return { targetId: child.id, confidence: conf };
2362
+ }
2363
+ }
2364
+ }
2365
+ const candidates = nameRegistry.get(ref.name) ?? [];
2366
+ for (const candidate of candidates) {
2367
+ if (candidate.receiverType === ref.receiver) {
2368
+ const targetFileId = candidate.id.split("::")[0];
2369
+ const conf = targetFileId === fileId ? 1 : 0.9;
2370
+ return { targetId: candidate.id, confidence: conf };
2371
+ }
2372
+ }
2373
+ return null;
2374
+ }
2375
+ if (ref.kind === "attribute" && ref.receiver) {
2376
+ const fileImports = importRegistry.get(fileId);
2377
+ if (fileImports) {
2378
+ const targetFileId = fileImports[ref.receiver];
2379
+ if (targetFileId) {
2380
+ const targetNames = fileRegistry.get(targetFileId);
2381
+ if (targetNames) {
2382
+ const target = targetNames.get(ref.name);
2383
+ if (target) {
2384
+ return { targetId: target.id, confidence: 0.9 };
2385
+ }
2386
+ }
2387
+ }
2388
+ }
2389
+ }
2390
+ if (ref.kind === "bare") {
2391
+ const fileImports = importRegistry.get(fileId);
2392
+ if (fileImports) {
2393
+ const targetFileId = fileImports[ref.name];
2394
+ if (targetFileId) {
2395
+ const targetNames = fileRegistry.get(targetFileId);
2396
+ if (targetNames) {
2397
+ const target = targetNames.get(ref.name);
2398
+ if (target) {
2399
+ if (target.kind === "class") {
2400
+ for (const child of target.children) {
2401
+ if (child.name === "__init__" || child.name === "constructor") {
2402
+ return { targetId: child.id, confidence: 0.9 };
2403
+ }
2404
+ }
2405
+ }
2406
+ return { targetId: target.id, confidence: 0.9 };
2407
+ }
2408
+ }
2409
+ }
2410
+ }
2411
+ }
2412
+ if (ref.kind === "bare" && classRegistry.has(ref.name)) {
2413
+ const classCandidates = classRegistry.get(ref.name);
2414
+ const sorted = [...classCandidates].sort(
2415
+ (a, b) => (a.fileId === fileId ? 0 : 1) - (b.fileId === fileId ? 0 : 1)
2416
+ );
2417
+ for (const cls2 of sorted) {
2418
+ for (const child of cls2.children) {
2419
+ if (child.name === "__init__" || child.name === "constructor") {
2420
+ const targetFileId2 = child.id.split("::")[0];
2421
+ const conf2 = targetFileId2 === fileId ? 1 : 0.8;
2422
+ return { targetId: child.id, confidence: conf2 };
2423
+ }
2424
+ }
2425
+ }
2426
+ const cls = sorted[0];
2427
+ const targetFileId = cls.id.split("::")[0];
2428
+ const conf = targetFileId === fileId ? 1 : 0.8;
2429
+ return { targetId: cls.id, confidence: conf };
2430
+ }
2431
+ if (ref.kind === "bare") {
2432
+ const fileNames = fileRegistry.get(fileId);
2433
+ if (fileNames) {
2434
+ const target = fileNames.get(ref.name);
2435
+ if (target) {
2436
+ return { targetId: target.id, confidence: 1 };
2437
+ }
2438
+ }
2439
+ }
2440
+ if (ref.kind === "bare") {
2441
+ const candidates = nameRegistry.get(ref.name) ?? [];
2442
+ const crossFile = candidates.filter((c) => c.id.split("::")[0] !== fileId);
2443
+ if (crossFile.length === 1) {
2444
+ return { targetId: crossFile[0].id, confidence: 0.8 };
2445
+ }
2446
+ }
2447
+ return null;
2448
+ }
2449
+ function findEnclosingClass(node, classRegistry) {
2450
+ const parts = node.id.split("::");
2451
+ for (let i = parts.length - 1; i >= 1; i--) {
2452
+ const potentialClassName = parts[i];
2453
+ const candidates = classRegistry.get(potentialClassName);
2454
+ if (candidates) {
2455
+ for (const cls of candidates) {
2456
+ if (node.id.startsWith(cls.id + "::")) {
2457
+ return cls;
2458
+ }
2459
+ }
2460
+ }
2461
+ }
2462
+ return null;
2463
+ }
2464
+ function resolvedCallsToRelationships(resolvedCalls) {
2465
+ return resolvedCalls.map((call) => ({
2466
+ id: `${call.sourceId}->CALLS->${call.targetId}`,
2467
+ type: "CALLS",
2468
+ source_id: call.sourceId,
2469
+ target_id: call.targetId,
2470
+ properties: { confidence: call.confidence }
2471
+ }));
2472
+ }
2473
+ function* execute$1(input) {
2474
+ const { registries, allCallInfo, stats } = input;
2475
+ yield {
2476
+ kind: "stage_start",
2477
+ phase: "resolving",
2478
+ message: `Resolving ${allCallInfo.length} call sites`
2479
+ };
2480
+ const resolvedCalls = resolveCalls(allCallInfo, registries);
2481
+ const callRels = resolvedCallsToRelationships(resolvedCalls);
2482
+ if (callRels.length > 0) {
2483
+ yield {
2484
+ kind: "stage_progress",
2485
+ phase: "resolving",
2486
+ message: `Resolved ${callRels.length} calls`,
2487
+ relationships: callRels
2488
+ };
2489
+ }
2490
+ yield {
2491
+ kind: "stage_stop",
2492
+ phase: "resolving",
2493
+ message: `Resolved ${callRels.length} calls`
2494
+ };
2495
+ return {
2496
+ nodesCreated: stats.nodesCreated,
2497
+ relationshipsCreated: stats.relationshipsCreated + callRels.length,
2498
+ filesProcessed: stats.filesProcessed,
2499
+ classesExtracted: stats.classesExtracted,
2500
+ functionsExtracted: stats.functionsExtracted
2501
+ };
2502
+ }
2503
+ function* execute(inner, store) {
2504
+ let nodesSaved = 0;
2505
+ let relsSaved = 0;
2506
+ for (const event of inner) {
2507
+ if (event.nodes) {
2508
+ for (const node of event.nodes) {
2509
+ store.saveNode(node);
2510
+ }
2511
+ nodesSaved += event.nodes.length;
2512
+ }
2513
+ if (event.relationships) {
2514
+ for (const rel of event.relationships) {
2515
+ store.saveRelationship(rel);
2516
+ }
2517
+ relsSaved += event.relationships.length;
2518
+ }
2519
+ yield event;
2520
+ }
2521
+ yield {
2522
+ kind: "stage_stop",
2523
+ phase: "submitting",
2524
+ message: `Saved ${nodesSaved} nodes and ${relsSaved} relationships`
2525
+ };
2526
+ }
2527
+ const VERB_MAP = {
2528
+ get: "Retrieves",
2529
+ fetch: "Retrieves",
2530
+ load: "Retrieves",
2531
+ find: "Retrieves",
2532
+ query: "Retrieves",
2533
+ read: "Reads",
2534
+ lookup: "Looks up",
2535
+ set: "Updates",
2536
+ update: "Updates",
2537
+ modify: "Updates",
2538
+ patch: "Updates",
2539
+ put: "Updates",
2540
+ validate: "Validates",
2541
+ verify: "Validates",
2542
+ check: "Validates",
2543
+ ensure: "Ensures",
2544
+ create: "Creates",
2545
+ make: "Creates",
2546
+ build: "Creates",
2547
+ generate: "Creates",
2548
+ new: "Creates",
2549
+ add: "Adds",
2550
+ insert: "Adds",
2551
+ append: "Adds",
2552
+ register: "Registers",
2553
+ delete: "Removes",
2554
+ remove: "Removes",
2555
+ destroy: "Removes",
2556
+ drop: "Removes",
2557
+ unset: "Removes",
2558
+ clear: "Clears",
2559
+ parse: "Parses",
2560
+ extract: "Extracts",
2561
+ decode: "Decodes",
2562
+ handle: "Handles",
2563
+ process: "Processes",
2564
+ run: "Runs",
2565
+ execute: "Executes",
2566
+ do: "Performs",
2567
+ perform: "Performs",
2568
+ convert: "Converts",
2569
+ transform: "Converts",
2570
+ to: "Converts to",
2571
+ format: "Formats",
2572
+ encode: "Encodes",
2573
+ serialize: "Serializes",
2574
+ marshal: "Serializes",
2575
+ deserialize: "Deserializes",
2576
+ unmarshal: "Deserializes",
2577
+ is: "Checks whether",
2578
+ has: "Checks whether",
2579
+ can: "Checks whether",
2580
+ should: "Checks whether",
2581
+ init: "Initializes",
2582
+ setup: "Initializes",
2583
+ configure: "Configures",
2584
+ start: "Starts",
2585
+ stop: "Stops",
2586
+ open: "Opens",
2587
+ close: "Closes",
2588
+ connect: "Connects",
2589
+ disconnect: "Disconnects",
2590
+ render: "Renders",
2591
+ display: "Renders",
2592
+ show: "Renders",
2593
+ draw: "Renders",
2594
+ paint: "Renders",
2595
+ hide: "Hides",
2596
+ send: "Sends",
2597
+ emit: "Emits",
2598
+ dispatch: "Dispatches",
2599
+ publish: "Publishes",
2600
+ broadcast: "Broadcasts",
2601
+ notify: "Notifies",
2602
+ receive: "Receives",
2603
+ listen: "Listens for",
2604
+ subscribe: "Subscribes to",
2605
+ on: "Handles",
2606
+ sort: "Sorts",
2607
+ filter: "Filters",
2608
+ map: "Maps",
2609
+ reduce: "Reduces",
2610
+ merge: "Merges",
2611
+ join: "Joins",
2612
+ split: "Splits",
2613
+ group: "Groups",
2614
+ flatten: "Flattens",
2615
+ test: "Tests",
2616
+ assert: "Tests",
2617
+ expect: "Tests",
2618
+ log: "Logs",
2619
+ print: "Logs",
2620
+ warn: "Logs warning for",
2621
+ error: "Logs error for",
2622
+ debug: "Logs debug info for",
2623
+ write: "Writes",
2624
+ save: "Saves",
2625
+ store: "Stores",
2626
+ cache: "Caches",
2627
+ flush: "Flushes",
2628
+ sync: "Synchronizes",
2629
+ reset: "Resets",
2630
+ refresh: "Refreshes",
2631
+ reload: "Reloads",
2632
+ retry: "Retries",
2633
+ wrap: "Wraps",
2634
+ unwrap: "Unwraps",
2635
+ apply: "Applies",
2636
+ resolve: "Resolves",
2637
+ reject: "Rejects",
2638
+ throw: "Throws",
2639
+ raise: "Raises",
2640
+ try: "Attempts",
2641
+ await: "Awaits",
2642
+ wait: "Waits for",
2643
+ schedule: "Schedules",
2644
+ defer: "Defers",
2645
+ cancel: "Cancels",
2646
+ abort: "Aborts",
2647
+ clone: "Clones",
2648
+ copy: "Copies",
2649
+ compare: "Compares",
2650
+ equals: "Checks equality of",
2651
+ match: "Matches",
2652
+ contains: "Checks whether contains",
2653
+ include: "Includes",
2654
+ exclude: "Excludes",
2655
+ enable: "Enables",
2656
+ disable: "Disables",
2657
+ toggle: "Toggles",
2658
+ mount: "Mounts",
2659
+ unmount: "Unmounts",
2660
+ use: "Uses",
2661
+ with: "Configures with",
2662
+ from: "Creates from",
2663
+ of: "Creates"
2664
+ };
2665
+ const CLASS_SUFFIX_MAP = {
2666
+ service: "Service",
2667
+ handler: "Handler",
2668
+ controller: "Controller",
2669
+ factory: "Factory",
2670
+ repository: "Repository",
2671
+ repo: "Repository",
2672
+ manager: "Manager",
2673
+ provider: "Provider",
2674
+ adapter: "Adapter",
2675
+ middleware: "Middleware",
2676
+ guard: "Guard",
2677
+ interceptor: "Interceptor",
2678
+ resolver: "Resolver",
2679
+ validator: "Validator",
2680
+ builder: "Builder",
2681
+ parser: "Parser",
2682
+ formatter: "Formatter",
2683
+ converter: "Converter",
2684
+ serializer: "Serializer",
2685
+ client: "Client",
2686
+ server: "Server",
2687
+ router: "Router",
2688
+ store: "Store",
2689
+ cache: "Cache",
2690
+ queue: "Queue",
2691
+ pool: "Pool",
2692
+ registry: "Registry",
2693
+ observer: "Observer",
2694
+ emitter: "Emitter",
2695
+ listener: "Listener",
2696
+ subscriber: "Subscriber",
2697
+ publisher: "Publisher",
2698
+ component: "Component",
2699
+ module: "Module",
2700
+ plugin: "Plugin",
2701
+ helper: "Helper",
2702
+ util: "Utility",
2703
+ utils: "Utility",
2704
+ error: "Error",
2705
+ exception: "Exception",
2706
+ model: "Model",
2707
+ entity: "Entity",
2708
+ dto: "DTO",
2709
+ config: "Configuration",
2710
+ options: "Options",
2711
+ context: "Context",
2712
+ state: "State",
2713
+ hook: "Hook"
2714
+ };
2715
+ const FILE_PATTERNS = [
2716
+ [/_test\.go$/, "Tests for"],
2717
+ [/_test\.py$/, "Tests for"],
2718
+ [/\.test\.[jt]sx?$/, "Tests for"],
2719
+ [/\.spec\.[jt]sx?$/, "Tests for"],
2720
+ [/^test_/, "Tests for"],
2721
+ [/^conftest\.py$/, "Pytest fixtures and configuration"],
2722
+ [/^setup\.[jt]s$/, "Setup configuration"],
2723
+ [/^index\.[jt]sx?$/, "Barrel exports for"],
2724
+ [/^main\.[a-z]+$/, "Application entry point"],
2725
+ [/^mod\.rs$/, "Module declarations"],
2726
+ [/^__init__\.py$/, "Package initialization for"],
2727
+ [/^constants?\.[a-z]+$/, "Constants and configuration values"],
2728
+ [/^types?\.[a-z]+$/, "Type definitions"],
2729
+ [/^utils?\.[a-z]+$/, "Utility functions"],
2730
+ [/^helpers?\.[a-z]+$/, "Helper functions"],
2731
+ [/^middleware\.[a-z]+$/, "Middleware definitions"],
2732
+ [/^routes?\.[a-z]+$/, "Route definitions"],
2733
+ [/^models?\.[a-z]+$/, "Data model definitions"],
2734
+ [/^schema\.[a-z]+$/, "Schema definitions"],
2735
+ [/^migrations?/, "Database migration"],
2736
+ [/^dockerfile/i, "Docker container configuration"],
2737
+ [/^makefile$/i, "Build automation rules"],
2738
+ [/^readme/i, "Project documentation"],
2739
+ [/^changelog/i, "Version change history"],
2740
+ [/^license/i, "License information"],
2741
+ [/\.config\.[a-z]+$/, "Configuration for"],
2742
+ [/rc\.[a-z]+$/, "Configuration for"]
2743
+ ];
2744
+ const DIR_PATTERNS = {
2745
+ api: "API layer",
2746
+ apis: "API layer",
2747
+ handlers: "Request handlers",
2748
+ handler: "Request handlers",
2749
+ controllers: "Request controllers",
2750
+ controller: "Request controllers",
2751
+ routes: "Route definitions",
2752
+ routing: "Route definitions",
2753
+ models: "Data models",
2754
+ model: "Data models",
2755
+ entities: "Data entities",
2756
+ schema: "Schema definitions",
2757
+ schemas: "Schema definitions",
2758
+ services: "Service layer",
2759
+ service: "Service layer",
2760
+ middleware: "Middleware",
2761
+ middlewares: "Middleware",
2762
+ utils: "Utility functions",
2763
+ util: "Utility functions",
2764
+ helpers: "Helper functions",
2765
+ helper: "Helper functions",
2766
+ lib: "Library modules",
2767
+ libs: "Library modules",
2768
+ pkg: "Package modules",
2769
+ internal: "Internal packages",
2770
+ cmd: "Command entry points",
2771
+ config: "Configuration",
2772
+ configs: "Configuration",
2773
+ tests: "Test suite",
2774
+ test: "Test suite",
2775
+ __tests__: "Test suite",
2776
+ spec: "Test specifications",
2777
+ specs: "Test specifications",
2778
+ fixtures: "Test fixtures",
2779
+ mocks: "Test mocks",
2780
+ components: "UI components",
2781
+ component: "UI components",
2782
+ pages: "Page components",
2783
+ views: "View components",
2784
+ layouts: "Layout components",
2785
+ hooks: "React hooks",
2786
+ store: "State management",
2787
+ stores: "State management",
2788
+ state: "State management",
2789
+ reducers: "State reducers",
2790
+ actions: "State actions",
2791
+ selectors: "State selectors",
2792
+ types: "Type definitions",
2793
+ interfaces: "Interface definitions",
2794
+ constants: "Constants",
2795
+ static: "Static assets",
2796
+ assets: "Static assets",
2797
+ public: "Public assets",
2798
+ styles: "Stylesheets",
2799
+ css: "Stylesheets",
2800
+ docs: "Documentation",
2801
+ doc: "Documentation",
2802
+ scripts: "Build and utility scripts",
2803
+ migrations: "Database migrations",
2804
+ seeds: "Database seed data",
2805
+ templates: "Templates",
2806
+ i18n: "Internationalization",
2807
+ locales: "Locale translations",
2808
+ proto: "Protocol buffer definitions",
2809
+ generated: "Generated code",
2810
+ gen: "Generated code",
2811
+ dist: "Build output",
2812
+ build: "Build output",
2813
+ vendor: "Vendored dependencies",
2814
+ node_modules: "NPM dependencies",
2815
+ bin: "Executable binaries",
2816
+ examples: "Usage examples",
2817
+ example: "Usage examples",
2818
+ plugins: "Plugin modules",
2819
+ extensions: "Extension modules",
2820
+ auth: "Authentication and authorization",
2821
+ security: "Security modules",
2822
+ crypto: "Cryptographic utilities",
2823
+ db: "Database layer",
2824
+ database: "Database layer",
2825
+ cache: "Caching layer",
2826
+ queue: "Message queue handlers",
2827
+ workers: "Background workers",
2828
+ jobs: "Background jobs",
2829
+ tasks: "Task definitions",
2830
+ events: "Event handlers",
2831
+ subscribers: "Event subscribers",
2832
+ publishers: "Event publishers",
2833
+ adapters: "Adapter implementations",
2834
+ providers: "Service providers",
2835
+ repositories: "Data repositories",
2836
+ repository: "Data repositories",
2837
+ clients: "External API clients",
2838
+ sdk: "SDK modules",
2839
+ common: "Shared common modules",
2840
+ shared: "Shared modules",
2841
+ core: "Core modules",
2842
+ base: "Base classes and interfaces",
2843
+ errors: "Error definitions",
2844
+ exceptions: "Exception definitions",
2845
+ validators: "Input validators",
2846
+ validation: "Validation logic",
2847
+ serializers: "Data serializers",
2848
+ parsers: "Data parsers",
2849
+ formatters: "Data formatters",
2850
+ converters: "Data converters",
2851
+ transformers: "Data transformers",
2852
+ mappers: "Data mappers",
2853
+ resolvers: "GraphQL resolvers",
2854
+ guards: "Route guards",
2855
+ interceptors: "Request interceptors",
2856
+ decorators: "Decorators",
2857
+ annotations: "Annotations",
2858
+ factories: "Factory functions",
2859
+ builders: "Builder patterns",
2860
+ observers: "Observer implementations",
2861
+ strategies: "Strategy pattern implementations",
2862
+ commands: "Command implementations",
2863
+ queries: "Query implementations",
2864
+ notifications: "Notification handlers",
2865
+ mailers: "Email sending",
2866
+ logging: "Logging configuration",
2867
+ monitoring: "Monitoring and metrics",
2868
+ metrics: "Application metrics",
2869
+ tracing: "Distributed tracing",
2870
+ indexer: "Indexing pipeline",
2871
+ graph: "Graph data structures",
2872
+ summarizer: "Summarization modules",
2873
+ embedder: "Embedding modules",
2874
+ extractors: "Data extractors"
2875
+ };
2876
+ const KEYWORD_PATTERNS = [
2877
+ {
2878
+ domain: "database",
2879
+ patterns: [
2880
+ /\bsql\b/i,
2881
+ /\bquery\b/i,
2882
+ /\bSELECT\b/,
2883
+ /\bINSERT\b/,
2884
+ /\bUPDATE\b.*\bSET\b/,
2885
+ /\bdb\./i,
2886
+ /\bcursor\b/i,
2887
+ /\bconnection\b/i,
2888
+ /\bprisma\b/i,
2889
+ /\bknex\b/i,
2890
+ /\bsequelize\b/i,
2891
+ /\bmongoose\b/i,
2892
+ /\bsqlx\b/i,
2893
+ /\borm\b/i,
2894
+ /\bmigration\b/i,
2895
+ /\bschema\b/i,
2896
+ /\btable\b/i,
2897
+ /\btransaction\b/i,
2898
+ /\bcolumn\b/i
2899
+ ]
2900
+ },
2901
+ {
2902
+ domain: "auth",
2903
+ patterns: [
2904
+ /\bauth\b/i,
2905
+ /\bjwt\b/i,
2906
+ /\btoken\b/i,
2907
+ /\bpassword\b/i,
2908
+ /\blogin\b/i,
2909
+ /\bsession\b/i,
2910
+ /\boauth\b/i,
2911
+ /\bbcrypt\b/i,
2912
+ /\bcredential\b/i,
2913
+ /\bpermission\b/i,
2914
+ /\brole\b/i,
2915
+ /\bacl\b/i,
2916
+ /\bsignin\b/i,
2917
+ /\bsignup\b/i
2918
+ ]
2919
+ },
2920
+ {
2921
+ domain: "http",
2922
+ patterns: [
2923
+ /\bhttp\b/i,
2924
+ /\brequest\b/i,
2925
+ /\bresponse\b/i,
2926
+ /\bfetch\s*\(/i,
2927
+ /\baxios\b/i,
2928
+ /\bhandler\b/i,
2929
+ /\bmiddleware\b/i,
2930
+ /\bcors\b/i,
2931
+ /\bendpoint\b/i,
2932
+ /\broute\b/i,
2933
+ /\bREST\b/i,
2934
+ /\bgraphql\b/i,
2935
+ /\bheader\b/i
2936
+ ]
2937
+ },
2938
+ {
2939
+ domain: "filesystem",
2940
+ patterns: [
2941
+ /\bfs\./i,
2942
+ /\breadFile\b/i,
2943
+ /\bwriteFile\b/i,
2944
+ /\bpath\./i,
2945
+ /\bstream\b/i,
2946
+ /\bbuffer\b/i,
2947
+ /\bmkdir\b/i,
2948
+ /\bunlink\b/i,
2949
+ /\bglob\b/i
2950
+ ]
2951
+ },
2952
+ {
2953
+ domain: "crypto",
2954
+ patterns: [
2955
+ /\bcrypto\b/i,
2956
+ /\bencrypt\b/i,
2957
+ /\bdecrypt\b/i,
2958
+ /\bhash\b/i,
2959
+ /\bsign\b/i,
2960
+ /\bverify\b/i,
2961
+ /\bcipher\b/i,
2962
+ /\bhmac\b/i
2963
+ ]
2964
+ },
2965
+ {
2966
+ domain: "cache",
2967
+ patterns: [
2968
+ /\bcache\b/i,
2969
+ /\bredis\b/i,
2970
+ /\bmemcached\b/i,
2971
+ /\bttl\b/i,
2972
+ /\binvalidate\b/i,
2973
+ /\bLRU\b/i
2974
+ ]
2975
+ },
2976
+ {
2977
+ domain: "queue",
2978
+ patterns: [
2979
+ /\bqueue\b/i,
2980
+ /\bworker\b/i,
2981
+ /\bjob\b/i,
2982
+ /\bpublish\b/i,
2983
+ /\bsubscribe\b/i,
2984
+ /\bkafka\b/i,
2985
+ /\brabbitmq\b/i,
2986
+ /\bamqp\b/i
2987
+ ]
2988
+ },
2989
+ {
2990
+ domain: "config",
2991
+ patterns: [
2992
+ /\bconfig\b/i,
2993
+ /\benv\b/i,
2994
+ /\bsettings\b/i,
2995
+ /\byaml\b/i,
2996
+ /\bdotenv\b/i,
2997
+ /\.env\b/i
2998
+ ]
2999
+ },
3000
+ {
3001
+ domain: "logging",
3002
+ patterns: [
3003
+ /\blogger\b/i,
3004
+ /\bwinston\b/i,
3005
+ /\bpino\b/i,
3006
+ /\blogrus\b/i,
3007
+ /\bslog\b/i,
3008
+ /\blog\./i
3009
+ ]
3010
+ },
3011
+ {
3012
+ domain: "testing",
3013
+ patterns: [
3014
+ /\btest\b/i,
3015
+ /\bassert\b/i,
3016
+ /\bexpect\b/i,
3017
+ /\bmock\b/i,
3018
+ /\bstub\b/i,
3019
+ /\bspy\b/i,
3020
+ /\bfixture\b/i,
3021
+ /\bjest\b/i,
3022
+ /\bpytest\b/i
3023
+ ]
3024
+ },
3025
+ {
3026
+ domain: "async",
3027
+ patterns: [
3028
+ /\basync\b/i,
3029
+ /\bawait\b/i,
3030
+ /\bPromise\b/,
3031
+ /\bgoroutine\b/i,
3032
+ /\bchannel\b/i,
3033
+ /\bconcurrent\b/i,
3034
+ /\bparallel\b/i,
3035
+ /\bmutex\b/i
3036
+ ]
3037
+ },
3038
+ {
3039
+ domain: "error",
3040
+ patterns: [
3041
+ /\btry\b/,
3042
+ /\bcatch\b/,
3043
+ /\bthrow\b/,
3044
+ /\bError\b/,
3045
+ /\bpanic\b/i,
3046
+ /\brecover\b/i,
3047
+ /\berrno\b/i
3048
+ ]
3049
+ },
3050
+ {
3051
+ domain: "validation",
3052
+ patterns: [
3053
+ /\bvalidate\b/i,
3054
+ /\bsanitize\b/i,
3055
+ /\bzod\b/i,
3056
+ /\byup\b/i,
3057
+ /\bjoi\b/i,
3058
+ /\bregexp\b/i,
3059
+ /\bregex\b/i
3060
+ ]
3061
+ },
3062
+ {
3063
+ domain: "websocket",
3064
+ patterns: [
3065
+ /\bwebsocket\b/i,
3066
+ /\bws\./i,
3067
+ /\bsocket\b/i,
3068
+ /\bWebSocket\b/,
3069
+ /\bemit\s*\(/i
3070
+ ]
3071
+ },
3072
+ {
3073
+ domain: "email",
3074
+ patterns: [/\bemail\b/i, /\bsmtp\b/i, /\bsendmail\b/i, /\bmailer\b/i]
3075
+ }
3076
+ ];
3077
+ function splitIdentifier(name) {
3078
+ const cleaned = name.replace(/^[_$]+/, "").replace(/[_$]+$/, "");
3079
+ if (!cleaned) return [name];
3080
+ const parts = cleaned.split(/[_-]+/).filter(Boolean);
3081
+ const words = [];
3082
+ for (const part of parts) {
3083
+ const subWords = part.replace(/([a-z])([A-Z])/g, "$1\0$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1\0$2").replace(/([a-zA-Z])(\d)/g, "$1\0$2").replace(/(\d)([a-zA-Z])/g, "$1\0$2").split("\0").filter(Boolean);
3084
+ words.push(...subWords);
3085
+ }
3086
+ return words.length > 0 ? words : [name];
3087
+ }
3088
+ function wordsToPhrase(words) {
3089
+ return words.map((w) => {
3090
+ if (w.length <= 4 && w === w.toUpperCase() && /^[A-Z]+$/.test(w))
3091
+ return w;
3092
+ return w.toLowerCase();
3093
+ }).join(" ");
3094
+ }
3095
+ function extractKeywords(source) {
3096
+ if (!source) return [];
3097
+ const found = [];
3098
+ for (const kp of KEYWORD_PATTERNS) {
3099
+ if (found.length >= 4) break;
3100
+ for (const pat of kp.patterns) {
3101
+ if (pat.test(source)) {
3102
+ found.push(kp.domain);
3103
+ break;
3104
+ }
3105
+ }
3106
+ }
3107
+ return found;
3108
+ }
3109
+ function formatKeywords(keywords) {
3110
+ return keywords.length > 0 ? ` [${keywords.join(", ")}]` : "";
3111
+ }
3112
+ const CONSTRUCTOR_NAMES = /* @__PURE__ */ new Set([
3113
+ "__init__",
3114
+ "constructor",
3115
+ "init",
3116
+ "initialize",
3117
+ "New"
3118
+ ]);
3119
+ function isNonDescriptive(name) {
3120
+ if (name.length <= 2) return true;
3121
+ const lower = name.toLowerCase();
3122
+ return [
3123
+ "foo",
3124
+ "bar",
3125
+ "baz",
3126
+ "tmp",
3127
+ "temp",
3128
+ "x",
3129
+ "y",
3130
+ "z",
3131
+ "fn",
3132
+ "cb",
3133
+ "f",
3134
+ "g"
3135
+ ].includes(lower);
3136
+ }
3137
+ function summarizeFunction(name, _signature, _language, _lineCount, receiverType, source) {
3138
+ if (CONSTRUCTOR_NAMES.has(name)) {
3139
+ const subject = receiverType || "instance";
3140
+ return `Initializes ${subject}`;
3141
+ }
3142
+ const lowerName = name.toLowerCase();
3143
+ if (lowerName.startsWith("test_") || lowerName.startsWith("test")) {
3144
+ const words2 = splitIdentifier(name);
3145
+ const testWords = words2[0].toLowerCase() === "test" ? words2.slice(1) : words2;
3146
+ if (testWords.length > 0) {
3147
+ return `Tests ${wordsToPhrase(testWords)}`;
3148
+ }
3149
+ return `Tests ${name}`;
3150
+ }
3151
+ if (isNonDescriptive(name)) {
3152
+ return `Function ${name}`;
3153
+ }
3154
+ const words = splitIdentifier(name);
3155
+ if (words.length === 0) return `Function ${name}`;
3156
+ const firstWord = words[0].toLowerCase();
3157
+ const restWords = words.slice(1);
3158
+ const verb = VERB_MAP[firstWord];
3159
+ if (verb) {
3160
+ const object = restWords.length > 0 ? ` ${wordsToPhrase(restWords)}` : "";
3161
+ let prefix = "";
3162
+ if (receiverType) {
3163
+ prefix = `${receiverType} method that `;
3164
+ const lowerVerb = verb.toLowerCase();
3165
+ const result3 = `${prefix}${lowerVerb}${object}`;
3166
+ const keywords3 = source ? extractKeywords(source) : [];
3167
+ return result3 + formatKeywords(keywords3);
3168
+ }
3169
+ const result2 = `${verb}${object}`;
3170
+ const keywords2 = source ? extractKeywords(source) : [];
3171
+ return result2 + formatKeywords(keywords2);
3172
+ }
3173
+ const phrase = wordsToPhrase(words);
3174
+ let result;
3175
+ if (receiverType) {
3176
+ result = `${receiverType} method for ${phrase}`;
3177
+ } else {
3178
+ result = phrase.charAt(0).toUpperCase() + phrase.slice(1);
3179
+ }
3180
+ const keywords = source ? extractKeywords(source) : [];
3181
+ return result + formatKeywords(keywords);
3182
+ }
3183
+ const CRUD_METHODS = /* @__PURE__ */ new Set([
3184
+ "create",
3185
+ "read",
3186
+ "get",
3187
+ "find",
3188
+ "update",
3189
+ "delete",
3190
+ "remove",
3191
+ "save",
3192
+ "list"
3193
+ ]);
3194
+ function summarizeClass(name, childNames, source) {
3195
+ const words = splitIdentifier(name);
3196
+ const readableName = wordsToPhrase(words);
3197
+ const capitalizedName = readableName.charAt(0).toUpperCase() + readableName.slice(1);
3198
+ const lastWord = words[words.length - 1].toLowerCase();
3199
+ const suffixLabel = CLASS_SUFFIX_MAP[lastWord];
3200
+ let hasCrud = false;
3201
+ if (childNames && childNames.length > 0) {
3202
+ const lowerChildren = childNames.map(
3203
+ (c) => splitIdentifier(c)[0].toLowerCase()
3204
+ );
3205
+ const crudCount = lowerChildren.filter((c) => CRUD_METHODS.has(c)).length;
3206
+ hasCrud = crudCount >= 3;
3207
+ }
3208
+ let summary = capitalizedName;
3209
+ if (hasCrud) {
3210
+ summary += " for CRUD operations";
3211
+ } else if (suffixLabel) {
3212
+ if (words.length > 1) ;
3213
+ }
3214
+ if (childNames && childNames.length > 0) {
3215
+ const methodList = childNames.slice(0, 5).join(", ");
3216
+ const extra = childNames.length > 5 ? ` and ${childNames.length - 5} more` : "";
3217
+ summary += ` with methods: ${methodList}${extra}`;
3218
+ }
3219
+ const keywords = source ? extractKeywords(source) : [];
3220
+ return summary + formatKeywords(keywords);
3221
+ }
3222
+ function summarizeFile(fileName, symbolNames, language, _source) {
3223
+ const lowerFile = fileName.toLowerCase();
3224
+ for (const [pattern, prefix] of FILE_PATTERNS) {
3225
+ if (pattern.test(lowerFile)) {
3226
+ if (prefix.endsWith("for")) {
3227
+ const baseName = fileName.replace(/_test\.\w+$/, "").replace(/\.test\.\w+$/, "").replace(/\.spec\.\w+$/, "").replace(/^test_/, "").replace(/\.\w+$/, "");
3228
+ const subject = wordsToPhrase(splitIdentifier(baseName));
3229
+ return `${prefix} ${subject}`;
3230
+ }
3231
+ if (prefix.endsWith("for") || prefix === "Barrel exports for") {
3232
+ if (symbolNames && symbolNames.length > 0) {
3233
+ const listing = symbolNames.slice(0, 3).join(", ");
3234
+ const extra = symbolNames.length > 3 ? ` and ${symbolNames.length - 3} more` : "";
3235
+ return `${prefix} ${listing}${extra}`;
3236
+ }
3237
+ }
3238
+ return prefix;
3239
+ }
3240
+ }
3241
+ if (symbolNames && symbolNames.length > 0) {
3242
+ const listing = symbolNames.slice(0, 3).join(", ");
3243
+ const extra = symbolNames.length > 3 ? ` and ${symbolNames.length - 3} more` : "";
3244
+ const langNote = language ? ` ${language}` : "";
3245
+ return `Defines${langNote} ${listing}${extra}`;
3246
+ }
3247
+ return `Source file ${fileName}`;
3248
+ }
3249
+ function summarizeDirectory(dirName, childNames) {
3250
+ const lowerDir = dirName.toLowerCase();
3251
+ const knownPurpose = DIR_PATTERNS[lowerDir];
3252
+ if (knownPurpose) {
3253
+ if (childNames.length > 0) {
3254
+ const listing = childNames.slice(0, 5).join(", ");
3255
+ const extra = childNames.length > 5 ? ` and ${childNames.length - 5} more` : "";
3256
+ return `${knownPurpose} containing ${listing}${extra}`;
3257
+ }
3258
+ return knownPurpose;
3259
+ }
3260
+ if (childNames.length > 0) {
3261
+ const listing = childNames.slice(0, 5).join(", ");
3262
+ const extra = childNames.length > 5 ? ` and ${childNames.length - 5} more` : "";
3263
+ return `Directory containing ${listing}${extra}`;
3264
+ }
3265
+ return `Directory ${dirName}`;
3266
+ }
3267
+ function summarizeFromMetadata(meta) {
3268
+ if (meta.docs) {
3269
+ const firstSentence = meta.docs.split(/\.\s|\n/)[0].trim();
3270
+ if (firstSentence) {
3271
+ return firstSentence.endsWith(".") ? firstSentence.slice(0, -1) : firstSentence;
3272
+ }
3273
+ }
3274
+ switch (meta.kind) {
3275
+ case "function":
3276
+ return summarizeFunction(
3277
+ meta.name,
3278
+ meta.signature,
3279
+ meta.language,
3280
+ meta.lineCount,
3281
+ meta.receiverType,
3282
+ meta.source
3283
+ );
3284
+ case "class":
3285
+ return summarizeClass(meta.name, meta.childNames, meta.source);
3286
+ case "file":
3287
+ return summarizeFile(
3288
+ meta.fileName || meta.name,
3289
+ meta.childNames,
3290
+ meta.language,
3291
+ meta.source
3292
+ );
3293
+ case "directory":
3294
+ return summarizeDirectory(meta.name, meta.childNames || []);
3295
+ default:
3296
+ return `${meta.kind} ${meta.name}`;
3297
+ }
3298
+ }
3299
+ class TemplateSummarizer {
3300
+ async init() {
3301
+ }
3302
+ async summarize(source, kind) {
3303
+ const firstLine = source.split("\n")[0] || "";
3304
+ const nameMatch = firstLine.match(
3305
+ /(?:function|def|func|class|const|let|var|type|interface)\s+(\w+)/
3306
+ );
3307
+ const name = nameMatch?.[1] || "unknown";
3308
+ return summarizeFromMetadata({ name, kind, source });
3309
+ }
3310
+ async summarizeBatch(items) {
3311
+ return Promise.all(
3312
+ items.map((item) => this.summarize(item.source, item.kind))
3313
+ );
3314
+ }
3315
+ async dispose() {
3316
+ }
3317
+ }
3318
+ const TYPE_TO_KIND = {
3319
+ Function: "function",
3320
+ Class: "class",
3321
+ File: "file",
3322
+ Directory: "directory"
3323
+ };
3324
+ function summarizeNode(node) {
3325
+ const kind = TYPE_TO_KIND[node.type];
3326
+ if (!kind) {
3327
+ return `${node.type} ${node.name}`;
3328
+ }
3329
+ const props = node.properties ?? {};
3330
+ return summarizeFromMetadata({
3331
+ name: node.name,
3332
+ kind,
3333
+ signature: props.signature,
3334
+ language: props.language,
3335
+ lineCount: typeof props.start_line === "number" && typeof props.end_line === "number" ? props.end_line - props.start_line + 1 : void 0,
3336
+ receiverType: props.receiver_type,
3337
+ fileName: kind === "file" ? props.path ?? node.name : void 0,
3338
+ childNames: props.childNames,
3339
+ docs: props.docs
3340
+ });
3341
+ }
3342
+ function* wrapWithSummaries(inner) {
3343
+ let summarized = 0;
3344
+ let total = 0;
3345
+ yield {
3346
+ kind: "stage_start",
3347
+ phase: "summarizing",
3348
+ message: "Summarizing nodes..."
3349
+ };
3350
+ for (const event of inner) {
3351
+ if (event.nodes) {
3352
+ for (const node of event.nodes) {
3353
+ total++;
3354
+ if (!node.properties?.summary) {
3355
+ const summary = summarizeNode(node);
3356
+ if (summary) {
3357
+ node.properties = { ...node.properties, summary };
3358
+ summarized++;
3359
+ }
3360
+ }
3361
+ }
3362
+ yield {
3363
+ kind: "stage_progress",
3364
+ phase: "summarizing",
3365
+ message: `Summarized ${summarized} of ${total} nodes`,
3366
+ detail: { current: summarized, total }
3367
+ };
3368
+ }
3369
+ yield event;
3370
+ }
3371
+ yield {
3372
+ kind: "stage_stop",
3373
+ phase: "summarizing",
3374
+ message: `Summarized ${summarized} nodes`
3375
+ };
3376
+ }
3377
+ function* corePipeline(input, ctx) {
3378
+ const scanResult = yield* execute$3(input, ctx);
3379
+ if (ctx.cancelled) return;
3380
+ const processingOutput = yield* execute$2(scanResult, ctx);
3381
+ if (ctx.cancelled) return;
3382
+ const finalResult = yield* execute$1(processingOutput);
3383
+ yield {
3384
+ kind: "done",
3385
+ phase: "resolving",
3386
+ message: "Pipeline complete",
3387
+ result: finalResult
3388
+ };
3389
+ }
3390
+ function* runPipeline(input, ctx, store) {
3391
+ const inner = wrapWithSummaries(corePipeline(input, ctx));
3392
+ if (store) {
3393
+ yield* execute(inner, store);
3394
+ } else {
3395
+ yield* inner;
3396
+ }
3397
+ }
3398
+ function collectPipeline(input, ctx, store) {
3399
+ const events = [];
3400
+ const nodes = [];
3401
+ const relationships = [];
3402
+ for (const event of runPipeline(input, ctx, store)) {
3403
+ events.push(event);
3404
+ if (event.nodes) nodes.push(...event.nodes);
3405
+ if (event.relationships) relationships.push(...event.relationships);
3406
+ }
3407
+ return { events, nodes, relationships };
3408
+ }
3409
+ class MemoryStore {
3410
+ nodes = /* @__PURE__ */ new Map();
3411
+ relationships = /* @__PURE__ */ new Map();
3412
+ saveNode(node) {
3413
+ const existing = this.nodes.get(node.id);
3414
+ if (existing) {
3415
+ existing.properties = {
3416
+ ...existing.properties,
3417
+ ...node.properties ?? {}
3418
+ };
3419
+ } else {
3420
+ this.nodes.set(node.id, node);
3421
+ }
3422
+ }
3423
+ saveRelationship(rel) {
3424
+ this.relationships.set(rel.id, rel);
3425
+ }
3426
+ }
3427
+ const DEFAULT_SUMMARIZER_CONFIG = {
3428
+ enabled: true,
3429
+ strategy: "template",
3430
+ model: "Xenova/flan-t5-small",
3431
+ maxInputLength: 480,
3432
+ minLines: 5
3433
+ };
3434
+ exports.DEFAULT_SUMMARIZER_CONFIG = DEFAULT_SUMMARIZER_CONFIG;
3435
+ exports.MemoryStore = MemoryStore;
3436
+ exports.TemplateSummarizer = TemplateSummarizer;
3437
+ exports.addToRegistry = addToRegistry;
3438
+ exports.analyzeGoImports = analyzeGoImports;
3439
+ exports.analyzeImports = analyzeImports;
3440
+ exports.analyzePythonImports = analyzePythonImports;
3441
+ exports.analyzeRubyImports = analyzeRubyImports;
3442
+ exports.analyzeRustImports = analyzeRustImports;
3443
+ exports.analyzeTypeScriptImports = analyzeTypeScriptImports;
3444
+ exports.collectPipeline = collectPipeline;
3445
+ exports.countSymbols = countSymbols;
3446
+ exports.detectLanguage = detectLanguage;
3447
+ exports.ensureDirChain = ensureDirChain;
3448
+ exports.extractGeneric = extractGeneric;
3449
+ exports.extractGo = extractGo;
3450
+ exports.extractKeywords = extractKeywords;
3451
+ exports.extractPython = extractPython;
3452
+ exports.extractTypeScript = extractTypeScript;
3453
+ exports.getExtension = getExtension;
3454
+ exports.getExtractor = getExtractor;
3455
+ exports.getParserForLanguage = getParserForLanguage;
3456
+ exports.initParsers = initParsers;
3457
+ exports.isManifestFile = isManifestFile;
3458
+ exports.normalizePyName = normalizePyName;
3459
+ exports.npmPackageName = npmPackageName;
3460
+ exports.packageId = packageId;
3461
+ exports.packageSourceUrl = packageSourceUrl;
3462
+ exports.parentDir = parentDir$1;
3463
+ exports.parseCargoToml = parseCargoToml;
3464
+ exports.parseFile = parseFile;
3465
+ exports.parseGoMod = parseGoMod;
3466
+ exports.parseManifest = parseManifest;
3467
+ exports.parsePackageJson = parsePackageJson;
3468
+ exports.parsePyprojectToml = parsePyprojectToml;
3469
+ exports.parseRequirementsTxt = parseRequirementsTxt;
3470
+ exports.processSymbol = processSymbol;
3471
+ exports.resetDirIndexCache = resetDirIndexCache;
3472
+ exports.resolveCalls = resolveCalls;
3473
+ exports.resolvedCallsToRelationships = resolvedCallsToRelationships;
3474
+ exports.runPipeline = runPipeline;
3475
+ exports.splitIdentifier = splitIdentifier;
3476
+ exports.summarizeClass = summarizeClass;
3477
+ exports.summarizeDirectory = summarizeDirectory;
3478
+ exports.summarizeFile = summarizeFile;
3479
+ exports.summarizeFromMetadata = summarizeFromMetadata;
3480
+ exports.summarizeFunction = summarizeFunction;
3481
+ //# sourceMappingURL=pipeline.cjs.map