@bd7pil/opencode-deep-memory 0.6.0 → 0.8.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 +114 -148
- package/dist/index.js +130 -38
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
OpenCode sessions are stateless. Every restart is a cold start. Native compaction
|
|
8
8
|
destroys conversation content. **deep-memory** adds three layers:
|
|
9
9
|
|
|
10
|
-
| Layer |
|
|
11
|
-
|
|
12
|
-
| **Remember** |
|
|
13
|
-
| **Recover** |
|
|
14
|
-
| **Compress** |
|
|
10
|
+
| Layer | What survives | How |
|
|
11
|
+
|-------|--------------|-----|
|
|
12
|
+
| **Remember** | Decisions, constraints, gotchas | `memory_search` / `memory_store` — BM25 + CJK search across sessions |
|
|
13
|
+
| **Recover** | Full conversation context | Checkpoint captures before compaction; resume injection on new session |
|
|
14
|
+
| **Compress** | Token budget | Deterministic stripping + pressure-triggered deep compression — no LLM calls |
|
|
15
15
|
|
|
16
16
|
## Quick start
|
|
17
17
|
|
|
@@ -30,125 +30,116 @@ OpenCode auto-installs on startup. Memory appears at `.deep-memory/` in your pro
|
|
|
30
30
|
## How it works
|
|
31
31
|
|
|
32
32
|
```
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
│
|
|
43
|
-
│
|
|
44
|
-
│
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
│
|
|
51
|
-
│
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
33
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
34
|
+
│ messages.transform (every turn) │
|
|
35
|
+
│ ├─ Strip reasoning/thinking parts (physical removal) │
|
|
36
|
+
│ ├─ Remove system-injected messages (physical removal) │
|
|
37
|
+
│ ├─ Truncate old tool errors │
|
|
38
|
+
│ └─ Deep compress: dedup / tool output / JSON / assistant text │
|
|
39
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
40
|
+
|
|
41
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
42
|
+
│ system.transform (every turn) │
|
|
43
|
+
│ ├─ Inject stable: MEMORY.md constraints + tool hint (cache hit)│
|
|
44
|
+
│ └─ Inject volatile: BM25 search results + repo map symbols │
|
|
45
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
46
|
+
|
|
47
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
48
|
+
│ compacting (before OpenCode destroys messages) │
|
|
49
|
+
│ ├─ Capture raw messages → checkpoint.raw.json │
|
|
50
|
+
│ ├─ Extract knowledge → checkpoint.md │
|
|
51
|
+
│ └─ Inject structured handoff prompt for LLM │
|
|
52
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
53
|
+
|
|
54
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
55
|
+
│ events │
|
|
56
|
+
│ ├─ session.created → resume + dream schedule │
|
|
57
|
+
│ ├─ session.idle → enrichment │
|
|
58
|
+
│ └─ session.compacted → pressure calibration │
|
|
59
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
55
60
|
```
|
|
56
61
|
|
|
57
62
|
## Context compression
|
|
58
63
|
|
|
59
|
-
Two
|
|
64
|
+
Two layers, fully automatic, no LLM calls.
|
|
60
65
|
|
|
61
|
-
### Layer 1: Deterministic stripping
|
|
66
|
+
### Layer 1: Deterministic stripping (always active)
|
|
62
67
|
|
|
63
|
-
|
|
68
|
+
| Target | Action |
|
|
69
|
+
|--------|--------|
|
|
70
|
+
| Old reasoning/thinking parts | Physical removal |
|
|
71
|
+
| System injections (`<system-reminder>`, etc.) | Physical removal |
|
|
72
|
+
| Tool errors >100 chars (older than 4 turns) | Truncate |
|
|
73
|
+
| Inline `<thinking>` tags | Regex strip |
|
|
64
74
|
|
|
65
|
-
|
|
66
|
-
|--------------------|-----|----------|
|
|
67
|
-
| `reasoning_details` metadata | Delete the JSON blob | Billing metadata, never reaches model |
|
|
68
|
-
| Old reasoning text | Replace with `[cleared]` | Conclusions are in assistant text |
|
|
69
|
-
| System injections | Replace with `[stripped]` | `<system-reminder>` stale after one turn |
|
|
70
|
-
| Tool errors >100 chars | Truncate | An old error only needs "it failed" |
|
|
71
|
-
| Inline `<thinking>` tags | Regex strip | Process, not product |
|
|
75
|
+
No marker pollution — old content is physically removed, not replaced with `[cleared]` or `[stripped]`. This prevents [context confusion](https://www.philschmid.de/context-engineering-part-2).
|
|
72
76
|
|
|
73
77
|
### Layer 2: Deep compression (pressure-triggered)
|
|
74
78
|
|
|
75
|
-
Activates when context pressure exceeds thresholds. Inspired by
|
|
76
|
-
[DCP](https://github.com/Opencode-DCP/opencode-dynamic-context-pruning),
|
|
77
|
-
[Headroom](https://github.com/chopratejas/headroom), and
|
|
78
|
-
[Edgee](https://github.com/edgee-ai/edgee).
|
|
79
|
-
|
|
80
79
|
| Pressure | Threshold | Actions |
|
|
81
80
|
|----------|-----------|---------|
|
|
82
|
-
| **always** | every turn | tool dedup + error purge + tool output compress + JSON crush
|
|
83
|
-
| **medium** | ≥
|
|
84
|
-
| **high** | ≥
|
|
81
|
+
| **always** | every turn | tool dedup + error purge + tool output compress + JSON crush + assistant text compress |
|
|
82
|
+
| **medium** | ≥ 50K tokens | + memory nudge (prompts LLM to use `memory_store`) |
|
|
83
|
+
| **high** | ≥ 150K tokens | + pressure nudge (prompts LLM to summarize old tasks) |
|
|
85
84
|
|
|
86
|
-
|
|
85
|
+
Thresholds are absolute, not percentage-based — they work consistently across 200K and 1M+ context windows. Based on [Focus Agent](https://arxiv.org/html/2601.07190v1) research.
|
|
87
86
|
|
|
88
87
|
| Target | Strategy | Source |
|
|
89
88
|
|--------|----------|--------|
|
|
90
|
-
| Duplicate tool calls | Signature matching
|
|
91
|
-
| Old error inputs | Purge
|
|
92
|
-
| File reads | Keep
|
|
93
|
-
| Command outputs | Keep errors +
|
|
94
|
-
| Search results | Keep top-20, group by file | Edgee |
|
|
95
|
-
| JSON arrays |
|
|
96
|
-
| Old assistant text |
|
|
89
|
+
| Duplicate tool calls | Signature matching | [DCP][] |
|
|
90
|
+
| Old error inputs | Purge after 4 turns | [DCP][] |
|
|
91
|
+
| File reads | Keep head + key lines + tail | [Edgee][] |
|
|
92
|
+
| Command outputs | Keep errors + tail | [Edgee][] |
|
|
93
|
+
| Search results | Keep top-20, group by file | [Edgee][] |
|
|
94
|
+
| JSON arrays | Head + dedup middle + tail | [Headroom][] |
|
|
95
|
+
| Old assistant text | Preserve structure, compress prose | [LLMLingua][] |
|
|
97
96
|
|
|
98
|
-
All compressed content is **reversible** via CCR (Compress-Cache-Retrieve)
|
|
99
|
-
originals are cached with SHA-256 hash and 5-minute TTL.
|
|
100
|
-
Models can retrieve them via the `deep_expand` tool.
|
|
97
|
+
All compressed content is **reversible** via CCR (Compress-Cache-Retrieve) — originals cached with SHA-256 hash, retrievable via `deep_expand` tool.
|
|
101
98
|
|
|
102
|
-
**Never touched**: user messages, recent
|
|
103
|
-
(question, edit, write, todowrite, memory_store/search/forget).
|
|
99
|
+
**Never touched**: user messages, recent 4K tokens, protected tools (question, edit, write, todowrite, memory_*).
|
|
104
100
|
|
|
105
|
-
##
|
|
101
|
+
## Memory nudge
|
|
106
102
|
|
|
107
|
-
|
|
108
|
-
what was compressed and injected. The notification level is chosen automatically:
|
|
103
|
+
Detects decisions, constraints, and fixes in conversation — nudges the LLM to persist them.
|
|
109
104
|
|
|
110
|
-
|
|
|
111
|
-
|
|
112
|
-
|
|
|
113
|
-
|
|
|
114
|
-
|
|
|
105
|
+
| Pattern | Example | Nudge |
|
|
106
|
+
|---------|---------|-------|
|
|
107
|
+
| Decision | "我决定用 PostgreSQL" / "I'll use PostgreSQL" | `memory_store(type="decision")` |
|
|
108
|
+
| Constraint | "不能用 eval()" / "must not use eval()" | `memory_store(type="constraint")` |
|
|
109
|
+
| Error fix | "修复了权限问题" / "fixed the permission error" | `memory_store(type="gotcha")` |
|
|
115
110
|
|
|
116
|
-
|
|
111
|
+
English + Chinese. Pressure nudge and memory nudge have independent cooldowns.
|
|
117
112
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
```
|
|
113
|
+
## Tools
|
|
114
|
+
|
|
115
|
+
| Tool | Purpose |
|
|
116
|
+
|------|---------|
|
|
117
|
+
| `memory_search` | Search persistent memory (BM25 + CJK bigram) |
|
|
118
|
+
| `memory_store` | Store decisions, constraints, gotchas, facts, notes |
|
|
119
|
+
| `memory_forget` | Remove stale memory entries |
|
|
120
|
+
| `memory_expand` | Retrieve original content of a compressed message |
|
|
121
|
+
| `deep_expand` | Retrieve original content via CCR hash |
|
|
128
122
|
|
|
129
|
-
##
|
|
123
|
+
## Compaction
|
|
130
124
|
|
|
131
|
-
|
|
125
|
+
When OpenCode compacts a session:
|
|
132
126
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
127
|
+
1. **Capture** raw messages to `checkpoint.raw.json`
|
|
128
|
+
2. **Extract** knowledge via 5 heuristic extractors
|
|
129
|
+
3. **Write** structured `checkpoint.md`
|
|
130
|
+
4. **Inject** Hermes-8 structured prompt + Codex-style handoff prefix
|
|
136
131
|
|
|
137
|
-
|
|
138
|
-
current query, tier-allocated by importance, plus repo map symbols for recently-read files.
|
|
139
|
-
This is the only part that changes per turn.
|
|
132
|
+
The LLM produces: Task Overview → Progress → Key Decisions → Constraints → Files Modified → Errors → Next Steps → Critical Context
|
|
140
133
|
|
|
141
|
-
|
|
142
|
-
(3000 on session resume), deep-reasoning agents get 400, and tool subagents get 80.
|
|
134
|
+
## Memory consolidation
|
|
143
135
|
|
|
144
|
-
|
|
136
|
+
| Cycle | Trigger | Action |
|
|
137
|
+
|-------|---------|--------|
|
|
138
|
+
| **Auto-dream** | 7 days or notes.md >20 lines | Consolidate notes + checkpoints → MEMORY.md |
|
|
139
|
+
| **Auto-distill** | 30 days | Package recurring workflows → skill candidates |
|
|
140
|
+
| **Enrichment** | Session idle after compaction | LLM enriches checkpoint with cross-references |
|
|
145
141
|
|
|
146
|
-
|
|
147
|
-
Chinese runs are split into sliding 2-character bigrams (`"权限死锁"` →
|
|
148
|
-
`["权","权限","限死","死锁","锁"]`), making multi-character CJK phrases searchable
|
|
149
|
-
without an embedding model. Latin text uses standard whitespace/punctuation splitting.
|
|
150
|
-
The index is rebuilt from Markdown files on startup (<250ms for 2000 entries) and
|
|
151
|
-
updated incrementally on writes.
|
|
142
|
+
New projects: MEMORY.md auto-bootstraps from notes.md. Both agents have `memory_forget` enabled.
|
|
152
143
|
|
|
153
144
|
## Configuration
|
|
154
145
|
|
|
@@ -161,48 +152,28 @@ updated incrementally on writes.
|
|
|
161
152
|
## Storage
|
|
162
153
|
|
|
163
154
|
```
|
|
164
|
-
<project>/.deep-memory/
|
|
155
|
+
<project>/.deep-memory/
|
|
165
156
|
├── MEMORY.md persistent decisions/constraints/gotchas
|
|
166
157
|
├── notes.md keyword captures
|
|
167
158
|
├── checkpoint.md last compaction extraction
|
|
159
|
+
├── checkpoint.raw.json raw messages dump
|
|
168
160
|
├── .schedule.json dream/distill state
|
|
169
|
-
|
|
161
|
+
├── .compaction-log.jsonl compaction audit trail
|
|
162
|
+
└── sessions/<sid>/ per-session archive
|
|
170
163
|
```
|
|
171
164
|
|
|
172
|
-
## Tools
|
|
173
|
-
|
|
174
|
-
| Tool | Purpose |
|
|
175
|
-
|------|---------|
|
|
176
|
-
| `memory_search` | Search persistent memory across sessions (BM25 + CJK) |
|
|
177
|
-
| `memory_store` | Store decisions, constraints, gotchas, facts, notes |
|
|
178
|
-
| `memory_forget` | Remove memory entries matching a query |
|
|
179
|
-
| `memory_expand` | Decompress a sentinel reference to its original content |
|
|
180
|
-
| `deep_expand` | Retrieve original content compressed by CCR (use `[ccr:HASH]` marker) |
|
|
181
|
-
| `deep_expand` | Retrieve original content compressed by CCR (use `[ccr:HASH]` marker) |
|
|
182
|
-
|
|
183
165
|
## Commands
|
|
184
166
|
|
|
185
|
-
Copy `.opencode/command/*.md` to your project:
|
|
186
|
-
|
|
187
167
|
- `/checkpoint` — manually capture session state
|
|
188
168
|
- `/dream` — consolidate notes into persistent memory
|
|
189
169
|
- `/distill` — package recurring workflows into skills
|
|
190
170
|
|
|
191
|
-
##
|
|
192
|
-
|
|
193
|
-
**Memory entries** carry a type (`decision`, `constraint`, `gotcha`, `fact`, `note`) and
|
|
194
|
-
an importance score. Importance is heuristically derived from entry type, recency,
|
|
195
|
-
frequency across sessions, and keyword-match relevance to the current query —
|
|
196
|
-
no LLM calls required.
|
|
197
|
-
|
|
198
|
-
Entries are stored as Markdown sections (e.g. `## Decisions`, `## Constraints`) in
|
|
199
|
-
`MEMORY.md`, with `[date]` timestamps for time-based decay. The BM25 index is rebuilt
|
|
200
|
-
from these files on startup and updated incrementally on write.
|
|
171
|
+
## Development
|
|
201
172
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
173
|
+
```bash
|
|
174
|
+
npm install
|
|
175
|
+
npm run verify # typecheck + test (363) + build + smoke (49)
|
|
176
|
+
```
|
|
206
177
|
|
|
207
178
|
## Acknowledgments
|
|
208
179
|
|
|
@@ -236,6 +207,21 @@ Our per-tool compression strategies (read, bash, grep, glob) are inspired by Edg
|
|
|
236
207
|
**[Contextomizer][]** — ultra-fast deterministic library for transforming bloated tool outputs.
|
|
237
208
|
Our content type detection pipeline is inspired by Contextomizer's approach.
|
|
238
209
|
|
|
210
|
+
**[Focus Agent][]** — autonomous memory management for coding agents.
|
|
211
|
+
Our absolute token thresholds and assistant text compression strategy are based on Focus Agent's research.
|
|
212
|
+
|
|
213
|
+
**[LLMLingua][]** — prompt compression for LLMs.
|
|
214
|
+
Our selective assistant text compression (preserve structure, compress prose) is inspired by LLMLingua's approach.
|
|
215
|
+
|
|
216
|
+
**[Codex CLI][]** — OpenAI's coding agent.
|
|
217
|
+
Our handoff prefix pattern (telling the LLM it's resuming a prior task) is based on Codex CLI's compaction protocol.
|
|
218
|
+
|
|
219
|
+
**[Google ADK][]** — Agent Development Kit with append-only event compaction.
|
|
220
|
+
Our structured compaction prompt (Hermes-8 sections) is inspired by ADK's compaction architecture.
|
|
221
|
+
|
|
222
|
+
**[Hermes][]** — production-grade compaction prompt design.
|
|
223
|
+
Our 8-section checkpoint template follows Hermes's structured summary format.
|
|
224
|
+
|
|
239
225
|
[MiMo-Code]: https://github.com/XiaomiMiMo/MiMo-Code
|
|
240
226
|
[Magic Context]: https://github.com/cortexkit/magic-context
|
|
241
227
|
[Aider]: https://github.com/Aider-AI/aider
|
|
@@ -247,31 +233,11 @@ Our content type detection pipeline is inspired by Contextomizer's approach.
|
|
|
247
233
|
[Headroom]: https://github.com/chopratejas/headroom
|
|
248
234
|
[Edgee]: https://github.com/edgee-ai/edgee
|
|
249
235
|
[Contextomizer]: https://github.com/GandalFran/contextomizer
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
npm run verify # typecheck + test (363) + build + smoke (49)
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
Stats: 54 source files, 27 test files (363 tests), 10 compress modules, 49 smoke checks.
|
|
259
|
-
|
|
260
|
-
## CI/CD (npm Trusted Publishing)
|
|
261
|
-
|
|
262
|
-
Releases use npm OIDC Trusted Publishing — no token needed. To set up for a fork:
|
|
263
|
-
|
|
264
|
-
1. **npmjs.com** → Package Settings → Trusted Publishers → Add:
|
|
265
|
-
- Owner: your GitHub username
|
|
266
|
-
- Repository: your fork name
|
|
267
|
-
- Workflow filename: `publish.yml`
|
|
268
|
-
2. **package.json** → update `repository.url` to match your fork
|
|
269
|
-
3. **Push a tag** → GitHub Actions auto-publishes:
|
|
270
|
-
```bash
|
|
271
|
-
git tag v1.0.0 && git push origin v1.0.0
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
Requirements: npm CLI ≥ 11.5.1, Node.js ≥ 22, `id-token: write` permission, public repository.
|
|
236
|
+
[Focus Agent]: https://arxiv.org/html/2601.07190v1
|
|
237
|
+
[LLMLingua]: https://github.com/microsoft/LLMLingua
|
|
238
|
+
[Codex CLI]: https://github.com/openai/codex
|
|
239
|
+
[Google ADK]: https://github.com/google/adk-python
|
|
240
|
+
[Hermes]: https://github.com/NousResearch/hermes-agent
|
|
275
241
|
|
|
276
242
|
## License
|
|
277
243
|
|