@colbymchenry/codegraph-darwin-x64 1.1.1 → 1.1.2
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/lib/dist/bin/codegraph.js +79 -52
- package/lib/dist/bin/codegraph.js.map +1 -1
- package/lib/dist/bin/command-supervision.d.ts +12 -0
- package/lib/dist/bin/command-supervision.d.ts.map +1 -0
- package/lib/dist/bin/command-supervision.js +76 -0
- package/lib/dist/bin/command-supervision.js.map +1 -0
- package/lib/dist/db/queries.d.ts.map +1 -1
- package/lib/dist/db/queries.js +10 -2
- package/lib/dist/db/queries.js.map +1 -1
- package/lib/dist/directory.d.ts +32 -0
- package/lib/dist/directory.d.ts.map +1 -1
- package/lib/dist/directory.js +83 -0
- package/lib/dist/directory.js.map +1 -1
- package/lib/dist/extraction/index.d.ts +13 -1
- package/lib/dist/extraction/index.d.ts.map +1 -1
- package/lib/dist/extraction/index.js +219 -213
- package/lib/dist/extraction/index.js.map +1 -1
- package/lib/dist/extraction/parse-pool.d.ts +126 -0
- package/lib/dist/extraction/parse-pool.d.ts.map +1 -0
- package/lib/dist/extraction/parse-pool.js +319 -0
- package/lib/dist/extraction/parse-pool.js.map +1 -0
- package/lib/dist/extraction/tree-sitter.d.ts.map +1 -1
- package/lib/dist/extraction/tree-sitter.js +48 -19
- package/lib/dist/extraction/tree-sitter.js.map +1 -1
- package/lib/dist/mcp/daemon-paths.d.ts +30 -3
- package/lib/dist/mcp/daemon-paths.d.ts.map +1 -1
- package/lib/dist/mcp/daemon-paths.js +50 -10
- package/lib/dist/mcp/daemon-paths.js.map +1 -1
- package/lib/dist/mcp/daemon-registry.d.ts.map +1 -1
- package/lib/dist/mcp/daemon-registry.js +7 -3
- package/lib/dist/mcp/daemon-registry.js.map +1 -1
- package/lib/dist/mcp/daemon.d.ts +38 -0
- package/lib/dist/mcp/daemon.d.ts.map +1 -1
- package/lib/dist/mcp/daemon.js +164 -31
- package/lib/dist/mcp/daemon.js.map +1 -1
- package/lib/dist/mcp/engine.d.ts +17 -0
- package/lib/dist/mcp/engine.d.ts.map +1 -1
- package/lib/dist/mcp/engine.js +73 -1
- package/lib/dist/mcp/engine.js.map +1 -1
- package/lib/dist/mcp/index.d.ts.map +1 -1
- package/lib/dist/mcp/index.js +25 -43
- package/lib/dist/mcp/index.js.map +1 -1
- package/lib/dist/mcp/ppid-watchdog.d.ts +18 -0
- package/lib/dist/mcp/ppid-watchdog.d.ts.map +1 -1
- package/lib/dist/mcp/ppid-watchdog.js +37 -0
- package/lib/dist/mcp/ppid-watchdog.js.map +1 -1
- package/lib/dist/mcp/query-pool.d.ts +94 -0
- package/lib/dist/mcp/query-pool.d.ts.map +1 -0
- package/lib/dist/mcp/query-pool.js +297 -0
- package/lib/dist/mcp/query-pool.js.map +1 -0
- package/lib/dist/mcp/query-worker.d.ts +24 -0
- package/lib/dist/mcp/query-worker.d.ts.map +1 -0
- package/lib/dist/mcp/query-worker.js +87 -0
- package/lib/dist/mcp/query-worker.js.map +1 -0
- package/lib/dist/mcp/tools.d.ts +57 -0
- package/lib/dist/mcp/tools.d.ts.map +1 -1
- package/lib/dist/mcp/tools.js +147 -37
- package/lib/dist/mcp/tools.js.map +1 -1
- package/lib/dist/project-config.d.ts +20 -0
- package/lib/dist/project-config.d.ts.map +1 -1
- package/lib/dist/project-config.js +42 -2
- package/lib/dist/project-config.js.map +1 -1
- package/lib/dist/resolution/c-fnptr-synthesizer.d.ts +0 -28
- package/lib/dist/resolution/c-fnptr-synthesizer.d.ts.map +1 -1
- package/lib/dist/resolution/c-fnptr-synthesizer.js +765 -79
- package/lib/dist/resolution/c-fnptr-synthesizer.js.map +1 -1
- package/lib/dist/resolution/name-matcher.d.ts.map +1 -1
- package/lib/dist/resolution/name-matcher.js +44 -0
- package/lib/dist/resolution/name-matcher.js.map +1 -1
- package/lib/node_modules/.package-lock.json +1 -1
- package/lib/package.json +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Query pool — runs CPU-heavy read-tool calls on a pool of worker threads so
|
|
4
|
+
* the shared daemon's main event loop stays free for the MCP transport.
|
|
5
|
+
*
|
|
6
|
+
* Why this exists: see {@link ./query-worker}. One daemon, one event loop, one
|
|
7
|
+
* synchronous SQLite connection serializes every concurrent `codegraph_explore`
|
|
8
|
+
* AND starves the transport (a 10-way wave delivered 0 transport heartbeats in
|
|
9
|
+
* 25s — responses can't flush until the whole batch drains, so clients time
|
|
10
|
+
* out). Spreading the dispatch across worker threads (each its own WAL read
|
|
11
|
+
* connection) restores true multi-core parallelism and an idle main loop.
|
|
12
|
+
*
|
|
13
|
+
* Properties:
|
|
14
|
+
* - lazy growth: one warm worker on construct, grows to `size` on demand, so a
|
|
15
|
+
* single-agent session pays for one connection and a 10-subagent burst grows
|
|
16
|
+
* to the core budget.
|
|
17
|
+
* - crash recovery: a dead worker is respawned and its in-flight call retried
|
|
18
|
+
* once; a poison call that keeps crashing fails gracefully (never wedges the
|
|
19
|
+
* pool). A crash budget trips a circuit breaker (`healthy` → false) so the
|
|
20
|
+
* caller falls back to in-process dispatch instead of thrashing respawns.
|
|
21
|
+
* - graceful backstop: a call that can't be served within `softTimeoutMs`
|
|
22
|
+
* resolves with SUCCESS-shaped "busy, retry" guidance — never `isError`, so
|
|
23
|
+
* a momentary overload can't teach the agent to abandon codegraph — instead
|
|
24
|
+
* of hanging past the client's hard timeout.
|
|
25
|
+
*/
|
|
26
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
27
|
+
if (k2 === undefined) k2 = k;
|
|
28
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
29
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
30
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
31
|
+
}
|
|
32
|
+
Object.defineProperty(o, k2, desc);
|
|
33
|
+
}) : (function(o, m, k, k2) {
|
|
34
|
+
if (k2 === undefined) k2 = k;
|
|
35
|
+
o[k2] = m[k];
|
|
36
|
+
}));
|
|
37
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
38
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
39
|
+
}) : function(o, v) {
|
|
40
|
+
o["default"] = v;
|
|
41
|
+
});
|
|
42
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
43
|
+
var ownKeys = function(o) {
|
|
44
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
45
|
+
var ar = [];
|
|
46
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
47
|
+
return ar;
|
|
48
|
+
};
|
|
49
|
+
return ownKeys(o);
|
|
50
|
+
};
|
|
51
|
+
return function (mod) {
|
|
52
|
+
if (mod && mod.__esModule) return mod;
|
|
53
|
+
var result = {};
|
|
54
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
55
|
+
__setModuleDefault(result, mod);
|
|
56
|
+
return result;
|
|
57
|
+
};
|
|
58
|
+
})();
|
|
59
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
60
|
+
exports.QueryPool = void 0;
|
|
61
|
+
exports.resolvePoolSize = resolvePoolSize;
|
|
62
|
+
const worker_threads_1 = require("worker_threads");
|
|
63
|
+
const path = __importStar(require("path"));
|
|
64
|
+
const os = __importStar(require("os"));
|
|
65
|
+
/** Compiled sibling — `query-worker.js` lives next to this file in `dist/mcp/`. */
|
|
66
|
+
const WORKER_FILE = path.join(__dirname, 'query-worker.js');
|
|
67
|
+
/** Default linger before a queued call is answered with busy-guidance. */
|
|
68
|
+
const DEFAULT_BUSY_TIMEOUT_MS = 45_000; // < the ~60s MCP client request timeout
|
|
69
|
+
/** Hard ceiling on pool size regardless of core count / env. */
|
|
70
|
+
const MAX_POOL_SIZE = 16;
|
|
71
|
+
/**
|
|
72
|
+
* Total worker deaths before the pool declares itself unhealthy and the caller
|
|
73
|
+
* reverts to in-process dispatch. High enough to ride out a few transient
|
|
74
|
+
* crashes, low enough that a systematically-broken worker (e.g. a platform that
|
|
75
|
+
* can't spawn threads) degrades quickly instead of respawning forever.
|
|
76
|
+
*/
|
|
77
|
+
const CRASH_BUDGET = 12;
|
|
78
|
+
/**
|
|
79
|
+
* Max workers cold-starting at once. A worker's cold start is heavy — full
|
|
80
|
+
* module load (tree-sitter etc.) + opening a large WAL DB — and starting the
|
|
81
|
+
* whole pool simultaneously thrashes CPU/I-O so badly it can stall the daemon's
|
|
82
|
+
* main loop for tens of seconds. Warming a couple at a time keeps each start
|
|
83
|
+
* fast; as one reports ready the next begins, so the pool still reaches full
|
|
84
|
+
* size within a few calls of a burst, just without the thundering herd.
|
|
85
|
+
*/
|
|
86
|
+
const MAX_CONCURRENT_SPAWN = 2;
|
|
87
|
+
/**
|
|
88
|
+
* Resolve the pool size from the `CODEGRAPH_QUERY_POOL_SIZE` override and the
|
|
89
|
+
* machine's core count. `0` (or a negative) explicitly disables the pool (the
|
|
90
|
+
* caller serves in-process — today's behavior). Unset → `clamp(cores-1, 1, 16)`:
|
|
91
|
+
* leave a core for the main loop + OS, but never zero, since even one worker
|
|
92
|
+
* frees the transport and lets responses flush incrementally.
|
|
93
|
+
*/
|
|
94
|
+
function resolvePoolSize(envVal, cpuCount) {
|
|
95
|
+
if (envVal !== undefined && envVal !== '') {
|
|
96
|
+
const n = Number(envVal);
|
|
97
|
+
if (Number.isFinite(n) && n >= 0)
|
|
98
|
+
return Math.min(Math.floor(n), MAX_POOL_SIZE);
|
|
99
|
+
// non-numeric / negative → fall through to the default
|
|
100
|
+
}
|
|
101
|
+
return Math.max(1, Math.min(cpuCount - 1, MAX_POOL_SIZE));
|
|
102
|
+
}
|
|
103
|
+
function resolveBusyTimeoutMs() {
|
|
104
|
+
const raw = process.env.CODEGRAPH_QUERY_BUSY_TIMEOUT_MS;
|
|
105
|
+
if (raw === undefined || raw === '')
|
|
106
|
+
return DEFAULT_BUSY_TIMEOUT_MS;
|
|
107
|
+
const n = Number(raw);
|
|
108
|
+
if (!Number.isFinite(n) || n < 1000)
|
|
109
|
+
return DEFAULT_BUSY_TIMEOUT_MS;
|
|
110
|
+
return Math.floor(n);
|
|
111
|
+
}
|
|
112
|
+
/** Success-shaped overload guidance (NEVER isError — see the abandonment rule). */
|
|
113
|
+
function busyGuidance(waitedMs) {
|
|
114
|
+
const secs = Math.max(1, Math.round(waitedMs / 1000));
|
|
115
|
+
return {
|
|
116
|
+
content: [{
|
|
117
|
+
type: 'text',
|
|
118
|
+
text: `CodeGraph is busy serving other concurrent requests right now (this call waited ${secs}s in the queue). ` +
|
|
119
|
+
`This is NOT an error and the index is fine — wait a few seconds and retry this exact call; it will return normally. ` +
|
|
120
|
+
`If you can't wait, use your built-in tools for just this one step.`,
|
|
121
|
+
}],
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
class QueryPool {
|
|
125
|
+
idle = [];
|
|
126
|
+
queue = [];
|
|
127
|
+
inflight = new Map();
|
|
128
|
+
workers = new Set();
|
|
129
|
+
// Workers spawned but not yet 'ready'. Growth must count these so a single
|
|
130
|
+
// first call (with the eager worker still starting) doesn't spawn the WHOLE
|
|
131
|
+
// pool at once — N simultaneous cold worker starts (each a full module load +
|
|
132
|
+
// a large DB open) saturate the box and starve the main loop. Grow only when
|
|
133
|
+
// the queue outstrips idle + pending.
|
|
134
|
+
pendingWorkers = new Set();
|
|
135
|
+
nextId = 1;
|
|
136
|
+
totalCrashes = 0;
|
|
137
|
+
destroyed = false;
|
|
138
|
+
root;
|
|
139
|
+
maxSize;
|
|
140
|
+
softTimeoutMs;
|
|
141
|
+
maxRetries;
|
|
142
|
+
createWorker;
|
|
143
|
+
constructor(opts) {
|
|
144
|
+
this.root = opts.root;
|
|
145
|
+
this.maxSize = Math.max(1, Math.min(opts.size ?? Math.max(1, os.cpus().length - 1), MAX_POOL_SIZE));
|
|
146
|
+
this.softTimeoutMs = opts.softTimeoutMs ?? resolveBusyTimeoutMs();
|
|
147
|
+
this.maxRetries = opts.maxRetries ?? 1;
|
|
148
|
+
this.createWorker = opts.createWorker ?? (() => new worker_threads_1.Worker(WORKER_FILE, { workerData: { root: this.root } }));
|
|
149
|
+
this.spawnOne(); // one eager warm worker, ready for the first call
|
|
150
|
+
}
|
|
151
|
+
/** Pool size cap (for logging/status). */
|
|
152
|
+
get size() { return this.maxSize; }
|
|
153
|
+
/** Live worker count (for tests/status). */
|
|
154
|
+
get liveWorkers() { return this.workers.size; }
|
|
155
|
+
/**
|
|
156
|
+
* False once the crash budget is exhausted (or after destroy). The ToolHandler
|
|
157
|
+
* checks this and falls back to in-process dispatch — a broken worker platform
|
|
158
|
+
* degrades to today's behavior instead of failing tool calls.
|
|
159
|
+
*/
|
|
160
|
+
get healthy() {
|
|
161
|
+
return !this.destroyed && this.totalCrashes < CRASH_BUDGET;
|
|
162
|
+
}
|
|
163
|
+
spawnOne() {
|
|
164
|
+
if (this.destroyed || this.workers.size >= this.maxSize)
|
|
165
|
+
return;
|
|
166
|
+
let w;
|
|
167
|
+
try {
|
|
168
|
+
w = this.createWorker();
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
this.totalCrashes++; // counts toward the circuit breaker
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
this.workers.add(w);
|
|
175
|
+
this.pendingWorkers.add(w);
|
|
176
|
+
w.on('message', (m) => this.onMessage(w, (m ?? {})));
|
|
177
|
+
w.on('error', () => this.onWorkerGone(w));
|
|
178
|
+
w.on('exit', (code) => { if (code !== 0)
|
|
179
|
+
this.onWorkerGone(w); });
|
|
180
|
+
}
|
|
181
|
+
onMessage(w, m) {
|
|
182
|
+
if (!m)
|
|
183
|
+
return;
|
|
184
|
+
if (m.type === 'ready') {
|
|
185
|
+
this.pendingWorkers.delete(w);
|
|
186
|
+
if (m.ok === false)
|
|
187
|
+
this.totalCrashes++; // hard open failure
|
|
188
|
+
this.idle.push(w);
|
|
189
|
+
this.drain();
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
if (m.type === 'result') {
|
|
193
|
+
const job = this.inflight.get(w);
|
|
194
|
+
this.inflight.delete(w);
|
|
195
|
+
this.idle.push(w);
|
|
196
|
+
if (job)
|
|
197
|
+
this.settle(job, m.result ?? busyGuidance(0));
|
|
198
|
+
this.drain();
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// A worker died (crash hook, OOM, segfault, exit≠0). Respawn a replacement and
|
|
202
|
+
// retry its in-flight job once; a job that keeps crashing workers fails
|
|
203
|
+
// gracefully so it can't loop the pool forever.
|
|
204
|
+
onWorkerGone(w) {
|
|
205
|
+
if (!this.workers.has(w))
|
|
206
|
+
return; // already handled (error+exit both fire)
|
|
207
|
+
this.workers.delete(w);
|
|
208
|
+
this.pendingWorkers.delete(w);
|
|
209
|
+
this.idle = this.idle.filter((x) => x !== w);
|
|
210
|
+
this.totalCrashes++;
|
|
211
|
+
const job = this.inflight.get(w);
|
|
212
|
+
this.inflight.delete(w);
|
|
213
|
+
try {
|
|
214
|
+
void w.terminate();
|
|
215
|
+
}
|
|
216
|
+
catch { /* already gone */ }
|
|
217
|
+
if (this.healthy)
|
|
218
|
+
this.spawnOne(); // keep capacity
|
|
219
|
+
if (job) {
|
|
220
|
+
if (job.retries < this.maxRetries && this.healthy) {
|
|
221
|
+
job.retries++;
|
|
222
|
+
this.queue.unshift(job); // head of line — retry promptly
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
this.settle(job, { isError: true, content: [{ type: 'text', text: 'codegraph worker crashed; please retry the call.' }] });
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
this.drain();
|
|
229
|
+
}
|
|
230
|
+
drain() {
|
|
231
|
+
// Grow toward maxSize while queued work outstrips workers that are idle OR
|
|
232
|
+
// already on their way up (pending) — so we never spawn the whole pool for a
|
|
233
|
+
// single call whose eager worker just hasn't reported ready yet.
|
|
234
|
+
while (this.queue.length > this.idle.length + this.pendingWorkers.size &&
|
|
235
|
+
this.workers.size < this.maxSize &&
|
|
236
|
+
this.pendingWorkers.size < MAX_CONCURRENT_SPAWN &&
|
|
237
|
+
this.healthy) {
|
|
238
|
+
this.spawnOne();
|
|
239
|
+
}
|
|
240
|
+
while (this.idle.length && this.queue.length) {
|
|
241
|
+
// Skip jobs the backstop already answered.
|
|
242
|
+
let job;
|
|
243
|
+
while (this.queue.length && (job = this.queue.shift()) && job.settled)
|
|
244
|
+
job = undefined;
|
|
245
|
+
if (!job || job.settled)
|
|
246
|
+
break;
|
|
247
|
+
const w = this.idle.pop();
|
|
248
|
+
this.inflight.set(w, job);
|
|
249
|
+
w.postMessage({ type: 'call', id: job.id, toolName: job.toolName, args: job.args });
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
settle(job, result) {
|
|
253
|
+
if (job.settled)
|
|
254
|
+
return; // already answered (by backstop or worker)
|
|
255
|
+
job.settled = true;
|
|
256
|
+
if (job.softTimer)
|
|
257
|
+
clearTimeout(job.softTimer);
|
|
258
|
+
job.resolve(result);
|
|
259
|
+
}
|
|
260
|
+
/** Run a read tool on the pool. Always resolves (never rejects). */
|
|
261
|
+
run(toolName, args) {
|
|
262
|
+
return new Promise((resolve) => {
|
|
263
|
+
const job = {
|
|
264
|
+
id: this.nextId++, toolName, args, resolve,
|
|
265
|
+
retries: 0, settled: false, enqueuedAt: Date.now(),
|
|
266
|
+
};
|
|
267
|
+
// Don't let the caller wait past softTimeoutMs. The worker may still be
|
|
268
|
+
// busy (we can't cancel synchronous CPU), but the CLIENT gets a prompt,
|
|
269
|
+
// success-shaped "retry" instead of a hard timeout.
|
|
270
|
+
job.softTimer = setTimeout(() => {
|
|
271
|
+
if (!job.settled)
|
|
272
|
+
this.settle(job, busyGuidance(Date.now() - job.enqueuedAt));
|
|
273
|
+
}, this.softTimeoutMs);
|
|
274
|
+
job.softTimer.unref?.();
|
|
275
|
+
this.queue.push(job);
|
|
276
|
+
this.drain();
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
/** Terminate all workers and answer any outstanding calls gracefully. */
|
|
280
|
+
async destroy() {
|
|
281
|
+
if (this.destroyed)
|
|
282
|
+
return;
|
|
283
|
+
this.destroyed = true;
|
|
284
|
+
const ws = [...this.workers];
|
|
285
|
+
this.workers.clear();
|
|
286
|
+
this.pendingWorkers.clear();
|
|
287
|
+
this.idle = [];
|
|
288
|
+
for (const job of [...this.inflight.values(), ...this.queue]) {
|
|
289
|
+
this.settle(job, { isError: true, content: [{ type: 'text', text: 'codegraph is shutting down; retry shortly.' }] });
|
|
290
|
+
}
|
|
291
|
+
this.inflight.clear();
|
|
292
|
+
this.queue = [];
|
|
293
|
+
await Promise.all(ws.map((w) => Promise.resolve(w.terminate()).catch(() => { })));
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
exports.QueryPool = QueryPool;
|
|
297
|
+
//# sourceMappingURL=query-pool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-pool.js","sourceRoot":"","sources":["../../src/mcp/query-pool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query worker thread — issue: concurrent MCP tool calls starve the daemon.
|
|
3
|
+
*
|
|
4
|
+
* The shared daemon serves every session on ONE event loop with synchronous
|
|
5
|
+
* `node:sqlite`. `codegraph_explore` is CPU-heavy (FTS + RWR/personalized-
|
|
6
|
+
* PageRank + impact + output building) stitched together by microtask `await`s,
|
|
7
|
+
* so N concurrent explores keep the microtask queue continuously full and
|
|
8
|
+
* starve the macrotask phases — timers AND socket I/O. The transport freezes:
|
|
9
|
+
* no response flushes, no request is read, until the whole batch drains. With
|
|
10
|
+
* ~10 subagents that routinely exceeds the MCP client's request timeout.
|
|
11
|
+
*
|
|
12
|
+
* This worker moves the heavy read-tool dispatch OFF the daemon's main loop.
|
|
13
|
+
* Each worker owns its OWN read connection (node:sqlite WAL allows N concurrent
|
|
14
|
+
* readers across connections — verified: a worker reader sees the main writer's
|
|
15
|
+
* committed catch-up/watcher writes), so {@link QueryPool} runs N tool calls in
|
|
16
|
+
* true parallel up to core count while the main loop stays free for the MCP
|
|
17
|
+
* transport. The worker runs {@link ToolHandler.executeReadTool} — validation +
|
|
18
|
+
* dispatch + error classification — and returns the raw {@link ToolResult}; the
|
|
19
|
+
* MAIN thread keeps the catch-up gate, the watcher-state notices (staleness /
|
|
20
|
+
* worktree), `codegraph_status`, and telemetry, none of which a watcher-less
|
|
21
|
+
* read connection can answer.
|
|
22
|
+
*/
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=query-worker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-worker.d.ts","sourceRoot":"","sources":["../../src/mcp/query-worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Query worker thread — issue: concurrent MCP tool calls starve the daemon.
|
|
4
|
+
*
|
|
5
|
+
* The shared daemon serves every session on ONE event loop with synchronous
|
|
6
|
+
* `node:sqlite`. `codegraph_explore` is CPU-heavy (FTS + RWR/personalized-
|
|
7
|
+
* PageRank + impact + output building) stitched together by microtask `await`s,
|
|
8
|
+
* so N concurrent explores keep the microtask queue continuously full and
|
|
9
|
+
* starve the macrotask phases — timers AND socket I/O. The transport freezes:
|
|
10
|
+
* no response flushes, no request is read, until the whole batch drains. With
|
|
11
|
+
* ~10 subagents that routinely exceeds the MCP client's request timeout.
|
|
12
|
+
*
|
|
13
|
+
* This worker moves the heavy read-tool dispatch OFF the daemon's main loop.
|
|
14
|
+
* Each worker owns its OWN read connection (node:sqlite WAL allows N concurrent
|
|
15
|
+
* readers across connections — verified: a worker reader sees the main writer's
|
|
16
|
+
* committed catch-up/watcher writes), so {@link QueryPool} runs N tool calls in
|
|
17
|
+
* true parallel up to core count while the main loop stays free for the MCP
|
|
18
|
+
* transport. The worker runs {@link ToolHandler.executeReadTool} — validation +
|
|
19
|
+
* dispatch + error classification — and returns the raw {@link ToolResult}; the
|
|
20
|
+
* MAIN thread keeps the catch-up gate, the watcher-state notices (staleness /
|
|
21
|
+
* worktree), `codegraph_status`, and telemetry, none of which a watcher-less
|
|
22
|
+
* read connection can answer.
|
|
23
|
+
*/
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
const worker_threads_1 = require("worker_threads");
|
|
26
|
+
// Mirror the engine's lazy-require of the heavy CodeGraph + tools chain. This
|
|
27
|
+
// module is only ever loaded as a Worker, so the require runs once on spawn.
|
|
28
|
+
const loadCodeGraph = () => require('../index').default;
|
|
29
|
+
const loadToolHandler = () => require('./tools').ToolHandler;
|
|
30
|
+
if (worker_threads_1.parentPort) {
|
|
31
|
+
const port = worker_threads_1.parentPort;
|
|
32
|
+
const { root } = worker_threads_1.workerData;
|
|
33
|
+
// Open the default project's READ connection once, at spawn. Other repos are
|
|
34
|
+
// opened lazily on first cross-project (projectPath) call by the ToolHandler's
|
|
35
|
+
// own per-handler cache. openSync does not start a watcher — workers are pure
|
|
36
|
+
// readers; the single watcher/writer stays on the daemon's main thread.
|
|
37
|
+
let handler = null;
|
|
38
|
+
let initError = null;
|
|
39
|
+
try {
|
|
40
|
+
const cg = loadCodeGraph().openSync(root);
|
|
41
|
+
handler = new (loadToolHandler())(cg);
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
initError = err instanceof Error ? err.message : String(err);
|
|
45
|
+
}
|
|
46
|
+
// Tell the pool we're up. `ok:false` lets the pool count a hard open failure
|
|
47
|
+
// against its crash budget (→ fall back to in-process) without hanging.
|
|
48
|
+
port.postMessage({ type: 'ready', ok: initError === null, error: initError });
|
|
49
|
+
port.on('message', (msg) => {
|
|
50
|
+
if (!msg || msg.type !== 'call')
|
|
51
|
+
return;
|
|
52
|
+
void serve(msg);
|
|
53
|
+
});
|
|
54
|
+
const serve = async (msg) => {
|
|
55
|
+
// Test-only crash hook so the pool's worker-recovery path is exercisable
|
|
56
|
+
// deterministically. Gated behind an env flag only the suite sets — inert in
|
|
57
|
+
// normal operation (and `__test_crash__` isn't a real tool name anyway).
|
|
58
|
+
if (msg.toolName === '__test_crash__' && process.env.CODEGRAPH_QUERY_WORKER_ALLOW_TEST_CRASH === '1') {
|
|
59
|
+
process.exit(13);
|
|
60
|
+
}
|
|
61
|
+
if (!handler) {
|
|
62
|
+
port.postMessage({
|
|
63
|
+
type: 'result',
|
|
64
|
+
id: msg.id,
|
|
65
|
+
result: errorResult(`codegraph worker could not open the project: ${initError}`),
|
|
66
|
+
});
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
// executeReadTool already classifies NotIndexed/PathRefusal/internal errors
|
|
71
|
+
// into a ToolResult and never throws — the catch is belt-and-suspenders.
|
|
72
|
+
const result = await handler.executeReadTool(msg.toolName, msg.args);
|
|
73
|
+
port.postMessage({ type: 'result', id: msg.id, result });
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
port.postMessage({
|
|
77
|
+
type: 'result',
|
|
78
|
+
id: msg.id,
|
|
79
|
+
result: errorResult(err instanceof Error ? err.message : String(err)),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function errorResult(text) {
|
|
85
|
+
return { isError: true, content: [{ type: 'text', text }] };
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=query-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-worker.js","sourceRoot":"","sources":["../../src/mcp/query-worker.ts"],"names":[],"mappings":"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"}
|
package/lib/dist/mcp/tools.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Defines the tools exposed by the CodeGraph MCP server.
|
|
5
5
|
*/
|
|
6
6
|
import type CodeGraph from '../index';
|
|
7
|
+
import type { QueryPool } from './query-pool';
|
|
7
8
|
import type { PendingFile } from '../sync';
|
|
8
9
|
/**
|
|
9
10
|
* An expected, recoverable "codegraph can't serve this" condition — most
|
|
@@ -113,6 +114,33 @@ export interface ToolDefinition {
|
|
|
113
114
|
properties: Record<string, PropertySchema>;
|
|
114
115
|
required?: string[];
|
|
115
116
|
};
|
|
117
|
+
/** Behavioral hints for clients (see {@link ToolAnnotations}). */
|
|
118
|
+
annotations?: ToolAnnotations;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* MCP ToolAnnotations — behavioral hints a client MAY use to decide how, or
|
|
122
|
+
* whether, to run a tool (introduced in the 2025-03-26 spec, carried in
|
|
123
|
+
* 2025-06-18). They are advisory and never to be trusted for security, but
|
|
124
|
+
* clients gate on them: Cursor's Ask mode, for one, refuses any MCP tool that
|
|
125
|
+
* doesn't advertise `readOnlyHint: true` (issue #1018).
|
|
126
|
+
*
|
|
127
|
+
* The field is purely additive — a client that predates annotations ignores it
|
|
128
|
+
* — so codegraph advertises these even though `initialize` still negotiates the
|
|
129
|
+
* 2024-11-05 protocol version.
|
|
130
|
+
*
|
|
131
|
+
* https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations
|
|
132
|
+
*/
|
|
133
|
+
export interface ToolAnnotations {
|
|
134
|
+
/** Human-readable title for the tool. */
|
|
135
|
+
title?: string;
|
|
136
|
+
/** If true, the tool does not modify its environment. Default (unset): false. */
|
|
137
|
+
readOnlyHint?: boolean;
|
|
138
|
+
/** Meaningful only when NOT read-only: may the tool perform destructive updates? */
|
|
139
|
+
destructiveHint?: boolean;
|
|
140
|
+
/** If true, repeat calls with the same arguments have no additional effect. */
|
|
141
|
+
idempotentHint?: boolean;
|
|
142
|
+
/** If true, the tool interacts with an open world of external entities. */
|
|
143
|
+
openWorldHint?: boolean;
|
|
116
144
|
}
|
|
117
145
|
interface PropertySchema {
|
|
118
146
|
type: string;
|
|
@@ -159,7 +187,15 @@ export declare class ToolHandler {
|
|
|
159
187
|
private defaultProjectHint;
|
|
160
188
|
private worktreeMismatchCache;
|
|
161
189
|
private catchUpGate;
|
|
190
|
+
private queryPool;
|
|
162
191
|
constructor(cg: CodeGraph | null);
|
|
192
|
+
/**
|
|
193
|
+
* Engine-only: attach (or detach with null) the worker-thread query pool. The
|
|
194
|
+
* shared daemon sets this once its default project is open; the workers each
|
|
195
|
+
* hold their own WAL read connection and run {@link executeReadTool}. A
|
|
196
|
+
* worker's own ToolHandler never has a pool, so there is no nested off-loading.
|
|
197
|
+
*/
|
|
198
|
+
setQueryPool(pool: QueryPool | null): void;
|
|
163
199
|
/**
|
|
164
200
|
* Update the default CodeGraph instance (e.g. after lazy initialization)
|
|
165
201
|
*/
|
|
@@ -286,6 +322,27 @@ export declare class ToolHandler {
|
|
|
286
322
|
* Execute a tool by name
|
|
287
323
|
*/
|
|
288
324
|
execute(toolName: string, args: Record<string, unknown>): Promise<ToolResult>;
|
|
325
|
+
/**
|
|
326
|
+
* Run a single read tool to completion and return its raw {@link ToolResult},
|
|
327
|
+
* classifying expected failures the same way {@link execute}'s catch does so
|
|
328
|
+
* the SHAPE is identical whether dispatch runs in-process or on a worker:
|
|
329
|
+
* NotIndexed → success-shaped guidance, PathRefusal → clean error, anything
|
|
330
|
+
* else → internal-error-with-retry. Never throws.
|
|
331
|
+
*
|
|
332
|
+
* This is the worker thread's entry point (see {@link ./query-worker}) and the
|
|
333
|
+
* in-process fallback for {@link execute}. It deliberately does NOT run the
|
|
334
|
+
* catch-up gate or the staleness/worktree notices — those need the daemon's
|
|
335
|
+
* watched main instance and stay on the main thread. Cross-cutting allowlist +
|
|
336
|
+
* path validation already ran in {@link execute} before routing here.
|
|
337
|
+
*/
|
|
338
|
+
executeReadTool(toolName: string, args: Record<string, unknown>): Promise<ToolResult>;
|
|
339
|
+
/**
|
|
340
|
+
* Pure dispatch over the read tools — the switch, with no gate, no notices, no
|
|
341
|
+
* allowlist/validation (the caller owns those). `codegraph_status` is handled
|
|
342
|
+
* on the main thread in {@link execute} and never reaches here. May throw
|
|
343
|
+
* NotIndexed/PathRefusal, which {@link executeReadTool} classifies.
|
|
344
|
+
*/
|
|
345
|
+
private dispatchTool;
|
|
289
346
|
/**
|
|
290
347
|
* Handle codegraph_search
|
|
291
348
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/mcp/tools.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,SAAS,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/mcp/tools.ts"],"names":[],"mappings":"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"}
|