grepmax 0.26.69 → 0.26.71
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/DOCUMENT-SEARCH.md +113 -0
- package/README.md +24 -0
- package/dist/bin.js +11 -2
- package/dist/commands/audit.js +9 -1
- package/dist/commands/mcp.js +16 -3
- package/dist/commands/project.js +7 -1
- package/dist/commands/skeleton.js +13 -10
- package/dist/commands/surprises.js +2 -0
- package/dist/lib/analysis/surprising-connections.js +16 -2
- package/dist/lib/daemon/daemon.js +50 -0
- package/dist/lib/daemon/document-search-handler.js +194 -0
- package/dist/lib/daemon/graph-handler.js +23 -8
- package/dist/lib/daemon/ipc-handler.js +29 -2
- package/dist/lib/daemon/rows-handler.js +48 -4
- package/dist/lib/mcp/document-contract.js +281 -0
- package/dist/lib/mcp/document-search.js +274 -0
- package/dist/lib/output/agent-budget.js +39 -0
- package/dist/lib/output/project-coverage.js +16 -0
- package/dist/lib/store/vector-db.js +13 -0
- package/dist/lib/utils/resource-budget.js +29 -1
- package/dist/lib/workers/embeddings/granite.js +8 -3
- package/dist/lib/workers/embeddings/mlx-client.js +27 -0
- package/dist/lib/workers/orchestrator.js +47 -9
- package/dist/lib/workers/pool.js +85 -3
- package/dist/lib/workers/process-child.js +22 -5
- package/dist/lib/workers/worker.js +4 -1
- package/package.json +5 -3
- package/plugins/grepmax/.claude-plugin/plugin.json +1 -1
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.DOCUMENT_STATES = exports.DOCUMENT_LIMITS = exports.DOCUMENT_CAPABILITIES = exports.DOCUMENT_CONTRACT_VERSION = void 0;
|
|
37
|
+
exports.documentFailure = documentFailure;
|
|
38
|
+
exports.inside = inside;
|
|
39
|
+
exports.selectDocumentContext = selectDocumentContext;
|
|
40
|
+
exports.documentPaths = documentPaths;
|
|
41
|
+
exports.documentCoveragePaths = documentCoveragePaths;
|
|
42
|
+
exports.documentGeneration = documentGeneration;
|
|
43
|
+
exports.documentIndexedAt = documentIndexedAt;
|
|
44
|
+
exports.documentMtime = documentMtime;
|
|
45
|
+
exports.documentIndexState = documentIndexState;
|
|
46
|
+
exports.documentQueryState = documentQueryState;
|
|
47
|
+
exports.canonicalPointer = canonicalPointer;
|
|
48
|
+
// This module is shared by the bridge and daemon. Node built-ins only.
|
|
49
|
+
const fs = __importStar(require("node:fs"));
|
|
50
|
+
const path = __importStar(require("node:path"));
|
|
51
|
+
const stores_1 = require("../utils/stores");
|
|
52
|
+
exports.DOCUMENT_CONTRACT_VERSION = 1;
|
|
53
|
+
exports.DOCUMENT_CAPABILITIES = Object.freeze({
|
|
54
|
+
existingIndexOnly: 1,
|
|
55
|
+
queryLogging: false,
|
|
56
|
+
watch: false,
|
|
57
|
+
runtimeStartup: false,
|
|
58
|
+
});
|
|
59
|
+
exports.DOCUMENT_LIMITS = Object.freeze({
|
|
60
|
+
query: 500,
|
|
61
|
+
prefixes: 32,
|
|
62
|
+
paths: 2000,
|
|
63
|
+
pathBytes: 512 * 1024,
|
|
64
|
+
frameBytes: 1024 * 1024,
|
|
65
|
+
candidates: 50,
|
|
66
|
+
deadlineMs: 10000,
|
|
67
|
+
});
|
|
68
|
+
exports.DOCUMENT_STATES = new Set([
|
|
69
|
+
"unsupported_tool",
|
|
70
|
+
"unsupported_daemon",
|
|
71
|
+
"no_index",
|
|
72
|
+
"index_unavailable",
|
|
73
|
+
"daemon_unavailable",
|
|
74
|
+
"store_unavailable",
|
|
75
|
+
"embedding_unavailable",
|
|
76
|
+
"embedding_mismatch",
|
|
77
|
+
"host_pressure",
|
|
78
|
+
"busy",
|
|
79
|
+
"cancelled",
|
|
80
|
+
"timeout",
|
|
81
|
+
"no_coverage",
|
|
82
|
+
"search_unavailable",
|
|
83
|
+
]);
|
|
84
|
+
function documentFailure(state) {
|
|
85
|
+
return {
|
|
86
|
+
ok: false,
|
|
87
|
+
state: exports.DOCUMENT_STATES.has(state) ? state : "search_unavailable",
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function inside(parent, child) {
|
|
91
|
+
const rel = path.relative(parent, child);
|
|
92
|
+
return (rel === "" ||
|
|
93
|
+
(!rel.startsWith(`..${path.sep}`) && rel !== ".." && !path.isAbsolute(rel)));
|
|
94
|
+
}
|
|
95
|
+
function selectDocumentContext(home, cwd) {
|
|
96
|
+
const checkout = fs.realpathSync(cwd);
|
|
97
|
+
try {
|
|
98
|
+
if (fs.statSync((0, stores_1.storesFilePath)()).size > exports.DOCUMENT_LIMITS.frameBytes)
|
|
99
|
+
throw new Error("store_unavailable");
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
if (error.code !== "ENOENT")
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
if ((0, stores_1.matchStore)(checkout).kind !== "primary" ||
|
|
106
|
+
process.env.GMAX_SECONDARY_STORE === "1")
|
|
107
|
+
throw new Error("store_unavailable");
|
|
108
|
+
const registry = path.join(home, "projects.json");
|
|
109
|
+
let projects;
|
|
110
|
+
try {
|
|
111
|
+
if (fs.statSync(registry).size > exports.DOCUMENT_LIMITS.frameBytes)
|
|
112
|
+
throw new Error();
|
|
113
|
+
projects = JSON.parse(fs.readFileSync(registry, "utf8"));
|
|
114
|
+
}
|
|
115
|
+
catch (_a) {
|
|
116
|
+
throw new Error("no_index");
|
|
117
|
+
}
|
|
118
|
+
if (!Array.isArray(projects))
|
|
119
|
+
throw new Error("no_index");
|
|
120
|
+
const roots = [];
|
|
121
|
+
for (const project of projects) {
|
|
122
|
+
if (!project ||
|
|
123
|
+
typeof project.root !== "string" ||
|
|
124
|
+
!path.isAbsolute(project.root) ||
|
|
125
|
+
project.status === "error")
|
|
126
|
+
continue;
|
|
127
|
+
try {
|
|
128
|
+
const root = fs.realpathSync(project.root);
|
|
129
|
+
if (inside(root, checkout))
|
|
130
|
+
roots.push({
|
|
131
|
+
root,
|
|
132
|
+
wireRoot: project.root,
|
|
133
|
+
lastIndexed: documentIndexedAt(project.lastIndexed),
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
catch (_b) {
|
|
137
|
+
/* deleted registry root */
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
roots.sort((a, b) => b.root.length - a.root.length);
|
|
141
|
+
if (!roots[0])
|
|
142
|
+
throw new Error("no_index");
|
|
143
|
+
return Object.assign(Object.assign({}, roots[0]), { checkout, store: path.join(home, "lancedb") });
|
|
144
|
+
}
|
|
145
|
+
function documentPaths(value, context, mode) {
|
|
146
|
+
return resolveDocumentPaths(value, context, mode, false).paths;
|
|
147
|
+
}
|
|
148
|
+
/** A disappearing sampled file reduces coverage; it cannot broaden retrieval. */
|
|
149
|
+
function documentCoveragePaths(value, context) {
|
|
150
|
+
return resolveDocumentPaths(value, context, "paths", true);
|
|
151
|
+
}
|
|
152
|
+
function resolveDocumentPaths(value, context, mode, allowMissing) {
|
|
153
|
+
if (!Array.isArray(value) ||
|
|
154
|
+
value.length > exports.DOCUMENT_LIMITS[mode] ||
|
|
155
|
+
(mode === "prefixes" && !value.length) ||
|
|
156
|
+
Buffer.byteLength(JSON.stringify(value)) > exports.DOCUMENT_LIMITS.pathBytes)
|
|
157
|
+
throw new Error("no_coverage");
|
|
158
|
+
const paths = [
|
|
159
|
+
...new Set(value.flatMap((input) => {
|
|
160
|
+
var _a;
|
|
161
|
+
if (typeof input !== "string" ||
|
|
162
|
+
!input ||
|
|
163
|
+
input.includes("\0") ||
|
|
164
|
+
!path.isAbsolute(input))
|
|
165
|
+
throw new Error("no_coverage");
|
|
166
|
+
let real;
|
|
167
|
+
try {
|
|
168
|
+
real = fs.realpathSync(input);
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
const code = error.code;
|
|
172
|
+
if (allowMissing &&
|
|
173
|
+
(code === "ENOENT" || code === "ENOTDIR") &&
|
|
174
|
+
path.extname(input).toLowerCase() === ".md") {
|
|
175
|
+
// Validate the nearest surviving parent too: missing paths outside
|
|
176
|
+
// the selected scope are invalid, not silently accepted coverage.
|
|
177
|
+
let parent = path.dirname(path.resolve(input));
|
|
178
|
+
for (;;) {
|
|
179
|
+
try {
|
|
180
|
+
const realParent = fs.realpathSync(parent);
|
|
181
|
+
if (!inside(context.checkout, realParent) ||
|
|
182
|
+
!inside(context.root, realParent))
|
|
183
|
+
throw new Error("no_coverage");
|
|
184
|
+
return [];
|
|
185
|
+
}
|
|
186
|
+
catch (parentError) {
|
|
187
|
+
if (!["ENOENT", "ENOTDIR"].includes((_a = parentError.code) !== null && _a !== void 0 ? _a : "") ||
|
|
188
|
+
parent === path.dirname(parent))
|
|
189
|
+
throw new Error("no_coverage");
|
|
190
|
+
parent = path.dirname(parent);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
throw new Error("no_coverage");
|
|
195
|
+
}
|
|
196
|
+
if (!inside(context.checkout, real) ||
|
|
197
|
+
!inside(context.root, real) ||
|
|
198
|
+
(mode === "paths" &&
|
|
199
|
+
(path.extname(real).toLowerCase() !== ".md" ||
|
|
200
|
+
!fs.statSync(real).isFile())))
|
|
201
|
+
throw new Error("no_coverage");
|
|
202
|
+
return [path.join(context.wireRoot, path.relative(context.root, real))];
|
|
203
|
+
})),
|
|
204
|
+
];
|
|
205
|
+
if (Buffer.byteLength(JSON.stringify(paths)) > exports.DOCUMENT_LIMITS.pathBytes)
|
|
206
|
+
throw new Error("no_coverage");
|
|
207
|
+
return { paths, requested: new Set(value).size };
|
|
208
|
+
}
|
|
209
|
+
function documentGeneration(value) {
|
|
210
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
|
|
211
|
+
}
|
|
212
|
+
function documentIndexedAt(value) {
|
|
213
|
+
return typeof value === "string" &&
|
|
214
|
+
value.length <= 40 &&
|
|
215
|
+
/^\d{4}-\d{2}-\d{2}(?:T[\d:.]+(?:Z|[+-]\d{2}:\d{2}))?$/.test(value) &&
|
|
216
|
+
Number.isFinite(Date.parse(value))
|
|
217
|
+
? value
|
|
218
|
+
: null;
|
|
219
|
+
}
|
|
220
|
+
function documentMtime(value) {
|
|
221
|
+
return typeof value === "number" &&
|
|
222
|
+
Number.isFinite(value) &&
|
|
223
|
+
value >= 0 &&
|
|
224
|
+
value <= 8640000000000000
|
|
225
|
+
? value
|
|
226
|
+
: null;
|
|
227
|
+
}
|
|
228
|
+
/** Deliberate metadata allowlist; no free-form diagnostics or cached content. */
|
|
229
|
+
function documentIndexState(value) {
|
|
230
|
+
const source = value && typeof value === "object" && !Array.isArray(value)
|
|
231
|
+
? value
|
|
232
|
+
: {};
|
|
233
|
+
const out = {};
|
|
234
|
+
const has = (key) => Object.getOwnPropertyDescriptor(source, key) !== undefined;
|
|
235
|
+
let invalid = typeof source.indexing !== "boolean";
|
|
236
|
+
for (const key of ["indexing", "verifying", "degraded", "catchupRunning"])
|
|
237
|
+
if (typeof source[key] === "boolean")
|
|
238
|
+
out[key] = source[key];
|
|
239
|
+
else if (has(key))
|
|
240
|
+
invalid = true;
|
|
241
|
+
for (const key of ["pendingFiles", "failedFiles", "overflowCount"])
|
|
242
|
+
if (typeof source[key] === "number" &&
|
|
243
|
+
Number.isSafeInteger(source[key]) &&
|
|
244
|
+
source[key] >= 0)
|
|
245
|
+
out[key] = source[key];
|
|
246
|
+
else if (has(key))
|
|
247
|
+
invalid = true;
|
|
248
|
+
for (const key of ["lastReconciledAt", "catchupMs"])
|
|
249
|
+
if (documentMtime(source[key]) !== null)
|
|
250
|
+
out[key] = source[key];
|
|
251
|
+
else if (has(key))
|
|
252
|
+
invalid = true;
|
|
253
|
+
if (typeof source.watcherMode === "string" &&
|
|
254
|
+
["native", "polling", "recovering"].includes(source.watcherMode))
|
|
255
|
+
out.watcherMode = source.watcherMode;
|
|
256
|
+
else if (has("watcherMode"))
|
|
257
|
+
invalid = true;
|
|
258
|
+
if (invalid)
|
|
259
|
+
out.degraded = true;
|
|
260
|
+
return out;
|
|
261
|
+
}
|
|
262
|
+
function documentQueryState(value) {
|
|
263
|
+
return typeof value === "string" &&
|
|
264
|
+
["ready", "busy", "embedding_unavailable", "host_pressure"].includes(value)
|
|
265
|
+
? value
|
|
266
|
+
: "embedding_unavailable";
|
|
267
|
+
}
|
|
268
|
+
function canonicalPointer(input, context) {
|
|
269
|
+
try {
|
|
270
|
+
const real = fs.realpathSync(input);
|
|
271
|
+
return inside(context.checkout, real) &&
|
|
272
|
+
inside(context.root, real) &&
|
|
273
|
+
path.extname(real).toLowerCase() === ".md" &&
|
|
274
|
+
fs.statSync(real).isFile()
|
|
275
|
+
? real
|
|
276
|
+
: null;
|
|
277
|
+
}
|
|
278
|
+
catch (_a) {
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.sendDocumentCommand = sendDocumentCommand;
|
|
46
|
+
exports.runDocumentSearchBridge = runDocumentSearchBridge;
|
|
47
|
+
// Dedicated stdio surface: no normal CLI, workers, models, native stores or watchers.
|
|
48
|
+
const net = __importStar(require("node:net"));
|
|
49
|
+
const os = __importStar(require("node:os"));
|
|
50
|
+
const path = __importStar(require("node:path"));
|
|
51
|
+
const node_string_decoder_1 = require("node:string_decoder");
|
|
52
|
+
const server_1 = require("@modelcontextprotocol/server");
|
|
53
|
+
const stdio_1 = require("@modelcontextprotocol/server/stdio");
|
|
54
|
+
const zod_1 = require("zod");
|
|
55
|
+
const document_contract_1 = require("./document-contract");
|
|
56
|
+
function sendDocumentCommand(socketPath, cmd, signal) {
|
|
57
|
+
return new Promise((resolve) => {
|
|
58
|
+
const socket = net.createConnection({ path: socketPath });
|
|
59
|
+
const decoder = new node_string_decoder_1.StringDecoder("utf8");
|
|
60
|
+
let settled = false, bytes = 0, buffer = "";
|
|
61
|
+
const finish = (response) => {
|
|
62
|
+
if (settled)
|
|
63
|
+
return;
|
|
64
|
+
settled = true;
|
|
65
|
+
clearTimeout(timer);
|
|
66
|
+
signal.removeEventListener("abort", abort);
|
|
67
|
+
socket.destroy();
|
|
68
|
+
resolve(response);
|
|
69
|
+
};
|
|
70
|
+
const abort = () => { var _a; return finish((0, document_contract_1.documentFailure)(((_a = signal.reason) === null || _a === void 0 ? void 0 : _a.name) === "TimeoutError" ? "timeout" : "cancelled")); };
|
|
71
|
+
const timer = setTimeout(() => finish((0, document_contract_1.documentFailure)("timeout")), document_contract_1.DOCUMENT_LIMITS.deadlineMs);
|
|
72
|
+
if (signal.aborted) {
|
|
73
|
+
abort();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
77
|
+
socket.on("connect", () => socket.write(`${JSON.stringify(cmd)}\n`));
|
|
78
|
+
socket.on("data", (chunk) => {
|
|
79
|
+
bytes += chunk.length;
|
|
80
|
+
if (bytes > document_contract_1.DOCUMENT_LIMITS.frameBytes) {
|
|
81
|
+
finish((0, document_contract_1.documentFailure)("search_unavailable"));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
buffer += decoder.write(chunk);
|
|
85
|
+
const nl = buffer.indexOf("\n");
|
|
86
|
+
if (nl < 0)
|
|
87
|
+
return;
|
|
88
|
+
try {
|
|
89
|
+
const response = JSON.parse(buffer.slice(0, nl));
|
|
90
|
+
finish(response && typeof response === "object" && !Array.isArray(response)
|
|
91
|
+
? response
|
|
92
|
+
: (0, document_contract_1.documentFailure)("search_unavailable"));
|
|
93
|
+
}
|
|
94
|
+
catch (_a) {
|
|
95
|
+
finish((0, document_contract_1.documentFailure)("search_unavailable"));
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
socket.on("error", () => finish((0, document_contract_1.documentFailure)("daemon_unavailable")));
|
|
99
|
+
socket.on("close", () => finish((0, document_contract_1.documentFailure)("daemon_unavailable")));
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
function runDocumentSearchBridge() {
|
|
103
|
+
var _a;
|
|
104
|
+
const home = path.resolve((_a = process.env.GMAX_HOME) !== null && _a !== void 0 ? _a : path.join(os.homedir(), ".gmax"));
|
|
105
|
+
const socket = path.join(home, "daemon.sock");
|
|
106
|
+
const transport = new stdio_1.StdioServerTransport(process.stdin, process.stdout, {
|
|
107
|
+
maxBufferSize: document_contract_1.DOCUMENT_LIMITS.frameBytes,
|
|
108
|
+
});
|
|
109
|
+
(0, stdio_1.serveStdio)(() => {
|
|
110
|
+
const server = new server_1.McpServer({
|
|
111
|
+
name: "gmax-document-search",
|
|
112
|
+
version: "1",
|
|
113
|
+
});
|
|
114
|
+
const call = (name, args, signal) => __awaiter(this, void 0, void 0, function* () {
|
|
115
|
+
var _a, _b;
|
|
116
|
+
var _c, _d;
|
|
117
|
+
signal = AbortSignal.any([
|
|
118
|
+
signal,
|
|
119
|
+
AbortSignal.timeout(document_contract_1.DOCUMENT_LIMITS.deadlineMs),
|
|
120
|
+
]);
|
|
121
|
+
let response;
|
|
122
|
+
try {
|
|
123
|
+
const context = (0, document_contract_1.selectDocumentContext)(home, process.cwd());
|
|
124
|
+
const selection = name === "document_search_status"
|
|
125
|
+
? (0, document_contract_1.documentCoveragePaths)(args.paths, context)
|
|
126
|
+
: {
|
|
127
|
+
paths: (0, document_contract_1.documentPaths)(args.prefixes, context, "prefixes"),
|
|
128
|
+
requested: 0,
|
|
129
|
+
};
|
|
130
|
+
const values = selection.paths;
|
|
131
|
+
const ping = yield sendDocumentCommand(socket, { cmd: "ping" }, signal);
|
|
132
|
+
if (ping.ok !== true)
|
|
133
|
+
response = (0, document_contract_1.documentFailure)(typeof ping.state === "string"
|
|
134
|
+
? ping.state
|
|
135
|
+
: "daemon_unavailable");
|
|
136
|
+
else if (((_a = ping.capabilities) === null || _a === void 0 ? void 0 : _a.existingIndexOnlySearch) !== 1)
|
|
137
|
+
response = (0, document_contract_1.documentFailure)("unsupported_daemon");
|
|
138
|
+
else if (ping.ready !== true)
|
|
139
|
+
response = (0, document_contract_1.documentFailure)("index_unavailable");
|
|
140
|
+
else if (!(0, document_contract_1.documentGeneration)(ping.resourceGeneration))
|
|
141
|
+
response = (0, document_contract_1.documentFailure)("embedding_mismatch");
|
|
142
|
+
else {
|
|
143
|
+
const result = yield sendDocumentCommand(socket, Object.assign({ cmd: name === "document_search_status"
|
|
144
|
+
? "documents.status"
|
|
145
|
+
: "documents.search", contractVersion: document_contract_1.DOCUMENT_CONTRACT_VERSION, checkout: context.checkout, projectRoot: context.wireRoot, store: context.store, generation: ping.resourceGeneration }, (name === "document_search_status"
|
|
146
|
+
? { paths: args.paths }
|
|
147
|
+
: { query: args.query, prefixes: values })), signal);
|
|
148
|
+
if (result.ok !== true)
|
|
149
|
+
response = (0, document_contract_1.documentFailure)(typeof result.state === "string"
|
|
150
|
+
? result.state
|
|
151
|
+
: "search_unavailable");
|
|
152
|
+
else if (result.root !== context.root ||
|
|
153
|
+
result.store !== context.store ||
|
|
154
|
+
!(0, document_contract_1.documentGeneration)(result.generation) ||
|
|
155
|
+
result.generation !== ping.resourceGeneration)
|
|
156
|
+
response = (0, document_contract_1.documentFailure)("embedding_mismatch");
|
|
157
|
+
else if (name === "document_search_status") {
|
|
158
|
+
const seen = new Set();
|
|
159
|
+
const covered = (Array.isArray(result.covered) ? result.covered : [])
|
|
160
|
+
.slice(0, document_contract_1.DOCUMENT_LIMITS.paths)
|
|
161
|
+
.flatMap((row) => {
|
|
162
|
+
const p = typeof (row === null || row === void 0 ? void 0 : row.path) === "string" && values.includes(row.path)
|
|
163
|
+
? (0, document_contract_1.canonicalPointer)(row.path, context)
|
|
164
|
+
: null;
|
|
165
|
+
if (!p || seen.has(p))
|
|
166
|
+
return [];
|
|
167
|
+
seen.add(p);
|
|
168
|
+
return [
|
|
169
|
+
Object.assign(Object.assign({ path: p }, pointerHash(row)), ((0, document_contract_1.documentMtime)(row.indexedMtimeMs) !== null
|
|
170
|
+
? { indexedMtimeMs: row.indexedMtimeMs }
|
|
171
|
+
: {})),
|
|
172
|
+
];
|
|
173
|
+
});
|
|
174
|
+
response = {
|
|
175
|
+
state: "ready",
|
|
176
|
+
generation: result.generation,
|
|
177
|
+
project: {
|
|
178
|
+
root: context.root,
|
|
179
|
+
store: context.store,
|
|
180
|
+
lastIndexed: (_c = (0, document_contract_1.documentIndexedAt)(result.lastIndexed)) !== null && _c !== void 0 ? _c : context.lastIndexed,
|
|
181
|
+
},
|
|
182
|
+
embeddingReady: result.embeddingReady === true &&
|
|
183
|
+
(0, document_contract_1.documentQueryState)(result.queryState) === "ready",
|
|
184
|
+
queryState: (0, document_contract_1.documentQueryState)(result.queryState),
|
|
185
|
+
covered,
|
|
186
|
+
coverage: {
|
|
187
|
+
requested: selection.requested,
|
|
188
|
+
indexed: covered.length,
|
|
189
|
+
partial: covered.length !== selection.requested ||
|
|
190
|
+
(0, document_contract_1.documentIndexState)(result.indexState).degraded === true ||
|
|
191
|
+
((_b = result.coverage) === null || _b === void 0 ? void 0 : _b.partial) === true,
|
|
192
|
+
},
|
|
193
|
+
indexState: (0, document_contract_1.documentIndexState)(result.indexState),
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
const matches = (Array.isArray(result.matches) ? result.matches : [])
|
|
198
|
+
.slice(0, document_contract_1.DOCUMENT_LIMITS.candidates)
|
|
199
|
+
.flatMap((row) => {
|
|
200
|
+
const p = typeof (row === null || row === void 0 ? void 0 : row.path) === "string"
|
|
201
|
+
? (0, document_contract_1.canonicalPointer)(row.path, context)
|
|
202
|
+
: null;
|
|
203
|
+
const wire = p &&
|
|
204
|
+
path.join(context.wireRoot, path.relative(context.root, p));
|
|
205
|
+
return p &&
|
|
206
|
+
wire &&
|
|
207
|
+
values.some((prefix) => wire === prefix || wire.startsWith(prefix + path.sep)) &&
|
|
208
|
+
Number.isInteger(row.startLine) &&
|
|
209
|
+
row.startLine > 0 &&
|
|
210
|
+
Number.isInteger(row.endLine) &&
|
|
211
|
+
row.endLine >= row.startLine &&
|
|
212
|
+
Number.isFinite(row.score)
|
|
213
|
+
? [
|
|
214
|
+
Object.assign({ path: p, startLine: row.startLine, endLine: row.endLine, score: row.score }, pointerHash(row)),
|
|
215
|
+
]
|
|
216
|
+
: [];
|
|
217
|
+
});
|
|
218
|
+
response = {
|
|
219
|
+
state: "ready",
|
|
220
|
+
generation: result.generation,
|
|
221
|
+
root: context.root,
|
|
222
|
+
store: context.store,
|
|
223
|
+
matches,
|
|
224
|
+
indexState: (0, document_contract_1.documentIndexState)(result.indexState),
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
response = (0, document_contract_1.documentFailure)(error.message);
|
|
231
|
+
}
|
|
232
|
+
let structuredContent = Object.assign(Object.assign({}, response), { contractVersion: document_contract_1.DOCUMENT_CONTRACT_VERSION, capabilities: document_contract_1.DOCUMENT_CAPABILITIES });
|
|
233
|
+
if (Buffer.byteLength(JSON.stringify(structuredContent)) >
|
|
234
|
+
document_contract_1.DOCUMENT_LIMITS.frameBytes - 4096)
|
|
235
|
+
structuredContent = Object.assign(Object.assign({}, (0, document_contract_1.documentFailure)("no_coverage")), { contractVersion: document_contract_1.DOCUMENT_CONTRACT_VERSION, capabilities: document_contract_1.DOCUMENT_CAPABILITIES });
|
|
236
|
+
return {
|
|
237
|
+
content: [
|
|
238
|
+
{
|
|
239
|
+
type: "text",
|
|
240
|
+
text: String((_d = structuredContent.state) !== null && _d !== void 0 ? _d : "search_unavailable"),
|
|
241
|
+
},
|
|
242
|
+
],
|
|
243
|
+
structuredContent,
|
|
244
|
+
};
|
|
245
|
+
});
|
|
246
|
+
server.registerTool("document_search_status", {
|
|
247
|
+
inputSchema: zod_1.z.object({
|
|
248
|
+
paths: zod_1.z.array(zod_1.z.string()).max(document_contract_1.DOCUMENT_LIMITS.paths),
|
|
249
|
+
}),
|
|
250
|
+
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
251
|
+
}, (args, context) => call("document_search_status", args, context.mcpReq.signal));
|
|
252
|
+
server.registerTool("semantic_search", {
|
|
253
|
+
inputSchema: zod_1.z.object({
|
|
254
|
+
query: zod_1.z.string().min(1).max(document_contract_1.DOCUMENT_LIMITS.query),
|
|
255
|
+
prefixes: zod_1.z.array(zod_1.z.string()).min(1).max(document_contract_1.DOCUMENT_LIMITS.prefixes),
|
|
256
|
+
}),
|
|
257
|
+
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
258
|
+
}, (args, context) => call("semantic_search", args, context.mcpReq.signal));
|
|
259
|
+
return server;
|
|
260
|
+
}, {
|
|
261
|
+
transport,
|
|
262
|
+
legacy: "serve",
|
|
263
|
+
onerror: () => {
|
|
264
|
+
/* Never retain query-bearing diagnostics. */
|
|
265
|
+
},
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
function pointerHash(row) {
|
|
269
|
+
return row.hashAlgorithm === "sha256-bytes" &&
|
|
270
|
+
typeof row.hash === "string" &&
|
|
271
|
+
/^[a-f0-9]{64}$/.test(row.hash)
|
|
272
|
+
? { hash: row.hash, hashAlgorithm: "sha256-bytes" }
|
|
273
|
+
: {};
|
|
274
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.boundedAgentText = boundedAgentText;
|
|
4
|
+
exports.boundedAgentList = boundedAgentList;
|
|
5
|
+
/** A bounded source excerpt with explicit loss counts. Full/JSON output stays exact. */
|
|
6
|
+
function boundedAgentText(text, maxChars = 6000, maxLines = 120) {
|
|
7
|
+
var _a;
|
|
8
|
+
const lines = text.split("\n");
|
|
9
|
+
const lineLimited = lines.slice(0, maxLines).join("\n");
|
|
10
|
+
let end = Math.min(lineLimited.length, maxChars);
|
|
11
|
+
// Do not emit half of a UTF-16 surrogate pair at the character boundary.
|
|
12
|
+
if (end > 0 &&
|
|
13
|
+
/[\uD800-\uDBFF]/.test(lineLimited[end - 1]) &&
|
|
14
|
+
/[\uDC00-\uDFFF]/.test((_a = lineLimited[end]) !== null && _a !== void 0 ? _a : ""))
|
|
15
|
+
end--;
|
|
16
|
+
const excerpt = lineLimited.slice(0, end);
|
|
17
|
+
if (excerpt.length === text.length)
|
|
18
|
+
return text;
|
|
19
|
+
const shownLines = excerpt ? excerpt.split("\n").length : 0;
|
|
20
|
+
return `${excerpt}\n… omitted ${Math.max(0, lines.length - shownLines)} lines, ${text.length - excerpt.length} characters`;
|
|
21
|
+
}
|
|
22
|
+
/** Preserve complete fields so loss counts describe files, not partial names. */
|
|
23
|
+
function boundedAgentList(items, maxItems = 8, maxChars = 1000) {
|
|
24
|
+
const shown = [];
|
|
25
|
+
let length = 0;
|
|
26
|
+
for (const item of items.slice(0, maxItems)) {
|
|
27
|
+
const field = item
|
|
28
|
+
.replace(/\\/g, "\\\\")
|
|
29
|
+
.replace(/\t/g, "\\t")
|
|
30
|
+
.replace(/\r/g, "\\r")
|
|
31
|
+
.replace(/\n/g, "\\n");
|
|
32
|
+
const nextLength = length + field.length + (shown.length ? 1 : 0);
|
|
33
|
+
if (nextLength > maxChars)
|
|
34
|
+
break;
|
|
35
|
+
shown.push(field);
|
|
36
|
+
length = nextLength;
|
|
37
|
+
}
|
|
38
|
+
return { text: shown.join(","), omitted: items.length - shown.length };
|
|
39
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.projectCounts = projectCounts;
|
|
4
|
+
exports.projectCoverageNotice = projectCoverageNotice;
|
|
5
|
+
function projectCounts(overview) {
|
|
6
|
+
const qualifier = overview.sampled ? "sampled " : "";
|
|
7
|
+
return `${overview.chunks} ${qualifier}chunks • ${overview.files} ${qualifier}files`;
|
|
8
|
+
}
|
|
9
|
+
function projectCoverageNotice(overview) {
|
|
10
|
+
if (!overview.sampled)
|
|
11
|
+
return null;
|
|
12
|
+
const total = overview.totalChunks === undefined
|
|
13
|
+
? "total chunk count unavailable"
|
|
14
|
+
: `${overview.totalChunks} total chunks`;
|
|
15
|
+
return `partial: ${overview.chunks} sampled chunks, ${overview.files} sampled files; ${total}; all breakdowns below describe the sample`;
|
|
16
|
+
}
|
|
@@ -845,6 +845,19 @@ class VectorDB {
|
|
|
845
845
|
return table;
|
|
846
846
|
});
|
|
847
847
|
}
|
|
848
|
+
/** Restricted reads must use the daemon connection without creating/evolving a table. */
|
|
849
|
+
existingTableForRead() {
|
|
850
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
851
|
+
if (!this.db)
|
|
852
|
+
throw new Error("store_unavailable");
|
|
853
|
+
try {
|
|
854
|
+
return yield this.db.openTable(TABLE_NAME);
|
|
855
|
+
}
|
|
856
|
+
catch (_a) {
|
|
857
|
+
throw new Error("store_unavailable");
|
|
858
|
+
}
|
|
859
|
+
});
|
|
860
|
+
}
|
|
848
861
|
openExistingTableUnsafe() {
|
|
849
862
|
return __awaiter(this, void 0, void 0, function* () {
|
|
850
863
|
const db = yield this.getDb();
|