agent-working-memory 0.5.6 → 0.6.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 +78 -43
- package/dist/adapters/claude-code.d.ts +4 -0
- package/dist/adapters/claude-code.d.ts.map +1 -0
- package/dist/adapters/claude-code.js +218 -0
- package/dist/adapters/claude-code.js.map +1 -0
- package/dist/adapters/codex.d.ts +4 -0
- package/dist/adapters/codex.d.ts.map +1 -0
- package/dist/adapters/codex.js +226 -0
- package/dist/adapters/codex.js.map +1 -0
- package/dist/adapters/common.d.ts +34 -0
- package/dist/adapters/common.d.ts.map +1 -0
- package/dist/adapters/common.js +145 -0
- package/dist/adapters/common.js.map +1 -0
- package/dist/adapters/cursor.d.ts +4 -0
- package/dist/adapters/cursor.d.ts.map +1 -0
- package/dist/adapters/cursor.js +138 -0
- package/dist/adapters/cursor.js.map +1 -0
- package/dist/adapters/http.d.ts +4 -0
- package/dist/adapters/http.d.ts.map +1 -0
- package/dist/adapters/http.js +88 -0
- package/dist/adapters/http.js.map +1 -0
- package/dist/adapters/index.d.ts +7 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +21 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/types.d.ts +65 -0
- package/dist/adapters/types.d.ts.map +1 -0
- package/dist/adapters/types.js +4 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/api/routes.d.ts.map +1 -1
- package/dist/api/routes.js +40 -1
- package/dist/api/routes.js.map +1 -1
- package/dist/cli.js +504 -230
- package/dist/cli.js.map +1 -1
- package/dist/coordination/events.d.ts +59 -0
- package/dist/coordination/events.d.ts.map +1 -0
- package/dist/coordination/events.js +28 -0
- package/dist/coordination/events.js.map +1 -0
- package/dist/coordination/index.d.ts +10 -1
- package/dist/coordination/index.d.ts.map +1 -1
- package/dist/coordination/index.js +87 -3
- package/dist/coordination/index.js.map +1 -1
- package/dist/coordination/mcp-tools.d.ts.map +1 -1
- package/dist/coordination/mcp-tools.js +10 -5
- package/dist/coordination/mcp-tools.js.map +1 -1
- package/dist/coordination/peer-decisions.d.ts +40 -0
- package/dist/coordination/peer-decisions.d.ts.map +1 -0
- package/dist/coordination/peer-decisions.js +82 -0
- package/dist/coordination/peer-decisions.js.map +1 -0
- package/dist/coordination/plugin-loader.d.ts +18 -0
- package/dist/coordination/plugin-loader.d.ts.map +1 -0
- package/dist/coordination/plugin-loader.js +55 -0
- package/dist/coordination/plugin-loader.js.map +1 -0
- package/dist/coordination/plugin.d.ts +40 -0
- package/dist/coordination/plugin.d.ts.map +1 -0
- package/dist/coordination/plugin.js +22 -0
- package/dist/coordination/plugin.js.map +1 -0
- package/dist/coordination/routes.d.ts +2 -1
- package/dist/coordination/routes.d.ts.map +1 -1
- package/dist/coordination/routes.js +1027 -65
- package/dist/coordination/routes.js.map +1 -1
- package/dist/coordination/schema.d.ts.map +1 -1
- package/dist/coordination/schema.js +104 -12
- package/dist/coordination/schema.js.map +1 -1
- package/dist/coordination/schemas.d.ts +105 -5
- package/dist/coordination/schemas.d.ts.map +1 -1
- package/dist/coordination/schemas.js +87 -1
- package/dist/coordination/schemas.js.map +1 -1
- package/dist/coordination/stale.d.ts +2 -0
- package/dist/coordination/stale.d.ts.map +1 -1
- package/dist/coordination/stale.js +7 -1
- package/dist/coordination/stale.js.map +1 -1
- package/dist/coordination/types.d.ts +252 -0
- package/dist/coordination/types.d.ts.map +1 -0
- package/dist/coordination/types.js +8 -0
- package/dist/coordination/types.js.map +1 -0
- package/dist/coordination/write-mutex.d.ts +26 -0
- package/dist/coordination/write-mutex.d.ts.map +1 -0
- package/dist/coordination/write-mutex.js +63 -0
- package/dist/coordination/write-mutex.js.map +1 -0
- package/dist/core/embeddings.d.ts +2 -0
- package/dist/core/embeddings.d.ts.map +1 -1
- package/dist/core/embeddings.js +4 -0
- package/dist/core/embeddings.js.map +1 -1
- package/dist/engine/activation.d.ts.map +1 -1
- package/dist/engine/activation.js +135 -26
- package/dist/engine/activation.js.map +1 -1
- package/dist/engine/consolidation.d.ts.map +1 -1
- package/dist/engine/consolidation.js +42 -12
- package/dist/engine/consolidation.js.map +1 -1
- package/dist/engine/retraction.d.ts +3 -1
- package/dist/engine/retraction.d.ts.map +1 -1
- package/dist/engine/retraction.js +19 -6
- package/dist/engine/retraction.js.map +1 -1
- package/dist/index.js +82 -16
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +113 -6
- package/dist/mcp.js.map +1 -1
- package/dist/storage/sqlite.d.ts +24 -1
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +88 -7
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/types/engram.d.ts +24 -0
- 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 +234 -0
- package/src/adapters/codex.ts +262 -0
- package/src/adapters/common.ts +172 -0
- package/src/adapters/cursor.ts +150 -0
- package/src/adapters/http.ts +100 -0
- package/src/adapters/index.ts +31 -0
- package/src/adapters/types.ts +75 -0
- package/src/api/routes.ts +50 -1
- package/src/cli.ts +561 -239
- package/src/coordination/events.ts +90 -0
- package/src/coordination/index.ts +102 -3
- package/src/coordination/mcp-tools.ts +10 -5
- package/src/coordination/peer-decisions.ts +105 -0
- package/src/coordination/plugin-loader.ts +60 -0
- package/src/coordination/plugin.ts +44 -0
- package/src/coordination/routes.ts +1353 -92
- package/src/coordination/schema.ts +91 -12
- package/src/coordination/schemas.ts +104 -1
- package/src/coordination/stale.ts +11 -2
- package/src/coordination/types.ts +311 -0
- package/src/coordination/write-mutex.ts +69 -0
- package/src/core/embeddings.ts +5 -0
- package/src/engine/activation.ts +138 -26
- package/src/engine/consolidation.ts +44 -12
- package/src/engine/retraction.ts +22 -6
- package/src/index.ts +76 -14
- package/src/mcp.ts +142 -9
- package/src/storage/sqlite.ts +92 -7
- package/src/types/engram.ts +28 -0
|
@@ -45,33 +45,46 @@ export class RetractionEngine {
|
|
|
45
45
|
// Update retracted_by to point to correction
|
|
46
46
|
this.store.retractEngram(target.id, correction.id);
|
|
47
47
|
}
|
|
48
|
-
// Reduce confidence of
|
|
49
|
-
|
|
48
|
+
// Reduce confidence of associated engrams (contamination spread)
|
|
49
|
+
// Depth 2 with 50% decay per hop, capped at 20 total affected nodes
|
|
50
|
+
const associatesAffected = this.propagateConfidenceReduction(target.id, 0.1, 2);
|
|
50
51
|
return { retractedId: target.id, correctionId, associatesAffected };
|
|
51
52
|
}
|
|
52
53
|
/**
|
|
53
54
|
* Reduce confidence of engrams associated with a retracted engram.
|
|
54
|
-
*
|
|
55
|
+
* Propagates up to maxDepth hops with decaying penalty (50% per hop).
|
|
56
|
+
* Capped at MAX_AFFECTED to prevent cascading through the graph.
|
|
55
57
|
*/
|
|
56
|
-
|
|
58
|
+
static MAX_AFFECTED = 20;
|
|
59
|
+
propagateConfidenceReduction(engramId, penalty, maxDepth, currentDepth = 0, visited = new Set()) {
|
|
57
60
|
if (currentDepth >= maxDepth)
|
|
58
61
|
return 0;
|
|
62
|
+
if (visited.size >= RetractionEngine.MAX_AFFECTED)
|
|
63
|
+
return 0;
|
|
64
|
+
visited.add(engramId);
|
|
59
65
|
let affected = 0;
|
|
60
66
|
const associations = this.store.getAssociationsFor(engramId);
|
|
61
67
|
for (const assoc of associations) {
|
|
62
68
|
if (assoc.type === 'invalidation')
|
|
63
69
|
continue; // Don't penalize corrections
|
|
70
|
+
if (visited.size >= RetractionEngine.MAX_AFFECTED)
|
|
71
|
+
break;
|
|
64
72
|
const neighborId = assoc.fromEngramId === engramId
|
|
65
73
|
? assoc.toEngramId
|
|
66
74
|
: assoc.fromEngramId;
|
|
75
|
+
if (visited.has(neighborId))
|
|
76
|
+
continue;
|
|
67
77
|
const neighbor = this.store.getEngram(neighborId);
|
|
68
78
|
if (!neighbor || neighbor.retracted)
|
|
69
79
|
continue;
|
|
70
|
-
// Scale penalty by association weight
|
|
71
|
-
const
|
|
80
|
+
// Scale penalty by association weight and decay per hop (50% per depth level)
|
|
81
|
+
const depthDecay = Math.pow(0.5, currentDepth);
|
|
82
|
+
const scaledPenalty = penalty * assoc.weight * depthDecay;
|
|
72
83
|
const newConfidence = Math.max(0.1, neighbor.confidence - scaledPenalty);
|
|
73
84
|
this.store.updateConfidence(neighborId, newConfidence);
|
|
74
85
|
affected++;
|
|
86
|
+
// Recurse to next depth
|
|
87
|
+
affected += this.propagateConfidenceReduction(neighborId, penalty, maxDepth, currentDepth + 1, visited);
|
|
75
88
|
}
|
|
76
89
|
return affected;
|
|
77
90
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retraction.js","sourceRoot":"","sources":["../../src/engine/retraction.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,sCAAsC;AACtC;;;;;;;;;;;GAWG;AAKH,MAAM,OAAO,gBAAgB;IACnB,KAAK,CAAc;IAE3B,YAAY,KAAkB;QAC5B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,UAAsB;QAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;QAC/D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,UAAU,UAAU,CAAC,cAAc,YAAY,CAAC,CAAC;QACnE,CAAC;QAED,iCAAiC;QACjC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAE1C,IAAI,YAAY,GAAkB,IAAI,CAAC;QAEvC,uDAAuD;QACvD,IAAI,UAAU,CAAC,cAAc,EAAE,CAAC;YAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC;gBACzC,OAAO,EAAE,UAAU,CAAC,OAAO;gBAC3B,OAAO,EAAE,cAAc,MAAM,CAAC,OAAO,EAAE;gBACvC,OAAO,EAAE,UAAU,CAAC,cAAc;gBAClC,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,YAAY,EAAE,YAAY,CAAC;gBAClD,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,8CAA8C;gBACxF,UAAU,EAAE,GAAG;gBACf,WAAW,EAAE,CAAC,uBAAuB,EAAE,eAAe,MAAM,CAAC,EAAE,EAAE,CAAC;aACnE,CAAC,CAAC;YAEH,YAAY,GAAG,UAAU,CAAC,EAAE,CAAC;YAE7B,2BAA2B;YAC3B,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAC1B,UAAU,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,CACnD,CAAC;YAEF,6CAA6C;YAC7C,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,EAAE,UAAU,CAAC,EAAE,CAAC,CAAC;QACrD,CAAC;QAED,
|
|
1
|
+
{"version":3,"file":"retraction.js","sourceRoot":"","sources":["../../src/engine/retraction.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Copyright 2026 Robert Winter / Complete Ideas
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
import { readFileSync, copyFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
3
|
+
import { readFileSync, copyFileSync, existsSync, mkdirSync, readdirSync, unlinkSync } from 'node:fs';
|
|
4
4
|
import { resolve, dirname, basename } from 'node:path';
|
|
5
5
|
import Fastify from 'fastify';
|
|
6
6
|
// Load .env file if present (no external dependency)
|
|
@@ -59,6 +59,37 @@ async function main() {
|
|
|
59
59
|
initLogger(DB_PATH);
|
|
60
60
|
// Storage
|
|
61
61
|
const store = new EngramStore(DB_PATH);
|
|
62
|
+
// Integrity check
|
|
63
|
+
const integrity = store.integrityCheck();
|
|
64
|
+
if (!integrity.ok) {
|
|
65
|
+
console.error(`DB integrity check FAILED: ${integrity.result}`);
|
|
66
|
+
// Close corrupt DB, restore from backup, and exit for process manager to restart
|
|
67
|
+
store.close();
|
|
68
|
+
const dbDir = dirname(resolve(DB_PATH));
|
|
69
|
+
const backupDir = resolve(dbDir, 'backups');
|
|
70
|
+
if (existsSync(backupDir)) {
|
|
71
|
+
const backups = readdirSync(backupDir)
|
|
72
|
+
.filter(f => f.endsWith('.db'))
|
|
73
|
+
.sort()
|
|
74
|
+
.reverse();
|
|
75
|
+
if (backups.length > 0) {
|
|
76
|
+
const restorePath = resolve(backupDir, backups[0]);
|
|
77
|
+
console.error(`Attempting restore from: ${restorePath}`);
|
|
78
|
+
try {
|
|
79
|
+
copyFileSync(restorePath, resolve(DB_PATH));
|
|
80
|
+
console.error('Restore complete — exiting for restart with restored DB');
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
catch (restoreErr) {
|
|
84
|
+
console.error(`Restore failed: ${restoreErr.message}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
console.error('No backup available — continuing with potentially corrupt DB');
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
console.log(' DB integrity check: ok');
|
|
92
|
+
}
|
|
62
93
|
// Engines
|
|
63
94
|
const activationEngine = new ActivationEngine(store);
|
|
64
95
|
const connectionEngine = new ConnectionEngine(store, activationEngine);
|
|
@@ -69,7 +100,8 @@ async function main() {
|
|
|
69
100
|
const consolidationEngine = new ConsolidationEngine(store);
|
|
70
101
|
const consolidationScheduler = new ConsolidationScheduler(store, consolidationEngine);
|
|
71
102
|
// API — disable Fastify's default request logging (too noisy for hive polling)
|
|
72
|
-
|
|
103
|
+
// bodyLimit: 512KB to prevent Content-Length mismatch errors with large task payloads
|
|
104
|
+
const app = Fastify({ logger: false, bodyLimit: 512_000 });
|
|
73
105
|
// Bearer token auth — only enforced when AWM_API_KEY is explicitly set and non-empty
|
|
74
106
|
if (API_KEY && API_KEY !== 'NONE' && API_KEY.length > 1) {
|
|
75
107
|
app.addHook('onRequest', async (req, reply) => {
|
|
@@ -89,17 +121,9 @@ async function main() {
|
|
|
89
121
|
consolidationEngine, consolidationScheduler,
|
|
90
122
|
});
|
|
91
123
|
// Coordination module (opt-in via AWM_COORDINATION=true)
|
|
92
|
-
|
|
93
|
-
const { isCoordinationEnabled, initCoordination } = await import('./coordination/index.js');
|
|
124
|
+
const { isCoordinationEnabled, initCoordination, stopCoordinationCleanup } = await import('./coordination/index.js');
|
|
94
125
|
if (isCoordinationEnabled()) {
|
|
95
|
-
initCoordination(app, store.getDb());
|
|
96
|
-
// Prune stale heartbeat events every 30s (keeps assignment/command events permanently)
|
|
97
|
-
const { pruneOldHeartbeats } = await import('./coordination/stale.js');
|
|
98
|
-
heartbeatPruneTimer = setInterval(() => {
|
|
99
|
-
const pruned = pruneOldHeartbeats(store.getDb());
|
|
100
|
-
if (pruned > 0)
|
|
101
|
-
console.log(`[coordination] pruned ${pruned} old heartbeat event(s)`);
|
|
102
|
-
}, 30_000);
|
|
126
|
+
initCoordination(app, store.getDb(), store);
|
|
103
127
|
}
|
|
104
128
|
else {
|
|
105
129
|
console.log(' Coordination module disabled (set AWM_COORDINATION=true to enable)');
|
|
@@ -107,19 +131,61 @@ async function main() {
|
|
|
107
131
|
// Background tasks
|
|
108
132
|
stagingBuffer.start(DEFAULT_AGENT_CONFIG.stagingTtlMs);
|
|
109
133
|
consolidationScheduler.start();
|
|
134
|
+
// Periodic hot backup every 10 minutes (keep last 6 = 1hr coverage)
|
|
135
|
+
const dbDir = dirname(resolve(DB_PATH));
|
|
136
|
+
const backupDir = resolve(dbDir, 'backups');
|
|
137
|
+
mkdirSync(backupDir, { recursive: true });
|
|
138
|
+
// Cleanup old backups on startup (older than 2 hours)
|
|
139
|
+
try {
|
|
140
|
+
const TWO_HOURS_MS = 2 * 60 * 60 * 1000;
|
|
141
|
+
const now = Date.now();
|
|
142
|
+
for (const f of readdirSync(backupDir).filter(f => f.endsWith('.db'))) {
|
|
143
|
+
const match = f.match(/(\d{4})-(\d{2})-(\d{2})T(\d{2})-(\d{2})-(\d{2})/);
|
|
144
|
+
if (match) {
|
|
145
|
+
const fileDate = new Date(`${match[1]}-${match[2]}-${match[3]}T${match[4]}:${match[5]}:${match[6]}Z`);
|
|
146
|
+
if (now - fileDate.getTime() > TWO_HOURS_MS) {
|
|
147
|
+
unlinkSync(resolve(backupDir, f));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
catch { /* cleanup is non-fatal */ }
|
|
153
|
+
const backupTimer = setInterval(() => {
|
|
154
|
+
try {
|
|
155
|
+
const ts = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
|
|
156
|
+
const backupPath = resolve(backupDir, `${basename(DB_PATH, '.db')}-${ts}.db`);
|
|
157
|
+
store.backup(backupPath);
|
|
158
|
+
// Prune: keep only last 6 backups
|
|
159
|
+
const backups = readdirSync(backupDir).filter(f => f.endsWith('.db')).sort();
|
|
160
|
+
while (backups.length > 6) {
|
|
161
|
+
const old = backups.shift();
|
|
162
|
+
try {
|
|
163
|
+
unlinkSync(resolve(backupDir, old));
|
|
164
|
+
}
|
|
165
|
+
catch { /* non-fatal */ }
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
console.warn(`[backup] failed: ${err.message}`);
|
|
170
|
+
}
|
|
171
|
+
}, 10 * 60_000); // 10 minutes
|
|
110
172
|
// Pre-load ML models (downloads on first run: embeddings ~22MB, reranker ~22MB, expander ~80MB)
|
|
111
173
|
getEmbedder().catch(err => console.warn('Embedding model unavailable:', err.message));
|
|
112
174
|
getReranker().catch(err => console.warn('Reranker model unavailable:', err.message));
|
|
113
175
|
getExpander().catch(err => console.warn('Query expander model unavailable:', err.message));
|
|
114
176
|
// Start server
|
|
115
177
|
await app.listen({ port: PORT, host: '0.0.0.0' });
|
|
116
|
-
console.log(`AgentWorkingMemory v0.
|
|
178
|
+
console.log(`AgentWorkingMemory v0.6.0 listening on port ${PORT}`);
|
|
117
179
|
// Graceful shutdown
|
|
118
|
-
const shutdown = () => {
|
|
119
|
-
|
|
120
|
-
|
|
180
|
+
const shutdown = async () => {
|
|
181
|
+
clearInterval(backupTimer);
|
|
182
|
+
await stopCoordinationCleanup();
|
|
121
183
|
consolidationScheduler.stop();
|
|
122
184
|
stagingBuffer.stop();
|
|
185
|
+
try {
|
|
186
|
+
store.walCheckpoint();
|
|
187
|
+
}
|
|
188
|
+
catch { /* non-fatal */ }
|
|
123
189
|
store.close();
|
|
124
190
|
process.exit(0);
|
|
125
191
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,sCAAsC;AACtC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp.js
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
*/
|
|
26
26
|
import { readFileSync } from 'node:fs';
|
|
27
27
|
import { resolve } from 'node:path';
|
|
28
|
-
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
28
|
+
import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
29
29
|
// Load .env file if present (no external dependency)
|
|
30
30
|
try {
|
|
31
31
|
const envPath = resolve(process.cwd(), '.env');
|
|
@@ -44,6 +44,10 @@ try {
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
catch { /* No .env file */ }
|
|
47
|
+
// MCP uses stdout for JSON-RPC. Redirect console.log to stderr so engine
|
|
48
|
+
// startup messages (ConsolidationScheduler, model loading, etc.) don't
|
|
49
|
+
// corrupt the transport. This MUST happen before any engine imports.
|
|
50
|
+
console.log = console.error;
|
|
47
51
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
48
52
|
import { z } from 'zod';
|
|
49
53
|
import { EngramStore } from './storage/sqlite.js';
|
|
@@ -60,13 +64,14 @@ import { DEFAULT_AGENT_CONFIG } from './types/agent.js';
|
|
|
60
64
|
import { embed } from './core/embeddings.js';
|
|
61
65
|
import { startSidecar } from './hooks/sidecar.js';
|
|
62
66
|
import { initLogger, log, getLogPath } from './core/logger.js';
|
|
67
|
+
import { queryPeerDecisions, formatPeerDecisions } from './coordination/peer-decisions.js';
|
|
63
68
|
// --- Incognito Mode ---
|
|
64
69
|
// When AWM_INCOGNITO=1, register zero tools. Claude won't see memory tools at all.
|
|
65
70
|
// No DB, no engines, no sidecar — just a bare MCP server that exposes nothing.
|
|
66
71
|
const INCOGNITO = process.env.AWM_INCOGNITO === '1' || process.env.AWM_INCOGNITO === 'true';
|
|
67
72
|
if (INCOGNITO) {
|
|
68
73
|
console.error('AWM: incognito mode — all memory tools disabled, nothing will be recorded');
|
|
69
|
-
const server = new McpServer({ name: 'agent-working-memory', version: '0.
|
|
74
|
+
const server = new McpServer({ name: 'agent-working-memory', version: '0.6.0' });
|
|
70
75
|
const transport = new StdioServerTransport();
|
|
71
76
|
server.connect(transport).catch(err => {
|
|
72
77
|
console.error('MCP server failed:', err);
|
|
@@ -93,10 +98,69 @@ else {
|
|
|
93
98
|
const consolidationScheduler = new ConsolidationScheduler(store, consolidationEngine);
|
|
94
99
|
stagingBuffer.start(DEFAULT_AGENT_CONFIG.stagingTtlMs);
|
|
95
100
|
consolidationScheduler.start();
|
|
101
|
+
// Coordination DB handle — set when AWM_COORDINATION=true, used by memory_write for decision propagation
|
|
102
|
+
let coordDb = null;
|
|
96
103
|
const server = new McpServer({
|
|
97
104
|
name: 'agent-working-memory',
|
|
98
|
-
version: '0.
|
|
105
|
+
version: '0.6.0',
|
|
99
106
|
});
|
|
107
|
+
server.registerResource('awm-overview', 'awm://server/overview', {
|
|
108
|
+
title: 'AWM Overview',
|
|
109
|
+
description: 'AgentWorkingMemory MCP server metadata and discovery notes',
|
|
110
|
+
mimeType: 'text/markdown',
|
|
111
|
+
}, async () => ({
|
|
112
|
+
contents: [{
|
|
113
|
+
uri: 'awm://server/overview',
|
|
114
|
+
text: [
|
|
115
|
+
'# Agent Working Memory',
|
|
116
|
+
'',
|
|
117
|
+
`Agent: ${AGENT_ID}`,
|
|
118
|
+
`DB: ${DB_PATH}`,
|
|
119
|
+
`Coordination: ${process.env.AWM_COORDINATION === 'true' || process.env.AWM_COORDINATION === '1' ? 'enabled' : 'disabled'}`,
|
|
120
|
+
'',
|
|
121
|
+
'This MCP server primarily exposes tools such as `memory_restore`, `memory_recall`, `memory_write`, and task/checkpoint operations.',
|
|
122
|
+
'The resources below exist so generic MCP clients can discover the server through `resources/list` and `resources/templates/list`.',
|
|
123
|
+
].join('\n'),
|
|
124
|
+
mimeType: 'text/markdown',
|
|
125
|
+
}],
|
|
126
|
+
}));
|
|
127
|
+
server.registerResource('awm-memory-template', new ResourceTemplate('awm://memory/{id}', { list: undefined }), {
|
|
128
|
+
title: 'AWM Memory By ID',
|
|
129
|
+
description: 'Metadata resource template for a memory identifier',
|
|
130
|
+
mimeType: 'text/markdown',
|
|
131
|
+
}, async (_uri, variables) => ({
|
|
132
|
+
contents: [{
|
|
133
|
+
uri: `awm://memory/${variables.id ?? ''}`,
|
|
134
|
+
text: [
|
|
135
|
+
'# AWM Memory Reference',
|
|
136
|
+
'',
|
|
137
|
+
`Requested memory id: ${variables.id ?? ''}`,
|
|
138
|
+
'',
|
|
139
|
+
'Use the AWM memory tools for actual retrieval and mutation:',
|
|
140
|
+
'- `memory_recall` for cognitive retrieval',
|
|
141
|
+
'- `memory_restore` for session state',
|
|
142
|
+
'- `memory_feedback`, `memory_retract`, `memory_supersede` for memory maintenance',
|
|
143
|
+
].join('\n'),
|
|
144
|
+
mimeType: 'text/markdown',
|
|
145
|
+
}],
|
|
146
|
+
}));
|
|
147
|
+
// --- Auto-classification for memory types ---
|
|
148
|
+
function classifyMemoryType(content) {
|
|
149
|
+
const lower = content.toLowerCase();
|
|
150
|
+
// Procedural: how-to, steps, numbered lists
|
|
151
|
+
if (/\bhow to\b|\bsteps?:/i.test(content) || /^\s*\d+[\.\)]\s/m.test(content) || /\bthen run\b|\bfirst,?\s/i.test(content)) {
|
|
152
|
+
return 'procedural';
|
|
153
|
+
}
|
|
154
|
+
// Episodic: past tense events, incidents, specific time references
|
|
155
|
+
if (/\b(discovered|debugged|fixed|encountered|happened|resolved|found that|we did|i did|yesterday|last week|today)\b/i.test(content)) {
|
|
156
|
+
return 'episodic';
|
|
157
|
+
}
|
|
158
|
+
// Semantic: facts, decisions, rules, patterns
|
|
159
|
+
if (/\b(is|are|should|always|never|must|uses?|requires?|means|pattern|decision|rule|convention)\b/i.test(content) && content.length < 500) {
|
|
160
|
+
return 'semantic';
|
|
161
|
+
}
|
|
162
|
+
return 'unclassified';
|
|
163
|
+
}
|
|
100
164
|
// --- Tools ---
|
|
101
165
|
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.
|
|
102
166
|
|
|
@@ -124,6 +188,8 @@ The concept should be a short label (3-8 words). The content should be the full
|
|
|
124
188
|
.describe('How much effort to resolve? 0=trivial, 1=significant debugging'),
|
|
125
189
|
memory_class: z.enum(['canonical', 'working', 'ephemeral']).optional().default('working')
|
|
126
190
|
.describe('Memory class: canonical (source-of-truth, never stages), working (default), ephemeral (temporary, decays faster)'),
|
|
191
|
+
memory_type: z.enum(['episodic', 'semantic', 'procedural', 'unclassified']).optional()
|
|
192
|
+
.describe('Memory type: episodic (events/incidents), semantic (facts/decisions), procedural (how-to/steps). Auto-classified if omitted.'),
|
|
127
193
|
supersedes: z.string().optional()
|
|
128
194
|
.describe('ID of an older memory this one replaces. The old memory is down-ranked, not deleted.'),
|
|
129
195
|
}, async (params) => {
|
|
@@ -190,6 +256,7 @@ The concept should be a short label (3-8 words). The content should be the full
|
|
|
190
256
|
: salience.disposition === 'staging'
|
|
191
257
|
? 0.40
|
|
192
258
|
: CONFIDENCE_PRIORS[params.event_type ?? 'observation'] ?? 0.45;
|
|
259
|
+
const memoryType = params.memory_type ?? classifyMemoryType(params.content);
|
|
193
260
|
const engram = store.createEngram({
|
|
194
261
|
agentId: AGENT_ID,
|
|
195
262
|
concept: params.concept,
|
|
@@ -201,6 +268,7 @@ The concept should be a short label (3-8 words). The content should be the full
|
|
|
201
268
|
reasonCodes: salience.reasonCodes,
|
|
202
269
|
ttl: salience.disposition === 'staging' ? DEFAULT_AGENT_CONFIG.stagingTtlMs : undefined,
|
|
203
270
|
memoryClass: params.memory_class,
|
|
271
|
+
memoryType,
|
|
204
272
|
supersedes: params.supersedes,
|
|
205
273
|
});
|
|
206
274
|
if (salience.disposition === 'staging') {
|
|
@@ -227,12 +295,23 @@ The concept should be a short label (3-8 words). The content should be the full
|
|
|
227
295
|
store.updateAutoCheckpointWrite(AGENT_ID, engram.id);
|
|
228
296
|
}
|
|
229
297
|
catch { /* non-fatal */ }
|
|
298
|
+
// Decision propagation: when decision_made=true and coordination is enabled,
|
|
299
|
+
// broadcast to coord_decisions so other agents can discover it
|
|
300
|
+
if (params.decision_made && coordDb) {
|
|
301
|
+
try {
|
|
302
|
+
const agent = coordDb.prepare(`SELECT id, current_task FROM coord_agents WHERE name = ? AND status != 'dead' ORDER BY last_seen DESC LIMIT 1`).get(AGENT_ID);
|
|
303
|
+
if (agent) {
|
|
304
|
+
coordDb.prepare(`INSERT INTO coord_decisions (author_id, assignment_id, tags, summary) VALUES (?, ?, ?, ?)`).run(agent.id, agent.current_task, params.tags ? JSON.stringify(params.tags) : null, params.concept);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
catch { /* decision propagation is non-fatal */ }
|
|
308
|
+
}
|
|
230
309
|
const logDisposition = isLowSalience ? 'low-salience' : salience.disposition;
|
|
231
310
|
log(AGENT_ID, `write:${logDisposition}`, `"${params.concept}" salience=${salience.score.toFixed(2)} novelty=${novelty.toFixed(1)} id=${engram.id}`);
|
|
232
311
|
return {
|
|
233
312
|
content: [{
|
|
234
313
|
type: 'text',
|
|
235
|
-
text: `Stored (${salience.disposition}) "${params.concept}" [${salience.score.toFixed(2)}]`,
|
|
314
|
+
text: `Stored (${salience.disposition}) "${params.concept}" [${salience.score.toFixed(2)}]\nID: ${engram.id}`,
|
|
236
315
|
}],
|
|
237
316
|
};
|
|
238
317
|
});
|
|
@@ -253,6 +332,7 @@ Returns the most relevant memories ranked by text relevance, temporal recency, a
|
|
|
253
332
|
include_staging: z.boolean().optional().default(false).describe('Include weak/unconfirmed memories?'),
|
|
254
333
|
use_reranker: z.boolean().optional().default(true).describe('Use cross-encoder re-ranking for better relevance (default true)'),
|
|
255
334
|
use_expansion: z.boolean().optional().default(true).describe('Expand query with synonyms for better recall (default true)'),
|
|
335
|
+
memory_type: z.enum(['episodic', 'semantic', 'procedural']).optional().describe('Filter by memory type (omit to search all types)'),
|
|
256
336
|
}, async (params) => {
|
|
257
337
|
const queryText = params.query ?? params.context;
|
|
258
338
|
if (!queryText) {
|
|
@@ -271,6 +351,7 @@ Returns the most relevant memories ranked by text relevance, temporal recency, a
|
|
|
271
351
|
includeStaging: params.include_staging,
|
|
272
352
|
useReranker: params.use_reranker,
|
|
273
353
|
useExpansion: params.use_expansion,
|
|
354
|
+
memoryType: params.memory_type,
|
|
274
355
|
});
|
|
275
356
|
// Auto-checkpoint: track recall
|
|
276
357
|
try {
|
|
@@ -279,11 +360,15 @@ Returns the most relevant memories ranked by text relevance, temporal recency, a
|
|
|
279
360
|
}
|
|
280
361
|
catch { /* non-fatal */ }
|
|
281
362
|
log(AGENT_ID, 'recall', `"${queryText.slice(0, 80)}" → ${results.length} results`);
|
|
363
|
+
// Peer decisions: append recent decisions by other agents relevant to this query
|
|
364
|
+
const peerSuffix = coordDb
|
|
365
|
+
? formatPeerDecisions(queryPeerDecisions(coordDb, AGENT_ID, queryText))
|
|
366
|
+
: '';
|
|
282
367
|
if (results.length === 0) {
|
|
283
368
|
return {
|
|
284
369
|
content: [{
|
|
285
370
|
type: 'text',
|
|
286
|
-
text: 'No relevant memories found.',
|
|
371
|
+
text: 'No relevant memories found.' + peerSuffix,
|
|
287
372
|
}],
|
|
288
373
|
};
|
|
289
374
|
}
|
|
@@ -293,7 +378,7 @@ Returns the most relevant memories ranked by text relevance, temporal recency, a
|
|
|
293
378
|
return {
|
|
294
379
|
content: [{
|
|
295
380
|
type: 'text',
|
|
296
|
-
text: lines.join('\n'),
|
|
381
|
+
text: lines.join('\n') + peerSuffix,
|
|
297
382
|
}],
|
|
298
383
|
};
|
|
299
384
|
});
|
|
@@ -558,6 +643,23 @@ Use this at the start of every session or after compaction to pick up where you
|
|
|
558
643
|
parts.push(`- **${m.concept}** (${m.score.toFixed(3)}): ${m.content.slice(0, 150)}${m.content.length > 150 ? '...' : ''}`);
|
|
559
644
|
}
|
|
560
645
|
}
|
|
646
|
+
// Peer decisions: show recent decisions from other agents (last 30 min)
|
|
647
|
+
if (coordDb) {
|
|
648
|
+
try {
|
|
649
|
+
const myAgent = coordDb.prepare(`SELECT id FROM coord_agents WHERE name = ? AND status != 'dead' ORDER BY last_seen DESC LIMIT 1`).get(AGENT_ID);
|
|
650
|
+
const peerDecisions = coordDb.prepare(`SELECT d.summary, a.name AS author_name, d.created_at
|
|
651
|
+
FROM coord_decisions d JOIN coord_agents a ON d.author_id = a.id
|
|
652
|
+
WHERE d.author_id != ? AND d.created_at > datetime('now', '-30 minutes')
|
|
653
|
+
ORDER BY d.created_at DESC LIMIT 10`).all(myAgent?.id ?? '');
|
|
654
|
+
if (peerDecisions.length > 0) {
|
|
655
|
+
parts.push(`\n**Peer decisions (last 30 min):**`);
|
|
656
|
+
for (const d of peerDecisions) {
|
|
657
|
+
parts.push(`- [${d.author_name}] ${d.summary} (${d.created_at})`);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
catch { /* peer decisions are non-fatal */ }
|
|
662
|
+
}
|
|
561
663
|
return {
|
|
562
664
|
content: [{
|
|
563
665
|
type: 'text',
|
|
@@ -851,6 +953,7 @@ This captures what was accomplished so future sessions can recall it.`, {
|
|
|
851
953
|
const { registerCoordinationTools } = await import('./coordination/mcp-tools.js');
|
|
852
954
|
initCoordinationTables(store.getDb());
|
|
853
955
|
registerCoordinationTools(server, store.getDb());
|
|
956
|
+
coordDb = store.getDb();
|
|
854
957
|
}
|
|
855
958
|
else {
|
|
856
959
|
console.error('AWM: coordination tools disabled (set AWM_COORDINATION=true to enable)');
|
|
@@ -863,6 +966,10 @@ This captures what was accomplished so future sessions can recall it.`, {
|
|
|
863
966
|
sidecar.close();
|
|
864
967
|
consolidationScheduler.stop();
|
|
865
968
|
stagingBuffer.stop();
|
|
969
|
+
try {
|
|
970
|
+
store.walCheckpoint();
|
|
971
|
+
}
|
|
972
|
+
catch { /* non-fatal */ }
|
|
866
973
|
store.close();
|
|
867
974
|
};
|
|
868
975
|
process.on('SIGINT', () => { cleanup(); process.exit(0); });
|