@swarmvaultai/engine 0.1.14 → 0.1.16
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.
- package/README.md +8 -3
- package/dist/chunk-EEWB4WGH.js +1056 -0
- package/dist/index.d.ts +20 -6
- package/dist/index.js +808 -50
- package/dist/registry-YDXVCE4Q.js +12 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
uniqueBy,
|
|
22
22
|
writeFileIfChanged,
|
|
23
23
|
writeJsonFile
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-EEWB4WGH.js";
|
|
25
25
|
|
|
26
26
|
// src/agents.ts
|
|
27
27
|
import fs from "fs/promises";
|
|
@@ -30,10 +30,10 @@ var managedStart = "<!-- swarmvault:managed:start -->";
|
|
|
30
30
|
var managedEnd = "<!-- swarmvault:managed:end -->";
|
|
31
31
|
var legacyManagedStart = "<!-- vault:managed:start -->";
|
|
32
32
|
var legacyManagedEnd = "<!-- vault:managed:end -->";
|
|
33
|
-
function buildManagedBlock(
|
|
33
|
+
function buildManagedBlock(target) {
|
|
34
34
|
const body = [
|
|
35
35
|
managedStart,
|
|
36
|
-
|
|
36
|
+
"# SwarmVault Rules",
|
|
37
37
|
"",
|
|
38
38
|
"- Read `swarmvault.schema.md` before compile or query style work. It is the canonical schema path.",
|
|
39
39
|
"- Treat `raw/` as immutable source input.",
|
|
@@ -45,11 +45,27 @@ function buildManagedBlock(agent) {
|
|
|
45
45
|
managedEnd,
|
|
46
46
|
""
|
|
47
47
|
].join("\n");
|
|
48
|
-
if (
|
|
48
|
+
if (target === "cursor") {
|
|
49
49
|
return body;
|
|
50
50
|
}
|
|
51
51
|
return body;
|
|
52
52
|
}
|
|
53
|
+
function targetPathForAgent(rootDir, agent) {
|
|
54
|
+
switch (agent) {
|
|
55
|
+
case "codex":
|
|
56
|
+
case "goose":
|
|
57
|
+
case "pi":
|
|
58
|
+
return path.join(rootDir, "AGENTS.md");
|
|
59
|
+
case "claude":
|
|
60
|
+
return path.join(rootDir, "CLAUDE.md");
|
|
61
|
+
case "gemini":
|
|
62
|
+
return path.join(rootDir, "GEMINI.md");
|
|
63
|
+
case "cursor":
|
|
64
|
+
return path.join(rootDir, ".cursor", "rules", "swarmvault.mdc");
|
|
65
|
+
default:
|
|
66
|
+
throw new Error(`Unsupported agent ${String(agent)}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
53
69
|
async function upsertManagedBlock(filePath, block) {
|
|
54
70
|
const existing = await fileExists(filePath) ? await fs.readFile(filePath, "utf8") : "";
|
|
55
71
|
if (!existing) {
|
|
@@ -72,23 +88,25 @@ ${block}
|
|
|
72
88
|
}
|
|
73
89
|
async function installAgent(rootDir, agent) {
|
|
74
90
|
await initWorkspace(rootDir);
|
|
75
|
-
const
|
|
91
|
+
const target = targetPathForAgent(rootDir, agent);
|
|
76
92
|
switch (agent) {
|
|
77
|
-
case "codex":
|
|
78
|
-
|
|
79
|
-
|
|
93
|
+
case "codex":
|
|
94
|
+
case "goose":
|
|
95
|
+
case "pi":
|
|
96
|
+
await upsertManagedBlock(target, buildManagedBlock("agents"));
|
|
80
97
|
return target;
|
|
81
|
-
}
|
|
82
98
|
case "claude": {
|
|
83
|
-
|
|
84
|
-
|
|
99
|
+
await upsertManagedBlock(target, buildManagedBlock("claude"));
|
|
100
|
+
return target;
|
|
101
|
+
}
|
|
102
|
+
case "gemini": {
|
|
103
|
+
await upsertManagedBlock(target, buildManagedBlock("gemini"));
|
|
85
104
|
return target;
|
|
86
105
|
}
|
|
87
106
|
case "cursor": {
|
|
88
|
-
const rulesDir = path.
|
|
107
|
+
const rulesDir = path.dirname(target);
|
|
89
108
|
await ensureDir(rulesDir);
|
|
90
|
-
|
|
91
|
-
await fs.writeFile(target, `${block}
|
|
109
|
+
await fs.writeFile(target, `${buildManagedBlock("cursor")}
|
|
92
110
|
`, "utf8");
|
|
93
111
|
return target;
|
|
94
112
|
}
|
|
@@ -98,7 +116,14 @@ async function installAgent(rootDir, agent) {
|
|
|
98
116
|
}
|
|
99
117
|
async function installConfiguredAgents(rootDir) {
|
|
100
118
|
const { config } = await initWorkspace(rootDir);
|
|
101
|
-
|
|
119
|
+
const dedupedTargets = /* @__PURE__ */ new Map();
|
|
120
|
+
for (const agent of config.agents) {
|
|
121
|
+
const target = targetPathForAgent(rootDir, agent);
|
|
122
|
+
if (!dedupedTargets.has(target)) {
|
|
123
|
+
dedupedTargets.set(target, agent);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return Promise.all([...dedupedTargets.values()].map((agent) => installAgent(rootDir, agent)));
|
|
102
127
|
}
|
|
103
128
|
|
|
104
129
|
// src/ingest.ts
|
|
@@ -125,7 +150,7 @@ function scriptKindFor(language) {
|
|
|
125
150
|
}
|
|
126
151
|
}
|
|
127
152
|
function isRelativeSpecifier(specifier) {
|
|
128
|
-
return specifier.startsWith("./") || specifier.startsWith("../");
|
|
153
|
+
return specifier.startsWith("./") || specifier.startsWith("../") || specifier.startsWith(".");
|
|
129
154
|
}
|
|
130
155
|
function formatDiagnosticCategory(category) {
|
|
131
156
|
switch (category) {
|
|
@@ -177,6 +202,22 @@ function collectCallNames(root, availableNames, selfName) {
|
|
|
177
202
|
visit(root);
|
|
178
203
|
return uniqueBy(names, (name) => name);
|
|
179
204
|
}
|
|
205
|
+
function collectCallNamesFromText(text, availableNames, selfName) {
|
|
206
|
+
if (!text) {
|
|
207
|
+
return [];
|
|
208
|
+
}
|
|
209
|
+
const names = [];
|
|
210
|
+
for (const name of availableNames) {
|
|
211
|
+
if (name === selfName) {
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
const pattern = new RegExp(`\\b${escapeRegExp(name)}\\s*\\(`, "g");
|
|
215
|
+
if (pattern.test(text)) {
|
|
216
|
+
names.push(name);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return uniqueBy(names, (name) => name);
|
|
220
|
+
}
|
|
180
221
|
function heritageNames(clauses, token) {
|
|
181
222
|
return uniqueBy(
|
|
182
223
|
(clauses ?? []).filter((clause) => clause.token === token).flatMap(
|
|
@@ -277,7 +318,689 @@ function codeQuestions(manifest, code) {
|
|
|
277
318
|
function resolveVariableKind(statement) {
|
|
278
319
|
return statement.declarationList.flags & ts.NodeFlags.Const ? "variable" : "variable";
|
|
279
320
|
}
|
|
280
|
-
function
|
|
321
|
+
function splitLines(content) {
|
|
322
|
+
return content.split(/\r?\n/);
|
|
323
|
+
}
|
|
324
|
+
function leadingIndent(line) {
|
|
325
|
+
const match = line.match(/^[ \t]*/);
|
|
326
|
+
return match ? match[0].replace(/\t/g, " ").length : 0;
|
|
327
|
+
}
|
|
328
|
+
function normalizeSymbolReference(value) {
|
|
329
|
+
const withoutGenerics = value.replace(/<[^>]*>/g, "");
|
|
330
|
+
const withoutDecorators = withoutGenerics.replace(/['"&*()[\]{}]/g, " ");
|
|
331
|
+
const trimmed = withoutDecorators.trim();
|
|
332
|
+
const lastSegment = trimmed.split(/::|\./).filter(Boolean).at(-1) ?? trimmed;
|
|
333
|
+
return lastSegment.replace(/[,:;]+$/g, "").trim();
|
|
334
|
+
}
|
|
335
|
+
function singleLineSignature(line) {
|
|
336
|
+
return truncate(
|
|
337
|
+
normalizeWhitespace(
|
|
338
|
+
line.replace(/\{\s*$/, "").replace(/:\s*$/, ":").trim()
|
|
339
|
+
),
|
|
340
|
+
180
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
function buildDiagnostic(code, message, line, column = 1, category = "warning") {
|
|
344
|
+
return { code, category, message, line, column };
|
|
345
|
+
}
|
|
346
|
+
function finalizeCodeAnalysis(manifest, language, imports, draftSymbols, exportLabels, diagnostics) {
|
|
347
|
+
const topLevelNames = new Set(draftSymbols.map((symbol) => symbol.name));
|
|
348
|
+
for (const symbol of draftSymbols) {
|
|
349
|
+
if (symbol.callNames.length === 0 && symbol.bodyText) {
|
|
350
|
+
symbol.callNames = collectCallNamesFromText(symbol.bodyText, topLevelNames, symbol.name);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
const seenSymbolIds = /* @__PURE__ */ new Map();
|
|
354
|
+
const symbols = draftSymbols.map((symbol) => ({
|
|
355
|
+
id: makeSymbolId(manifest.sourceId, symbol.name, seenSymbolIds),
|
|
356
|
+
name: symbol.name,
|
|
357
|
+
kind: symbol.kind,
|
|
358
|
+
signature: symbol.signature,
|
|
359
|
+
exported: symbol.exported,
|
|
360
|
+
calls: uniqueBy(symbol.callNames, (name) => name),
|
|
361
|
+
extends: uniqueBy(symbol.extendsNames.map((name) => normalizeSymbolReference(name)).filter(Boolean), (name) => name),
|
|
362
|
+
implements: uniqueBy(symbol.implementsNames.map((name) => normalizeSymbolReference(name)).filter(Boolean), (name) => name)
|
|
363
|
+
}));
|
|
364
|
+
return {
|
|
365
|
+
moduleId: `module:${manifest.sourceId}`,
|
|
366
|
+
language,
|
|
367
|
+
imports,
|
|
368
|
+
dependencies: uniqueBy(
|
|
369
|
+
imports.filter((item) => item.isExternal).map((item) => item.specifier),
|
|
370
|
+
(specifier) => specifier
|
|
371
|
+
),
|
|
372
|
+
symbols,
|
|
373
|
+
exports: uniqueBy([...symbols.filter((symbol) => symbol.exported).map((symbol) => symbol.name), ...exportLabels], (label) => label),
|
|
374
|
+
diagnostics
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
function collectPythonBlock(lines, startIndex) {
|
|
378
|
+
const startIndent = leadingIndent(lines[startIndex] ?? "");
|
|
379
|
+
const parts = [];
|
|
380
|
+
for (let index = startIndex + 1; index < lines.length; index += 1) {
|
|
381
|
+
const line = lines[index] ?? "";
|
|
382
|
+
const trimmed = line.trim();
|
|
383
|
+
if (!trimmed) {
|
|
384
|
+
parts.push(line);
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
if (leadingIndent(line) <= startIndent) {
|
|
388
|
+
break;
|
|
389
|
+
}
|
|
390
|
+
parts.push(line);
|
|
391
|
+
}
|
|
392
|
+
return parts.join("\n");
|
|
393
|
+
}
|
|
394
|
+
function parsePythonImportList(value) {
|
|
395
|
+
return value.split(",").map((item) => item.trim()).filter(Boolean).map((item) => {
|
|
396
|
+
const [rawSpecifier, rawAlias] = item.split(/\s+as\s+/i);
|
|
397
|
+
return {
|
|
398
|
+
specifier: rawSpecifier.trim(),
|
|
399
|
+
alias: rawAlias?.trim()
|
|
400
|
+
};
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
function parsePythonAllExportList(value) {
|
|
404
|
+
const match = value.match(/\[(.*)\]/);
|
|
405
|
+
if (!match) {
|
|
406
|
+
return [];
|
|
407
|
+
}
|
|
408
|
+
return uniqueBy(
|
|
409
|
+
match[1].split(",").map((item) => item.trim().replace(/^['"]|['"]$/g, "")).filter(Boolean),
|
|
410
|
+
(item) => item
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
function analyzePythonCode(manifest, content) {
|
|
414
|
+
const lines = splitLines(content);
|
|
415
|
+
const imports = [];
|
|
416
|
+
const draftSymbols = [];
|
|
417
|
+
const exportLabels = [];
|
|
418
|
+
const diagnostics = [];
|
|
419
|
+
let explicitExports = [];
|
|
420
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
421
|
+
const rawLine = lines[index] ?? "";
|
|
422
|
+
const trimmed = rawLine.trim();
|
|
423
|
+
if (!trimmed || trimmed.startsWith("#") || leadingIndent(rawLine) > 0) {
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
const importMatch = trimmed.match(/^import\s+(.+)$/);
|
|
427
|
+
if (importMatch) {
|
|
428
|
+
for (const item of parsePythonImportList(importMatch[1])) {
|
|
429
|
+
imports.push({
|
|
430
|
+
specifier: item.specifier,
|
|
431
|
+
importedSymbols: [],
|
|
432
|
+
namespaceImport: item.alias,
|
|
433
|
+
isExternal: !isRelativeSpecifier(item.specifier),
|
|
434
|
+
reExport: false
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
continue;
|
|
438
|
+
}
|
|
439
|
+
const fromImportMatch = trimmed.match(/^from\s+([.\w]+)\s+import\s+(.+)$/);
|
|
440
|
+
if (fromImportMatch) {
|
|
441
|
+
const importedSymbols = fromImportMatch[2].split(",").map((item) => item.trim()).filter(Boolean);
|
|
442
|
+
imports.push({
|
|
443
|
+
specifier: fromImportMatch[1],
|
|
444
|
+
importedSymbols,
|
|
445
|
+
isExternal: !isRelativeSpecifier(fromImportMatch[1]),
|
|
446
|
+
reExport: false
|
|
447
|
+
});
|
|
448
|
+
continue;
|
|
449
|
+
}
|
|
450
|
+
const classMatch = trimmed.match(/^class\s+([A-Za-z_]\w*)\s*(?:\(([^)]*)\))?\s*:/);
|
|
451
|
+
if (classMatch) {
|
|
452
|
+
const baseNames = classMatch[2] ? classMatch[2].split(",").map((item) => normalizeSymbolReference(item)).filter(Boolean) : [];
|
|
453
|
+
draftSymbols.push({
|
|
454
|
+
name: classMatch[1],
|
|
455
|
+
kind: "class",
|
|
456
|
+
signature: singleLineSignature(trimmed),
|
|
457
|
+
exported: !classMatch[1].startsWith("_"),
|
|
458
|
+
callNames: [],
|
|
459
|
+
extendsNames: baseNames,
|
|
460
|
+
implementsNames: [],
|
|
461
|
+
bodyText: collectPythonBlock(lines, index)
|
|
462
|
+
});
|
|
463
|
+
continue;
|
|
464
|
+
}
|
|
465
|
+
if (trimmed.startsWith("class ")) {
|
|
466
|
+
diagnostics.push(buildDiagnostic(1001, "Python class declaration is missing a trailing colon.", index + 1));
|
|
467
|
+
continue;
|
|
468
|
+
}
|
|
469
|
+
const functionMatch = trimmed.match(/^(?:async\s+)?def\s+([A-Za-z_]\w*)\s*\(/);
|
|
470
|
+
if (functionMatch) {
|
|
471
|
+
draftSymbols.push({
|
|
472
|
+
name: functionMatch[1],
|
|
473
|
+
kind: "function",
|
|
474
|
+
signature: singleLineSignature(trimmed),
|
|
475
|
+
exported: !functionMatch[1].startsWith("_"),
|
|
476
|
+
callNames: [],
|
|
477
|
+
extendsNames: [],
|
|
478
|
+
implementsNames: [],
|
|
479
|
+
bodyText: collectPythonBlock(lines, index)
|
|
480
|
+
});
|
|
481
|
+
continue;
|
|
482
|
+
}
|
|
483
|
+
if (trimmed.startsWith("def ") || trimmed.startsWith("async def ")) {
|
|
484
|
+
diagnostics.push(buildDiagnostic(1002, "Python function declaration is missing a trailing colon.", index + 1));
|
|
485
|
+
continue;
|
|
486
|
+
}
|
|
487
|
+
const allMatch = trimmed.match(/^__all__\s*=\s*\[(.*)\]\s*$/);
|
|
488
|
+
if (allMatch) {
|
|
489
|
+
explicitExports = parsePythonAllExportList(trimmed);
|
|
490
|
+
continue;
|
|
491
|
+
}
|
|
492
|
+
const variableMatch = trimmed.match(/^([A-Za-z_]\w*)\s*(?::[^=]+)?=\s*(.+)$/);
|
|
493
|
+
if (variableMatch && !["True", "False", "None"].includes(variableMatch[1])) {
|
|
494
|
+
draftSymbols.push({
|
|
495
|
+
name: variableMatch[1],
|
|
496
|
+
kind: "variable",
|
|
497
|
+
signature: singleLineSignature(trimmed),
|
|
498
|
+
exported: !variableMatch[1].startsWith("_"),
|
|
499
|
+
callNames: [],
|
|
500
|
+
extendsNames: [],
|
|
501
|
+
implementsNames: [],
|
|
502
|
+
bodyText: variableMatch[2]
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
if (explicitExports.length > 0) {
|
|
507
|
+
const explicitExportSet = new Set(explicitExports);
|
|
508
|
+
for (const symbol of draftSymbols) {
|
|
509
|
+
symbol.exported = explicitExportSet.has(symbol.name);
|
|
510
|
+
}
|
|
511
|
+
exportLabels.push(...explicitExports);
|
|
512
|
+
}
|
|
513
|
+
return finalizeCodeAnalysis(manifest, "python", imports, draftSymbols, exportLabels, diagnostics);
|
|
514
|
+
}
|
|
515
|
+
function collectBracedBlock(lines, startIndex) {
|
|
516
|
+
const parts = [];
|
|
517
|
+
let depth = 0;
|
|
518
|
+
let started = false;
|
|
519
|
+
for (let index = startIndex; index < lines.length; index += 1) {
|
|
520
|
+
const line = lines[index] ?? "";
|
|
521
|
+
parts.push(line);
|
|
522
|
+
for (const character of line) {
|
|
523
|
+
if (character === "{") {
|
|
524
|
+
depth += 1;
|
|
525
|
+
started = true;
|
|
526
|
+
} else if (character === "}") {
|
|
527
|
+
depth -= 1;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
if (started && depth <= 0) {
|
|
531
|
+
return { text: parts.join("\n"), endIndex: index };
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
return {
|
|
535
|
+
text: parts.join("\n"),
|
|
536
|
+
endIndex: started ? lines.length - 1 : startIndex
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
function exportedByCapitalization(name) {
|
|
540
|
+
return /^[A-Z]/.test(name);
|
|
541
|
+
}
|
|
542
|
+
function parseGoImportLine(line) {
|
|
543
|
+
const match = line.trim().match(/^(?:([._A-Za-z]\w*)\s+)?"([^"]+)"$/);
|
|
544
|
+
if (!match) {
|
|
545
|
+
return void 0;
|
|
546
|
+
}
|
|
547
|
+
return {
|
|
548
|
+
specifier: match[2],
|
|
549
|
+
importedSymbols: [],
|
|
550
|
+
namespaceImport: match[1] && ![".", "_"].includes(match[1]) ? match[1] : void 0,
|
|
551
|
+
isExternal: !isRelativeSpecifier(match[2]),
|
|
552
|
+
reExport: false
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
function receiverTypeName(receiver) {
|
|
556
|
+
const tokens = receiver.replace(/[()*]/g, " ").split(/\s+/).map((item) => item.trim()).filter(Boolean);
|
|
557
|
+
return normalizeSymbolReference(tokens.at(-1) ?? "");
|
|
558
|
+
}
|
|
559
|
+
function analyzeGoCode(manifest, content) {
|
|
560
|
+
const lines = splitLines(content);
|
|
561
|
+
const imports = [];
|
|
562
|
+
const draftSymbols = [];
|
|
563
|
+
const exportLabels = [];
|
|
564
|
+
const diagnostics = [];
|
|
565
|
+
let inImportBlock = false;
|
|
566
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
567
|
+
const rawLine = lines[index] ?? "";
|
|
568
|
+
const trimmed = rawLine.trim();
|
|
569
|
+
if (!trimmed || trimmed.startsWith("//")) {
|
|
570
|
+
continue;
|
|
571
|
+
}
|
|
572
|
+
if (inImportBlock) {
|
|
573
|
+
if (trimmed === ")") {
|
|
574
|
+
inImportBlock = false;
|
|
575
|
+
continue;
|
|
576
|
+
}
|
|
577
|
+
const parsed = parseGoImportLine(trimmed);
|
|
578
|
+
if (parsed) {
|
|
579
|
+
imports.push(parsed);
|
|
580
|
+
}
|
|
581
|
+
continue;
|
|
582
|
+
}
|
|
583
|
+
const importBlockMatch = trimmed.match(/^import\s+\($/);
|
|
584
|
+
if (importBlockMatch) {
|
|
585
|
+
inImportBlock = true;
|
|
586
|
+
continue;
|
|
587
|
+
}
|
|
588
|
+
const singleImportMatch = trimmed.match(/^import\s+(.+)$/);
|
|
589
|
+
if (singleImportMatch) {
|
|
590
|
+
const parsed = parseGoImportLine(singleImportMatch[1]);
|
|
591
|
+
if (parsed) {
|
|
592
|
+
imports.push(parsed);
|
|
593
|
+
}
|
|
594
|
+
continue;
|
|
595
|
+
}
|
|
596
|
+
const typeMatch = trimmed.match(/^type\s+([A-Za-z_]\w*)\s+(struct|interface)\b/);
|
|
597
|
+
if (typeMatch) {
|
|
598
|
+
const exported = exportedByCapitalization(typeMatch[1]);
|
|
599
|
+
draftSymbols.push({
|
|
600
|
+
name: typeMatch[1],
|
|
601
|
+
kind: typeMatch[2] === "interface" ? "interface" : "class",
|
|
602
|
+
signature: singleLineSignature(trimmed),
|
|
603
|
+
exported,
|
|
604
|
+
callNames: [],
|
|
605
|
+
extendsNames: [],
|
|
606
|
+
implementsNames: [],
|
|
607
|
+
bodyText: collectBracedBlock(lines, index).text
|
|
608
|
+
});
|
|
609
|
+
if (exported) {
|
|
610
|
+
exportLabels.push(typeMatch[1]);
|
|
611
|
+
}
|
|
612
|
+
continue;
|
|
613
|
+
}
|
|
614
|
+
const aliasTypeMatch = trimmed.match(/^type\s+([A-Za-z_]\w*)\b(?!\s+(?:struct|interface)\b)/);
|
|
615
|
+
if (aliasTypeMatch) {
|
|
616
|
+
const exported = exportedByCapitalization(aliasTypeMatch[1]);
|
|
617
|
+
draftSymbols.push({
|
|
618
|
+
name: aliasTypeMatch[1],
|
|
619
|
+
kind: "type_alias",
|
|
620
|
+
signature: singleLineSignature(trimmed),
|
|
621
|
+
exported,
|
|
622
|
+
callNames: [],
|
|
623
|
+
extendsNames: [],
|
|
624
|
+
implementsNames: [],
|
|
625
|
+
bodyText: trimmed
|
|
626
|
+
});
|
|
627
|
+
if (exported) {
|
|
628
|
+
exportLabels.push(aliasTypeMatch[1]);
|
|
629
|
+
}
|
|
630
|
+
continue;
|
|
631
|
+
}
|
|
632
|
+
const funcMatch = trimmed.match(/^func\s+(?:\(([^)]*)\)\s*)?([A-Za-z_]\w*)\s*\(/);
|
|
633
|
+
if (funcMatch) {
|
|
634
|
+
const receiverType = funcMatch[1] ? receiverTypeName(funcMatch[1]) : "";
|
|
635
|
+
const symbolName = receiverType ? `${receiverType}.${funcMatch[2]}` : funcMatch[2];
|
|
636
|
+
const exported = exportedByCapitalization(funcMatch[2]);
|
|
637
|
+
const block = collectBracedBlock(lines, index);
|
|
638
|
+
draftSymbols.push({
|
|
639
|
+
name: symbolName,
|
|
640
|
+
kind: "function",
|
|
641
|
+
signature: singleLineSignature(trimmed),
|
|
642
|
+
exported,
|
|
643
|
+
callNames: [],
|
|
644
|
+
extendsNames: [],
|
|
645
|
+
implementsNames: [],
|
|
646
|
+
bodyText: block.text
|
|
647
|
+
});
|
|
648
|
+
if (exported) {
|
|
649
|
+
exportLabels.push(symbolName);
|
|
650
|
+
}
|
|
651
|
+
index = block.endIndex;
|
|
652
|
+
continue;
|
|
653
|
+
}
|
|
654
|
+
const variableMatch = trimmed.match(/^(?:var|const)\s+([A-Za-z_]\w*)\b/);
|
|
655
|
+
if (variableMatch) {
|
|
656
|
+
const exported = exportedByCapitalization(variableMatch[1]);
|
|
657
|
+
draftSymbols.push({
|
|
658
|
+
name: variableMatch[1],
|
|
659
|
+
kind: "variable",
|
|
660
|
+
signature: singleLineSignature(trimmed),
|
|
661
|
+
exported,
|
|
662
|
+
callNames: [],
|
|
663
|
+
extendsNames: [],
|
|
664
|
+
implementsNames: [],
|
|
665
|
+
bodyText: trimmed
|
|
666
|
+
});
|
|
667
|
+
if (exported) {
|
|
668
|
+
exportLabels.push(variableMatch[1]);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
return finalizeCodeAnalysis(manifest, "go", imports, draftSymbols, exportLabels, diagnostics);
|
|
673
|
+
}
|
|
674
|
+
function analyzeRustUseStatement(statement) {
|
|
675
|
+
const cleaned = statement.replace(/^pub\s+/, "").replace(/^use\s+/, "").replace(/;$/, "").trim();
|
|
676
|
+
const aliasMatch = cleaned.match(/\s+as\s+([A-Za-z_]\w*)$/);
|
|
677
|
+
const withoutAlias = aliasMatch ? cleaned.slice(0, aliasMatch.index).trim() : cleaned;
|
|
678
|
+
const braceMatch = withoutAlias.match(/^(.*)::\{(.+)\}$/);
|
|
679
|
+
const importedSymbols = braceMatch ? braceMatch[2].split(",").map((item) => item.trim()).filter(Boolean) : [aliasMatch ? `${normalizeSymbolReference(withoutAlias)} as ${aliasMatch[1]}` : normalizeSymbolReference(withoutAlias)].filter(
|
|
680
|
+
Boolean
|
|
681
|
+
);
|
|
682
|
+
const specifier = braceMatch ? braceMatch[1].trim() : withoutAlias;
|
|
683
|
+
return {
|
|
684
|
+
specifier,
|
|
685
|
+
importedSymbols,
|
|
686
|
+
isExternal: !/^(crate|self|super)::/.test(specifier),
|
|
687
|
+
reExport: statement.trim().startsWith("pub use ")
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
function rustVisibilityPrefix(trimmed) {
|
|
691
|
+
return /^(pub(?:\([^)]*\))?\s+)/.test(trimmed);
|
|
692
|
+
}
|
|
693
|
+
function analyzeRustCode(manifest, content) {
|
|
694
|
+
const lines = splitLines(content);
|
|
695
|
+
const imports = [];
|
|
696
|
+
const draftSymbols = [];
|
|
697
|
+
const exportLabels = [];
|
|
698
|
+
const diagnostics = [];
|
|
699
|
+
const symbolByName = /* @__PURE__ */ new Map();
|
|
700
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
701
|
+
const rawLine = lines[index] ?? "";
|
|
702
|
+
const trimmed = rawLine.trim();
|
|
703
|
+
if (!trimmed || trimmed.startsWith("//")) {
|
|
704
|
+
continue;
|
|
705
|
+
}
|
|
706
|
+
const useMatch = trimmed.match(/^(?:pub\s+)?use\s+.+;$/);
|
|
707
|
+
if (useMatch) {
|
|
708
|
+
imports.push(analyzeRustUseStatement(trimmed));
|
|
709
|
+
continue;
|
|
710
|
+
}
|
|
711
|
+
const functionMatch = trimmed.match(/^(?:pub(?:\([^)]*\))?\s+)?fn\s+([A-Za-z_]\w*)\s*\(/);
|
|
712
|
+
if (functionMatch) {
|
|
713
|
+
const exported = rustVisibilityPrefix(trimmed);
|
|
714
|
+
const block = collectBracedBlock(lines, index);
|
|
715
|
+
const symbol = {
|
|
716
|
+
name: functionMatch[1],
|
|
717
|
+
kind: "function",
|
|
718
|
+
signature: singleLineSignature(trimmed),
|
|
719
|
+
exported,
|
|
720
|
+
callNames: [],
|
|
721
|
+
extendsNames: [],
|
|
722
|
+
implementsNames: [],
|
|
723
|
+
bodyText: block.text
|
|
724
|
+
};
|
|
725
|
+
draftSymbols.push(symbol);
|
|
726
|
+
symbolByName.set(symbol.name, symbol);
|
|
727
|
+
if (exported) {
|
|
728
|
+
exportLabels.push(symbol.name);
|
|
729
|
+
}
|
|
730
|
+
index = block.endIndex;
|
|
731
|
+
continue;
|
|
732
|
+
}
|
|
733
|
+
const structMatch = trimmed.match(/^(?:pub(?:\([^)]*\))?\s+)?struct\s+([A-Za-z_]\w*)\b/);
|
|
734
|
+
if (structMatch) {
|
|
735
|
+
const exported = rustVisibilityPrefix(trimmed);
|
|
736
|
+
const block = collectBracedBlock(lines, index);
|
|
737
|
+
const symbol = {
|
|
738
|
+
name: structMatch[1],
|
|
739
|
+
kind: "class",
|
|
740
|
+
signature: singleLineSignature(trimmed),
|
|
741
|
+
exported,
|
|
742
|
+
callNames: [],
|
|
743
|
+
extendsNames: [],
|
|
744
|
+
implementsNames: [],
|
|
745
|
+
bodyText: block.text
|
|
746
|
+
};
|
|
747
|
+
draftSymbols.push(symbol);
|
|
748
|
+
symbolByName.set(symbol.name, symbol);
|
|
749
|
+
if (exported) {
|
|
750
|
+
exportLabels.push(symbol.name);
|
|
751
|
+
}
|
|
752
|
+
index = block.endIndex;
|
|
753
|
+
continue;
|
|
754
|
+
}
|
|
755
|
+
const enumMatch = trimmed.match(/^(?:pub(?:\([^)]*\))?\s+)?enum\s+([A-Za-z_]\w*)\b/);
|
|
756
|
+
if (enumMatch) {
|
|
757
|
+
const exported = rustVisibilityPrefix(trimmed);
|
|
758
|
+
const block = collectBracedBlock(lines, index);
|
|
759
|
+
const symbol = {
|
|
760
|
+
name: enumMatch[1],
|
|
761
|
+
kind: "enum",
|
|
762
|
+
signature: singleLineSignature(trimmed),
|
|
763
|
+
exported,
|
|
764
|
+
callNames: [],
|
|
765
|
+
extendsNames: [],
|
|
766
|
+
implementsNames: [],
|
|
767
|
+
bodyText: block.text
|
|
768
|
+
};
|
|
769
|
+
draftSymbols.push(symbol);
|
|
770
|
+
symbolByName.set(symbol.name, symbol);
|
|
771
|
+
if (exported) {
|
|
772
|
+
exportLabels.push(symbol.name);
|
|
773
|
+
}
|
|
774
|
+
index = block.endIndex;
|
|
775
|
+
continue;
|
|
776
|
+
}
|
|
777
|
+
const traitMatch = trimmed.match(/^(?:pub(?:\([^)]*\))?\s+)?trait\s+([A-Za-z_]\w*)\b/);
|
|
778
|
+
if (traitMatch) {
|
|
779
|
+
const exported = rustVisibilityPrefix(trimmed);
|
|
780
|
+
const block = collectBracedBlock(lines, index);
|
|
781
|
+
const symbol = {
|
|
782
|
+
name: traitMatch[1],
|
|
783
|
+
kind: "interface",
|
|
784
|
+
signature: singleLineSignature(trimmed),
|
|
785
|
+
exported,
|
|
786
|
+
callNames: [],
|
|
787
|
+
extendsNames: [],
|
|
788
|
+
implementsNames: [],
|
|
789
|
+
bodyText: block.text
|
|
790
|
+
};
|
|
791
|
+
draftSymbols.push(symbol);
|
|
792
|
+
symbolByName.set(symbol.name, symbol);
|
|
793
|
+
if (exported) {
|
|
794
|
+
exportLabels.push(symbol.name);
|
|
795
|
+
}
|
|
796
|
+
index = block.endIndex;
|
|
797
|
+
continue;
|
|
798
|
+
}
|
|
799
|
+
const aliasMatch = trimmed.match(/^(?:pub(?:\([^)]*\))?\s+)?type\s+([A-Za-z_]\w*)\s*=/);
|
|
800
|
+
if (aliasMatch) {
|
|
801
|
+
const exported = rustVisibilityPrefix(trimmed);
|
|
802
|
+
const symbol = {
|
|
803
|
+
name: aliasMatch[1],
|
|
804
|
+
kind: "type_alias",
|
|
805
|
+
signature: singleLineSignature(trimmed),
|
|
806
|
+
exported,
|
|
807
|
+
callNames: [],
|
|
808
|
+
extendsNames: [],
|
|
809
|
+
implementsNames: [],
|
|
810
|
+
bodyText: trimmed
|
|
811
|
+
};
|
|
812
|
+
draftSymbols.push(symbol);
|
|
813
|
+
symbolByName.set(symbol.name, symbol);
|
|
814
|
+
if (exported) {
|
|
815
|
+
exportLabels.push(symbol.name);
|
|
816
|
+
}
|
|
817
|
+
continue;
|
|
818
|
+
}
|
|
819
|
+
const variableMatch = trimmed.match(/^(?:pub(?:\([^)]*\))?\s+)?(?:const|static)\s+([A-Za-z_]\w*)\b/);
|
|
820
|
+
if (variableMatch) {
|
|
821
|
+
const exported = rustVisibilityPrefix(trimmed);
|
|
822
|
+
const symbol = {
|
|
823
|
+
name: variableMatch[1],
|
|
824
|
+
kind: "variable",
|
|
825
|
+
signature: singleLineSignature(trimmed),
|
|
826
|
+
exported,
|
|
827
|
+
callNames: [],
|
|
828
|
+
extendsNames: [],
|
|
829
|
+
implementsNames: [],
|
|
830
|
+
bodyText: trimmed
|
|
831
|
+
};
|
|
832
|
+
draftSymbols.push(symbol);
|
|
833
|
+
symbolByName.set(symbol.name, symbol);
|
|
834
|
+
if (exported) {
|
|
835
|
+
exportLabels.push(symbol.name);
|
|
836
|
+
}
|
|
837
|
+
continue;
|
|
838
|
+
}
|
|
839
|
+
const implMatch = trimmed.match(/^impl(?:<[^>]+>)?\s+(.+?)\s+for\s+([A-Za-z_][\w:<>]*)/);
|
|
840
|
+
if (implMatch) {
|
|
841
|
+
const traitName = normalizeSymbolReference(implMatch[1]);
|
|
842
|
+
const typeName = normalizeSymbolReference(implMatch[2]);
|
|
843
|
+
const symbol = symbolByName.get(typeName);
|
|
844
|
+
if (symbol && traitName) {
|
|
845
|
+
symbol.implementsNames.push(traitName);
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
for (const rawLine of lines) {
|
|
850
|
+
const trimmed = rawLine.trim();
|
|
851
|
+
const traitMatch = trimmed.match(/^(?:pub(?:\([^)]*\))?\s+)?trait\s+([A-Za-z_]\w*)\b/);
|
|
852
|
+
if (!traitMatch || symbolByName.has(traitMatch[1])) {
|
|
853
|
+
continue;
|
|
854
|
+
}
|
|
855
|
+
const exported = rustVisibilityPrefix(trimmed);
|
|
856
|
+
const symbol = {
|
|
857
|
+
name: traitMatch[1],
|
|
858
|
+
kind: "interface",
|
|
859
|
+
signature: singleLineSignature(trimmed),
|
|
860
|
+
exported,
|
|
861
|
+
callNames: [],
|
|
862
|
+
extendsNames: [],
|
|
863
|
+
implementsNames: [],
|
|
864
|
+
bodyText: trimmed
|
|
865
|
+
};
|
|
866
|
+
draftSymbols.push(symbol);
|
|
867
|
+
symbolByName.set(symbol.name, symbol);
|
|
868
|
+
if (exported) {
|
|
869
|
+
exportLabels.push(symbol.name);
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
return finalizeCodeAnalysis(manifest, "rust", imports, draftSymbols, exportLabels, diagnostics);
|
|
873
|
+
}
|
|
874
|
+
function analyzeJavaImport(statement) {
|
|
875
|
+
const cleaned = statement.replace(/^import\s+/, "").replace(/^static\s+/, "").replace(/;$/, "").trim();
|
|
876
|
+
const symbolName = normalizeSymbolReference(cleaned.replace(/\.\*$/, ""));
|
|
877
|
+
return {
|
|
878
|
+
specifier: cleaned.replace(/\.\*$/, ""),
|
|
879
|
+
importedSymbols: symbolName ? [symbolName] : [],
|
|
880
|
+
isExternal: true,
|
|
881
|
+
reExport: false
|
|
882
|
+
};
|
|
883
|
+
}
|
|
884
|
+
function parseJavaImplements(value) {
|
|
885
|
+
return (value ?? "").split(",").map((item) => normalizeSymbolReference(item)).filter(Boolean);
|
|
886
|
+
}
|
|
887
|
+
function analyzeJavaCode(manifest, content) {
|
|
888
|
+
const lines = splitLines(content);
|
|
889
|
+
const imports = [];
|
|
890
|
+
const draftSymbols = [];
|
|
891
|
+
const exportLabels = [];
|
|
892
|
+
const diagnostics = [];
|
|
893
|
+
let depth = 0;
|
|
894
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
895
|
+
const rawLine = lines[index] ?? "";
|
|
896
|
+
const trimmed = rawLine.trim();
|
|
897
|
+
const lineDepth = depth;
|
|
898
|
+
if (lineDepth === 0 && trimmed.startsWith("import ")) {
|
|
899
|
+
imports.push(analyzeJavaImport(trimmed));
|
|
900
|
+
}
|
|
901
|
+
if (lineDepth === 0) {
|
|
902
|
+
const classMatch = trimmed.match(
|
|
903
|
+
/^(public\s+)?(?:abstract\s+|final\s+|sealed\s+|non-sealed\s+)*class\s+([A-Za-z_]\w*)\b(?:\s+extends\s+([A-Za-z_][\w.<>]*))?(?:\s+implements\s+([A-Za-z_][\w.,<>\s]*))?/
|
|
904
|
+
);
|
|
905
|
+
if (classMatch) {
|
|
906
|
+
const exported = Boolean(classMatch[1]);
|
|
907
|
+
const block = collectBracedBlock(lines, index);
|
|
908
|
+
draftSymbols.push({
|
|
909
|
+
name: classMatch[2],
|
|
910
|
+
kind: "class",
|
|
911
|
+
signature: singleLineSignature(trimmed),
|
|
912
|
+
exported,
|
|
913
|
+
callNames: [],
|
|
914
|
+
extendsNames: classMatch[3] ? [classMatch[3]] : [],
|
|
915
|
+
implementsNames: parseJavaImplements(classMatch[4]),
|
|
916
|
+
bodyText: block.text
|
|
917
|
+
});
|
|
918
|
+
if (exported) {
|
|
919
|
+
exportLabels.push(classMatch[2]);
|
|
920
|
+
}
|
|
921
|
+
index = block.endIndex;
|
|
922
|
+
depth = 0;
|
|
923
|
+
continue;
|
|
924
|
+
}
|
|
925
|
+
const interfaceMatch = trimmed.match(
|
|
926
|
+
/^(public\s+)?(?:sealed\s+|non-sealed\s+)?interface\s+([A-Za-z_]\w*)\b(?:\s+extends\s+([A-Za-z_][\w.,<>\s]*))?/
|
|
927
|
+
);
|
|
928
|
+
if (interfaceMatch) {
|
|
929
|
+
const exported = Boolean(interfaceMatch[1]);
|
|
930
|
+
const block = collectBracedBlock(lines, index);
|
|
931
|
+
draftSymbols.push({
|
|
932
|
+
name: interfaceMatch[2],
|
|
933
|
+
kind: "interface",
|
|
934
|
+
signature: singleLineSignature(trimmed),
|
|
935
|
+
exported,
|
|
936
|
+
callNames: [],
|
|
937
|
+
extendsNames: parseJavaImplements(interfaceMatch[3]),
|
|
938
|
+
implementsNames: [],
|
|
939
|
+
bodyText: block.text
|
|
940
|
+
});
|
|
941
|
+
if (exported) {
|
|
942
|
+
exportLabels.push(interfaceMatch[2]);
|
|
943
|
+
}
|
|
944
|
+
index = block.endIndex;
|
|
945
|
+
depth = 0;
|
|
946
|
+
continue;
|
|
947
|
+
}
|
|
948
|
+
const enumMatch = trimmed.match(/^(public\s+)?enum\s+([A-Za-z_]\w*)\b(?:\s+implements\s+([A-Za-z_][\w.,<>\s]*))?/);
|
|
949
|
+
if (enumMatch) {
|
|
950
|
+
const exported = Boolean(enumMatch[1]);
|
|
951
|
+
const block = collectBracedBlock(lines, index);
|
|
952
|
+
draftSymbols.push({
|
|
953
|
+
name: enumMatch[2],
|
|
954
|
+
kind: "enum",
|
|
955
|
+
signature: singleLineSignature(trimmed),
|
|
956
|
+
exported,
|
|
957
|
+
callNames: [],
|
|
958
|
+
extendsNames: [],
|
|
959
|
+
implementsNames: parseJavaImplements(enumMatch[3]),
|
|
960
|
+
bodyText: block.text
|
|
961
|
+
});
|
|
962
|
+
if (exported) {
|
|
963
|
+
exportLabels.push(enumMatch[2]);
|
|
964
|
+
}
|
|
965
|
+
index = block.endIndex;
|
|
966
|
+
depth = 0;
|
|
967
|
+
continue;
|
|
968
|
+
}
|
|
969
|
+
const recordMatch = trimmed.match(
|
|
970
|
+
/^(public\s+)?record\s+([A-Za-z_]\w*)\b(?:\s*\([^)]*\))?(?:\s+implements\s+([A-Za-z_][\w.,<>\s]*))?/
|
|
971
|
+
);
|
|
972
|
+
if (recordMatch) {
|
|
973
|
+
const exported = Boolean(recordMatch[1]);
|
|
974
|
+
const block = collectBracedBlock(lines, index);
|
|
975
|
+
draftSymbols.push({
|
|
976
|
+
name: recordMatch[2],
|
|
977
|
+
kind: "class",
|
|
978
|
+
signature: singleLineSignature(trimmed),
|
|
979
|
+
exported,
|
|
980
|
+
callNames: [],
|
|
981
|
+
extendsNames: [],
|
|
982
|
+
implementsNames: parseJavaImplements(recordMatch[3]),
|
|
983
|
+
bodyText: block.text
|
|
984
|
+
});
|
|
985
|
+
if (exported) {
|
|
986
|
+
exportLabels.push(recordMatch[2]);
|
|
987
|
+
}
|
|
988
|
+
index = block.endIndex;
|
|
989
|
+
depth = 0;
|
|
990
|
+
continue;
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
for (const character of rawLine) {
|
|
994
|
+
if (character === "{") {
|
|
995
|
+
depth += 1;
|
|
996
|
+
} else if (character === "}") {
|
|
997
|
+
depth -= 1;
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
return finalizeCodeAnalysis(manifest, "java", imports, draftSymbols, exportLabels, diagnostics);
|
|
1002
|
+
}
|
|
1003
|
+
function analyzeTypeScriptLikeCode(manifest, content) {
|
|
281
1004
|
const language = manifest.language ?? inferCodeLanguage(manifest.originalPath ?? manifest.storedPath, manifest.mimeType) ?? "typescript";
|
|
282
1005
|
const sourceFile = ts.createSourceFile(
|
|
283
1006
|
manifest.originalPath ?? manifest.storedPath,
|
|
@@ -478,17 +1201,6 @@ function analyzeTopLevelCode(manifest, content) {
|
|
|
478
1201
|
}
|
|
479
1202
|
}
|
|
480
1203
|
}
|
|
481
|
-
const seenSymbolIds = /* @__PURE__ */ new Map();
|
|
482
|
-
const symbols = draftSymbols.map((symbol) => ({
|
|
483
|
-
id: makeSymbolId(manifest.sourceId, symbol.name, seenSymbolIds),
|
|
484
|
-
name: symbol.name,
|
|
485
|
-
kind: symbol.kind,
|
|
486
|
-
signature: symbol.signature,
|
|
487
|
-
exported: symbol.exported || localExportNames.has(symbol.name),
|
|
488
|
-
calls: symbol.callNames,
|
|
489
|
-
extends: symbol.extendsNames,
|
|
490
|
-
implements: symbol.implementsNames
|
|
491
|
-
}));
|
|
492
1204
|
const parseDiagnostics = sourceFile.parseDiagnostics ?? [];
|
|
493
1205
|
const diagnostics = parseDiagnostics.map((diagnostic) => {
|
|
494
1206
|
const position = diagnostic.start !== void 0 ? sourceFile.getLineAndCharacterOfPosition(diagnostic.start) : void 0;
|
|
@@ -500,22 +1212,11 @@ function analyzeTopLevelCode(manifest, content) {
|
|
|
500
1212
|
column: (position?.character ?? 0) + 1
|
|
501
1213
|
};
|
|
502
1214
|
});
|
|
503
|
-
return
|
|
504
|
-
moduleId: `module:${manifest.sourceId}`,
|
|
505
|
-
language,
|
|
506
|
-
imports,
|
|
507
|
-
dependencies: uniqueBy(
|
|
508
|
-
imports.filter((item) => item.isExternal).map((item) => item.specifier),
|
|
509
|
-
(specifier) => specifier
|
|
510
|
-
),
|
|
511
|
-
symbols,
|
|
512
|
-
exports: uniqueBy([...symbols.filter((symbol) => symbol.exported).map((symbol) => symbol.name), ...exportLabels], (label) => label),
|
|
513
|
-
diagnostics
|
|
514
|
-
};
|
|
1215
|
+
return finalizeCodeAnalysis(manifest, language, imports, draftSymbols, exportLabels, diagnostics);
|
|
515
1216
|
}
|
|
516
1217
|
function inferCodeLanguage(filePath, mimeType = "") {
|
|
517
1218
|
const extension = path2.extname(filePath).toLowerCase();
|
|
518
|
-
if (extension === ".ts") {
|
|
1219
|
+
if (extension === ".ts" || extension === ".mts" || extension === ".cts") {
|
|
519
1220
|
return "typescript";
|
|
520
1221
|
}
|
|
521
1222
|
if (extension === ".tsx") {
|
|
@@ -524,35 +1225,92 @@ function inferCodeLanguage(filePath, mimeType = "") {
|
|
|
524
1225
|
if (extension === ".jsx") {
|
|
525
1226
|
return "jsx";
|
|
526
1227
|
}
|
|
527
|
-
if (extension === ".js" || mimeType.includes("javascript")) {
|
|
1228
|
+
if (extension === ".js" || extension === ".mjs" || extension === ".cjs" || mimeType.includes("javascript")) {
|
|
528
1229
|
return "javascript";
|
|
529
1230
|
}
|
|
1231
|
+
if (extension === ".py") {
|
|
1232
|
+
return "python";
|
|
1233
|
+
}
|
|
1234
|
+
if (extension === ".go") {
|
|
1235
|
+
return "go";
|
|
1236
|
+
}
|
|
1237
|
+
if (extension === ".rs") {
|
|
1238
|
+
return "rust";
|
|
1239
|
+
}
|
|
1240
|
+
if (extension === ".java") {
|
|
1241
|
+
return "java";
|
|
1242
|
+
}
|
|
530
1243
|
return void 0;
|
|
531
1244
|
}
|
|
532
1245
|
function modulePageTitle(manifest) {
|
|
533
1246
|
return `${manifest.title} module`;
|
|
534
1247
|
}
|
|
535
|
-
function importResolutionCandidates(basePath, specifier) {
|
|
1248
|
+
function importResolutionCandidates(basePath, specifier, extensions) {
|
|
536
1249
|
const resolved = path2.resolve(path2.dirname(basePath), specifier);
|
|
537
1250
|
if (path2.extname(resolved)) {
|
|
538
1251
|
return [path2.normalize(resolved)];
|
|
539
1252
|
}
|
|
540
|
-
const extensions = [".ts", ".tsx", ".js", ".jsx", ".mts", ".cts", ".mjs", ".cjs"];
|
|
541
1253
|
const direct = extensions.map((extension) => path2.normalize(`${resolved}${extension}`));
|
|
542
1254
|
const indexFiles = extensions.map((extension) => path2.normalize(path2.join(resolved, `index${extension}`)));
|
|
543
1255
|
return uniqueBy([path2.normalize(resolved), ...direct, ...indexFiles], (candidate) => candidate);
|
|
544
1256
|
}
|
|
545
|
-
function
|
|
1257
|
+
function resolveJsLikeImportSourceId(manifest, specifier, manifests) {
|
|
546
1258
|
if (manifest.originType !== "file" || !manifest.originalPath || !isRelativeSpecifier(specifier)) {
|
|
547
1259
|
return void 0;
|
|
548
1260
|
}
|
|
549
|
-
const candidates = new Set(
|
|
1261
|
+
const candidates = new Set(
|
|
1262
|
+
importResolutionCandidates(manifest.originalPath, specifier, [".ts", ".tsx", ".js", ".jsx", ".mts", ".cts", ".mjs", ".cjs"])
|
|
1263
|
+
);
|
|
550
1264
|
return manifests.find(
|
|
551
1265
|
(candidate) => candidate.sourceKind === "code" && candidate.originalPath && candidates.has(path2.normalize(candidate.originalPath))
|
|
552
1266
|
)?.sourceId;
|
|
553
1267
|
}
|
|
1268
|
+
function resolvePythonImportSourceId(manifest, specifier, manifests) {
|
|
1269
|
+
if (manifest.originType !== "file" || !manifest.originalPath) {
|
|
1270
|
+
return void 0;
|
|
1271
|
+
}
|
|
1272
|
+
if (specifier.startsWith(".")) {
|
|
1273
|
+
const dotMatch = specifier.match(/^\.+/);
|
|
1274
|
+
const depth = dotMatch ? dotMatch[0].length : 0;
|
|
1275
|
+
const relativeModule = specifier.slice(depth).replace(/\./g, "/");
|
|
1276
|
+
const baseDir = path2.dirname(manifest.originalPath);
|
|
1277
|
+
const parentDir = path2.resolve(baseDir, ...Array(Math.max(depth - 1, 0)).fill(".."));
|
|
1278
|
+
const moduleBase = relativeModule ? path2.join(parentDir, relativeModule) : parentDir;
|
|
1279
|
+
const candidates = /* @__PURE__ */ new Set([path2.normalize(`${moduleBase}.py`), path2.normalize(path2.join(moduleBase, "__init__.py"))]);
|
|
1280
|
+
return manifests.find(
|
|
1281
|
+
(candidate) => candidate.sourceKind === "code" && candidate.originalPath && candidates.has(path2.normalize(candidate.originalPath))
|
|
1282
|
+
)?.sourceId;
|
|
1283
|
+
}
|
|
1284
|
+
const modulePath = specifier.replace(/\./g, "/");
|
|
1285
|
+
const suffixes = [`/${modulePath}.py`, `/${modulePath}/__init__.py`];
|
|
1286
|
+
return manifests.find((candidate) => {
|
|
1287
|
+
if (candidate.sourceKind !== "code" || !candidate.originalPath) {
|
|
1288
|
+
return false;
|
|
1289
|
+
}
|
|
1290
|
+
const normalizedOriginalPath = path2.normalize(candidate.originalPath);
|
|
1291
|
+
return suffixes.some((suffix) => normalizedOriginalPath.endsWith(path2.normalize(suffix)));
|
|
1292
|
+
})?.sourceId;
|
|
1293
|
+
}
|
|
1294
|
+
function resolveCodeImportSourceId(manifest, specifier, manifests) {
|
|
1295
|
+
const language = manifest.language ?? inferCodeLanguage(manifest.originalPath ?? manifest.storedPath, manifest.mimeType);
|
|
1296
|
+
switch (language) {
|
|
1297
|
+
case "javascript":
|
|
1298
|
+
case "jsx":
|
|
1299
|
+
case "typescript":
|
|
1300
|
+
case "tsx":
|
|
1301
|
+
return resolveJsLikeImportSourceId(manifest, specifier, manifests);
|
|
1302
|
+
case "python":
|
|
1303
|
+
return resolvePythonImportSourceId(manifest, specifier, manifests);
|
|
1304
|
+
default:
|
|
1305
|
+
return void 0;
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
function escapeRegExp(value) {
|
|
1309
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1310
|
+
}
|
|
554
1311
|
function analyzeCodeSource(manifest, extractedText, schemaHash) {
|
|
555
|
-
const
|
|
1312
|
+
const language = manifest.language ?? inferCodeLanguage(manifest.originalPath ?? manifest.storedPath, manifest.mimeType) ?? "typescript";
|
|
1313
|
+
const code = language === "python" ? analyzePythonCode(manifest, extractedText) : language === "go" ? analyzeGoCode(manifest, extractedText) : language === "rust" ? analyzeRustCode(manifest, extractedText) : language === "java" ? analyzeJavaCode(manifest, extractedText) : analyzeTypeScriptLikeCode(manifest, extractedText);
|
|
556
1314
|
return {
|
|
557
1315
|
sourceId: manifest.sourceId,
|
|
558
1316
|
sourceHash: manifest.contentHash,
|
|
@@ -2432,7 +3190,7 @@ function buildModulePage(input) {
|
|
|
2432
3190
|
]);
|
|
2433
3191
|
const callsSection = code.symbols.flatMap((symbol) => symbol.calls.map((target) => `- \`${symbol.name}\` calls \`${target}\``));
|
|
2434
3192
|
const diagnosticsSection = code.diagnostics.length ? code.diagnostics.map(
|
|
2435
|
-
(diagnostic) => `- ${diagnostic.category}
|
|
3193
|
+
(diagnostic) => `- ${diagnostic.category} diagnostic ${diagnostic.code} at ${diagnostic.line}:${diagnostic.column}: ${diagnostic.message}`
|
|
2436
3194
|
) : ["- No parser diagnostics."];
|
|
2437
3195
|
const frontmatter = {
|
|
2438
3196
|
page_id: pageId,
|
|
@@ -3827,7 +4585,7 @@ async function resolveImageGenerationProvider(rootDir) {
|
|
|
3827
4585
|
if (!providerConfig) {
|
|
3828
4586
|
throw new Error(`No provider configured with id "${preferredProviderId}" for task "imageProvider".`);
|
|
3829
4587
|
}
|
|
3830
|
-
const { createProvider: createProvider2 } = await import("./registry-
|
|
4588
|
+
const { createProvider: createProvider2 } = await import("./registry-YDXVCE4Q.js");
|
|
3831
4589
|
return createProvider2(preferredProviderId, providerConfig, rootDir);
|
|
3832
4590
|
}
|
|
3833
4591
|
async function generateOutputArtifacts(rootDir, input) {
|
|
@@ -6766,7 +7524,7 @@ async function bootstrapDemo(rootDir, input) {
|
|
|
6766
7524
|
}
|
|
6767
7525
|
|
|
6768
7526
|
// src/mcp.ts
|
|
6769
|
-
var SERVER_VERSION = "0.1.
|
|
7527
|
+
var SERVER_VERSION = "0.1.16";
|
|
6770
7528
|
async function createMcpServer(rootDir) {
|
|
6771
7529
|
const server = new McpServer({
|
|
6772
7530
|
name: "swarmvault",
|