agent-working-memory 0.11.0 → 0.12.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 +29 -0
- package/dist/adapters/claude-code.d.ts.map +1 -1
- package/dist/adapters/claude-code.js +63 -3
- package/dist/adapters/claude-code.js.map +1 -1
- package/dist/adapters/common.d.ts.map +1 -1
- package/dist/adapters/common.js +329 -306
- package/dist/adapters/common.js.map +1 -1
- package/dist/api/routes.d.ts.map +1 -1
- package/dist/api/routes.js +29 -7
- package/dist/api/routes.js.map +1 -1
- package/dist/coordination/routes.d.ts.map +1 -1
- package/dist/coordination/routes.js +174 -170
- package/dist/coordination/routes.js.map +1 -1
- package/dist/core/embeddings.d.ts.map +1 -1
- package/dist/core/embeddings.js +3 -0
- package/dist/core/embeddings.js.map +1 -1
- package/dist/core/entity-extract.d.ts +3 -0
- package/dist/core/entity-extract.d.ts.map +1 -0
- package/dist/core/entity-extract.js +47 -0
- package/dist/core/entity-extract.js.map +1 -0
- package/dist/core/salience.d.ts.map +1 -1
- package/dist/core/salience.js +14 -2
- package/dist/core/salience.js.map +1 -1
- package/dist/core/whoami.d.ts +24 -0
- package/dist/core/whoami.d.ts.map +1 -0
- package/dist/core/whoami.js +66 -0
- package/dist/core/whoami.js.map +1 -0
- package/dist/core/write-pipeline.d.ts +9 -0
- package/dist/core/write-pipeline.d.ts.map +1 -1
- package/dist/core/write-pipeline.js +109 -68
- package/dist/core/write-pipeline.js.map +1 -1
- package/dist/core/write-telemetry.d.ts +33 -0
- package/dist/core/write-telemetry.d.ts.map +1 -0
- package/dist/core/write-telemetry.js +110 -0
- package/dist/core/write-telemetry.js.map +1 -0
- package/dist/engine/activation.d.ts +22 -12
- package/dist/engine/activation.d.ts.map +1 -1
- package/dist/engine/activation.js +133 -17
- package/dist/engine/activation.js.map +1 -1
- package/dist/engine/consolidation-scheduler.d.ts +1 -1
- package/dist/engine/consolidation-scheduler.js +1 -1
- package/dist/engine/consolidation.d.ts +1 -0
- package/dist/engine/consolidation.d.ts.map +1 -1
- package/dist/engine/consolidation.js +18 -0
- package/dist/engine/consolidation.js.map +1 -1
- package/dist/engine/eval.d.ts.map +1 -1
- package/dist/engine/eval.js +5 -1
- package/dist/engine/eval.js.map +1 -1
- package/dist/index.js +20 -2
- package/dist/index.js.map +1 -1
- package/dist/mcp.d.ts +2 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +168 -100
- package/dist/mcp.js.map +1 -1
- package/dist/recipes/index.d.ts +57 -0
- package/dist/recipes/index.d.ts.map +1 -0
- package/dist/recipes/index.js +81 -0
- package/dist/recipes/index.js.map +1 -0
- package/dist/storage/pglite-schema.d.ts.map +1 -1
- package/dist/storage/pglite-schema.js +27 -0
- package/dist/storage/pglite-schema.js.map +1 -1
- package/dist/storage/pglite.d.ts +5 -0
- package/dist/storage/pglite.d.ts.map +1 -1
- package/dist/storage/pglite.js +180 -138
- package/dist/storage/pglite.js.map +1 -1
- package/dist/storage/postgres.d.ts +5 -0
- package/dist/storage/postgres.d.ts.map +1 -1
- package/dist/storage/postgres.js +180 -138
- package/dist/storage/postgres.js.map +1 -1
- package/dist/storage/sqlite.d.ts +9 -0
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +394 -326
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/types/engram.d.ts +14 -0
- package/dist/types/engram.d.ts.map +1 -1
- package/dist/types/engram.js.map +1 -1
- package/package.json +1 -1
- package/src/adapters/claude-code.ts +66 -3
- package/src/adapters/common.ts +538 -515
- package/src/api/routes.ts +999 -971
- package/src/coordination/routes.ts +2155 -2150
- package/src/core/embeddings.ts +3 -0
- package/src/core/entity-extract.ts +47 -0
- package/src/core/salience.ts +529 -514
- package/src/core/whoami.ts +92 -0
- package/src/core/write-pipeline.ts +60 -8
- package/src/core/write-telemetry.ts +131 -0
- package/src/engine/activation.ts +1468 -1369
- package/src/engine/consolidation-scheduler.ts +1 -1
- package/src/engine/consolidation.ts +887 -869
- package/src/engine/eval.ts +6 -1
- package/src/index.ts +248 -227
- package/src/mcp.ts +1341 -1270
- package/src/recipes/index.ts +125 -0
- package/src/storage/pglite-schema.ts +27 -0
- package/src/storage/pglite.ts +1420 -1372
- package/src/storage/postgres.ts +1523 -1475
- package/src/storage/sqlite.ts +1936 -1861
- package/src/types/engram.ts +22 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// Copyright 2026 Robert Winter / Complete Ideas
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Cognition Recipes — the intelligence interface (D14, 2026-07-30).
|
|
6
|
+
*
|
|
7
|
+
* AWM is a memory space for an LLM, not containing an LLM. Anything that
|
|
8
|
+
* requires real thinking (distilling a procedure, reflecting on a failure)
|
|
9
|
+
* runs HOST-SIDE: AWM ships a versioned recipe — a prompt plus a strict
|
|
10
|
+
* output contract — the host agent executes it as a SEPARATE focused call,
|
|
11
|
+
* and writes the result back as an ordinary memory carrying provenance
|
|
12
|
+
* (origin_class='recipe', recipe_id). AWM validates the write-back shape.
|
|
13
|
+
*
|
|
14
|
+
* Ported from memory-working-agent (MWA #14, live since 2026-06-15), whose
|
|
15
|
+
* production lessons are baked in:
|
|
16
|
+
* - SEPARATE focused call: cheap models reliably omit a "skill" field when
|
|
17
|
+
* it is bundled with other questions. One recipe = one call.
|
|
18
|
+
* - Host-side gating: only the host knows whether a task was procedural
|
|
19
|
+
* (tool calls, dispatches). The invitation states the gate; the host
|
|
20
|
+
* decides.
|
|
21
|
+
* - Dedupe by concept: writing the same skill name reinforces the existing
|
|
22
|
+
* memory (the R1 write-pipeline rule) instead of piling up copies.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export interface RecipeValidation {
|
|
26
|
+
ok: boolean;
|
|
27
|
+
errors: string[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface CognitionRecipe {
|
|
31
|
+
/** Stable id including version, e.g. 'skill-derivation@1'. */
|
|
32
|
+
id: string;
|
|
33
|
+
title: string;
|
|
34
|
+
/** When the HOST should run this (the host owns the gate). */
|
|
35
|
+
gate: string;
|
|
36
|
+
/** The system prompt for the host's separate focused call. */
|
|
37
|
+
prompt: string;
|
|
38
|
+
/** Human-readable description of the required JSON output. */
|
|
39
|
+
output: string;
|
|
40
|
+
/** How the host must write the result back to AWM. */
|
|
41
|
+
writeBack: string;
|
|
42
|
+
/** Validate a write-back's concept/content shape. */
|
|
43
|
+
validate(concept: string, content: string): RecipeValidation;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function slugify(name: string): string {
|
|
47
|
+
return name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '').slice(0, 40);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const SKILL_DERIVATION: CognitionRecipe = {
|
|
51
|
+
id: 'skill-derivation@1',
|
|
52
|
+
title: 'Derive a reusable skill from a completed task',
|
|
53
|
+
gate: 'Run ONLY after a task that used tools/multiple steps (roughly: 3+ tool calls or a delegated sub-task). Skip trivial one-offs.',
|
|
54
|
+
prompt: 'A task was just completed using tools. If it followed a REPEATABLE procedure that would help on similar future requests, output ONLY JSON {"name":"short skill name (e.g. \'triage scouting inbox\')","steps":"numbered how-to a future run can follow"}. If it was a trivial one-off, output exactly {}.',
|
|
55
|
+
output: '{"name": string, "steps": string-with-numbered-lines} or {} when nothing repeatable was learned.',
|
|
56
|
+
writeBack: "memory_write with concept: 'skill: <name>', content: <steps>, origin_class: 'recipe', recipe_id: 'skill-derivation@1', memory_class: 'canonical', memory_type: 'procedural', tags: ['topic=skill', 'skill=<slug>'].",
|
|
57
|
+
validate(concept: string, content: string): RecipeValidation {
|
|
58
|
+
const errors: string[] = [];
|
|
59
|
+
if (!/^skill:\s*\S/.test(concept)) errors.push("concept must start with 'skill: <name>'");
|
|
60
|
+
if (!content || content.trim().length < 20) errors.push('steps content too short to be a usable procedure');
|
|
61
|
+
if (!/(^|\n)\s*(\d+[.)]|[-*])\s+/.test(content)) errors.push('content must contain numbered or bulleted steps');
|
|
62
|
+
return { ok: errors.length === 0, errors };
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const FRICTION_LESSON: CognitionRecipe = {
|
|
67
|
+
id: 'friction-lesson@1',
|
|
68
|
+
title: 'Record a failure lesson (Reflexion) from a task that went wrong',
|
|
69
|
+
gate: 'Run ONLY after a task that failed, required a retry/revert, or surfaced a wrong assumption.',
|
|
70
|
+
prompt: 'A task just hit a failure, retry, or wrong assumption. Output ONLY JSON {"topic":"short subject of the lesson","lesson":"what went wrong and the rule to apply next time (include the WHY)"}. If nothing generalizable was learned, output exactly {}.',
|
|
71
|
+
output: '{"topic": string, "lesson": string} or {} when nothing generalizable was learned.',
|
|
72
|
+
writeBack: "memory_write with concept: 'lesson: <topic>', content: <lesson>, origin_class: 'recipe', recipe_id: 'friction-lesson@1', memory_class: 'canonical', event_type: 'friction', tags: ['topic=friction', 'about=<slug>'].",
|
|
73
|
+
validate(concept: string, content: string): RecipeValidation {
|
|
74
|
+
const errors: string[] = [];
|
|
75
|
+
if (!/^lesson:\s*\S/.test(concept)) errors.push("concept must start with 'lesson: <topic>'");
|
|
76
|
+
if (!content || content.trim().length < 20) errors.push('lesson content too short to be applicable');
|
|
77
|
+
return { ok: errors.length === 0, errors };
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const REGISTRY: Record<string, CognitionRecipe> = {
|
|
82
|
+
[SKILL_DERIVATION.id]: SKILL_DERIVATION,
|
|
83
|
+
[FRICTION_LESSON.id]: FRICTION_LESSON,
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export function getRecipe(id: string): CognitionRecipe | null {
|
|
87
|
+
return REGISTRY[id] ?? null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function listRecipes(): CognitionRecipe[] {
|
|
91
|
+
return Object.values(REGISTRY);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Validate a recipe-attributed write. Unknown recipe ids are rejected —
|
|
96
|
+
* provenance must never claim a recipe that does not exist.
|
|
97
|
+
*/
|
|
98
|
+
export function validateRecipeWrite(recipeId: string, concept: string, content: string): RecipeValidation {
|
|
99
|
+
const recipe = getRecipe(recipeId);
|
|
100
|
+
if (!recipe) return { ok: false, errors: [`unknown recipe id '${recipeId}' — known: ${Object.keys(REGISTRY).join(', ')}`] };
|
|
101
|
+
return recipe.validate(concept, content);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Derive the standard skill/lesson slug tag value from a concept. */
|
|
105
|
+
export function recipeSlug(concept: string): string {
|
|
106
|
+
return slugify(concept.replace(/^(skill|lesson):\s*/i, ''));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The invitation appended to memory_task_end responses. Kept compact — it is
|
|
111
|
+
* read by an LLM in-band. The host runs the recipe as its OWN next step
|
|
112
|
+
* (separate focused call) and writes back via ordinary memory_write.
|
|
113
|
+
*/
|
|
114
|
+
export function renderTaskEndInvitation(): string {
|
|
115
|
+
return [
|
|
116
|
+
'',
|
|
117
|
+
'COGNITION RECIPES (host-side — you do the thinking, one SEPARATE focused pass each):',
|
|
118
|
+
`1. ${SKILL_DERIVATION.title}. Gate: ${SKILL_DERIVATION.gate}`,
|
|
119
|
+
` Think: ${SKILL_DERIVATION.prompt}`,
|
|
120
|
+
` If non-empty, write back: ${SKILL_DERIVATION.writeBack}`,
|
|
121
|
+
`2. ${FRICTION_LESSON.title}. Gate: ${FRICTION_LESSON.gate}`,
|
|
122
|
+
` Think: ${FRICTION_LESSON.prompt}`,
|
|
123
|
+
` If non-empty, write back: ${FRICTION_LESSON.writeBack}`,
|
|
124
|
+
].join('\n');
|
|
125
|
+
}
|
|
@@ -53,9 +53,22 @@ export const PGLITE_SCHEMA_DDL = `
|
|
|
53
53
|
blocked_by TEXT,
|
|
54
54
|
sequence INTEGER,
|
|
55
55
|
references_json TEXT,
|
|
56
|
+
origin_class TEXT,
|
|
57
|
+
writer_session TEXT,
|
|
58
|
+
recipe_id TEXT,
|
|
59
|
+
valid_from TEXT,
|
|
60
|
+
valid_to TEXT,
|
|
56
61
|
fts TSVECTOR
|
|
57
62
|
);
|
|
58
63
|
|
|
64
|
+
-- Memory-spine migration (D5/D8, 2026-07-30): idempotent column adds so
|
|
65
|
+
-- pre-existing stores gain provenance + temporal-validity fields.
|
|
66
|
+
ALTER TABLE engrams ADD COLUMN IF NOT EXISTS origin_class TEXT;
|
|
67
|
+
ALTER TABLE engrams ADD COLUMN IF NOT EXISTS writer_session TEXT;
|
|
68
|
+
ALTER TABLE engrams ADD COLUMN IF NOT EXISTS recipe_id TEXT;
|
|
69
|
+
ALTER TABLE engrams ADD COLUMN IF NOT EXISTS valid_from TEXT;
|
|
70
|
+
ALTER TABLE engrams ADD COLUMN IF NOT EXISTS valid_to TEXT;
|
|
71
|
+
|
|
59
72
|
CREATE INDEX IF NOT EXISTS idx_engrams_agent ON engrams(agent_id);
|
|
60
73
|
CREATE INDEX IF NOT EXISTS idx_engrams_stage ON engrams(agent_id, stage);
|
|
61
74
|
CREATE INDEX IF NOT EXISTS idx_engrams_concept ON engrams(concept);
|
|
@@ -163,4 +176,18 @@ export const PGLITE_SCHEMA_DDL = `
|
|
|
163
176
|
consolidation_cycle_count INTEGER NOT NULL DEFAULT 0,
|
|
164
177
|
updated_at TEXT NOT NULL DEFAULT (to_char(now() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"'))
|
|
165
178
|
);
|
|
179
|
+
|
|
180
|
+
CREATE TABLE IF NOT EXISTS entity_mentions (
|
|
181
|
+
entity TEXT NOT NULL,
|
|
182
|
+
engram_id TEXT NOT NULL,
|
|
183
|
+
agent_id TEXT NOT NULL,
|
|
184
|
+
PRIMARY KEY (entity, engram_id)
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
CREATE INDEX IF NOT EXISTS idx_entity_mentions_agent ON entity_mentions(agent_id, entity);
|
|
188
|
+
|
|
189
|
+
CREATE TABLE IF NOT EXISTS entity_aliases (
|
|
190
|
+
alias TEXT PRIMARY KEY,
|
|
191
|
+
entity TEXT NOT NULL
|
|
192
|
+
);
|
|
166
193
|
`;
|