grepmax 0.26.43 → 0.26.45
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/.claude-plugin/marketplace.json +1 -1
- package/NOTICE +6 -0
- package/README.md +5 -1
- package/dist/bin.js +4 -0
- package/dist/commands/doctor.js +2 -1
- package/dist/commands/mcp.js +234 -93
- package/dist/commands/project.js +0 -1
- package/dist/commands/similar.js +0 -1
- package/dist/commands/skeleton.js +0 -1
- package/dist/commands/status.js +32 -18
- package/dist/commands/surprises.js +0 -1
- package/dist/commands/symbols.js +0 -1
- package/dist/commands/watch.js +2 -1
- package/dist/eval-like-limit-probe.js +60 -41
- package/dist/lib/analysis/surprising-connections.js +4 -3
- package/dist/lib/daemon/daemon.js +14 -2
- package/dist/lib/daemon/graph-handler.js +33 -33
- package/dist/lib/daemon/rows-handler.js +13 -51
- package/dist/lib/daemon/vector-handler.js +18 -17
- package/dist/lib/graph/graph-builder.js +33 -16
- package/dist/lib/graph/impact.js +9 -8
- package/dist/lib/index/index-config.js +2 -2
- package/dist/lib/llm/config.js +9 -3
- package/dist/lib/llm/tools.js +5 -4
- package/dist/lib/output/mcp-results.js +177 -0
- package/dist/lib/search/pagerank.js +2 -1
- package/dist/lib/search/searcher.js +5 -4
- package/dist/lib/skeleton/retriever.js +2 -1
- package/dist/lib/store/lance-sdk.js +46 -0
- package/dist/lib/store/vector-db.js +57 -16
- package/dist/lib/utils/cross-project.js +2 -2
- package/dist/lib/utils/project-registry.js +8 -8
- package/dist/lib/utils/query-timeout.js +53 -13
- package/dist/lib/utils/store-access.js +6 -5
- package/dist/lib/utils/store-context.js +102 -0
- package/dist/lib/utils/stores.js +1 -1
- package/dist/vendor/lancedb/LICENSE +202 -0
- package/dist/vendor/lancedb/NODEJS_THIRD_PARTY_LICENSES.md +668 -0
- package/dist/vendor/lancedb/RUST_THIRD_PARTY_LICENSES.html +14607 -0
- package/dist/vendor/lancedb/arrow.d.ts +296 -0
- package/dist/vendor/lancedb/arrow.js +1145 -0
- package/dist/vendor/lancedb/arrow_type.d.ts +9 -0
- package/dist/vendor/lancedb/arrow_type.js +29 -0
- package/dist/vendor/lancedb/connection.d.ts +508 -0
- package/dist/vendor/lancedb/connection.js +298 -0
- package/dist/vendor/lancedb/embedding/embedding_function.d.ts +103 -0
- package/dist/vendor/lancedb/embedding/embedding_function.js +192 -0
- package/dist/vendor/lancedb/embedding/index.d.ts +37 -0
- package/dist/vendor/lancedb/embedding/index.js +108 -0
- package/dist/vendor/lancedb/embedding/openai.d.ts +16 -0
- package/dist/vendor/lancedb/embedding/openai.js +81 -0
- package/dist/vendor/lancedb/embedding/registry.d.ts +94 -0
- package/dist/vendor/lancedb/embedding/registry.js +221 -0
- package/dist/vendor/lancedb/embedding/transformers.d.ts +36 -0
- package/dist/vendor/lancedb/embedding/transformers.js +110 -0
- package/dist/vendor/lancedb/header.d.ts +162 -0
- package/dist/vendor/lancedb/header.js +217 -0
- package/dist/vendor/lancedb/index.d.ts +246 -0
- package/dist/vendor/lancedb/index.js +176 -0
- package/dist/vendor/lancedb/indices.d.ts +721 -0
- package/dist/vendor/lancedb/indices.js +166 -0
- package/dist/vendor/lancedb/license_header.txt +2 -0
- package/dist/vendor/lancedb/materialized_view.d.ts +69 -0
- package/dist/vendor/lancedb/materialized_view.js +112 -0
- package/dist/vendor/lancedb/merge.d.ts +104 -0
- package/dist/vendor/lancedb/merge.js +120 -0
- package/dist/vendor/lancedb/native.d.ts +1193 -0
- package/dist/vendor/lancedb/native.js +688 -0
- package/dist/vendor/lancedb/oauth.d.ts +66 -0
- package/dist/vendor/lancedb/oauth.js +15 -0
- package/dist/vendor/lancedb/otel.d.ts +26 -0
- package/dist/vendor/lancedb/otel.js +114 -0
- package/dist/vendor/lancedb/permutation.d.ts +143 -0
- package/dist/vendor/lancedb/permutation.js +184 -0
- package/dist/vendor/lancedb/provenance.json +6 -0
- package/dist/vendor/lancedb/query.d.ts +663 -0
- package/dist/vendor/lancedb/query.js +966 -0
- package/dist/vendor/lancedb/rerankers/index.d.ts +5 -0
- package/dist/vendor/lancedb/rerankers/index.js +19 -0
- package/dist/vendor/lancedb/rerankers/rrf.d.ts +14 -0
- package/dist/vendor/lancedb/rerankers/rrf.js +28 -0
- package/dist/vendor/lancedb/sanitize.d.ts +32 -0
- package/dist/vendor/lancedb/sanitize.js +544 -0
- package/dist/vendor/lancedb/scannable.d.ts +92 -0
- package/dist/vendor/lancedb/scannable.js +200 -0
- package/dist/vendor/lancedb/schema.d.ts +16 -0
- package/dist/vendor/lancedb/schema.js +387 -0
- package/dist/vendor/lancedb/table.d.ts +1069 -0
- package/dist/vendor/lancedb/table.js +498 -0
- package/dist/vendor/lancedb/util.d.ts +14 -0
- package/dist/vendor/lancedb/util.js +77 -0
- package/package.json +19 -7
- package/plugins/grepmax/.claude-plugin/plugin.json +1 -1
package/dist/commands/mcp.js
CHANGED
|
@@ -79,11 +79,13 @@ const graph_handler_1 = require("../lib/daemon/graph-handler");
|
|
|
79
79
|
const rows_handler_1 = require("../lib/daemon/rows-handler");
|
|
80
80
|
const vector_handler_1 = require("../lib/daemon/vector-handler");
|
|
81
81
|
const test_hits_1 = require("../lib/graph/test-hits");
|
|
82
|
+
const embedding_generation_1 = require("../lib/index/embedding-generation");
|
|
82
83
|
const embedding_status_1 = require("../lib/index/embedding-status");
|
|
83
84
|
const index_config_1 = require("../lib/index/index-config");
|
|
84
85
|
const syncer_1 = require("../lib/index/syncer");
|
|
85
86
|
const agent_search_formatter_1 = require("../lib/output/agent-search-formatter");
|
|
86
87
|
const index_state_footer_1 = require("../lib/output/index-state-footer");
|
|
88
|
+
const mcp_results_1 = require("../lib/output/mcp-results");
|
|
87
89
|
const searcher_1 = require("../lib/search/searcher");
|
|
88
90
|
const annotator_1 = require("../lib/skeleton/annotator");
|
|
89
91
|
const skeletonizer_1 = require("../lib/skeleton/skeletonizer");
|
|
@@ -100,8 +102,11 @@ const project_registry_1 = require("../lib/utils/project-registry");
|
|
|
100
102
|
const project_root_1 = require("../lib/utils/project-root");
|
|
101
103
|
const scope_filter_1 = require("../lib/utils/scope-filter");
|
|
102
104
|
const store_access_1 = require("../lib/utils/store-access");
|
|
105
|
+
const store_context_1 = require("../lib/utils/store-context");
|
|
106
|
+
const stores_1 = require("../lib/utils/stores");
|
|
103
107
|
const watcher_launcher_1 = require("../lib/utils/watcher-launcher");
|
|
104
108
|
const watcher_store_1 = require("../lib/utils/watcher-store");
|
|
109
|
+
const pool_1 = require("../lib/workers/pool");
|
|
105
110
|
// ---------------------------------------------------------------------------
|
|
106
111
|
// Helpers
|
|
107
112
|
// ---------------------------------------------------------------------------
|
|
@@ -119,8 +124,8 @@ function toStringArray(val) {
|
|
|
119
124
|
}
|
|
120
125
|
return [];
|
|
121
126
|
}
|
|
122
|
-
function ok(text) {
|
|
123
|
-
return { content: [{ type: "text", text }] };
|
|
127
|
+
function ok(text, structuredContent) {
|
|
128
|
+
return Object.assign({ content: [{ type: "text", text }] }, (structuredContent ? { structuredContent } : {}));
|
|
124
129
|
}
|
|
125
130
|
function err(text) {
|
|
126
131
|
return { content: [{ type: "text", text }], isError: true };
|
|
@@ -143,9 +148,6 @@ function isMcpSessionFallback(error) {
|
|
|
143
148
|
/**
|
|
144
149
|
* MCP's read-tool fallback policy, in one object so every tool shares it.
|
|
145
150
|
*
|
|
146
|
-
* - `fallbackOnUnknownVerb` — a daemon older than this build does not know the
|
|
147
|
-
* read verbs (the live 0.26.27 daemon does not); answer from the store rather
|
|
148
|
-
* than failing the tool call. Removed one release after the verbs ship.
|
|
149
151
|
* - `fallbackOnOversize` — the daemon's 2 MB response cap. See
|
|
150
152
|
* `isOversizeError` for why MCP opts in and the CLI does not.
|
|
151
153
|
* - `extraFallback` — the two session-readiness answers above.
|
|
@@ -161,7 +163,6 @@ function isMcpSessionFallback(error) {
|
|
|
161
163
|
const MCP_WATCH_LEASE_RENEW_MS = 5 * 60 * 1000;
|
|
162
164
|
const MCP_WATCH_LEASE_TTL_MS = 3 * MCP_WATCH_LEASE_RENEW_MS;
|
|
163
165
|
const MCP_STORE_FALLBACK = {
|
|
164
|
-
fallbackOnUnknownVerb: true,
|
|
165
166
|
fallbackOnOversize: true,
|
|
166
167
|
extraFallback: isMcpSessionFallback,
|
|
167
168
|
};
|
|
@@ -172,7 +173,6 @@ const MCP_STORE_FALLBACK = {
|
|
|
172
173
|
*/
|
|
173
174
|
function shouldFallbackMcpDaemonSearch(error) {
|
|
174
175
|
return ((0, store_access_1.classifyDaemonError)(error) === "no-daemon" ||
|
|
175
|
-
(0, store_access_1.isUnknownCommandError)(error) ||
|
|
176
176
|
(0, store_access_1.isOversizeError)(error) ||
|
|
177
177
|
isMcpSessionFallback(error));
|
|
178
178
|
}
|
|
@@ -192,14 +192,30 @@ function resolveMcpProject(requested, currentRoot, projects = (0, project_regist
|
|
|
192
192
|
if (byName.length > 1)
|
|
193
193
|
return undefined;
|
|
194
194
|
const resolved = path.resolve(value);
|
|
195
|
-
|
|
195
|
+
const physical = (value) => {
|
|
196
|
+
try {
|
|
197
|
+
return fs.realpathSync(value);
|
|
198
|
+
}
|
|
199
|
+
catch (_a) {
|
|
200
|
+
return path.resolve(value);
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
return projects.find((project) => physical(project.root) === physical(resolved));
|
|
196
204
|
}
|
|
197
205
|
const resolvedCurrent = path.resolve(currentRoot);
|
|
198
|
-
const
|
|
206
|
+
const physical = (value) => {
|
|
207
|
+
try {
|
|
208
|
+
return fs.realpathSync(value);
|
|
209
|
+
}
|
|
210
|
+
catch (_a) {
|
|
211
|
+
return path.resolve(value);
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
const exact = projects.find((project) => physical(project.root) === physical(resolvedCurrent));
|
|
199
215
|
if (exact)
|
|
200
216
|
return exact;
|
|
201
217
|
return projects
|
|
202
|
-
.filter((project) => (0, path_containment_1.isPathWithin)(project.root, resolvedCurrent))
|
|
218
|
+
.filter((project) => (0, path_containment_1.isPathWithin)(physical(project.root), physical(resolvedCurrent)))
|
|
203
219
|
.sort((a, b) => b.root.length - a.root.length)[0];
|
|
204
220
|
}
|
|
205
221
|
function containMcpTarget(root, target) {
|
|
@@ -241,13 +257,13 @@ function searchResultPath(r) {
|
|
|
241
257
|
}
|
|
242
258
|
function searchResultStartLine(r) {
|
|
243
259
|
var _a;
|
|
244
|
-
var _b, _c;
|
|
245
|
-
return Number((_c = (_b = r === null || r === void 0 ? void 0 : r.
|
|
260
|
+
var _b, _c, _d;
|
|
261
|
+
return Number((_d = (_c = (_b = r === null || r === void 0 ? void 0 : r.startLine) !== null && _b !== void 0 ? _b : r === null || r === void 0 ? void 0 : r.start_line) !== null && _c !== void 0 ? _c : (_a = r === null || r === void 0 ? void 0 : r.generated_metadata) === null || _a === void 0 ? void 0 : _a.start_line) !== null && _d !== void 0 ? _d : 0);
|
|
246
262
|
}
|
|
247
263
|
function searchResultEndLine(r, fallbackStart = 0) {
|
|
248
264
|
var _a;
|
|
249
|
-
var _b, _c;
|
|
250
|
-
return Number((_c = (_b = r === null || r === void 0 ? void 0 : r.
|
|
265
|
+
var _b, _c, _d;
|
|
266
|
+
return Number((_d = (_c = (_b = r === null || r === void 0 ? void 0 : r.endLine) !== null && _b !== void 0 ? _b : r === null || r === void 0 ? void 0 : r.end_line) !== null && _c !== void 0 ? _c : (_a = r === null || r === void 0 ? void 0 : r.generated_metadata) === null || _a === void 0 ? void 0 : _a.end_line) !== null && _d !== void 0 ? _d : fallbackStart);
|
|
251
267
|
}
|
|
252
268
|
function filterMcpSearchResults(data, options = {}) {
|
|
253
269
|
var _a, _b;
|
|
@@ -380,6 +396,11 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
380
396
|
// --- Project context ---
|
|
381
397
|
const projectRoot = (0, project_root_1.findProjectRoot)(process.cwd());
|
|
382
398
|
const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
|
|
399
|
+
const currentRoot = () => { var _a; var _b; return (_b = (_a = (0, store_context_1.currentStoreContext)()) === null || _a === void 0 ? void 0 : _a.root) !== null && _b !== void 0 ? _b : projectRoot; };
|
|
400
|
+
const storeProjects = () => { var _a; var _b; return (_b = (_a = (0, store_context_1.currentStoreContext)()) === null || _a === void 0 ? void 0 : _a.projects) !== null && _b !== void 0 ? _b : (0, project_registry_1.listProjects)(); };
|
|
401
|
+
const storeConfig = () => { var _a; var _b; return (_b = (_a = (0, store_context_1.currentStoreContext)()) === null || _a === void 0 ? void 0 : _a.config) !== null && _b !== void 0 ? _b : (0, index_config_1.readGlobalConfig)(); };
|
|
402
|
+
const secondary = () => { var _a; var _b; return (_b = (_a = (0, store_context_1.currentStoreContext)()) === null || _a === void 0 ? void 0 : _a.secondary) !== null && _b !== void 0 ? _b : false; };
|
|
403
|
+
const storeDir = () => { var _a; var _b; return (_b = (_a = (0, store_context_1.currentStoreContext)()) === null || _a === void 0 ? void 0 : _a.lancedbDir) !== null && _b !== void 0 ? _b : paths.lancedbDir; };
|
|
383
404
|
// Propagate project root to worker processes
|
|
384
405
|
process.env.GMAX_PROJECT_ROOT = paths.root;
|
|
385
406
|
// --- Store access ---
|
|
@@ -388,15 +409,15 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
388
409
|
* `inProcess` branch is entered only when no daemon serves the verb.
|
|
389
410
|
*/
|
|
390
411
|
function readStore(name, opts) {
|
|
391
|
-
return (0, store_access_1.withStoreRead)(name, Object.assign(Object.assign({}, opts), MCP_STORE_FALLBACK));
|
|
412
|
+
return (0, store_access_1.withStoreRead)(name, Object.assign(Object.assign(Object.assign({}, opts), MCP_STORE_FALLBACK), { skipDaemon: secondary() }));
|
|
392
413
|
}
|
|
393
414
|
/** Open the shared store for the duration of one fallback, then close it. */
|
|
394
415
|
function localStore(fn) {
|
|
395
|
-
return (0, rows_handler_1.withLocalStore)(
|
|
416
|
+
return (0, rows_handler_1.withLocalStore)(storeDir(), fn, storeConfig().vectorDim);
|
|
396
417
|
}
|
|
397
418
|
/** A graph verb with MCP's fallback allowances. */
|
|
398
419
|
function graphVerb(verb, call) {
|
|
399
|
-
return (0, graph_handler_1.callGraphVerb)(verb, Object.assign(Object.assign({}, call), { fallback: MCP_STORE_FALLBACK }));
|
|
420
|
+
return (0, graph_handler_1.callGraphVerb)(verb, Object.assign(Object.assign({}, call), { fallback: Object.assign(Object.assign({}, MCP_STORE_FALLBACK), (secondary() ? { skipDaemon: true } : {})) }));
|
|
400
421
|
}
|
|
401
422
|
/**
|
|
402
423
|
* MCP tools take no `--in`/`--exclude`, so a tool's scope is always the
|
|
@@ -440,8 +461,16 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
440
461
|
};
|
|
441
462
|
},
|
|
442
463
|
inProcess: () => localStore((deps) => __awaiter(this, void 0, void 0, function* () {
|
|
443
|
-
const
|
|
444
|
-
|
|
464
|
+
const pool = secondary()
|
|
465
|
+
? new pool_1.WorkerPool((0, embedding_generation_1.resolveEmbeddingGeneration)(storeConfig()), storeConfig().embedMode)
|
|
466
|
+
: undefined;
|
|
467
|
+
try {
|
|
468
|
+
const searcher = new searcher_1.Searcher(deps.vectorDb, pool);
|
|
469
|
+
return yield searcher.search(args.query, args.limit, { rerank: args.rerank, seeds: args.seeds }, args.filters, args.pathPrefix);
|
|
470
|
+
}
|
|
471
|
+
finally {
|
|
472
|
+
yield pool === null || pool === void 0 ? void 0 : pool.destroy();
|
|
473
|
+
}
|
|
445
474
|
})),
|
|
446
475
|
daemonErrorMessage: (resp) => [resp.error, resp.hint]
|
|
447
476
|
.filter((value) => typeof value === "string" && value)
|
|
@@ -509,7 +538,7 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
509
538
|
* order. Batched so a per-symbol loop costs one round trip, not hundreds.
|
|
510
539
|
*/
|
|
511
540
|
function locateRows(root, req) {
|
|
512
|
-
return (0, rows_handler_1.readRows)(Object.assign({ name: "locate", projectRoot: root, lancedbDir:
|
|
541
|
+
return (0, rows_handler_1.readRows)(Object.assign({ name: "locate", projectRoot: root, lancedbDir: storeDir(), vectorDim: storeConfig().vectorDim, scope: projectScope(root), fallback: Object.assign(Object.assign({}, MCP_STORE_FALLBACK), { skipDaemon: secondary() }) }, req));
|
|
513
542
|
}
|
|
514
543
|
/**
|
|
515
544
|
* Chunk and file totals for `index_status`, summed per registered project.
|
|
@@ -574,8 +603,8 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
574
603
|
return __awaiter(this, void 0, void 0, function* () {
|
|
575
604
|
if (_indexReady)
|
|
576
605
|
return;
|
|
577
|
-
const projects = (
|
|
578
|
-
const isRegistered = projects.some((p) => p.root ===
|
|
606
|
+
const projects = storeProjects();
|
|
607
|
+
const isRegistered = projects.some((p) => p.root === currentRoot());
|
|
579
608
|
if (isRegistered) {
|
|
580
609
|
_indexReady = true;
|
|
581
610
|
}
|
|
@@ -593,8 +622,10 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
593
622
|
return __awaiter(this, void 0, void 0, function* () {
|
|
594
623
|
var _a;
|
|
595
624
|
try {
|
|
596
|
-
const watchRoot = root !== null && root !== void 0 ? root : (_a = resolveMcpProject(undefined,
|
|
597
|
-
if (!watchRoot
|
|
625
|
+
const watchRoot = root !== null && root !== void 0 ? root : (_a = resolveMcpProject(undefined, currentRoot(), storeProjects())) === null || _a === void 0 ? void 0 : _a.root;
|
|
626
|
+
if (!watchRoot ||
|
|
627
|
+
secondary() ||
|
|
628
|
+
(0, stores_1.matchStore)(watchRoot).kind !== "primary")
|
|
598
629
|
return;
|
|
599
630
|
const result = yield (0, watcher_launcher_1.launchWatcher)(watchRoot, WATCH_LEASE);
|
|
600
631
|
if (result.ok && !result.reused) {
|
|
@@ -614,10 +645,10 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
614
645
|
// covers the cwd, and scope to it instead of silently widening to the whole
|
|
615
646
|
// index. `root` is the registered project root to scope to.
|
|
616
647
|
function resolveRegisteredProject(requested) {
|
|
617
|
-
const project = resolveMcpProject(requested,
|
|
648
|
+
const project = resolveMcpProject(requested, currentRoot(), storeProjects());
|
|
618
649
|
if (project)
|
|
619
650
|
return { proj: project, root: project.root };
|
|
620
|
-
return { proj: undefined, root:
|
|
651
|
+
return { proj: undefined, root: currentRoot() };
|
|
621
652
|
}
|
|
622
653
|
// --- Tool handlers ---
|
|
623
654
|
function handleSemanticSearch(args_1) {
|
|
@@ -648,7 +679,7 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
648
679
|
if (typeof args.root === "string") {
|
|
649
680
|
return err("Project not added to gmax yet. Run `gmax add` to index it first.");
|
|
650
681
|
}
|
|
651
|
-
const indexed = (
|
|
682
|
+
const indexed = storeProjects().filter((p) => { var _a; return p.status !== "pending" && ((_a = p.chunkCount) !== null && _a !== void 0 ? _a : 0) > 0; });
|
|
652
683
|
if (indexed.length === 0) {
|
|
653
684
|
return err("No indexed projects yet. cd into a repo and run `gmax add` to index it first.");
|
|
654
685
|
}
|
|
@@ -692,7 +723,7 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
692
723
|
excludeProjects: typeof args.exclude_projects === "string"
|
|
693
724
|
? args.exclude_projects
|
|
694
725
|
: undefined,
|
|
695
|
-
});
|
|
726
|
+
}, storeProjects());
|
|
696
727
|
if (crossScope.projectRoots.length === 0) {
|
|
697
728
|
return err("No matching indexed projects.");
|
|
698
729
|
}
|
|
@@ -709,7 +740,7 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
709
740
|
const selectedRoots = searchAll
|
|
710
741
|
? new Set((_a = filters.projectRoots) !== null && _a !== void 0 ? _a : [])
|
|
711
742
|
: new Set([resolvedRoot]);
|
|
712
|
-
(0, embedding_status_1.assertEmbeddingSearchCompatible)((
|
|
743
|
+
(0, embedding_status_1.assertEmbeddingSearchCompatible)(storeProjects().filter((project) => selectedRoots.has(project.root)), storeConfig());
|
|
713
744
|
// Aider-style seeding: the agent passes its open files / discussed
|
|
714
745
|
// symbols; the searcher biases candidate generation toward them.
|
|
715
746
|
const parseSeedList = (v) => {
|
|
@@ -742,6 +773,26 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
742
773
|
return (candidate.length > 0 &&
|
|
743
774
|
allowedRoots.some((root) => (0, path_containment_1.isPathWithin)(root, candidate)));
|
|
744
775
|
});
|
|
776
|
+
const structuredSearch = (matches) => { var _a; return ({
|
|
777
|
+
schemaVersion: 1,
|
|
778
|
+
query,
|
|
779
|
+
roots: allowedRoots,
|
|
780
|
+
warnings: ((_a = result.warnings) !== null && _a !== void 0 ? _a : []).filter(Boolean),
|
|
781
|
+
matches: matches.map((r) => {
|
|
782
|
+
var _a;
|
|
783
|
+
const startLine = searchResultStartLine(r);
|
|
784
|
+
return {
|
|
785
|
+
path: chunkAbsPath(r),
|
|
786
|
+
startLine: startLine + 1,
|
|
787
|
+
endLine: searchResultEndLine(r, startLine) + 1,
|
|
788
|
+
symbols: chunkSymbols(r),
|
|
789
|
+
role: String((_a = r.role) !== null && _a !== void 0 ? _a : "IMPLEMENTATION"),
|
|
790
|
+
score: typeof r.score === "number" && Number.isFinite(r.score)
|
|
791
|
+
? r.score
|
|
792
|
+
: null,
|
|
793
|
+
};
|
|
794
|
+
}),
|
|
795
|
+
}); };
|
|
745
796
|
// Prepend any searcher warnings to whatever body we return.
|
|
746
797
|
const prefixNotes = (body) => {
|
|
747
798
|
var _a;
|
|
@@ -749,7 +800,7 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
749
800
|
return notes.length ? `${notes.join("\n")}\n\n${body}` : body;
|
|
750
801
|
};
|
|
751
802
|
if (!result.data || result.data.length === 0) {
|
|
752
|
-
return ok(prefixNotes("No matches found. Try broadening your query, using fewer keywords, or check `gmax status` to verify the project is indexed."));
|
|
803
|
+
return ok(prefixNotes("No matches found. Try broadening your query, using fewer keywords, or check `gmax status` to verify the project is indexed."), structuredSearch([]));
|
|
753
804
|
}
|
|
754
805
|
const minScore = typeof args.min_score === "number" ? args.min_score : 0;
|
|
755
806
|
const maxPerFile = typeof args.max_per_file === "number" ? args.max_per_file : 0;
|
|
@@ -779,21 +830,25 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
779
830
|
getImportsForFile,
|
|
780
831
|
query,
|
|
781
832
|
});
|
|
782
|
-
return ok(prefixNotes(output)
|
|
833
|
+
return ok(prefixNotes(output), structuredSearch(filterMcpSearchResults(result.data, {
|
|
834
|
+
minScore,
|
|
835
|
+
maxPerFile,
|
|
836
|
+
namePattern,
|
|
837
|
+
})));
|
|
783
838
|
}
|
|
784
839
|
let results = result.data.map((r) => {
|
|
785
|
-
var _a
|
|
786
|
-
var
|
|
787
|
-
const absPath = (
|
|
840
|
+
var _a;
|
|
841
|
+
var _b, _c, _d, _e, _f;
|
|
842
|
+
const absPath = (_c = (_b = r.path) !== null && _b !== void 0 ? _b : (_a = r.metadata) === null || _a === void 0 ? void 0 : _a.path) !== null && _c !== void 0 ? _c : "";
|
|
788
843
|
const relPath = absPath.startsWith(displayRoot)
|
|
789
844
|
? absPath.slice(displayRoot.length + 1)
|
|
790
845
|
: absPath;
|
|
791
|
-
const startLine = (
|
|
792
|
-
const endLine = (
|
|
793
|
-
const defs = toStringArray((
|
|
794
|
-
const refs = toStringArray((
|
|
846
|
+
const startLine = searchResultStartLine(r);
|
|
847
|
+
const endLine = searchResultEndLine(r, startLine);
|
|
848
|
+
const defs = toStringArray((_d = r.definedSymbols) !== null && _d !== void 0 ? _d : r.defined_symbols);
|
|
849
|
+
const refs = toStringArray((_e = r.referenced_symbols) !== null && _e !== void 0 ? _e : r.referencedSymbols);
|
|
795
850
|
const symbol = defs[0] || "(anonymous)";
|
|
796
|
-
const role = ((
|
|
851
|
+
const role = ((_f = r.role) !== null && _f !== void 0 ? _f : "IMPL").slice(0, 4).toUpperCase();
|
|
797
852
|
const exported = r.is_exported ? "exported " : "";
|
|
798
853
|
const complexity = typeof r.complexity === "number" && r.complexity > 0
|
|
799
854
|
? ` C:${Math.round(r.complexity)}`
|
|
@@ -825,7 +880,7 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
825
880
|
.map((l, i) => `${ctxStart + i + 1}│${l}`)
|
|
826
881
|
.join("\n");
|
|
827
882
|
}
|
|
828
|
-
catch (
|
|
883
|
+
catch (_g) {
|
|
829
884
|
// Fall through to chunk content
|
|
830
885
|
}
|
|
831
886
|
}
|
|
@@ -855,6 +910,7 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
855
910
|
}
|
|
856
911
|
}
|
|
857
912
|
return {
|
|
913
|
+
row: r,
|
|
858
914
|
absPath,
|
|
859
915
|
text,
|
|
860
916
|
score: typeof r.score === "number" ? r.score : 0,
|
|
@@ -927,7 +983,7 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
927
983
|
// Trace failed — return search results without trace
|
|
928
984
|
}
|
|
929
985
|
}
|
|
930
|
-
return ok(prefixNotes(output));
|
|
986
|
+
return ok(prefixNotes(output), structuredSearch(results.map((r) => r.row)));
|
|
931
987
|
}
|
|
932
988
|
catch (e) {
|
|
933
989
|
return toolError("Search failed", e);
|
|
@@ -1075,8 +1131,9 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
1075
1131
|
render: (resp) => resp.graph,
|
|
1076
1132
|
inProcess: () => localStore((deps) => (0, graph_handler_1.runGraphTrace)(deps.vectorDb, { symbol, hops: depth, scope })),
|
|
1077
1133
|
});
|
|
1134
|
+
const structured = (0, mcp_results_1.traceResult)(symbol, root, graph);
|
|
1078
1135
|
if (!graph.center) {
|
|
1079
|
-
return ok(`Symbol '${symbol}' not found in the index. Check \`gmax status\` to see which projects are indexed, or try \`gmax search ${symbol}\` to find similar symbols
|
|
1136
|
+
return ok(`Symbol '${symbol}' not found in the index. Check \`gmax status\` to see which projects are indexed, or try \`gmax search ${symbol}\` to find similar symbols.`, structured);
|
|
1080
1137
|
}
|
|
1081
1138
|
const lines = [];
|
|
1082
1139
|
// Center
|
|
@@ -1135,7 +1192,7 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
1135
1192
|
else {
|
|
1136
1193
|
lines.push("Calls: none");
|
|
1137
1194
|
}
|
|
1138
|
-
return ok(lines.join("\n"));
|
|
1195
|
+
return ok(lines.join("\n"), structured);
|
|
1139
1196
|
}
|
|
1140
1197
|
catch (e) {
|
|
1141
1198
|
return toolError("Trace failed", e);
|
|
@@ -1376,16 +1433,17 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
1376
1433
|
render: (resp) => resp.dead,
|
|
1377
1434
|
inProcess: () => localStore((deps) => (0, graph_handler_1.runGraphDead)(deps.vectorDb, { symbol, scope })),
|
|
1378
1435
|
});
|
|
1436
|
+
const structured = (0, mcp_results_1.deadResult)(symbol, root, facts);
|
|
1379
1437
|
if (!facts.found) {
|
|
1380
|
-
return ok(`Symbol '${symbol}' not found in the index. Check \`gmax status\` to see which projects are indexed, or try \`gmax search ${symbol}\` to find similar symbols
|
|
1438
|
+
return ok(`Symbol '${symbol}' not found in the index. Check \`gmax status\` to see which projects are indexed, or try \`gmax search ${symbol}\` to find similar symbols.`, structured);
|
|
1381
1439
|
}
|
|
1382
1440
|
const rel = (p) => p.startsWith(root) ? p.slice(root.length + 1) : p;
|
|
1383
1441
|
const defLoc = `${rel(facts.defPath)}:${facts.defLine + 1}`;
|
|
1384
1442
|
if (facts.callerCount === 0) {
|
|
1385
1443
|
if (facts.isExported) {
|
|
1386
|
-
return ok(`PUBLIC EXPORT ${defLoc} defines ${symbol} — no internal callers found; check external usage
|
|
1444
|
+
return ok(`PUBLIC EXPORT ${defLoc} defines ${symbol} — no internal callers found; check external usage`, structured);
|
|
1387
1445
|
}
|
|
1388
|
-
return ok(`DEAD ${defLoc} defines ${symbol}
|
|
1446
|
+
return ok(`DEAD ${defLoc} defines ${symbol}`, structured);
|
|
1389
1447
|
}
|
|
1390
1448
|
const top = facts.topCallers;
|
|
1391
1449
|
const lines = [
|
|
@@ -1394,7 +1452,7 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
1394
1452
|
for (const c of top) {
|
|
1395
1453
|
lines.push(` ${rel(c.file)}:${c.line + 1}`);
|
|
1396
1454
|
}
|
|
1397
|
-
return ok(lines.join("\n"));
|
|
1455
|
+
return ok(lines.join("\n"), structured);
|
|
1398
1456
|
}
|
|
1399
1457
|
catch (e) {
|
|
1400
1458
|
return toolError("Dead check failed", e);
|
|
@@ -1711,26 +1769,38 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
1711
1769
|
});
|
|
1712
1770
|
}
|
|
1713
1771
|
function handleListProjects() {
|
|
1714
|
-
return __awaiter(this,
|
|
1772
|
+
return __awaiter(this, arguments, void 0, function* (args = {}) {
|
|
1715
1773
|
var _a;
|
|
1716
1774
|
try {
|
|
1717
|
-
const
|
|
1718
|
-
|
|
1775
|
+
const inventory = args.root === undefined ? (0, store_context_1.storeInventory)() : [];
|
|
1776
|
+
const projects = [
|
|
1777
|
+
...storeProjects(),
|
|
1778
|
+
...inventory
|
|
1779
|
+
.filter((store) => { var _a; var _b; return store.home !==
|
|
1780
|
+
((_b = (_a = (0, store_context_1.currentStoreContext)()) === null || _a === void 0 ? void 0 : _a.home) !== null && _b !== void 0 ? _b : config_1.PATHS.globalRoot); })
|
|
1781
|
+
.flatMap((store) => store.projects),
|
|
1782
|
+
];
|
|
1783
|
+
if (projects.length === 0 && inventory.length === 0) {
|
|
1719
1784
|
return ok("No projects indexed yet. cd into a repo and run `gmax add` to index it.");
|
|
1720
1785
|
}
|
|
1721
|
-
const currentName = (_a = resolveMcpProject(undefined,
|
|
1722
|
-
const globalConfig = (
|
|
1786
|
+
const currentName = (_a = resolveMcpProject(undefined, currentRoot(), storeProjects())) === null || _a === void 0 ? void 0 : _a.name;
|
|
1787
|
+
const globalConfig = storeConfig();
|
|
1723
1788
|
const lines = projects.map((p) => {
|
|
1724
1789
|
const here = p.name === currentName ? " (current)" : "";
|
|
1725
1790
|
const chunks = typeof p.chunkCount === "number"
|
|
1726
1791
|
? `\t(${p.chunkCount} chunks)`
|
|
1727
1792
|
: "";
|
|
1728
|
-
const
|
|
1793
|
+
const matching = inventory.find((store) => store.projects.some((project) => project.root === p.root));
|
|
1794
|
+
const identity = (0, embedding_status_1.projectEmbeddingStatus)(p, matching ? (0, index_config_1.readGlobalConfig)(matching.home) : globalConfig);
|
|
1729
1795
|
return `${p.name}${here}\t${p.root}\t${p.status}\tembedding=${identity.state}${chunks}`;
|
|
1730
1796
|
});
|
|
1731
1797
|
return ok(`${projects.length} indexed project(s). ` +
|
|
1732
1798
|
`Pass a name to semantic_search via projects:"name", or use scope:"all".\n\n` +
|
|
1733
|
-
lines.join("\n")
|
|
1799
|
+
lines.join("\n") +
|
|
1800
|
+
inventory
|
|
1801
|
+
.filter((store) => store.state !== "mounted")
|
|
1802
|
+
.map((store) => `\nStore ${store.home}: ${store.state}${store.error ? ` — ${store.error}` : ""}`)
|
|
1803
|
+
.join(""));
|
|
1734
1804
|
}
|
|
1735
1805
|
catch (e) {
|
|
1736
1806
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -1740,20 +1810,22 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
1740
1810
|
}
|
|
1741
1811
|
function handleIndexStatus() {
|
|
1742
1812
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1743
|
-
var _a, _b;
|
|
1813
|
+
var _a, _b, _c, _d, _e;
|
|
1744
1814
|
try {
|
|
1745
|
-
const globalConfig = (
|
|
1746
|
-
const projects = (
|
|
1747
|
-
const currentProject = resolveMcpProject(undefined,
|
|
1815
|
+
const globalConfig = storeConfig();
|
|
1816
|
+
const projects = storeProjects();
|
|
1817
|
+
const currentProject = resolveMcpProject(undefined, currentRoot(), storeProjects());
|
|
1748
1818
|
const identity = (0, embedding_status_1.projectEmbeddingStatus)(currentProject, globalConfig);
|
|
1749
1819
|
const { chunks, files } = yield indexTotals(projects);
|
|
1750
|
-
const daemonStatus =
|
|
1820
|
+
const daemonStatus = secondary()
|
|
1821
|
+
? { ok: true, projects: [] }
|
|
1822
|
+
: yield (0, daemon_client_1.sendDaemonCommand)({ cmd: "status" });
|
|
1751
1823
|
const watched = (Array.isArray(daemonStatus.projects) ? daemonStatus.projects : []);
|
|
1752
1824
|
const daemonProject = watched.find((p) => p.root === (currentProject === null || currentProject === void 0 ? void 0 : currentProject.root));
|
|
1753
1825
|
// Only use the registry when no daemon answered; sandboxed reads stay IPC-only.
|
|
1754
1826
|
const watcher = daemonStatus.ok
|
|
1755
1827
|
? undefined
|
|
1756
|
-
: (0, watcher_store_1.getWatcherCoveringPath)(
|
|
1828
|
+
: (0, watcher_store_1.getWatcherCoveringPath)(currentRoot());
|
|
1757
1829
|
let watcherLine = "Watcher: not running";
|
|
1758
1830
|
if (watcher) {
|
|
1759
1831
|
const status = (_a = watcher.status) !== null && _a !== void 0 ? _a : "unknown";
|
|
@@ -1778,7 +1850,7 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
1778
1850
|
// per-project chunk counts) lives in `list_projects` — keep this tool
|
|
1779
1851
|
// focused on index health and avoid the N-project LanceDB scans.
|
|
1780
1852
|
const lines = [
|
|
1781
|
-
`Index:
|
|
1853
|
+
`Index: ${storeDir()} (${chunks} chunks, ${files} files)`,
|
|
1782
1854
|
`Configured embedding: ${identity.configured.tier} ${identity.configured.vectorDim}d [${(0, embedding_status_1.embeddingFingerprintLabel)(identity.configured.fingerprint)}] (${globalConfig.embedMode})`,
|
|
1783
1855
|
identity.built
|
|
1784
1856
|
? `Built embedding: ${identity.built.tier} ${identity.built.vectorDim}d [${(0, embedding_status_1.embeddingFingerprintLabel)(identity.built.fingerprint)}] (${identity.state})`
|
|
@@ -1790,7 +1862,36 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
1790
1862
|
(0, compaction_result_1.formatCompactionStatus)(daemonStatus.compaction),
|
|
1791
1863
|
`Projects: ${projects.length} indexed (call list_projects for names + per-project chunk counts)`,
|
|
1792
1864
|
].filter(Boolean);
|
|
1793
|
-
|
|
1865
|
+
const compaction = mcp_results_1.compactionSchema.safeParse(daemonStatus.compaction);
|
|
1866
|
+
return ok(lines.join("\n"), {
|
|
1867
|
+
schemaVersion: 1,
|
|
1868
|
+
root: currentRoot(),
|
|
1869
|
+
store: storeDir(),
|
|
1870
|
+
secondary: secondary(),
|
|
1871
|
+
chunks,
|
|
1872
|
+
files,
|
|
1873
|
+
projects: projects.length,
|
|
1874
|
+
embedding: {
|
|
1875
|
+
state: identity.state,
|
|
1876
|
+
configured: {
|
|
1877
|
+
tier: identity.configured.tier,
|
|
1878
|
+
vectorDim: identity.configured.vectorDim,
|
|
1879
|
+
fingerprint: identity.configured.fingerprint,
|
|
1880
|
+
},
|
|
1881
|
+
built: identity.built
|
|
1882
|
+
? {
|
|
1883
|
+
tier: identity.built.tier,
|
|
1884
|
+
vectorDim: identity.built.vectorDim,
|
|
1885
|
+
fingerprint: identity.built.fingerprint,
|
|
1886
|
+
}
|
|
1887
|
+
: null,
|
|
1888
|
+
},
|
|
1889
|
+
watcher: {
|
|
1890
|
+
status: (_d = (_c = daemonProject === null || daemonProject === void 0 ? void 0 : daemonProject.status) !== null && _c !== void 0 ? _c : watcher === null || watcher === void 0 ? void 0 : watcher.status) !== null && _d !== void 0 ? _d : (secondary() || !daemonStatus.ok ? "unobserved" : "not_running"),
|
|
1891
|
+
indexState: (_e = daemonProject === null || daemonProject === void 0 ? void 0 : daemonProject.indexState) !== null && _e !== void 0 ? _e : null,
|
|
1892
|
+
},
|
|
1893
|
+
compaction: compaction.success ? compaction.data : null,
|
|
1894
|
+
});
|
|
1794
1895
|
}
|
|
1795
1896
|
catch (e) {
|
|
1796
1897
|
return toolError("Status check failed", e);
|
|
@@ -2001,6 +2102,8 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
2001
2102
|
function handleRecentChanges(args) {
|
|
2002
2103
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2003
2104
|
var _a, e_1, _b, _c;
|
|
2105
|
+
var _d;
|
|
2106
|
+
var _e;
|
|
2004
2107
|
ensureWatcher();
|
|
2005
2108
|
const limit = Math.min(Math.max(Number(args.limit) || 20, 1), 50);
|
|
2006
2109
|
const { proj, root } = resolveRegisteredProject(args.root);
|
|
@@ -2008,13 +2111,13 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
2008
2111
|
return err("Project not added to gmax yet.");
|
|
2009
2112
|
const prefix = root.endsWith("/") ? root : `${root}/`;
|
|
2010
2113
|
try {
|
|
2011
|
-
const metaCache = new meta_cache_1.MetaCache(config_1.PATHS.lmdbPath);
|
|
2114
|
+
const metaCache = new meta_cache_1.MetaCache((_e = (_d = (0, store_context_1.currentStoreContext)()) === null || _d === void 0 ? void 0 : _d.lmdbPath) !== null && _e !== void 0 ? _e : config_1.PATHS.lmdbPath);
|
|
2012
2115
|
try {
|
|
2013
2116
|
const files = [];
|
|
2014
2117
|
try {
|
|
2015
|
-
for (var
|
|
2016
|
-
_c =
|
|
2017
|
-
|
|
2118
|
+
for (var _f = true, _g = __asyncValues(metaCache.entries()), _h; _h = yield _g.next(), _a = _h.done, !_a; _f = true) {
|
|
2119
|
+
_c = _h.value;
|
|
2120
|
+
_f = false;
|
|
2018
2121
|
const { path: p, entry } = _c;
|
|
2019
2122
|
if (p.startsWith(prefix)) {
|
|
2020
2123
|
files.push({ path: p, mtimeMs: entry.mtimeMs });
|
|
@@ -2024,7 +2127,7 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
2024
2127
|
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
2025
2128
|
finally {
|
|
2026
2129
|
try {
|
|
2027
|
-
if (!
|
|
2130
|
+
if (!_f && !_a && (_b = _g.return)) yield _b.call(_g);
|
|
2028
2131
|
}
|
|
2029
2132
|
finally { if (e_1) throw e_1.error; }
|
|
2030
2133
|
}
|
|
@@ -2069,7 +2172,7 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
2069
2172
|
const { proj, root } = resolveRegisteredProject();
|
|
2070
2173
|
if (!proj)
|
|
2071
2174
|
return err("Project not added to gmax yet.");
|
|
2072
|
-
(0, embedding_status_1.assertEmbeddingSearchCompatible)([proj], (
|
|
2175
|
+
(0, embedding_status_1.assertEmbeddingSearchCompatible)([proj], storeConfig());
|
|
2073
2176
|
const changedFiles = getChangedFiles(ref, root);
|
|
2074
2177
|
if (changedFiles.length === 0) {
|
|
2075
2178
|
return ok(ref
|
|
@@ -2269,7 +2372,7 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
2269
2372
|
const { proj, root } = resolveRegisteredProject();
|
|
2270
2373
|
if (!proj)
|
|
2271
2374
|
return err("Project not added to gmax yet.");
|
|
2272
|
-
(0, embedding_status_1.assertEmbeddingSearchCompatible)([proj], (
|
|
2375
|
+
(0, embedding_status_1.assertEmbeddingSearchCompatible)([proj], storeConfig());
|
|
2273
2376
|
const isFile = target.includes("/") ||
|
|
2274
2377
|
(target.includes(".") && !target.includes(" "));
|
|
2275
2378
|
// Resolved here: containment is this process's filesystem question.
|
|
@@ -2335,7 +2438,7 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
2335
2438
|
const { proj, root } = resolveRegisteredProject();
|
|
2336
2439
|
if (!proj)
|
|
2337
2440
|
return err("Project not added to gmax yet.");
|
|
2338
|
-
(0, embedding_status_1.assertEmbeddingSearchCompatible)([proj], (
|
|
2441
|
+
(0, embedding_status_1.assertEmbeddingSearchCompatible)([proj], storeConfig());
|
|
2339
2442
|
const searchOptions = { rerank: process.env.GMAX_RERANK === "1" };
|
|
2340
2443
|
const response = yield searchStore(Object.assign({ projectRoot: root, query: topic, limit, filters: {}, pathPrefix: root }, searchOptions));
|
|
2341
2444
|
if (response.data.length === 0)
|
|
@@ -2405,7 +2508,11 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
2405
2508
|
return err("LLM server not available. Run `gmax llm on && gmax llm start`.");
|
|
2406
2509
|
}
|
|
2407
2510
|
const { investigate } = yield Promise.resolve().then(() => __importStar(require("../lib/llm/investigate")));
|
|
2408
|
-
const inv = yield investigate({
|
|
2511
|
+
const inv = yield investigate({
|
|
2512
|
+
question,
|
|
2513
|
+
projectRoot: currentRoot(),
|
|
2514
|
+
maxRounds,
|
|
2515
|
+
});
|
|
2409
2516
|
return ok(inv.answer);
|
|
2410
2517
|
}
|
|
2411
2518
|
catch (e) {
|
|
@@ -2429,12 +2536,15 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
2429
2536
|
return err("LLM server not available. Run `gmax llm on && gmax llm start`.");
|
|
2430
2537
|
}
|
|
2431
2538
|
const { reviewCommit } = yield Promise.resolve().then(() => __importStar(require("../lib/llm/review")));
|
|
2432
|
-
const rev = yield reviewCommit({
|
|
2539
|
+
const rev = yield reviewCommit({
|
|
2540
|
+
commitRef,
|
|
2541
|
+
projectRoot: currentRoot(),
|
|
2542
|
+
});
|
|
2433
2543
|
if (rev.clean) {
|
|
2434
2544
|
return ok(`Clean commit (${rev.commit}) — no issues found in ${rev.duration}s.`);
|
|
2435
2545
|
}
|
|
2436
2546
|
const { readReport } = yield Promise.resolve().then(() => __importStar(require("../lib/llm/report")));
|
|
2437
|
-
const report = readReport(
|
|
2547
|
+
const report = readReport(currentRoot());
|
|
2438
2548
|
const entry = report === null || report === void 0 ? void 0 : report.reviews.find((r) => r.commit === rev.commit);
|
|
2439
2549
|
return ok(JSON.stringify({
|
|
2440
2550
|
commit: rev.commit,
|
|
@@ -2459,26 +2569,26 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
2459
2569
|
// returns the location.
|
|
2460
2570
|
const { extractDiff, extractSymbols, fileChurn } = yield Promise.resolve().then(() => __importStar(require("../lib/llm/diff")));
|
|
2461
2571
|
const { computeRiskTable, formatRiskTable } = yield Promise.resolve().then(() => __importStar(require("../lib/review/risk")));
|
|
2462
|
-
const diff = extractDiff(commitRef,
|
|
2572
|
+
const diff = extractDiff(commitRef, currentRoot());
|
|
2463
2573
|
const symbols = diff ? extractSymbols(diff) : [];
|
|
2464
2574
|
if (symbols.length === 0) {
|
|
2465
2575
|
return ok("(no changed symbols in this diff)");
|
|
2466
2576
|
}
|
|
2467
|
-
const scope = projectScope(
|
|
2577
|
+
const scope = projectScope(currentRoot());
|
|
2468
2578
|
const facts = yield graphVerb("graph.risk", {
|
|
2469
|
-
projectRoot,
|
|
2579
|
+
projectRoot: currentRoot(),
|
|
2470
2580
|
scope,
|
|
2471
2581
|
payload: { symbols },
|
|
2472
2582
|
render: (resp) => { var _a; return (_a = resp.facts) !== null && _a !== void 0 ? _a : []; },
|
|
2473
2583
|
inProcess: () => localStore((deps) => (0, graph_handler_1.runGraphRisk)(deps.vectorDb, {
|
|
2474
2584
|
symbols,
|
|
2475
|
-
queryRoot:
|
|
2585
|
+
queryRoot: currentRoot(),
|
|
2476
2586
|
scope,
|
|
2477
2587
|
})),
|
|
2478
2588
|
});
|
|
2479
|
-
const prefix =
|
|
2480
|
-
?
|
|
2481
|
-
: `${
|
|
2589
|
+
const prefix = currentRoot().endsWith("/")
|
|
2590
|
+
? currentRoot()
|
|
2591
|
+
: `${currentRoot()}/`;
|
|
2482
2592
|
const rows = computeRiskTable(facts.map((fact) => ({
|
|
2483
2593
|
symbol: fact.symbol,
|
|
2484
2594
|
file: fact.file
|
|
@@ -2489,7 +2599,7 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
2489
2599
|
line: fact.line,
|
|
2490
2600
|
callerCount: fact.callerCount,
|
|
2491
2601
|
hasTests: fact.hasTests,
|
|
2492
|
-
churn: fileChurn(fact.file,
|
|
2602
|
+
churn: fileChurn(fact.file, currentRoot()),
|
|
2493
2603
|
})));
|
|
2494
2604
|
return rows.length === 0
|
|
2495
2605
|
? ok("(no changed symbols in this diff)")
|
|
@@ -2504,7 +2614,7 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
2504
2614
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2505
2615
|
try {
|
|
2506
2616
|
const { readReport, formatReportText } = yield Promise.resolve().then(() => __importStar(require("../lib/llm/report")));
|
|
2507
|
-
const report = readReport(
|
|
2617
|
+
const report = readReport(currentRoot());
|
|
2508
2618
|
if (!report || report.reviews.length === 0) {
|
|
2509
2619
|
return ok("No review findings yet.");
|
|
2510
2620
|
}
|
|
@@ -2519,6 +2629,7 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
2519
2629
|
});
|
|
2520
2630
|
}
|
|
2521
2631
|
// --- MCP server setup ---
|
|
2632
|
+
// Local-only MCP: client-owned pipes, no HTTP/SSE/TCP listener or host option.
|
|
2522
2633
|
const transport = new stdio_js_1.StdioServerTransport();
|
|
2523
2634
|
const server = new mcp_js_1.McpServer({
|
|
2524
2635
|
name: "gmax",
|
|
@@ -2554,7 +2665,7 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
2554
2665
|
source: "mcp",
|
|
2555
2666
|
tool: name,
|
|
2556
2667
|
query: mcpLogQuery(name, toolArgs),
|
|
2557
|
-
project:
|
|
2668
|
+
project: currentRoot(),
|
|
2558
2669
|
results: resultLines,
|
|
2559
2670
|
ms: Date.now() - startMs,
|
|
2560
2671
|
error: result.isError ? text.slice(0, 200) : undefined,
|
|
@@ -2566,21 +2677,51 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
2566
2677
|
// shapes give us free input validation (the SDK rejects calls that violate
|
|
2567
2678
|
// the schema before the handler runs); handlers stay defensively coded.
|
|
2568
2679
|
function tool(name, config, handler) {
|
|
2569
|
-
server.registerTool(name,
|
|
2680
|
+
server.registerTool(name, Object.assign(Object.assign(Object.assign({}, config), (mcp_results_1.MCP_READ_OUTPUT_SCHEMAS[name]
|
|
2681
|
+
? {
|
|
2682
|
+
outputSchema: mcp_results_1.MCP_READ_OUTPUT_SCHEMAS[name],
|
|
2683
|
+
annotations: {
|
|
2684
|
+
readOnlyHint: true,
|
|
2685
|
+
destructiveHint: false,
|
|
2686
|
+
openWorldHint: false,
|
|
2687
|
+
},
|
|
2688
|
+
}
|
|
2689
|
+
: {})), { inputSchema: Object.assign({ root: zod_1.z.string().optional() }, config.inputSchema) }), (rawArgs) => __awaiter(this, void 0, void 0, function* () {
|
|
2570
2690
|
let args = (rawArgs !== null && rawArgs !== void 0 ? rawArgs : {});
|
|
2571
2691
|
const startMs = Date.now();
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
if (
|
|
2575
|
-
const
|
|
2692
|
+
let target = projectRoot;
|
|
2693
|
+
try {
|
|
2694
|
+
if (typeof args.root === "string" && args.root.trim()) {
|
|
2695
|
+
const raw = args.root.trim();
|
|
2696
|
+
if (path.isAbsolute(raw) || raw.includes(path.sep))
|
|
2697
|
+
target = path.resolve(raw);
|
|
2698
|
+
else {
|
|
2699
|
+
const projects = [
|
|
2700
|
+
...(0, project_registry_1.listProjects)(),
|
|
2701
|
+
...(0, store_context_1.storeInventory)().flatMap((store) => store.projects),
|
|
2702
|
+
].filter((project, i, all) => all.findIndex((p) => p.root === project.root) === i);
|
|
2703
|
+
const selected = resolveMcpProject(raw, projectRoot, projects);
|
|
2704
|
+
if (!selected)
|
|
2705
|
+
return err(`Unknown or ambiguous registered project: ${raw}. Use list_projects or an exact root.`);
|
|
2706
|
+
target = selected.root;
|
|
2707
|
+
}
|
|
2708
|
+
}
|
|
2709
|
+
return yield (0, store_context_1.withStoreContext)(target, () => __awaiter(this, void 0, void 0, function* () {
|
|
2710
|
+
if (args.root !== undefined) {
|
|
2711
|
+
const selected = resolveMcpProject(args.root, currentRoot(), storeProjects());
|
|
2712
|
+
if (!selected)
|
|
2713
|
+
return err(`Unknown registered project: ${args.root}. Use list_projects to select a project name or exact root.`);
|
|
2714
|
+
args = Object.assign(Object.assign({}, args), { root: selected.root });
|
|
2715
|
+
(0, store_context_1.currentStoreContext)().root = selected.root;
|
|
2716
|
+
}
|
|
2717
|
+
const result = yield handler(args);
|
|
2576
2718
|
yield logToolCall(name, args, startMs, result);
|
|
2577
2719
|
return result;
|
|
2578
|
-
}
|
|
2579
|
-
|
|
2720
|
+
}));
|
|
2721
|
+
}
|
|
2722
|
+
catch (error) {
|
|
2723
|
+
return toolError("Tool failed", error);
|
|
2580
2724
|
}
|
|
2581
|
-
const result = yield handler(args);
|
|
2582
|
-
yield logToolCall(name, args, startMs, result);
|
|
2583
|
-
return result;
|
|
2584
2725
|
}));
|
|
2585
2726
|
}
|
|
2586
2727
|
tool("semantic_search", {
|