grepmax 0.26.70 → 0.26.72
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 +134 -0
- package/README.md +96 -0
- package/dist/bin.js +11 -2
- package/dist/lib/daemon/daemon.js +50 -0
- package/dist/lib/daemon/document-search-handler.js +194 -0
- package/dist/lib/daemon/ipc-handler.js +29 -2
- package/dist/lib/mcp/document-contract.js +281 -0
- package/dist/lib/mcp/document-search.js +274 -0
- package/dist/lib/store/vector-db.js +13 -0
- package/dist/lib/utils/resource-budget.js +39 -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 +192 -4
- 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
|
+
}
|
|
@@ -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();
|
|
@@ -106,7 +106,7 @@ function assertResourceSnapshot(snapshot, chargedMb, budgetMb, now = Date.now(),
|
|
|
106
106
|
class ResourceBudget {
|
|
107
107
|
constructor(overrides = {}) {
|
|
108
108
|
this.deps = Object.assign({ root: path.join(config_1.PATHS.sharedRoot, "resource-budget"), platform: process.platform, pid: process.pid, now: Date.now, sample: (extraPids = []) => {
|
|
109
|
-
const records = this.
|
|
109
|
+
const records = this.readExistingRecords();
|
|
110
110
|
return (0, host_resource_1.sampleHostResources)([...records.map((r) => r.pid), ...extraPids], this.deps.samplerOverrides, records.flatMap((r) => (r.groupPid ? [r.groupPid] : [])));
|
|
111
111
|
}, signal: (pid) => process.kill(pid, 0), policy: host_guard_policy_1.hostGuardPolicy, requireClientRegistration: true, samplerOverrides: {}, sampleMaxAgeMs: 5000, criticalSample: host_guard_policy_1.sampleCriticalPressure, quarantine: autostart_1.daemonStartDeniedReason, latch: safety_latch_1.latchSafetyStop, processStart: () => (0, node_child_process_1.execFileSync)("ps", ["-p", String(process.pid), "-o", "lstart="], {
|
|
112
112
|
encoding: "utf8",
|
|
@@ -147,6 +147,21 @@ class ResourceBudget {
|
|
|
147
147
|
release();
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
|
+
/** Existing-only reads may encounter a critical-only home with no ledger. */
|
|
151
|
+
readExistingRecords() {
|
|
152
|
+
let stat;
|
|
153
|
+
try {
|
|
154
|
+
stat = fs.lstatSync(this.deps.root);
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
if (error.code === "ENOENT")
|
|
158
|
+
return [];
|
|
159
|
+
throw error;
|
|
160
|
+
}
|
|
161
|
+
if (!stat.isDirectory() || stat.isSymbolicLink())
|
|
162
|
+
throw new ResourceAdmissionError("unverified resource budget directory");
|
|
163
|
+
return this.readRecords();
|
|
164
|
+
}
|
|
150
165
|
readRecords() {
|
|
151
166
|
const entries = fs.readdirSync(this.deps.root);
|
|
152
167
|
if (entries.some((name) => name.endsWith(".tmp")))
|
|
@@ -308,6 +323,29 @@ class ResourceBudget {
|
|
|
308
323
|
},
|
|
309
324
|
};
|
|
310
325
|
}
|
|
326
|
+
/** Read-only admission for existing inference, honoring the selected host policy.
|
|
327
|
+
* Never seed/lock/prune the ledger or latch. */
|
|
328
|
+
checkExisting() {
|
|
329
|
+
if (this.deps.quarantine())
|
|
330
|
+
throw new ResourceAdmissionError("host containment");
|
|
331
|
+
if (this.deps.platform !== "darwin")
|
|
332
|
+
return null;
|
|
333
|
+
if (this.deps.policy() === "critical-only") {
|
|
334
|
+
const snapshot = this.deps.criticalSample();
|
|
335
|
+
if (snapshot.memoryPressure === "critical" ||
|
|
336
|
+
snapshot.kernelPressure === "critical")
|
|
337
|
+
throw new ResourceAdmissionError("critical host pressure; existing inference refused", true);
|
|
338
|
+
if (this.deps.quarantine())
|
|
339
|
+
throw new ResourceAdmissionError("host containment");
|
|
340
|
+
return snapshot;
|
|
341
|
+
}
|
|
342
|
+
const records = this.readExistingRecords();
|
|
343
|
+
const snapshot = this.deps.sample();
|
|
344
|
+
assertResourceSnapshot(snapshot, this.charge(snapshot, records), resolveResourceBudgetMb(), this.deps.now(), this.deps.sampleMaxAgeMs);
|
|
345
|
+
if (this.deps.quarantine())
|
|
346
|
+
throw new ResourceAdmissionError("host containment");
|
|
347
|
+
return snapshot;
|
|
348
|
+
}
|
|
311
349
|
check(requiredPid) {
|
|
312
350
|
if (this.deps.platform !== "darwin")
|
|
313
351
|
return null;
|
|
@@ -145,14 +145,19 @@ class GraniteModel {
|
|
|
145
145
|
}
|
|
146
146
|
return vectors;
|
|
147
147
|
}
|
|
148
|
-
runBatch(
|
|
149
|
-
return __awaiter(this,
|
|
148
|
+
runBatch(texts_1) {
|
|
149
|
+
return __awaiter(this, arguments, void 0, function* (texts, existingOnly = false) {
|
|
150
150
|
var _a;
|
|
151
151
|
var _b, _c;
|
|
152
152
|
// Lazy-load: in the normal path MLX/GPU handles dense embedding and this
|
|
153
153
|
// ONNX model is never used, so we avoid paying its resident cost in every
|
|
154
154
|
// worker. load() is idempotent and only runs on the first fallback batch.
|
|
155
|
-
|
|
155
|
+
if (existingOnly) {
|
|
156
|
+
if (!this.isReady())
|
|
157
|
+
throw new Error("embedding_unavailable");
|
|
158
|
+
}
|
|
159
|
+
else
|
|
160
|
+
yield this.load();
|
|
156
161
|
if (!this.session || !this.tokenizer)
|
|
157
162
|
return [];
|
|
158
163
|
const encoded = yield this.tokenizer(texts, {
|