@keb-org/consol 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +91 -53
- package/dist/consol.d.ts +2 -2
- package/dist/errors.d.ts +1 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +128 -418
- package/dist/mcp.d.ts +2 -0
- package/dist/mcp.js +20422 -0
- package/dist/native.d.ts +96 -0
- package/dist/transport.d.ts +3 -2
- package/dist/types.d.ts +86 -95
- package/dist/vault.d.ts +43 -98
- package/package.json +14 -10
- package/dist/stdio.d.ts +0 -120
package/dist/index.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
var __create = Object.create;
|
|
2
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
3
1
|
var __defProp = Object.defineProperty;
|
|
4
2
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -7,30 +5,6 @@ var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
|
7
5
|
function __accessProp(key) {
|
|
8
6
|
return this[key];
|
|
9
7
|
}
|
|
10
|
-
var __toESMCache_node;
|
|
11
|
-
var __toESMCache_esm;
|
|
12
|
-
var __toESM = (mod, isNodeMode, target) => {
|
|
13
|
-
var canCache = mod != null && typeof mod === "object";
|
|
14
|
-
if (canCache) {
|
|
15
|
-
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
16
|
-
var cached = cache.get(mod);
|
|
17
|
-
if (cached)
|
|
18
|
-
return cached;
|
|
19
|
-
}
|
|
20
|
-
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
21
|
-
const to = isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
22
|
-
if (mod && typeof mod === "object" || typeof mod === "function") {
|
|
23
|
-
for (let key of __getOwnPropNames(mod))
|
|
24
|
-
if (!__hasOwnProp.call(to, key))
|
|
25
|
-
__defProp(to, key, {
|
|
26
|
-
get: __accessProp.bind(mod, key),
|
|
27
|
-
enumerable: true
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
if (canCache)
|
|
31
|
-
cache.set(mod, to);
|
|
32
|
-
return to;
|
|
33
|
-
};
|
|
34
8
|
var __toCommonJS = (from) => {
|
|
35
9
|
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
|
36
10
|
if (entry)
|
|
@@ -84,7 +58,6 @@ class ConsolError extends Error {
|
|
|
84
58
|
field;
|
|
85
59
|
tool;
|
|
86
60
|
status;
|
|
87
|
-
stderrTail;
|
|
88
61
|
result;
|
|
89
62
|
constructor(code, message, details = {}) {
|
|
90
63
|
super(message, details.cause === undefined ? undefined : { cause: details.cause });
|
|
@@ -97,8 +70,6 @@ class ConsolError extends Error {
|
|
|
97
70
|
this.tool = details.tool;
|
|
98
71
|
if (details.status !== undefined)
|
|
99
72
|
this.status = details.status;
|
|
100
|
-
if (details.stderrTail !== undefined)
|
|
101
|
-
this.stderrTail = details.stderrTail;
|
|
102
73
|
if (details.result !== undefined)
|
|
103
74
|
this.result = details.result;
|
|
104
75
|
Object.defineProperty(this, BRAND, { value: true });
|
|
@@ -118,11 +89,8 @@ function replyError(reply, tool) {
|
|
|
118
89
|
result: reply
|
|
119
90
|
});
|
|
120
91
|
}
|
|
121
|
-
// src/
|
|
122
|
-
var
|
|
123
|
-
var import_node_fs = require("node:fs");
|
|
124
|
-
var readline = __toESM(require("node:readline"));
|
|
125
|
-
var import_node_string_decoder = require("node:string_decoder");
|
|
92
|
+
// src/native.ts
|
|
93
|
+
var import_node_path = require("node:path");
|
|
126
94
|
|
|
127
95
|
// src/transport.ts
|
|
128
96
|
var DEFAULT_TIMEOUT_MS = 300000;
|
|
@@ -211,409 +179,164 @@ class HttpTransport {
|
|
|
211
179
|
}
|
|
212
180
|
}
|
|
213
181
|
|
|
214
|
-
// src/
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
var KILL_WAIT_MS = 4000;
|
|
218
|
-
function engineEnv(o) {
|
|
219
|
-
const env = {};
|
|
182
|
+
// src/native.ts
|
|
183
|
+
function engineSettings(o) {
|
|
184
|
+
const s = {};
|
|
220
185
|
const db = o.db ?? process.env.CONSOL_DB_URL;
|
|
221
186
|
if (db !== undefined)
|
|
222
|
-
|
|
187
|
+
s.CONSOL_DB_URL = db;
|
|
223
188
|
const e = o.embedding;
|
|
224
189
|
if (e !== undefined) {
|
|
225
|
-
|
|
190
|
+
s.CONSOL_EMBED_URL = e.url;
|
|
226
191
|
if (e.apiKey !== undefined)
|
|
227
|
-
|
|
228
|
-
|
|
192
|
+
s.CONSOL_EMBED_API_KEY = e.apiKey;
|
|
193
|
+
s.CONSOL_EMBED_MODEL = e.model;
|
|
229
194
|
if (e.dims !== undefined)
|
|
230
|
-
|
|
231
|
-
if (e.queryPrefix !== undefined)
|
|
232
|
-
env.CONSOL_EMBED_QUERY_PREFIX = e.queryPrefix;
|
|
233
|
-
if (e.batchSize !== undefined)
|
|
234
|
-
env.CONSOL_EMBED_BATCH = String(e.batchSize);
|
|
195
|
+
s.CONSOL_EMBED_DIMS = String(e.dims);
|
|
235
196
|
if (e.timeoutMs !== undefined)
|
|
236
|
-
|
|
197
|
+
s.CONSOL_EMBED_TIMEOUT_MS = String(e.timeoutMs);
|
|
237
198
|
}
|
|
238
199
|
const j = o.jev;
|
|
239
200
|
if (j !== undefined) {
|
|
240
201
|
if (j.url !== undefined)
|
|
241
|
-
|
|
202
|
+
s.CONSOL_JEV_URL = j.url;
|
|
242
203
|
if (j.apiKey !== undefined)
|
|
243
|
-
|
|
204
|
+
s.CONSOL_JEV_API_KEY = j.apiKey;
|
|
244
205
|
if (j.model !== undefined)
|
|
245
|
-
|
|
206
|
+
s.CONSOL_JEV_MODEL = j.model;
|
|
246
207
|
if (j.auto === false)
|
|
247
|
-
|
|
208
|
+
s.CONSOL_JEV_AUTO = "0";
|
|
248
209
|
}
|
|
249
|
-
return env;
|
|
250
|
-
}
|
|
251
|
-
function platformExe() {
|
|
252
|
-
return process.platform === "win32" ? "consol.exe" : "consol";
|
|
210
|
+
return { ...s, ...o.env };
|
|
253
211
|
}
|
|
254
|
-
function
|
|
212
|
+
function loadAddon(explicit) {
|
|
213
|
+
const fromEnv = process.env.CONSOL_ADDON;
|
|
214
|
+
const spec = `@keb-org/consol-${process.platform}-${process.arch}/consol.node`;
|
|
215
|
+
const [attempt, target] = explicit ? [`addonPath:${explicit}`, import_node_path.resolve(explicit)] : fromEnv ? [`CONSOL_ADDON:${fromEnv}`, import_node_path.resolve(fromEnv)] : [`package:${spec}`, spec];
|
|
255
216
|
try {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
217
|
+
const sdkRequire = require;
|
|
218
|
+
return sdkRequire(target);
|
|
219
|
+
} catch (cause) {
|
|
220
|
+
throw new ConsolError("addon_not_found", `addon not found: ${attempt} (${String(cause?.message).split(`
|
|
221
|
+
`)[0]})`, { cause });
|
|
259
222
|
}
|
|
260
223
|
}
|
|
261
|
-
|
|
262
|
-
|
|
224
|
+
var logSinks = new Set;
|
|
225
|
+
var fanOut = (line) => {
|
|
226
|
+
for (const sink of logSinks)
|
|
227
|
+
sink(line);
|
|
228
|
+
};
|
|
229
|
+
function subscribe(addon, onLog, level) {
|
|
230
|
+
const sink = (line) => {
|
|
231
|
+
try {
|
|
232
|
+
onLog(line);
|
|
233
|
+
} catch {}
|
|
234
|
+
};
|
|
235
|
+
logSinks.add(sink);
|
|
236
|
+
addon.setLogSink(fanOut, level);
|
|
237
|
+
return () => {
|
|
238
|
+
if (logSinks.delete(sink) && logSinks.size === 0)
|
|
239
|
+
addon.setLogSink(null);
|
|
240
|
+
};
|
|
263
241
|
}
|
|
264
|
-
function
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
throw missingBinary(`explicit:${explicit}`);
|
|
269
|
-
return { path: explicit, attempts: [`explicit:${explicit}`] };
|
|
270
|
-
}
|
|
271
|
-
const fromEnv = process.env.CONSOL_BIN;
|
|
272
|
-
if (fromEnv) {
|
|
273
|
-
if (!isFile(fromEnv))
|
|
274
|
-
throw missingBinary(`CONSOL_BIN:${fromEnv}`);
|
|
275
|
-
return { path: fromEnv, attempts: [`CONSOL_BIN:${fromEnv}`] };
|
|
276
|
-
}
|
|
277
|
-
const spec = `@keb-org/consol-${process.platform}-${process.arch}/bin/${exe}`;
|
|
242
|
+
function engineError(error) {
|
|
243
|
+
if (ConsolError.is(error))
|
|
244
|
+
return error;
|
|
245
|
+
const text = error instanceof Error ? error.message : String(error);
|
|
278
246
|
try {
|
|
279
|
-
const
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
const name = process.platform === "win32" ? key.toUpperCase() : key;
|
|
289
|
-
if (value === undefined || name.startsWith("CONSOL_") || name === "RUST_LOG")
|
|
290
|
-
continue;
|
|
291
|
-
env[key] = value;
|
|
292
|
-
}
|
|
293
|
-
return { ...env, ...base, ...extra };
|
|
247
|
+
const { code, message, field } = JSON.parse(text);
|
|
248
|
+
if (typeof code === "string") {
|
|
249
|
+
return new ConsolError(code, typeof message === "string" ? message : code, {
|
|
250
|
+
field: typeof field === "string" ? field : undefined,
|
|
251
|
+
cause: error
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
} catch {}
|
|
255
|
+
return new ConsolError("internal", text, { cause: error });
|
|
294
256
|
}
|
|
295
|
-
function
|
|
296
|
-
const
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
257
|
+
function race(work, label, ms, closed, user) {
|
|
258
|
+
const timer = ms > 0 ? AbortSignal.timeout(ms) : undefined;
|
|
259
|
+
const stop = anySignal([closed, user, timer].filter((s) => s !== undefined));
|
|
260
|
+
return new Promise((resolve, reject) => {
|
|
261
|
+
const onStop = () => reject(closed?.aborted ? new ConsolError("closed", "vault is closed") : user?.aborted ? new ConsolError("aborted", `${label} aborted`, { cause: user.reason }) : new ConsolError("timeout", `${label} timed out after ${ms}ms`));
|
|
262
|
+
stop.addEventListener("abort", onStop, { once: true });
|
|
263
|
+
work.then(resolve, reject).finally(() => stop.removeEventListener("abort", onStop));
|
|
264
|
+
});
|
|
303
265
|
}
|
|
304
|
-
var READY = 0;
|
|
305
266
|
|
|
306
|
-
class
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
binary;
|
|
267
|
+
class NativeTransport {
|
|
268
|
+
engine;
|
|
269
|
+
version;
|
|
310
270
|
timeoutMs;
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
generation = 0;
|
|
314
|
-
nextId = 1;
|
|
315
|
-
pending = new Map;
|
|
316
|
-
starting = null;
|
|
317
|
-
started = false;
|
|
318
|
-
closed = false;
|
|
271
|
+
unsubscribe;
|
|
272
|
+
closed = new AbortController;
|
|
319
273
|
closing = null;
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
this.
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
const lines = (this.stderrPartial + this.decoder.write(chunk)).split(/\r?\n/);
|
|
334
|
-
this.stderrPartial = lastBytes(lines.pop() ?? "");
|
|
335
|
-
for (const line of lines)
|
|
336
|
-
this.pushLine(line);
|
|
337
|
-
}
|
|
338
|
-
flushStderr() {
|
|
339
|
-
const rest = (this.stderrPartial + this.decoder.end()).trim();
|
|
340
|
-
this.stderrPartial = "";
|
|
341
|
-
this.decoder = new import_node_string_decoder.StringDecoder("utf8");
|
|
342
|
-
if (rest)
|
|
343
|
-
this.pushLine(rest);
|
|
344
|
-
}
|
|
345
|
-
pushLine(line) {
|
|
346
|
-
const text = lastBytes(line.trim().replace(/\x1b\[[0-9;]*[A-Za-z]/g, ""));
|
|
347
|
-
if (!text)
|
|
348
|
-
return;
|
|
349
|
-
this.stderrTail.push(text);
|
|
350
|
-
this.stderrTailBytes += Buffer.byteLength(text, "utf8");
|
|
351
|
-
while (this.stderrTailBytes > STDERR_TAIL_BYTES && this.stderrTail.length > 1) {
|
|
352
|
-
const dropped = this.stderrTail.shift();
|
|
353
|
-
this.stderrTailBytes -= Buffer.byteLength(dropped, "utf8");
|
|
354
|
-
}
|
|
355
|
-
try {
|
|
356
|
-
this.opts.onLog?.(text);
|
|
357
|
-
} catch {}
|
|
358
|
-
}
|
|
359
|
-
tailText() {
|
|
360
|
-
return this.stderrTail.join(`
|
|
361
|
-
`);
|
|
362
|
-
}
|
|
363
|
-
updateRef() {
|
|
364
|
-
const child = this.child;
|
|
365
|
-
if (!child || child.exitCode !== null || child.signalCode !== null)
|
|
366
|
-
return;
|
|
367
|
-
try {
|
|
368
|
-
if (this.pending.size > 0 || this.starting !== null)
|
|
369
|
-
child.ref();
|
|
370
|
-
else
|
|
371
|
-
child.unref();
|
|
372
|
-
} catch {}
|
|
373
|
-
}
|
|
374
|
-
onDeath(error) {
|
|
375
|
-
const child = this.child;
|
|
376
|
-
this.child = null;
|
|
377
|
-
this.reader?.close();
|
|
378
|
-
this.reader = null;
|
|
274
|
+
constructor(engine, version, timeoutMs, unsubscribe) {
|
|
275
|
+
this.engine = engine;
|
|
276
|
+
this.version = version;
|
|
277
|
+
this.timeoutMs = timeoutMs;
|
|
278
|
+
this.unsubscribe = unsubscribe;
|
|
279
|
+
}
|
|
280
|
+
static async start(opts) {
|
|
281
|
+
const timeoutMs = deadline(opts.timeoutMs, DEFAULT_TIMEOUT_MS);
|
|
282
|
+
const addon = loadAddon(opts.addonPath);
|
|
283
|
+
const version = checkVersion(addon.version(), opts.sdkVersion);
|
|
284
|
+
const unsubscribe = opts.onLog ? subscribe(addon, opts.onLog, opts.logLevel) : () => {};
|
|
285
|
+
let opening;
|
|
286
|
+
let engine;
|
|
379
287
|
try {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
288
|
+
opening = addon.openEngine(JSON.stringify(opts.location), engineSettings(opts));
|
|
289
|
+
engine = await race(opening, "start", timeoutMs);
|
|
290
|
+
} catch (error) {
|
|
291
|
+
unsubscribe();
|
|
292
|
+
opening?.then((late) => late.close()).catch(() => {});
|
|
293
|
+
throw engineError(error);
|
|
294
|
+
}
|
|
295
|
+
const transport = new NativeTransport(engine, version, timeoutMs, unsubscribe);
|
|
296
|
+
const { boot } = opts;
|
|
297
|
+
if (boot) {
|
|
298
|
+
try {
|
|
299
|
+
const error = replyError(await transport.vaultOp(boot.create ? "create_vault" : "open_vault", boot.vault));
|
|
300
|
+
if (error)
|
|
301
|
+
throw error;
|
|
302
|
+
} catch (error) {
|
|
303
|
+
await transport.close().catch(() => {});
|
|
304
|
+
throw error;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return transport;
|
|
387
308
|
}
|
|
388
309
|
close() {
|
|
389
310
|
this.closing ??= this.shutdown();
|
|
390
311
|
return this.closing;
|
|
391
312
|
}
|
|
392
313
|
async shutdown() {
|
|
393
|
-
this.closed
|
|
394
|
-
|
|
395
|
-
this.child = null;
|
|
396
|
-
this.reader?.close();
|
|
397
|
-
this.reader = null;
|
|
398
|
-
const failure = new ConsolError("closed", "vault is closed");
|
|
399
|
-
for (const pending of this.pending.values())
|
|
400
|
-
pending.reject(failure);
|
|
401
|
-
this.pending.clear();
|
|
402
|
-
if (!child)
|
|
403
|
-
return;
|
|
404
|
-
await new Promise((resolve) => {
|
|
405
|
-
if (!child.pid || child.exitCode !== null || child.signalCode !== null) {
|
|
406
|
-
resolve();
|
|
407
|
-
return;
|
|
408
|
-
}
|
|
409
|
-
const terminate = setTimeout(() => {
|
|
410
|
-
try {
|
|
411
|
-
child.kill();
|
|
412
|
-
} catch {}
|
|
413
|
-
}, EXIT_WAIT_MS);
|
|
414
|
-
const force = setTimeout(() => {
|
|
415
|
-
try {
|
|
416
|
-
child.kill("SIGKILL");
|
|
417
|
-
} catch {}
|
|
418
|
-
}, KILL_WAIT_MS);
|
|
419
|
-
child.once("close", () => {
|
|
420
|
-
clearTimeout(terminate);
|
|
421
|
-
clearTimeout(force);
|
|
422
|
-
resolve();
|
|
423
|
-
});
|
|
424
|
-
try {
|
|
425
|
-
child.stdin?.end();
|
|
426
|
-
} catch {
|
|
427
|
-
resolve();
|
|
428
|
-
}
|
|
429
|
-
});
|
|
430
|
-
}
|
|
431
|
-
async start() {
|
|
432
|
-
if (this.closed)
|
|
433
|
-
throw new ConsolError("closed", "vault is closed");
|
|
434
|
-
if (!this.starting && !this.child)
|
|
435
|
-
this.starting = this.spawn();
|
|
436
|
-
if (this.starting) {
|
|
437
|
-
try {
|
|
438
|
-
await this.starting;
|
|
439
|
-
} finally {
|
|
440
|
-
this.starting = null;
|
|
441
|
-
this.updateRef();
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
if (this.closed)
|
|
445
|
-
throw new ConsolError("closed", "vault is closed");
|
|
446
|
-
}
|
|
447
|
-
async spawn() {
|
|
448
|
-
const generation = ++this.generation;
|
|
449
|
-
const child = import_node_child_process.spawn(this.binary, ["stdio", ...this.opts.location], {
|
|
450
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
451
|
-
env: childEnv(engineEnv(this.opts), this.opts.env)
|
|
452
|
-
});
|
|
453
|
-
this.child = child;
|
|
454
|
-
for (const stream of [child.stdin, child.stdout, child.stderr])
|
|
455
|
-
stream?.unref?.();
|
|
456
|
-
this.updateRef();
|
|
457
|
-
child.stderr?.on("data", (chunk) => this.onStderr(chunk));
|
|
458
|
-
child.stderr?.on("error", () => {});
|
|
459
|
-
const dead = (reason, cause) => {
|
|
460
|
-
if (this.child !== child)
|
|
461
|
-
return;
|
|
462
|
-
this.flushStderr();
|
|
463
|
-
const tail = this.stderrTail.slice(-3).join(" | ");
|
|
464
|
-
this.onDeath(new ConsolError("server_exited", `${reason}${tail ? `: ${tail}` : ""}`, {
|
|
465
|
-
stderrTail: this.tailText() || undefined,
|
|
466
|
-
...cause === undefined ? {} : { cause }
|
|
467
|
-
}));
|
|
468
|
-
};
|
|
469
|
-
child.once("error", (error) => {
|
|
470
|
-
if (error?.code === "ENOENT") {
|
|
471
|
-
if (this.child !== child)
|
|
472
|
-
return;
|
|
473
|
-
this.onDeath(new ConsolError("binary_not_found", `binary not found: ${this.binary}`, {
|
|
474
|
-
stderrTail: this.attempts.join(`
|
|
475
|
-
`),
|
|
476
|
-
cause: error
|
|
477
|
-
}));
|
|
478
|
-
} else {
|
|
479
|
-
dead(`server failed to start: ${error.message}`, error);
|
|
480
|
-
}
|
|
481
|
-
});
|
|
482
|
-
child.once("exit", (code, signal) => {
|
|
483
|
-
dead(`server exited (${signal ?? code})`);
|
|
484
|
-
});
|
|
485
|
-
child.stdin?.on("error", () => {
|
|
486
|
-
dead("server stdin failed");
|
|
487
|
-
});
|
|
488
|
-
const reader = readline.createInterface({ input: child.stdout, crlfDelay: Infinity });
|
|
489
|
-
this.reader = reader;
|
|
490
|
-
reader.once("close", () => {
|
|
491
|
-
dead("server closed output");
|
|
492
|
-
});
|
|
493
|
-
reader.on("line", (line) => {
|
|
494
|
-
if (this.child === child && generation === this.generation)
|
|
495
|
-
this.onLine(line);
|
|
496
|
-
});
|
|
314
|
+
this.closed.abort();
|
|
315
|
+
this.unsubscribe();
|
|
497
316
|
try {
|
|
498
|
-
|
|
499
|
-
const boot = this.opts.boot;
|
|
500
|
-
if (boot) {
|
|
501
|
-
const op = boot.create && !this.started ? "create_vault" : "open_vault";
|
|
502
|
-
const reply = await this.call(op, this.nextId++, { op, vault: boot.vault }, {});
|
|
503
|
-
const error = replyError(reply);
|
|
504
|
-
if (error)
|
|
505
|
-
throw error;
|
|
506
|
-
}
|
|
507
|
-
this.started = true;
|
|
508
|
-
this.stderrTail = [];
|
|
509
|
-
this.stderrTailBytes = 0;
|
|
317
|
+
await this.engine.close();
|
|
510
318
|
} catch (error) {
|
|
511
|
-
|
|
512
|
-
this.child = null;
|
|
513
|
-
this.reader?.close();
|
|
514
|
-
this.reader = null;
|
|
515
|
-
try {
|
|
516
|
-
child.kill();
|
|
517
|
-
} catch {}
|
|
518
|
-
}
|
|
519
|
-
throw error instanceof ConsolError ? error : new ConsolError("internal", String(error), { cause: error });
|
|
319
|
+
throw engineError(error);
|
|
520
320
|
}
|
|
521
321
|
}
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
322
|
+
async send(frame, options) {
|
|
323
|
+
const { signal } = options;
|
|
324
|
+
if (this.closed.signal.aborted)
|
|
325
|
+
throw new ConsolError("closed", "vault is closed");
|
|
326
|
+
if (signal?.aborted)
|
|
327
|
+
throw new ConsolError("aborted", `${frame.op} aborted before dispatch`, { cause: signal.reason });
|
|
328
|
+
const ms = deadline(options.timeoutMs, this.timeoutMs);
|
|
329
|
+
let text;
|
|
526
330
|
try {
|
|
527
|
-
|
|
528
|
-
} catch {
|
|
529
|
-
|
|
530
|
-
stderrTail: this.tailText() || undefined
|
|
531
|
-
}));
|
|
532
|
-
return;
|
|
533
|
-
}
|
|
534
|
-
const id = msg?.ready === true ? READY : msg?.id;
|
|
535
|
-
if (typeof id !== "number")
|
|
536
|
-
return;
|
|
537
|
-
const pending = this.pending.get(id);
|
|
538
|
-
if (!pending || pending.settled)
|
|
539
|
-
return;
|
|
540
|
-
this.pending.delete(id);
|
|
541
|
-
if (id === READY) {
|
|
542
|
-
pending.resolve(msg.version);
|
|
543
|
-
} else {
|
|
544
|
-
try {
|
|
545
|
-
this.version = checkVersion(msg.reply?.version, this.opts.sdkVersion);
|
|
546
|
-
pending.resolve(msg.reply);
|
|
547
|
-
} catch (error) {
|
|
548
|
-
pending.reject(error);
|
|
549
|
-
}
|
|
331
|
+
text = JSON.stringify(frame);
|
|
332
|
+
} catch (cause) {
|
|
333
|
+
throw new ConsolError("invalid_argument", `${frame.op}: body is not JSON`, { cause });
|
|
550
334
|
}
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
const signal = options.signal;
|
|
556
|
-
if (signal?.aborted) {
|
|
557
|
-
reject(new ConsolError("aborted", `${label} aborted before dispatch`, { cause: signal.reason }));
|
|
558
|
-
return;
|
|
559
|
-
}
|
|
560
|
-
let line = null;
|
|
561
|
-
let timeoutMs;
|
|
562
|
-
try {
|
|
563
|
-
timeoutMs = deadline(options.timeoutMs, this.timeoutMs);
|
|
564
|
-
line = frame ? JSON.stringify({ id, ...frame }) + `
|
|
565
|
-
` : null;
|
|
566
|
-
} catch (error) {
|
|
567
|
-
reject(ConsolError.is(error) ? error : new ConsolError("invalid_argument", `${label}: body is not JSON`, { cause: error }));
|
|
568
|
-
return;
|
|
569
|
-
}
|
|
570
|
-
const input = this.child?.stdin;
|
|
571
|
-
if (line && !input?.writable) {
|
|
572
|
-
reject(new ConsolError(this.closed ? "closed" : "server_exited", "server is not running"));
|
|
573
|
-
return;
|
|
574
|
-
}
|
|
575
|
-
const pending = { resolve, reject, settled: false };
|
|
576
|
-
const done = (error, value) => {
|
|
577
|
-
if (pending.settled)
|
|
578
|
-
return;
|
|
579
|
-
pending.settled = true;
|
|
580
|
-
if (pending.timer !== undefined)
|
|
581
|
-
clearTimeout(pending.timer);
|
|
582
|
-
if (pending.onAbort && signal)
|
|
583
|
-
signal.removeEventListener("abort", pending.onAbort);
|
|
584
|
-
this.pending.delete(id);
|
|
585
|
-
if (error)
|
|
586
|
-
reject(error);
|
|
587
|
-
else
|
|
588
|
-
resolve(value);
|
|
589
|
-
this.updateRef();
|
|
590
|
-
};
|
|
591
|
-
pending.resolve = (value) => done(null, value);
|
|
592
|
-
pending.reject = (error) => done(error);
|
|
593
|
-
if (timeoutMs > 0) {
|
|
594
|
-
pending.timer = setTimeout(() => done(new ConsolError("timeout", `${label} timed out after ${timeoutMs}ms`)), timeoutMs);
|
|
595
|
-
pending.timer.unref?.();
|
|
596
|
-
}
|
|
597
|
-
if (signal) {
|
|
598
|
-
pending.onAbort = () => done(new ConsolError("aborted", `${label} aborted`, { cause: signal.reason }));
|
|
599
|
-
signal.addEventListener("abort", pending.onAbort, { once: true });
|
|
600
|
-
}
|
|
601
|
-
this.pending.set(id, pending);
|
|
602
|
-
this.updateRef();
|
|
603
|
-
if (line) {
|
|
604
|
-
input.write(line, (error) => {
|
|
605
|
-
if (error)
|
|
606
|
-
done(new ConsolError("server_exited", "server stdin failed", { cause: error }));
|
|
607
|
-
});
|
|
608
|
-
}
|
|
609
|
-
});
|
|
610
|
-
}
|
|
611
|
-
async send(frame, options) {
|
|
612
|
-
if (options.signal?.aborted) {
|
|
613
|
-
throw new ConsolError("aborted", `${frame.op} aborted before dispatch`, { cause: options.signal.reason });
|
|
335
|
+
try {
|
|
336
|
+
return JSON.parse(await race(this.engine.request(text), frame.op, ms, this.closed.signal, signal));
|
|
337
|
+
} catch (error) {
|
|
338
|
+
throw engineError(error);
|
|
614
339
|
}
|
|
615
|
-
await this.start();
|
|
616
|
-
return await this.call(frame.op, this.nextId++, frame, options);
|
|
617
340
|
}
|
|
618
341
|
handle(body, ctx, options = {}) {
|
|
619
342
|
return this.send({ op: "handle", ctx: { vaults: ctx.vaults, agent: ctx.agent ?? null }, body }, options);
|
|
@@ -624,7 +347,7 @@ class StdioTransport {
|
|
|
624
347
|
}
|
|
625
348
|
|
|
626
349
|
// src/vault.ts
|
|
627
|
-
var
|
|
350
|
+
var import_node_path2 = require("node:path");
|
|
628
351
|
|
|
629
352
|
// src/types.ts
|
|
630
353
|
function sliceUtf8(text, start, end) {
|
|
@@ -646,7 +369,7 @@ function sliceUtf8(text, start, end) {
|
|
|
646
369
|
}
|
|
647
370
|
|
|
648
371
|
// src/vault.ts
|
|
649
|
-
var CLIENT_INFO = { name: "consol-js-client", version: "0.
|
|
372
|
+
var CLIENT_INFO = { name: "consol-js-client", version: "0.3.0" };
|
|
650
373
|
var LOCAL = "default";
|
|
651
374
|
function payload(tool, reply) {
|
|
652
375
|
const error = replyError(reply, tool);
|
|
@@ -709,19 +432,13 @@ function required(options, fields) {
|
|
|
709
432
|
}
|
|
710
433
|
async function local(options, create) {
|
|
711
434
|
required(options, ["path", "agent"]);
|
|
712
|
-
const path = options.path.startsWith("s3://") ? options.path :
|
|
713
|
-
const transport =
|
|
435
|
+
const path = options.path.startsWith("s3://") ? options.path : import_node_path2.resolve(options.path);
|
|
436
|
+
const transport = await NativeTransport.start({
|
|
714
437
|
...options,
|
|
715
|
-
location:
|
|
438
|
+
location: { vault: path },
|
|
716
439
|
boot: { vault: LOCAL, create },
|
|
717
440
|
sdkVersion: CLIENT_INFO.version
|
|
718
441
|
});
|
|
719
|
-
try {
|
|
720
|
-
await transport.start();
|
|
721
|
-
} catch (error) {
|
|
722
|
-
await transport.close();
|
|
723
|
-
throw error;
|
|
724
|
-
}
|
|
725
442
|
return construct(transport, LOCAL, options.agent);
|
|
726
443
|
}
|
|
727
444
|
function createVault(options) {
|
|
@@ -777,18 +494,11 @@ class Consol {
|
|
|
777
494
|
if (vaultRoot === undefined === (vault === undefined)) {
|
|
778
495
|
throw new ConsolError("invalid_argument", "give exactly one of vaultRoot or vault", { field: "vaultRoot" });
|
|
779
496
|
}
|
|
780
|
-
|
|
497
|
+
return new Consol(await NativeTransport.start({
|
|
781
498
|
...engine,
|
|
782
|
-
location: vaultRoot === undefined ?
|
|
499
|
+
location: vaultRoot === undefined ? { vault } : { vaultRoot },
|
|
783
500
|
sdkVersion: CLIENT_INFO.version
|
|
784
|
-
});
|
|
785
|
-
try {
|
|
786
|
-
await transport.start();
|
|
787
|
-
} catch (error) {
|
|
788
|
-
await transport.close();
|
|
789
|
-
throw error;
|
|
790
|
-
}
|
|
791
|
-
return new Consol(transport);
|
|
501
|
+
}));
|
|
792
502
|
}
|
|
793
503
|
async handle(body, ctx, options) {
|
|
794
504
|
if (ctx === null || typeof ctx !== "object" || ctx.vaults !== null && !Array.isArray(ctx.vaults)) {
|
package/dist/mcp.d.ts
ADDED