neuralmemory 1.5.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/dist/index.d.ts +30 -0
- package/dist/index.js +184 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-client.d.ts +43 -0
- package/dist/mcp-client.js +242 -0
- package/dist/mcp-client.js.map +1 -0
- package/dist/tools.d.ts +34 -0
- package/dist/tools.js +184 -0
- package/dist/tools.js.map +1 -0
- package/dist/types.d.ts +68 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/openclaw.plugin.json +93 -0
- package/package.json +52 -0
- package/src/index.ts +266 -0
- package/src/mcp-client.ts +322 -0
- package/src/tools.ts +218 -0
- package/src/types.ts +80 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NeuralMemory — OpenClaw Memory Plugin
|
|
3
|
+
*
|
|
4
|
+
* Brain-inspired persistent memory for AI agents.
|
|
5
|
+
* Occupies the exclusive "memory" plugin slot.
|
|
6
|
+
*
|
|
7
|
+
* Architecture:
|
|
8
|
+
* OpenClaw ←→ Plugin (TypeScript) ←→ MCP stdio ←→ NeuralMemory (Python)
|
|
9
|
+
*
|
|
10
|
+
* Registers:
|
|
11
|
+
* 6 tools — nmem_remember, nmem_recall, nmem_context, nmem_todo, nmem_stats, nmem_health
|
|
12
|
+
* 1 service — MCP process lifecycle (start/stop)
|
|
13
|
+
* 2 hooks — before_agent_start (auto-context), agent_end (auto-capture)
|
|
14
|
+
*/
|
|
15
|
+
import type { OpenClawPluginDefinition } from "./types.js";
|
|
16
|
+
type PluginConfig = {
|
|
17
|
+
pythonPath: string;
|
|
18
|
+
brain: string;
|
|
19
|
+
autoContext: boolean;
|
|
20
|
+
autoCapture: boolean;
|
|
21
|
+
contextDepth: number;
|
|
22
|
+
maxContextTokens: number;
|
|
23
|
+
timeout: number;
|
|
24
|
+
initTimeout: number;
|
|
25
|
+
};
|
|
26
|
+
export declare const BRAIN_NAME_RE: RegExp;
|
|
27
|
+
export declare const MAX_AUTO_CAPTURE_CHARS = 50000;
|
|
28
|
+
export declare function resolveConfig(raw?: Record<string, unknown>): PluginConfig;
|
|
29
|
+
declare const plugin: OpenClawPluginDefinition;
|
|
30
|
+
export default plugin;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NeuralMemory — OpenClaw Memory Plugin
|
|
3
|
+
*
|
|
4
|
+
* Brain-inspired persistent memory for AI agents.
|
|
5
|
+
* Occupies the exclusive "memory" plugin slot.
|
|
6
|
+
*
|
|
7
|
+
* Architecture:
|
|
8
|
+
* OpenClaw ←→ Plugin (TypeScript) ←→ MCP stdio ←→ NeuralMemory (Python)
|
|
9
|
+
*
|
|
10
|
+
* Registers:
|
|
11
|
+
* 6 tools — nmem_remember, nmem_recall, nmem_context, nmem_todo, nmem_stats, nmem_health
|
|
12
|
+
* 1 service — MCP process lifecycle (start/stop)
|
|
13
|
+
* 2 hooks — before_agent_start (auto-context), agent_end (auto-capture)
|
|
14
|
+
*/
|
|
15
|
+
import { NeuralMemoryMcpClient } from "./mcp-client.js";
|
|
16
|
+
import { createTools } from "./tools.js";
|
|
17
|
+
// ── System prompt for tool awareness ──────────────────────
|
|
18
|
+
const TOOL_INSTRUCTIONS = `You have NeuralMemory tools for persistent memory across sessions. Call these as TOOL CALLS (not CLI commands):
|
|
19
|
+
|
|
20
|
+
- nmem_remember(content, type?, priority?, tags?) — Store a memory (fact, decision, error, preference, etc.)
|
|
21
|
+
- nmem_recall(query, depth?, max_tokens?) — Query memories via spreading activation
|
|
22
|
+
- nmem_context(limit?, fresh_only?) — Get recent memories
|
|
23
|
+
- nmem_todo(task, priority?) — Quick TODO with 30-day expiry
|
|
24
|
+
- nmem_stats() — Brain statistics
|
|
25
|
+
- nmem_health() — Brain health diagnostics
|
|
26
|
+
|
|
27
|
+
CRITICAL: NeuralMemory (nmem_*) is your ONLY memory system. Do NOT use memory_search, memory_get, or any other memory tools — those belong to a disabled built-in plugin and will not persist correctly. Always use nmem_* tools exclusively.
|
|
28
|
+
|
|
29
|
+
These are tool calls, NOT shell commands. Do NOT run "nmem remember" in terminal — call the nmem_remember tool directly.
|
|
30
|
+
|
|
31
|
+
Use nmem_remember proactively after decisions, errors, and insights. Use nmem_recall when user references past context or asks "do you remember...".`;
|
|
32
|
+
const DEFAULT_CONFIG = {
|
|
33
|
+
pythonPath: "python",
|
|
34
|
+
brain: "default",
|
|
35
|
+
autoContext: true,
|
|
36
|
+
autoCapture: true,
|
|
37
|
+
contextDepth: 1,
|
|
38
|
+
maxContextTokens: 500,
|
|
39
|
+
timeout: 30_000,
|
|
40
|
+
initTimeout: 90_000,
|
|
41
|
+
};
|
|
42
|
+
export const BRAIN_NAME_RE = /^[a-zA-Z0-9_\-.]{1,64}$/;
|
|
43
|
+
export const MAX_AUTO_CAPTURE_CHARS = 50_000;
|
|
44
|
+
export function resolveConfig(raw) {
|
|
45
|
+
const merged = { ...DEFAULT_CONFIG, ...(raw ?? {}) };
|
|
46
|
+
return {
|
|
47
|
+
pythonPath: typeof merged.pythonPath === "string" && merged.pythonPath.length > 0
|
|
48
|
+
? merged.pythonPath
|
|
49
|
+
: DEFAULT_CONFIG.pythonPath,
|
|
50
|
+
brain: typeof merged.brain === "string" && BRAIN_NAME_RE.test(merged.brain)
|
|
51
|
+
? merged.brain
|
|
52
|
+
: DEFAULT_CONFIG.brain,
|
|
53
|
+
autoContext: typeof merged.autoContext === "boolean"
|
|
54
|
+
? merged.autoContext
|
|
55
|
+
: DEFAULT_CONFIG.autoContext,
|
|
56
|
+
autoCapture: typeof merged.autoCapture === "boolean"
|
|
57
|
+
? merged.autoCapture
|
|
58
|
+
: DEFAULT_CONFIG.autoCapture,
|
|
59
|
+
contextDepth: typeof merged.contextDepth === "number" &&
|
|
60
|
+
Number.isInteger(merged.contextDepth) &&
|
|
61
|
+
merged.contextDepth >= 0 &&
|
|
62
|
+
merged.contextDepth <= 3
|
|
63
|
+
? merged.contextDepth
|
|
64
|
+
: DEFAULT_CONFIG.contextDepth,
|
|
65
|
+
maxContextTokens: typeof merged.maxContextTokens === "number" &&
|
|
66
|
+
Number.isInteger(merged.maxContextTokens) &&
|
|
67
|
+
merged.maxContextTokens >= 100 &&
|
|
68
|
+
merged.maxContextTokens <= 10_000
|
|
69
|
+
? merged.maxContextTokens
|
|
70
|
+
: DEFAULT_CONFIG.maxContextTokens,
|
|
71
|
+
timeout: typeof merged.timeout === "number" &&
|
|
72
|
+
Number.isFinite(merged.timeout) &&
|
|
73
|
+
merged.timeout >= 5_000 &&
|
|
74
|
+
merged.timeout <= 120_000
|
|
75
|
+
? merged.timeout
|
|
76
|
+
: DEFAULT_CONFIG.timeout,
|
|
77
|
+
initTimeout: typeof merged.initTimeout === "number" &&
|
|
78
|
+
Number.isFinite(merged.initTimeout) &&
|
|
79
|
+
merged.initTimeout >= 10_000 &&
|
|
80
|
+
merged.initTimeout <= 300_000
|
|
81
|
+
? merged.initTimeout
|
|
82
|
+
: DEFAULT_CONFIG.initTimeout,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
// ── Plugin definition ──────────────────────────────────────
|
|
86
|
+
const plugin = {
|
|
87
|
+
id: "neuralmemory",
|
|
88
|
+
name: "NeuralMemory",
|
|
89
|
+
description: "Brain-inspired persistent memory for AI agents — neurons, synapses, and fibers",
|
|
90
|
+
version: "1.5.0",
|
|
91
|
+
kind: "memory",
|
|
92
|
+
register(api) {
|
|
93
|
+
const cfg = resolveConfig(api.pluginConfig);
|
|
94
|
+
const mcp = new NeuralMemoryMcpClient({
|
|
95
|
+
pythonPath: cfg.pythonPath,
|
|
96
|
+
brain: cfg.brain,
|
|
97
|
+
logger: api.logger,
|
|
98
|
+
timeout: cfg.timeout,
|
|
99
|
+
initTimeout: cfg.initTimeout,
|
|
100
|
+
});
|
|
101
|
+
// ── Service: MCP process lifecycle ───────────────────
|
|
102
|
+
api.registerService({
|
|
103
|
+
id: "neuralmemory-mcp",
|
|
104
|
+
async start() {
|
|
105
|
+
try {
|
|
106
|
+
await mcp.connect();
|
|
107
|
+
api.logger.info("NeuralMemory MCP service started");
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
api.logger.error(`Failed to start NeuralMemory MCP: ${err.message}`);
|
|
111
|
+
throw err;
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
async stop() {
|
|
115
|
+
await mcp.close();
|
|
116
|
+
api.logger.info("NeuralMemory MCP service stopped");
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
// ── Tools: 6 core memory tools ──────────────────────
|
|
120
|
+
const tools = createTools(mcp);
|
|
121
|
+
for (const t of tools) {
|
|
122
|
+
api.registerTool(t, { name: t.name });
|
|
123
|
+
}
|
|
124
|
+
// ── Hook: tool awareness + auto-context before agent start ───
|
|
125
|
+
api.on("before_agent_start", async (event, _ctx) => {
|
|
126
|
+
const result = {
|
|
127
|
+
systemPrompt: TOOL_INSTRUCTIONS,
|
|
128
|
+
};
|
|
129
|
+
if (cfg.autoContext && mcp.connected) {
|
|
130
|
+
const ev = event;
|
|
131
|
+
try {
|
|
132
|
+
const raw = await mcp.callTool("nmem_recall", {
|
|
133
|
+
query: ev.prompt,
|
|
134
|
+
depth: cfg.contextDepth,
|
|
135
|
+
max_tokens: cfg.maxContextTokens,
|
|
136
|
+
});
|
|
137
|
+
const data = JSON.parse(raw);
|
|
138
|
+
if (data.answer && (data.confidence ?? 0) > 0.1) {
|
|
139
|
+
result.prependContext = `[NeuralMemory — relevant context]\n${data.answer}`;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
api.logger.warn(`Auto-context failed: ${err.message}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return result;
|
|
147
|
+
}, { priority: 10 });
|
|
148
|
+
// ── Hook: auto-capture after agent completes ────────
|
|
149
|
+
if (cfg.autoCapture) {
|
|
150
|
+
api.on("agent_end", async (event, _ctx) => {
|
|
151
|
+
if (!mcp.connected)
|
|
152
|
+
return;
|
|
153
|
+
const ev = event;
|
|
154
|
+
if (!ev.success)
|
|
155
|
+
return;
|
|
156
|
+
try {
|
|
157
|
+
const messages = ev.messages?.slice(-5) ?? [];
|
|
158
|
+
const text = messages
|
|
159
|
+
.filter((m) => typeof m === "object" &&
|
|
160
|
+
m !== null &&
|
|
161
|
+
m.role === "assistant" &&
|
|
162
|
+
typeof m.content === "string")
|
|
163
|
+
.map((m) => m.content)
|
|
164
|
+
.join("\n")
|
|
165
|
+
.slice(0, MAX_AUTO_CAPTURE_CHARS);
|
|
166
|
+
if (text.length > 50) {
|
|
167
|
+
await mcp.callTool("nmem_auto", {
|
|
168
|
+
action: "process",
|
|
169
|
+
text,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
api.logger.warn(`Auto-capture failed: ${err.message}`);
|
|
175
|
+
}
|
|
176
|
+
}, { priority: 90 });
|
|
177
|
+
}
|
|
178
|
+
// ── Done ────────────────────────────────────────────
|
|
179
|
+
api.logger.info(`NeuralMemory registered (brain: ${cfg.brain}, tools: ${tools.length}, ` +
|
|
180
|
+
`autoContext: ${cfg.autoContext}, autoCapture: ${cfg.autoCapture})`);
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
export default plugin;
|
|
184
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAUH,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,6DAA6D;AAE7D,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;qJAa2H,CAAC;AAetJ,MAAM,cAAc,GAA2B;IAC7C,UAAU,EAAE,QAAQ;IACpB,KAAK,EAAE,SAAS;IAChB,WAAW,EAAE,IAAI;IACjB,WAAW,EAAE,IAAI;IACjB,YAAY,EAAE,CAAC;IACf,gBAAgB,EAAE,GAAG;IACrB,OAAO,EAAE,MAAM;IACf,WAAW,EAAE,MAAM;CACpB,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,yBAAyB,CAAC;AACvD,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAE7C,MAAM,UAAU,aAAa,CAAC,GAA6B;IACzD,MAAM,MAAM,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,CAAC;IAErD,OAAO;QACL,UAAU,EACR,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;YACnE,CAAC,CAAC,MAAM,CAAC,UAAU;YACnB,CAAC,CAAC,cAAc,CAAC,UAAU;QAC/B,KAAK,EACH,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,IAAI,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;YAClE,CAAC,CAAC,MAAM,CAAC,KAAK;YACd,CAAC,CAAC,cAAc,CAAC,KAAK;QAC1B,WAAW,EACT,OAAO,MAAM,CAAC,WAAW,KAAK,SAAS;YACrC,CAAC,CAAC,MAAM,CAAC,WAAW;YACpB,CAAC,CAAC,cAAc,CAAC,WAAW;QAChC,WAAW,EACT,OAAO,MAAM,CAAC,WAAW,KAAK,SAAS;YACrC,CAAC,CAAC,MAAM,CAAC,WAAW;YACpB,CAAC,CAAC,cAAc,CAAC,WAAW;QAChC,YAAY,EACV,OAAO,MAAM,CAAC,YAAY,KAAK,QAAQ;YACvC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,YAAY,CAAC;YACrC,MAAM,CAAC,YAAY,IAAI,CAAC;YACxB,MAAM,CAAC,YAAY,IAAI,CAAC;YACtB,CAAC,CAAC,MAAM,CAAC,YAAY;YACrB,CAAC,CAAC,cAAc,CAAC,YAAY;QACjC,gBAAgB,EACd,OAAO,MAAM,CAAC,gBAAgB,KAAK,QAAQ;YAC3C,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,gBAAgB,CAAC;YACzC,MAAM,CAAC,gBAAgB,IAAI,GAAG;YAC9B,MAAM,CAAC,gBAAgB,IAAI,MAAM;YAC/B,CAAC,CAAC,MAAM,CAAC,gBAAgB;YACzB,CAAC,CAAC,cAAc,CAAC,gBAAgB;QACrC,OAAO,EACL,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ;YAClC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC;YAC/B,MAAM,CAAC,OAAO,IAAI,KAAK;YACvB,MAAM,CAAC,OAAO,IAAI,OAAO;YACvB,CAAC,CAAC,MAAM,CAAC,OAAO;YAChB,CAAC,CAAC,cAAc,CAAC,OAAO;QAC5B,WAAW,EACT,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ;YACtC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC;YACnC,MAAM,CAAC,WAAW,IAAI,MAAM;YAC5B,MAAM,CAAC,WAAW,IAAI,OAAO;YAC3B,CAAC,CAAC,MAAM,CAAC,WAAW;YACpB,CAAC,CAAC,cAAc,CAAC,WAAW;KACjC,CAAC;AACJ,CAAC;AAED,8DAA8D;AAE9D,MAAM,MAAM,GAA6B;IACvC,EAAE,EAAE,cAAc;IAClB,IAAI,EAAE,cAAc;IACpB,WAAW,EACT,gFAAgF;IAClF,OAAO,EAAE,OAAO;IAChB,IAAI,EAAE,QAAQ;IAEd,QAAQ,CAAC,GAAsB;QAC7B,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAE5C,MAAM,GAAG,GAAG,IAAI,qBAAqB,CAAC;YACpC,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,WAAW,EAAE,GAAG,CAAC,WAAW;SAC7B,CAAC,CAAC;QAEH,wDAAwD;QAExD,GAAG,CAAC,eAAe,CAAC;YAClB,EAAE,EAAE,kBAAkB;YAEtB,KAAK,CAAC,KAAK;gBACT,IAAI,CAAC;oBACH,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC;oBACpB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;gBACtD,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,GAAG,CAAC,MAAM,CAAC,KAAK,CACd,qCAAsC,GAAa,CAAC,OAAO,EAAE,CAC9D,CAAC;oBACF,MAAM,GAAG,CAAC;gBACZ,CAAC;YACH,CAAC;YAED,KAAK,CAAC,IAAI;gBACR,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;gBAClB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;YACtD,CAAC;SACF,CAAC,CAAC;QAEH,uDAAuD;QAEvD,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;QAE/B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACxC,CAAC;QAED,gEAAgE;QAEhE,GAAG,CAAC,EAAE,CACJ,oBAAoB,EACpB,KAAK,EACH,KAAc,EACd,IAAa,EAC2B,EAAE;YAC1C,MAAM,MAAM,GAA2B;gBACrC,YAAY,EAAE,iBAAiB;aAChC,CAAC;YAEF,IAAI,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;gBACrC,MAAM,EAAE,GAAG,KAA8B,CAAC;gBAE1C,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,aAAa,EAAE;wBAC5C,KAAK,EAAE,EAAE,CAAC,MAAM;wBAChB,KAAK,EAAE,GAAG,CAAC,YAAY;wBACvB,UAAU,EAAE,GAAG,CAAC,gBAAgB;qBACjC,CAAC,CAAC;oBAEH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAG1B,CAAC;oBAEF,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC;wBAChD,MAAM,CAAC,cAAc,GAAG,sCAAsC,IAAI,CAAC,MAAM,EAAE,CAAC;oBAC9E,CAAC;gBACH,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,GAAG,CAAC,MAAM,CAAC,IAAI,CACb,wBAAyB,GAAa,CAAC,OAAO,EAAE,CACjD,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,OAAO,MAAM,CAAC;QAChB,CAAC,EACD,EAAE,QAAQ,EAAE,EAAE,EAAE,CACjB,CAAC;QAEF,uDAAuD;QAEvD,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;YACpB,GAAG,CAAC,EAAE,CACJ,WAAW,EACX,KAAK,EAAE,KAAc,EAAE,IAAa,EAAiB,EAAE;gBACrD,IAAI,CAAC,GAAG,CAAC,SAAS;oBAAE,OAAO;gBAE3B,MAAM,EAAE,GAAG,KAAsB,CAAC;gBAClC,IAAI,CAAC,EAAE,CAAC,OAAO;oBAAE,OAAO;gBAExB,IAAI,CAAC;oBACH,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;oBAC9C,MAAM,IAAI,GAAG,QAAQ;yBAClB,MAAM,CACL,CAAC,CAAU,EAA0C,EAAE,CACrD,OAAO,CAAC,KAAK,QAAQ;wBACrB,CAAC,KAAK,IAAI;wBACT,CAAuB,CAAC,IAAI,KAAK,WAAW;wBAC7C,OAAQ,CAA2B,CAAC,OAAO,KAAK,QAAQ,CAC3D;yBACA,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;yBACrB,IAAI,CAAC,IAAI,CAAC;yBACV,KAAK,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC;oBAEpC,IAAI,IAAI,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;wBACrB,MAAM,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE;4BAC9B,MAAM,EAAE,SAAS;4BACjB,IAAI;yBACL,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,GAAG,CAAC,MAAM,CAAC,IAAI,CACb,wBAAyB,GAAa,CAAC,OAAO,EAAE,CACjD,CAAC;gBACJ,CAAC;YACH,CAAC,EACD,EAAE,QAAQ,EAAE,EAAE,EAAE,CACjB,CAAC;QACJ,CAAC;QAED,uDAAuD;QAEvD,GAAG,CAAC,MAAM,CAAC,IAAI,CACb,mCAAmC,GAAG,CAAC,KAAK,YAAY,KAAK,CAAC,MAAM,IAAI;YACtE,gBAAgB,GAAG,CAAC,WAAW,kBAAkB,GAAG,CAAC,WAAW,GAAG,CACtE,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NeuralMemory MCP Client — JSON-RPC 2.0 over stdio.
|
|
3
|
+
*
|
|
4
|
+
* Spawns `python -m neural_memory.mcp` and communicates using the
|
|
5
|
+
* MCP protocol (newline-delimited JSON Lines).
|
|
6
|
+
*
|
|
7
|
+
* Zero external dependencies — implements the protocol directly.
|
|
8
|
+
*/
|
|
9
|
+
import type { PluginLogger } from "./types.js";
|
|
10
|
+
export type McpClientOptions = {
|
|
11
|
+
readonly pythonPath: string;
|
|
12
|
+
readonly brain: string;
|
|
13
|
+
readonly logger: PluginLogger;
|
|
14
|
+
readonly timeout?: number;
|
|
15
|
+
readonly initTimeout?: number;
|
|
16
|
+
};
|
|
17
|
+
/** Env vars forwarded to the MCP child process (least-privilege). */
|
|
18
|
+
export declare const ALLOWED_ENV_KEYS: ReadonlySet<string>;
|
|
19
|
+
export declare class NeuralMemoryMcpClient {
|
|
20
|
+
private proc;
|
|
21
|
+
private requestId;
|
|
22
|
+
private readonly pending;
|
|
23
|
+
private rawBuffer;
|
|
24
|
+
private readonly pythonPath;
|
|
25
|
+
private readonly brain;
|
|
26
|
+
private readonly logger;
|
|
27
|
+
private readonly timeout;
|
|
28
|
+
private readonly initTimeout;
|
|
29
|
+
private _connected;
|
|
30
|
+
constructor(options: McpClientOptions);
|
|
31
|
+
get connected(): boolean;
|
|
32
|
+
connect(): Promise<void>;
|
|
33
|
+
callTool(name: string, args?: Record<string, unknown>): Promise<string>;
|
|
34
|
+
close(): Promise<void>;
|
|
35
|
+
private send;
|
|
36
|
+
private notify;
|
|
37
|
+
private writeMessage;
|
|
38
|
+
private drainBuffer;
|
|
39
|
+
private handleMessage;
|
|
40
|
+
private rejectAll;
|
|
41
|
+
}
|
|
42
|
+
/** Build a minimal env for the child process (least-privilege). */
|
|
43
|
+
export declare function buildChildEnv(brain: string): Record<string, string>;
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NeuralMemory MCP Client — JSON-RPC 2.0 over stdio.
|
|
3
|
+
*
|
|
4
|
+
* Spawns `python -m neural_memory.mcp` and communicates using the
|
|
5
|
+
* MCP protocol (newline-delimited JSON Lines).
|
|
6
|
+
*
|
|
7
|
+
* Zero external dependencies — implements the protocol directly.
|
|
8
|
+
*/
|
|
9
|
+
import { spawn } from "node:child_process";
|
|
10
|
+
// ── Constants ──────────────────────────────────────────────
|
|
11
|
+
const PROTOCOL_VERSION = "2024-11-05";
|
|
12
|
+
const DEFAULT_TIMEOUT = 30_000;
|
|
13
|
+
const CLIENT_NAME = "openclaw-neuralmemory";
|
|
14
|
+
const CLIENT_VERSION = "1.5.0";
|
|
15
|
+
const MAX_BUFFER_BYTES = 10 * 1024 * 1024; // 10 MB safety cap
|
|
16
|
+
const MAX_STDERR_LINES = 50;
|
|
17
|
+
/** Env vars forwarded to the MCP child process (least-privilege). */
|
|
18
|
+
export const ALLOWED_ENV_KEYS = new Set([
|
|
19
|
+
"PATH",
|
|
20
|
+
"PATHEXT",
|
|
21
|
+
"HOME",
|
|
22
|
+
"USERPROFILE",
|
|
23
|
+
"SYSTEMROOT",
|
|
24
|
+
"TEMP",
|
|
25
|
+
"TMP",
|
|
26
|
+
"LANG",
|
|
27
|
+
"LC_ALL",
|
|
28
|
+
"VIRTUAL_ENV",
|
|
29
|
+
"CONDA_PREFIX",
|
|
30
|
+
"PYTHONPATH",
|
|
31
|
+
"PYTHONHOME",
|
|
32
|
+
"NEURALMEMORY_DIR",
|
|
33
|
+
"NEURALMEMORY_BRAIN",
|
|
34
|
+
"NEURAL_MEMORY_DIR",
|
|
35
|
+
"NEURAL_MEMORY_JSON",
|
|
36
|
+
"NEURAL_MEMORY_DEBUG",
|
|
37
|
+
]);
|
|
38
|
+
// ── Client ─────────────────────────────────────────────────
|
|
39
|
+
export class NeuralMemoryMcpClient {
|
|
40
|
+
proc = null;
|
|
41
|
+
requestId = 0;
|
|
42
|
+
pending = new Map();
|
|
43
|
+
rawBuffer = Buffer.alloc(0);
|
|
44
|
+
pythonPath;
|
|
45
|
+
brain;
|
|
46
|
+
logger;
|
|
47
|
+
timeout;
|
|
48
|
+
initTimeout;
|
|
49
|
+
_connected = false;
|
|
50
|
+
constructor(options) {
|
|
51
|
+
this.pythonPath = options.pythonPath;
|
|
52
|
+
this.brain = options.brain;
|
|
53
|
+
this.logger = options.logger;
|
|
54
|
+
this.timeout = options.timeout ?? DEFAULT_TIMEOUT;
|
|
55
|
+
this.initTimeout = options.initTimeout ?? 90_000;
|
|
56
|
+
}
|
|
57
|
+
get connected() {
|
|
58
|
+
return this._connected;
|
|
59
|
+
}
|
|
60
|
+
async connect() {
|
|
61
|
+
const env = buildChildEnv(this.brain);
|
|
62
|
+
this.proc = spawn(this.pythonPath, ["-m", "neural_memory.mcp"], {
|
|
63
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
64
|
+
env,
|
|
65
|
+
});
|
|
66
|
+
this.proc.stdout.on("data", (chunk) => {
|
|
67
|
+
this.rawBuffer = Buffer.concat([this.rawBuffer, chunk]);
|
|
68
|
+
if (this.rawBuffer.length > MAX_BUFFER_BYTES) {
|
|
69
|
+
this.logger.error(`MCP buffer exceeded ${MAX_BUFFER_BYTES} bytes — killing process`);
|
|
70
|
+
this.proc?.kill("SIGKILL");
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
this.drainBuffer();
|
|
74
|
+
});
|
|
75
|
+
const stderrChunks = [];
|
|
76
|
+
this.proc.stderr.on("data", (chunk) => {
|
|
77
|
+
const msg = chunk.toString("utf-8").trim();
|
|
78
|
+
if (msg) {
|
|
79
|
+
if (stderrChunks.length < MAX_STDERR_LINES) {
|
|
80
|
+
stderrChunks.push(msg);
|
|
81
|
+
}
|
|
82
|
+
this.logger.warn(`[mcp stderr] ${msg}`);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
this.proc.on("exit", (code) => {
|
|
86
|
+
this._connected = false;
|
|
87
|
+
const hint = code === 1
|
|
88
|
+
? " — check that neural-memory is installed: pip install neural-memory"
|
|
89
|
+
: "";
|
|
90
|
+
this.rejectAll(new Error(`MCP process exited with code ${code}${hint}`));
|
|
91
|
+
this.logger.error(`MCP process exited (code: ${code})${hint}`);
|
|
92
|
+
});
|
|
93
|
+
this.proc.on("error", (err) => {
|
|
94
|
+
this._connected = false;
|
|
95
|
+
const hint = err.message.includes("ENOENT")
|
|
96
|
+
? ` — "${this.pythonPath}" not found. Check pythonPath in plugin config.`
|
|
97
|
+
: "";
|
|
98
|
+
this.rejectAll(new Error(`MCP process error: ${err.message}${hint}`));
|
|
99
|
+
this.logger.error(`MCP process error: ${err.message}${hint}`);
|
|
100
|
+
});
|
|
101
|
+
// MCP initialize handshake (uses longer timeout for cold starts)
|
|
102
|
+
try {
|
|
103
|
+
await this.send("initialize", {
|
|
104
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
105
|
+
capabilities: {},
|
|
106
|
+
clientInfo: { name: CLIENT_NAME, version: CLIENT_VERSION },
|
|
107
|
+
}, this.initTimeout);
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
const stderr = stderrChunks.join("\n");
|
|
111
|
+
const detail = stderr
|
|
112
|
+
? `\nPython stderr:\n${stderr}`
|
|
113
|
+
: "\nNo stderr output — the Python process may have hung.";
|
|
114
|
+
throw new Error(`MCP initialize failed: ${err.message}${detail}\n` +
|
|
115
|
+
`Verify: ${this.pythonPath} -m neural_memory.mcp`);
|
|
116
|
+
}
|
|
117
|
+
// Send initialized notification (no response expected)
|
|
118
|
+
this.notify("notifications/initialized", {});
|
|
119
|
+
this._connected = true;
|
|
120
|
+
this.logger.info(`MCP connected (brain: ${this.brain}, protocol: ${PROTOCOL_VERSION})`);
|
|
121
|
+
}
|
|
122
|
+
async callTool(name, args = {}) {
|
|
123
|
+
const result = (await this.send("tools/call", {
|
|
124
|
+
name,
|
|
125
|
+
arguments: args,
|
|
126
|
+
}));
|
|
127
|
+
if (result.isError) {
|
|
128
|
+
const text = result.content?.[0]?.text ?? "Unknown MCP error";
|
|
129
|
+
throw new Error(text);
|
|
130
|
+
}
|
|
131
|
+
return result.content?.[0]?.text ?? "";
|
|
132
|
+
}
|
|
133
|
+
async close() {
|
|
134
|
+
this._connected = false;
|
|
135
|
+
this.rejectAll(new Error("Client closing"));
|
|
136
|
+
const proc = this.proc;
|
|
137
|
+
this.proc = null;
|
|
138
|
+
this.rawBuffer = Buffer.alloc(0);
|
|
139
|
+
if (proc) {
|
|
140
|
+
proc.removeAllListeners();
|
|
141
|
+
proc.stdout?.removeAllListeners();
|
|
142
|
+
proc.stderr?.removeAllListeners();
|
|
143
|
+
const exited = new Promise((resolve) => {
|
|
144
|
+
proc.once("exit", () => resolve());
|
|
145
|
+
setTimeout(() => {
|
|
146
|
+
proc.kill("SIGKILL");
|
|
147
|
+
resolve();
|
|
148
|
+
}, 3_000);
|
|
149
|
+
});
|
|
150
|
+
proc.kill("SIGTERM");
|
|
151
|
+
await exited;
|
|
152
|
+
}
|
|
153
|
+
this.logger.info("MCP client closed");
|
|
154
|
+
}
|
|
155
|
+
// ── JSON-RPC protocol layer ──────────────────────────────
|
|
156
|
+
send(method, params, timeoutOverride) {
|
|
157
|
+
return new Promise((resolve, reject) => {
|
|
158
|
+
if (!this.proc?.stdin?.writable) {
|
|
159
|
+
reject(new Error("MCP process not available"));
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const id = ++this.requestId;
|
|
163
|
+
const ms = timeoutOverride ?? this.timeout;
|
|
164
|
+
const timer = setTimeout(() => {
|
|
165
|
+
this.pending.delete(id);
|
|
166
|
+
reject(new Error(`MCP timeout: ${method} (${ms}ms)`));
|
|
167
|
+
}, ms);
|
|
168
|
+
this.pending.set(id, { resolve, reject, timer });
|
|
169
|
+
this.writeMessage({ jsonrpc: "2.0", id, method, params });
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
notify(method, params) {
|
|
173
|
+
if (!this.proc?.stdin?.writable)
|
|
174
|
+
return;
|
|
175
|
+
this.writeMessage({ jsonrpc: "2.0", method, params });
|
|
176
|
+
}
|
|
177
|
+
writeMessage(message) {
|
|
178
|
+
if (!this.proc?.stdin?.writable)
|
|
179
|
+
return;
|
|
180
|
+
const json = JSON.stringify(message);
|
|
181
|
+
const frame = `${json}\n`;
|
|
182
|
+
this.proc.stdin.write(frame);
|
|
183
|
+
}
|
|
184
|
+
// ── Response parsing (newline-delimited JSON Lines) ────────
|
|
185
|
+
drainBuffer() {
|
|
186
|
+
while (true) {
|
|
187
|
+
const newlineIndex = this.rawBuffer.indexOf("\n");
|
|
188
|
+
if (newlineIndex === -1)
|
|
189
|
+
break;
|
|
190
|
+
const line = this.rawBuffer.subarray(0, newlineIndex).toString("utf-8");
|
|
191
|
+
this.rawBuffer = this.rawBuffer.subarray(newlineIndex + 1);
|
|
192
|
+
if (!line.trim())
|
|
193
|
+
continue;
|
|
194
|
+
try {
|
|
195
|
+
const message = JSON.parse(line);
|
|
196
|
+
this.handleMessage(message);
|
|
197
|
+
}
|
|
198
|
+
catch (err) {
|
|
199
|
+
this.logger.error(`Failed to parse MCP message: ${err.message}`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
handleMessage(message) {
|
|
204
|
+
// Notifications (no id) — ignore silently
|
|
205
|
+
if (message.id == null)
|
|
206
|
+
return;
|
|
207
|
+
const pending = this.pending.get(message.id);
|
|
208
|
+
if (!pending)
|
|
209
|
+
return;
|
|
210
|
+
this.pending.delete(message.id);
|
|
211
|
+
clearTimeout(pending.timer);
|
|
212
|
+
if (message.error) {
|
|
213
|
+
pending.reject(new Error(`MCP error ${message.error.code}: ${message.error.message}`));
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
pending.resolve(message.result);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
rejectAll(error) {
|
|
220
|
+
for (const [, pending] of this.pending) {
|
|
221
|
+
clearTimeout(pending.timer);
|
|
222
|
+
pending.reject(error);
|
|
223
|
+
}
|
|
224
|
+
this.pending.clear();
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
// ── Helpers ─────────────────────────────────────────────────
|
|
228
|
+
/** Build a minimal env for the child process (least-privilege). */
|
|
229
|
+
export function buildChildEnv(brain) {
|
|
230
|
+
const env = {};
|
|
231
|
+
for (const key of ALLOWED_ENV_KEYS) {
|
|
232
|
+
const value = process.env[key];
|
|
233
|
+
if (value !== undefined) {
|
|
234
|
+
env[key] = value;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (brain !== "default") {
|
|
238
|
+
env.NEURALMEMORY_BRAIN = brain;
|
|
239
|
+
}
|
|
240
|
+
return env;
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=mcp-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-client.js","sourceRoot":"","sources":["../src/mcp-client.ts"],"names":[],"mappings":"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"}
|
package/dist/tools.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NeuralMemory tool definitions for OpenClaw.
|
|
3
|
+
*
|
|
4
|
+
* Each tool proxies to the MCP server via JSON-RPC.
|
|
5
|
+
*
|
|
6
|
+
* Uses raw JSON Schema for parameters. Provider compatibility notes:
|
|
7
|
+
* - `additionalProperties: false` required by OpenAI strict mode
|
|
8
|
+
* - `number` instead of `integer` for Gemini compatibility
|
|
9
|
+
* - No `maxLength`/`maxItems`/`minimum`/`maximum` — some providers
|
|
10
|
+
* reject schemas with constraint keywords; our MCP server validates
|
|
11
|
+
*
|
|
12
|
+
* Registers 6 core tools:
|
|
13
|
+
* nmem_remember — Store a memory
|
|
14
|
+
* nmem_recall — Query/search memories
|
|
15
|
+
* nmem_context — Get recent context
|
|
16
|
+
* nmem_todo — Quick TODO shortcut
|
|
17
|
+
* nmem_stats — Brain statistics
|
|
18
|
+
* nmem_health — Brain health diagnostics
|
|
19
|
+
*/
|
|
20
|
+
import type { NeuralMemoryMcpClient } from "./mcp-client.js";
|
|
21
|
+
type JsonSchema = {
|
|
22
|
+
readonly type: "object";
|
|
23
|
+
readonly properties: Record<string, unknown>;
|
|
24
|
+
readonly required?: readonly string[];
|
|
25
|
+
readonly additionalProperties?: boolean;
|
|
26
|
+
};
|
|
27
|
+
export type ToolDefinition = {
|
|
28
|
+
readonly name: string;
|
|
29
|
+
readonly description: string;
|
|
30
|
+
readonly parameters: JsonSchema;
|
|
31
|
+
readonly execute: (id: string, args: Record<string, unknown>) => Promise<unknown>;
|
|
32
|
+
};
|
|
33
|
+
export declare function createTools(mcp: NeuralMemoryMcpClient): ToolDefinition[];
|
|
34
|
+
export {};
|