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
package/README.md
CHANGED
|
@@ -65,7 +65,7 @@ Most "memory for AI" projects are vector databases with a retrieval wrapper. AWM
|
|
|
65
65
|
| **Over time** | Grows forever, gets noisier | Consolidation: diameter-enforced clustering, cross-topic bridges, synaptic-tagged decay |
|
|
66
66
|
| **Forgetting** | Manual cleanup | Cognitive forgetting: unused memories fade, reinforced knowledge persists (access-count modulated) |
|
|
67
67
|
| **Feedback** | None | Useful/not-useful signals tune confidence and retrieval rank |
|
|
68
|
-
| **Correction** | Delete and re-insert | Retraction: wrong memories invalidated, corrections linked, penalties propagate |
|
|
68
|
+
| **Correction** | Delete and re-insert | Retraction: wrong memories invalidated, corrections linked, penalties propagate (depth 2, decaying) |
|
|
69
69
|
| **Noise rejection** | None | Multi-channel agreement gate: requires 2+ retrieval channels to agree before returning results |
|
|
70
70
|
| **Duplicates** | Stored repeatedly | Reinforce-on-duplicate: near-exact matches boost existing memory instead of creating copies |
|
|
71
71
|
|
|
@@ -73,31 +73,49 @@ The design is based on cognitive science — ACT-R activation decay, Hebbian lea
|
|
|
73
73
|
|
|
74
74
|
---
|
|
75
75
|
|
|
76
|
-
## Benchmarks (v0.
|
|
76
|
+
## Benchmarks (v0.6.0)
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
|------|-------|---------------|
|
|
80
|
-
| Edge Cases | **100% (34/34)** | 9 failure modes: context collapse, hub toxicity, flashbulb distortion, narcissistic interference, identity collision, contradiction trapping, bridge overshoot, noise forgetting |
|
|
81
|
-
| Stress Test | **96.2% (50/52)** | 500 memories, 100 sleep cycles, 10 topic clusters, 20 bridges/cycle, catastrophic forgetting, adversarial spam, recovery |
|
|
82
|
-
| Workday | **93.3%** | 43 memories across 4 simulated work sessions, knowledge transfer, context switching, cross-cutting queries, noise filtering |
|
|
83
|
-
| A/B Test | **AWM 85% vs Baseline 83%** | 100 project events, 24 recall questions, 22/22 fact recall |
|
|
84
|
-
| Sleep Cycle | **85.7% pre-sleep** | 60 memories, 4 topic clusters, consolidation impact measurement |
|
|
85
|
-
| Token Savings | **67.5% accuracy, 55% savings** | Memory-guided context vs full conversation history, 2.2x efficiency |
|
|
86
|
-
| LoCoMo | **28.2%** | Industry-standard conversational memory benchmark (1,986 QA pairs, 10 conversations) |
|
|
87
|
-
| Mini Multi-Hop | **80% (4/5)** | Entity bridging across conversation turns |
|
|
78
|
+
### Eval Harness (new in v0.6.0)
|
|
88
79
|
|
|
89
|
-
|
|
80
|
+
| Suite | Score | Threshold | What it tests |
|
|
81
|
+
|-------|-------|-----------|---------------|
|
|
82
|
+
| Retrieval | **Recall@5 = 0.800** | >= 0.80 | 200 facts, 50 queries — BM25 + vector + reranker pipeline precision |
|
|
83
|
+
| Associative | **success@10 = 1.000** | >= 0.70 | 20 multi-hop causal chains — graph walk finds non-obvious connections |
|
|
84
|
+
| Redundancy | **dedup F1 = 0.966** | >= 0.80 | 50 clusters × 4 paraphrases — consolidation removes duplicates correctly |
|
|
85
|
+
| Temporal | **Spearman = 0.932** | >= 0.75 | 25 facts with controlled age/access — ACT-R decay ranking accuracy |
|
|
86
|
+
|
|
87
|
+
Key finding: **consolidation improves retrieval by 30%** — post-consolidation recall (0.950) exceeds pre-consolidation (0.650). Removing redundant noise helps ranking.
|
|
88
|
+
|
|
89
|
+
### Full Test Suite
|
|
90
|
+
|
|
91
|
+
| Command | Score | What it tests |
|
|
92
|
+
|---------|-------|---------------|
|
|
93
|
+
| `npm run eval` | **4/4 suites pass** | Retrieval, associative, redundancy, temporal benchmarks with ablation support |
|
|
94
|
+
| `npm run test:run` | **77/77 tests** | Unit tests: salience, decay, hebbian, supersession, coordination |
|
|
95
|
+
| `npm run test:mcp` | **5/5 pass** | MCP protocol: write, recall, feedback, retract, stats |
|
|
96
|
+
| `npm run test:self` | **94.1% EXCELLENT** | Pipeline component checks across all cognitive subsystems |
|
|
97
|
+
| `npm run test:edge` | **All pass** | 9 failure modes: narcissistic interference, identity collision, contradiction trapping, bridge overshoot, noise forgetting |
|
|
98
|
+
| `npm run test:stress` | **96.2% (50/52)** | 500 memories, 100 sleep cycles, catastrophic forgetting, adversarial spam, recovery |
|
|
99
|
+
| `npm run test:workday` | **93.3% EXCELLENT** | 43 memories across 4 projects, cross-cutting queries, noise filtering |
|
|
100
|
+
| `npm run test:ab` | **AWM 20/22 vs Baseline 18/22** | AWM outperforms keyword baseline on architecture + testing topics |
|
|
101
|
+
| `npm run test:sleep` | **71.4%** | 60 memories, 4 topic clusters, consolidation impact across 3 cycles |
|
|
102
|
+
| `npm run test:tokens` | **56.3% savings, 2.3x efficiency** | Memory-guided context vs full history, keyword accuracy 72.5% |
|
|
103
|
+
| `npm run test:pilot` | **14/15 pass** | Production-like queries with noise rejection (5/5 noise rejected) |
|
|
104
|
+
| `npm run test:locomo` | **28.2%** | Industry-standard LoCoMo conversational memory benchmark (1,986 QA pairs) |
|
|
105
|
+
|
|
106
|
+
### Consolidation Health (v0.6.0)
|
|
90
107
|
|
|
91
108
|
| Metric | Value |
|
|
92
109
|
|--------|-------|
|
|
93
110
|
| Topic clusters formed | **10** per consolidation cycle |
|
|
94
111
|
| Cross-topic bridges | **20** in first cycle |
|
|
95
|
-
| Edges strengthened | **
|
|
112
|
+
| Edges strengthened | **135** per cycle (access-weighted) |
|
|
96
113
|
| Graph size at scale | **3,000-4,500 edges** (500 memories) |
|
|
97
114
|
| Recall after 100 cycles | **90%** stable |
|
|
98
115
|
| Catastrophic forgetting survival | **5/5** (100%) |
|
|
116
|
+
| Post-dedup retrieval | **0.950** (consolidation improves recall) |
|
|
99
117
|
|
|
100
|
-
All evals are reproducible
|
|
118
|
+
All evals are reproducible. See [Testing & Evaluation](#testing--evaluation).
|
|
101
119
|
|
|
102
120
|
---
|
|
103
121
|
|
|
@@ -313,21 +331,34 @@ For detailed architecture including pipeline phases, database schema, and system
|
|
|
313
331
|
### Unit Tests
|
|
314
332
|
|
|
315
333
|
```bash
|
|
316
|
-
npx vitest run #
|
|
334
|
+
npx vitest run # 77 tests (salience, decay, hebbian, supersession)
|
|
317
335
|
```
|
|
318
336
|
|
|
319
|
-
### Eval
|
|
337
|
+
### Eval Harness (v0.6.0)
|
|
338
|
+
|
|
339
|
+
```bash
|
|
340
|
+
npm run eval # All 4 benchmark suites
|
|
341
|
+
npm run eval -- --suite=retrieval # Single suite
|
|
342
|
+
npm run eval -- --bm25-only # Ablation: BM25 only
|
|
343
|
+
npm run eval -- --no-graph-walk # Ablation: disable graph walk
|
|
344
|
+
```
|
|
320
345
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
346
|
+
Suites: retrieval (Recall@5), associative (multi-hop), redundancy (dedup F1), temporal (Spearman vs ACT-R). Ablation flags isolate each pipeline component's contribution.
|
|
347
|
+
|
|
348
|
+
### Full Test Suite
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
npm run test:mcp # MCP protocol smoke test (5/5)
|
|
352
|
+
npm run test:self # Pipeline component checks (94.1%)
|
|
353
|
+
npm run test:edge # 9 adversarial failure modes
|
|
354
|
+
npm run test:stress # 500 memories, 100 consolidation cycles (96.2%)
|
|
355
|
+
npm run test:workday # 4-session production simulation (93.3%)
|
|
356
|
+
npm run test:ab # AWM vs baseline comparison
|
|
357
|
+
npm run test:sleep # Consolidation impact measurement
|
|
358
|
+
npm run test:tokens # Token savings analysis (56.3% savings)
|
|
359
|
+
npm run test:pilot # Production-like query validation (14/15)
|
|
360
|
+
npm run test:locomo # LoCoMo industry benchmark (28.2%)
|
|
361
|
+
```
|
|
331
362
|
|
|
332
363
|
---
|
|
333
364
|
|
|
@@ -363,34 +394,38 @@ npx vitest run # 68 tests
|
|
|
363
394
|
|
|
364
395
|
All three ML models run locally via ONNX. No external API calls for retrieval. The entire system is a single SQLite file + a Node.js process.
|
|
365
396
|
|
|
366
|
-
## What's New in v0.
|
|
397
|
+
## What's New in v0.6.1
|
|
398
|
+
|
|
399
|
+
- **Embedding version tracking** — new `embedding_model` column prevents silent drift when changing models. Each embedding records its source model.
|
|
400
|
+
- **Batch embedding backfill** — consolidation uses `embedBatch()` (batch size 32) instead of single-item loop. 10x faster for large backfills.
|
|
401
|
+
- **Deeper retraction propagation** — confidence penalties now propagate 2 hops (was 1) with 50% decay per hop, capped at 20 affected nodes.
|
|
402
|
+
- **Retrieval timeouts** — 5s timeout on query expansion, 10s on cross-encoder reranker. Both fail gracefully to text-only signals.
|
|
403
|
+
- **Channel push delivery** — assignments delivered directly to worker HTTP endpoints with mailbox fallback.
|
|
404
|
+
- **Cross-UUID assignment migration** — resolves assignments across alternate agent UUIDs.
|
|
405
|
+
|
|
406
|
+
### v0.6.0
|
|
367
407
|
|
|
368
|
-
- **
|
|
369
|
-
- **
|
|
370
|
-
- **
|
|
371
|
-
- **
|
|
372
|
-
- **
|
|
373
|
-
- **Reinforce-on-duplicate** — near-duplicate writes boost existing memories
|
|
374
|
-
- **No-discard salience** — low-salience memories stored at reduced confidence (available for fallback recall)
|
|
375
|
-
- **Synaptic tagging** — access count modulates decay (heavily-used memories persist longer)
|
|
376
|
-
- **Coref expansion** — pronoun queries auto-expanded with recent entity names
|
|
377
|
-
- **Async consolidation** — embedding backfill ensures all memories are clusterable
|
|
378
|
-
- **Auto-backup** — database copied to backups/ on server startup
|
|
408
|
+
- **Memory taxonomy** — memories classified as `episodic`, `semantic`, `procedural`, or `unclassified`. Auto-classified on write. Filter by type on recall.
|
|
409
|
+
- **Query-adaptive retrieval** — pipeline adapts to query type: `targeted` | `exploratory` | `balanced` | `auto`.
|
|
410
|
+
- **Decision propagation** — decisions broadcast to coordination layer for cross-agent discovery.
|
|
411
|
+
- **Eval harness** — `npm run eval` benchmarks retrieval, associative, redundancy, and temporal performance.
|
|
412
|
+
- **DB hardening** — busy_timeout, integrity check on startup, hot backups every 10 min, WAL checkpoint on shutdown.
|
|
379
413
|
|
|
380
|
-
See [CHANGELOG
|
|
414
|
+
See [CHANGELOG.md](CHANGELOG.md) for full details.
|
|
381
415
|
|
|
382
416
|
## Project Status
|
|
383
417
|
|
|
384
|
-
AWM is in active development (v0.
|
|
418
|
+
AWM is in active development (v0.6.1). The core memory pipeline, consolidation system, multi-agent coordination, and MCP integration are stable and used daily in production coding workflows.
|
|
385
419
|
|
|
386
420
|
- Core retrieval and consolidation: **stable**
|
|
387
421
|
- MCP tools and Claude Code integration: **stable**
|
|
422
|
+
- Multi-agent coordination: **stable** (v0.6.0)
|
|
388
423
|
- Task management: **stable**
|
|
389
424
|
- Hook sidecar and auto-checkpoint: **stable**
|
|
390
425
|
- HTTP API: **stable** (for custom agents)
|
|
391
|
-
-
|
|
426
|
+
- Eval harness: **stable** (v0.6.0)
|
|
392
427
|
|
|
393
|
-
See [CHANGELOG
|
|
428
|
+
See [CHANGELOG.md](CHANGELOG.md) for version history.
|
|
394
429
|
|
|
395
430
|
---
|
|
396
431
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../src/adapters/claude-code.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,UAAU,EAAkC,MAAM,YAAY,CAAC;AAG7E,QAAA,MAAM,OAAO,EAAE,UAwNd,CAAC;AAEF,eAAe,OAAO,CAAC"}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
// Copyright 2026 Robert Winter / Complete Ideas
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Claude Code adapter — writes .mcp.json, CLAUDE.md, and hooks.
|
|
5
|
+
*
|
|
6
|
+
* This is a direct extraction of the original setup() behavior.
|
|
7
|
+
* Zero behavioral change from the monolithic version.
|
|
8
|
+
*/
|
|
9
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
|
|
10
|
+
import { join, dirname, basename } from 'node:path';
|
|
11
|
+
import { resolveMcpCommand, homedir, AWM_INSTRUCTION_CONTENT } from './common.js';
|
|
12
|
+
const adapter = {
|
|
13
|
+
id: 'claude-code',
|
|
14
|
+
name: 'Claude Code',
|
|
15
|
+
supportsProjectScope: true,
|
|
16
|
+
supportsGlobalScope: true,
|
|
17
|
+
writeMcpConfig(ctx) {
|
|
18
|
+
const mcpCmd = resolveMcpCommand(ctx);
|
|
19
|
+
const mcpConfig = { ...mcpCmd, env: ctx.envVars };
|
|
20
|
+
// Global: ~/.mcp.json (standard MCP location, all projects)
|
|
21
|
+
// Project: .claude/mcp.json (Claude Code's native project scope)
|
|
22
|
+
const mcpJsonPath = ctx.isGlobal
|
|
23
|
+
? join(homedir(), '.mcp.json')
|
|
24
|
+
: join(ctx.cwd, '.claude', 'mcp.json');
|
|
25
|
+
const mcpDir = dirname(mcpJsonPath);
|
|
26
|
+
if (!existsSync(mcpDir)) {
|
|
27
|
+
mkdirSync(mcpDir, { recursive: true });
|
|
28
|
+
}
|
|
29
|
+
let existing = {};
|
|
30
|
+
if (existsSync(mcpJsonPath)) {
|
|
31
|
+
try {
|
|
32
|
+
existing = JSON.parse(readFileSync(mcpJsonPath, 'utf-8'));
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
existing = {};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (!existing.mcpServers)
|
|
39
|
+
existing.mcpServers = {};
|
|
40
|
+
existing.mcpServers['agent-working-memory'] = mcpConfig;
|
|
41
|
+
writeFileSync(mcpJsonPath, JSON.stringify(existing, null, 2) + '\n');
|
|
42
|
+
return `MCP config: ${mcpJsonPath}`;
|
|
43
|
+
},
|
|
44
|
+
writeInstructions(ctx, skip) {
|
|
45
|
+
const claudeMdPath = ctx.isGlobal
|
|
46
|
+
? join(homedir(), '.claude', 'CLAUDE.md')
|
|
47
|
+
: join(ctx.cwd, 'CLAUDE.md');
|
|
48
|
+
if (skip)
|
|
49
|
+
return 'CLAUDE.md: skipped (--no-instructions)';
|
|
50
|
+
// Ensure parent directory exists
|
|
51
|
+
const dir = dirname(claudeMdPath);
|
|
52
|
+
if (!existsSync(dir)) {
|
|
53
|
+
mkdirSync(dir, { recursive: true });
|
|
54
|
+
}
|
|
55
|
+
if (existsSync(claudeMdPath)) {
|
|
56
|
+
const content = readFileSync(claudeMdPath, 'utf-8');
|
|
57
|
+
if (content.includes('## Memory (AWM)')) {
|
|
58
|
+
return 'CLAUDE.md: already has AWM section (skipped)';
|
|
59
|
+
}
|
|
60
|
+
writeFileSync(claudeMdPath, content.trimEnd() + '\n\n' + AWM_INSTRUCTION_CONTENT);
|
|
61
|
+
return 'CLAUDE.md: appended AWM workflow section';
|
|
62
|
+
}
|
|
63
|
+
const title = ctx.isGlobal ? '# Global Instructions' : `# ${basename(ctx.cwd)}`;
|
|
64
|
+
writeFileSync(claudeMdPath, `${title}\n\n${AWM_INSTRUCTION_CONTENT}`);
|
|
65
|
+
return 'CLAUDE.md: created with AWM workflow section';
|
|
66
|
+
},
|
|
67
|
+
writeHooks(ctx, skip) {
|
|
68
|
+
if (skip)
|
|
69
|
+
return 'Hooks: skipped (--no-hooks)';
|
|
70
|
+
const settingsPath = join(homedir(), '.claude', 'settings.json');
|
|
71
|
+
let settings = {};
|
|
72
|
+
if (existsSync(settingsPath)) {
|
|
73
|
+
try {
|
|
74
|
+
settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
settings = {};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (!settings.hooks)
|
|
81
|
+
settings.hooks = {};
|
|
82
|
+
const hookUrl = `http://127.0.0.1:${ctx.hookPort}/hooks/checkpoint`;
|
|
83
|
+
// Stop — remind Claude to write/recall/switch tasks
|
|
84
|
+
settings.hooks.Stop = [{
|
|
85
|
+
matcher: '',
|
|
86
|
+
hooks: [{
|
|
87
|
+
type: 'command',
|
|
88
|
+
command: 'echo "MEMORY: (1) Did you learn anything new? Call memory_write. (2) Are you about to work on a topic you might have prior knowledge about? Call memory_recall. (3) Switching tasks? Call memory_task_begin."',
|
|
89
|
+
timeout: 5,
|
|
90
|
+
async: true,
|
|
91
|
+
}],
|
|
92
|
+
}];
|
|
93
|
+
// Multi-port fallback for separate memory pools
|
|
94
|
+
const altPort = ctx.hookPort === '8401' ? '8402' : '8401';
|
|
95
|
+
const hookUrlAlt = `http://127.0.0.1:${altPort}/hooks/checkpoint`;
|
|
96
|
+
const buildHookCmd = (event, maxTime) => {
|
|
97
|
+
const primary = `curl -sf -X POST ${hookUrl} -H "Content-Type: application/json" -H "Authorization: Bearer ${ctx.hookSecret}" -d "{\\"hook_event_name\\":\\"${event}\\"}" --max-time ${maxTime}`;
|
|
98
|
+
const fallback = `curl -sf -X POST ${hookUrlAlt} -H "Content-Type: application/json" -H "Authorization: Bearer ${ctx.hookSecret}" -d "{\\"hook_event_name\\":\\"${event}\\"}" --max-time ${maxTime}`;
|
|
99
|
+
return `${primary} || ${fallback}`;
|
|
100
|
+
};
|
|
101
|
+
// PreCompact — auto-checkpoint before context compaction
|
|
102
|
+
settings.hooks.PreCompact = [{
|
|
103
|
+
matcher: '',
|
|
104
|
+
hooks: [{
|
|
105
|
+
type: 'command',
|
|
106
|
+
command: buildHookCmd('PreCompact', 5),
|
|
107
|
+
timeout: 10,
|
|
108
|
+
}],
|
|
109
|
+
}];
|
|
110
|
+
// SessionEnd — auto-checkpoint on session close
|
|
111
|
+
settings.hooks.SessionEnd = [{
|
|
112
|
+
matcher: '',
|
|
113
|
+
hooks: [{
|
|
114
|
+
type: 'command',
|
|
115
|
+
command: buildHookCmd('SessionEnd', 2),
|
|
116
|
+
timeout: 5,
|
|
117
|
+
}],
|
|
118
|
+
}];
|
|
119
|
+
const settingsDir = dirname(settingsPath);
|
|
120
|
+
if (!existsSync(settingsDir)) {
|
|
121
|
+
mkdirSync(settingsDir, { recursive: true });
|
|
122
|
+
}
|
|
123
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
|
|
124
|
+
return `Hooks: Stop + PreCompact + SessionEnd (port ${ctx.hookPort})`;
|
|
125
|
+
},
|
|
126
|
+
diagnose(ctx) {
|
|
127
|
+
const results = [];
|
|
128
|
+
// Check MCP config — Claude Code reads from both locations, check all
|
|
129
|
+
const globalPath = join(homedir(), '.mcp.json');
|
|
130
|
+
const projectPath = join(ctx.cwd, '.claude', 'mcp.json');
|
|
131
|
+
const candidates = [projectPath, globalPath];
|
|
132
|
+
let foundConfig = false;
|
|
133
|
+
for (const mcpJsonPath of candidates) {
|
|
134
|
+
if (!existsSync(mcpJsonPath))
|
|
135
|
+
continue;
|
|
136
|
+
try {
|
|
137
|
+
const config = JSON.parse(readFileSync(mcpJsonPath, 'utf-8'));
|
|
138
|
+
if (config.mcpServers?.['agent-working-memory']) {
|
|
139
|
+
results.push({ check: 'MCP config', status: 'ok', message: `AWM registered in ${mcpJsonPath}` });
|
|
140
|
+
foundConfig = true;
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch { /* not valid JSON, skip */ }
|
|
145
|
+
}
|
|
146
|
+
if (!foundConfig) {
|
|
147
|
+
results.push({
|
|
148
|
+
check: 'MCP config',
|
|
149
|
+
status: 'fail',
|
|
150
|
+
message: 'No AWM MCP config found',
|
|
151
|
+
fix: `Run: awm setup claude-code${ctx.isGlobal ? ' --global' : ''}`,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
// Check MCP entrypoint
|
|
155
|
+
if (ctx.hasDist) {
|
|
156
|
+
results.push({ check: 'MCP entrypoint', status: 'ok', message: `dist/mcp.js exists` });
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
results.push({
|
|
160
|
+
check: 'MCP entrypoint',
|
|
161
|
+
status: 'warn',
|
|
162
|
+
message: 'dist/mcp.js not found — using dev mode (npx tsx)',
|
|
163
|
+
fix: 'Run: npm run build',
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
// Check database
|
|
167
|
+
if (existsSync(ctx.dbPath)) {
|
|
168
|
+
results.push({ check: 'Database', status: 'ok', message: ctx.dbPath });
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
results.push({ check: 'Database', status: 'warn', message: `${ctx.dbPath} not found (will be created on first use)` });
|
|
172
|
+
}
|
|
173
|
+
// Check CLAUDE.md
|
|
174
|
+
const claudeMdPath = ctx.isGlobal
|
|
175
|
+
? join(homedir(), '.claude', 'CLAUDE.md')
|
|
176
|
+
: join(ctx.cwd, 'CLAUDE.md');
|
|
177
|
+
if (existsSync(claudeMdPath)) {
|
|
178
|
+
const content = readFileSync(claudeMdPath, 'utf-8');
|
|
179
|
+
if (content.includes('## Memory (AWM)')) {
|
|
180
|
+
results.push({ check: 'Instructions', status: 'ok', message: `CLAUDE.md has AWM section` });
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
results.push({
|
|
184
|
+
check: 'Instructions',
|
|
185
|
+
status: 'warn',
|
|
186
|
+
message: `CLAUDE.md exists but missing AWM section`,
|
|
187
|
+
fix: `Run: awm setup claude-code${ctx.isGlobal ? ' --global' : ''}`,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
results.push({ check: 'Instructions', status: 'warn', message: `CLAUDE.md not found` });
|
|
193
|
+
}
|
|
194
|
+
// Check hooks
|
|
195
|
+
const settingsPath = join(homedir(), '.claude', 'settings.json');
|
|
196
|
+
if (existsSync(settingsPath)) {
|
|
197
|
+
try {
|
|
198
|
+
const settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
|
|
199
|
+
const hasHooks = settings.hooks?.PreCompact && settings.hooks?.SessionEnd;
|
|
200
|
+
if (hasHooks) {
|
|
201
|
+
results.push({ check: 'Hooks', status: 'ok', message: 'PreCompact + SessionEnd configured' });
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
results.push({ check: 'Hooks', status: 'warn', message: 'Hooks partially configured' });
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
results.push({ check: 'Hooks', status: 'warn', message: 'settings.json is not valid JSON' });
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
results.push({ check: 'Hooks', status: 'warn', message: 'No hooks configured (auto-checkpoint disabled)' });
|
|
213
|
+
}
|
|
214
|
+
return results;
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
export default adapter;
|
|
218
|
+
//# sourceMappingURL=claude-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/adapters/claude-code.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../src/adapters/codex.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,UAAU,EAAkC,MAAM,YAAY,CAAC;AA4G7E,QAAA,MAAM,OAAO,EAAE,UA2Id,CAAC;AAEF,eAAe,OAAO,CAAC"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
// Copyright 2026 Robert Winter / Complete Ideas
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Codex CLI adapter — writes TOML config, AGENTS.md instructions.
|
|
5
|
+
*
|
|
6
|
+
* Codex stores MCP config in ~/.codex/config.toml (global only).
|
|
7
|
+
* Uses snake_case [mcp_servers.name] sections.
|
|
8
|
+
*/
|
|
9
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
|
|
10
|
+
import { join, dirname, basename } from 'node:path';
|
|
11
|
+
import { resolveMcpCommand, homedir, AWM_INSTRUCTION_CONTENT } from './common.js';
|
|
12
|
+
function parseTOML(content) {
|
|
13
|
+
const doc = { sections: new Map(), preamble: [] };
|
|
14
|
+
let currentSection = '';
|
|
15
|
+
const lines = content.split('\n');
|
|
16
|
+
for (const line of lines) {
|
|
17
|
+
const trimmed = line.trim();
|
|
18
|
+
// Section header
|
|
19
|
+
const sectionMatch = trimmed.match(/^\[([^\]]+)\]$/);
|
|
20
|
+
if (sectionMatch) {
|
|
21
|
+
currentSection = sectionMatch[1];
|
|
22
|
+
if (!doc.sections.has(currentSection)) {
|
|
23
|
+
doc.sections.set(currentSection, {});
|
|
24
|
+
}
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
// Skip comments and empty lines
|
|
28
|
+
if (!trimmed || trimmed.startsWith('#')) {
|
|
29
|
+
if (!currentSection)
|
|
30
|
+
doc.preamble.push(line);
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
// Key = value
|
|
34
|
+
const eqIdx = trimmed.indexOf('=');
|
|
35
|
+
if (eqIdx === -1) {
|
|
36
|
+
if (!currentSection)
|
|
37
|
+
doc.preamble.push(line);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const key = trimmed.slice(0, eqIdx).trim();
|
|
41
|
+
const rawVal = trimmed.slice(eqIdx + 1).trim();
|
|
42
|
+
if (!currentSection) {
|
|
43
|
+
if (!doc.sections.has(''))
|
|
44
|
+
doc.sections.set('', {});
|
|
45
|
+
doc.sections.get('')[key] = parseTomlValue(rawVal);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (!doc.sections.has(currentSection)) {
|
|
49
|
+
doc.sections.set(currentSection, {});
|
|
50
|
+
}
|
|
51
|
+
doc.sections.get(currentSection)[key] = parseTomlValue(rawVal);
|
|
52
|
+
}
|
|
53
|
+
return doc;
|
|
54
|
+
}
|
|
55
|
+
function parseTomlValue(raw) {
|
|
56
|
+
// Array: ["a", "b"]
|
|
57
|
+
if (raw.startsWith('[')) {
|
|
58
|
+
const inner = raw.slice(1, raw.lastIndexOf(']'));
|
|
59
|
+
return inner.split(',')
|
|
60
|
+
.map(s => s.trim().replace(/^["']|["']$/g, ''))
|
|
61
|
+
.filter(s => s.length > 0);
|
|
62
|
+
}
|
|
63
|
+
// Quoted string
|
|
64
|
+
return raw.replace(/^["']|["']$/g, '');
|
|
65
|
+
}
|
|
66
|
+
function serializeTOML(doc) {
|
|
67
|
+
const lines = [];
|
|
68
|
+
// Preamble (top-level content before any section)
|
|
69
|
+
if (doc.preamble.length > 0) {
|
|
70
|
+
lines.push(...doc.preamble);
|
|
71
|
+
if (lines.length > 0 && lines[lines.length - 1].trim() !== '') {
|
|
72
|
+
lines.push('');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
for (const [section, values] of doc.sections) {
|
|
76
|
+
if (section === '')
|
|
77
|
+
continue; // already in preamble
|
|
78
|
+
lines.push(`[${section}]`);
|
|
79
|
+
for (const [key, val] of Object.entries(values)) {
|
|
80
|
+
if (Array.isArray(val)) {
|
|
81
|
+
const items = val.map(v => `"${v}"`).join(', ');
|
|
82
|
+
lines.push(`${key} = [${items}]`);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
lines.push(`${key} = "${val}"`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
lines.push('');
|
|
89
|
+
}
|
|
90
|
+
return lines.join('\n');
|
|
91
|
+
}
|
|
92
|
+
// ─── Adapter ──────────────────────────────────────────
|
|
93
|
+
const adapter = {
|
|
94
|
+
id: 'codex',
|
|
95
|
+
name: 'Codex',
|
|
96
|
+
supportsProjectScope: false,
|
|
97
|
+
supportsGlobalScope: true,
|
|
98
|
+
writeMcpConfig(ctx) {
|
|
99
|
+
if (!ctx.isGlobal) {
|
|
100
|
+
console.log(' Note: Codex only supports global MCP config. Using --global automatically.');
|
|
101
|
+
}
|
|
102
|
+
const configPath = join(homedir(), '.codex', 'config.toml');
|
|
103
|
+
const mcpCmd = resolveMcpCommand(ctx);
|
|
104
|
+
// Read existing config or start fresh
|
|
105
|
+
let doc;
|
|
106
|
+
if (existsSync(configPath)) {
|
|
107
|
+
doc = parseTOML(readFileSync(configPath, 'utf-8'));
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
doc = { sections: new Map(), preamble: [] };
|
|
111
|
+
mkdirSync(dirname(configPath), { recursive: true });
|
|
112
|
+
}
|
|
113
|
+
// Write the MCP server section
|
|
114
|
+
const sectionName = 'mcp_servers.agent-working-memory';
|
|
115
|
+
doc.sections.set(sectionName, {
|
|
116
|
+
command: mcpCmd.command,
|
|
117
|
+
args: mcpCmd.args,
|
|
118
|
+
});
|
|
119
|
+
// Write env vars in a sub-section
|
|
120
|
+
const envSection = `${sectionName}.env`;
|
|
121
|
+
const envEntries = {};
|
|
122
|
+
for (const [key, val] of Object.entries(ctx.envVars)) {
|
|
123
|
+
envEntries[key] = val;
|
|
124
|
+
}
|
|
125
|
+
doc.sections.set(envSection, envEntries);
|
|
126
|
+
writeFileSync(configPath, serializeTOML(doc));
|
|
127
|
+
return `MCP config: ${configPath}`;
|
|
128
|
+
},
|
|
129
|
+
writeInstructions(ctx, skip) {
|
|
130
|
+
const agentsMdPath = join(ctx.cwd, 'AGENTS.md');
|
|
131
|
+
if (skip)
|
|
132
|
+
return 'AGENTS.md: skipped (--no-instructions)';
|
|
133
|
+
if (existsSync(agentsMdPath)) {
|
|
134
|
+
const content = readFileSync(agentsMdPath, 'utf-8');
|
|
135
|
+
if (content.includes('## Memory (AWM)')) {
|
|
136
|
+
return 'AGENTS.md: already has AWM section (skipped)';
|
|
137
|
+
}
|
|
138
|
+
writeFileSync(agentsMdPath, content.trimEnd() + '\n\n' + AWM_INSTRUCTION_CONTENT);
|
|
139
|
+
return 'AGENTS.md: appended AWM workflow section';
|
|
140
|
+
}
|
|
141
|
+
const title = `# ${basename(ctx.cwd)} — Agent Instructions`;
|
|
142
|
+
writeFileSync(agentsMdPath, `${title}\n\n${AWM_INSTRUCTION_CONTENT}`);
|
|
143
|
+
return 'AGENTS.md: created with AWM workflow section';
|
|
144
|
+
},
|
|
145
|
+
writeHooks(_ctx, _skip) {
|
|
146
|
+
return 'Hooks: not supported by Codex (auto-checkpoint unavailable)';
|
|
147
|
+
},
|
|
148
|
+
diagnose(ctx) {
|
|
149
|
+
const results = [];
|
|
150
|
+
// Check TOML config
|
|
151
|
+
const configPath = join(homedir(), '.codex', 'config.toml');
|
|
152
|
+
if (!existsSync(configPath)) {
|
|
153
|
+
results.push({
|
|
154
|
+
check: 'MCP config',
|
|
155
|
+
status: 'fail',
|
|
156
|
+
message: `${configPath} not found`,
|
|
157
|
+
fix: 'Run: awm setup codex',
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
try {
|
|
162
|
+
const doc = parseTOML(readFileSync(configPath, 'utf-8'));
|
|
163
|
+
if (doc.sections.has('mcp_servers.agent-working-memory')) {
|
|
164
|
+
results.push({ check: 'MCP config', status: 'ok', message: `AWM registered in ${configPath}` });
|
|
165
|
+
// Verify the command points to a real file
|
|
166
|
+
const section = doc.sections.get('mcp_servers.agent-working-memory');
|
|
167
|
+
const args = section.args;
|
|
168
|
+
if (Array.isArray(args) && args.length > 0) {
|
|
169
|
+
const entrypoint = args[args.length - 1];
|
|
170
|
+
if (existsSync(entrypoint)) {
|
|
171
|
+
results.push({ check: 'MCP entrypoint', status: 'ok', message: entrypoint });
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
results.push({
|
|
175
|
+
check: 'MCP entrypoint',
|
|
176
|
+
status: 'fail',
|
|
177
|
+
message: `Configured entrypoint not found: ${entrypoint}`,
|
|
178
|
+
fix: 'Run: npm run build (in AWM package) then awm setup codex',
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
results.push({
|
|
185
|
+
check: 'MCP config',
|
|
186
|
+
status: 'fail',
|
|
187
|
+
message: 'config.toml exists but missing agent-working-memory section',
|
|
188
|
+
fix: 'Run: awm setup codex',
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
results.push({ check: 'MCP config', status: 'fail', message: `${configPath} could not be parsed` });
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// Check database
|
|
197
|
+
if (existsSync(ctx.dbPath)) {
|
|
198
|
+
results.push({ check: 'Database', status: 'ok', message: ctx.dbPath });
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
results.push({ check: 'Database', status: 'warn', message: `${ctx.dbPath} not found (will be created on first use)` });
|
|
202
|
+
}
|
|
203
|
+
// Check AGENTS.md
|
|
204
|
+
const agentsMdPath = join(ctx.cwd, 'AGENTS.md');
|
|
205
|
+
if (existsSync(agentsMdPath)) {
|
|
206
|
+
const content = readFileSync(agentsMdPath, 'utf-8');
|
|
207
|
+
if (content.includes('## Memory (AWM)')) {
|
|
208
|
+
results.push({ check: 'Instructions', status: 'ok', message: 'AGENTS.md has AWM section' });
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
results.push({
|
|
212
|
+
check: 'Instructions',
|
|
213
|
+
status: 'warn',
|
|
214
|
+
message: 'AGENTS.md exists but missing AWM section',
|
|
215
|
+
fix: 'Run: awm setup codex',
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
results.push({ check: 'Instructions', status: 'warn', message: 'AGENTS.md not found' });
|
|
221
|
+
}
|
|
222
|
+
return results;
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
export default adapter;
|
|
226
|
+
//# sourceMappingURL=codex.js.map
|