agent-working-memory 0.5.6 → 0.6.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/README.md +73 -44
- 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 +401 -1
- package/dist/cli.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/routes.d.ts.map +1 -1
- package/dist/coordination/routes.js +155 -16
- package/dist/coordination/routes.js.map +1 -1
- package/dist/coordination/schema.d.ts.map +1 -1
- package/dist/coordination/schema.js +35 -1
- package/dist/coordination/schema.js.map +1 -1
- package/dist/coordination/schemas.d.ts +21 -2
- package/dist/coordination/schemas.d.ts.map +1 -1
- package/dist/coordination/schemas.js +16 -0
- 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 +5 -0
- package/dist/coordination/stale.js.map +1 -1
- package/dist/engine/activation.d.ts.map +1 -1
- package/dist/engine/activation.js +119 -23
- package/dist/engine/activation.js.map +1 -1
- package/dist/engine/consolidation.d.ts.map +1 -1
- package/dist/engine/consolidation.js +27 -6
- package/dist/engine/consolidation.js.map +1 -1
- package/dist/index.js +81 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +61 -3
- package/dist/mcp.js.map +1 -1
- package/dist/storage/sqlite.d.ts +18 -0
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +50 -5
- 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/api/routes.ts +50 -1
- package/src/cli.ts +454 -1
- package/src/coordination/mcp-tools.ts +10 -5
- package/src/coordination/routes.ts +209 -19
- package/src/coordination/schema.ts +27 -1
- package/src/coordination/schemas.ts +19 -0
- package/src/coordination/stale.ts +8 -0
- package/src/engine/activation.ts +125 -23
- package/src/engine/consolidation.ts +29 -6
- package/src/index.ts +74 -3
- package/src/mcp.ts +72 -3
- package/src/storage/sqlite.ts +54 -5
- package/src/types/engram.ts +28 -0
package/src/storage/sqlite.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { randomUUID } from 'node:crypto';
|
|
|
12
12
|
import type {
|
|
13
13
|
Engram, EngramCreate, EngramStage, Association, AssociationType,
|
|
14
14
|
SearchQuery, SalienceFeatures, ActivationEvent, StagingEvent,
|
|
15
|
-
RetrievalFeedbackEvent, Episode, TaskStatus, TaskPriority, MemoryClass,
|
|
15
|
+
RetrievalFeedbackEvent, Episode, TaskStatus, TaskPriority, MemoryClass, MemoryType,
|
|
16
16
|
ConsciousState, AutoCheckpoint, CheckpointRow,
|
|
17
17
|
} from '../types/index.js';
|
|
18
18
|
|
|
@@ -35,6 +35,8 @@ export class EngramStore {
|
|
|
35
35
|
this.db = new Database(dbPath);
|
|
36
36
|
this.db.pragma('journal_mode = WAL');
|
|
37
37
|
this.db.pragma('foreign_keys = ON');
|
|
38
|
+
this.db.pragma('busy_timeout = 5000');
|
|
39
|
+
this.db.pragma('synchronous = NORMAL');
|
|
38
40
|
this.init();
|
|
39
41
|
}
|
|
40
42
|
|
|
@@ -43,6 +45,27 @@ export class EngramStore {
|
|
|
43
45
|
return this.db;
|
|
44
46
|
}
|
|
45
47
|
|
|
48
|
+
/** Run PRAGMA quick_check and return true if DB is healthy. */
|
|
49
|
+
integrityCheck(): { ok: boolean; result: string } {
|
|
50
|
+
try {
|
|
51
|
+
const rows = this.db.pragma('quick_check') as Array<{ quick_check: string }>;
|
|
52
|
+
const result = rows[0]?.quick_check ?? 'unknown';
|
|
53
|
+
return { ok: result === 'ok', result };
|
|
54
|
+
} catch (err) {
|
|
55
|
+
return { ok: false, result: (err as Error).message };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Hot backup using SQLite backup API. Returns the backup path. */
|
|
60
|
+
backup(destPath: string): void {
|
|
61
|
+
this.db.backup(destPath);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Flush WAL to main database file. */
|
|
65
|
+
walCheckpoint(): void {
|
|
66
|
+
this.db.pragma('wal_checkpoint(TRUNCATE)');
|
|
67
|
+
}
|
|
68
|
+
|
|
46
69
|
private init(): void {
|
|
47
70
|
this.db.exec(`
|
|
48
71
|
CREATE TABLE IF NOT EXISTS engrams (
|
|
@@ -63,7 +86,8 @@ export class EngramStore {
|
|
|
63
86
|
retracted INTEGER NOT NULL DEFAULT 0,
|
|
64
87
|
retracted_by TEXT,
|
|
65
88
|
retracted_at TEXT,
|
|
66
|
-
tags TEXT NOT NULL DEFAULT '[]'
|
|
89
|
+
tags TEXT NOT NULL DEFAULT '[]',
|
|
90
|
+
memory_type TEXT NOT NULL DEFAULT 'unclassified'
|
|
67
91
|
);
|
|
68
92
|
|
|
69
93
|
CREATE INDEX IF NOT EXISTS idx_engrams_agent ON engrams(agent_id);
|
|
@@ -211,6 +235,13 @@ export class EngramStore {
|
|
|
211
235
|
try {
|
|
212
236
|
this.db.exec(`ALTER TABLE conscious_state ADD COLUMN consolidation_cycle_count INTEGER NOT NULL DEFAULT 0`);
|
|
213
237
|
} catch { /* column already exists */ }
|
|
238
|
+
|
|
239
|
+
// Migration: add memory_type column if missing
|
|
240
|
+
try {
|
|
241
|
+
this.db.prepare('SELECT memory_type FROM engrams LIMIT 0').get();
|
|
242
|
+
} catch {
|
|
243
|
+
this.db.exec(`ALTER TABLE engrams ADD COLUMN memory_type TEXT NOT NULL DEFAULT 'unclassified'`);
|
|
244
|
+
}
|
|
214
245
|
}
|
|
215
246
|
|
|
216
247
|
// --- Engram CRUD ---
|
|
@@ -225,8 +256,8 @@ export class EngramStore {
|
|
|
225
256
|
this.db.prepare(`
|
|
226
257
|
INSERT INTO engrams (id, agent_id, concept, content, embedding, confidence, salience,
|
|
227
258
|
access_count, last_accessed, created_at, salience_features, reason_codes, stage, tags, episode_id,
|
|
228
|
-
ttl, memory_class, supersedes, task_status, task_priority, blocked_by)
|
|
229
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, 0, ?, ?, ?, ?, 'active', ?, ?, ?, ?, ?, ?, ?, ?)
|
|
259
|
+
ttl, memory_class, supersedes, task_status, task_priority, blocked_by, memory_type)
|
|
260
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, 0, ?, ?, ?, ?, 'active', ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
230
261
|
`).run(
|
|
231
262
|
id, input.agentId, input.concept, input.content, embeddingBlob,
|
|
232
263
|
input.confidence ?? 0.5,
|
|
@@ -242,6 +273,7 @@ export class EngramStore {
|
|
|
242
273
|
input.taskStatus ?? null,
|
|
243
274
|
input.taskPriority ?? null,
|
|
244
275
|
input.blockedBy ?? null,
|
|
276
|
+
input.memoryType ?? 'unclassified',
|
|
245
277
|
);
|
|
246
278
|
|
|
247
279
|
return this.getEngram(id)!;
|
|
@@ -267,9 +299,21 @@ export class EngramStore {
|
|
|
267
299
|
return (this.db.prepare(query).all(...params) as any[]).map(r => this.rowToEngram(r));
|
|
268
300
|
}
|
|
269
301
|
|
|
302
|
+
/**
|
|
303
|
+
* Touch an engram: increment access count, update last_accessed, and
|
|
304
|
+
* nudge confidence upward. Each retrieval is weak evidence the memory
|
|
305
|
+
* is useful — bounded so only explicit feedback can push confidence
|
|
306
|
+
* above 0.85. Diminishing returns: first accesses matter most.
|
|
307
|
+
*
|
|
308
|
+
* Boost: +0.02 per access, scaled by 1/sqrt(accessCount+1), capped at 0.85.
|
|
309
|
+
*/
|
|
270
310
|
touchEngram(id: string): void {
|
|
271
311
|
this.db.prepare(`
|
|
272
|
-
UPDATE engrams
|
|
312
|
+
UPDATE engrams
|
|
313
|
+
SET access_count = access_count + 1,
|
|
314
|
+
last_accessed = ?,
|
|
315
|
+
confidence = MIN(0.85, confidence + 0.02 / (1.0 + sqrt(access_count)))
|
|
316
|
+
WHERE id = ?
|
|
273
317
|
`).run(new Date().toISOString(), id);
|
|
274
318
|
}
|
|
275
319
|
|
|
@@ -502,6 +546,10 @@ export class EngramStore {
|
|
|
502
546
|
this.db.prepare('UPDATE engrams SET memory_class = ? WHERE id = ?').run(memoryClass, id);
|
|
503
547
|
}
|
|
504
548
|
|
|
549
|
+
updateTags(id: string, tags: string[]): void {
|
|
550
|
+
this.db.prepare('UPDATE engrams SET tags = ? WHERE id = ?').run(JSON.stringify(tags), id);
|
|
551
|
+
}
|
|
552
|
+
|
|
505
553
|
// --- Associations ---
|
|
506
554
|
|
|
507
555
|
upsertAssociation(
|
|
@@ -722,6 +770,7 @@ export class EngramStore {
|
|
|
722
770
|
tags: JSON.parse(row.tags),
|
|
723
771
|
episodeId: row.episode_id ?? null,
|
|
724
772
|
memoryClass: (row.memory_class ?? 'working') as MemoryClass,
|
|
773
|
+
memoryType: (row.memory_type ?? 'unclassified') as MemoryType,
|
|
725
774
|
supersededBy: row.superseded_by ?? null,
|
|
726
775
|
supersedes: row.supersedes ?? null,
|
|
727
776
|
taskStatus: row.task_status ?? null,
|
package/src/types/engram.ts
CHANGED
|
@@ -43,6 +43,9 @@ export interface Engram {
|
|
|
43
43
|
// Memory class
|
|
44
44
|
memoryClass: MemoryClass;
|
|
45
45
|
|
|
46
|
+
// Memory type (content classification)
|
|
47
|
+
memoryType: MemoryType;
|
|
48
|
+
|
|
46
49
|
// Supersession — "this replaces that" (not retraction — original wasn't wrong, just outdated)
|
|
47
50
|
supersededBy: string | null; // ID of the engram that replaced this one
|
|
48
51
|
supersedes: string | null; // ID of the engram this one replaces
|
|
@@ -70,6 +73,16 @@ export type TaskPriority = 'urgent' | 'high' | 'medium' | 'low';
|
|
|
70
73
|
*/
|
|
71
74
|
export type MemoryClass = 'canonical' | 'working' | 'ephemeral';
|
|
72
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Memory type — content classification for retrieval routing.
|
|
78
|
+
*
|
|
79
|
+
* episodic: Events, incidents, debugging sessions ("we did X because Y").
|
|
80
|
+
* semantic: Facts, decisions, patterns ("X is true", "we use Y for Z").
|
|
81
|
+
* procedural: How-to, steps, processes ("to deploy, run X then Y").
|
|
82
|
+
* unclassified: Default for backwards compatibility.
|
|
83
|
+
*/
|
|
84
|
+
export type MemoryType = 'episodic' | 'semantic' | 'procedural' | 'unclassified';
|
|
85
|
+
|
|
73
86
|
/**
|
|
74
87
|
* Raw feature scores that produced the salience score.
|
|
75
88
|
* Persisted for auditability and tuning.
|
|
@@ -95,6 +108,7 @@ export interface EngramCreate {
|
|
|
95
108
|
episodeId?: string;
|
|
96
109
|
ttl?: number;
|
|
97
110
|
memoryClass?: MemoryClass;
|
|
111
|
+
memoryType?: MemoryType;
|
|
98
112
|
supersedes?: string;
|
|
99
113
|
taskStatus?: TaskStatus;
|
|
100
114
|
taskPriority?: TaskPriority;
|
|
@@ -147,6 +161,18 @@ export interface PhaseScores {
|
|
|
147
161
|
rerankerScore: number; // Cross-encoder relevance (0-1), 0 if reranker disabled
|
|
148
162
|
}
|
|
149
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Query mode — controls how the activation pipeline weights its signals.
|
|
166
|
+
*
|
|
167
|
+
* targeted: Query has identifiers, ticket IDs, specific names. Boost BM25,
|
|
168
|
+
* narrow graph beam, stronger decay, stricter vector z-gate.
|
|
169
|
+
* exploratory: Vague/conceptual query. Boost vector/semantic signals, wider
|
|
170
|
+
* graph beam, weaker decay, relaxed z-gate.
|
|
171
|
+
* balanced: Default weights (current behavior).
|
|
172
|
+
* auto: Classify automatically based on query characteristics.
|
|
173
|
+
*/
|
|
174
|
+
export type QueryMode = 'targeted' | 'exploratory' | 'balanced' | 'auto';
|
|
175
|
+
|
|
150
176
|
export interface ActivationQuery {
|
|
151
177
|
agentId: string;
|
|
152
178
|
context: string;
|
|
@@ -158,6 +184,8 @@ export interface ActivationQuery {
|
|
|
158
184
|
useExpansion?: boolean; // Enable query expansion (default: true)
|
|
159
185
|
abstentionThreshold?: number; // Min reranker score to return results (default: 0)
|
|
160
186
|
internal?: boolean; // Skip access count increment, Hebbian update, and event logging (for system calls)
|
|
187
|
+
memoryType?: MemoryType; // Filter by memory type (episodic, semantic, procedural)
|
|
188
|
+
mode?: QueryMode; // Pipeline mode — 'auto' by default
|
|
161
189
|
}
|
|
162
190
|
|
|
163
191
|
/**
|