zmemory 0.1.0 → 0.1.1
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 +4 -0
- package/bin/zmemory-mcp.js +2 -0
- package/bin/zmemory.js +3 -5
- package/package.json +3 -3
- package/src/commands/help.js +6 -1
- package/src/commands/init.js +2 -0
- package/src/commands/setup.js +51 -15
- package/src/integrations/auto-bootstrap.js +5 -0
- package/src/mcp/server.js +152 -39
package/README.md
CHANGED
package/bin/zmemory.js
CHANGED
|
@@ -49,12 +49,12 @@ const args = process.argv.slice(2);
|
|
|
49
49
|
const cmd = args[0];
|
|
50
50
|
|
|
51
51
|
// Global flags
|
|
52
|
-
if (args.
|
|
52
|
+
if (args.length === 1 && (args[0] === "-v" || args[0] === "--version")) {
|
|
53
53
|
await versionCommand();
|
|
54
54
|
process.exit(0);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
if (args.
|
|
57
|
+
if (args.length === 1 && (args[0] === "-h" || args[0] === "--help")) {
|
|
58
58
|
await helpCommand();
|
|
59
59
|
process.exit(0);
|
|
60
60
|
}
|
|
@@ -414,12 +414,10 @@ async function main() {
|
|
|
414
414
|
await doctor();
|
|
415
415
|
break;
|
|
416
416
|
case "mcp":
|
|
417
|
-
console.error("ZMemory MCP server started (stdio mode)");
|
|
418
417
|
await import("../src/mcp/server.js");
|
|
419
418
|
break;
|
|
420
419
|
default:
|
|
421
|
-
|
|
422
|
-
console.log("Commands: init status start-run context event handoff decision failure next summary");
|
|
420
|
+
await helpCommand();
|
|
423
421
|
}
|
|
424
422
|
}
|
|
425
423
|
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zmemory",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Local-first shared memory layer for AI coding agents",
|
|
5
5
|
"bin": {
|
|
6
|
-
"zmemory": "bin/zmemory.js"
|
|
6
|
+
"zmemory": "bin/zmemory.js",
|
|
7
|
+
"zmemory-mcp": "bin/zmemory-mcp.js"
|
|
7
8
|
},
|
|
8
9
|
"keywords": [
|
|
9
10
|
"ai",
|
|
@@ -36,7 +37,6 @@
|
|
|
36
37
|
"prepare": "node scripts/prepare.js"
|
|
37
38
|
},
|
|
38
39
|
"dependencies": {
|
|
39
|
-
"picomatch": "^4.0.0",
|
|
40
40
|
"@clack/prompts": "^0.7.0"
|
|
41
41
|
}
|
|
42
42
|
}
|
package/src/commands/help.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
export async function helpCommand() {
|
|
2
|
-
console.log("ZMemory");
|
|
2
|
+
console.log("ZMemory CLI");
|
|
3
3
|
console.log("Shared project memory for AI agents\n");
|
|
4
4
|
|
|
5
|
+
console.log("Common commands:");
|
|
6
|
+
console.log(" zmemory setup Interactive platform setup");
|
|
7
|
+
console.log(" zmemory init Initialize .zmemory in this repo");
|
|
8
|
+
console.log(" zmemory bootstrap Ensure .zmemory structure exists\n");
|
|
9
|
+
|
|
5
10
|
console.log("Core:");
|
|
6
11
|
console.log(" zmemory setup Interactive platform setup");
|
|
7
12
|
console.log(" zmemory init Initialize .zmemory in this repo");
|
package/src/commands/init.js
CHANGED
|
@@ -10,6 +10,8 @@ export async function initProject() {
|
|
|
10
10
|
ensureDir(path.join(base, "logs"));
|
|
11
11
|
ensureDir(path.join(base, "packets"));
|
|
12
12
|
ensureDir(path.join(base, "skills"));
|
|
13
|
+
ensureDir(path.join(base, "agents"));
|
|
14
|
+
ensureDir(path.join(base, "claims"));
|
|
13
15
|
|
|
14
16
|
writeJSON(path.join(base, "config.json"), {
|
|
15
17
|
project_name: "project",
|
package/src/commands/setup.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import os from "os";
|
|
3
3
|
import path from "path";
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
const MCP_COMMAND = "zmemory-mcp";
|
|
5
6
|
|
|
6
7
|
function ensureDir(p) {
|
|
7
8
|
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
@@ -12,11 +13,31 @@ function writeJSONMerge(file, patch) {
|
|
|
12
13
|
try {
|
|
13
14
|
if (fs.existsSync(file)) data = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
14
15
|
} catch {}
|
|
15
|
-
|
|
16
|
+
|
|
17
|
+
const merged = deepMerge(data, patch);
|
|
16
18
|
ensureDir(file);
|
|
17
19
|
fs.writeFileSync(file, JSON.stringify(merged, null, 2));
|
|
18
20
|
}
|
|
19
21
|
|
|
22
|
+
function deepMerge(base, patch) {
|
|
23
|
+
const out = { ...base };
|
|
24
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
25
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
26
|
+
out[key] = deepMerge(out[key] && typeof out[key] === "object" && !Array.isArray(out[key]) ? out[key] : {}, value);
|
|
27
|
+
} else {
|
|
28
|
+
out[key] = value;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return out;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function removePluginValue(data, value) {
|
|
35
|
+
if (Array.isArray(data.plugin)) {
|
|
36
|
+
data.plugin = data.plugin.filter((p) => p !== value);
|
|
37
|
+
if (!data.plugin.length) delete data.plugin;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
20
41
|
function installClaude() {
|
|
21
42
|
const file = path.join(os.homedir(), ".claude", "settings.json");
|
|
22
43
|
let data = {};
|
|
@@ -25,7 +46,7 @@ function installClaude() {
|
|
|
25
46
|
} catch {}
|
|
26
47
|
|
|
27
48
|
data.mcpServers = data.mcpServers || {};
|
|
28
|
-
data.mcpServers.zmemory = { command:
|
|
49
|
+
data.mcpServers.zmemory = { command: MCP_COMMAND };
|
|
29
50
|
|
|
30
51
|
ensureDir(file);
|
|
31
52
|
fs.writeFileSync(file, JSON.stringify(data, null, 2));
|
|
@@ -38,8 +59,11 @@ function installCodex() {
|
|
|
38
59
|
if (fs.existsSync(file)) content = fs.readFileSync(file, "utf8");
|
|
39
60
|
} catch {}
|
|
40
61
|
|
|
41
|
-
|
|
42
|
-
|
|
62
|
+
const block = `[mcp_servers.zmemory]\ncommand = "${MCP_COMMAND}"\n`;
|
|
63
|
+
if (content.includes("[mcp_servers.zmemory]")) {
|
|
64
|
+
content = content.replace(/\n?\[mcp_servers\.zmemory\][\s\S]*?(?=\n\[|$)/, `\n${block}`);
|
|
65
|
+
} else {
|
|
66
|
+
content += `\n${block}`;
|
|
43
67
|
}
|
|
44
68
|
|
|
45
69
|
ensureDir(file);
|
|
@@ -54,7 +78,7 @@ function installCursor() {
|
|
|
54
78
|
} catch {}
|
|
55
79
|
|
|
56
80
|
data.mcpServers = data.mcpServers || {};
|
|
57
|
-
data.mcpServers.zmemory = { command:
|
|
81
|
+
data.mcpServers.zmemory = { command: MCP_COMMAND };
|
|
58
82
|
|
|
59
83
|
ensureDir(file);
|
|
60
84
|
fs.writeFileSync(file, JSON.stringify(data, null, 2));
|
|
@@ -67,8 +91,12 @@ function installOpenCode() {
|
|
|
67
91
|
if (fs.existsSync(file)) data = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
68
92
|
} catch {}
|
|
69
93
|
|
|
70
|
-
data
|
|
71
|
-
|
|
94
|
+
removePluginValue(data, "zmemory");
|
|
95
|
+
data.mcp = data.mcp || {};
|
|
96
|
+
data.mcp.zmemory = {
|
|
97
|
+
type: "local",
|
|
98
|
+
command: [MCP_COMMAND]
|
|
99
|
+
};
|
|
72
100
|
|
|
73
101
|
ensureDir(file);
|
|
74
102
|
fs.writeFileSync(file, JSON.stringify(data, null, 2));
|
|
@@ -81,28 +109,36 @@ function installKilo() {
|
|
|
81
109
|
if (fs.existsSync(file)) data = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
82
110
|
} catch {}
|
|
83
111
|
|
|
84
|
-
data
|
|
85
|
-
|
|
112
|
+
data.$schema = "https://app.kilo.ai/config.json";
|
|
113
|
+
removePluginValue(data, "zmemory");
|
|
114
|
+
if (data.mcpServers?.zmemory) delete data.mcpServers.zmemory;
|
|
115
|
+
if (data.mcpServers && !Object.keys(data.mcpServers).length) delete data.mcpServers;
|
|
116
|
+
data.mcp = data.mcp || {};
|
|
117
|
+
data.mcp.zmemory = {
|
|
118
|
+
type: "local",
|
|
119
|
+
command: [MCP_COMMAND]
|
|
120
|
+
};
|
|
86
121
|
|
|
87
122
|
ensureDir(file);
|
|
88
123
|
fs.writeFileSync(file, JSON.stringify(data, null, 2));
|
|
89
124
|
}
|
|
90
125
|
|
|
91
126
|
function installAGY() {
|
|
92
|
-
const file = path.join(os.homedir(), ".
|
|
127
|
+
const file = path.join(os.homedir(), ".gemini", "config", "mcp_config.json");
|
|
93
128
|
writeJSONMerge(file, {
|
|
94
|
-
mcpServers: { zmemory: { command:
|
|
129
|
+
mcpServers: { zmemory: { command: MCP_COMMAND } }
|
|
95
130
|
});
|
|
96
131
|
}
|
|
97
132
|
|
|
98
133
|
function installKimi() {
|
|
99
134
|
const file = path.join(os.homedir(), ".kimi-code", "mcp.json");
|
|
100
135
|
writeJSONMerge(file, {
|
|
101
|
-
mcpServers: { zmemory: { command:
|
|
136
|
+
mcpServers: { zmemory: { command: MCP_COMMAND, args: [] } }
|
|
102
137
|
});
|
|
103
138
|
}
|
|
104
139
|
|
|
105
140
|
export async function setupCommand() {
|
|
141
|
+
const { multiselect, confirm, intro, outro, isCancel } = await import("@clack/prompts");
|
|
106
142
|
intro("ZMemory Setup");
|
|
107
143
|
|
|
108
144
|
const selected = await multiselect({
|
|
@@ -118,7 +154,7 @@ export async function setupCommand() {
|
|
|
118
154
|
]
|
|
119
155
|
});
|
|
120
156
|
|
|
121
|
-
if (!selected || !selected.length) {
|
|
157
|
+
if (isCancel(selected) || !selected || !selected.length) {
|
|
122
158
|
outro("No platforms selected.");
|
|
123
159
|
return;
|
|
124
160
|
}
|
|
@@ -132,7 +168,7 @@ export async function setupCommand() {
|
|
|
132
168
|
if (selected.includes("kimi")) installKimi();
|
|
133
169
|
|
|
134
170
|
const initRepo = await confirm({ message: "Initialize .zmemory in this repo?" });
|
|
135
|
-
if (initRepo) {
|
|
171
|
+
if (!isCancel(initRepo) && initRepo) {
|
|
136
172
|
const { initProject } = await import("./init.js");
|
|
137
173
|
await initProject();
|
|
138
174
|
}
|
|
@@ -14,9 +14,14 @@ export function ensureZMemory() {
|
|
|
14
14
|
fs.mkdirSync(path.join(dir, "runs/active"), { recursive: true });
|
|
15
15
|
fs.mkdirSync(path.join(dir, "runs/archived"), { recursive: true });
|
|
16
16
|
fs.mkdirSync(path.join(dir, "logs"), { recursive: true });
|
|
17
|
+
fs.mkdirSync(path.join(dir, "agents"), { recursive: true });
|
|
18
|
+
fs.mkdirSync(path.join(dir, "claims"), { recursive: true });
|
|
17
19
|
fs.writeFileSync(path.join(dir, "logs/events.jsonl"), "");
|
|
18
20
|
}
|
|
19
21
|
|
|
22
|
+
fs.mkdirSync(path.join(dir, "agents"), { recursive: true });
|
|
23
|
+
fs.mkdirSync(path.join(dir, "claims"), { recursive: true });
|
|
24
|
+
|
|
20
25
|
const skillsDir = path.join(dir, "skills");
|
|
21
26
|
fs.mkdirSync(skillsDir, { recursive: true });
|
|
22
27
|
const skillFile = path.join(skillsDir, "coordination.md");
|
package/src/mcp/server.js
CHANGED
|
@@ -9,12 +9,14 @@ import { planCommand } from "../commands/plan.js";
|
|
|
9
9
|
import { routeRun } from "../commands/route.js";
|
|
10
10
|
import { readJSON, writeJSON } from "../lib/fs.js";
|
|
11
11
|
import { acquireLock, releaseLock } from "../lib/lock.js";
|
|
12
|
+
import { claimPattern, listClaims, releaseClaims } from "../lib/coordination/claims.js";
|
|
13
|
+
import { who as whoLookup } from "../lib/coordination/who.js";
|
|
14
|
+
|
|
12
15
|
const EVENTS_FILE = `.zmemory/logs/events.jsonl`;
|
|
13
16
|
const ARCHIVE_DIR = `.zmemory/logs/archive`;
|
|
14
17
|
const MAX_ACTIVE_EVENTS = 5000;
|
|
15
18
|
const ARCHIVE_BATCH = 2000;
|
|
16
|
-
|
|
17
|
-
import { who as whoLookup } from "../lib/coordination/who.js";
|
|
19
|
+
const SERVER_VERSION = JSON.parse(fs.readFileSync(new URL("../../package.json", import.meta.url), "utf8")).version;
|
|
18
20
|
|
|
19
21
|
// ---- Tool Contracts (source of truth) ----
|
|
20
22
|
const toolContracts = {
|
|
@@ -324,6 +326,139 @@ try {
|
|
|
324
326
|
let buffer = "";
|
|
325
327
|
let lineQueue = Promise.resolve();
|
|
326
328
|
|
|
329
|
+
function writeProtocolJSON(value) {
|
|
330
|
+
process.stdout.write(JSON.stringify(value) + "\n");
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function typeToJSONSchema(type) {
|
|
334
|
+
if (type === "number") return { type: "number" };
|
|
335
|
+
if (type === "boolean") return { type: "boolean" };
|
|
336
|
+
if (type === "array:string") return { type: "array", items: { type: "string", minLength: 1 } };
|
|
337
|
+
if (type === "run_id" || type === "nonempty:string") return { type: "string", minLength: 1 };
|
|
338
|
+
return { type: "string" };
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
function contractToMCPTool(name, contract) {
|
|
342
|
+
const required = Object.keys(contract.input.required || {});
|
|
343
|
+
const properties = {};
|
|
344
|
+
for (const [key, type] of Object.entries(contract.input.required || {})) {
|
|
345
|
+
properties[key] = typeToJSONSchema(type);
|
|
346
|
+
}
|
|
347
|
+
for (const [key, type] of Object.entries(contract.input.optional || {})) {
|
|
348
|
+
properties[key] = typeToJSONSchema(type);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
return {
|
|
352
|
+
name,
|
|
353
|
+
description: contract.description,
|
|
354
|
+
inputSchema: {
|
|
355
|
+
type: "object",
|
|
356
|
+
properties,
|
|
357
|
+
required,
|
|
358
|
+
additionalProperties: false
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
async function invokeTool(toolName, input) {
|
|
364
|
+
const fn = tools[toolName];
|
|
365
|
+
if (!fn) throw new Error("unknown tool");
|
|
366
|
+
|
|
367
|
+
let capturedOut = "";
|
|
368
|
+
let capturedErr = "";
|
|
369
|
+
const origLog = console.log;
|
|
370
|
+
const origErr = console.error;
|
|
371
|
+
|
|
372
|
+
console.log = (...a) => {
|
|
373
|
+
capturedOut += a.map(v => String(v)).join(" ") + "\n";
|
|
374
|
+
};
|
|
375
|
+
console.error = (...a) => {
|
|
376
|
+
capturedErr += a.map(v => String(v)).join(" ") + "\n";
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
try {
|
|
380
|
+
validateInput(toolName, input);
|
|
381
|
+
const raw = await fn(input);
|
|
382
|
+
return {
|
|
383
|
+
result: raw === undefined ? null : raw,
|
|
384
|
+
stdout: capturedOut,
|
|
385
|
+
stderr: capturedErr
|
|
386
|
+
};
|
|
387
|
+
} finally {
|
|
388
|
+
console.log = origLog;
|
|
389
|
+
console.error = origErr;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
function jsonRpcResult(id, result) {
|
|
394
|
+
writeProtocolJSON({ jsonrpc: "2.0", id, result });
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
function jsonRpcError(id, code, message) {
|
|
398
|
+
writeProtocolJSON({ jsonrpc: "2.0", id, error: { code, message } });
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
function mcpToolContent(payload) {
|
|
402
|
+
const hasOnlyResult = !payload.stdout && !payload.stderr;
|
|
403
|
+
const value = hasOnlyResult ? payload.result : payload;
|
|
404
|
+
const text = typeof value === "string" ? value : JSON.stringify(value, null, 2);
|
|
405
|
+
return { content: [{ type: "text", text }] };
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
async function handleJsonRpcMessage(msg) {
|
|
409
|
+
const id = msg.id ?? null;
|
|
410
|
+
const method = msg.method;
|
|
411
|
+
|
|
412
|
+
if (method === "notifications/initialized" || method === "initialized") return;
|
|
413
|
+
|
|
414
|
+
if (method === "initialize") {
|
|
415
|
+
jsonRpcResult(id, {
|
|
416
|
+
protocolVersion: msg.params?.protocolVersion || "2024-11-05",
|
|
417
|
+
capabilities: { tools: {} },
|
|
418
|
+
serverInfo: { name: "zmemory", version: SERVER_VERSION }
|
|
419
|
+
});
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
if (method === "ping") {
|
|
424
|
+
jsonRpcResult(id, {});
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
if (method === "tools/list") {
|
|
429
|
+
jsonRpcResult(id, {
|
|
430
|
+
tools: Object.entries(toolContracts).map(([name, contract]) => contractToMCPTool(name, contract))
|
|
431
|
+
});
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
if (method === "tools/call") {
|
|
436
|
+
const name = msg.params?.name;
|
|
437
|
+
const input = msg.params?.arguments || {};
|
|
438
|
+
if (typeof name !== "string" || !name.trim()) {
|
|
439
|
+
jsonRpcError(id, -32602, "invalid tool name");
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
443
|
+
jsonRpcError(id, -32602, "invalid tool arguments");
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
try {
|
|
448
|
+
const payload = await invokeTool(name.trim(), input);
|
|
449
|
+
jsonRpcResult(id, mcpToolContent(payload));
|
|
450
|
+
} catch (e) {
|
|
451
|
+
jsonRpcResult(id, {
|
|
452
|
+
isError: true,
|
|
453
|
+
content: [{ type: "text", text: e?.message || String(e) }]
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
jsonRpcError(id, -32601, "method not found");
|
|
460
|
+
}
|
|
461
|
+
|
|
327
462
|
|
|
328
463
|
|
|
329
464
|
async function handleLine(line) {
|
|
@@ -333,7 +468,7 @@ async function handleLine(line) {
|
|
|
333
468
|
try {
|
|
334
469
|
msg = JSON.parse(line);
|
|
335
470
|
} catch {
|
|
336
|
-
|
|
471
|
+
writeProtocolJSON({ error: "malformed json" });
|
|
337
472
|
return;
|
|
338
473
|
}
|
|
339
474
|
|
|
@@ -341,64 +476,42 @@ async function handleLine(line) {
|
|
|
341
476
|
if (!msg || typeof msg !== "object" || Array.isArray(msg)) {
|
|
342
477
|
const out = { error: "invalid message" };
|
|
343
478
|
if (id !== undefined) out.id = id;
|
|
344
|
-
|
|
479
|
+
writeProtocolJSON(out);
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
if (typeof msg.method === "string") {
|
|
484
|
+
await handleJsonRpcMessage(msg);
|
|
345
485
|
return;
|
|
346
486
|
}
|
|
347
487
|
|
|
348
488
|
if (typeof msg.tool !== "string" || !msg.tool.trim()) {
|
|
349
489
|
const out = { error: "invalid message: tool" };
|
|
350
490
|
if (id !== undefined) out.id = id;
|
|
351
|
-
|
|
491
|
+
writeProtocolJSON(out);
|
|
352
492
|
return;
|
|
353
493
|
}
|
|
354
494
|
|
|
355
495
|
if (msg.input !== undefined && (msg.input === null || typeof msg.input !== "object" || Array.isArray(msg.input))) {
|
|
356
496
|
const out = { error: "invalid message: input" };
|
|
357
497
|
if (id !== undefined) out.id = id;
|
|
358
|
-
|
|
498
|
+
writeProtocolJSON(out);
|
|
359
499
|
return;
|
|
360
500
|
}
|
|
361
501
|
const toolName = msg.tool.trim();
|
|
362
|
-
const fn = tools[toolName];
|
|
363
|
-
if (!fn) {
|
|
364
|
-
const out = { error: "unknown tool" };
|
|
365
|
-
if (id !== undefined) out.id = id;
|
|
366
|
-
process.stdout.write(JSON.stringify(out) + "\n");
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
let capturedOut = "";
|
|
371
|
-
let capturedErr = "";
|
|
372
|
-
|
|
373
|
-
const origLog = console.log;
|
|
374
|
-
const origErr = console.error;
|
|
375
|
-
|
|
376
|
-
console.log = (...a) => {
|
|
377
|
-
capturedOut += a.map(v => String(v)).join(" ") + "\n";
|
|
378
|
-
};
|
|
379
|
-
console.error = (...a) => {
|
|
380
|
-
capturedErr += a.map(v => String(v)).join(" ") + "\n";
|
|
381
|
-
};
|
|
382
502
|
|
|
383
503
|
try {
|
|
384
504
|
const input = msg.input || {};
|
|
385
|
-
|
|
386
|
-
const
|
|
387
|
-
const result = raw === undefined ? null : raw;
|
|
388
|
-
const out = { result };
|
|
505
|
+
const payload = await invokeTool(toolName, input);
|
|
506
|
+
const out = { result: payload.result };
|
|
389
507
|
if (id !== undefined) out.id = id;
|
|
390
|
-
if (
|
|
391
|
-
if (
|
|
392
|
-
|
|
508
|
+
if (payload.stdout) out.stdout = payload.stdout;
|
|
509
|
+
if (payload.stderr) out.stderr = payload.stderr;
|
|
510
|
+
writeProtocolJSON(out);
|
|
393
511
|
} catch (e) {
|
|
394
512
|
const out = { error: e?.message || String(e) };
|
|
395
513
|
if (id !== undefined) out.id = id;
|
|
396
|
-
|
|
397
|
-
if (capturedErr) out.stderr = capturedErr;
|
|
398
|
-
process.stdout.write(JSON.stringify(out) + "\n");
|
|
399
|
-
} finally {
|
|
400
|
-
console.log = origLog;
|
|
401
|
-
console.error = origErr;
|
|
514
|
+
writeProtocolJSON(out);
|
|
402
515
|
}
|
|
403
516
|
}
|
|
404
517
|
|