@pentatonic-ai/openclaw-memory-plugin 0.4.8 → 0.4.9
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/index.js +85 -96
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -237,110 +237,99 @@ export default {
|
|
|
237
237
|
id: "pentatonic-memory",
|
|
238
238
|
name: "Pentatonic Memory",
|
|
239
239
|
description: "Persistent, searchable memory with multi-signal retrieval and HyDE query expansion",
|
|
240
|
+
kind: "context-engine",
|
|
240
241
|
|
|
241
242
|
register(api) {
|
|
242
243
|
const config = api.config || {};
|
|
243
244
|
const hosted = !!(config.tes_endpoint && config.tes_api_key);
|
|
244
245
|
const baseUrl = config.memory_url || "http://localhost:3333";
|
|
246
|
+
const searchLimit = config.search_limit || 5;
|
|
247
|
+
const minScore = config.min_score || 0.3;
|
|
245
248
|
const log = (msg) => process.stderr.write(`[pentatonic-memory] ${msg}\n`);
|
|
246
249
|
|
|
247
|
-
//
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
log("Plugin registered (hosted)");
|
|
293
|
-
} else {
|
|
294
|
-
// Local mode tools — always point at baseUrl
|
|
295
|
-
log(`Local mode — ${baseUrl}`);
|
|
296
|
-
|
|
297
|
-
api.registerTool({
|
|
298
|
-
name: "memory_search",
|
|
299
|
-
description: "Search memories for relevant context. Use when you need to recall past conversations, decisions, or knowledge.",
|
|
300
|
-
parameters: {
|
|
301
|
-
type: "object",
|
|
302
|
-
properties: {
|
|
303
|
-
query: { type: "string", description: "What to search for" },
|
|
304
|
-
limit: { type: "number", description: "Max results (default 5)" },
|
|
305
|
-
},
|
|
306
|
-
required: ["query"],
|
|
307
|
-
},
|
|
308
|
-
async execute({ query, limit }) {
|
|
309
|
-
return formatResults(await localSearch(baseUrl, query, limit || 5, 0.3));
|
|
310
|
-
},
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
api.registerTool({
|
|
314
|
-
name: "memory_store",
|
|
315
|
-
description: "Explicitly store something important. Use for decisions, solutions, or facts worth remembering.",
|
|
316
|
-
parameters: {
|
|
317
|
-
type: "object",
|
|
318
|
-
properties: { content: { type: "string", description: "What to remember" } },
|
|
319
|
-
required: ["content"],
|
|
320
|
-
},
|
|
321
|
-
async execute({ content }) {
|
|
322
|
-
const result = await localStore(baseUrl, content, { source: "openclaw-tool" });
|
|
323
|
-
return result ? `Stored: ${result.id}` : "Failed to store memory.";
|
|
324
|
-
},
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
// Auto-detect: check if local memory server is running, register context engine if so
|
|
328
|
-
localHealth(baseUrl).then((ok) => {
|
|
329
|
-
if (ok) {
|
|
330
|
-
api.registerContextEngine("pentatonic-memory", () =>
|
|
331
|
-
createLocalContextEngine(baseUrl, {
|
|
332
|
-
searchLimit: config.search_limit || 5,
|
|
333
|
-
minScore: config.min_score || 0.3,
|
|
334
|
-
logger: log,
|
|
335
|
-
})
|
|
336
|
-
);
|
|
337
|
-
log("Memory server detected — context engine registered");
|
|
338
|
-
} else {
|
|
339
|
-
log(`Memory server not reachable at ${baseUrl} — tools available, no auto-ingest/assemble`);
|
|
250
|
+
// Unified search/store that routes to local or hosted
|
|
251
|
+
const search = hosted
|
|
252
|
+
? (query, limit, score) => hostedSearch(config, query, limit, score)
|
|
253
|
+
: (query, limit, score) => localSearch(baseUrl, query, limit, score);
|
|
254
|
+
|
|
255
|
+
const store = hosted
|
|
256
|
+
? (content, metadata) => hostedStore(config, content, metadata)
|
|
257
|
+
: (content, metadata) => localStore(baseUrl, content, metadata);
|
|
258
|
+
|
|
259
|
+
// --- Context engine: always registered, proxies to backend ---
|
|
260
|
+
// Methods return graceful empty results if backend is unavailable.
|
|
261
|
+
|
|
262
|
+
api.registerContextEngine("pentatonic-memory", () => ({
|
|
263
|
+
info: {
|
|
264
|
+
id: "pentatonic-memory",
|
|
265
|
+
name: `Pentatonic Memory (${hosted ? "Hosted" : "Local"})`,
|
|
266
|
+
ownsCompaction: false,
|
|
267
|
+
},
|
|
268
|
+
|
|
269
|
+
async ingest({ sessionId, message }) {
|
|
270
|
+
if (!message?.content) return { ingested: false };
|
|
271
|
+
const role = message.role || message.type;
|
|
272
|
+
if (role !== "user" && role !== "assistant") return { ingested: false };
|
|
273
|
+
try {
|
|
274
|
+
await store(message.content, { session_id: sessionId, role });
|
|
275
|
+
return { ingested: true };
|
|
276
|
+
} catch {
|
|
277
|
+
return { ingested: false };
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
|
|
281
|
+
async assemble({ sessionId, messages }) {
|
|
282
|
+
const lastUserMsg = [...messages].reverse().find((m) => m.role === "user" || m.type === "user");
|
|
283
|
+
if (!lastUserMsg?.content) return { messages, estimatedTokens: 0 };
|
|
284
|
+
try {
|
|
285
|
+
const results = await search(lastUserMsg.content, searchLimit, minScore);
|
|
286
|
+
if (!results.length) return { messages, estimatedTokens: 0 };
|
|
287
|
+
const memoryText = results
|
|
288
|
+
.map((m) => `- [${Math.round((m.similarity || 0) * 100)}%] ${m.content}`)
|
|
289
|
+
.join("\n");
|
|
290
|
+
const addition = `[Memory] Relevant context from past conversations:\n${memoryText}`;
|
|
291
|
+
return { messages, estimatedTokens: Math.ceil(addition.length / 4), systemPromptAddition: addition };
|
|
292
|
+
} catch {
|
|
293
|
+
return { messages, estimatedTokens: 0 };
|
|
340
294
|
}
|
|
341
|
-
}
|
|
295
|
+
},
|
|
296
|
+
|
|
297
|
+
async compact() { return { ok: true, compacted: false }; },
|
|
298
|
+
async afterTurn() {},
|
|
299
|
+
}));
|
|
300
|
+
|
|
301
|
+
// --- Tools: agent-driven search and store ---
|
|
302
|
+
|
|
303
|
+
api.registerTool({
|
|
304
|
+
name: "memory_search",
|
|
305
|
+
description: "Search memories for relevant context. Use when you need to recall past conversations, decisions, or knowledge.",
|
|
306
|
+
parameters: {
|
|
307
|
+
type: "object",
|
|
308
|
+
properties: {
|
|
309
|
+
query: { type: "string", description: "What to search for" },
|
|
310
|
+
limit: { type: "number", description: "Max results (default 5)" },
|
|
311
|
+
},
|
|
312
|
+
required: ["query"],
|
|
313
|
+
},
|
|
314
|
+
async execute({ query, limit }) {
|
|
315
|
+
return formatResults(await search(query, limit || 5, 0.3));
|
|
316
|
+
},
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
api.registerTool({
|
|
320
|
+
name: "memory_store",
|
|
321
|
+
description: "Explicitly store something important. Use for decisions, solutions, or facts worth remembering.",
|
|
322
|
+
parameters: {
|
|
323
|
+
type: "object",
|
|
324
|
+
properties: { content: { type: "string", description: "What to remember" } },
|
|
325
|
+
required: ["content"],
|
|
326
|
+
},
|
|
327
|
+
async execute({ content }) {
|
|
328
|
+
const result = await store(content, { source: "openclaw-tool" });
|
|
329
|
+
return result ? "Memory stored." : "Failed to store memory.";
|
|
330
|
+
},
|
|
331
|
+
});
|
|
342
332
|
|
|
343
|
-
|
|
344
|
-
}
|
|
333
|
+
log(`Plugin registered (${hosted ? "hosted" : "local"} — ${hosted ? config.tes_endpoint : baseUrl})`);
|
|
345
334
|
},
|
|
346
335
|
};
|
package/openclaw.plugin.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "Pentatonic Memory",
|
|
4
4
|
"description": "Persistent, searchable memory with multi-signal retrieval and HyDE query expansion. Local (Docker + Ollama) or hosted (Pentatonic TES).",
|
|
5
5
|
"version": "0.4.4",
|
|
6
|
-
"kind": "
|
|
6
|
+
"kind": "context-engine",
|
|
7
7
|
"configSchema": {
|
|
8
8
|
"type": "object",
|
|
9
9
|
"additionalProperties": false,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pentatonic-ai/openclaw-memory-plugin",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.9",
|
|
4
4
|
"description": "Pentatonic Memory plugin for OpenClaw — persistent, searchable memory with multi-signal retrieval and HyDE query expansion",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|