agent-working-memory 0.7.17 → 0.8.6
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 +156 -15
- package/dist/adapters/common.d.ts.map +1 -1
- package/dist/adapters/common.js +289 -202
- package/dist/adapters/common.js.map +1 -1
- package/dist/adapters/http.js +22 -22
- package/dist/api/routes.d.ts +1 -1
- package/dist/api/routes.d.ts.map +1 -1
- package/dist/api/routes.js +258 -79
- package/dist/api/routes.js.map +1 -1
- package/dist/cli/migrate.d.ts +42 -0
- package/dist/cli/migrate.d.ts.map +1 -0
- package/dist/cli/migrate.js +268 -0
- package/dist/cli/migrate.js.map +1 -0
- package/dist/cli.js +147 -103
- package/dist/cli.js.map +1 -1
- package/dist/coordination/circuit-breaker.d.ts +24 -0
- package/dist/coordination/circuit-breaker.d.ts.map +1 -0
- package/dist/coordination/circuit-breaker.js +70 -0
- package/dist/coordination/circuit-breaker.js.map +1 -0
- package/dist/coordination/failure-modes.d.ts +21 -0
- package/dist/coordination/failure-modes.d.ts.map +1 -0
- package/dist/coordination/failure-modes.js +49 -0
- package/dist/coordination/failure-modes.js.map +1 -0
- package/dist/coordination/peer-decisions.js +7 -7
- package/dist/coordination/routes.d.ts.map +1 -1
- package/dist/coordination/routes.js +44 -1
- package/dist/coordination/routes.js.map +1 -1
- package/dist/coordination/schema.d.ts.map +1 -1
- package/dist/coordination/schema.js +18 -0
- package/dist/coordination/schema.js.map +1 -1
- package/dist/coordination/schemas.d.ts +9 -9
- package/dist/coordination/stale.d.ts +9 -1
- package/dist/coordination/stale.d.ts.map +1 -1
- package/dist/coordination/stale.js +53 -9
- package/dist/coordination/stale.js.map +1 -1
- package/dist/core/embeddings.d.ts +16 -10
- package/dist/core/embeddings.d.ts.map +1 -1
- package/dist/core/embeddings.js +54 -38
- package/dist/core/embeddings.js.map +1 -1
- package/dist/core/ml-worker-entry.d.ts +17 -0
- package/dist/core/ml-worker-entry.d.ts.map +1 -0
- package/dist/core/ml-worker-entry.js +193 -0
- package/dist/core/ml-worker-entry.js.map +1 -0
- package/dist/core/ml-worker.d.ts +59 -0
- package/dist/core/ml-worker.d.ts.map +1 -0
- package/dist/core/ml-worker.js +253 -0
- package/dist/core/ml-worker.js.map +1 -0
- package/dist/core/query-expander.d.ts +13 -15
- package/dist/core/query-expander.d.ts.map +1 -1
- package/dist/core/query-expander.js +48 -54
- package/dist/core/query-expander.js.map +1 -1
- package/dist/core/reranker.d.ts +9 -19
- package/dist/core/reranker.d.ts.map +1 -1
- package/dist/core/reranker.js +33 -35
- package/dist/core/reranker.js.map +1 -1
- package/dist/core/salience.d.ts +32 -5
- package/dist/core/salience.d.ts.map +1 -1
- package/dist/core/salience.js +201 -28
- package/dist/core/salience.js.map +1 -1
- package/dist/core/write-pipeline.d.ts +10 -2
- package/dist/core/write-pipeline.d.ts.map +1 -1
- package/dist/core/write-pipeline.js +218 -49
- package/dist/core/write-pipeline.js.map +1 -1
- package/dist/engine/activation.d.ts +2 -2
- package/dist/engine/activation.d.ts.map +1 -1
- package/dist/engine/activation.js +238 -115
- package/dist/engine/activation.js.map +1 -1
- package/dist/engine/confidence.d.ts +62 -0
- package/dist/engine/confidence.d.ts.map +1 -0
- package/dist/engine/confidence.js +100 -0
- package/dist/engine/confidence.js.map +1 -0
- package/dist/engine/connections.d.ts +47 -8
- package/dist/engine/connections.d.ts.map +1 -1
- package/dist/engine/connections.js +83 -22
- package/dist/engine/connections.js.map +1 -1
- package/dist/engine/consolidation-scheduler.d.ts +46 -10
- package/dist/engine/consolidation-scheduler.d.ts.map +1 -1
- package/dist/engine/consolidation-scheduler.js +170 -50
- package/dist/engine/consolidation-scheduler.js.map +1 -1
- package/dist/engine/consolidation.d.ts +16 -2
- package/dist/engine/consolidation.d.ts.map +1 -1
- package/dist/engine/consolidation.js +143 -44
- package/dist/engine/consolidation.js.map +1 -1
- package/dist/engine/eval.d.ts +2 -2
- package/dist/engine/eval.d.ts.map +1 -1
- package/dist/engine/eval.js +9 -9
- package/dist/engine/eval.js.map +1 -1
- package/dist/engine/eviction.d.ts +4 -4
- package/dist/engine/eviction.d.ts.map +1 -1
- package/dist/engine/eviction.js +15 -15
- package/dist/engine/eviction.js.map +1 -1
- package/dist/engine/retraction.d.ts +93 -5
- package/dist/engine/retraction.d.ts.map +1 -1
- package/dist/engine/retraction.js +238 -19
- package/dist/engine/retraction.js.map +1 -1
- package/dist/engine/staging.d.ts +1 -1
- package/dist/engine/staging.d.ts.map +1 -1
- package/dist/engine/staging.js +3 -3
- package/dist/engine/staging.js.map +1 -1
- package/dist/hooks/sidecar.d.ts +1 -1
- package/dist/hooks/sidecar.d.ts.map +1 -1
- package/dist/hooks/sidecar.js +4 -4
- package/dist/hooks/sidecar.js.map +1 -1
- package/dist/index.js +48 -31
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +167 -141
- package/dist/mcp.js.map +1 -1
- package/dist/storage/factory.d.ts +55 -0
- package/dist/storage/factory.d.ts.map +1 -0
- package/dist/storage/factory.js +135 -0
- package/dist/storage/factory.js.map +1 -0
- package/dist/storage/pglite-schema.d.ts +20 -0
- package/dist/storage/pglite-schema.d.ts.map +1 -0
- package/dist/storage/pglite-schema.js +165 -0
- package/dist/storage/pglite-schema.js.map +1 -0
- package/dist/storage/pglite.d.ts +187 -0
- package/dist/storage/pglite.d.ts.map +1 -0
- package/dist/storage/pglite.js +1114 -0
- package/dist/storage/pglite.js.map +1 -0
- package/dist/storage/sqlite.d.ts +117 -0
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +357 -8
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/storage/store.d.ts +63 -0
- package/dist/storage/store.d.ts.map +1 -0
- package/dist/storage/store.js +27 -0
- package/dist/storage/store.js.map +1 -0
- package/dist/types/engram.d.ts +92 -2
- package/dist/types/engram.d.ts.map +1 -1
- package/dist/types/engram.js.map +1 -1
- package/package.json +3 -1
- package/src/adapters/claude-code.ts +218 -218
- package/src/adapters/codex.ts +252 -252
- package/src/adapters/common.ts +498 -411
- package/src/adapters/cursor.ts +135 -135
- package/src/adapters/http.ts +93 -93
- package/src/adapters/index.ts +31 -31
- package/src/adapters/types.ts +75 -75
- package/src/api/index.ts +3 -3
- package/src/api/routes.ts +970 -714
- package/src/cli/migrate.ts +307 -0
- package/src/cli.ts +755 -719
- package/src/coordination/circuit-breaker.ts +83 -0
- package/src/coordination/events.ts +90 -90
- package/src/coordination/failure-modes.ts +50 -0
- package/src/coordination/peer-decisions.ts +105 -105
- package/src/coordination/plugin-loader.ts +60 -60
- package/src/coordination/plugin.ts +44 -44
- package/src/coordination/routes.ts +56 -1
- package/src/coordination/schema.ts +13 -0
- package/src/coordination/stale.ts +80 -11
- package/src/coordination/types.ts +311 -311
- package/src/coordination/write-mutex.ts +69 -69
- package/src/core/auto-tagger.ts +168 -168
- package/src/core/decay.ts +63 -63
- package/src/core/embeddings.ts +110 -93
- package/src/core/index.ts +5 -5
- package/src/core/logger.ts +36 -36
- package/src/core/ml-worker-entry.ts +194 -0
- package/src/core/ml-worker.ts +281 -0
- package/src/core/query-expander.ts +122 -128
- package/src/core/reranker.ts +119 -125
- package/src/core/salience.ts +200 -33
- package/src/core/write-pipeline.ts +521 -343
- package/src/engine/activation.ts +235 -109
- package/src/engine/confidence.ts +120 -0
- package/src/engine/connections.ts +162 -103
- package/src/engine/consolidation-scheduler.ts +242 -125
- package/src/engine/consolidation.ts +138 -45
- package/src/engine/eval.ts +102 -102
- package/src/engine/eviction.ts +101 -101
- package/src/engine/index.ts +8 -8
- package/src/engine/retraction.ts +366 -116
- package/src/engine/staging.ts +74 -74
- package/src/hooks/sidecar.ts +5 -5
- package/src/index.ts +226 -212
- package/src/mcp.ts +1145 -1121
- package/src/storage/factory.ts +147 -0
- package/src/storage/index.ts +3 -3
- package/src/storage/pglite-schema.ts +166 -0
- package/src/storage/pglite.ts +1363 -0
- package/src/storage/sqlite.ts +402 -7
- package/src/storage/store.ts +80 -0
- package/src/types/agent.ts +67 -67
- package/src/types/checkpoint.ts +46 -46
- package/src/types/engram.ts +101 -3
- package/src/types/eval.ts +100 -100
- package/src/types/index.ts +6 -6
package/dist/mcp.js
CHANGED
|
@@ -50,7 +50,7 @@ catch { /* No .env file */ }
|
|
|
50
50
|
console.log = console.error;
|
|
51
51
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
52
52
|
import { z } from 'zod';
|
|
53
|
-
import {
|
|
53
|
+
import { openStore, getConfiguredBackend } from './storage/factory.js';
|
|
54
54
|
import { ActivationEngine } from './engine/activation.js';
|
|
55
55
|
import { ConnectionEngine } from './engine/connections.js';
|
|
56
56
|
import { StagingBuffer } from './engine/staging.js';
|
|
@@ -72,7 +72,7 @@ import { queryPeerDecisions, formatPeerDecisions } from './coordination/peer-dec
|
|
|
72
72
|
const INCOGNITO = process.env.AWM_INCOGNITO === '1' || process.env.AWM_INCOGNITO === 'true';
|
|
73
73
|
if (INCOGNITO) {
|
|
74
74
|
console.error('AWM: incognito mode — all memory tools disabled, nothing will be recorded');
|
|
75
|
-
const server = new McpServer({ name: 'agent-working-memory', version: '0.
|
|
75
|
+
const server = new McpServer({ name: 'agent-working-memory', version: '0.8.6' });
|
|
76
76
|
const transport = new StdioServerTransport();
|
|
77
77
|
server.connect(transport).catch(err => {
|
|
78
78
|
console.error('MCP server failed:', err);
|
|
@@ -82,20 +82,25 @@ if (INCOGNITO) {
|
|
|
82
82
|
}
|
|
83
83
|
else {
|
|
84
84
|
// --- Setup ---
|
|
85
|
-
const
|
|
85
|
+
const BACKEND = getConfiguredBackend();
|
|
86
|
+
const DB_PATH = process.env.AWM_DB_PATH ?? (BACKEND === 'pglite' ? 'memory-pglite' : 'memory.db');
|
|
86
87
|
const AGENT_ID = process.env.AWM_AGENT_ID ?? process.env.WORKER_NAME ?? 'claude-code';
|
|
87
88
|
const HOOK_PORT = parseInt(process.env.AWM_HOOK_PORT ?? '8401', 10);
|
|
88
89
|
const HOOK_SECRET = process.env.AWM_HOOK_SECRET ?? null;
|
|
89
90
|
initLogger(DB_PATH);
|
|
90
|
-
log(AGENT_ID, 'startup', `MCP server starting (db: ${DB_PATH}, hooks: ${HOOK_PORT})`);
|
|
91
|
-
|
|
91
|
+
log(AGENT_ID, 'startup', `MCP server starting (backend: ${BACKEND}, db: ${DB_PATH}, hooks: ${HOOK_PORT})`);
|
|
92
|
+
// AWM 0.8.x: openStore() returns either SQLite (sync) or PGlite (async) store.
|
|
93
|
+
// Engines accept either via IEngramStore (MaybePromise<T> contract).
|
|
94
|
+
const { store: storeAny } = await openStore();
|
|
95
|
+
// Engines accept the async contract; SQLite-only call sites must guard on BACKEND.
|
|
96
|
+
const store = storeAny;
|
|
92
97
|
const activationEngine = new ActivationEngine(store);
|
|
93
98
|
const connectionEngine = new ConnectionEngine(store, activationEngine);
|
|
94
99
|
const stagingBuffer = new StagingBuffer(store, activationEngine);
|
|
95
100
|
const evictionEngine = new EvictionEngine(store);
|
|
96
101
|
const retractionEngine = new RetractionEngine(store);
|
|
97
102
|
const evalEngine = new EvalEngine(store);
|
|
98
|
-
const consolidationEngine = new ConsolidationEngine(store);
|
|
103
|
+
const consolidationEngine = new ConsolidationEngine(store, connectionEngine);
|
|
99
104
|
const consolidationScheduler = new ConsolidationScheduler(store, consolidationEngine);
|
|
100
105
|
stagingBuffer.start(DEFAULT_AGENT_CONFIG.stagingTtlMs);
|
|
101
106
|
consolidationScheduler.start();
|
|
@@ -103,7 +108,7 @@ else {
|
|
|
103
108
|
let coordDb = null;
|
|
104
109
|
const server = new McpServer({
|
|
105
110
|
name: 'agent-working-memory',
|
|
106
|
-
version: '0.
|
|
111
|
+
version: '0.8.6',
|
|
107
112
|
});
|
|
108
113
|
server.registerResource('awm-overview', 'awm://server/overview', {
|
|
109
114
|
title: 'AWM Overview',
|
|
@@ -163,15 +168,15 @@ else {
|
|
|
163
168
|
return 'unclassified';
|
|
164
169
|
}
|
|
165
170
|
// --- Tools ---
|
|
166
|
-
server.tool('memory_write', `Store a memory. The salience filter decides whether it's worth keeping (active), needs more evidence (staging), or should be discarded.
|
|
167
|
-
|
|
168
|
-
CALL THIS PROACTIVELY — do not wait to be asked. Write memories when you:
|
|
169
|
-
- Discover something about the codebase, bugs, or architecture
|
|
170
|
-
- Make a decision and want to remember why
|
|
171
|
-
- Encounter and resolve an error
|
|
172
|
-
- Learn a user preference or project pattern
|
|
173
|
-
- Complete a significant piece of work
|
|
174
|
-
|
|
171
|
+
server.tool('memory_write', `Store a memory. The salience filter decides whether it's worth keeping (active), needs more evidence (staging), or should be discarded.
|
|
172
|
+
|
|
173
|
+
CALL THIS PROACTIVELY — do not wait to be asked. Write memories when you:
|
|
174
|
+
- Discover something about the codebase, bugs, or architecture
|
|
175
|
+
- Make a decision and want to remember why
|
|
176
|
+
- Encounter and resolve an error
|
|
177
|
+
- Learn a user preference or project pattern
|
|
178
|
+
- Complete a significant piece of work
|
|
179
|
+
|
|
175
180
|
The concept should be a short label (3-8 words). The content should be the full detail.`, {
|
|
176
181
|
concept: z.string().describe('Short label for this memory (3-8 words)'),
|
|
177
182
|
content: z.string().describe('Full detail of what was learned'),
|
|
@@ -223,7 +228,7 @@ The concept should be a short label (3-8 words). The content should be the full
|
|
|
223
228
|
if (params.intent)
|
|
224
229
|
metaTags.push(`intent=${params.intent}`);
|
|
225
230
|
const memoryType = params.memory_type ?? classifyMemoryType(params.content);
|
|
226
|
-
const result = performWrite({ store, connectionEngine }, {
|
|
231
|
+
const result = await performWrite({ store, connectionEngine }, {
|
|
227
232
|
agentId: AGENT_ID,
|
|
228
233
|
concept: params.concept,
|
|
229
234
|
content: params.content,
|
|
@@ -239,7 +244,7 @@ The concept should be a short label (3-8 words). The content should be the full
|
|
|
239
244
|
});
|
|
240
245
|
// Auto-checkpoint — covers create/reinforce/supersede uniformly
|
|
241
246
|
try {
|
|
242
|
-
store.updateAutoCheckpointWrite(AGENT_ID, result.engram.id);
|
|
247
|
+
await store.updateAutoCheckpointWrite(AGENT_ID, result.engram.id);
|
|
243
248
|
}
|
|
244
249
|
catch { /* non-fatal */ }
|
|
245
250
|
if (result.action === 'reinforce') {
|
|
@@ -275,15 +280,15 @@ The concept should be a short label (3-8 words). The content should be the full
|
|
|
275
280
|
}],
|
|
276
281
|
};
|
|
277
282
|
});
|
|
278
|
-
server.tool('memory_recall', `Recall memories relevant to a query. Uses cognitive activation — not keyword search.
|
|
279
|
-
|
|
280
|
-
ALWAYS call this when:
|
|
281
|
-
- Starting work on a project or topic (recall what you know)
|
|
282
|
-
- Debugging (recall similar errors and solutions)
|
|
283
|
-
- Making decisions (recall past decisions and outcomes)
|
|
284
|
-
- The user mentions a topic you might have stored memories about
|
|
285
|
-
|
|
286
|
-
Accepts either "query" or "context" parameter — both work identically.
|
|
283
|
+
server.tool('memory_recall', `Recall memories relevant to a query. Uses cognitive activation — not keyword search.
|
|
284
|
+
|
|
285
|
+
ALWAYS call this when:
|
|
286
|
+
- Starting work on a project or topic (recall what you know)
|
|
287
|
+
- Debugging (recall similar errors and solutions)
|
|
288
|
+
- Making decisions (recall past decisions and outcomes)
|
|
289
|
+
- The user mentions a topic you might have stored memories about
|
|
290
|
+
|
|
291
|
+
Accepts either "query" or "context" parameter — both work identically.
|
|
287
292
|
Returns the most relevant memories ranked by text relevance, temporal recency, and associative strength.`, {
|
|
288
293
|
query: z.string().optional().describe('What to search for — describe the situation, question, or topic'),
|
|
289
294
|
context: z.string().optional().describe('Alias for query (either works)'),
|
|
@@ -294,6 +299,8 @@ Returns the most relevant memories ranked by text relevance, temporal recency, a
|
|
|
294
299
|
use_expansion: z.boolean().optional().default(true).describe('Expand query with synonyms for better recall (default true)'),
|
|
295
300
|
memory_type: z.enum(['episodic', 'semantic', 'procedural']).optional().describe('Filter by memory type (omit to search all types)'),
|
|
296
301
|
workspace: z.string().optional().describe('Search across all agents in this workspace (hive mode). Omit for agent-scoped recall only.'),
|
|
302
|
+
require_confidence: z.number().optional().describe('Opt-in: abstain (return []) when recall confidence is below this threshold. Typical values: 0.10 (strict), 0.25 (balanced), 0.40 (aggressive). Confidence is the shape of the result-score distribution; low confidence indicates a noisy or best-of-bad-bunch recall.'),
|
|
303
|
+
granularity: z.enum(['full', 'compact', 'auto']).optional().describe('Output granularity (Paper 3: cognitive teaming). "full" (default): no change. "compact": every result carries a short summary field. "auto": confidence-adaptive — top result gets a longer summary when there is a clear winner, otherwise everything is compact for scanning.'),
|
|
297
304
|
}, async (params) => {
|
|
298
305
|
const queryText = params.query ?? params.context;
|
|
299
306
|
if (!queryText) {
|
|
@@ -316,11 +323,13 @@ Returns the most relevant memories ranked by text relevance, temporal recency, a
|
|
|
316
323
|
useExpansion: params.use_expansion,
|
|
317
324
|
memoryType: params.memory_type,
|
|
318
325
|
workspace,
|
|
326
|
+
requireConfidence: params.require_confidence,
|
|
327
|
+
granularity: params.granularity,
|
|
319
328
|
});
|
|
320
329
|
// Auto-checkpoint: track recall
|
|
321
330
|
try {
|
|
322
331
|
const ids = results.map(r => r.engram.id);
|
|
323
|
-
store.updateAutoCheckpointRecall(AGENT_ID, queryText, ids);
|
|
332
|
+
await store.updateAutoCheckpointRecall(AGENT_ID, queryText, ids);
|
|
324
333
|
}
|
|
325
334
|
catch { /* non-fatal */ }
|
|
326
335
|
log(AGENT_ID, 'recall', `"${queryText.slice(0, 80)}" → ${results.length} results`);
|
|
@@ -337,7 +346,11 @@ Returns the most relevant memories ranked by text relevance, temporal recency, a
|
|
|
337
346
|
};
|
|
338
347
|
}
|
|
339
348
|
const lines = results.map((r, i) => {
|
|
340
|
-
|
|
349
|
+
// Confidence-adaptive output (Paper 3: cognitive teaming). When the caller
|
|
350
|
+
// requested 'compact' or 'auto' granularity, surface the engine-computed
|
|
351
|
+
// summary instead of the full content — same engram, less to read.
|
|
352
|
+
const body = r.summary ?? r.engram.content;
|
|
353
|
+
return `${i + 1}. **${r.engram.concept}** (${r.score.toFixed(3)}): ${body}`;
|
|
341
354
|
});
|
|
342
355
|
return {
|
|
343
356
|
content: [{
|
|
@@ -346,23 +359,23 @@ Returns the most relevant memories ranked by text relevance, temporal recency, a
|
|
|
346
359
|
}],
|
|
347
360
|
};
|
|
348
361
|
});
|
|
349
|
-
server.tool('memory_feedback', `Report whether a recalled memory was actually useful. This updates the memory's confidence score — useful memories become stronger, useless ones weaken.
|
|
350
|
-
|
|
362
|
+
server.tool('memory_feedback', `Report whether a recalled memory was actually useful. This updates the memory's confidence score — useful memories become stronger, useless ones weaken.
|
|
363
|
+
|
|
351
364
|
Always call this after using a recalled memory so the system learns what's valuable.`, {
|
|
352
365
|
engram_id: z.string().describe('ID of the memory (from memory_recall results)'),
|
|
353
366
|
useful: z.boolean().describe('Was this memory actually helpful?'),
|
|
354
367
|
context: z.string().optional().describe('Brief note on why it was/wasn\'t useful'),
|
|
355
368
|
}, async (params) => {
|
|
356
|
-
store.logRetrievalFeedback(null, params.engram_id, params.useful, params.context ?? '');
|
|
357
|
-
const engram = store.getEngram(params.engram_id);
|
|
369
|
+
await store.logRetrievalFeedback(null, params.engram_id, params.useful, params.context ?? '');
|
|
370
|
+
const engram = await store.getEngram(params.engram_id);
|
|
358
371
|
if (engram) {
|
|
359
372
|
const delta = params.useful
|
|
360
373
|
? DEFAULT_AGENT_CONFIG.feedbackPositiveBoost
|
|
361
374
|
: -DEFAULT_AGENT_CONFIG.feedbackNegativePenalty;
|
|
362
|
-
store.updateConfidence(engram.id, engram.confidence + delta);
|
|
375
|
+
await store.updateConfidence(engram.id, engram.confidence + delta);
|
|
363
376
|
}
|
|
364
377
|
// Validation-gated Hebbian: resolve pending co-activation pairs for this engram
|
|
365
|
-
const hebbianUpdated = activationEngine.resolveHebbianFeedback(params.engram_id, params.useful);
|
|
378
|
+
const hebbianUpdated = await activationEngine.resolveHebbianFeedback(params.engram_id, params.useful);
|
|
366
379
|
return {
|
|
367
380
|
content: [{
|
|
368
381
|
type: 'text',
|
|
@@ -370,14 +383,14 @@ Always call this after using a recalled memory so the system learns what's valua
|
|
|
370
383
|
}],
|
|
371
384
|
};
|
|
372
385
|
});
|
|
373
|
-
server.tool('memory_retract', `Retract a memory that turned out to be wrong. Creates a correction and reduces confidence of related memories.
|
|
374
|
-
|
|
386
|
+
server.tool('memory_retract', `Retract a memory that turned out to be wrong. Creates a correction and reduces confidence of related memories.
|
|
387
|
+
|
|
375
388
|
Use this when you discover a memory contains incorrect information.`, {
|
|
376
389
|
engram_id: z.string().describe('ID of the wrong memory'),
|
|
377
390
|
reason: z.string().describe('Why is this memory wrong?'),
|
|
378
391
|
correction: z.string().optional().describe('What is the correct information? (creates a new memory)'),
|
|
379
392
|
}, async (params) => {
|
|
380
|
-
const result = retractionEngine.retract({
|
|
393
|
+
const result = await retractionEngine.retract({
|
|
381
394
|
agentId: AGENT_ID,
|
|
382
395
|
targetEngramId: params.engram_id,
|
|
383
396
|
reason: params.reason,
|
|
@@ -395,31 +408,31 @@ Use this when you discover a memory contains incorrect information.`, {
|
|
|
395
408
|
}],
|
|
396
409
|
};
|
|
397
410
|
});
|
|
398
|
-
server.tool('memory_supersede', `Replace an outdated memory with a newer one. Unlike retraction (which marks memories as wrong), supersession marks the old memory as outdated but historically correct.
|
|
399
|
-
|
|
400
|
-
Use this when:
|
|
401
|
-
- A status or count has changed (e.g., "5 reviews done" → "7 reviews done")
|
|
402
|
-
- Architecture or infrastructure evolved (e.g., "two-repo model" → "three-repo model")
|
|
403
|
-
- A schedule or plan was updated
|
|
404
|
-
|
|
411
|
+
server.tool('memory_supersede', `Replace an outdated memory with a newer one. Unlike retraction (which marks memories as wrong), supersession marks the old memory as outdated but historically correct.
|
|
412
|
+
|
|
413
|
+
Use this when:
|
|
414
|
+
- A status or count has changed (e.g., "5 reviews done" → "7 reviews done")
|
|
415
|
+
- Architecture or infrastructure evolved (e.g., "two-repo model" → "three-repo model")
|
|
416
|
+
- A schedule or plan was updated
|
|
417
|
+
|
|
405
418
|
The old memory stays in the database (searchable for history) but is heavily down-ranked in recall so the current version dominates.`, {
|
|
406
419
|
old_engram_id: z.string().describe('ID of the outdated memory'),
|
|
407
420
|
new_engram_id: z.string().describe('ID of the replacement memory'),
|
|
408
421
|
reason: z.string().optional().describe('Why the old memory is outdated'),
|
|
409
422
|
}, async (params) => {
|
|
410
|
-
const oldEngram = store.getEngram(params.old_engram_id);
|
|
423
|
+
const oldEngram = await store.getEngram(params.old_engram_id);
|
|
411
424
|
if (!oldEngram) {
|
|
412
425
|
return { content: [{ type: 'text', text: `Old memory not found: ${params.old_engram_id}` }] };
|
|
413
426
|
}
|
|
414
|
-
const newEngram = store.getEngram(params.new_engram_id);
|
|
427
|
+
const newEngram = await store.getEngram(params.new_engram_id);
|
|
415
428
|
if (!newEngram) {
|
|
416
429
|
return { content: [{ type: 'text', text: `New memory not found: ${params.new_engram_id}` }] };
|
|
417
430
|
}
|
|
418
|
-
store.supersedeEngram(params.old_engram_id, params.new_engram_id);
|
|
431
|
+
await store.supersedeEngram(params.old_engram_id, params.new_engram_id);
|
|
419
432
|
// Create supersession association (new → old)
|
|
420
|
-
store.upsertAssociation(params.new_engram_id, params.old_engram_id, 0.8, 'causal', 0.9);
|
|
433
|
+
await store.upsertAssociation(params.new_engram_id, params.old_engram_id, 0.8, 'causal', 0.9);
|
|
421
434
|
// Reduce old memory's confidence (not to zero — it's historical, not wrong)
|
|
422
|
-
store.updateConfidence(params.old_engram_id, Math.max(0.2, oldEngram.confidence * 0.4));
|
|
435
|
+
await store.updateConfidence(params.old_engram_id, Math.max(0.2, oldEngram.confidence * 0.4));
|
|
423
436
|
log(AGENT_ID, 'supersede', `"${oldEngram.concept}" → "${newEngram.concept}"${params.reason ? ` (${params.reason})` : ''}`);
|
|
424
437
|
return {
|
|
425
438
|
content: [{
|
|
@@ -428,10 +441,10 @@ The old memory stays in the database (searchable for history) but is heavily dow
|
|
|
428
441
|
}],
|
|
429
442
|
};
|
|
430
443
|
});
|
|
431
|
-
server.tool('memory_stats', `Get memory health stats — how many memories, confidence levels, association count, and system performance.
|
|
444
|
+
server.tool('memory_stats', `Get memory health stats — how many memories, confidence levels, association count, and system performance.
|
|
432
445
|
Also shows the activity log path so the user can tail it to see what's happening.`, {}, async () => {
|
|
433
|
-
const metrics = evalEngine.computeMetrics(AGENT_ID);
|
|
434
|
-
const checkpoint = store.getCheckpoint(AGENT_ID);
|
|
446
|
+
const metrics = await evalEngine.computeMetrics(AGENT_ID);
|
|
447
|
+
const checkpoint = await store.getCheckpoint(AGENT_ID);
|
|
435
448
|
const lines = [
|
|
436
449
|
`Agent: ${AGENT_ID}`,
|
|
437
450
|
`Active memories: ${metrics.activeEngramCount}`,
|
|
@@ -459,13 +472,13 @@ Also shows the activity log path so the user can tail it to see what's happening
|
|
|
459
472
|
};
|
|
460
473
|
});
|
|
461
474
|
// --- Checkpointing Tools ---
|
|
462
|
-
server.tool('memory_checkpoint', `Save your current execution state so you can recover after context compaction.
|
|
463
|
-
|
|
464
|
-
ALWAYS call this before:
|
|
465
|
-
- Long operations (multi-file generation, large refactors, overnight work)
|
|
466
|
-
- Anything that might fill the context window
|
|
467
|
-
- Switching to a different task
|
|
468
|
-
|
|
475
|
+
server.tool('memory_checkpoint', `Save your current execution state so you can recover after context compaction.
|
|
476
|
+
|
|
477
|
+
ALWAYS call this before:
|
|
478
|
+
- Long operations (multi-file generation, large refactors, overnight work)
|
|
479
|
+
- Anything that might fill the context window
|
|
480
|
+
- Switching to a different task
|
|
481
|
+
|
|
469
482
|
Also call periodically during long sessions to avoid losing state. The state is saved per-agent and overwrites any previous checkpoint.`, {
|
|
470
483
|
current_task: z.string().describe('What you are currently working on'),
|
|
471
484
|
decisions: z.array(z.string()).optional().default([])
|
|
@@ -490,7 +503,7 @@ Also call periodically during long sessions to avoid losing state. The state is
|
|
|
490
503
|
notes: params.notes,
|
|
491
504
|
episodeId: params.episode_id ?? null,
|
|
492
505
|
};
|
|
493
|
-
store.saveCheckpoint(AGENT_ID, state);
|
|
506
|
+
await store.saveCheckpoint(AGENT_ID, state);
|
|
494
507
|
log(AGENT_ID, 'checkpoint', `"${params.current_task}" decisions=${params.decisions.length} files=${params.active_files.length}`);
|
|
495
508
|
return {
|
|
496
509
|
content: [{
|
|
@@ -499,16 +512,16 @@ Also call periodically during long sessions to avoid losing state. The state is
|
|
|
499
512
|
}],
|
|
500
513
|
};
|
|
501
514
|
});
|
|
502
|
-
server.tool('memory_restore', `Restore your previous execution state after context compaction or at session start.
|
|
503
|
-
|
|
504
|
-
Returns:
|
|
505
|
-
- Your saved execution state (task, decisions, next steps, files)
|
|
506
|
-
- Recently recalled memories for context
|
|
507
|
-
- Your last write for continuity
|
|
508
|
-
- How long you were idle
|
|
509
|
-
|
|
515
|
+
server.tool('memory_restore', `Restore your previous execution state after context compaction or at session start.
|
|
516
|
+
|
|
517
|
+
Returns:
|
|
518
|
+
- Your saved execution state (task, decisions, next steps, files)
|
|
519
|
+
- Recently recalled memories for context
|
|
520
|
+
- Your last write for continuity
|
|
521
|
+
- How long you were idle
|
|
522
|
+
|
|
510
523
|
Use this at the start of every session or after compaction to pick up where you left off.`, {}, async () => {
|
|
511
|
-
const checkpoint = store.getCheckpoint(AGENT_ID);
|
|
524
|
+
const checkpoint = await store.getCheckpoint(AGENT_ID);
|
|
512
525
|
const now = Date.now();
|
|
513
526
|
const idleMs = checkpoint
|
|
514
527
|
? now - checkpoint.auto.lastActivityAt.getTime()
|
|
@@ -516,7 +529,7 @@ Use this at the start of every session or after compaction to pick up where you
|
|
|
516
529
|
// Get last written engram
|
|
517
530
|
let lastWrite = null;
|
|
518
531
|
if (checkpoint?.auto.lastWriteId) {
|
|
519
|
-
const engram = store.getEngram(checkpoint.auto.lastWriteId);
|
|
532
|
+
const engram = await store.getEngram(checkpoint.auto.lastWriteId);
|
|
520
533
|
if (engram) {
|
|
521
534
|
lastWrite = { id: engram.id, concept: engram.concept, content: engram.content };
|
|
522
535
|
}
|
|
@@ -562,7 +575,7 @@ Use this at the start of every session or after compaction to pick up where you
|
|
|
562
575
|
fullConsolidationTriggered = true;
|
|
563
576
|
try {
|
|
564
577
|
const result = await consolidationEngine.consolidate(AGENT_ID);
|
|
565
|
-
store.markConsolidation(AGENT_ID, false);
|
|
578
|
+
await store.markConsolidation(AGENT_ID, false);
|
|
566
579
|
log(AGENT_ID, 'consolidation', `full sleep cycle on restore (no graceful exit, idle ${Math.round(idleMs / 60_000)}min, last consolidation ${Math.round(sinceLastConsolidation / 60_000)}min ago) — ${result.edgesStrengthened} strengthened, ${result.memoriesForgotten} forgotten`);
|
|
567
580
|
}
|
|
568
581
|
catch { /* consolidation failure is non-fatal */ }
|
|
@@ -614,9 +627,9 @@ Use this at the start of every session or after compaction to pick up where you
|
|
|
614
627
|
if (coordDb) {
|
|
615
628
|
try {
|
|
616
629
|
const myAgent = coordDb.prepare(`SELECT id FROM coord_agents WHERE name = ? AND status != 'dead' ORDER BY last_seen DESC LIMIT 1`).get(AGENT_ID);
|
|
617
|
-
const peerDecisions = coordDb.prepare(`SELECT d.summary, a.name AS author_name, d.created_at
|
|
618
|
-
FROM coord_decisions d JOIN coord_agents a ON d.author_id = a.id
|
|
619
|
-
WHERE d.author_id != ? AND d.created_at > datetime('now', '-30 minutes')
|
|
630
|
+
const peerDecisions = coordDb.prepare(`SELECT d.summary, a.name AS author_name, d.created_at
|
|
631
|
+
FROM coord_decisions d JOIN coord_agents a ON d.author_id = a.id
|
|
632
|
+
WHERE d.author_id != ? AND d.created_at > datetime('now', '-30 minutes')
|
|
620
633
|
ORDER BY d.created_at DESC LIMIT 10`).all(myAgent?.id ?? '');
|
|
621
634
|
if (peerDecisions.length > 0) {
|
|
622
635
|
parts.push(`\n**Peer decisions (last 30 min):**`);
|
|
@@ -635,13 +648,13 @@ Use this at the start of every session or after compaction to pick up where you
|
|
|
635
648
|
};
|
|
636
649
|
});
|
|
637
650
|
// --- Task Management Tools ---
|
|
638
|
-
server.tool('memory_task_add', `Create a task that you need to come back to. Tasks are memories with status and priority tracking.
|
|
639
|
-
|
|
640
|
-
Use this when:
|
|
641
|
-
- You identify work that needs doing but can't do it right now
|
|
642
|
-
- The user mentions something to do later
|
|
643
|
-
- You want to park a sub-task while focusing on something more urgent
|
|
644
|
-
|
|
651
|
+
server.tool('memory_task_add', `Create a task that you need to come back to. Tasks are memories with status and priority tracking.
|
|
652
|
+
|
|
653
|
+
Use this when:
|
|
654
|
+
- You identify work that needs doing but can't do it right now
|
|
655
|
+
- The user mentions something to do later
|
|
656
|
+
- You want to park a sub-task while focusing on something more urgent
|
|
657
|
+
|
|
645
658
|
Tasks automatically get high salience so they won't be discarded.`, {
|
|
646
659
|
concept: z.string().describe('Short task title (3-10 words)'),
|
|
647
660
|
content: z.string().describe('Full task description — what needs doing, context, acceptance criteria'),
|
|
@@ -650,7 +663,7 @@ Tasks automatically get high salience so they won't be discarded.`, {
|
|
|
650
663
|
.describe('Task priority: urgent (do now), high (do soon), medium (normal), low (backlog)'),
|
|
651
664
|
blocked_by: z.string().optional().describe('ID of a task that must finish first'),
|
|
652
665
|
}, async (params) => {
|
|
653
|
-
const engram = store.createEngram({
|
|
666
|
+
const engram = await store.createEngram({
|
|
654
667
|
agentId: AGENT_ID,
|
|
655
668
|
concept: params.concept,
|
|
656
669
|
content: params.content,
|
|
@@ -671,8 +684,8 @@ Tasks automatically get high salience so they won't be discarded.`, {
|
|
|
671
684
|
});
|
|
672
685
|
connectionEngine.enqueue(engram.id);
|
|
673
686
|
// Generate embedding asynchronously
|
|
674
|
-
embed(`${params.concept} ${params.content}`).then(vec => {
|
|
675
|
-
store.updateEmbedding(engram.id, vec);
|
|
687
|
+
embed(`${params.concept} ${params.content}`).then(async (vec) => {
|
|
688
|
+
await store.updateEmbedding(engram.id, vec);
|
|
676
689
|
}).catch(() => { });
|
|
677
690
|
return {
|
|
678
691
|
content: [{
|
|
@@ -681,11 +694,11 @@ Tasks automatically get high salience so they won't be discarded.`, {
|
|
|
681
694
|
}],
|
|
682
695
|
};
|
|
683
696
|
});
|
|
684
|
-
server.tool('memory_task_update', `Update a task's status or priority. Use this to:
|
|
685
|
-
- Start working on a task (open → in_progress)
|
|
686
|
-
- Mark a task done (→ done)
|
|
687
|
-
- Block a task on another (→ blocked)
|
|
688
|
-
- Reprioritize (change priority)
|
|
697
|
+
server.tool('memory_task_update', `Update a task's status or priority. Use this to:
|
|
698
|
+
- Start working on a task (open → in_progress)
|
|
699
|
+
- Mark a task done (→ done)
|
|
700
|
+
- Block a task on another (→ blocked)
|
|
701
|
+
- Reprioritize (change priority)
|
|
689
702
|
- Unblock a task (clear blocked_by)`, {
|
|
690
703
|
task_id: z.string().describe('ID of the task to update'),
|
|
691
704
|
status: z.enum(['open', 'in_progress', 'blocked', 'done']).optional()
|
|
@@ -694,20 +707,20 @@ Tasks automatically get high salience so they won't be discarded.`, {
|
|
|
694
707
|
.describe('New priority'),
|
|
695
708
|
blocked_by: z.string().optional().describe('ID of blocking task (set to empty string to unblock)'),
|
|
696
709
|
}, async (params) => {
|
|
697
|
-
const engram = store.getEngram(params.task_id);
|
|
710
|
+
const engram = await store.getEngram(params.task_id);
|
|
698
711
|
if (!engram || !engram.taskStatus) {
|
|
699
712
|
return { content: [{ type: 'text', text: `Task not found: ${params.task_id}` }] };
|
|
700
713
|
}
|
|
701
714
|
if (params.blocked_by !== undefined) {
|
|
702
|
-
store.updateBlockedBy(params.task_id, params.blocked_by || null);
|
|
715
|
+
await store.updateBlockedBy(params.task_id, params.blocked_by || null);
|
|
703
716
|
}
|
|
704
717
|
if (params.status) {
|
|
705
|
-
store.updateTaskStatus(params.task_id, params.status);
|
|
718
|
+
await store.updateTaskStatus(params.task_id, params.status);
|
|
706
719
|
}
|
|
707
720
|
if (params.priority) {
|
|
708
|
-
store.updateTaskPriority(params.task_id, params.priority);
|
|
721
|
+
await store.updateTaskPriority(params.task_id, params.priority);
|
|
709
722
|
}
|
|
710
|
-
const updated = store.getEngram(params.task_id);
|
|
723
|
+
const updated = (await store.getEngram(params.task_id));
|
|
711
724
|
return {
|
|
712
725
|
content: [{
|
|
713
726
|
type: 'text',
|
|
@@ -715,15 +728,15 @@ Tasks automatically get high salience so they won't be discarded.`, {
|
|
|
715
728
|
}],
|
|
716
729
|
};
|
|
717
730
|
});
|
|
718
|
-
server.tool('memory_task_list', `List tasks with optional status filter. Shows tasks ordered by priority (urgent first).
|
|
719
|
-
|
|
731
|
+
server.tool('memory_task_list', `List tasks with optional status filter. Shows tasks ordered by priority (urgent first).
|
|
732
|
+
|
|
720
733
|
Use at the start of a session to see what's pending, or to check blocked/done tasks.`, {
|
|
721
734
|
status: z.enum(['open', 'in_progress', 'blocked', 'done']).optional()
|
|
722
735
|
.describe('Filter by status (omit to see all active tasks)'),
|
|
723
736
|
include_done: z.boolean().optional().default(false)
|
|
724
737
|
.describe('Include completed tasks?'),
|
|
725
738
|
}, async (params) => {
|
|
726
|
-
let tasks = store.getTasks(AGENT_ID, params.status);
|
|
739
|
+
let tasks = await store.getTasks(AGENT_ID, params.status);
|
|
727
740
|
if (!params.include_done && !params.status) {
|
|
728
741
|
tasks = tasks.filter(t => t.taskStatus !== 'done');
|
|
729
742
|
}
|
|
@@ -742,12 +755,12 @@ Use at the start of a session to see what's pending, or to check blocked/done ta
|
|
|
742
755
|
}],
|
|
743
756
|
};
|
|
744
757
|
});
|
|
745
|
-
server.tool('memory_task_next', `Get the single most important task to work on next.
|
|
746
|
-
|
|
747
|
-
Prioritizes: in_progress tasks first (finish what you started), then by priority level, then oldest first. Skips blocked and done tasks.
|
|
748
|
-
|
|
758
|
+
server.tool('memory_task_next', `Get the single most important task to work on next.
|
|
759
|
+
|
|
760
|
+
Prioritizes: in_progress tasks first (finish what you started), then by priority level, then oldest first. Skips blocked and done tasks.
|
|
761
|
+
|
|
749
762
|
Use this when you finish a task or need to decide what to do next.`, {}, async () => {
|
|
750
|
-
const next = store.getNextTask(AGENT_ID);
|
|
763
|
+
const next = await store.getNextTask(AGENT_ID);
|
|
751
764
|
if (!next) {
|
|
752
765
|
return { content: [{ type: 'text', text: 'No actionable tasks. All clear!' }] };
|
|
753
766
|
}
|
|
@@ -761,13 +774,13 @@ Use this when you finish a task or need to decide what to do next.`, {}, async (
|
|
|
761
774
|
};
|
|
762
775
|
});
|
|
763
776
|
// --- Task Bracket Tools ---
|
|
764
|
-
server.tool('memory_task_begin', `Signal that you're starting a significant task. Auto-checkpoints current state and recalls relevant memories.
|
|
765
|
-
|
|
766
|
-
CALL THIS when starting:
|
|
767
|
-
- A multi-step operation (doc generation, large refactor, migration)
|
|
768
|
-
- Work on a new topic or project area
|
|
769
|
-
- Anything that might fill the context window
|
|
770
|
-
|
|
777
|
+
server.tool('memory_task_begin', `Signal that you're starting a significant task. Auto-checkpoints current state and recalls relevant memories.
|
|
778
|
+
|
|
779
|
+
CALL THIS when starting:
|
|
780
|
+
- A multi-step operation (doc generation, large refactor, migration)
|
|
781
|
+
- Work on a new topic or project area
|
|
782
|
+
- Anything that might fill the context window
|
|
783
|
+
|
|
771
784
|
This ensures your state is saved before you start, and primes recall with relevant context.`, {
|
|
772
785
|
topic: z.string().describe('What task are you starting? (3-15 words)'),
|
|
773
786
|
files: z.array(z.string()).optional().default([])
|
|
@@ -776,9 +789,9 @@ This ensures your state is saved before you start, and primes recall with releva
|
|
|
776
789
|
.describe('Any additional context'),
|
|
777
790
|
}, async (params) => {
|
|
778
791
|
// 1. Checkpoint current state
|
|
779
|
-
const checkpoint = store.getCheckpoint(AGENT_ID);
|
|
792
|
+
const checkpoint = await store.getCheckpoint(AGENT_ID);
|
|
780
793
|
const prevTask = checkpoint?.executionState?.currentTask ?? 'None';
|
|
781
|
-
store.saveCheckpoint(AGENT_ID, {
|
|
794
|
+
await store.saveCheckpoint(AGENT_ID, {
|
|
782
795
|
currentTask: params.topic,
|
|
783
796
|
decisions: [],
|
|
784
797
|
activeFiles: params.files,
|
|
@@ -806,7 +819,7 @@ This ensures your state is saved before you start, and primes recall with releva
|
|
|
806
819
|
});
|
|
807
820
|
recalledSummary = `\n\n**Recalled memories (${results.length}):**\n${lines.join('\n')}`;
|
|
808
821
|
// Track recall
|
|
809
|
-
store.updateAutoCheckpointRecall(AGENT_ID, params.topic, results.map(r => r.engram.id));
|
|
822
|
+
await store.updateAutoCheckpointRecall(AGENT_ID, params.topic, results.map(r => r.engram.id));
|
|
810
823
|
}
|
|
811
824
|
}
|
|
812
825
|
catch { /* recall failure is non-fatal */ }
|
|
@@ -818,13 +831,13 @@ This ensures your state is saved before you start, and primes recall with releva
|
|
|
818
831
|
}],
|
|
819
832
|
};
|
|
820
833
|
});
|
|
821
|
-
server.tool('memory_task_end', `Signal that you've finished a significant task. Writes a summary memory and auto-checkpoints.
|
|
822
|
-
|
|
823
|
-
CALL THIS when you finish:
|
|
824
|
-
- A multi-step operation
|
|
825
|
-
- Before switching to a different topic
|
|
826
|
-
- At the end of a work session
|
|
827
|
-
|
|
834
|
+
server.tool('memory_task_end', `Signal that you've finished a significant task. Writes a summary memory and auto-checkpoints.
|
|
835
|
+
|
|
836
|
+
CALL THIS when you finish:
|
|
837
|
+
- A multi-step operation
|
|
838
|
+
- Before switching to a different topic
|
|
839
|
+
- At the end of a work session
|
|
840
|
+
|
|
828
841
|
This captures what was accomplished so future sessions can recall it.`, {
|
|
829
842
|
summary: z.string().describe('What was accomplished? Include key outcomes, decisions, and any issues.'),
|
|
830
843
|
tags: z.array(z.string()).optional().default([])
|
|
@@ -842,7 +855,7 @@ This captures what was accomplished so future sessions can recall it.`, {
|
|
|
842
855
|
resolutionEffort: 0.5,
|
|
843
856
|
});
|
|
844
857
|
// Determine the real task name for the summary engram
|
|
845
|
-
const checkpoint = store.getCheckpoint(AGENT_ID);
|
|
858
|
+
const checkpoint = await store.getCheckpoint(AGENT_ID);
|
|
846
859
|
const rawTask = checkpoint?.executionState?.currentTask ?? 'Unknown task';
|
|
847
860
|
// Strip any "Completed: " prefixes to avoid cascading
|
|
848
861
|
const cleanedTask = rawTask.replace(/^(Completed: )+/, '');
|
|
@@ -851,7 +864,7 @@ This captures what was accomplished so future sessions can recall it.`, {
|
|
|
851
864
|
const completedTask = isNamedTask
|
|
852
865
|
? cleanedTask
|
|
853
866
|
: params.summary.slice(0, 60).replace(/\n/g, ' ');
|
|
854
|
-
const engram = store.createEngram({
|
|
867
|
+
const engram = await store.createEngram({
|
|
855
868
|
agentId: AGENT_ID,
|
|
856
869
|
concept: completedTask.slice(0, 80),
|
|
857
870
|
content: params.summary,
|
|
@@ -865,20 +878,20 @@ This captures what was accomplished so future sessions can recall it.`, {
|
|
|
865
878
|
// 2. Handle supersessions — mark old memories as outdated
|
|
866
879
|
let supersededCount = 0;
|
|
867
880
|
for (const oldId of params.supersedes) {
|
|
868
|
-
const oldEngram = store.getEngram(oldId);
|
|
881
|
+
const oldEngram = await store.getEngram(oldId);
|
|
869
882
|
if (oldEngram) {
|
|
870
|
-
store.supersedeEngram(oldId, engram.id);
|
|
871
|
-
store.upsertAssociation(engram.id, oldId, 0.8, 'causal', 0.9);
|
|
872
|
-
store.updateConfidence(oldId, Math.max(0.2, oldEngram.confidence * 0.4));
|
|
883
|
+
await store.supersedeEngram(oldId, engram.id);
|
|
884
|
+
await store.upsertAssociation(engram.id, oldId, 0.8, 'causal', 0.9);
|
|
885
|
+
await store.updateConfidence(oldId, Math.max(0.2, oldEngram.confidence * 0.4));
|
|
873
886
|
supersededCount++;
|
|
874
887
|
}
|
|
875
888
|
}
|
|
876
889
|
// Generate embedding asynchronously
|
|
877
|
-
embed(`Task completed: ${params.summary}`).then(vec => {
|
|
878
|
-
store.updateEmbedding(engram.id, vec);
|
|
890
|
+
embed(`Task completed: ${params.summary}`).then(async (vec) => {
|
|
891
|
+
await store.updateEmbedding(engram.id, vec);
|
|
879
892
|
}).catch(() => { });
|
|
880
893
|
// 2. Update checkpoint to reflect completion
|
|
881
|
-
store.saveCheckpoint(AGENT_ID, {
|
|
894
|
+
await store.saveCheckpoint(AGENT_ID, {
|
|
882
895
|
currentTask: `Completed: ${completedTask}`,
|
|
883
896
|
decisions: checkpoint?.executionState?.decisions ?? [],
|
|
884
897
|
activeFiles: [],
|
|
@@ -887,7 +900,7 @@ This captures what was accomplished so future sessions can recall it.`, {
|
|
|
887
900
|
notes: `Task completed. Summary memory: ${engram.id}`,
|
|
888
901
|
episodeId: null,
|
|
889
902
|
});
|
|
890
|
-
store.updateAutoCheckpointWrite(AGENT_ID, engram.id);
|
|
903
|
+
await store.updateAutoCheckpointWrite(AGENT_ID, engram.id);
|
|
891
904
|
log(AGENT_ID, 'task:end', `"${completedTask}" summary=${engram.id} salience=${salience.score.toFixed(2)} superseded=${supersededCount}`);
|
|
892
905
|
const supersededNote = supersededCount > 0 ? ` (${supersededCount} old memories superseded)` : '';
|
|
893
906
|
return {
|
|
@@ -910,18 +923,26 @@ This captures what was accomplished so future sessions can recall it.`, {
|
|
|
910
923
|
onConsolidate: async (agentId, reason) => {
|
|
911
924
|
console.error(`[mcp] consolidation triggered: ${reason}`);
|
|
912
925
|
const result = await consolidationEngine.consolidate(agentId);
|
|
913
|
-
store.markConsolidation(agentId, false);
|
|
926
|
+
await store.markConsolidation(agentId, false);
|
|
914
927
|
console.error(`[mcp] consolidation done: ${result.edgesStrengthened} strengthened, ${result.memoriesForgotten} forgotten`);
|
|
915
928
|
},
|
|
916
929
|
});
|
|
917
930
|
// Coordination MCP tools (opt-in via AWM_COORDINATION=true)
|
|
918
|
-
|
|
931
|
+
// AWM 0.8.x: coordination requires SQLite (uses store.getDb()). On PGlite,
|
|
932
|
+
// coordination is auto-disabled with a warning; re-enable when coordination
|
|
933
|
+
// is ported to async/PGlite.
|
|
934
|
+
const coordRequested = process.env.AWM_COORDINATION === 'true' || process.env.AWM_COORDINATION === '1';
|
|
935
|
+
const coordEnabled = coordRequested && BACKEND === 'sqlite';
|
|
919
936
|
if (coordEnabled) {
|
|
920
937
|
const { initCoordinationTables } = await import('./coordination/schema.js');
|
|
921
938
|
const { registerCoordinationTools } = await import('./coordination/mcp-tools.js');
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
939
|
+
const sqliteStore = store;
|
|
940
|
+
initCoordinationTables(sqliteStore.getDb());
|
|
941
|
+
registerCoordinationTools(server, sqliteStore.getDb());
|
|
942
|
+
coordDb = sqliteStore.getDb();
|
|
943
|
+
}
|
|
944
|
+
else if (coordRequested && BACKEND === 'pglite') {
|
|
945
|
+
console.error('AWM: coordination requested but disabled — coordination plugin requires SQLite backend');
|
|
925
946
|
}
|
|
926
947
|
else {
|
|
927
948
|
console.error('AWM: coordination tools disabled (set AWM_COORDINATION=true to enable)');
|
|
@@ -930,18 +951,23 @@ This captures what was accomplished so future sessions can recall it.`, {
|
|
|
930
951
|
console.error(`AgentWorkingMemory MCP server started (agent: ${AGENT_ID}, db: ${DB_PATH})`);
|
|
931
952
|
console.error(`Hook sidecar on 127.0.0.1:${HOOK_PORT}${HOOK_SECRET ? ' (auth enabled)' : ' (no auth — set AWM_HOOK_SECRET)'}`);
|
|
932
953
|
// Clean shutdown
|
|
933
|
-
const cleanup = () => {
|
|
954
|
+
const cleanup = async () => {
|
|
934
955
|
sidecar.close();
|
|
935
956
|
consolidationScheduler.stop();
|
|
936
957
|
stagingBuffer.stop();
|
|
958
|
+
if (BACKEND === 'sqlite') {
|
|
959
|
+
try {
|
|
960
|
+
store.walCheckpoint?.();
|
|
961
|
+
}
|
|
962
|
+
catch { /* non-fatal */ }
|
|
963
|
+
}
|
|
937
964
|
try {
|
|
938
|
-
store.
|
|
965
|
+
await store.close?.();
|
|
939
966
|
}
|
|
940
|
-
catch { /*
|
|
941
|
-
store.close();
|
|
967
|
+
catch { /* best-effort */ }
|
|
942
968
|
};
|
|
943
|
-
process.on('SIGINT', () => { cleanup()
|
|
944
|
-
process.on('SIGTERM', () => { cleanup()
|
|
969
|
+
process.on('SIGINT', () => { void cleanup().finally(() => process.exit(0)); });
|
|
970
|
+
process.on('SIGTERM', () => { void cleanup().finally(() => process.exit(0)); });
|
|
945
971
|
}
|
|
946
972
|
main().catch(err => {
|
|
947
973
|
console.error('MCP server failed:', err);
|