@aiready/ast-mcp-server 0.1.1 → 0.1.3

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/index.cjs CHANGED
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
8
11
  var __export = (target, all) => {
9
12
  for (var name in all)
10
13
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -27,17 +30,121 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
30
  ));
28
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
32
 
33
+ // ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.21.0_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js
34
+ var getImportMetaUrl, importMetaUrl;
35
+ var init_cjs_shims = __esm({
36
+ "../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.21.0_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js"() {
37
+ "use strict";
38
+ getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
39
+ importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
40
+ }
41
+ });
42
+
43
+ // src/security.ts
44
+ function resolveWorkspaceRoot() {
45
+ return process.env.AST_WORKSPACE_ROOT || process.cwd();
46
+ }
47
+ function validateWorkspacePath(inputPath) {
48
+ const root = resolveWorkspaceRoot();
49
+ const resolved = import_path.default.resolve(root, inputPath);
50
+ const normalized = import_path.default.normalize(resolved);
51
+ if (!normalized.startsWith(root)) {
52
+ throw new Error(
53
+ `Path traversal detected: ${inputPath} escapes workspace root`
54
+ );
55
+ }
56
+ if (normalized.includes("\0")) {
57
+ throw new Error("Path contains null bytes");
58
+ }
59
+ return normalized;
60
+ }
61
+ var import_path;
62
+ var init_security = __esm({
63
+ "src/security.ts"() {
64
+ "use strict";
65
+ init_cjs_shims();
66
+ import_path = __toESM(require("path"), 1);
67
+ }
68
+ });
69
+
70
+ // src/tools/search-code.ts
71
+ var search_code_exports = {};
72
+ __export(search_code_exports, {
73
+ searchCode: () => searchCode
74
+ });
75
+ async function searchCode(pattern, searchPath, filePattern, limit = 50, regex = true) {
76
+ const safePath = validateWorkspacePath(searchPath);
77
+ const args = [
78
+ "--json",
79
+ "--max-count",
80
+ limit.toString(),
81
+ "--max-columns",
82
+ "500"
83
+ ];
84
+ if (!regex) {
85
+ args.push("--fixed-strings");
86
+ }
87
+ args.push(pattern, safePath);
88
+ if (filePattern) {
89
+ args.push("--glob", filePattern);
90
+ }
91
+ args.push("--glob", "!**/node_modules/**");
92
+ args.push("--glob", "!**/dist/**");
93
+ args.push("--glob", "!**/.git/**");
94
+ try {
95
+ const { stdout } = await execFileAsync(import_ripgrep.rgPath, args);
96
+ const lines = stdout.split("\n").filter(Boolean);
97
+ const results = [];
98
+ for (const line of lines) {
99
+ const data = JSON.parse(line);
100
+ if (data.type === "match") {
101
+ const file = data.data.path.text;
102
+ const lineNumber = data.data.line_number;
103
+ const submatches = data.data.submatches;
104
+ for (const submatch of submatches) {
105
+ results.push({
106
+ file,
107
+ line: lineNumber,
108
+ column: submatch.start,
109
+ text: data.data.lines.text.trim()
110
+ });
111
+ }
112
+ }
113
+ }
114
+ return results.slice(0, limit);
115
+ } catch (error) {
116
+ if (error.code === 1) {
117
+ return [];
118
+ }
119
+ throw error;
120
+ }
121
+ }
122
+ var import_child_process, import_util, import_ripgrep, execFileAsync;
123
+ var init_search_code = __esm({
124
+ "src/tools/search-code.ts"() {
125
+ "use strict";
126
+ init_cjs_shims();
127
+ import_child_process = require("child_process");
128
+ import_util = require("util");
129
+ import_ripgrep = require("@vscode/ripgrep");
130
+ init_security();
131
+ execFileAsync = (0, import_util.promisify)(import_child_process.execFile);
132
+ }
133
+ });
134
+
30
135
  // src/index.ts
31
136
  var index_exports = {};
32
137
  __export(index_exports, {
33
138
  ASTExplorerServer: () => ASTExplorerServer
34
139
  });
35
140
  module.exports = __toCommonJS(index_exports);
141
+ init_cjs_shims();
36
142
  var import_server = require("@modelcontextprotocol/sdk/server/index.js");
37
143
  var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
38
144
  var import_types = require("@modelcontextprotocol/sdk/types.js");
39
145
 
40
146
  // src/schemas.ts
147
+ init_cjs_shims();
41
148
  var import_zod = require("zod");
42
149
  var ResolveDefinitionSchema = import_zod.z.object({
43
150
  symbol: import_zod.z.string().describe(
@@ -61,10 +168,11 @@ var GetFileStructureSchema = import_zod.z.object({
61
168
  file: import_zod.z.string().describe("Absolute path to the file to analyze")
62
169
  });
63
170
  var SearchCodeSchema = import_zod.z.object({
64
- pattern: import_zod.z.string().describe("Search pattern (regex)"),
171
+ pattern: import_zod.z.string().describe("Search pattern (regex by default)"),
65
172
  path: import_zod.z.string().describe("Directory to search in"),
66
173
  filePattern: import_zod.z.string().optional().describe('Glob filter (e.g., "*.ts")'),
67
- limit: import_zod.z.number().optional().default(50).describe("Max matches to return")
174
+ limit: import_zod.z.number().optional().default(50).describe("Max matches to return"),
175
+ regex: import_zod.z.boolean().optional().default(true).describe("Use regex mode (default true)")
68
176
  });
69
177
  var GetSymbolDocsSchema = import_zod.z.object({
70
178
  symbol: import_zod.z.string().describe("Symbol name to get documentation for"),
@@ -74,189 +182,555 @@ var BuildSymbolIndexSchema = import_zod.z.object({
74
182
  path: import_zod.z.string().describe("Project root directory to index")
75
183
  });
76
184
 
185
+ // src/tools/resolve-definition.ts
186
+ init_cjs_shims();
187
+
77
188
  // src/adapters/typescript-adapter.ts
78
- var import_ts_morph2 = require("ts-morph");
189
+ init_cjs_shims();
190
+ var import_ts_morph3 = require("ts-morph");
191
+ var import_fs3 = __toESM(require("fs"), 1);
79
192
 
80
193
  // src/project-manager.ts
194
+ init_cjs_shims();
81
195
  var import_ts_morph = require("ts-morph");
82
- var import_path = __toESM(require("path"), 1);
196
+ var import_path2 = __toESM(require("path"), 1);
83
197
  var import_fs = __toESM(require("fs"), 1);
84
198
  var import_glob = require("glob");
199
+ init_security();
85
200
  var ProjectManager = class {
86
201
  projects = /* @__PURE__ */ new Map();
87
202
  tsconfigCache = /* @__PURE__ */ new Map();
203
+ accessOrder = [];
204
+ // MRU at front
205
+ maxProjects = 4;
88
206
  /**
89
207
  * Find all tsconfig.json files in a directory (recursive)
90
208
  */
91
209
  async findTsConfigs(rootDir) {
92
- if (this.tsconfigCache.has(rootDir)) {
93
- return this.tsconfigCache.get(rootDir);
210
+ const safeRoot = validateWorkspacePath(rootDir);
211
+ if (this.tsconfigCache.has(safeRoot)) {
212
+ return this.tsconfigCache.get(safeRoot);
94
213
  }
95
214
  const configs = await (0, import_glob.glob)("**/tsconfig.json", {
96
- cwd: rootDir,
215
+ cwd: safeRoot,
97
216
  absolute: true,
98
217
  ignore: ["**/node_modules/**", "**/dist/**"]
99
218
  });
100
- this.tsconfigCache.set(rootDir, configs);
219
+ this.tsconfigCache.set(safeRoot, configs);
101
220
  return configs;
102
221
  }
103
222
  /**
104
- * Get or create a Project for a specific file path
105
- */
106
- async getProjectForFile(filePath) {
107
- const tsconfigPath = await this.findNearestTsConfig(filePath);
108
- if (!tsconfigPath) return void 0;
109
- return this.getOrCreateProject(tsconfigPath);
110
- }
111
- /**
112
- * Get or create a Project for a tsconfig path
223
+ * Ensure a Project exists for a given tsconfig path, managing LRU cache
113
224
  */
114
- getOrCreateProject(tsconfigPath) {
225
+ ensureProject(tsconfigPath) {
226
+ this.checkMemoryPressure();
115
227
  if (this.projects.has(tsconfigPath)) {
228
+ this.moveToFront(tsconfigPath);
116
229
  return this.projects.get(tsconfigPath);
117
230
  }
231
+ while (this.projects.size >= this.maxProjects) {
232
+ const oldest = this.accessOrder.pop();
233
+ this.disposeProject(oldest);
234
+ }
118
235
  const project = new import_ts_morph.Project({
119
236
  tsConfigFilePath: tsconfigPath,
120
- skipAddingFilesFromTsConfig: false
237
+ skipAddingFilesFromTsConfig: true
238
+ // KEY: don't load all files
121
239
  });
122
240
  this.projects.set(tsconfigPath, project);
241
+ this.accessOrder.unshift(tsconfigPath);
123
242
  return project;
124
243
  }
244
+ /**
245
+ * Move a tsconfig path to the front of the access order (MRU)
246
+ */
247
+ moveToFront(tsconfigPath) {
248
+ const index = this.accessOrder.indexOf(tsconfigPath);
249
+ if (index > -1) {
250
+ this.accessOrder.splice(index, 1);
251
+ this.accessOrder.unshift(tsconfigPath);
252
+ }
253
+ }
254
+ checkMemoryPressure() {
255
+ const heapUsed = process.memoryUsage().heapUsed / 1024 / 1024;
256
+ const maxHeap = parseInt(process.env.AST_MAX_HEAP_MB || "1536", 10);
257
+ while (heapUsed > maxHeap && this.projects.size > 1) {
258
+ const oldest = this.accessOrder.pop();
259
+ this.disposeProject(oldest);
260
+ }
261
+ }
262
+ disposeProject(tsconfigPath) {
263
+ const project = this.projects.get(tsconfigPath);
264
+ if (project) {
265
+ for (const sourceFile of project.getSourceFiles()) {
266
+ project.removeSourceFile(sourceFile);
267
+ }
268
+ this.projects.delete(tsconfigPath);
269
+ }
270
+ }
125
271
  /**
126
272
  * Find the nearest tsconfig.json for a file
127
273
  */
128
274
  async findNearestTsConfig(filePath) {
129
- let currentDir = import_path.default.dirname(filePath);
130
- const root = import_path.default.parse(currentDir).root;
275
+ const safePath = validateWorkspacePath(filePath);
276
+ let currentDir = import_path2.default.dirname(safePath);
277
+ const root = import_path2.default.parse(currentDir).root;
131
278
  while (currentDir !== root) {
132
- const tsconfigPath = import_path.default.join(currentDir, "tsconfig.json");
279
+ const tsconfigPath = import_path2.default.join(currentDir, "tsconfig.json");
133
280
  if (import_fs.default.existsSync(tsconfigPath)) {
134
281
  return tsconfigPath;
135
282
  }
136
- currentDir = import_path.default.dirname(currentDir);
283
+ currentDir = import_path2.default.dirname(currentDir);
137
284
  }
138
285
  return void 0;
139
286
  }
140
287
  /**
141
- * Get all projects that might contain a file or serve a path
288
+ * Get all tsconfigs for a path
142
289
  */
143
290
  async getProjectsForPath(rootDir) {
144
- const configs = await this.findTsConfigs(rootDir);
145
- return configs.map((config) => this.getOrCreateProject(config));
291
+ return this.findTsConfigs(rootDir);
146
292
  }
147
293
  /**
148
294
  * Dispose all projects to free memory
149
295
  */
150
296
  disposeAll() {
151
- for (const project of this.projects.values()) {
152
- project.getLanguageService().compilerObject.dispose();
297
+ for (const [key] of this.projects) {
298
+ this.disposeProject(key);
153
299
  }
154
- this.projects.clear();
300
+ this.accessOrder = [];
155
301
  }
156
302
  };
157
303
  var projectManager = new ProjectManager();
158
304
 
159
- // src/adapters/typescript-adapter.ts
160
- var TypeScriptAdapter = class {
305
+ // src/index/symbol-index.ts
306
+ init_cjs_shims();
307
+ init_security();
308
+ var import_fs2 = __toESM(require("fs"), 1);
309
+ var import_crypto = __toESM(require("crypto"), 1);
310
+ var import_path3 = __toESM(require("path"), 1);
311
+ var import_ts_morph2 = require("ts-morph");
312
+ var SymbolIndex = class {
313
+ index = {};
314
+ getCachePath(rootDir) {
315
+ const hash = import_crypto.default.createHash("sha256").update(rootDir).digest("hex").slice(0, 12);
316
+ return import_path3.default.join(
317
+ process.platform === "win32" ? process.env.TEMP || "c:/temp" : "/tmp",
318
+ `ast-index-${hash}.json`
319
+ );
320
+ }
321
+ isCacheValid(cached, rootDir) {
322
+ if (cached.rootDir !== rootDir) return false;
323
+ for (const [file, cachedMtime] of Object.entries(cached.fileHashes)) {
324
+ if (!import_fs2.default.existsSync(file)) return false;
325
+ if (import_fs2.default.statSync(file).mtimeMs !== cachedMtime) return false;
326
+ }
327
+ return true;
328
+ }
329
+ computeStats(cache, duration_ms, memory_mb) {
330
+ const files = Object.keys(cache.fileHashes).length;
331
+ let functions = 0;
332
+ let classes = 0;
333
+ let interfaces = 0;
334
+ let types = 0;
335
+ for (const entries of Object.values(cache.symbols)) {
336
+ for (const entry of entries) {
337
+ if (entry.kind === "function" || entry.kind === "method") functions++;
338
+ if (entry.kind === "class") classes++;
339
+ if (entry.kind === "interface") interfaces++;
340
+ if (entry.kind === "type_alias") types++;
341
+ }
342
+ }
343
+ return {
344
+ indexed: {
345
+ files,
346
+ functions,
347
+ classes,
348
+ interfaces,
349
+ types
350
+ },
351
+ duration_ms: duration_ms || 0,
352
+ memory_mb: memory_mb || 0
353
+ };
354
+ }
355
+ mapKind(node) {
356
+ if (import_ts_morph2.Node.isClassDeclaration(node)) return "class";
357
+ if (import_ts_morph2.Node.isFunctionDeclaration(node)) return "function";
358
+ if (import_ts_morph2.Node.isInterfaceDeclaration(node)) return "interface";
359
+ if (import_ts_morph2.Node.isTypeAliasDeclaration(node)) return "type_alias";
360
+ if (import_ts_morph2.Node.isEnumDeclaration(node)) return "enum";
361
+ if (import_ts_morph2.Node.isVariableDeclaration(node)) return "variable";
362
+ if (import_ts_morph2.Node.isMethodDeclaration(node)) return "method";
363
+ if (import_ts_morph2.Node.isPropertyDeclaration(node)) return "property";
364
+ if (import_ts_morph2.Node.isParameterDeclaration(node)) return "parameter";
365
+ return "variable";
366
+ }
161
367
  /**
162
- * Resolve definition of a symbol at a path
368
+ * Build/Warm the index for a given path
163
369
  */
164
- async resolveDefinition(symbolName, path2) {
165
- const projects = await projectManager.getProjectsForPath(path2);
166
- const results = [];
167
- for (const project of projects) {
168
- const sourceFiles = project.getSourceFiles();
169
- for (const sourceFile of sourceFiles) {
170
- const nodes = sourceFile.getDescendantsOfKind(import_ts_morph2.SyntaxKind.Identifier).filter((id) => id.getText() === symbolName);
171
- for (const node of nodes) {
172
- const definitions = node.getDefinitionNodes();
173
- for (const defNode of definitions) {
174
- results.push(this.mapToDefinitionLocation(defNode));
370
+ async buildIndex(rootDir) {
371
+ const startTime = Date.now();
372
+ const safeRoot = validateWorkspacePath(rootDir);
373
+ const cachePath = this.getCachePath(safeRoot);
374
+ if (import_fs2.default.existsSync(cachePath)) {
375
+ try {
376
+ const cached = JSON.parse(
377
+ import_fs2.default.readFileSync(cachePath, "utf-8")
378
+ );
379
+ if (this.isCacheValid(cached, safeRoot)) {
380
+ this.index = cached.symbols;
381
+ return this.computeStats(
382
+ cached,
383
+ Date.now() - startTime,
384
+ process.memoryUsage().heapUsed / 1024 / 1024
385
+ );
386
+ }
387
+ } catch (e) {
388
+ }
389
+ }
390
+ const tsconfigs = await projectManager.getProjectsForPath(safeRoot);
391
+ const symbols = {};
392
+ const fileHashes = {};
393
+ for (const config of tsconfigs) {
394
+ const project = projectManager.ensureProject(config);
395
+ project.addSourceFilesFromTsConfig(config);
396
+ for (const sourceFile of project.getSourceFiles()) {
397
+ const filePath = sourceFile.getFilePath();
398
+ try {
399
+ fileHashes[filePath] = import_fs2.default.statSync(filePath).mtimeMs;
400
+ } catch {
401
+ continue;
402
+ }
403
+ for (const [name, decls] of sourceFile.getExportedDeclarations()) {
404
+ for (const decl of decls) {
405
+ const entry = {
406
+ name,
407
+ kind: this.mapKind(decl),
408
+ file: filePath,
409
+ line: decl.getStartLineNumber(),
410
+ column: decl.getStart() - decl.getStartLinePos(),
411
+ exported: true
412
+ };
413
+ (symbols[name] ||= []).push(entry);
414
+ }
415
+ }
416
+ for (const fn of sourceFile.getFunctions()) {
417
+ const name = fn.getName();
418
+ if (name && !symbols[name]?.some(
419
+ (s) => s.file === filePath && s.line === fn.getStartLineNumber()
420
+ )) {
421
+ const entry = {
422
+ name,
423
+ kind: "function",
424
+ file: filePath,
425
+ line: fn.getStartLineNumber(),
426
+ column: fn.getStart() - fn.getStartLinePos(),
427
+ exported: false
428
+ };
429
+ (symbols[name] ||= []).push(entry);
430
+ }
431
+ }
432
+ for (const cls of sourceFile.getClasses()) {
433
+ const name = cls.getName();
434
+ if (name && !symbols[name]?.some(
435
+ (s) => s.file === filePath && s.line === cls.getStartLineNumber()
436
+ )) {
437
+ const entry = {
438
+ name,
439
+ kind: "class",
440
+ file: filePath,
441
+ line: cls.getStartLineNumber(),
442
+ column: cls.getStart() - cls.getStartLinePos(),
443
+ exported: false
444
+ };
445
+ (symbols[name] ||= []).push(entry);
175
446
  }
176
447
  }
177
448
  }
178
449
  }
179
- return this.deduplicateLocations(results);
450
+ const cache = {
451
+ version: 1,
452
+ rootDir: safeRoot,
453
+ builtAt: (/* @__PURE__ */ new Date()).toISOString(),
454
+ fileHashes,
455
+ symbols
456
+ };
457
+ import_fs2.default.mkdirSync(import_path3.default.dirname(cachePath), { recursive: true });
458
+ import_fs2.default.writeFileSync(cachePath, JSON.stringify(cache));
459
+ this.index = symbols;
460
+ const duration = Date.now() - startTime;
461
+ const memoryUsage = process.memoryUsage().heapUsed / 1024 / 1024;
462
+ return this.computeStats(cache, duration, Math.round(memoryUsage));
180
463
  }
181
- /**
182
- * Find references to a symbol
183
- */
184
- async findReferences(symbolName, path2, limit = 50, offset = 0) {
185
- const projects = await projectManager.getProjectsForPath(path2);
186
- const results = [];
187
- for (const project of projects) {
188
- const sourceFiles = project.getSourceFiles();
189
- for (const sourceFile of sourceFiles) {
190
- const nodes = sourceFile.getDescendantsOfKind(import_ts_morph2.SyntaxKind.Identifier).filter((id) => id.getText() === symbolName);
191
- for (const node of nodes) {
192
- const referencedSymbols = node.findReferences();
193
- for (const referencedSymbol of referencedSymbols) {
194
- const references = referencedSymbol.getReferences();
195
- for (const ref of references) {
196
- const sourceFile2 = ref.getSourceFile();
197
- const lineAndColumn = sourceFile2.getLineAndColumnAtPos(
198
- ref.getTextSpan().getStart()
199
- );
200
- results.push({
201
- file: sourceFile2.getFilePath(),
202
- line: lineAndColumn.line,
203
- column: lineAndColumn.column,
204
- text: ref.getNode().getParent()?.getText() || ref.getNode().getText()
205
- });
464
+ lookup(name) {
465
+ return this.index[name] || [];
466
+ }
467
+ lookupByFile(file) {
468
+ return Object.values(this.index).flat().filter((e) => e.file === file);
469
+ }
470
+ };
471
+ var symbolIndex = new SymbolIndex();
472
+
473
+ // src/adapters/typescript-adapter.ts
474
+ init_security();
475
+
476
+ // src/worker/pool.ts
477
+ init_cjs_shims();
478
+ var import_worker_threads = require("worker_threads");
479
+ var import_path4 = __toESM(require("path"), 1);
480
+ var import_url = require("url");
481
+ var WorkerPool = class {
482
+ constructor(poolSize) {
483
+ this.poolSize = poolSize;
484
+ }
485
+ workers = [];
486
+ available = [];
487
+ queue = [];
488
+ activeJobs = /* @__PURE__ */ new Map();
489
+ taskId = 0;
490
+ async init() {
491
+ const __dirname = import_path4.default.dirname((0, import_url.fileURLToPath)(importMetaUrl));
492
+ const workerPath = import_path4.default.join(__dirname, "ast-worker.js");
493
+ for (let i = 0; i < this.poolSize; i++) {
494
+ const worker = new import_worker_threads.Worker(workerPath);
495
+ worker.on("message", (msg) => this.handleResult(msg));
496
+ worker.on("error", (err) => this.handleWorkerError(worker, err));
497
+ this.workers.push(worker);
498
+ this.available.push(worker);
499
+ }
500
+ }
501
+ async execute(type, payload) {
502
+ return new Promise((resolve, reject) => {
503
+ const id = String(++this.taskId);
504
+ const task = { id, type, payload, resolve, reject };
505
+ const worker = this.available.pop();
506
+ if (worker) {
507
+ this.dispatch(worker, task);
508
+ } else {
509
+ this.queue.push(task);
510
+ }
511
+ });
512
+ }
513
+ dispatch(worker, task) {
514
+ this.activeJobs.set(task.id, task);
515
+ worker.postMessage({ id: task.id, type: task.type, payload: task.payload });
516
+ }
517
+ handleResult(msg) {
518
+ const task = this.activeJobs.get(msg.id);
519
+ if (!task) return;
520
+ this.activeJobs.delete(msg.id);
521
+ if (msg.error) {
522
+ task.reject(new Error(msg.error));
523
+ } else {
524
+ task.resolve(msg.result);
525
+ }
526
+ const worker = this.workers.find(
527
+ (w) => !this.available.includes(w) && ![...this.activeJobs.values()].some((t) => t.id === msg.id)
528
+ // simplistic
529
+ );
530
+ }
531
+ handleWorkerError(worker, err) {
532
+ const idx = this.workers.indexOf(worker);
533
+ if (idx !== -1) {
534
+ worker.terminate();
535
+ const __dirname = import_path4.default.dirname((0, import_url.fileURLToPath)(importMetaUrl));
536
+ const workerPath = import_path4.default.join(__dirname, "ast-worker.js");
537
+ const newWorker = new import_worker_threads.Worker(workerPath);
538
+ newWorker.on("message", (msg) => this.handleResult(msg));
539
+ newWorker.on("error", (e) => this.handleWorkerError(newWorker, e));
540
+ this.workers[idx] = newWorker;
541
+ this.available.push(newWorker);
542
+ }
543
+ }
544
+ async terminate() {
545
+ await Promise.all(this.workers.map((w) => w.terminate()));
546
+ this.workers = [];
547
+ this.available = [];
548
+ }
549
+ };
550
+
551
+ // src/adapters/typescript-adapter.ts
552
+ var TypeScriptAdapter = class {
553
+ pool;
554
+ constructor() {
555
+ const poolSize = parseInt(process.env.AST_WORKER_POOL_SIZE || "2");
556
+ this.pool = new WorkerPool(poolSize);
557
+ }
558
+ async resolveDefinition(symbolName, path5) {
559
+ validateWorkspacePath(path5);
560
+ const indexHits = symbolIndex.lookup(symbolName);
561
+ if (indexHits.length > 0) {
562
+ const results = [];
563
+ for (const hit of indexHits) {
564
+ const tsconfig2 = await projectManager.findNearestTsConfig(hit.file);
565
+ if (tsconfig2) {
566
+ const project = projectManager.ensureProject(tsconfig2);
567
+ const sourceFile = project.addSourceFileAtPathIfExists(hit.file);
568
+ if (sourceFile) {
569
+ const exported = sourceFile.getExportedDeclarations().get(symbolName);
570
+ if (exported && exported.length > 0) {
571
+ results.push(this.mapToDefinitionLocation(exported[0]));
572
+ continue;
206
573
  }
207
574
  }
208
575
  }
576
+ results.push({
577
+ file: hit.file,
578
+ line: hit.line,
579
+ column: hit.column,
580
+ kind: hit.kind,
581
+ snippet: "",
582
+ documentation: void 0
583
+ });
209
584
  }
585
+ return results;
586
+ }
587
+ if (import_fs3.default.statSync(path5).isDirectory()) {
588
+ return [];
589
+ }
590
+ const tsconfig = await projectManager.findNearestTsConfig(path5);
591
+ if (!tsconfig) return [];
592
+ try {
593
+ const result = await this.pool.execute(
594
+ "resolve_definition",
595
+ {
596
+ tsconfig,
597
+ file: path5,
598
+ symbol: symbolName
599
+ }
600
+ );
601
+ return result;
602
+ } catch {
603
+ const project = projectManager.ensureProject(tsconfig);
604
+ const sourceFile = project.addSourceFileAtPathIfExists(path5);
605
+ if (!sourceFile) return [];
606
+ const exported = sourceFile.getExportedDeclarations().get(symbolName);
607
+ if (!exported) return [];
608
+ return exported.map((decl) => this.mapToDefinitionLocation(decl));
210
609
  }
211
- const uniqueResults = this.deduplicateLocations(results);
212
- return {
213
- references: uniqueResults.slice(offset, offset + limit),
214
- total_count: uniqueResults.length
215
- };
216
610
  }
217
- /**
218
- * Find implementations for a symbol
219
- */
220
- async findImplementations(symbolName, path2, limit = 50, offset = 0) {
221
- const projects = await projectManager.getProjectsForPath(path2);
611
+ async findReferences(symbolName, path5, limit = 50, offset = 0) {
612
+ validateWorkspacePath(path5);
613
+ const hits = symbolIndex.lookup(symbolName);
614
+ if (hits.length === 0) return { references: [], total_count: 0 };
615
+ const hit = hits[0];
616
+ const tsconfig = await projectManager.findNearestTsConfig(hit.file);
617
+ if (!tsconfig) return { references: [], total_count: 0 };
618
+ const project = projectManager.ensureProject(tsconfig);
619
+ const sourceFile = project.addSourceFileAtPathIfExists(hit.file);
620
+ if (!sourceFile) return { references: [], total_count: 0 };
621
+ const exported = sourceFile.getExportedDeclarations().get(symbolName);
622
+ if (!exported || exported.length === 0)
623
+ return { references: [], total_count: 0 };
624
+ const targetNode = exported[0];
625
+ try {
626
+ const { searchCode: searchCode2 } = await Promise.resolve().then(() => (init_search_code(), search_code_exports));
627
+ const searchResults = await searchCode2(
628
+ symbolName,
629
+ path5,
630
+ "*.{ts,tsx,js,jsx}",
631
+ 1e3,
632
+ false
633
+ );
634
+ const filesToLoad = [...new Set(searchResults.map((r) => r.file))];
635
+ for (const file of filesToLoad) {
636
+ project.addSourceFileAtPathIfExists(file);
637
+ }
638
+ } catch (_e) {
639
+ }
640
+ const refSymbols = targetNode.findReferences?.();
641
+ if (!refSymbols) return { references: [], total_count: 0 };
222
642
  const results = [];
223
- for (const project of projects) {
224
- const sourceFiles = project.getSourceFiles();
225
- for (const sourceFile of sourceFiles) {
226
- const nodes = sourceFile.getDescendantsOfKind(import_ts_morph2.SyntaxKind.Identifier).filter((id) => id.getText() === symbolName);
227
- for (const node of nodes) {
228
- const implementations = node.getImplementations();
229
- for (const impl of implementations) {
230
- const sourceFile2 = impl.getSourceFile();
231
- const lineAndColumn = sourceFile2.getLineAndColumnAtPos(
232
- impl.getTextSpan().getStart()
233
- );
234
- results.push({
235
- file: sourceFile2.getFilePath(),
236
- line: lineAndColumn.line,
237
- column: lineAndColumn.column,
238
- text: impl.getNode().getParent()?.getText() || impl.getNode().getText()
239
- });
240
- }
241
- }
643
+ for (const refSymbol of refSymbols) {
644
+ for (const ref of refSymbol.getReferences()) {
645
+ const sf = ref.getSourceFile();
646
+ const lc = sf.getLineAndColumnAtPos(ref.getTextSpan().getStart());
647
+ results.push({
648
+ file: sf.getFilePath(),
649
+ line: lc.line,
650
+ column: lc.column,
651
+ text: ref.getNode().getParent()?.getText() || ref.getNode().getText()
652
+ });
242
653
  }
243
654
  }
244
- const uniqueResults = this.deduplicateLocations(results);
655
+ const unique = this.deduplicateLocations(results);
245
656
  return {
246
- implementations: uniqueResults.slice(offset, offset + limit),
247
- total_count: uniqueResults.length
657
+ references: unique.slice(offset, offset + limit),
658
+ total_count: unique.length
248
659
  };
249
660
  }
250
- /**
251
- * Get file structure overview
252
- */
661
+ async findImplementations(symbolName, path5, limit = 50, offset = 0) {
662
+ validateWorkspacePath(path5);
663
+ const hits = symbolIndex.lookup(symbolName);
664
+ if (hits.length === 0) return { implementations: [], total_count: 0 };
665
+ const hit = hits[0];
666
+ const tsconfig = await projectManager.findNearestTsConfig(hit.file);
667
+ if (!tsconfig) return { implementations: [], total_count: 0 };
668
+ try {
669
+ const result = await this.pool.execute("find_implementations", {
670
+ tsconfig,
671
+ file: hit.file,
672
+ symbol: symbolName
673
+ });
674
+ return {
675
+ implementations: result.implementations.slice(offset, offset + limit),
676
+ total_count: result.total_count
677
+ };
678
+ } catch {
679
+ const project = projectManager.ensureProject(tsconfig);
680
+ const sourceFile = project.addSourceFileAtPathIfExists(hit.file);
681
+ if (!sourceFile) return { implementations: [], total_count: 0 };
682
+ const exported = sourceFile.getExportedDeclarations().get(symbolName);
683
+ if (!exported || exported.length === 0)
684
+ return { implementations: [], total_count: 0 };
685
+ const targetNode = exported[0];
686
+ if (!import_ts_morph3.Node.isClassDeclaration(targetNode) && !import_ts_morph3.Node.isInterfaceDeclaration(targetNode)) {
687
+ return { implementations: [], total_count: 0 };
688
+ }
689
+ try {
690
+ const { searchCode: searchCode2 } = await Promise.resolve().then(() => (init_search_code(), search_code_exports));
691
+ const searchResults = await searchCode2(
692
+ symbolName,
693
+ path5,
694
+ "*.{ts,tsx,js,jsx}",
695
+ 1e3,
696
+ false
697
+ );
698
+ const filesToLoad = [...new Set(searchResults.map((r) => r.file))];
699
+ for (const file of filesToLoad) {
700
+ project.addSourceFileAtPathIfExists(file);
701
+ }
702
+ } catch (_e) {
703
+ }
704
+ const results = [];
705
+ const implementations = targetNode.getImplementations?.();
706
+ if (implementations) {
707
+ for (const impl of implementations) {
708
+ const sf = impl.getSourceFile();
709
+ const lc = sf.getLineAndColumnAtPos(impl.getTextSpan().getStart());
710
+ results.push({
711
+ file: sf.getFilePath(),
712
+ line: lc.line,
713
+ column: lc.column,
714
+ text: impl.getNode().getParent()?.getText() || impl.getNode().getText()
715
+ });
716
+ }
717
+ }
718
+ const unique = this.deduplicateLocations(results);
719
+ return {
720
+ implementations: unique.slice(offset, offset + limit),
721
+ total_count: unique.length
722
+ };
723
+ }
724
+ }
253
725
  async getFileStructure(filePath) {
254
- const project = await projectManager.getProjectForFile(filePath);
255
- if (!project) return void 0;
256
- const sourceFile = project.getSourceFile(filePath);
726
+ const safePath = validateWorkspacePath(filePath);
727
+ const tsconfig = await projectManager.findNearestTsConfig(safePath);
728
+ if (!tsconfig) return void 0;
729
+ const project = projectManager.ensureProject(tsconfig);
730
+ const sourceFile = project.addSourceFileAtPathIfExists(safePath);
257
731
  if (!sourceFile) return void 0;
258
732
  const structure = {
259
- file: filePath,
733
+ file: safePath,
260
734
  imports: sourceFile.getImportDeclarations().map((imp) => ({
261
735
  module: imp.getModuleSpecifierValue(),
262
736
  names: imp.getNamedImports().map((ni) => ni.getName())
@@ -273,9 +747,9 @@ var TypeScriptAdapter = class {
273
747
  };
274
748
  return structure;
275
749
  }
276
- /**
277
- * Helper: Map ts-morph Node (Declaration) to DefinitionLocation
278
- */
750
+ async shutdown() {
751
+ await this.pool.terminate();
752
+ }
279
753
  mapToDefinitionLocation(node) {
280
754
  const sourceFile = node.getSourceFile();
281
755
  const lineAndColumn = sourceFile.getLineAndColumnAtPos(node.getStart());
@@ -288,34 +762,25 @@ var TypeScriptAdapter = class {
288
762
  documentation: this.getJsDoc(node)
289
763
  };
290
764
  }
291
- /**
292
- * Helper: Map ts-morph Node to SymbolKind
293
- */
294
765
  mapNodeToSymbolKind(node) {
295
- if (import_ts_morph2.Node.isClassDeclaration(node)) return "class";
296
- if (import_ts_morph2.Node.isFunctionDeclaration(node)) return "function";
297
- if (import_ts_morph2.Node.isInterfaceDeclaration(node)) return "interface";
298
- if (import_ts_morph2.Node.isTypeAliasDeclaration(node)) return "type_alias";
299
- if (import_ts_morph2.Node.isEnumDeclaration(node)) return "enum";
300
- if (import_ts_morph2.Node.isVariableDeclaration(node)) return "variable";
301
- if (import_ts_morph2.Node.isMethodDeclaration(node)) return "method";
302
- if (import_ts_morph2.Node.isPropertyDeclaration(node)) return "property";
303
- if (import_ts_morph2.Node.isParameterDeclaration(node)) return "parameter";
766
+ if (import_ts_morph3.Node.isClassDeclaration(node)) return "class";
767
+ if (import_ts_morph3.Node.isFunctionDeclaration(node)) return "function";
768
+ if (import_ts_morph3.Node.isInterfaceDeclaration(node)) return "interface";
769
+ if (import_ts_morph3.Node.isTypeAliasDeclaration(node)) return "type_alias";
770
+ if (import_ts_morph3.Node.isEnumDeclaration(node)) return "enum";
771
+ if (import_ts_morph3.Node.isVariableDeclaration(node)) return "variable";
772
+ if (import_ts_morph3.Node.isMethodDeclaration(node)) return "method";
773
+ if (import_ts_morph3.Node.isPropertyDeclaration(node)) return "property";
774
+ if (import_ts_morph3.Node.isParameterDeclaration(node)) return "parameter";
304
775
  return "variable";
305
776
  }
306
- /**
307
- * Helper: Map Symbol to SymbolKind
308
- */
309
777
  mapSymbolKind(symbol) {
310
778
  const decls = symbol.getDeclarations();
311
779
  if (decls.length > 0) return this.mapNodeToSymbolKind(decls[0]);
312
780
  return "variable";
313
781
  }
314
- /**
315
- * Helper: Get JSDoc from Node
316
- */
317
782
  getJsDoc(node) {
318
- if (import_ts_morph2.Node.isJSDocable(node)) {
783
+ if (import_ts_morph3.Node.isJSDocable(node)) {
319
784
  const docs = node.getJsDocs();
320
785
  if (docs.length > 0) {
321
786
  return docs[0].getCommentText();
@@ -323,11 +788,8 @@ var TypeScriptAdapter = class {
323
788
  }
324
789
  return void 0;
325
790
  }
326
- /**
327
- * Helper: Get full JSDoc info (with tags)
328
- */
329
791
  getSymbolDocs(node) {
330
- if (import_ts_morph2.Node.isJSDocable(node)) {
792
+ if (import_ts_morph3.Node.isJSDocable(node)) {
331
793
  const docs = node.getJsDocs();
332
794
  if (docs.length > 0) {
333
795
  const doc = docs[0];
@@ -390,9 +852,6 @@ var TypeScriptAdapter = class {
390
852
  members: enm.getMembers().map((m) => m.getName())
391
853
  };
392
854
  }
393
- /**
394
- * Helper: Deduplicate locations
395
- */
396
855
  deduplicateLocations(locations) {
397
856
  const seen = /* @__PURE__ */ new Set();
398
857
  return locations.filter((loc) => {
@@ -406,100 +865,59 @@ var TypeScriptAdapter = class {
406
865
  var typescriptAdapter = new TypeScriptAdapter();
407
866
 
408
867
  // src/tools/resolve-definition.ts
409
- async function resolveDefinition(symbol, path2) {
410
- return await typescriptAdapter.resolveDefinition(symbol, path2);
868
+ async function resolveDefinition(symbol, path5) {
869
+ return await typescriptAdapter.resolveDefinition(symbol, path5);
411
870
  }
412
871
 
413
872
  // src/tools/find-references.ts
414
- async function findReferences(symbol, path2, limit = 50, offset = 0) {
415
- return await typescriptAdapter.findReferences(symbol, path2, limit, offset);
873
+ init_cjs_shims();
874
+ async function findReferences(symbol, path5, limit = 50, offset = 0) {
875
+ return await typescriptAdapter.findReferences(symbol, path5, limit, offset);
416
876
  }
417
877
 
418
878
  // src/tools/find-implementations.ts
419
- async function findImplementations(symbol, path2, limit = 50, offset = 0) {
879
+ init_cjs_shims();
880
+ async function findImplementations(symbol, path5, limit = 50, offset = 0) {
420
881
  return await typescriptAdapter.findImplementations(
421
882
  symbol,
422
- path2,
883
+ path5,
423
884
  limit,
424
885
  offset
425
886
  );
426
887
  }
427
888
 
428
889
  // src/tools/get-file-structure.ts
890
+ init_cjs_shims();
429
891
  async function getFileStructure(file) {
430
892
  return await typescriptAdapter.getFileStructure(file);
431
893
  }
432
894
 
433
- // src/tools/search-code.ts
434
- var import_child_process = require("child_process");
435
- var import_util = require("util");
436
- var import_ripgrep = require("@vscode/ripgrep");
437
- var execFileAsync = (0, import_util.promisify)(import_child_process.execFile);
438
- async function searchCode(pattern, searchPath, filePattern, limit = 50) {
439
- const args = [
440
- "--json",
441
- "--max-count",
442
- limit.toString(),
443
- "--fixed-strings",
444
- // Default to fixed strings unless we want regex
445
- pattern,
446
- searchPath
447
- ];
448
- if (filePattern) {
449
- args.push("--glob", filePattern);
450
- }
451
- args.push("--glob", "!**/node_modules/**");
452
- args.push("--glob", "!**/dist/**");
453
- args.push("--glob", "!**/.git/**");
454
- try {
455
- const { stdout } = await execFileAsync(import_ripgrep.rgPath, args);
456
- const lines = stdout.split("\n").filter(Boolean);
457
- const results = [];
458
- for (const line of lines) {
459
- const data = JSON.parse(line);
460
- if (data.type === "match") {
461
- const file = data.data.path.text;
462
- const lineNumber = data.data.line_number;
463
- const submatches = data.data.submatches;
464
- for (const submatch of submatches) {
465
- results.push({
466
- file,
467
- line: lineNumber,
468
- column: submatch.start,
469
- text: data.data.lines.text.trim()
470
- });
471
- }
472
- }
473
- }
474
- return results.slice(0, limit);
475
- } catch (error) {
476
- if (error.code === 1) {
477
- return [];
478
- }
479
- throw error;
480
- }
481
- }
895
+ // src/index.ts
896
+ init_search_code();
482
897
 
483
898
  // src/tools/get-symbol-docs.ts
484
- var import_ts_morph3 = require("ts-morph");
899
+ init_cjs_shims();
900
+ var import_ts_morph4 = require("ts-morph");
901
+ init_security();
485
902
  async function getSymbolDocs(symbol, filePath) {
486
- const projects = await projectManager.getProjectsForPath(filePath);
487
- for (const project of projects) {
488
- const sourceFile = project.getSourceFile(filePath);
489
- if (sourceFile) {
490
- const node = sourceFile.getDescendantsOfKind(import_ts_morph3.SyntaxKind.Identifier).find((id) => id.getText() === symbol);
491
- if (node) {
492
- const decls = node.getSymbol()?.getDeclarations();
493
- if (decls && decls.length > 0) {
494
- const docs = typescriptAdapter.getSymbolDocs(decls[0]);
495
- if (docs) {
496
- return {
497
- symbol,
498
- file: sourceFile.getFilePath(),
499
- line: sourceFile.getLineAndColumnAtPos(decls[0].getStart()).line,
500
- ...docs
501
- };
502
- }
903
+ const safePath = validateWorkspacePath(filePath);
904
+ const tsconfig = await projectManager.findNearestTsConfig(safePath);
905
+ if (!tsconfig) return void 0;
906
+ const project = projectManager.ensureProject(tsconfig);
907
+ const sourceFile = project.addSourceFileAtPathIfExists(safePath);
908
+ if (sourceFile) {
909
+ const node = sourceFile.getDescendantsOfKind(import_ts_morph4.SyntaxKind.Identifier).find((id) => id.getText() === symbol);
910
+ if (node) {
911
+ const decls = node.getSymbol()?.getDeclarations();
912
+ if (decls && decls.length > 0) {
913
+ const docs = typescriptAdapter.getSymbolDocs(decls[0]);
914
+ if (docs) {
915
+ return {
916
+ symbol,
917
+ file: sourceFile.getFilePath(),
918
+ line: sourceFile.getLineAndColumnAtPos(decls[0].getStart()).line,
919
+ ...docs
920
+ };
503
921
  }
504
922
  }
505
923
  }
@@ -507,49 +925,10 @@ async function getSymbolDocs(symbol, filePath) {
507
925
  return void 0;
508
926
  }
509
927
 
510
- // src/index/symbol-index.ts
511
- var SymbolIndex = class {
512
- /**
513
- * Build/Warm the index for a given path
514
- */
515
- async buildIndex(rootDir) {
516
- const startTime = Date.now();
517
- const projects = await projectManager.getProjectsForPath(rootDir);
518
- let fileCount = 0;
519
- let functionCount = 0;
520
- let classCount = 0;
521
- let interfaceCount = 0;
522
- let typeCount = 0;
523
- for (const project of projects) {
524
- const sourceFiles = project.getSourceFiles();
525
- fileCount += sourceFiles.length;
526
- for (const sourceFile of sourceFiles) {
527
- functionCount += sourceFile.getFunctions().length;
528
- classCount += sourceFile.getClasses().length;
529
- interfaceCount += sourceFile.getInterfaces().length;
530
- typeCount += sourceFile.getTypeAliases().length;
531
- }
532
- }
533
- const duration = Date.now() - startTime;
534
- const memoryUsage = process.memoryUsage().heapUsed / 1024 / 1024;
535
- return {
536
- indexed: {
537
- files: fileCount,
538
- functions: functionCount,
539
- classes: classCount,
540
- interfaces: interfaceCount,
541
- types: typeCount
542
- },
543
- duration_ms: duration,
544
- memory_mb: Math.round(memoryUsage)
545
- };
546
- }
547
- };
548
- var symbolIndex = new SymbolIndex();
549
-
550
928
  // src/tools/build-symbol-index.ts
551
- async function buildSymbolIndex(path2) {
552
- return await symbolIndex.buildIndex(path2);
929
+ init_cjs_shims();
930
+ async function buildSymbolIndex(path5) {
931
+ return await symbolIndex.buildIndex(path5);
553
932
  }
554
933
 
555
934
  // src/index.ts
@@ -643,7 +1022,8 @@ var ASTExplorerServer = class {
643
1022
  pattern: { type: "string", description: "Search pattern" },
644
1023
  path: { type: "string", description: "Directory to search" },
645
1024
  filePattern: { type: "string", description: "Glob filter" },
646
- limit: { type: "number", default: 50 }
1025
+ limit: { type: "number", default: 50 },
1026
+ regex: { type: "boolean", default: true }
647
1027
  },
648
1028
  required: ["pattern", "path"]
649
1029
  }
@@ -679,8 +1059,8 @@ var ASTExplorerServer = class {
679
1059
  try {
680
1060
  switch (name) {
681
1061
  case "resolve_definition": {
682
- const { symbol, path: path2 } = ResolveDefinitionSchema.parse(args);
683
- const results = await resolveDefinition(symbol, path2);
1062
+ const { symbol, path: path5 } = ResolveDefinitionSchema.parse(args);
1063
+ const results = await resolveDefinition(symbol, path5);
684
1064
  return {
685
1065
  content: [
686
1066
  { type: "text", text: JSON.stringify(results, null, 2) }
@@ -688,8 +1068,8 @@ var ASTExplorerServer = class {
688
1068
  };
689
1069
  }
690
1070
  case "find_references": {
691
- const { symbol, path: path2, limit, offset } = FindReferencesSchema.parse(args);
692
- const results = await findReferences(symbol, path2, limit, offset);
1071
+ const { symbol, path: path5, limit, offset } = FindReferencesSchema.parse(args);
1072
+ const results = await findReferences(symbol, path5, limit, offset);
693
1073
  return {
694
1074
  content: [
695
1075
  { type: "text", text: JSON.stringify(results, null, 2) }
@@ -697,10 +1077,10 @@ var ASTExplorerServer = class {
697
1077
  };
698
1078
  }
699
1079
  case "find_implementations": {
700
- const { symbol, path: path2, limit, offset } = FindImplementationsSchema.parse(args);
1080
+ const { symbol, path: path5, limit, offset } = FindImplementationsSchema.parse(args);
701
1081
  const results = await findImplementations(
702
1082
  symbol,
703
- path2,
1083
+ path5,
704
1084
  limit,
705
1085
  offset
706
1086
  );
@@ -720,8 +1100,14 @@ var ASTExplorerServer = class {
720
1100
  };
721
1101
  }
722
1102
  case "search_code": {
723
- const { pattern, path: path2, filePattern, limit } = SearchCodeSchema.parse(args);
724
- const results = await searchCode(pattern, path2, filePattern, limit);
1103
+ const { pattern, path: path5, filePattern, limit, regex } = SearchCodeSchema.parse(args);
1104
+ const results = await searchCode(
1105
+ pattern,
1106
+ path5,
1107
+ filePattern,
1108
+ limit,
1109
+ regex
1110
+ );
725
1111
  return {
726
1112
  content: [
727
1113
  { type: "text", text: JSON.stringify(results, null, 2) }
@@ -729,15 +1115,15 @@ var ASTExplorerServer = class {
729
1115
  };
730
1116
  }
731
1117
  case "get_symbol_docs": {
732
- const { symbol, path: path2 } = GetSymbolDocsSchema.parse(args);
733
- const docs = await getSymbolDocs(symbol, path2);
1118
+ const { symbol, path: path5 } = GetSymbolDocsSchema.parse(args);
1119
+ const docs = await getSymbolDocs(symbol, path5);
734
1120
  return {
735
1121
  content: [{ type: "text", text: JSON.stringify(docs, null, 2) }]
736
1122
  };
737
1123
  }
738
1124
  case "build_symbol_index": {
739
- const { path: path2 } = BuildSymbolIndexSchema.parse(args);
740
- const stats = await buildSymbolIndex(path2);
1125
+ const { path: path5 } = BuildSymbolIndexSchema.parse(args);
1126
+ const stats = await buildSymbolIndex(path5);
741
1127
  return {
742
1128
  content: [{ type: "text", text: JSON.stringify(stats, null, 2) }]
743
1129
  };