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.
- package/README.md +2 -1
- package/dist/commands/context.js +118 -21
- package/dist/commands/mcp.js +305 -118
- package/dist/commands/search.js +40 -102
- package/dist/lib/daemon/daemon.js +105 -1
- package/dist/lib/output/agent-search-formatter.js +163 -0
- package/dist/lib/workers/embeddings/colbert.js +5 -0
- package/dist/lib/workers/embeddings/granite.js +11 -0
- package/dist/lib/workers/orchestrator.js +4 -2
- package/dist/lib/workers/pool.js +187 -15
- package/dist/lib/workers/process-child.js +4 -1
- package/package.json +1 -1
- package/plugins/grepmax/.claude-plugin/plugin.json +1 -1
- package/plugins/grepmax/hooks/start.js +1 -1
- package/plugins/grepmax/skills/grepmax/SKILL.md +4 -2
package/dist/commands/mcp.js
CHANGED
|
@@ -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
|
|
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: {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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: {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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: {
|
|
120
|
-
|
|
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: {
|
|
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: {
|
|
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: {
|
|
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: {
|
|
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: {
|
|
201
|
-
|
|
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: {
|
|
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: {
|
|
222
|
-
|
|
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: {
|
|
251
|
-
|
|
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: {
|
|
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: {
|
|
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: {
|
|
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: {
|
|
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: {
|
|
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: {
|
|
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: {
|
|
314
|
-
|
|
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: {
|
|
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: {
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
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 (
|
|
866
|
+
catch (_d) {
|
|
696
867
|
// Trace failed — return search results without trace
|
|
697
868
|
}
|
|
698
869
|
}
|
|
699
|
-
if ((
|
|
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([
|
|
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
|
|
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
|
|
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 || "")
|
|
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
|
|
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)
|
|
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
|
|
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("/") ||
|
|
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
|
|
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)
|
|
1938
|
+
.limit(1)
|
|
1939
|
+
.toArray();
|
|
1773
1940
|
}
|
|
1774
1941
|
else {
|
|
1775
|
-
sourceRows = yield table
|
|
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)
|
|
1946
|
+
.limit(1)
|
|
1947
|
+
.toArray();
|
|
1779
1948
|
}
|
|
1780
1949
|
if (sourceRows.length === 0)
|
|
1781
|
-
return ok(isFile
|
|
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([
|
|
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)
|
|
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
|
|
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 (
|
|
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({
|
|
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) {
|