trace-mcp 1.5.3 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -4563,7 +4563,8 @@ var TraceMcpConfigSchema = z.object({
4563
4563
  watch: z.object({
4564
4564
  enabled: z.boolean().default(true),
4565
4565
  debounceMs: z.number().int().min(500).max(3e4).default(2e3)
4566
- }).default({})
4566
+ }).default({}),
4567
+ children: z.array(z.string()).optional()
4567
4568
  });
4568
4569
  function loadGlobalConfigRaw() {
4569
4570
  if (!fs2.existsSync(GLOBAL_CONFIG_PATH)) return {};
@@ -4636,6 +4637,13 @@ function saveProjectConfig(projectRoot, config) {
4636
4637
  existing.projects = projects;
4637
4638
  fs2.writeFileSync(GLOBAL_CONFIG_PATH, JSON.stringify(existing, null, 2) + "\n");
4638
4639
  }
4640
+ function removeProjectConfig(projectRoot) {
4641
+ const existing = loadGlobalConfigRaw();
4642
+ const projects = existing.projects ?? {};
4643
+ delete projects[projectRoot];
4644
+ existing.projects = projects;
4645
+ fs2.writeFileSync(GLOBAL_CONFIG_PATH, JSON.stringify(existing, null, 2) + "\n");
4646
+ }
4639
4647
 
4640
4648
  // src/server/server.ts
4641
4649
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -5014,6 +5022,22 @@ function detectWorkspaces(rootPath) {
5014
5022
  if (composerResult.length > 0) return composerResult;
5015
5023
  return [];
5016
5024
  }
5025
+ function buildMultiRootWorkspaces(parentDir, childRoots) {
5026
+ const workspaces = [];
5027
+ for (const childRoot of childRoots) {
5028
+ const relPath = path3.relative(parentDir, childRoot).replace(/\\/g, "/");
5029
+ const childName = path3.basename(childRoot);
5030
+ workspaces.push({ name: childName, path: relPath });
5031
+ const subWorkspaces = detectWorkspaces(childRoot);
5032
+ for (const sub of subWorkspaces) {
5033
+ workspaces.push({
5034
+ name: `${childName}/${sub.name}`,
5035
+ path: `${relPath}/${sub.path}`
5036
+ });
5037
+ }
5038
+ }
5039
+ return workspaces;
5040
+ }
5017
5041
  function detectPnpmWorkspaces(rootPath) {
5018
5042
  const yamlPath = path3.join(rootPath, "pnpm-workspace.yaml");
5019
5043
  if (!fs4.existsSync(yamlPath)) return [];
@@ -7411,9 +7435,14 @@ var IndexingPipeline = class _IndexingPipeline {
7411
7435
  const result = this._lock.then(async () => {
7412
7436
  this._isIncremental = false;
7413
7437
  const start = Date.now();
7414
- this.workspaces = detectWorkspaces(this.rootPath);
7415
- if (this.workspaces.length > 0) {
7416
- logger.info({ workspaces: this.workspaces.map((w) => w.name) }, "Detected workspaces");
7438
+ if (this.config.children?.length) {
7439
+ this.workspaces = buildMultiRootWorkspaces(this.rootPath, this.config.children);
7440
+ logger.info({ workspaces: this.workspaces.map((w) => w.name) }, "Multi-root workspaces");
7441
+ } else {
7442
+ this.workspaces = detectWorkspaces(this.rootPath);
7443
+ if (this.workspaces.length > 0) {
7444
+ logger.info({ workspaces: this.workspaces.map((w) => w.name) }, "Detected workspaces");
7445
+ }
7417
7446
  }
7418
7447
  const filePaths = await this.collectFiles();
7419
7448
  return this.runPipeline(filePaths, force ?? false, start);
@@ -9727,6 +9756,14 @@ function buildInstructions(detectedFrameworks, verbosity) {
9727
9756
  "Before creating new functions/classes:",
9728
9757
  '- `check_duplication` { name: "functionName", kind: "function" } \u2014 checks if similar symbols already exist. Use BEFORE writing new code to avoid reinventing existing logic.',
9729
9758
  "",
9759
+ "Bulk mechanical changes (adding async/await, updating patterns, fixing imports across many files):",
9760
+ "- `apply_codemod` { pattern, replacement, file_pattern } \u2014 regex find-and-replace across files. Dry-run by default (shows preview). Two-step workflow:",
9761
+ " 1. Call with dry_run: true (default) \u2192 review preview with context lines",
9762
+ " 2. Call with dry_run: false \u2192 apply changes. Requires confirm_large: true if >20 files affected.",
9763
+ "- Use `filter_content` to narrow scope to files containing a specific substring.",
9764
+ "- Use `multiline: true` for patterns spanning multiple lines.",
9765
+ "- NEVER use dozens of Edit calls for the same regex replacement \u2014 use apply_codemod instead.",
9766
+ "",
9730
9767
  "WHEN TO USE native tools (Read/Grep/Glob):",
9731
9768
  "- Non-code files (.md, .json, .yaml, .toml, config) \u2192 Read/Grep",
9732
9769
  "- Reading a file before editing (Edit needs full content) \u2192 Read",
@@ -18903,6 +18940,7 @@ import { z as z7 } from "zod";
18903
18940
  // src/tools/refactoring/refactor.ts
18904
18941
  import fs24 from "fs";
18905
18942
  import path35 from "path";
18943
+ import fg4 from "fast-glob";
18906
18944
  function readLines2(filePath) {
18907
18945
  return fs24.readFileSync(filePath, "utf-8").split("\n");
18908
18946
  }
@@ -19236,6 +19274,193 @@ ${functionDef}`
19236
19274
  }
19237
19275
  return result;
19238
19276
  }
19277
+ var CODEMOD_MAX_PREVIEW = 20;
19278
+ var CODEMOD_LARGE_THRESHOLD = 20;
19279
+ var CODEMOD_CONTEXT_LINES = 2;
19280
+ var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
19281
+ ".png",
19282
+ ".jpg",
19283
+ ".jpeg",
19284
+ ".gif",
19285
+ ".bmp",
19286
+ ".ico",
19287
+ ".svg",
19288
+ ".webp",
19289
+ ".woff",
19290
+ ".woff2",
19291
+ ".ttf",
19292
+ ".eot",
19293
+ ".otf",
19294
+ ".zip",
19295
+ ".tar",
19296
+ ".gz",
19297
+ ".bz2",
19298
+ ".7z",
19299
+ ".rar",
19300
+ ".pdf",
19301
+ ".doc",
19302
+ ".docx",
19303
+ ".xls",
19304
+ ".xlsx",
19305
+ ".mp3",
19306
+ ".mp4",
19307
+ ".avi",
19308
+ ".mov",
19309
+ ".wav",
19310
+ ".exe",
19311
+ ".dll",
19312
+ ".so",
19313
+ ".dylib",
19314
+ ".o",
19315
+ ".a",
19316
+ ".wasm",
19317
+ ".pyc",
19318
+ ".class"
19319
+ ]);
19320
+ var SKIP_DIRS = ["node_modules", ".git", "dist", "build", "vendor", "__pycache__", ".next", ".nuxt"];
19321
+ function applyCodemod(projectRoot, pattern, replacement, filePattern, options) {
19322
+ const result = {
19323
+ success: false,
19324
+ tool: "apply_codemod",
19325
+ dry_run: options.dryRun,
19326
+ matches: [],
19327
+ files_modified: [],
19328
+ total_replacements: 0,
19329
+ total_files: 0,
19330
+ warnings: []
19331
+ };
19332
+ let regex;
19333
+ try {
19334
+ const flags = options.multiline ? "gms" : "gm";
19335
+ regex = new RegExp(pattern, flags);
19336
+ } catch (e) {
19337
+ result.error = `Invalid regex pattern: ${e.message}`;
19338
+ return result;
19339
+ }
19340
+ let files;
19341
+ try {
19342
+ files = fg4.sync(filePattern, {
19343
+ cwd: projectRoot,
19344
+ ignore: SKIP_DIRS.map((d) => `**/${d}/**`),
19345
+ onlyFiles: true,
19346
+ absolute: false
19347
+ });
19348
+ } catch (e) {
19349
+ result.error = `Invalid file pattern: ${e.message}`;
19350
+ return result;
19351
+ }
19352
+ files = files.filter((f) => !BINARY_EXTENSIONS.has(path35.extname(f).toLowerCase()));
19353
+ if (files.length === 0) {
19354
+ result.error = `No files matched pattern: ${filePattern}`;
19355
+ return result;
19356
+ }
19357
+ const allMatches = [];
19358
+ const filesWithMatches = /* @__PURE__ */ new Set();
19359
+ for (const relPath of files) {
19360
+ const absPath = path35.resolve(projectRoot, relPath);
19361
+ if (!fs24.existsSync(absPath)) continue;
19362
+ let content;
19363
+ try {
19364
+ content = fs24.readFileSync(absPath, "utf-8");
19365
+ } catch {
19366
+ result.warnings.push(`Could not read: ${relPath}`);
19367
+ continue;
19368
+ }
19369
+ if (options.filterContent && !content.includes(options.filterContent)) {
19370
+ continue;
19371
+ }
19372
+ const lines = content.split("\n");
19373
+ if (options.multiline) {
19374
+ regex.lastIndex = 0;
19375
+ if (!regex.test(content)) continue;
19376
+ filesWithMatches.add(relPath);
19377
+ regex.lastIndex = 0;
19378
+ let matchCount = 0;
19379
+ const matchPositions = [];
19380
+ let m;
19381
+ while ((m = regex.exec(content)) !== null) {
19382
+ matchPositions.push({ index: m.index, match: m[0] });
19383
+ matchCount++;
19384
+ if (m[0].length === 0) {
19385
+ regex.lastIndex++;
19386
+ }
19387
+ }
19388
+ for (const pos of matchPositions.slice(0, CODEMOD_MAX_PREVIEW - allMatches.length)) {
19389
+ const lineNum = content.slice(0, pos.index).split("\n").length;
19390
+ const original = pos.match;
19391
+ regex.lastIndex = 0;
19392
+ const replaced = original.replace(regex, replacement);
19393
+ allMatches.push({
19394
+ file: relPath,
19395
+ line: lineNum,
19396
+ original: original.length > 200 ? original.slice(0, 200) + "\u2026" : original,
19397
+ replaced: replaced.length > 200 ? replaced.slice(0, 200) + "\u2026" : replaced,
19398
+ context_before: lines.slice(Math.max(0, lineNum - 1 - CODEMOD_CONTEXT_LINES), lineNum - 1),
19399
+ context_after: lines.slice(lineNum, lineNum + CODEMOD_CONTEXT_LINES)
19400
+ });
19401
+ }
19402
+ result.total_replacements += matchCount;
19403
+ } else {
19404
+ let fileMatchCount = 0;
19405
+ for (let i = 0; i < lines.length; i++) {
19406
+ regex.lastIndex = 0;
19407
+ if (!regex.test(lines[i])) continue;
19408
+ filesWithMatches.add(relPath);
19409
+ fileMatchCount++;
19410
+ regex.lastIndex = 0;
19411
+ const newLine = lines[i].replace(regex, replacement);
19412
+ if (allMatches.length < CODEMOD_MAX_PREVIEW) {
19413
+ allMatches.push({
19414
+ file: relPath,
19415
+ line: i + 1,
19416
+ original: lines[i],
19417
+ replaced: newLine,
19418
+ context_before: lines.slice(Math.max(0, i - CODEMOD_CONTEXT_LINES), i),
19419
+ context_after: lines.slice(i + 1, i + 1 + CODEMOD_CONTEXT_LINES)
19420
+ });
19421
+ }
19422
+ }
19423
+ result.total_replacements += fileMatchCount;
19424
+ }
19425
+ }
19426
+ result.total_files = filesWithMatches.size;
19427
+ if (allMatches.length === 0) {
19428
+ result.error = `No matches found for pattern in ${files.length} files`;
19429
+ return result;
19430
+ }
19431
+ if (filesWithMatches.size > CODEMOD_LARGE_THRESHOLD && !options.confirmLarge) {
19432
+ result.matches = allMatches;
19433
+ result.warnings.push(
19434
+ `Affects ${filesWithMatches.size} files (>${CODEMOD_LARGE_THRESHOLD}). Re-run with confirm_large: true to proceed, or narrow file_pattern.`
19435
+ );
19436
+ result.dry_run = true;
19437
+ result.success = true;
19438
+ return result;
19439
+ }
19440
+ if (options.dryRun) {
19441
+ result.matches = allMatches;
19442
+ result.success = true;
19443
+ return result;
19444
+ }
19445
+ for (const relPath of filesWithMatches) {
19446
+ const absPath = path35.resolve(projectRoot, relPath);
19447
+ try {
19448
+ const content = fs24.readFileSync(absPath, "utf-8");
19449
+ const flags = options.multiline ? "gms" : "gm";
19450
+ const freshRegex = new RegExp(pattern, flags);
19451
+ const newContent = content.replace(freshRegex, replacement);
19452
+ if (newContent !== content) {
19453
+ fs24.writeFileSync(absPath, newContent, "utf-8");
19454
+ result.files_modified.push(relPath);
19455
+ }
19456
+ } catch (e) {
19457
+ result.warnings.push(`Failed to write ${relPath}: ${e.message}`);
19458
+ }
19459
+ }
19460
+ result.matches = allMatches;
19461
+ result.success = true;
19462
+ return result;
19463
+ }
19239
19464
  function detectLanguage2(ext) {
19240
19465
  switch (ext) {
19241
19466
  case ".ts":
@@ -19472,6 +19697,31 @@ function registerRefactoringTools(server, ctx) {
19472
19697
  return { content: [{ type: "text", text: j3(result) }] };
19473
19698
  }
19474
19699
  );
19700
+ server.tool(
19701
+ "apply_codemod",
19702
+ "Bulk regex find-and-replace across files. Dry-run by default \u2014 first call shows preview, second call with dry_run=false applies. Use for mechanical changes like adding async/await, renaming patterns, updating imports across many files.",
19703
+ {
19704
+ pattern: z7.string().min(1).max(1e3).describe("Regex pattern to match (JavaScript regex syntax)"),
19705
+ replacement: z7.string().max(1e3).describe("Replacement string ($1, $2 for capture groups)"),
19706
+ file_pattern: z7.string().min(1).max(512).describe('Glob pattern for files to scan (e.g. "tests/**/*.test.ts", "src/**/*.py")'),
19707
+ dry_run: z7.boolean().default(true).describe("Preview changes without writing (default: true). Set to false to apply."),
19708
+ confirm_large: z7.boolean().optional().describe("Required when >20 files affected. Acknowledges large-scale change."),
19709
+ filter_content: z7.string().max(500).optional().describe("Only process files containing this substring (narrows scope)"),
19710
+ multiline: z7.boolean().optional().describe("Enable multiline mode (dot matches newlines, patterns span lines)")
19711
+ },
19712
+ async ({ pattern, replacement, file_pattern, dry_run, confirm_large, filter_content, multiline }) => {
19713
+ const result = applyCodemod(projectRoot, pattern, replacement, file_pattern, {
19714
+ dryRun: dry_run,
19715
+ confirmLarge: confirm_large,
19716
+ filterContent: filter_content,
19717
+ multiline
19718
+ });
19719
+ if (!result.success) {
19720
+ return { content: [{ type: "text", text: j3(result) }], isError: true };
19721
+ }
19722
+ return { content: [{ type: "text", text: j3(result) }] };
19723
+ }
19724
+ );
19475
19725
  }
19476
19726
 
19477
19727
  // src/tools/register/advanced.ts
@@ -28652,6 +28902,8 @@ var KNOWN_PACKAGES = {
28652
28902
  "@clack/prompts": { category: "infra", priority: "medium", plugin: "clack" },
28653
28903
  "@clack/core": { category: "infra", priority: "medium", plugin: "clack" },
28654
28904
  "tree-sitter": { category: "infra", priority: "medium", plugin: "tree-sitter" },
28905
+ "web-tree-sitter": { category: "infra", priority: "medium", plugin: "tree-sitter" },
28906
+ "tree-sitter-wasms": { category: "infra", priority: "low", plugin: "tree-sitter" },
28655
28907
  "n8n-workflow": { category: "infra", priority: "high", plugin: "n8n" },
28656
28908
  // --- JavaScript / npm: Build tools (with plugin) ---
28657
28909
  "tsup": { category: "infra", priority: "low", plugin: "build-tools" },
@@ -29621,7 +29873,7 @@ function registerSessionTools(server, ctx) {
29621
29873
  }
29622
29874
 
29623
29875
  // src/server/server.ts
29624
- var PKG_VERSION = true ? "1.5.3" : "0.0.0-dev";
29876
+ var PKG_VERSION = true ? "1.6.0" : "0.0.0-dev";
29625
29877
  function j2(value) {
29626
29878
  return JSON.stringify(value, (_key, val) => val === null || val === void 0 ? void 0 : val);
29627
29879
  }
@@ -29894,9 +30146,76 @@ function createServer2(store, registry, config, rootPath) {
29894
30146
  }
29895
30147
 
29896
30148
  // src/indexer/plugins/language/php/index.ts
29897
- import { createRequire } from "module";
29898
30149
  import { ok as ok9, err as err12 } from "neverthrow";
29899
30150
 
30151
+ // src/parser/tree-sitter.ts
30152
+ import Parser from "web-tree-sitter";
30153
+ import { createRequire } from "module";
30154
+ var initPromise = null;
30155
+ var languageCache = /* @__PURE__ */ new Map();
30156
+ var parserCache = /* @__PURE__ */ new Map();
30157
+ var LANG_WASM_MAP = {
30158
+ bash: "tree-sitter-bash.wasm",
30159
+ c: "tree-sitter-c.wasm",
30160
+ cpp: "tree-sitter-cpp.wasm",
30161
+ csharp: "tree-sitter-c_sharp.wasm",
30162
+ css: "tree-sitter-css.wasm",
30163
+ dart: "tree-sitter-dart.wasm",
30164
+ elisp: "tree-sitter-elisp.wasm",
30165
+ elixir: "tree-sitter-elixir.wasm",
30166
+ elm: "tree-sitter-elm.wasm",
30167
+ embedded_template: "tree-sitter-embedded_template.wasm",
30168
+ go: "tree-sitter-go.wasm",
30169
+ html: "tree-sitter-html.wasm",
30170
+ java: "tree-sitter-java.wasm",
30171
+ javascript: "tree-sitter-javascript.wasm",
30172
+ json: "tree-sitter-json.wasm",
30173
+ kotlin: "tree-sitter-kotlin.wasm",
30174
+ lua: "tree-sitter-lua.wasm",
30175
+ objc: "tree-sitter-objc.wasm",
30176
+ ocaml: "tree-sitter-ocaml.wasm",
30177
+ php: "tree-sitter-php.wasm",
30178
+ python: "tree-sitter-python.wasm",
30179
+ ql: "tree-sitter-ql.wasm",
30180
+ rescript: "tree-sitter-rescript.wasm",
30181
+ ruby: "tree-sitter-ruby.wasm",
30182
+ rust: "tree-sitter-rust.wasm",
30183
+ scala: "tree-sitter-scala.wasm",
30184
+ solidity: "tree-sitter-solidity.wasm",
30185
+ swift: "tree-sitter-swift.wasm",
30186
+ systemrdl: "tree-sitter-systemrdl.wasm",
30187
+ tlaplus: "tree-sitter-tlaplus.wasm",
30188
+ toml: "tree-sitter-toml.wasm",
30189
+ tsx: "tree-sitter-tsx.wasm",
30190
+ typescript: "tree-sitter-typescript.wasm",
30191
+ vue: "tree-sitter-vue.wasm",
30192
+ yaml: "tree-sitter-yaml.wasm",
30193
+ zig: "tree-sitter-zig.wasm"
30194
+ };
30195
+ var _require = createRequire(import.meta.url);
30196
+ function ensureInit() {
30197
+ if (!initPromise) {
30198
+ initPromise = Parser.init();
30199
+ }
30200
+ return initPromise;
30201
+ }
30202
+ async function getParser(language) {
30203
+ await ensureInit();
30204
+ if (parserCache.has(language)) return parserCache.get(language);
30205
+ const wasmFile = LANG_WASM_MAP[language];
30206
+ if (!wasmFile) throw new Error(`Unsupported tree-sitter language: ${language}`);
30207
+ let lang = languageCache.get(language);
30208
+ if (!lang) {
30209
+ const wasmPath = _require.resolve(`tree-sitter-wasms/out/${wasmFile}`);
30210
+ lang = await Parser.Language.load(wasmPath);
30211
+ languageCache.set(language, lang);
30212
+ }
30213
+ const parser = new Parser();
30214
+ parser.setLanguage(lang);
30215
+ parserCache.set(language, parser);
30216
+ return parser;
30217
+ }
30218
+
29900
30219
  // src/indexer/plugins/language/php/helpers.ts
29901
30220
  function extractNamespace(rootNode) {
29902
30221
  for (const child of rootNode.namedChildren) {
@@ -30152,17 +30471,6 @@ function detectMinPhpVersion(nodeTypes) {
30152
30471
  }
30153
30472
 
30154
30473
  // src/indexer/plugins/language/php/index.ts
30155
- var require2 = createRequire(import.meta.url);
30156
- var Parser = require2("tree-sitter");
30157
- var PhpGrammar = require2("tree-sitter-php");
30158
- var parserInstance = null;
30159
- function getParser() {
30160
- if (!parserInstance) {
30161
- parserInstance = new Parser();
30162
- parserInstance.setLanguage(PhpGrammar.php);
30163
- }
30164
- return parserInstance;
30165
- }
30166
30474
  var PhpLanguagePlugin = class {
30167
30475
  manifest = {
30168
30476
  name: "php-language",
@@ -30189,9 +30497,9 @@ var PhpLanguagePlugin = class {
30189
30497
  "8.3",
30190
30498
  "8.4"
30191
30499
  ];
30192
- extractSymbols(filePath, content) {
30500
+ async extractSymbols(filePath, content) {
30193
30501
  try {
30194
- const parser = getParser();
30502
+ const parser = await getParser("php");
30195
30503
  const sourceCode = content.toString("utf-8");
30196
30504
  const tree = parser.parse(sourceCode);
30197
30505
  const root = tree.rootNode;
@@ -30416,7 +30724,6 @@ var PhpLanguagePlugin = class {
30416
30724
  };
30417
30725
 
30418
30726
  // src/indexer/plugins/language/typescript/index.ts
30419
- import { createRequire as createRequire2 } from "module";
30420
30727
  import { ok as ok10, err as err13 } from "neverthrow";
30421
30728
 
30422
30729
  // src/indexer/plugins/language/typescript/helpers.ts
@@ -30738,25 +31045,6 @@ function detectMinEsVersion(nodeTypes) {
30738
31045
  }
30739
31046
 
30740
31047
  // src/indexer/plugins/language/typescript/index.ts
30741
- var require3 = createRequire2(import.meta.url);
30742
- var Parser2 = require3("tree-sitter");
30743
- var TsGrammar = require3("tree-sitter-typescript");
30744
- var tsParser = null;
30745
- var tsxParser = null;
30746
- function getParser2(tsx) {
30747
- if (tsx) {
30748
- if (!tsxParser) {
30749
- tsxParser = new Parser2();
30750
- tsxParser.setLanguage(TsGrammar.tsx);
30751
- }
30752
- return tsxParser;
30753
- }
30754
- if (!tsParser) {
30755
- tsParser = new Parser2();
30756
- tsParser.setLanguage(TsGrammar.typescript);
30757
- }
30758
- return tsParser;
30759
- }
30760
31048
  var TSX_EXTENSIONS = /* @__PURE__ */ new Set([".tsx", ".jsx"]);
30761
31049
  var JS_EXTENSIONS = /* @__PURE__ */ new Set([".js", ".jsx", ".mjs", ".cjs"]);
30762
31050
  var TypeScriptLanguagePlugin = class {
@@ -30767,11 +31055,11 @@ var TypeScriptLanguagePlugin = class {
30767
31055
  };
30768
31056
  supportedExtensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
30769
31057
  supportedVersions = ["12", "14", "16", "17", "18", "19", "20", "21", "22", "23", "24"];
30770
- extractSymbols(filePath, content) {
31058
+ async extractSymbols(filePath, content) {
30771
31059
  try {
30772
31060
  const ext = filePath.substring(filePath.lastIndexOf("."));
30773
31061
  const useTsx = TSX_EXTENSIONS.has(ext);
30774
- const parser = getParser2(useTsx);
31062
+ const parser = await getParser(useTsx ? "tsx" : "typescript");
30775
31063
  const sourceCode = content.toString("utf-8");
30776
31064
  const tree = parser.parse(sourceCode);
30777
31065
  const root = tree.rootNode;
@@ -31022,7 +31310,6 @@ var TypeScriptLanguagePlugin = class {
31022
31310
  };
31023
31311
 
31024
31312
  // src/indexer/plugins/language/vue/index.ts
31025
- import { createRequire as createRequire3 } from "module";
31026
31313
  import { parse as parseSFC } from "@vue/compiler-sfc";
31027
31314
  import { ok as ok11, err as err14 } from "neverthrow";
31028
31315
 
@@ -31321,17 +31608,6 @@ function componentNameFromPath(filePath) {
31321
31608
  }
31322
31609
 
31323
31610
  // src/indexer/plugins/language/vue/index.ts
31324
- var require4 = createRequire3(import.meta.url);
31325
- var Parser3 = require4("tree-sitter");
31326
- var TsGrammar2 = require4("tree-sitter-typescript");
31327
- var tsParser2 = null;
31328
- function getParser3() {
31329
- if (!tsParser2) {
31330
- tsParser2 = new Parser3();
31331
- tsParser2.setLanguage(TsGrammar2.typescript);
31332
- }
31333
- return tsParser2;
31334
- }
31335
31611
  var VueLanguagePlugin = class {
31336
31612
  manifest = {
31337
31613
  name: "vue-language",
@@ -31339,7 +31615,7 @@ var VueLanguagePlugin = class {
31339
31615
  priority: 10
31340
31616
  };
31341
31617
  supportedExtensions = [".vue"];
31342
- extractSymbols(filePath, content) {
31618
+ async extractSymbols(filePath, content) {
31343
31619
  try {
31344
31620
  const sourceCode = content.toString("utf-8");
31345
31621
  const { descriptor, errors } = parseSFC(sourceCode, {
@@ -31378,14 +31654,14 @@ var VueLanguagePlugin = class {
31378
31654
  emits = extractEmits(setupContent);
31379
31655
  exposed = extractExposed(setupContent);
31380
31656
  composables = extractComposables(setupContent);
31381
- const setupEdges = this.parseScriptEdges(setupContent);
31657
+ const setupEdges = await this.parseScriptEdges(setupContent);
31382
31658
  edges.push(...setupEdges);
31383
31659
  }
31384
31660
  if (descriptor.script) {
31385
31661
  const scriptContent = descriptor.script.content;
31386
- const scriptSymbols = this.parseScriptSymbols(scriptContent, filePath);
31662
+ const scriptSymbols = await this.parseScriptSymbols(scriptContent, filePath);
31387
31663
  symbols.push(...scriptSymbols);
31388
- const scriptEdges = this.parseScriptEdges(scriptContent);
31664
+ const scriptEdges = await this.parseScriptEdges(scriptContent);
31389
31665
  edges.push(...scriptEdges);
31390
31666
  }
31391
31667
  let templateComponents = [];
@@ -31426,9 +31702,9 @@ var VueLanguagePlugin = class {
31426
31702
  /**
31427
31703
  * Parse a script block with tree-sitter to extract import edges.
31428
31704
  */
31429
- parseScriptEdges(scriptContent) {
31705
+ async parseScriptEdges(scriptContent) {
31430
31706
  try {
31431
- const parser = getParser3();
31707
+ const parser = await getParser("typescript");
31432
31708
  const tree = parser.parse(scriptContent);
31433
31709
  return extractImportEdges(tree.rootNode);
31434
31710
  } catch {
@@ -31439,9 +31715,9 @@ var VueLanguagePlugin = class {
31439
31715
  * Parse a <script> block with tree-sitter to extract top-level symbols.
31440
31716
  * Used for Options API / non-setup scripts.
31441
31717
  */
31442
- parseScriptSymbols(scriptContent, filePath) {
31718
+ async parseScriptSymbols(scriptContent, filePath) {
31443
31719
  try {
31444
- const parser = getParser3();
31720
+ const parser = await getParser("typescript");
31445
31721
  const tree = parser.parse(scriptContent);
31446
31722
  const root = tree.rootNode;
31447
31723
  const symbols = [];
@@ -31502,7 +31778,6 @@ var VueLanguagePlugin = class {
31502
31778
  };
31503
31779
 
31504
31780
  // src/indexer/plugins/language/python/index.ts
31505
- import { createRequire as createRequire4 } from "module";
31506
31781
  import { ok as ok12, err as err15 } from "neverthrow";
31507
31782
 
31508
31783
  // src/indexer/plugins/language/python/helpers.ts
@@ -31831,17 +32106,6 @@ function detectMinPythonVersion(nodeTypes) {
31831
32106
  }
31832
32107
 
31833
32108
  // src/indexer/plugins/language/python/index.ts
31834
- var require5 = createRequire4(import.meta.url);
31835
- var Parser4 = require5("tree-sitter");
31836
- var PythonGrammar = require5("tree-sitter-python");
31837
- var parserInstance2 = null;
31838
- function getParser4() {
31839
- if (!parserInstance2) {
31840
- parserInstance2 = new Parser4();
31841
- parserInstance2.setLanguage(PythonGrammar);
31842
- }
31843
- return parserInstance2;
31844
- }
31845
32109
  var PythonLanguagePlugin = class {
31846
32110
  manifest = {
31847
32111
  name: "python-language",
@@ -31867,9 +32131,9 @@ var PythonLanguagePlugin = class {
31867
32131
  "3.13",
31868
32132
  "3.14"
31869
32133
  ];
31870
- extractSymbols(filePath, content) {
32134
+ async extractSymbols(filePath, content) {
31871
32135
  try {
31872
- const parser = getParser4();
32136
+ const parser = await getParser("python");
31873
32137
  const sourceCode = content.toString("utf-8");
31874
32138
  const tree = parser.parse(sourceCode);
31875
32139
  const root = tree.rootNode;
@@ -32140,7 +32404,6 @@ var PythonLanguagePlugin = class {
32140
32404
  };
32141
32405
 
32142
32406
  // src/indexer/plugins/language/java/index.ts
32143
- import { createRequire as createRequire5 } from "module";
32144
32407
  import { ok as ok13, err as err16 } from "neverthrow";
32145
32408
 
32146
32409
  // src/indexer/plugins/language/java/version-features.ts
@@ -32441,17 +32704,6 @@ function findChildByType(node, type) {
32441
32704
  }
32442
32705
 
32443
32706
  // src/indexer/plugins/language/java/index.ts
32444
- var require6 = createRequire5(import.meta.url);
32445
- var Parser5 = require6("tree-sitter");
32446
- var JavaGrammar = require6("tree-sitter-java");
32447
- var parserInstance3 = null;
32448
- function getParser5() {
32449
- if (!parserInstance3) {
32450
- parserInstance3 = new Parser5();
32451
- parserInstance3.setLanguage(JavaGrammar);
32452
- }
32453
- return parserInstance3;
32454
- }
32455
32707
  var JavaLanguagePlugin = class {
32456
32708
  manifest = {
32457
32709
  name: "java-language",
@@ -32460,9 +32712,9 @@ var JavaLanguagePlugin = class {
32460
32712
  };
32461
32713
  supportedExtensions = [".java"];
32462
32714
  supportedVersions = ["8", "9", "10", "11", "14", "15", "16", "17", "21", "22", "23"];
32463
- extractSymbols(filePath, content) {
32715
+ async extractSymbols(filePath, content) {
32464
32716
  try {
32465
- const parser = getParser5();
32717
+ const parser = await getParser("java");
32466
32718
  const sourceCode = content.toString("utf-8");
32467
32719
  const tree = parser.parse(sourceCode);
32468
32720
  const root = tree.rootNode;
@@ -32806,7 +33058,6 @@ var KotlinLanguagePlugin = class {
32806
33058
  };
32807
33059
 
32808
33060
  // src/indexer/plugins/language/ruby/index.ts
32809
- import { createRequire as createRequire6 } from "module";
32810
33061
  import { ok as ok15, err as err18 } from "neverthrow";
32811
33062
 
32812
33063
  // src/indexer/plugins/language/ruby/version-features.ts
@@ -33057,17 +33308,6 @@ function extractConstants(body, filePath, containerName, containerSymbolId, name
33057
33308
  }
33058
33309
 
33059
33310
  // src/indexer/plugins/language/ruby/index.ts
33060
- var require7 = createRequire6(import.meta.url);
33061
- var Parser6 = require7("tree-sitter");
33062
- var RubyGrammar = require7("tree-sitter-ruby");
33063
- var parserInstance4 = null;
33064
- function getParser6() {
33065
- if (!parserInstance4) {
33066
- parserInstance4 = new Parser6();
33067
- parserInstance4.setLanguage(RubyGrammar);
33068
- }
33069
- return parserInstance4;
33070
- }
33071
33311
  var RubyLanguagePlugin = class {
33072
33312
  manifest = {
33073
33313
  name: "ruby-language",
@@ -33076,9 +33316,9 @@ var RubyLanguagePlugin = class {
33076
33316
  };
33077
33317
  supportedExtensions = [".rb", ".rake"];
33078
33318
  supportedVersions = ["2.0", "2.3", "2.5", "2.6", "2.7", "3.0", "3.1", "3.2", "3.3"];
33079
- extractSymbols(filePath, content) {
33319
+ async extractSymbols(filePath, content) {
33080
33320
  try {
33081
- const parser = getParser6();
33321
+ const parser = await getParser("ruby");
33082
33322
  const sourceCode = content.toString("utf-8");
33083
33323
  const tree = parser.parse(sourceCode);
33084
33324
  const root = tree.rootNode;
@@ -33215,7 +33455,6 @@ var RubyLanguagePlugin = class {
33215
33455
  };
33216
33456
 
33217
33457
  // src/indexer/plugins/language/go/index.ts
33218
- import { createRequire as createRequire7 } from "module";
33219
33458
  import { ok as ok16, err as err19 } from "neverthrow";
33220
33459
 
33221
33460
  // src/indexer/plugins/language/go/version-features.ts
@@ -33386,17 +33625,6 @@ function extractInterfaceMethods(body, filePath, ifaceName, ifaceSymbolId) {
33386
33625
  }
33387
33626
 
33388
33627
  // src/indexer/plugins/language/go/index.ts
33389
- var require8 = createRequire7(import.meta.url);
33390
- var Parser7 = require8("tree-sitter");
33391
- var GoGrammar = require8("tree-sitter-go");
33392
- var parserInstance5 = null;
33393
- function getParser7() {
33394
- if (!parserInstance5) {
33395
- parserInstance5 = new Parser7();
33396
- parserInstance5.setLanguage(GoGrammar);
33397
- }
33398
- return parserInstance5;
33399
- }
33400
33628
  var GoLanguagePlugin = class {
33401
33629
  manifest = {
33402
33630
  name: "go-language",
@@ -33405,9 +33633,9 @@ var GoLanguagePlugin = class {
33405
33633
  };
33406
33634
  supportedExtensions = [".go"];
33407
33635
  supportedVersions = ["1.11", "1.13", "1.14", "1.16", "1.17", "1.18", "1.19", "1.20", "1.21", "1.22", "1.23"];
33408
- extractSymbols(filePath, content) {
33636
+ async extractSymbols(filePath, content) {
33409
33637
  try {
33410
- const parser = getParser7();
33638
+ const parser = await getParser("go");
33411
33639
  const sourceCode = content.toString("utf-8");
33412
33640
  const tree = parser.parse(sourceCode);
33413
33641
  const root = tree.rootNode;
@@ -33957,7 +34185,6 @@ function lineAt2(source, offset) {
33957
34185
  }
33958
34186
 
33959
34187
  // src/indexer/plugins/language/rust/index.ts
33960
- import { createRequire as createRequire8 } from "module";
33961
34188
  import { ok as ok19, err as err20 } from "neverthrow";
33962
34189
 
33963
34190
  // src/indexer/plugins/language/rust/helpers.ts
@@ -34161,17 +34388,6 @@ function extractTraitMethods(body, filePath, traitName, traitSymbolId) {
34161
34388
  }
34162
34389
 
34163
34390
  // src/indexer/plugins/language/rust/index.ts
34164
- var require9 = createRequire8(import.meta.url);
34165
- var Parser8 = require9("tree-sitter");
34166
- var RustGrammar = require9("tree-sitter-rust");
34167
- var parserInstance6 = null;
34168
- function getParser8() {
34169
- if (!parserInstance6) {
34170
- parserInstance6 = new Parser8();
34171
- parserInstance6.setLanguage(RustGrammar);
34172
- }
34173
- return parserInstance6;
34174
- }
34175
34391
  var RustLanguagePlugin = class {
34176
34392
  manifest = {
34177
34393
  name: "rust-language",
@@ -34179,9 +34395,9 @@ var RustLanguagePlugin = class {
34179
34395
  priority: 5
34180
34396
  };
34181
34397
  supportedExtensions = [".rs"];
34182
- extractSymbols(filePath, content) {
34398
+ async extractSymbols(filePath, content) {
34183
34399
  try {
34184
- const parser = getParser8();
34400
+ const parser = await getParser("rust");
34185
34401
  const sourceCode = content.toString("utf-8");
34186
34402
  const tree = parser.parse(sourceCode);
34187
34403
  const root = tree.rootNode;
@@ -34463,7 +34679,6 @@ var RustLanguagePlugin = class {
34463
34679
  };
34464
34680
 
34465
34681
  // src/indexer/plugins/language/c/index.ts
34466
- import { createRequire as createRequire9 } from "module";
34467
34682
  import { ok as ok20, err as err21 } from "neverthrow";
34468
34683
 
34469
34684
  // src/indexer/plugins/language/c/helpers.ts
@@ -34594,17 +34809,6 @@ function extractEnumConstants2(body, filePath, enumName, enumSymbolId) {
34594
34809
  }
34595
34810
 
34596
34811
  // src/indexer/plugins/language/c/index.ts
34597
- var require10 = createRequire9(import.meta.url);
34598
- var Parser9 = require10("tree-sitter");
34599
- var CGrammar = require10("tree-sitter-c");
34600
- var parserInstance7 = null;
34601
- function getParser9() {
34602
- if (!parserInstance7) {
34603
- parserInstance7 = new Parser9();
34604
- parserInstance7.setLanguage(CGrammar);
34605
- }
34606
- return parserInstance7;
34607
- }
34608
34812
  var CLanguagePlugin = class {
34609
34813
  manifest = {
34610
34814
  name: "c-language",
@@ -34612,9 +34816,9 @@ var CLanguagePlugin = class {
34612
34816
  priority: 5
34613
34817
  };
34614
34818
  supportedExtensions = [".c", ".h"];
34615
- extractSymbols(filePath, content) {
34819
+ async extractSymbols(filePath, content) {
34616
34820
  try {
34617
- const parser = getParser9();
34821
+ const parser = await getParser("c");
34618
34822
  const sourceCode = content.toString("utf-8");
34619
34823
  const tree = parser.parse(sourceCode);
34620
34824
  const root = tree.rootNode;
@@ -34881,7 +35085,6 @@ var CLanguagePlugin = class {
34881
35085
  };
34882
35086
 
34883
35087
  // src/indexer/plugins/language/cpp/index.ts
34884
- import { createRequire as createRequire10 } from "module";
34885
35088
  import { ok as ok21, err as err22 } from "neverthrow";
34886
35089
 
34887
35090
  // src/indexer/plugins/language/cpp/helpers.ts
@@ -35063,17 +35266,6 @@ function isVirtual(node) {
35063
35266
  }
35064
35267
 
35065
35268
  // src/indexer/plugins/language/cpp/index.ts
35066
- var require11 = createRequire10(import.meta.url);
35067
- var Parser10 = require11("tree-sitter");
35068
- var CppGrammar = require11("tree-sitter-cpp");
35069
- var parserInstance8 = null;
35070
- function getParser10() {
35071
- if (!parserInstance8) {
35072
- parserInstance8 = new Parser10();
35073
- parserInstance8.setLanguage(CppGrammar);
35074
- }
35075
- return parserInstance8;
35076
- }
35077
35269
  var CppLanguagePlugin = class {
35078
35270
  manifest = {
35079
35271
  name: "cpp-language",
@@ -35081,9 +35273,9 @@ var CppLanguagePlugin = class {
35081
35273
  priority: 5
35082
35274
  };
35083
35275
  supportedExtensions = [".cpp", ".cxx", ".cc", ".hpp", ".hxx", ".hh", ".h++"];
35084
- extractSymbols(filePath, content) {
35276
+ async extractSymbols(filePath, content) {
35085
35277
  try {
35086
- const parser = getParser10();
35278
+ const parser = await getParser("cpp");
35087
35279
  const sourceCode = content.toString("utf-8");
35088
35280
  const tree = parser.parse(sourceCode);
35089
35281
  const root = tree.rootNode;
@@ -35500,7 +35692,6 @@ var CppLanguagePlugin = class {
35500
35692
  };
35501
35693
 
35502
35694
  // src/indexer/plugins/language/csharp/index.ts
35503
- import { createRequire as createRequire11 } from "module";
35504
35695
  import { ok as ok22, err as err23 } from "neverthrow";
35505
35696
 
35506
35697
  // src/indexer/plugins/language/csharp/helpers.ts
@@ -35853,17 +36044,6 @@ function findChildByType2(node, type) {
35853
36044
  }
35854
36045
 
35855
36046
  // src/indexer/plugins/language/csharp/index.ts
35856
- var require12 = createRequire11(import.meta.url);
35857
- var Parser11 = require12("tree-sitter");
35858
- var CSharpGrammar = require12("tree-sitter-c-sharp");
35859
- var parserInstance9 = null;
35860
- function getParser11() {
35861
- if (!parserInstance9) {
35862
- parserInstance9 = new Parser11();
35863
- parserInstance9.setLanguage(CSharpGrammar);
35864
- }
35865
- return parserInstance9;
35866
- }
35867
36047
  var CSharpLanguagePlugin = class {
35868
36048
  manifest = {
35869
36049
  name: "csharp-language",
@@ -35883,9 +36063,9 @@ var CSharpLanguagePlugin = class {
35883
36063
  "12.0",
35884
36064
  "13.0"
35885
36065
  ];
35886
- extractSymbols(filePath, content) {
36066
+ async extractSymbols(filePath, content) {
35887
36067
  try {
35888
- const parser = getParser11();
36068
+ const parser = await getParser("csharp");
35889
36069
  const sourceCode = content.toString("utf-8");
35890
36070
  const tree = parser.parse(sourceCode);
35891
36071
  const root = tree.rootNode;
@@ -36509,7 +36689,6 @@ var DartLanguagePlugin = class {
36509
36689
  };
36510
36690
 
36511
36691
  // src/indexer/plugins/language/scala/index.ts
36512
- import { createRequire as createRequire12 } from "module";
36513
36692
  import { ok as ok25, err as err24 } from "neverthrow";
36514
36693
 
36515
36694
  // src/indexer/plugins/language/scala/helpers.ts
@@ -36874,17 +37053,6 @@ function extractValVarName(node) {
36874
37053
  }
36875
37054
 
36876
37055
  // src/indexer/plugins/language/scala/index.ts
36877
- var require13 = createRequire12(import.meta.url);
36878
- var Parser12 = require13("tree-sitter");
36879
- var ScalaGrammar = require13("tree-sitter-scala");
36880
- var parserInstance10 = null;
36881
- function getParser12() {
36882
- if (!parserInstance10) {
36883
- parserInstance10 = new Parser12();
36884
- parserInstance10.setLanguage(ScalaGrammar);
36885
- }
36886
- return parserInstance10;
36887
- }
36888
37056
  var ScalaLanguagePlugin = class {
36889
37057
  manifest = {
36890
37058
  name: "scala-language",
@@ -36893,9 +37061,9 @@ var ScalaLanguagePlugin = class {
36893
37061
  };
36894
37062
  supportedExtensions = [".scala", ".sc"];
36895
37063
  supportedVersions = ["2.11", "2.12", "2.13", "3.0", "3.1", "3.2", "3.3", "3.4", "3.5"];
36896
- extractSymbols(filePath, content) {
37064
+ async extractSymbols(filePath, content) {
36897
37065
  try {
36898
- const parser = getParser12();
37066
+ const parser = await getParser("scala");
36899
37067
  const sourceCode = content.toString("utf-8");
36900
37068
  const tree = parser.parse(sourceCode);
36901
37069
  const root = tree.rootNode;
@@ -45363,13 +45531,9 @@ var ExpressPlugin = class {
45363
45531
  };
45364
45532
 
45365
45533
  // src/indexer/plugins/integration/framework/fastapi/index.ts
45366
- import { createRequire as createRequire13 } from "module";
45367
45534
  import fs43 from "fs";
45368
45535
  import path55 from "path";
45369
45536
  import { ok as ok38, err as err25 } from "neverthrow";
45370
- var require14 = createRequire13(import.meta.url);
45371
- var Parser13 = require14("tree-sitter");
45372
- var PythonGrammar2 = require14("tree-sitter-python");
45373
45537
  var HTTP_METHODS3 = /* @__PURE__ */ new Set(["get", "post", "put", "delete", "patch", "options", "head"]);
45374
45538
  function hasPythonDep(ctx, pkg) {
45375
45539
  const lowerPkg = pkg.toLowerCase();
@@ -45416,7 +45580,7 @@ var FastAPIPlugin = class {
45416
45580
  ]
45417
45581
  };
45418
45582
  }
45419
- extractNodes(filePath, content, language) {
45583
+ async extractNodes(filePath, content, language) {
45420
45584
  if (language !== "python") {
45421
45585
  return ok38({ status: "ok", symbols: [] });
45422
45586
  }
@@ -45432,8 +45596,7 @@ var FastAPIPlugin = class {
45432
45596
  warnings: []
45433
45597
  };
45434
45598
  try {
45435
- const parser = new Parser13();
45436
- parser.setLanguage(PythonGrammar2);
45599
+ const parser = await getParser("python");
45437
45600
  const tree = parser.parse(source);
45438
45601
  const root = tree.rootNode;
45439
45602
  this.extractRoutes(root, source, filePath, result);
@@ -45680,13 +45843,9 @@ var FastAPIPlugin = class {
45680
45843
  };
45681
45844
 
45682
45845
  // src/indexer/plugins/integration/framework/flask/index.ts
45683
- import { createRequire as createRequire14 } from "module";
45684
45846
  import fs44 from "fs";
45685
45847
  import path56 from "path";
45686
45848
  import { ok as ok39, err as err26 } from "neverthrow";
45687
- var require15 = createRequire14(import.meta.url);
45688
- var Parser14 = require15("tree-sitter");
45689
- var PythonGrammar3 = require15("tree-sitter-python");
45690
45849
  var DEFAULT_METHODS = ["GET"];
45691
45850
  function hasPythonDep2(ctx, pkg) {
45692
45851
  const lowerPkg = pkg.toLowerCase();
@@ -45732,7 +45891,7 @@ var FlaskPlugin = class {
45732
45891
  ]
45733
45892
  };
45734
45893
  }
45735
- extractNodes(filePath, content, language) {
45894
+ async extractNodes(filePath, content, language) {
45736
45895
  if (language !== "python") {
45737
45896
  return ok39({ status: "ok", symbols: [] });
45738
45897
  }
@@ -45748,8 +45907,7 @@ var FlaskPlugin = class {
45748
45907
  warnings: []
45749
45908
  };
45750
45909
  try {
45751
- const parser = new Parser14();
45752
- parser.setLanguage(PythonGrammar3);
45910
+ const parser = await getParser("python");
45753
45911
  const tree = parser.parse(source);
45754
45912
  const root = tree.rootNode;
45755
45913
  this.extractRoutes(root, source, filePath, result);
@@ -47838,13 +47996,9 @@ function extractRefs(fields, sourceModelName) {
47838
47996
  }
47839
47997
 
47840
47998
  // src/indexer/plugins/integration/orm/sqlalchemy/index.ts
47841
- import { createRequire as createRequire15 } from "module";
47842
47999
  import fs53 from "fs";
47843
48000
  import path65 from "path";
47844
48001
  import { ok as ok43, err as err27 } from "neverthrow";
47845
- var require16 = createRequire15(import.meta.url);
47846
- var Parser15 = require16("tree-sitter");
47847
- var PythonGrammar4 = require16("tree-sitter-python");
47848
48002
  var MODEL_BASES = /* @__PURE__ */ new Set([
47849
48003
  "Base",
47850
48004
  "DeclarativeBase",
@@ -47895,7 +48049,7 @@ var SQLAlchemyPlugin = class {
47895
48049
  ]
47896
48050
  };
47897
48051
  }
47898
- extractNodes(filePath, content, language) {
48052
+ async extractNodes(filePath, content, language) {
47899
48053
  if (language !== "python") {
47900
48054
  return ok43({ status: "ok", symbols: [] });
47901
48055
  }
@@ -47913,8 +48067,7 @@ var SQLAlchemyPlugin = class {
47913
48067
  if (isAlembicMigration) {
47914
48068
  if (source.includes("op.create_table") || source.includes("op.add_column") || source.includes("op.drop_table")) {
47915
48069
  try {
47916
- const parser = new Parser15();
47917
- parser.setLanguage(PythonGrammar4);
48070
+ const parser = await getParser("python");
47918
48071
  const tree = parser.parse(source);
47919
48072
  this.extractAlembicMigrations(tree.rootNode, source, filePath, result);
47920
48073
  } catch (e) {
@@ -47929,8 +48082,7 @@ var SQLAlchemyPlugin = class {
47929
48082
  return ok43({ status: "ok", symbols: [] });
47930
48083
  }
47931
48084
  try {
47932
- const parser = new Parser15();
47933
- parser.setLanguage(PythonGrammar4);
48085
+ const parser = await getParser("python");
47934
48086
  const tree = parser.parse(source);
47935
48087
  const root = tree.rootNode;
47936
48088
  this.extractModels(root, source, filePath, result);
@@ -48550,27 +48702,7 @@ var RawSqlPlugin = class {
48550
48702
  };
48551
48703
 
48552
48704
  // src/indexer/plugins/integration/view/react/index.ts
48553
- import { createRequire as createRequire16 } from "module";
48554
48705
  import { ok as ok45, err as err28 } from "neverthrow";
48555
- var require17 = createRequire16(import.meta.url);
48556
- var Parser16 = require17("tree-sitter");
48557
- var TsGrammar3 = require17("tree-sitter-typescript");
48558
- var tsParser3 = null;
48559
- var tsxParser2 = null;
48560
- function getParser13(tsx) {
48561
- if (tsx) {
48562
- if (!tsxParser2) {
48563
- tsxParser2 = new Parser16();
48564
- tsxParser2.setLanguage(TsGrammar3.tsx);
48565
- }
48566
- return tsxParser2;
48567
- }
48568
- if (!tsParser3) {
48569
- tsParser3 = new Parser16();
48570
- tsParser3.setLanguage(TsGrammar3.typescript);
48571
- }
48572
- return tsParser3;
48573
- }
48574
48706
  var BUILTIN_HOOKS = /* @__PURE__ */ new Set([
48575
48707
  "useState",
48576
48708
  "useEffect",
@@ -48657,7 +48789,7 @@ var ReactPlugin = class {
48657
48789
  ]
48658
48790
  };
48659
48791
  }
48660
- extractNodes(filePath, content, language) {
48792
+ async extractNodes(filePath, content, language) {
48661
48793
  if (!["typescript", "typescriptreact", "javascript", "javascriptreact"].includes(language)) {
48662
48794
  return ok45({ status: "ok", symbols: [] });
48663
48795
  }
@@ -48674,7 +48806,7 @@ var ReactPlugin = class {
48674
48806
  this.extractDirectives(source, result);
48675
48807
  try {
48676
48808
  const useTsx = /\.(tsx|jsx)$/.test(filePath);
48677
- const parser = getParser13(useTsx);
48809
+ const parser = await getParser(useTsx ? "tsx" : "typescript");
48678
48810
  const tree = parser.parse(source);
48679
48811
  const root = tree.rootNode;
48680
48812
  for (const node of walk(root)) {
@@ -52076,21 +52208,9 @@ var TrpcPlugin = class {
52076
52208
  };
52077
52209
 
52078
52210
  // src/indexer/plugins/integration/api/drf/index.ts
52079
- import { createRequire as createRequire17 } from "module";
52080
52211
  import fs64 from "fs";
52081
52212
  import path76 from "path";
52082
52213
  import { ok as ok52, err as err29 } from "neverthrow";
52083
- var require18 = createRequire17(import.meta.url);
52084
- var Parser17 = require18("tree-sitter");
52085
- var PythonGrammar5 = require18("tree-sitter-python");
52086
- var parserInstance11 = null;
52087
- function getParser14() {
52088
- if (!parserInstance11) {
52089
- parserInstance11 = new Parser17();
52090
- parserInstance11.setLanguage(PythonGrammar5);
52091
- }
52092
- return parserInstance11;
52093
- }
52094
52214
  function hasPythonDep4(rootPath, depName) {
52095
52215
  for (const reqFile of ["requirements.txt", "requirements/base.txt", "requirements/prod.txt"]) {
52096
52216
  try {
@@ -52344,7 +52464,7 @@ var DRFPlugin = class {
52344
52464
  ]
52345
52465
  };
52346
52466
  }
52347
- extractNodes(filePath, content, language) {
52467
+ async extractNodes(filePath, content, language) {
52348
52468
  if (language !== "python") {
52349
52469
  return ok52({ status: "ok", symbols: [] });
52350
52470
  }
@@ -52357,7 +52477,7 @@ var DRFPlugin = class {
52357
52477
  };
52358
52478
  let tree;
52359
52479
  try {
52360
- const parser = getParser14();
52480
+ const parser = await getParser("python");
52361
52481
  tree = parser.parse(source);
52362
52482
  } catch (e) {
52363
52483
  return err29(parseError(filePath, `tree-sitter parse failed: ${e}`));
@@ -52620,21 +52740,9 @@ var ZodPlugin = class {
52620
52740
  };
52621
52741
 
52622
52742
  // src/indexer/plugins/integration/validation/pydantic/index.ts
52623
- import { createRequire as createRequire18 } from "module";
52624
52743
  import fs67 from "fs";
52625
52744
  import path79 from "path";
52626
52745
  import { ok as ok53, err as err30 } from "neverthrow";
52627
- var require19 = createRequire18(import.meta.url);
52628
- var Parser18 = require19("tree-sitter");
52629
- var PythonGrammar6 = require19("tree-sitter-python");
52630
- var parserInstance12 = null;
52631
- function getParser15() {
52632
- if (!parserInstance12) {
52633
- parserInstance12 = new Parser18();
52634
- parserInstance12.setLanguage(PythonGrammar6);
52635
- }
52636
- return parserInstance12;
52637
- }
52638
52746
  function hasPythonDep5(rootPath, depName) {
52639
52747
  for (const reqFile of ["requirements.txt", "requirements/base.txt", "requirements/prod.txt"]) {
52640
52748
  try {
@@ -52954,7 +53062,7 @@ var PydanticPlugin = class {
52954
53062
  ]
52955
53063
  };
52956
53064
  }
52957
- extractNodes(filePath, content, language) {
53065
+ async extractNodes(filePath, content, language) {
52958
53066
  if (language !== "python") {
52959
53067
  return ok53({ status: "ok", symbols: [] });
52960
53068
  }
@@ -52966,7 +53074,7 @@ var PydanticPlugin = class {
52966
53074
  };
52967
53075
  let tree;
52968
53076
  try {
52969
- const parser = getParser15();
53077
+ const parser = await getParser("python");
52970
53078
  tree = parser.parse(source);
52971
53079
  } catch (e) {
52972
53080
  return err30(parseError(filePath, `tree-sitter parse failed: ${e}`));
@@ -53492,21 +53600,9 @@ var TestingPlugin = class {
53492
53600
  };
53493
53601
 
53494
53602
  // src/indexer/plugins/integration/tooling/celery/index.ts
53495
- import { createRequire as createRequire19 } from "module";
53496
53603
  import fs70 from "fs";
53497
53604
  import path82 from "path";
53498
53605
  import { ok as ok55, err as err31 } from "neverthrow";
53499
- var require20 = createRequire19(import.meta.url);
53500
- var Parser19 = require20("tree-sitter");
53501
- var PythonGrammar7 = require20("tree-sitter-python");
53502
- var parserInstance13 = null;
53503
- function getParser16() {
53504
- if (!parserInstance13) {
53505
- parserInstance13 = new Parser19();
53506
- parserInstance13.setLanguage(PythonGrammar7);
53507
- }
53508
- return parserInstance13;
53509
- }
53510
53606
  function hasPythonDep6(rootPath, depName) {
53511
53607
  for (const reqFile of ["requirements.txt", "requirements/base.txt", "requirements/prod.txt"]) {
53512
53608
  try {
@@ -53684,7 +53780,7 @@ var CeleryPlugin = class {
53684
53780
  ]
53685
53781
  };
53686
53782
  }
53687
- extractNodes(filePath, content, language) {
53783
+ async extractNodes(filePath, content, language) {
53688
53784
  if (language !== "python") {
53689
53785
  return ok55({ status: "ok", symbols: [] });
53690
53786
  }
@@ -53697,7 +53793,7 @@ var CeleryPlugin = class {
53697
53793
  };
53698
53794
  let tree;
53699
53795
  try {
53700
- const parser = getParser16();
53796
+ const parser = await getParser("python");
53701
53797
  tree = parser.parse(source);
53702
53798
  } catch (e) {
53703
53799
  return err31(parseError(filePath, `tree-sitter parse failed: ${e}`));
@@ -55319,6 +55415,7 @@ import path86 from "path";
55319
55415
  var TREE_SITTER_PACKAGES = [
55320
55416
  "tree-sitter",
55321
55417
  "web-tree-sitter",
55418
+ "tree-sitter-wasms",
55322
55419
  "tree-sitter-typescript",
55323
55420
  "tree-sitter-javascript",
55324
55421
  "tree-sitter-python",
@@ -56387,8 +56484,12 @@ function clientExists(client) {
56387
56484
  }
56388
56485
  function findHookSource(scriptName) {
56389
56486
  const filename = `${scriptName}${HOOK_EXT}`;
56487
+ const base = import.meta.dirname ?? ".";
56390
56488
  const candidates = [
56391
- path95.resolve(import.meta.dirname ?? ".", "..", "..", "hooks", filename),
56489
+ path95.resolve(base, "..", "..", "hooks", filename),
56490
+ // dev: src/init/ → ../../hooks
56491
+ path95.resolve(base, "..", "hooks", filename),
56492
+ // bundled: dist/ → ../hooks
56392
56493
  path95.resolve(process.cwd(), "hooks", filename)
56393
56494
  ];
56394
56495
  for (const c of candidates) {
@@ -57663,6 +57764,31 @@ var ROOT_MARKERS = [
57663
57764
  "build.gradle",
57664
57765
  "build.gradle.kts"
57665
57766
  ];
57767
+ var SKIP_DIRS2 = /* @__PURE__ */ new Set([".git", "node_modules", "vendor", ".svn", "__pycache__", ".tox"]);
57768
+ function discoverChildProjects(parentDir) {
57769
+ const absParent = path100.resolve(parentDir);
57770
+ if (!fs87.existsSync(absParent)) return [];
57771
+ let entries;
57772
+ try {
57773
+ entries = fs87.readdirSync(absParent, { withFileTypes: true });
57774
+ } catch {
57775
+ return [];
57776
+ }
57777
+ const children = [];
57778
+ for (const entry of entries) {
57779
+ if (!entry.isDirectory()) continue;
57780
+ if (entry.name.startsWith(".")) continue;
57781
+ if (SKIP_DIRS2.has(entry.name)) continue;
57782
+ const childDir = path100.join(absParent, entry.name);
57783
+ for (const marker of ROOT_MARKERS) {
57784
+ if (fs87.existsSync(path100.join(childDir, marker))) {
57785
+ children.push(childDir);
57786
+ break;
57787
+ }
57788
+ }
57789
+ }
57790
+ return children.sort();
57791
+ }
57666
57792
  function findProjectRoot(from) {
57667
57793
  let dir = path100.resolve(from ?? process.cwd());
57668
57794
  while (true) {
@@ -57935,10 +58061,10 @@ function saveRegistry(reg) {
57935
58061
  fs88.writeFileSync(tmp, JSON.stringify(reg, null, 2) + "\n");
57936
58062
  fs88.renameSync(tmp, REGISTRY_PATH);
57937
58063
  }
57938
- function registerProject(root) {
58064
+ function registerProject(root, opts) {
57939
58065
  const absRoot = path101.resolve(root);
57940
58066
  const reg = loadRegistry2();
57941
- if (reg.projects[absRoot]) {
58067
+ if (reg.projects[absRoot] && !opts) {
57942
58068
  return reg.projects[absRoot];
57943
58069
  }
57944
58070
  const entry = {
@@ -57946,12 +58072,30 @@ function registerProject(root) {
57946
58072
  root: absRoot,
57947
58073
  dbPath: getDbPath(absRoot),
57948
58074
  lastIndexed: null,
57949
- addedAt: (/* @__PURE__ */ new Date()).toISOString()
58075
+ addedAt: (/* @__PURE__ */ new Date()).toISOString(),
58076
+ ...opts?.type && { type: opts.type },
58077
+ ...opts?.children && { children: opts.children }
57950
58078
  };
57951
58079
  reg.projects[absRoot] = entry;
57952
58080
  saveRegistry(reg);
57953
58081
  return entry;
57954
58082
  }
58083
+ function findParentProject(childRoot) {
58084
+ const absChild = path101.resolve(childRoot);
58085
+ const reg = loadRegistry2();
58086
+ for (const entry of Object.values(reg.projects)) {
58087
+ if (entry.type === "multi-root" && entry.children?.includes(absChild)) {
58088
+ return entry;
58089
+ }
58090
+ }
58091
+ return null;
58092
+ }
58093
+ function unregisterProject(root) {
58094
+ const absRoot = path101.resolve(root);
58095
+ const reg = loadRegistry2();
58096
+ delete reg.projects[absRoot];
58097
+ saveRegistry(reg);
58098
+ }
57955
58099
  function getProject(root) {
57956
58100
  const absRoot = path101.resolve(root);
57957
58101
  const reg = loadRegistry2();
@@ -58239,11 +58383,17 @@ function executeSteps(steps, opts) {
58239
58383
  }
58240
58384
  }
58241
58385
  function registerAndIndexProject(dir, opts) {
58242
- let projectRoot;
58386
+ let projectRoot = null;
58243
58387
  try {
58244
58388
  projectRoot = findProjectRoot(dir);
58245
58389
  } catch {
58246
- return { target: dir, action: "skipped", detail: "Could not detect project root" };
58390
+ }
58391
+ if (!projectRoot) {
58392
+ const childRoots = discoverChildProjects(dir);
58393
+ if (childRoots.length === 0) {
58394
+ return { target: dir, action: "skipped", detail: "Could not detect project root or child projects" };
58395
+ }
58396
+ return registerMultiRootProject(dir, childRoots, opts);
58247
58397
  }
58248
58398
  if (opts.dryRun) {
58249
58399
  return { target: projectRoot, action: "skipped", detail: "Would register and index project" };
@@ -58269,6 +58419,52 @@ function registerAndIndexProject(dir, opts) {
58269
58419
  detail: `Registered project: ${entry.name}`
58270
58420
  };
58271
58421
  }
58422
+ function registerMultiRootProject(parentDir, childRoots, opts) {
58423
+ if (opts.dryRun) {
58424
+ return {
58425
+ target: parentDir,
58426
+ action: "skipped",
58427
+ detail: `Would register multi-root with ${childRoots.length} children: ${childRoots.map((r) => path102.basename(r)).join(", ")}`
58428
+ };
58429
+ }
58430
+ const existing = getProject(parentDir);
58431
+ if (existing && !opts.force) {
58432
+ return { target: parentDir, action: "already_configured", detail: `Multi-root already registered: ${existing.name}` };
58433
+ }
58434
+ const allInclude = [];
58435
+ const allExclude = [];
58436
+ for (const childRoot of childRoots) {
58437
+ const relPath = path102.relative(parentDir, childRoot).replace(/\\/g, "/");
58438
+ const detection = detectProject(childRoot);
58439
+ const config = generateConfig(detection);
58440
+ for (const pattern of config.include) allInclude.push(`${relPath}/${pattern}`);
58441
+ for (const pattern of config.exclude) allExclude.push(`${relPath}/${pattern}`);
58442
+ }
58443
+ const allProjects = listProjects();
58444
+ const parentPrefix = parentDir + path102.sep;
58445
+ for (const proj of allProjects) {
58446
+ if (proj.root !== parentDir && proj.root.startsWith(parentPrefix)) {
58447
+ if (fs89.existsSync(proj.dbPath)) fs89.unlinkSync(proj.dbPath);
58448
+ unregisterProject(proj.root);
58449
+ removeProjectConfig(proj.root);
58450
+ }
58451
+ }
58452
+ saveProjectConfig(parentDir, {
58453
+ root: ".",
58454
+ include: allInclude,
58455
+ exclude: allExclude,
58456
+ children: childRoots
58457
+ });
58458
+ const dbPath = getDbPath(parentDir);
58459
+ const db = initializeDatabase(dbPath);
58460
+ db.close();
58461
+ const entry = registerProject(parentDir, { type: "multi-root", children: childRoots });
58462
+ return {
58463
+ target: parentDir,
58464
+ action: existing ? "updated" : "created",
58465
+ detail: `Registered multi-root (${childRoots.length} children): ${childRoots.map((r) => path102.basename(r)).join(", ")}`
58466
+ };
58467
+ }
58272
58468
  function formatClientName(name) {
58273
58469
  const names = {
58274
58470
  "claude-code": "Claude Code",
@@ -58404,8 +58600,15 @@ var addCommand = new Command3("add").description("Register a project for indexin
58404
58600
  let projectRoot;
58405
58601
  try {
58406
58602
  projectRoot = findProjectRoot(resolvedDir);
58407
- } catch (e) {
58408
- console.error(e instanceof Error ? e.message : String(e));
58603
+ } catch {
58604
+ const children = discoverChildProjects(resolvedDir);
58605
+ if (children.length > 0) {
58606
+ await handleMultiRoot(resolvedDir, children, opts);
58607
+ return;
58608
+ }
58609
+ console.error(
58610
+ `Could not find project root from ${resolvedDir}, and no child projects discovered in subdirectories.`
58611
+ );
58409
58612
  process.exit(1);
58410
58613
  }
58411
58614
  const isInteractive = !opts.json;
@@ -58415,6 +58618,20 @@ var addCommand = new Command3("add").description("Register a project for indexin
58415
58618
  p2.note(`Detected project root: ${projectRoot}`, "Root");
58416
58619
  }
58417
58620
  }
58621
+ const parentEntry = findParentProject(projectRoot);
58622
+ if (parentEntry && !opts.force) {
58623
+ if (opts.json) {
58624
+ console.log(JSON.stringify({ status: "child_of_multi_root", parent: parentEntry }));
58625
+ } else {
58626
+ p2.note(
58627
+ `This project is already part of multi-root index: ${parentEntry.name}
58628
+ Root: ${parentEntry.root}`,
58629
+ "Multi-root"
58630
+ );
58631
+ p2.outro("Use --force to register it separately.");
58632
+ }
58633
+ return;
58634
+ }
58418
58635
  const existing = getProject(projectRoot);
58419
58636
  if (existing && !opts.force) {
58420
58637
  if (opts.json) {
@@ -58482,6 +58699,104 @@ DB: ${shortPath4(existing.dbPath)}`, "Existing");
58482
58699
  p2.outro("Project registered. It will be indexed when trace-mcp serve starts.");
58483
58700
  }
58484
58701
  });
58702
+ async function handleMultiRoot(parentDir, childRoots, opts) {
58703
+ const isInteractive = !opts.json;
58704
+ if (isInteractive) {
58705
+ p2.intro("trace-mcp add (multi-root)");
58706
+ p2.note(
58707
+ `No project root markers in ${parentDir}
58708
+ Discovered ${childRoots.length} child project(s):
58709
+ ` + childRoots.map((r) => ` ${path104.basename(r)}`).join("\n"),
58710
+ "Multi-root"
58711
+ );
58712
+ }
58713
+ const existing = getProject(parentDir);
58714
+ if (existing && !opts.force) {
58715
+ if (opts.json) {
58716
+ console.log(JSON.stringify({ status: "already_registered", project: existing }));
58717
+ } else {
58718
+ p2.note(`Already registered as multi-root: ${existing.name}`, "Existing");
58719
+ p2.outro("Use --force to re-register.");
58720
+ }
58721
+ return;
58722
+ }
58723
+ const mergedInclude = [];
58724
+ const mergedExclude = [];
58725
+ const allLanguages = /* @__PURE__ */ new Set();
58726
+ const allFrameworks = /* @__PURE__ */ new Set();
58727
+ for (const childRoot of childRoots) {
58728
+ const relPath = path104.relative(parentDir, childRoot).replace(/\\/g, "/");
58729
+ const detection = detectProject(childRoot);
58730
+ const config = generateConfig(detection);
58731
+ for (const pattern of config.include) {
58732
+ mergedInclude.push(`${relPath}/${pattern}`);
58733
+ }
58734
+ for (const pattern of config.exclude) {
58735
+ mergedExclude.push(`${relPath}/${pattern}`);
58736
+ }
58737
+ for (const lang of detection.languages) allLanguages.add(lang);
58738
+ for (const fw of detection.frameworks) allFrameworks.add(fw.name);
58739
+ }
58740
+ if (isInteractive) {
58741
+ const detectedLines = [];
58742
+ if (allLanguages.size > 0) {
58743
+ detectedLines.push(`Languages: ${[...allLanguages].join(", ")}`);
58744
+ }
58745
+ if (allFrameworks.size > 0) {
58746
+ detectedLines.push(`Frameworks: ${[...allFrameworks].join(", ")}`);
58747
+ }
58748
+ if (detectedLines.length > 0) {
58749
+ p2.note(detectedLines.join("\n"), "Detected (all children)");
58750
+ }
58751
+ }
58752
+ const allProjects = listProjects();
58753
+ const cleaned = [];
58754
+ for (const proj of allProjects) {
58755
+ if (proj.root.startsWith(parentDir + path104.sep) || proj.root.startsWith(parentDir + "/")) {
58756
+ if (fs91.existsSync(proj.dbPath)) {
58757
+ fs91.unlinkSync(proj.dbPath);
58758
+ }
58759
+ unregisterProject(proj.root);
58760
+ removeProjectConfig(proj.root);
58761
+ cleaned.push(path104.basename(proj.root));
58762
+ }
58763
+ }
58764
+ if (isInteractive && cleaned.length > 0) {
58765
+ p2.note(`Removed individual indexes: ${cleaned.join(", ")}`, "Cleanup");
58766
+ }
58767
+ ensureGlobalDirs();
58768
+ const configForSave = {
58769
+ root: ".",
58770
+ include: mergedInclude,
58771
+ exclude: mergedExclude,
58772
+ children: childRoots
58773
+ };
58774
+ saveProjectConfig(parentDir, configForSave);
58775
+ const dbPath = getDbPath(parentDir);
58776
+ const db = initializeDatabase(dbPath);
58777
+ db.close();
58778
+ const entry = registerProject(parentDir, {
58779
+ type: "multi-root",
58780
+ children: childRoots
58781
+ });
58782
+ if (opts.json) {
58783
+ console.log(JSON.stringify({
58784
+ status: existing ? "re-registered" : "registered",
58785
+ type: "multi-root",
58786
+ project: entry,
58787
+ children: childRoots.map((r) => path104.basename(r)),
58788
+ cleaned
58789
+ }, null, 2));
58790
+ } else {
58791
+ const lines = [];
58792
+ lines.push(`Project: ${entry.name} (multi-root)`);
58793
+ lines.push(`Root: ${parentDir}`);
58794
+ lines.push(`DB: ${shortPath4(dbPath)}`);
58795
+ lines.push(`Children: ${childRoots.map((r) => path104.basename(r)).join(", ")}`);
58796
+ p2.note(lines.join("\n"), existing ? "Re-registered" : "Registered");
58797
+ p2.outro("Multi-root project registered. It will be indexed when trace-mcp serve starts.");
58798
+ }
58799
+ }
58485
58800
  function shortPath4(p4) {
58486
58801
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
58487
58802
  if (home && p4.startsWith(home)) return "~" + p4.slice(home.length);
@@ -59594,7 +59909,7 @@ analyticsCommand.command("trends").description("Show daily usage trends: tokens,
59594
59909
  });
59595
59910
 
59596
59911
  // src/cli.ts
59597
- var PKG_VERSION2 = true ? "1.5.3" : "0.0.0-dev";
59912
+ var PKG_VERSION2 = true ? "1.6.0" : "0.0.0-dev";
59598
59913
  function registerDefaultPlugins(registry) {
59599
59914
  for (const p4 of createAllLanguagePlugins()) registry.registerLanguagePlugin(p4);
59600
59915
  for (const p4 of createAllIntegrationPlugins()) registry.registerFrameworkPlugin(p4);