@bd7pil/opencode-deep-memory 0.3.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/LICENSE +21 -0
- package/README.md +181 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +15747 -0
- package/dist/index.js.map +1 -0
- package/package.json +51 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 opencode-deep-memory contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# opencode-deep-memory
|
|
2
|
+
|
|
3
|
+
> Persistent memory, checkpoint resilience, and deterministic context compression for [OpenCode](https://github.com/anomalyco/opencode) — zero runtime dependencies.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
OpenCode sessions are stateless. Every restart is a cold start. Native compaction
|
|
8
|
+
destroys conversation content. **deep-memory** adds three layers:
|
|
9
|
+
|
|
10
|
+
| Layer | Hook | Purpose |
|
|
11
|
+
|-------|------|---------|
|
|
12
|
+
| **Remember** | `memory_search`, `memory_store`, `memory_forget`, `memory_expand` | Decisions, constraints, gotchas survive across sessions via BM25 + CJK search. Storage at `.deep-memory/` in your project root — visible, version-controllable. |
|
|
13
|
+
| **Recover** | `session.created`, `experimental.session.compacting` | Checkpoint captures conversation before compaction destroys it. Resume injection recalls everything on a new session (3000 token first-turn budget). |
|
|
14
|
+
| **Compress** | `experimental.chat.messages.transform` | Old reasoning, metadata, system injections, and thinking tags stripped deterministically — no LLM calls. Cache-stable sentinel replacements preserve prompt cache. |
|
|
15
|
+
|
|
16
|
+
## Quick start
|
|
17
|
+
|
|
18
|
+
```jsonc
|
|
19
|
+
// opencode.json
|
|
20
|
+
{
|
|
21
|
+
"plugin": [
|
|
22
|
+
"oh-my-openagent",
|
|
23
|
+
"@bd7pil/opencode-deep-memory"
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
OpenCode auto-installs on startup. Memory appears at `.deep-memory/` in your project root.
|
|
29
|
+
|
|
30
|
+
## How it works
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
┌─────────────────────────────┐
|
|
34
|
+
│ system.transform │
|
|
35
|
+
│ m[0] stable (cache hit) │
|
|
36
|
+
│ m[1] volatile (per-turn) │
|
|
37
|
+
│ repo map (code symbols) │
|
|
38
|
+
└─────────────────────────────┘
|
|
39
|
+
▲
|
|
40
|
+
┌──────────────┐ ┌──────────────┐ │ ┌──────────────┐
|
|
41
|
+
│ chat.message │ │ chat.params │ │ │messages.tfm │
|
|
42
|
+
│ keyword→notes│ │ agent→budget │ │ │ strip old │
|
|
43
|
+
│ "记住"/"rem" │ │ main 800t │ │ │ reasoning + │
|
|
44
|
+
│ │ │ oracle 400t │ │ │ metadata + │
|
|
45
|
+
└──────────────┘ └──────────────┘ │ │ errors │
|
|
46
|
+
│ └──────────────┘
|
|
47
|
+
┌──────────────┘
|
|
48
|
+
│
|
|
49
|
+
┌─────────────────────┴───────────────────────┐
|
|
50
|
+
│ event │
|
|
51
|
+
│ session.created → resume + dream schedule │
|
|
52
|
+
│ session.idle → enrichment │
|
|
53
|
+
│ session.compacted → checkpoint │
|
|
54
|
+
└─────────────────────────────────────────────┘
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Context compression
|
|
58
|
+
|
|
59
|
+
Old messages (>8 turns) are compressed deterministically, without calling an LLM.
|
|
60
|
+
The key insight: **reasoning is a disposable process** — once the model reaches a conclusion
|
|
61
|
+
(in the text or tool output), the reasoning that got it there no longer affects future turns.
|
|
62
|
+
Similarly, API metadata, system notifications, and inline thinking tags carry no value
|
|
63
|
+
once the conversation moves past them. We strip these in-place, replacing removed parts
|
|
64
|
+
with sentinels so message structure stays intact and prompt caching is preserved.
|
|
65
|
+
|
|
66
|
+
| What gets stripped | How | Why safe |
|
|
67
|
+
|--------------------|-----|----------|
|
|
68
|
+
| `reasoning_details` metadata | Delete the JSON blob from the part | API billing metadata, never reaches the model |
|
|
69
|
+
| Old reasoning text | Set `thinking`/`text` to `"[cleared]"` | Conclusions are in the assistant's text output |
|
|
70
|
+
| System injections | Replace entire message with sentinel | `<system-reminder>` and OMO markers are stale after one turn |
|
|
71
|
+
| Tool errors >100 chars | Truncate to first 100 chars | An old error only needs "it failed", not the full trace |
|
|
72
|
+
| Inline `<thinking>` tags | Regex strip from old assistant text | Same as reasoning — process, not product |
|
|
73
|
+
|
|
74
|
+
**Never touched**: user messages (anchor turn boundaries), recent 8 messages (working context),
|
|
75
|
+
tool calls and their results (API pairing integrity).
|
|
76
|
+
|
|
77
|
+
## Cache-stable injection
|
|
78
|
+
|
|
79
|
+
Each turn pushes two system prompt fragments:
|
|
80
|
+
|
|
81
|
+
- **Stable** (`<deep-memory-stable>`): constraints, rules, and the tool hint.
|
|
82
|
+
These change only when MEMORY.md is updated — typically across sessions, not turns.
|
|
83
|
+
Because they're byte-identical turn after turn, the provider's prompt cache hits on this prefix.
|
|
84
|
+
|
|
85
|
+
- **Volatile** (`<deep-memory-volatile>`): context-aware search results from the user's
|
|
86
|
+
current query, tier-allocated by importance, plus repo map symbols for recently-read files.
|
|
87
|
+
This is the only part that changes per turn.
|
|
88
|
+
|
|
89
|
+
The injection budget adapts to the agent: main orchestrator gets 800 tokens per turn
|
|
90
|
+
(3000 on session resume), deep-reasoning agents get 400, and tool subagents get 80.
|
|
91
|
+
|
|
92
|
+
## Memory search (BM25 + CJK bigram)
|
|
93
|
+
|
|
94
|
+
Instead of SQLite FTS5, we use a pure-JS BM25 engine with a CJK-aware tokenizer.
|
|
95
|
+
Chinese runs are split into sliding 2-character bigrams (`"权限死锁"` →
|
|
96
|
+
`["权","权限","限死","死锁","锁"]`), making multi-character CJK phrases searchable
|
|
97
|
+
without an embedding model. Latin text uses standard whitespace/punctuation splitting.
|
|
98
|
+
The index is rebuilt from Markdown files on startup (<250ms for 2000 entries) and
|
|
99
|
+
updated incrementally on writes.
|
|
100
|
+
|
|
101
|
+
## Configuration
|
|
102
|
+
|
|
103
|
+
| Variable | Default | Purpose |
|
|
104
|
+
|----------|---------|---------|
|
|
105
|
+
| `DEEP_MEMORY_DEBUG` | off | `1` = debug log, `trace` = +hook I/O |
|
|
106
|
+
| `DEEP_MEMORY_PROJECT_SUBDIR` | `.deep-memory` | Memory directory name |
|
|
107
|
+
| `DEEP_MEMORY_GLOBAL_ROOT` | `~/.local/share/opencode/deep-memory` | Cross-project memory |
|
|
108
|
+
|
|
109
|
+
## Storage
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
<project>/.deep-memory/ ← version-controllable
|
|
113
|
+
├── MEMORY.md persistent decisions/constraints/gotchas
|
|
114
|
+
├── notes.md keyword captures
|
|
115
|
+
├── checkpoint.md last compaction extraction
|
|
116
|
+
├── .schedule.json dream/distill state
|
|
117
|
+
└── sessions/<sid>/ per-session archive
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Commands
|
|
121
|
+
|
|
122
|
+
Copy `.opencode/command/*.md` to your project:
|
|
123
|
+
|
|
124
|
+
- `/checkpoint` — manually capture session state
|
|
125
|
+
- `/dream` — consolidate notes into persistent memory
|
|
126
|
+
- `/distill` — package recurring workflows into skills
|
|
127
|
+
|
|
128
|
+
## Design
|
|
129
|
+
|
|
130
|
+
**Memory entries** carry a type (`decision`, `constraint`, `gotcha`, `fact`, `note`) and
|
|
131
|
+
an importance score. Importance is heuristically derived from entry type, recency,
|
|
132
|
+
frequency across sessions, and keyword-match relevance to the current query —
|
|
133
|
+
no LLM calls required.
|
|
134
|
+
|
|
135
|
+
Entries are stored as Markdown sections (e.g. `## Decisions`, `## Constraints`) in
|
|
136
|
+
`MEMORY.md`, with `[date]` timestamps for time-based decay. The BM25 index is rebuilt
|
|
137
|
+
from these files on startup and updated incrementally on write.
|
|
138
|
+
|
|
139
|
+
Background consolidation runs on a 7-day cycle (auto-dream) plus an accumulation trigger
|
|
140
|
+
(when `notes.md` exceeds 20 lines). A separate 30-day cycle (auto-distill) packages
|
|
141
|
+
recurring workflows into skill candidates. Both use background sessions to avoid
|
|
142
|
+
consuming the main session's context budget.
|
|
143
|
+
|
|
144
|
+
## Acknowledgments
|
|
145
|
+
|
|
146
|
+
**[MiMo-Code][]** — a terminal-native AI coding assistant with persistent memory that keeps a
|
|
147
|
+
deep understanding of your project across sessions while continuously improving itself.
|
|
148
|
+
|
|
149
|
+
**[Magic Context][]** — unbounded context. Memory that manages itself. One session, for life.
|
|
150
|
+
The hippocampus for coding agents, part of CortexKit.
|
|
151
|
+
|
|
152
|
+
**[Aider][]** — AI pair programming in your terminal. Lets you pair program with LLMs to start
|
|
153
|
+
a new project or build on your existing codebase.
|
|
154
|
+
|
|
155
|
+
**[Roo Code][]** — a whole dev team of AI agents in your code editor.
|
|
156
|
+
|
|
157
|
+
**[Continue][]** — pioneering open-source coding agent, available as a CLI, VS Code extension,
|
|
158
|
+
and JetBrains plugin.
|
|
159
|
+
|
|
160
|
+
**[OpenHands][]** — Code Less, Make More. A community focused on AI-driven development.
|
|
161
|
+
|
|
162
|
+
**[Plandex][]** — an AI coding agent designed for large tasks and real world projects.
|
|
163
|
+
|
|
164
|
+
[MiMo-Code]: https://github.com/XiaomiMiMo/MiMo-Code
|
|
165
|
+
[Magic Context]: https://github.com/cortexkit/magic-context
|
|
166
|
+
[Aider]: https://github.com/Aider-AI/aider
|
|
167
|
+
[Roo Code]: https://github.com/RooCodeInc/Roo-Code
|
|
168
|
+
[Continue]: https://github.com/continuedev/continue
|
|
169
|
+
[OpenHands]: https://github.com/All-Hands-AI/OpenHands
|
|
170
|
+
[Plandex]: https://github.com/plandex-ai/plandex
|
|
171
|
+
|
|
172
|
+
## Development
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
npm install
|
|
176
|
+
npm run verify # typecheck + test (363) + build + smoke (49)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## License
|
|
180
|
+
|
|
181
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Plugin, PluginModule } from '@opencode-ai/plugin';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* opencode-deep-memory — Plugin Entry
|
|
5
|
+
*
|
|
6
|
+
* Wires together all hooks and tools:
|
|
7
|
+
* - chat.params: record sessionID → agent map
|
|
8
|
+
* - chat.message: capture keyword-matching user messages to notes.md
|
|
9
|
+
* - experimental.chat.system.transform: adaptive memory injection
|
|
10
|
+
* - event: session.created → resume detection + auto-dream scheduling
|
|
11
|
+
* - tool: memory_search / memory_store / memory_forget
|
|
12
|
+
*
|
|
13
|
+
* Storage: <data>/local-memory/{global,projects/<hash>}/...
|
|
14
|
+
* See DESIGN.md for full architecture.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
declare const deepMemoryPlugin: Plugin;
|
|
18
|
+
declare const pluginModule: PluginModule;
|
|
19
|
+
|
|
20
|
+
export { deepMemoryPlugin, pluginModule as default };
|