grepmax 0.17.3 → 0.17.5

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.
@@ -53,6 +53,8 @@ exports.mcp = void 0;
53
53
  exports.toStringArray = toStringArray;
54
54
  exports.ok = ok;
55
55
  exports.err = err;
56
+ exports.filterMcpSearchResults = filterMcpSearchResults;
57
+ exports.formatMcpPointerSearchResults = formatMcpPointerSearchResults;
56
58
  const fs = __importStar(require("node:fs"));
57
59
  const path = __importStar(require("node:path"));
58
60
  const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
@@ -63,12 +65,13 @@ const config_1 = require("../config");
63
65
  const graph_builder_1 = require("../lib/graph/graph-builder");
64
66
  const index_config_1 = require("../lib/index/index-config");
65
67
  const syncer_1 = require("../lib/index/syncer");
66
- const meta_cache_1 = require("../lib/store/meta-cache");
68
+ const agent_search_formatter_1 = require("../lib/output/agent-search-formatter");
67
69
  const searcher_1 = require("../lib/search/searcher");
68
70
  const annotator_1 = require("../lib/skeleton/annotator");
69
71
  const retriever_1 = require("../lib/skeleton/retriever");
70
- const symbol_extractor_1 = require("../lib/skeleton/symbol-extractor");
71
72
  const skeletonizer_1 = require("../lib/skeleton/skeletonizer");
73
+ const symbol_extractor_1 = require("../lib/skeleton/symbol-extractor");
74
+ const meta_cache_1 = require("../lib/store/meta-cache");
72
75
  const vector_db_1 = require("../lib/store/vector-db");
73
76
  const file_utils_1 = require("../lib/utils/file-utils");
74
77
  const filter_builder_1 = require("../lib/utils/filter-builder");
@@ -88,24 +91,72 @@ const TOOLS = [
88
91
  inputSchema: {
89
92
  type: "object",
90
93
  properties: {
91
- query: { type: "string", description: "Natural language query (5+ words recommended)" },
92
- limit: { type: "number", description: "Max results (default 3, max 50)" },
93
- root: { type: "string", description: "Search a different directory (absolute path)" },
94
- path: { type: "string", description: "Path prefix filter (e.g. 'src/auth/')" },
95
- detail: { type: "string", description: "'pointer' (default), 'code', or 'full'" },
94
+ query: {
95
+ type: "string",
96
+ description: "Natural language query (5+ words recommended)",
97
+ },
98
+ limit: {
99
+ type: "number",
100
+ description: "Max results (default 3, max 50)",
101
+ },
102
+ root: {
103
+ type: "string",
104
+ description: "Search a different directory (absolute path)",
105
+ },
106
+ path: {
107
+ type: "string",
108
+ description: "Path prefix filter (e.g. 'src/auth/')",
109
+ },
110
+ detail: {
111
+ type: "string",
112
+ description: "'pointer' (default), 'code', or 'full'",
113
+ },
96
114
  min_score: { type: "number", description: "Min score 0-1 (default 0)" },
97
115
  max_per_file: { type: "number", description: "Max results per file" },
98
- file: { type: "string", description: "Filename filter (e.g. 'syncer.ts')" },
99
- exclude: { type: "string", description: "Exclude path prefix (e.g. 'tests/')" },
100
- language: { type: "string", description: "Extension filter (e.g. 'ts', 'py')" },
101
- role: { type: "string", description: "'ORCHESTRATION', 'DEFINITION', or 'IMPLEMENTATION'" },
102
- context_lines: { type: "number", description: "Lines before/after chunk (max 20)" },
103
- mode: { type: "string", description: "'default' or 'symbol' (appends call graph)" },
104
- include_imports: { type: "boolean", description: "Prepend file imports to results" },
105
- name_pattern: { type: "string", description: "Regex filter on symbol name" },
106
- scope: { type: "string", description: "'project' (default) or 'all' (search everything)" },
107
- projects: { type: "string", description: "Project names to include (comma-separated)" },
108
- exclude_projects: { type: "string", description: "Project names to exclude (comma-separated)" },
116
+ file: {
117
+ type: "string",
118
+ description: "Filename filter (e.g. 'syncer.ts')",
119
+ },
120
+ exclude: {
121
+ type: "string",
122
+ description: "Exclude path prefix (e.g. 'tests/')",
123
+ },
124
+ language: {
125
+ type: "string",
126
+ description: "Extension filter (e.g. 'ts', 'py')",
127
+ },
128
+ role: {
129
+ type: "string",
130
+ description: "'ORCHESTRATION', 'DEFINITION', or 'IMPLEMENTATION'",
131
+ },
132
+ context_lines: {
133
+ type: "number",
134
+ description: "Lines before/after chunk (max 20)",
135
+ },
136
+ mode: {
137
+ type: "string",
138
+ description: "'default' or 'symbol' (appends call graph)",
139
+ },
140
+ include_imports: {
141
+ type: "boolean",
142
+ description: "Prepend file imports to results",
143
+ },
144
+ name_pattern: {
145
+ type: "string",
146
+ description: "Regex filter on symbol name",
147
+ },
148
+ scope: {
149
+ type: "string",
150
+ description: "'project' (default) or 'all' (search everything)",
151
+ },
152
+ projects: {
153
+ type: "string",
154
+ description: "Project names to include (comma-separated)",
155
+ },
156
+ exclude_projects: {
157
+ type: "string",
158
+ description: "Project names to exclude (comma-separated)",
159
+ },
109
160
  },
110
161
  required: ["query"],
111
162
  },
@@ -116,8 +167,14 @@ const TOOLS = [
116
167
  inputSchema: {
117
168
  type: "object",
118
169
  properties: {
119
- target: { type: "string", description: "File, directory, or comma-separated paths" },
120
- limit: { type: "number", description: "Max files for directory mode (default 10)" },
170
+ target: {
171
+ type: "string",
172
+ description: "File, directory, or comma-separated paths",
173
+ },
174
+ limit: {
175
+ type: "number",
176
+ description: "Max files for directory mode (default 10)",
177
+ },
121
178
  format: { type: "string", description: "'text' (default) or 'json'" },
122
179
  },
123
180
  required: ["target"],
@@ -130,7 +187,10 @@ const TOOLS = [
130
187
  type: "object",
131
188
  properties: {
132
189
  symbol: { type: "string", description: "Function/class name to trace" },
133
- depth: { type: "number", description: "Caller depth (default 1, max 3)" },
190
+ depth: {
191
+ type: "number",
192
+ description: "Caller depth (default 1, max 3)",
193
+ },
134
194
  },
135
195
  required: ["symbol"],
136
196
  },
@@ -143,7 +203,10 @@ const TOOLS = [
143
203
  properties: {
144
204
  symbol: { type: "string", description: "Symbol name to extract" },
145
205
  root: { type: "string", description: "Project root (absolute path)" },
146
- include_imports: { type: "boolean", description: "Prepend file imports" },
206
+ include_imports: {
207
+ type: "boolean",
208
+ description: "Prepend file imports",
209
+ },
147
210
  },
148
211
  required: ["symbol"],
149
212
  },
@@ -156,7 +219,10 @@ const TOOLS = [
156
219
  properties: {
157
220
  symbol: { type: "string", description: "Symbol name" },
158
221
  root: { type: "string", description: "Project root (absolute path)" },
159
- depth: { type: "number", description: "Caller depth (default 1, max 3)" },
222
+ depth: {
223
+ type: "number",
224
+ description: "Caller depth (default 1, max 3)",
225
+ },
160
226
  },
161
227
  required: ["symbol"],
162
228
  },
@@ -179,7 +245,10 @@ const TOOLS = [
179
245
  inputSchema: {
180
246
  type: "object",
181
247
  properties: {
182
- pattern: { type: "string", description: "Name filter (case-insensitive)" },
248
+ pattern: {
249
+ type: "string",
250
+ description: "Name filter (case-insensitive)",
251
+ },
183
252
  limit: { type: "number", description: "Max results (default 20)" },
184
253
  path: { type: "string", description: "Path prefix filter" },
185
254
  },
@@ -197,8 +266,14 @@ const TOOLS = [
197
266
  inputSchema: {
198
267
  type: "object",
199
268
  properties: {
200
- path: { type: "string", description: "Directory to summarize (default: project root)" },
201
- limit: { type: "number", description: "Max chunks (default 200, max 5000)" },
269
+ path: {
270
+ type: "string",
271
+ description: "Directory to summarize (default: project root)",
272
+ },
273
+ limit: {
274
+ type: "number",
275
+ description: "Max chunks (default 200, max 5000)",
276
+ },
202
277
  },
203
278
  },
204
279
  },
@@ -208,7 +283,10 @@ const TOOLS = [
208
283
  inputSchema: {
209
284
  type: "object",
210
285
  properties: {
211
- root: { type: "string", description: "Project root (default: current)" },
286
+ root: {
287
+ type: "string",
288
+ description: "Project root (default: current)",
289
+ },
212
290
  },
213
291
  },
214
292
  },
@@ -218,8 +296,14 @@ const TOOLS = [
218
296
  inputSchema: {
219
297
  type: "object",
220
298
  properties: {
221
- file: { type: "string", description: "File path relative to project root" },
222
- limit: { type: "number", description: "Max results per direction (default 10)" },
299
+ file: {
300
+ type: "string",
301
+ description: "File path relative to project root",
302
+ },
303
+ limit: {
304
+ type: "number",
305
+ description: "Max results per direction (default 10)",
306
+ },
223
307
  },
224
308
  required: ["file"],
225
309
  },
@@ -247,10 +331,19 @@ const TOOLS = [
247
331
  inputSchema: {
248
332
  type: "object",
249
333
  properties: {
250
- ref: { type: "string", description: "Git ref to diff against (e.g. main, HEAD~5)" },
251
- query: { type: "string", description: "Semantic search within changed files" },
334
+ ref: {
335
+ type: "string",
336
+ description: "Git ref to diff against (e.g. main, HEAD~5)",
337
+ },
338
+ query: {
339
+ type: "string",
340
+ description: "Semantic search within changed files",
341
+ },
252
342
  limit: { type: "number", description: "Max results (default 10)" },
253
- role: { type: "string", description: "Filter by role: ORCHESTRATION, DEFINITION, IMPLEMENTATION" },
343
+ role: {
344
+ type: "string",
345
+ description: "Filter by role: ORCHESTRATION, DEFINITION, IMPLEMENTATION",
346
+ },
254
347
  },
255
348
  },
256
349
  },
@@ -261,7 +354,10 @@ const TOOLS = [
261
354
  type: "object",
262
355
  properties: {
263
356
  target: { type: "string", description: "Symbol name or file path" },
264
- depth: { type: "number", description: "Caller traversal depth 1-3 (default 1)" },
357
+ depth: {
358
+ type: "number",
359
+ description: "Caller traversal depth 1-3 (default 1)",
360
+ },
265
361
  },
266
362
  required: ["target"],
267
363
  },
@@ -273,7 +369,10 @@ const TOOLS = [
273
369
  type: "object",
274
370
  properties: {
275
371
  target: { type: "string", description: "Symbol name or file path" },
276
- depth: { type: "number", description: "Caller traversal depth 1-3 (default 1)" },
372
+ depth: {
373
+ type: "number",
374
+ description: "Caller traversal depth 1-3 (default 1)",
375
+ },
277
376
  },
278
377
  required: ["target"],
279
378
  },
@@ -286,7 +385,10 @@ const TOOLS = [
286
385
  properties: {
287
386
  target: { type: "string", description: "Symbol name or file path" },
288
387
  limit: { type: "number", description: "Max results (default 5)" },
289
- threshold: { type: "number", description: "Min similarity 0-1 (default 0)" },
388
+ threshold: {
389
+ type: "number",
390
+ description: "Min similarity 0-1 (default 0)",
391
+ },
290
392
  },
291
393
  required: ["target"],
292
394
  },
@@ -297,9 +399,15 @@ const TOOLS = [
297
399
  inputSchema: {
298
400
  type: "object",
299
401
  properties: {
300
- topic: { type: "string", description: "Natural language topic or directory path" },
402
+ topic: {
403
+ type: "string",
404
+ description: "Natural language topic or directory path",
405
+ },
301
406
  budget: { type: "number", description: "Max tokens (default 4000)" },
302
- limit: { type: "number", description: "Search result limit (default 10)" },
407
+ limit: {
408
+ type: "number",
409
+ description: "Search result limit (default 10)",
410
+ },
303
411
  },
304
412
  required: ["topic"],
305
413
  },
@@ -310,8 +418,14 @@ const TOOLS = [
310
418
  inputSchema: {
311
419
  type: "object",
312
420
  properties: {
313
- question: { type: "string", description: "Natural language question about the codebase" },
314
- max_rounds: { type: "number", description: "Max tool-call rounds (default 10)" },
421
+ question: {
422
+ type: "string",
423
+ description: "Natural language question about the codebase",
424
+ },
425
+ max_rounds: {
426
+ type: "number",
427
+ description: "Max tool-call rounds (default 10)",
428
+ },
315
429
  },
316
430
  required: ["question"],
317
431
  },
@@ -322,7 +436,10 @@ const TOOLS = [
322
436
  inputSchema: {
323
437
  type: "object",
324
438
  properties: {
325
- commit: { type: "string", description: "Git ref to review (default: HEAD)" },
439
+ commit: {
440
+ type: "string",
441
+ description: "Git ref to review (default: HEAD)",
442
+ },
326
443
  },
327
444
  required: [],
328
445
  },
@@ -333,7 +450,10 @@ const TOOLS = [
333
450
  inputSchema: {
334
451
  type: "object",
335
452
  properties: {
336
- json: { type: "boolean", description: "Return raw JSON instead of text (default: false)" },
453
+ json: {
454
+ type: "boolean",
455
+ description: "Return raw JSON instead of text (default: false)",
456
+ },
337
457
  },
338
458
  required: [],
339
459
  },
@@ -362,6 +482,50 @@ function ok(text) {
362
482
  function err(text) {
363
483
  return { content: [{ type: "text", text }], isError: true };
364
484
  }
485
+ function chunkAbsPath(chunk) {
486
+ const metadata = chunk.metadata;
487
+ return String(chunk.path || (metadata === null || metadata === void 0 ? void 0 : metadata.path) || "");
488
+ }
489
+ function chunkSymbols(chunk) {
490
+ var _a;
491
+ return toStringArray((_a = chunk.definedSymbols) !== null && _a !== void 0 ? _a : chunk.defined_symbols);
492
+ }
493
+ function filterMcpSearchResults(data, options = {}) {
494
+ var _a, _b;
495
+ let results = data;
496
+ const minScore = (_a = options.minScore) !== null && _a !== void 0 ? _a : 0;
497
+ if (minScore > 0) {
498
+ results = results.filter((r) => typeof r.score !== "number" || r.score >= minScore);
499
+ }
500
+ const maxPerFile = (_b = options.maxPerFile) !== null && _b !== void 0 ? _b : 0;
501
+ if (maxPerFile > 0) {
502
+ const counts = new Map();
503
+ results = results.filter((r) => {
504
+ const absPath = chunkAbsPath(r);
505
+ const count = counts.get(absPath) || 0;
506
+ if (count >= maxPerFile)
507
+ return false;
508
+ counts.set(absPath, count + 1);
509
+ return true;
510
+ });
511
+ }
512
+ if (options.namePattern) {
513
+ try {
514
+ const regex = new RegExp(options.namePattern, "i");
515
+ results = results.filter((r) => chunkSymbols(r).some((symbol) => regex.test(symbol)));
516
+ }
517
+ catch (_c) {
518
+ // Preserve existing MCP behavior: invalid regex means no name filter.
519
+ }
520
+ }
521
+ return results;
522
+ }
523
+ function formatMcpPointerSearchResults(data, displayRoot, options = {}) {
524
+ return (0, agent_search_formatter_1.formatAgentSearchResults)(filterMcpSearchResults(data, options), displayRoot, {
525
+ includeImports: options.includeImports,
526
+ getImportsForFile: options.getImportsForFile,
527
+ });
528
+ }
365
529
  // ---------------------------------------------------------------------------
366
530
  // Command
367
531
  // ---------------------------------------------------------------------------
@@ -458,7 +622,7 @@ exports.mcp = new commander_1.Command("mcp")
458
622
  // --- Tool handlers ---
459
623
  function handleSemanticSearch(args_1) {
460
624
  return __awaiter(this, arguments, void 0, function* (args, isSearchAll = false) {
461
- var _a;
625
+ var _a, _b;
462
626
  const query = String(args.query || "");
463
627
  if (!query)
464
628
  return err("Missing required parameter: query");
@@ -485,9 +649,7 @@ exports.mcp = new commander_1.Command("mcp")
485
649
  return err(`Directory not found: ${args.root}`);
486
650
  }
487
651
  displayRoot = searchRoot;
488
- pathPrefix = searchRoot.endsWith("/")
489
- ? searchRoot
490
- : `${searchRoot}/`;
652
+ pathPrefix = searchRoot.endsWith("/") ? searchRoot : `${searchRoot}/`;
491
653
  if (typeof args.path === "string") {
492
654
  pathPrefix = path.join(searchRoot, args.path);
493
655
  if (!pathPrefix.endsWith("/"))
@@ -510,9 +672,7 @@ exports.mcp = new commander_1.Command("mcp")
510
672
  if (searchAll) {
511
673
  const allProjects = (0, project_registry_1.listProjects)();
512
674
  if (typeof args.projects === "string" && args.projects) {
513
- const names = args.projects
514
- .split(",")
515
- .map((s) => s.trim());
675
+ const names = args.projects.split(",").map((s) => s.trim());
516
676
  const roots = names
517
677
  .map((n) => { var _a; return (_a = allProjects.find((p) => p.name === n)) === null || _a === void 0 ? void 0 : _a.root; })
518
678
  .filter(Boolean);
@@ -542,6 +702,30 @@ exports.mcp = new commander_1.Command("mcp")
542
702
  const detail = typeof args.detail === "string" ? args.detail : "pointer";
543
703
  const includeImports = Boolean(args.include_imports);
544
704
  const importCache = new Map();
705
+ const namePattern = typeof args.name_pattern === "string" ? args.name_pattern : "";
706
+ const mode = typeof args.mode === "string" ? args.mode : "default";
707
+ const getImportsForFile = (absPath) => {
708
+ var _a;
709
+ if (!includeImports || !absPath)
710
+ return "";
711
+ if (!importCache.has(absPath)) {
712
+ importCache.set(absPath, (0, import_extractor_1.extractImports)(absPath));
713
+ }
714
+ return (_a = importCache.get(absPath)) !== null && _a !== void 0 ? _a : "";
715
+ };
716
+ if (detail === "pointer" && mode !== "symbol") {
717
+ const output = formatMcpPointerSearchResults(result.data, displayRoot, {
718
+ minScore,
719
+ maxPerFile,
720
+ namePattern,
721
+ includeImports,
722
+ getImportsForFile,
723
+ });
724
+ if ((_a = result.warnings) === null || _a === void 0 ? void 0 : _a.length) {
725
+ return ok(`${result.warnings.join("\n")}\n\n${output}`);
726
+ }
727
+ return ok(output);
728
+ }
545
729
  let results = result.data.map((r) => {
546
730
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
547
731
  const absPath = (_c = (_a = r.path) !== null && _a !== void 0 ? _a : (_b = r.metadata) === null || _b === void 0 ? void 0 : _b.path) !== null && _c !== void 0 ? _c : "";
@@ -558,17 +742,11 @@ exports.mcp = new commander_1.Command("mcp")
558
742
  const complexity = typeof r.complexity === "number" && r.complexity > 0
559
743
  ? ` C:${Math.round(r.complexity)}`
560
744
  : "";
561
- const parentStr = r.parent_symbol
562
- ? `parent:${r.parent_symbol} `
563
- : "";
564
- const callsStr = refs.length > 0
565
- ? `calls:${refs.slice(0, 8).join(",")}`
566
- : "";
745
+ const parentStr = r.parent_symbol ? `parent:${r.parent_symbol} ` : "";
746
+ const callsStr = refs.length > 0 ? `calls:${refs.slice(0, 8).join(",")}` : "";
567
747
  const line1 = `${symbol} [${exported}${role}${complexity}] ${relPath}:${startLine + 1}-${endLine + 1}`;
568
748
  const summaryStr = r.summary ? ` ${r.summary}` : "";
569
- const line2 = parentStr || callsStr
570
- ? ` ${parentStr}${callsStr}`
571
- : "";
749
+ const line2 = parentStr || callsStr ? ` ${parentStr}${callsStr}` : "";
572
750
  let snippet = "";
573
751
  const contextN = typeof args.context_lines === "number"
574
752
  ? Math.min(Math.max(args.context_lines, 0), 20)
@@ -612,10 +790,7 @@ exports.mcp = new commander_1.Command("mcp")
612
790
  (line2 ? `\n${line2}` : "") +
613
791
  snippet;
614
792
  if (includeImports && absPath) {
615
- if (!importCache.has(absPath)) {
616
- importCache.set(absPath, (0, import_extractor_1.extractImports)(absPath));
617
- }
618
- const imports = importCache.get(absPath);
793
+ const imports = getImportsForFile(absPath);
619
794
  if (imports) {
620
795
  text = `imports:\n${imports}\n\n${text}`;
621
796
  }
@@ -640,21 +815,17 @@ exports.mcp = new commander_1.Command("mcp")
640
815
  return true;
641
816
  });
642
817
  }
643
- const namePattern = typeof args.name_pattern === "string"
644
- ? args.name_pattern
645
- : "";
646
818
  if (namePattern) {
647
819
  try {
648
820
  const regex = new RegExp(namePattern, "i");
649
821
  results = results.filter((r) => r.symbols.some((s) => regex.test(s)));
650
822
  }
651
- catch (_b) {
823
+ catch (_c) {
652
824
  // Invalid regex — skip filter
653
825
  }
654
826
  }
655
827
  let output = results.map((r) => r.text).join("\n\n");
656
828
  // Symbol mode: append call graph
657
- const mode = typeof args.mode === "string" ? args.mode : "default";
658
829
  if (mode === "symbol" && !searchAll) {
659
830
  try {
660
831
  const db = getVectorDb();
@@ -692,11 +863,11 @@ exports.mcp = new commander_1.Command("mcp")
692
863
  output += `\n${traceLines.join("\n")}`;
693
864
  }
694
865
  }
695
- catch (_c) {
866
+ catch (_d) {
696
867
  // Trace failed — return search results without trace
697
868
  }
698
869
  }
699
- if ((_a = result.warnings) === null || _a === void 0 ? void 0 : _a.length) {
870
+ if ((_b = result.warnings) === null || _b === void 0 ? void 0 : _b.length) {
700
871
  return ok(`${result.warnings.join("\n")}\n\n${output}`);
701
872
  }
702
873
  return ok(output);
@@ -727,8 +898,7 @@ exports.mcp = new commander_1.Command("mcp")
727
898
  if (fs.existsSync(absPath) && fs.statSync(absPath).isDirectory()) {
728
899
  const entries = fs.readdirSync(absPath, { withFileTypes: true });
729
900
  targets = entries
730
- .filter((e) => e.isFile() &&
731
- (0, file_utils_1.isIndexableFile)(path.join(absPath, e.name)))
901
+ .filter((e) => e.isFile() && (0, file_utils_1.isIndexableFile)(path.join(absPath, e.name)))
732
902
  .map((e) => path.relative(projectRoot, path.join(absPath, e.name)))
733
903
  .slice(0, fileLimit);
734
904
  if (targets.length === 0) {
@@ -814,9 +984,7 @@ exports.mcp = new commander_1.Command("mcp")
814
984
  }
815
985
  }
816
986
  if (fmt === "json") {
817
- const output = jsonFiles.length === 1
818
- ? jsonFiles[0]
819
- : { files: jsonFiles };
987
+ const output = jsonFiles.length === 1 ? jsonFiles[0] : { files: jsonFiles };
820
988
  return ok(JSON.stringify(output, null, 2));
821
989
  }
822
990
  return ok(parts.join("\n\n---\n\n"));
@@ -912,9 +1080,7 @@ exports.mcp = new commander_1.Command("mcp")
912
1080
  if (!symbol)
913
1081
  return err("Missing required parameter: symbol");
914
1082
  try {
915
- const root = typeof args.root === "string" && args.root
916
- ? args.root
917
- : projectRoot;
1083
+ const root = typeof args.root === "string" && args.root ? args.root : projectRoot;
918
1084
  const db = getVectorDb();
919
1085
  const table = yield db.ensureTable();
920
1086
  const prefix = root.endsWith("/") ? root : `${root}/`;
@@ -1005,9 +1171,7 @@ exports.mcp = new commander_1.Command("mcp")
1005
1171
  if (!symbol)
1006
1172
  return err("Missing required parameter: symbol");
1007
1173
  try {
1008
- const root = typeof args.root === "string" && args.root
1009
- ? args.root
1010
- : projectRoot;
1174
+ const root = typeof args.root === "string" && args.root ? args.root : projectRoot;
1011
1175
  const depth = Math.min(Math.max(Number(args.depth || 1), 1), 3);
1012
1176
  const db = getVectorDb();
1013
1177
  const { GraphBuilder } = yield Promise.resolve().then(() => __importStar(require("../lib/graph/graph-builder")));
@@ -1132,9 +1296,7 @@ exports.mcp = new commander_1.Command("mcp")
1132
1296
  if (!symbol)
1133
1297
  return err("Missing required parameter: symbol");
1134
1298
  try {
1135
- const root = typeof args.root === "string" && args.root
1136
- ? args.root
1137
- : projectRoot;
1299
+ const root = typeof args.root === "string" && args.root ? args.root : projectRoot;
1138
1300
  const db = getVectorDb();
1139
1301
  const table = yield db.ensureTable();
1140
1302
  const prefix = root.endsWith("/") ? root : `${root}/`;
@@ -1191,7 +1353,13 @@ exports.mcp = new commander_1.Command("mcp")
1191
1353
  const table = yield db.ensureTable();
1192
1354
  let query = table
1193
1355
  .query()
1194
- .select(["defined_symbols", "path", "start_line", "role", "is_exported"])
1356
+ .select([
1357
+ "defined_symbols",
1358
+ "path",
1359
+ "start_line",
1360
+ "role",
1361
+ "is_exported",
1362
+ ])
1195
1363
  .where("array_length(defined_symbols) > 0")
1196
1364
  .limit(pattern ? 10000 : Math.max(limit * 50, 2000));
1197
1365
  if (pathPrefix) {
@@ -1282,9 +1450,7 @@ exports.mcp = new commander_1.Command("mcp")
1282
1450
  const lines = [
1283
1451
  `Index: ~/.gmax/lancedb (${stats.chunks} chunks, ${fileCount} files)`,
1284
1452
  `Model: ${globalConfig.embedMode === "gpu" ? ((_d = (_c = (_b = config_1.MODEL_TIERS[globalConfig.modelTier]) === null || _b === void 0 ? void 0 : _b.mlxModel) !== null && _c !== void 0 ? _c : config === null || config === void 0 ? void 0 : config.embedModel) !== null && _d !== void 0 ? _d : "unknown") : ((_e = config === null || config === void 0 ? void 0 : config.embedModel) !== null && _e !== void 0 ? _e : "unknown")} (${(_f = config === null || config === void 0 ? void 0 : config.vectorDim) !== null && _f !== void 0 ? _f : "?"}d, ${globalConfig.embedMode})`,
1285
- (config === null || config === void 0 ? void 0 : config.indexedAt)
1286
- ? `Last indexed: ${config.indexedAt}`
1287
- : "",
1453
+ (config === null || config === void 0 ? void 0 : config.indexedAt) ? `Last indexed: ${config.indexedAt}` : "",
1288
1454
  watcherLine,
1289
1455
  "",
1290
1456
  "Indexed directories:",
@@ -1316,9 +1482,7 @@ exports.mcp = new commander_1.Command("mcp")
1316
1482
  }
1317
1483
  function handleSummarizeDirectory(args) {
1318
1484
  return __awaiter(this, void 0, void 0, function* () {
1319
- const dir = typeof args.path === "string"
1320
- ? path.resolve(args.path)
1321
- : projectRoot;
1485
+ const dir = typeof args.path === "string" ? path.resolve(args.path) : projectRoot;
1322
1486
  const prefix = dir.endsWith("/") ? dir : `${dir}/`;
1323
1487
  const limit = Math.min(Math.max(Number(args.limit) || 200, 1), 5000);
1324
1488
  try {
@@ -1343,9 +1507,7 @@ exports.mcp = new commander_1.Command("mcp")
1343
1507
  function handleSummarizeProject(args) {
1344
1508
  return __awaiter(this, void 0, void 0, function* () {
1345
1509
  var _a;
1346
- const root = typeof args.root === "string"
1347
- ? path.resolve(args.root)
1348
- : projectRoot;
1510
+ const root = typeof args.root === "string" ? path.resolve(args.root) : projectRoot;
1349
1511
  const prefix = root.endsWith("/") ? root : `${root}/`;
1350
1512
  const projectName = path.basename(root);
1351
1513
  try {
@@ -1383,9 +1545,7 @@ exports.mcp = new commander_1.Command("mcp")
1383
1545
  files.add(p);
1384
1546
  const ext = path.extname(p).toLowerCase() || path.basename(p);
1385
1547
  extCounts.set(ext, (extCounts.get(ext) || 0) + 1);
1386
- const rel = p.startsWith(prefix)
1387
- ? p.slice(prefix.length)
1388
- : p;
1548
+ const rel = p.startsWith(prefix) ? p.slice(prefix.length) : p;
1389
1549
  const parts = rel.split("/");
1390
1550
  const dir = parts.length > 2
1391
1551
  ? `${parts.slice(0, 2).join("/")}/`
@@ -1406,9 +1566,7 @@ exports.mcp = new commander_1.Command("mcp")
1406
1566
  role === "ORCHESTRATION" &&
1407
1567
  complexity >= 5 &&
1408
1568
  defs.length > 0) {
1409
- const relPath = p.startsWith(prefix)
1410
- ? p.slice(prefix.length)
1411
- : p;
1569
+ const relPath = p.startsWith(prefix) ? p.slice(prefix.length) : p;
1412
1570
  entryPoints.push({ symbol: defs[0], path: relPath });
1413
1571
  }
1414
1572
  }
@@ -1571,9 +1729,7 @@ exports.mcp = new commander_1.Command("mcp")
1571
1729
  var _a, e_1, _b, _c;
1572
1730
  ensureWatcher();
1573
1731
  const limit = Math.min(Math.max(Number(args.limit) || 20, 1), 50);
1574
- const root = typeof args.root === "string"
1575
- ? path.resolve(args.root)
1576
- : projectRoot;
1732
+ const root = typeof args.root === "string" ? path.resolve(args.root) : projectRoot;
1577
1733
  const prefix = root.endsWith("/") ? root : `${root}/`;
1578
1734
  try {
1579
1735
  const metaCache = new meta_cache_1.MetaCache(config_1.PATHS.lmdbPath);
@@ -1583,7 +1739,7 @@ exports.mcp = new commander_1.Command("mcp")
1583
1739
  for (var _d = true, _e = __asyncValues(metaCache.entries()), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
1584
1740
  _c = _f.value;
1585
1741
  _d = false;
1586
- const { path: p, entry, } = _c;
1742
+ const { path: p, entry } = _c;
1587
1743
  if (p.startsWith(prefix)) {
1588
1744
  files.push({ path: p, mtimeMs: entry.mtimeMs });
1589
1745
  }
@@ -1636,7 +1792,9 @@ exports.mcp = new commander_1.Command("mcp")
1636
1792
  try {
1637
1793
  const changedFiles = getChangedFiles(ref, projectRoot);
1638
1794
  if (changedFiles.length === 0) {
1639
- return ok(ref ? `No changes found relative to ${ref}.` : "No uncommitted changes found.");
1795
+ return ok(ref
1796
+ ? `No changes found relative to ${ref}.`
1797
+ : "No uncommitted changes found.");
1640
1798
  }
1641
1799
  const rel = (p) => p.startsWith(`${projectRoot}/`) ? p.slice(projectRoot.length + 1) : p;
1642
1800
  if (query) {
@@ -1645,7 +1803,9 @@ exports.mcp = new commander_1.Command("mcp")
1645
1803
  const changedSet = new Set(changedFiles);
1646
1804
  let filtered = response.data.filter((r) => changedSet.has(String(r.path || "")));
1647
1805
  if (role)
1648
- filtered = filtered.filter((r) => String(r.role || "").toUpperCase().startsWith(role));
1806
+ filtered = filtered.filter((r) => String(r.role || "")
1807
+ .toUpperCase()
1808
+ .startsWith(role));
1649
1809
  if (filtered.length === 0)
1650
1810
  return ok("No indexed results found in changed files for that query.");
1651
1811
  const lines = filtered.slice(0, limit).map((r) => {
@@ -1659,10 +1819,12 @@ exports.mcp = new commander_1.Command("mcp")
1659
1819
  const table = yield db.ensureTable();
1660
1820
  const lines = [];
1661
1821
  for (const file of changedFiles) {
1662
- const chunks = yield table.query()
1822
+ const chunks = yield table
1823
+ .query()
1663
1824
  .select(["defined_symbols", "role"])
1664
1825
  .where(`path = '${(0, filter_builder_1.escapeSqlString)(file)}'`)
1665
- .limit(50).toArray();
1826
+ .limit(50)
1827
+ .toArray();
1666
1828
  const symbols = chunks.flatMap((c) => toStringArray(c.defined_symbols));
1667
1829
  lines.push(symbols.length > 0
1668
1830
  ? `${rel(file)} (${symbols.slice(0, 5).join(", ")}${symbols.length > 5 ? "..." : ""})`
@@ -1716,7 +1878,9 @@ exports.mcp = new commander_1.Command("mcp")
1716
1878
  const { symbols, resolvedAsFile } = yield resolveTargetSymbols(target, db, projectRoot);
1717
1879
  if (symbols.length === 0)
1718
1880
  return ok(`No symbols found for: ${target}`);
1719
- const targetPath = resolvedAsFile ? path.resolve(projectRoot, target) : undefined;
1881
+ const targetPath = resolvedAsFile
1882
+ ? path.resolve(projectRoot, target)
1883
+ : undefined;
1720
1884
  const excludePaths = targetPath ? new Set([targetPath]) : undefined;
1721
1885
  const [dependents, tests] = yield Promise.all([
1722
1886
  findDependents(symbols, db, projectRoot, excludePaths),
@@ -1762,31 +1926,45 @@ exports.mcp = new commander_1.Command("mcp")
1762
1926
  try {
1763
1927
  const db = getVectorDb();
1764
1928
  const table = yield db.ensureTable();
1765
- const isFile = target.includes("/") || (target.includes(".") && !target.includes(" "));
1929
+ const isFile = target.includes("/") ||
1930
+ (target.includes(".") && !target.includes(" "));
1766
1931
  let sourceRows;
1767
1932
  if (isFile) {
1768
1933
  const absPath = path.resolve(projectRoot, target);
1769
- sourceRows = yield table.query()
1934
+ sourceRows = yield table
1935
+ .query()
1770
1936
  .select(["vector", "path", "start_line"])
1771
1937
  .where(`path = '${(0, filter_builder_1.escapeSqlString)(absPath)}'`)
1772
- .limit(1).toArray();
1938
+ .limit(1)
1939
+ .toArray();
1773
1940
  }
1774
1941
  else {
1775
- sourceRows = yield table.query()
1942
+ sourceRows = yield table
1943
+ .query()
1776
1944
  .select(["vector", "path", "start_line"])
1777
1945
  .where(`array_contains(defined_symbols, '${(0, filter_builder_1.escapeSqlString)(target)}')`)
1778
- .limit(1).toArray();
1946
+ .limit(1)
1947
+ .toArray();
1779
1948
  }
1780
1949
  if (sourceRows.length === 0)
1781
- return ok(isFile ? `File not found: ${target}` : `Symbol not found: ${target}`);
1950
+ return ok(isFile
1951
+ ? `File not found: ${target}`
1952
+ : `Symbol not found: ${target}`);
1782
1953
  const source = sourceRows[0];
1783
1954
  if (!source.vector || source.vector.length === 0)
1784
1955
  return ok("Source chunk has no embedding.");
1785
1956
  const results = yield table
1786
1957
  .vectorSearch(source.vector)
1787
- .select(["path", "start_line", "defined_symbols", "role", "_distance"])
1958
+ .select([
1959
+ "path",
1960
+ "start_line",
1961
+ "defined_symbols",
1962
+ "role",
1963
+ "_distance",
1964
+ ])
1788
1965
  .where(`path LIKE '${(0, filter_builder_1.escapeSqlString)(projectRoot)}/%'`)
1789
- .limit(limit + 5).toArray();
1966
+ .limit(limit + 5)
1967
+ .toArray();
1790
1968
  let filtered = results.filter((r) => !(r.path === source.path && r.start_line === source.start_line));
1791
1969
  if (threshold > 0)
1792
1970
  filtered = filtered.filter((r) => { var _a; return 1 / (1 + ((_a = r._distance) !== null && _a !== void 0 ? _a : 0)) >= threshold; });
@@ -1840,14 +2018,19 @@ exports.mcp = new commander_1.Command("mcp")
1840
2018
  const sym = (_d = (_c = toStringArray(r.defined_symbols)) === null || _c === void 0 ? void 0 : _c[0]) !== null && _d !== void 0 ? _d : "";
1841
2019
  try {
1842
2020
  const content = fs.readFileSync(absP, "utf-8");
1843
- const body = content.split("\n").slice(startLine, endLine + 1).join("\n");
2021
+ const body = content
2022
+ .split("\n")
2023
+ .slice(startLine, endLine + 1)
2024
+ .join("\n");
1844
2025
  const blob = `\n--- ${rel(absP)}:${startLine + 1} ${sym} ---\n${body}`;
1845
2026
  if (tokensUsed + estTokens(blob) > budget)
1846
2027
  break;
1847
2028
  sections.push(blob);
1848
2029
  tokensUsed += estTokens(blob);
1849
2030
  }
1850
- catch ( /* skip unreadable */_e) { /* skip unreadable */ }
2031
+ catch (_e) {
2032
+ /* skip unreadable */
2033
+ }
1851
2034
  }
1852
2035
  sections.push(`\n(~${tokensUsed}/${budget} tokens)`);
1853
2036
  return ok(sections.join("\n"));
@@ -1983,7 +2166,11 @@ exports.mcp = new commander_1.Command("mcp")
1983
2166
  const { readReport } = yield Promise.resolve().then(() => __importStar(require("../lib/llm/report")));
1984
2167
  const report = readReport(projectRoot);
1985
2168
  const entry = report === null || report === void 0 ? void 0 : report.reviews.find((r) => r.commit === rev.commit);
1986
- result = ok(JSON.stringify({ commit: rev.commit, findings: (_a = entry === null || entry === void 0 ? void 0 : entry.findings) !== null && _a !== void 0 ? _a : [], duration: rev.duration }, null, 2));
2169
+ result = ok(JSON.stringify({
2170
+ commit: rev.commit,
2171
+ findings: (_a = entry === null || entry === void 0 ? void 0 : entry.findings) !== null && _a !== void 0 ? _a : [],
2172
+ duration: rev.duration,
2173
+ }, null, 2));
1987
2174
  }
1988
2175
  }
1989
2176
  catch (e) {