@x-otto/memory 0.0.1-alpha.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 ADDED
@@ -0,0 +1,161 @@
1
+ # @x-otto/memory
2
+
3
+ Agent working memory pipeline: LLM-driven compaction, LLM-free pruning, archive persistence, multi-source AGENTS.md memory, writable cross-session auto-memory, operational learning, and workspace file-state snapshots.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pnpm add @x-otto/memory
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```ts
14
+ import { MemoryManager, OperationalLearningStore, FileStateManager } from '@x-otto/memory'
15
+
16
+ // Pipeline: prune → compaction → archive
17
+ const memory = new MemoryManager({
18
+ workspaceDir: process.cwd(),
19
+ model: 'claude-sonnet-4-5',
20
+ provider: myProvider,
21
+ })
22
+ const result = await memory.process(messages, sessionId)
23
+ // Returns { messages, summary, archivePath, pruned, compacted }
24
+
25
+ // Token estimation (CJK-aware, no LLM call)
26
+ import { estimateMessagesTokens } from '@x-otto/memory'
27
+ const tokens = estimateMessagesTokens(messages)
28
+
29
+ // Operational learning
30
+ const lessons = new OperationalLearningStore({ path: './.otto/lessons.json' })
31
+ await lessons.save({ tags: ['testing'], trigger: 'flaky test', insight: 'reset state first' })
32
+
33
+ // File state snapshot
34
+ const fsm = new FileStateManager()
35
+ const snapshot = await fsm.capture({ workspaceDir: '.' })
36
+ // snapshot → { tree, recentFiles: { created, modified, deleted } }
37
+ ```
38
+
39
+ ## Pipeline: prune → compaction → archive
40
+
41
+ ### 1. Prune — no-LLM fast cleanup (`prune.ts`)
42
+
43
+ - Triggered when estimated tokens exceed `prune.trigger` threshold
44
+ - Protection window: last N messages (by token count) are always kept
45
+ - `tool_result` content outside protection → `[output pruned — N tokens]`
46
+ - `tool_call` arguments for write tools (write/edit/apply_patch) truncated beyond `truncateMaxLength`
47
+ - Minimum gain gate: rolls back if net savings < `minimum` tokens
48
+
49
+ ### 2. Compaction — LLM-driven summary (`compaction.ts`)
50
+
51
+ - `findCutPoint`: keep recent tokens, align to user/assistant boundary, detect split-turn
52
+ - Separates messages-to-summarize / preserved / turn-prefix region
53
+ - Extracts file operations (read/modified paths) from tool_results
54
+ - Calls injected `summarize(system, messages, opts)` with structured prompt (Goal / Constraints / Progress / Key Decisions / Next Steps / File Operations / Critical Context)
55
+ - Iterative: previous summary + new messages → `UPDATE_SUMMARIZATION_PROMPT`
56
+ - Split turn: generates additional turn-prefix summary via `TURN_PREFIX_SUMMARIZATION_PROMPT`
57
+
58
+ ### 3. Archive — persist compaction output (`archive.ts`)
59
+
60
+ - Formats compressed messages + summary as Markdown (single messages >2000 chars truncated)
61
+ - Backends: `InMemoryArchiveStorage` (default), `PersistenceBackedArchiveStorage` (file/HTTP via `@x-otto/persistence`)
62
+ - Factory: `createArchiveStorage(options)` — file default `$OTTO_HOME/agent/archives`
63
+
64
+ ## Persistent Memory (`persistent-memory.ts`)
65
+
66
+ Multi-source AGENTS.md loading + writable:
67
+
68
+ | Source | Path | Writable |
69
+ |--------|------|----------|
70
+ | Global user | `~/.otto/AGENTS.md` | ✓ |
71
+ | Project | `./.otto/AGENTS.md` | ✓ (by default) |
72
+ | Community | `./AGENTS.md` | ✗ (read-only) |
73
+
74
+ ### MemoryStore backends
75
+
76
+ | Backend | Store | Notes |
77
+ |---------|-------|-------|
78
+ | File system | `FileSystemMemoryStore` | Direct fs — AGENTS.md must stay human-editable, bypasses persistence envelope |
79
+ | In-memory | `InMemoryMemoryStore` | Testing |
80
+ | HTTP | `HttpMemoryStore` | Remote via `@x-otto/persistence` HttpPersistence; 1 source = 1 doc |
81
+
82
+ ### AutoMemory (`auto-memory.ts`)
83
+
84
+ Writable cross-session memory with progressive disclosure:
85
+ - `<baseDir>/MEMORY.md` — index with one-line pointers (injected only, keeps tokens low)
86
+ - `<baseDir>/memory/<slug>.md` — per-entry full content, fetched on demand
87
+ - `record(name, content)`, `read(name)`, `forget(name)`, `getInjection()`, `asSource()`
88
+
89
+ ### Memory Injection
90
+
91
+ `buildMemoryInjection(sources)` wraps content in `<agent_memory>` + `<memory_guidelines>` blocks for model injection.
92
+
93
+ ## Token Estimation (`token-estimator.ts`)
94
+
95
+ CJK-aware classification heuristic (not `length/4`):
96
+
97
+ - CJK: 1 token/char, ASCII/symbols: 0.25–0.5/char → conservatively high (triggers early rather than overflow)
98
+ - `estimateMessageTokens`: content blocks (text/thinking/tool_call), images ~2000 tokens constant, + role overhead
99
+ - `estimateContextTokens`: hybrid — last assistant's usage as baseline, estimate only trailing tail
100
+ - Exports `messageToText` and re-exports `getTokensFromUsage` from `@x-otto/ai`
101
+
102
+ ## Operational Learning (`operational-learning.ts`)
103
+
104
+ `OperationalLearningStore` — experience knowledge base:
105
+
106
+ | Method | Description |
107
+ |--------|-------------|
108
+ | `save(input)` | Auto-assigns `lesson_<n>` id, writes snapshot |
109
+ | `search(query, limit)` | Weighted scoring on trigger/insight/tags, increments `appliedCount` |
110
+ | `list(filter)` | Filter by tags / query |
111
+ | `get(id)`, `delete(id)` | Single entry CRUD |
112
+ | `size` | Entry count |
113
+
114
+ Persistence via `@x-otto/persistence` FilePersistence (atomic tmp+rename), single snapshot store. Auto-upgrades pre-M19 flat JSON format on write.
115
+
116
+ ## File State Snapshot (`file-state-snapshot.ts`)
117
+
118
+ Read-only workspace snapshot for agent context:
119
+ - `capture({workspaceDir, recentFiles, planStatus})` — directory tree walk (depth ≤4, ≤50 per dir, ignores node_modules/.git/dist) + recent file stat check (birthtime/mtime → created/modified/deleted)
120
+ - `formatSnapshot(snapshot)` — text block for model injection
121
+ - `getLastSnapshot()` — most recent snapshot
122
+
123
+ ## Key Files
124
+
125
+ ```
126
+ src/
127
+ types.ts # Config types, MemoryStore, ArchiveStorage, ManagerConfig
128
+ memory-manager.ts # Pipeline coordinator + persistent memory facade
129
+ prune.ts # No-LLM pruning (window, tool_result truncation, gain gate)
130
+ compaction.ts # Cut point, LLM summary, split-turn, file ops extraction
131
+ archive.ts # InMemoryArchiveStorage + formatArchive + createArchiveStorage
132
+ persistent-memory.ts # AGENTS.md multi-source + FileSystemMemoryStore / InMemoryMemoryStore
133
+ http-memory-store.ts # Remote HTTP memory store
134
+ auto-memory.ts # Cross-session progressive-disclosure memory
135
+ auto-extract.ts # Auto-memory candidate extraction
136
+ agents-discovery.ts # AGENTS.md path discovery
137
+ memory-extractor.ts # Derive persistable memory entries from session
138
+ token-estimator.ts # CJK-aware token estimation + usage-hybrid context
139
+ defaults.ts # computeMemoryDefaults / resolveContextSize
140
+ operational-learning.ts # Lessons store (CRUD + weighted search + atomic persistence)
141
+ file-state-snapshot.ts # Workspace read-only snapshot
142
+ prompts.ts # Summary prompts + memory/archive injection builders
143
+ constants.ts # Thresholds, paths
144
+ index.ts # Barrel exports
145
+ ```
146
+
147
+ ## Dependencies
148
+
149
+ - Internal: `@x-otto/ai` (Message types, getTokensFromUsage), `@x-otto/persistence`, `@x-otto/shared`, `@x-otto/env` (thresholds, tool name constants)
150
+ - External: `js-tiktoken`
151
+ - LLM access: via injected `summarize` callback (not direct)
152
+
153
+ ## Testing
154
+
155
+ ```bash
156
+ pnpm --filter @x-otto/memory typecheck
157
+ pnpm --filter @x-otto/memory build
158
+ pnpm vitest run packages/memory/tests/
159
+ ```
160
+
161
+ 11 test files covering: prune (window, gain rollback), compaction (cut-point, split-turn, iterative, fileOps), archive (memory + persistence), persistent-memory (multi-source, writable, injection), auto-memory (record/read/forget/slug dedup), token estimation (CJK/symbol/image/usage-hybrid), operational learning (CRUD/search/upgrade), file-state-snapshot, prompts, defaults.