@bd7pil/opencode-deep-memory 0.8.7 → 0.9.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 +143 -172
- package/dist/ccr-REOCHH53.js +12 -0
- package/dist/ccr-REOCHH53.js.map +1 -0
- package/dist/chunk-FUQATBWM.js +43 -0
- package/dist/chunk-FUQATBWM.js.map +1 -0
- package/dist/index.d.ts +3 -4
- package/dist/index.js +472 -1872
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,17 +1,8 @@
|
|
|
1
1
|
# opencode-deep-memory
|
|
2
2
|
|
|
3
|
-
> Persistent memory
|
|
3
|
+
> Persistent cross-session memory for [OpenCode](https://github.com/anomalyco/opencode) — zero runtime dependencies.
|
|
4
4
|
|
|
5
|
-
|
|
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 | 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 |
|
|
5
|
+
V4 architecture. Built on research from 7 production coding agents, 30+ memory systems, and 5 academic papers. Eliminates the two independent LLM output degradation paths found in V2: volatile system-prompt injection and post-hoc tool output compression.
|
|
15
6
|
|
|
16
7
|
## Quick start
|
|
17
8
|
|
|
@@ -25,211 +16,191 @@ destroys conversation content. **deep-memory** adds three layers:
|
|
|
25
16
|
}
|
|
26
17
|
```
|
|
27
18
|
|
|
28
|
-
|
|
19
|
+
Memory lives at `.deep-memory/` in your project root.
|
|
29
20
|
|
|
30
|
-
##
|
|
21
|
+
## What it does
|
|
31
22
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
└─────────────────────────────────────────────────────────────────┘
|
|
60
|
-
```
|
|
23
|
+
| Capability | How |
|
|
24
|
+
|---|---|
|
|
25
|
+
| **Remember** decisions, constraints, gotchas, facts | `memory_store` → BM25-indexed `MEMORY.md` (200 line cap) |
|
|
26
|
+
| **Retrieve** across sessions | `memory_search` — BM25 + CJK bigram |
|
|
27
|
+
| **Forget** stale entries | `memory_forget` — by query + confirmation |
|
|
28
|
+
| **Recover** compressed content | `deep_expand` / `memory_expand` — SHA-256 CCR, 30min cache |
|
|
29
|
+
| **Compress** on demand | `context_compress` — agent-initiated, originals recoverable |
|
|
30
|
+
| **Deduplicate** on compaction | SIMHash dedup of MEMORY.md (synchronous, no LLM) |
|
|
61
31
|
|
|
62
|
-
##
|
|
32
|
+
## 6-Layer architecture
|
|
63
33
|
|
|
64
|
-
|
|
34
|
+
All six layers are backed by production evidence — not theory.
|
|
65
35
|
|
|
66
|
-
### Layer 1:
|
|
36
|
+
### Layer 1: Capture-time tool output limiting
|
|
67
37
|
|
|
68
|
-
|
|
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 |
|
|
38
|
+
Tool outputs are capped once at capture time, not post-hoc mid-conversation.
|
|
74
39
|
|
|
75
|
-
|
|
40
|
+
| Tool | Default cap | Strategy |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| `bash` | 48K chars | Head + error lines + tail 200 + recovery hint |
|
|
43
|
+
| `read` | 50K chars | Head + tail + key lines + re-read hint |
|
|
44
|
+
| `grep`/`search` | 20 files × 5 matches | Group by file, top matches |
|
|
45
|
+
| `task`/`background_output` | 30K chars | Headers + code fences + key lines |
|
|
46
|
+
| `webfetch` | 20K chars | Head + headings + tail |
|
|
76
47
|
|
|
77
|
-
|
|
48
|
+
Recovery hint tells the LLM how to get more detail (re-read with offset, grep with pattern), not a dead-end marker.
|
|
78
49
|
|
|
79
|
-
|
|
80
|
-
|----------|-----------|---------|
|
|
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) |
|
|
50
|
+
**Evidence**: Cline source (`output-limits.ts`: bash 48K, read 50K). Aider and Cody: no post-hoc compression at all.
|
|
84
51
|
|
|
85
|
-
|
|
52
|
+
### Layer 2: Stale-read rewriting
|
|
86
53
|
|
|
87
|
-
|
|
88
|
-
|--------|----------|--------|
|
|
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
|
-
| Subagent output | Headers + key lines + tail with [ccr:] preservation | [Claude Code][] |
|
|
96
|
-
| Skill output | Frontmatter + MUST rules + structure headers | [Claude Code][] |
|
|
97
|
-
| Nested JSON objects | Compress child arrays >30 items | This project |
|
|
98
|
-
| Old assistant text | Preserve structure, compress prose | [LLMLingua][] |
|
|
54
|
+
When the same tool is called multiple times with identical input+output, older copies are marked `[OUTDATED — superseded by newer identical call]`. The LLM sees a useful signal instead of a meaningless placeholder that it may mimic in output.
|
|
99
55
|
|
|
100
|
-
|
|
56
|
+
**Replaces**: `[superseded by duplicate call]` placeholder (V2) and `[context-stripped]` orphan repair — both known to cause the LLM to produce placeholder-style output.
|
|
101
57
|
|
|
102
|
-
|
|
58
|
+
### Layer 3: Static memory file (byte-stable system prompt)
|
|
103
59
|
|
|
104
|
-
|
|
60
|
+
The system prompt is frozen across turns — TOOL_HINT + MEMORY.md content are injected once and only change when `memory_store` writes to MEMORY.md (mtime cache). No volatile BM25 results, no per-turn search, no repomap in the system prompt.
|
|
105
61
|
|
|
106
|
-
|
|
62
|
+
```
|
|
63
|
+
Position 0 (frozen): TOOL_HINT — ~150 tokens, byte-identical every turn
|
|
64
|
+
Position 0 (cached): MEMORY.md — up to 200 lines / 25KB, cached by mtime
|
|
65
|
+
```
|
|
107
66
|
|
|
108
|
-
|
|
67
|
+
When MEMORY.md hasn't changed: 100% byte-stable system prompt across turns.
|
|
109
68
|
|
|
110
|
-
|
|
111
|
-
|---------|---------|-------|
|
|
112
|
-
| Decision | "我决定用 PostgreSQL" / "I'll use PostgreSQL" | `memory_store(type="decision")` |
|
|
113
|
-
| Constraint | "不能用 eval()" / "must not use eval()" | `memory_store(type="constraint")` |
|
|
114
|
-
| Error fix | "修复了权限问题" / "fixed the permission error" | `memory_store(type="gotcha")` |
|
|
69
|
+
**Key difference from V2**: V2 injected BM25 search results (560–2720 tokens) into `system[1]` every turn, changing content per-turn. This violated the consensus that system prompts should be byte-stable (Cognee, Aider, Copilot all inject dynamic content in user message, not system prompt). Context Rot research (Chroma 2025) confirmed all 18 tested models degrade with per-turn mutation.
|
|
115
70
|
|
|
116
|
-
|
|
71
|
+
### Layer 4: Hybrid retrieval (one-time auto-search)
|
|
117
72
|
|
|
118
|
-
|
|
73
|
+
Pure pull-based retrieval doesn't work reliably — When2Tool (arxiv 2605.09252) shows LLMs know when to retrieve (hidden-state AUROC 0.89) but fail to act during generation. V4 uses a hybrid:
|
|
119
74
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
| `memory_store` | Store decisions, constraints, gotchas, facts, notes |
|
|
124
|
-
| `memory_forget` | Remove stale memory entries |
|
|
125
|
-
| `memory_expand` | Retrieve original content of a compressed message |
|
|
126
|
-
| `deep_expand` | Retrieve original content via CCR hash |
|
|
75
|
+
- **First turn only**: quiet `memory_search(userQuery)` runs. If top-1 BM25 score ≥ 2.0, a ≤30-token whisper is appended: `[memory hint: N relevant entries ...]`
|
|
76
|
+
- **Turns 2+**: system prompt is byte-stable. Zero whisper overhead.
|
|
77
|
+
- **On demand**: `memory_search` tool is always available.
|
|
127
78
|
|
|
128
|
-
|
|
79
|
+
### Layer 5: Synchronous consolidation (no background)
|
|
129
80
|
|
|
130
|
-
|
|
81
|
+
V2's dream/distill used `client.session.promptAsync` fire-and-forget — it never worked because the main process doesn't persist for 7-day cycles. V4 consolidation is strictly synchronous, runs inside hooks:
|
|
131
82
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
83
|
+
| Trigger | Action | Duration |
|
|
84
|
+
|---|---|---|
|
|
85
|
+
| `session.compacting` hook | SIMHash dedup of MEMORY.md (≥0.92 similarity threshold) | <100ms |
|
|
86
|
+
| `/checkpoint` command | Manual memory capture + dedup | <200ms |
|
|
87
|
+
| `memory_store` after 200 lines | Overflow to MEMORY-archive.md | <10ms |
|
|
136
88
|
|
|
137
|
-
|
|
89
|
+
No `promptAsync`, no `setInterval`, no child sessions, no LLM calls in consolidation.
|
|
138
90
|
|
|
139
|
-
|
|
91
|
+
### Layer 6: Agent-initiated compression
|
|
140
92
|
|
|
141
|
-
|
|
142
|
-
|-------|---------|--------|
|
|
143
|
-
| **Auto-dream** | 7 days or notes.md >20 lines | Consolidate notes + checkpoints → MEMORY.md |
|
|
144
|
-
| **Auto-distill** | 30 days | Package recurring workflows → skill candidates |
|
|
145
|
-
| **Enrichment** | Session idle after compaction | LLM enriches checkpoint with cross-references |
|
|
93
|
+
When the LLM feels context is bloated, it calls `context_compress(keep_recent=8)`. This sets a flag consumed by the next `messages.transform`, which replaces old tool outputs with head/tail summaries. Originals stored in CCR — `deep_expand` retrieves them.
|
|
146
94
|
|
|
147
|
-
|
|
95
|
+
CCR markers are actionable: `[compressed — call deep_expand("hash") to restore original]` instead of V2's dead-end `[ccr:hash]`.
|
|
148
96
|
|
|
149
|
-
##
|
|
97
|
+
## Tools
|
|
150
98
|
|
|
151
|
-
|
|
|
152
|
-
|
|
153
|
-
| `
|
|
154
|
-
| `
|
|
155
|
-
| `
|
|
99
|
+
| Tool | Purpose |
|
|
100
|
+
|---|---|
|
|
101
|
+
| `memory_search` | BM25 + CJK bigram search across project and global memory |
|
|
102
|
+
| `memory_store` | Store one entry (decision/constraint/gotcha/fact/note) |
|
|
103
|
+
| `memory_forget` | Find matching entries and remove them |
|
|
104
|
+
| `memory_expand` | Restore original content from compressed conversation messages |
|
|
105
|
+
| `deep_expand` | Restore original content from CCR-compressed tool output |
|
|
106
|
+
| `context_compress` | Request compression of old tool outputs on next turn |
|
|
107
|
+
|
|
108
|
+
## Commands
|
|
109
|
+
|
|
110
|
+
- `/checkpoint` — capture session state + consolidate MEMORY.md (SIMHash dedup)
|
|
111
|
+
|
|
112
|
+
## Compaction
|
|
113
|
+
|
|
114
|
+
When OpenCode compacts a session:
|
|
115
|
+
1. Capture raw messages to `checkpoint.md` via 5 heuristic extractors
|
|
116
|
+
2. Deduplicate MEMORY.md via SIMHash (acquired via file lock, zero race conditions)
|
|
117
|
+
3. Inject structured handoff prompt for LLM
|
|
118
|
+
|
|
119
|
+
No background LLM sessions, no `client.session.promptAsync`, no dream/distill.
|
|
156
120
|
|
|
157
121
|
## Storage
|
|
158
122
|
|
|
159
123
|
```
|
|
160
124
|
<project>/.deep-memory/
|
|
161
|
-
├── MEMORY.md
|
|
162
|
-
├──
|
|
163
|
-
├── checkpoint.md
|
|
164
|
-
├──
|
|
165
|
-
|
|
166
|
-
├── .compaction-log.jsonl compaction audit trail
|
|
167
|
-
└── sessions/<sid>/ per-session archive
|
|
125
|
+
├── MEMORY.md persistent memory (200 line cap, user curated)
|
|
126
|
+
├── MEMORY-archive.md overflow when cap is reached
|
|
127
|
+
├── checkpoint.md last compaction extraction
|
|
128
|
+
├── .compaction-log.jsonl compaction audit trail
|
|
129
|
+
└── .index-state.json BM25 index mtime tracker
|
|
168
130
|
```
|
|
169
131
|
|
|
170
|
-
##
|
|
132
|
+
## Configuration
|
|
171
133
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
134
|
+
| Variable | Default | Purpose |
|
|
135
|
+
|---|---|---|
|
|
136
|
+
| `DEEP_MEMORY_DEBUG` | off | `1` = debug log, `trace` = +hook I/O |
|
|
137
|
+
| `DEEP_MEMORY_PROJECT_SUBDIR` | `.deep-memory` | Memory directory name |
|
|
138
|
+
| `DEEP_MEMORY_GLOBAL_ROOT` | `~/.local/share/opencode/deep-memory` | Cross-project memory |
|
|
175
139
|
|
|
176
140
|
## Development
|
|
177
141
|
|
|
178
142
|
```bash
|
|
179
143
|
npm install
|
|
180
|
-
npm run verify # typecheck + test
|
|
144
|
+
npm run verify # typecheck + test + build + smoke
|
|
181
145
|
```
|
|
182
146
|
|
|
183
|
-
##
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
**
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
**
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
[
|
|
228
|
-
[
|
|
229
|
-
[
|
|
230
|
-
[
|
|
231
|
-
[
|
|
232
|
-
|
|
147
|
+
## What V4 removed (and why)
|
|
148
|
+
|
|
149
|
+
| Feature | Failure mode | Replacement |
|
|
150
|
+
|---|---|---|
|
|
151
|
+
| Volatile BM25 injection in system prompt | Per-turn mutation degrades quality (Context Rot, 18 models) | Frozen TOOL_HINT + mtime-cached MEMORY.md |
|
|
152
|
+
| Dream/distill auto-generation | `promptAsync` fire-and-forget never worked (3 independent failure layers) | User-curated MEMORY.md + sync consolidation |
|
|
153
|
+
| Post-hoc tool output compression | Middle content lost mid-conversation | Capture-time caps (Cline pattern) |
|
|
154
|
+
| `[superseded by duplicate call]` | LLM mimics placeholder in output | `[OUTDATED]` signal |
|
|
155
|
+
| `[context-stripped]` orphan repair | Same | Removed entirely |
|
|
156
|
+
| `[ccr:<hash>]` dead-end markers | Stored but unretrievable | Actionable hint + working deep_expand |
|
|
157
|
+
| Memory nudge / pressure nudge XML | Contradicts pull-based model | Agent-initiated `context_compress` |
|
|
158
|
+
| Tier-based memory rendering (P1-P5) | Unnecessary complexity | Full MEMORY.md injected verbatim |
|
|
159
|
+
|
|
160
|
+
## Evidence base
|
|
161
|
+
|
|
162
|
+
V4 was designed through 3 rounds of research against production systems and academic literature.
|
|
163
|
+
|
|
164
|
+
### Production coding agents (7)
|
|
165
|
+
|
|
166
|
+
| Agent | Key insight borrowed |
|
|
167
|
+
|---|---|
|
|
168
|
+
| **Claude Code** | CLAUDE.md verbatim injection, user-curated, never auto-generated; 200-line/25KB hard cap |
|
|
169
|
+
| **Cline** | Capture-time tool output caps (bash 48K, read 50K); stale-read rewriting; 90% compaction trigger |
|
|
170
|
+
| **Aider** | No post-hoc tool compression; background recursive summarization |
|
|
171
|
+
| **Cursor** | Same-model self-summarization preserves quality |
|
|
172
|
+
| **Cody** | No compression at all — pure retrieval |
|
|
173
|
+
| **Copilot** | 4 cache-control breakpoints → 94% cache hit rate |
|
|
174
|
+
| **Continue** | Context-aware truncation direction |
|
|
175
|
+
|
|
176
|
+
### Memory systems surveyed (30+)
|
|
177
|
+
|
|
178
|
+
- **Mem0** — pull-based search, no auto-injection
|
|
179
|
+
- **Letta** — fixed-size memory blocks, agent-managed content mutation
|
|
180
|
+
- **Magic Context** — cache-stable deferred mutation; zero per-turn change
|
|
181
|
+
- **A-Mem** — proactive dedup/update prevents stale context accumulation
|
|
182
|
+
- **Cognee** — injects memory in user message, not system prompt (keeps prefix stable)
|
|
183
|
+
- **DCP** — LLM-initiated compress tool (model decides what to compress)
|
|
184
|
+
- **Headroom** — CCR store with lossless recovery
|
|
185
|
+
- **LLMLingua** — token-level perplexity compression (avoided: too aggressive for code)
|
|
186
|
+
- **Focus Agent** — agent-initiated `consolidate_learning` + persistent Knowledge block
|
|
187
|
+
- **Edgee** — protected-content patterns
|
|
188
|
+
|
|
189
|
+
### Academic papers
|
|
190
|
+
|
|
191
|
+
- [Lost in the Middle](https://arxiv.org/abs/2307.03172) — 20%+ accuracy drop for mid-prompt content (Liu et al., TACL 2024)
|
|
192
|
+
- [Context Rot](https://www.trychroma.com/research/context-rot) — all 18 tested models degrade with prompt length (Chroma 2025)
|
|
193
|
+
- [When2Tool](https://arxiv.org/abs/2605.09252) — LLMs know when to retrieve (AUROC 0.89-0.96) but fail to act; pure pull not viable (arxiv 2605.09252)
|
|
194
|
+
- [Self-RAG](https://arxiv.org/abs/2310.11511) — adaptive retrieval requires fine-tuning (arxiv 2310.11511)
|
|
195
|
+
- [Focus Agent](https://arxiv.org/html/2601.07190v1) — 22.7% token reduction, no accuracy loss (arxiv 2601.07190)
|
|
196
|
+
|
|
197
|
+
### Design decisions (stored in project memory)
|
|
198
|
+
|
|
199
|
+
- [V4 prohibits background/fire-and-forget patterns — dream/distill failure post-mortem]
|
|
200
|
+
- [6-layer architecture — all layers have production evidence]
|
|
201
|
+
- [D1: MEMORY.md 200 lines / 25KB — Claude Code source-enforced]
|
|
202
|
+
- [D3: capture-time caps, Cline defaults, configurable]
|
|
203
|
+
- [D5: MEMORY.md in system.transform with mtime caching — SDK constraint: messages.transform has no sessionID]
|
|
233
204
|
|
|
234
205
|
## License
|
|
235
206
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/* opencode-deep-memory — zero runtime dependencies */
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __export = (target, all) => {
|
|
4
|
+
for (var name in all)
|
|
5
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
// src/compress/ccr.ts
|
|
9
|
+
import { createHash } from "crypto";
|
|
10
|
+
var CCR_TTL_MS = 30 * 60 * 1e3;
|
|
11
|
+
function ccrStore(state, original, compressed, toolName, callID) {
|
|
12
|
+
const hash = sha256(original).slice(0, 24);
|
|
13
|
+
state.ccStore(hash, {
|
|
14
|
+
hash,
|
|
15
|
+
original,
|
|
16
|
+
compressed,
|
|
17
|
+
createdAt: Date.now(),
|
|
18
|
+
toolName,
|
|
19
|
+
callID
|
|
20
|
+
});
|
|
21
|
+
return hash;
|
|
22
|
+
}
|
|
23
|
+
function ccrRetrieve(state, hash) {
|
|
24
|
+
const entry = state.ccrGet(hash);
|
|
25
|
+
if (!entry) return void 0;
|
|
26
|
+
if (Date.now() - entry.createdAt > CCR_TTL_MS) return void 0;
|
|
27
|
+
return entry.original;
|
|
28
|
+
}
|
|
29
|
+
function ccrInjectMarker(compressed, hash) {
|
|
30
|
+
return `${compressed}
|
|
31
|
+
[compressed \u2014 call deep_expand("${hash}") to restore original]`;
|
|
32
|
+
}
|
|
33
|
+
function sha256(data) {
|
|
34
|
+
return createHash("sha256").update(data).digest("hex");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export {
|
|
38
|
+
__export,
|
|
39
|
+
ccrStore,
|
|
40
|
+
ccrRetrieve,
|
|
41
|
+
ccrInjectMarker
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=chunk-FUQATBWM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/compress/ccr.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport type { PluginState } from \"../hooks/shared-state.js\";\n\nconst CCR_TTL_MS = 30 * 60 * 1000;\n\nexport function ccrStore(\n state: PluginState,\n original: string,\n compressed: string,\n toolName?: string,\n callID?: string,\n): string {\n const hash = sha256(original).slice(0, 24);\n state.ccStore(hash, {\n hash,\n original,\n compressed,\n createdAt: Date.now(),\n toolName,\n callID,\n });\n return hash;\n}\n\nexport function ccrRetrieve(state: PluginState, hash: string): string | undefined {\n const entry = state.ccrGet(hash);\n if (!entry) return undefined;\n if (Date.now() - entry.createdAt > CCR_TTL_MS) return undefined;\n return entry.original;\n}\n\nexport function ccrInjectMarker(compressed: string, hash: string): string {\n return `${compressed}\\n[compressed — call deep_expand(\"${hash}\") to restore original]`;\n}\n\nfunction sha256(data: string): string {\n return createHash(\"sha256\").update(data).digest(\"hex\");\n}\n"],"mappings":";;;;;;;;AAAA,SAAS,kBAAkB;AAG3B,IAAM,aAAa,KAAK,KAAK;AAEtB,SAAS,SACd,OACA,UACA,YACA,UACA,QACQ;AACR,QAAM,OAAO,OAAO,QAAQ,EAAE,MAAM,GAAG,EAAE;AACzC,QAAM,QAAQ,MAAM;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW,KAAK,IAAI;AAAA,IACpB;AAAA,IACA;AAAA,EACF,CAAC;AACD,SAAO;AACT;AAEO,SAAS,YAAY,OAAoB,MAAkC;AAChF,QAAM,QAAQ,MAAM,OAAO,IAAI;AAC/B,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,KAAK,IAAI,IAAI,MAAM,YAAY,WAAY,QAAO;AACtD,SAAO,MAAM;AACf;AAEO,SAAS,gBAAgB,YAAoB,MAAsB;AACxE,SAAO,GAAG,UAAU;AAAA,uCAAqC,IAAI;AAC/D;AAEA,SAAS,OAAO,MAAsB;AACpC,SAAO,WAAW,QAAQ,EAAE,OAAO,IAAI,EAAE,OAAO,KAAK;AACvD;","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,10 +5,9 @@ import { Plugin, PluginModule } from '@opencode-ai/plugin';
|
|
|
5
5
|
*
|
|
6
6
|
* Wires together all hooks and tools:
|
|
7
7
|
* - chat.params: record sessionID → agent map
|
|
8
|
-
* - chat.
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
11
|
-
* - tool: memory_search / memory_store / memory_forget
|
|
8
|
+
* - experimental.chat.system.transform: V4 frozen TOOL_HINT + mtime-cached MEMORY.md
|
|
9
|
+
* - event: session.compacted → pressure calibration + audit log
|
|
10
|
+
* - tool: memory_search / memory_store / memory_forget / memory_expand / context_compress
|
|
12
11
|
*
|
|
13
12
|
* Storage: <data>/local-memory/{global,projects/<hash>}/...
|
|
14
13
|
* See DESIGN.md for full architecture.
|