@qdang46/opencode-dcp-plugin 0.2.1 → 0.2.2

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.
Files changed (2) hide show
  1. package/README.md +346 -23
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,24 +1,22 @@
1
+ <div align="center">
2
+
1
3
  # @qdang46/opencode-dcp-plugin
2
4
 
3
- NAPI-RS native Dynamic Context Pruning plugin for [OpenCode](https://github.com/anomalyco/opencode).
5
+ **NAPI-RS native Dynamic Context Pruning plugin for [OpenCode](https://github.com/anomalyco/opencode)**
6
+
7
+ [![npm version](https://img.shields.io/npm/v/@qdang46/opencode-dcp-plugin?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@qdang46/opencode-dcp-plugin)
8
+ [![License: MIT](https://img.shields.io/github/license/quangdang46/dynamic_context_pruning?style=for-the-badge)](https://github.com/quangdang46/dynamic_context_pruning/blob/main/LICENSE)
9
+ [![npm downloads](https://img.shields.io/npm/dm/@qdang46/opencode-dcp-plugin?style=for-the-badge)](https://www.npmjs.com/package/@qdang46/opencode-dcp-plugin)
4
10
 
5
11
  Automatically reduces token usage in OpenCode sessions by pruning obsolete tool outputs,
6
12
  deduplicating repeated calls, purging errored tool inputs, and compressing stale conversation
7
13
  content — all powered by a Rust native addon for zero-serialization performance.
8
14
 
9
- ## Installation
15
+ </div>
10
16
 
11
- ```bash
12
- opencode plugin add @qdang46/opencode-dcp-plugin
13
- ```
17
+ ---
14
18
 
15
- Or globally:
16
-
17
- ```bash
18
- opencode plugin @qdang46/opencode-dcp-plugin@latest --global
19
- ```
20
-
21
- ## Features
19
+ ## ✨ Features
22
20
 
23
21
  | Feature | Description |
24
22
  |---------|-------------|
@@ -26,29 +24,354 @@ opencode plugin @qdang46/opencode-dcp-plugin@latest --global
26
24
  | **System prompt injection** | Appends DCP instructions so the model can use the compress tool |
27
25
  | **Compress tool** | LLM-driven compression of stale conversation ranges into technical summaries |
28
26
  | **Decompress / Recompress** | Restore or re-activate compressed blocks on demand |
29
- | **Slash commands** | `/dcp context`, `/dcp stats`, `/dcp sweep`, `/dcp manual`, `/dcp decompress`, `/dcp recompress` |
27
+ | **Slash commands** | `/dcp`, `/dcp-compress` for interactive context management |
30
28
  | **Config cascade** | JSONC config loaded from 4-tier cascade (builtin → global → custom → project) |
31
29
  | **Cache stability** | `agent-message`, `aggressive`, or `manual` modes for prompt cache preservation |
32
30
  | **Protected tools** | Glob patterns to keep specific tool outputs from being pruned |
31
+ | **Turn protection** | Shield recent N turns from compression suggestions |
32
+ | **Purge errors** | Automatically purge errored tool outputs after N turns |
33
+ | **Stale file reads** | Remove stale file read outputs when files are modified |
34
+ | **Deduplication** | Merge duplicate tool calls and outputs |
35
+
36
+ ---
37
+
38
+ ## 🚀 Installation
39
+
40
+ ### Global (Recommended)
41
+
42
+ ```bash
43
+ opencode plugin @qdang46/opencode-dcp-plugin --global
44
+ ```
45
+
46
+ ### Local (Project-scoped)
47
+
48
+ ```bash
49
+ cd your-project
50
+ opencode plugin @qdang46/opencode-dcp-plugin
51
+ ```
52
+
53
+ ### Manual
54
+
55
+ Add to your `~/.config/opencode/opencode.jsonc`:
56
+
57
+ ```jsonc
58
+ {
59
+ "plugin": [
60
+ "@qdang46/opencode-dcp-plugin"
61
+ ]
62
+ }
63
+ ```
64
+
65
+ And install dependencies:
66
+
67
+ ```bash
68
+ cd ~/.config/opencode && npm install @qdang46/opencode-dcp-plugin@latest
69
+ ```
70
+
71
+ ---
33
72
 
34
- ## Configuration
73
+ ## ⚙️ Configuration
35
74
 
36
- DCP loads configuration from `.dynamic_context_pruning/config.jsonc` in your project directory.
37
- See the [dcp.schema.json](./dcp.schema.json) for the full config schema.
75
+ DCP loads configuration from multiple sources in cascade order (later overrides earlier):
38
76
 
39
- ## Development
77
+ 1. **Built-in defaults** — compiled into the binary
78
+ 2. **Global** — `~/.config/dynamic_context_pruning/config.jsonc` (or `$XDG_CONFIG_HOME/...`)
79
+ 3. **Custom** — `$DCP_CONFIG_DIR/config.jsonc` (if env var is set)
80
+ 4. **Project** — `.dynamic_context_pruning/config.jsonc` in working directory or ancestor
81
+
82
+ ### Create Global Config
40
83
 
41
84
  ```bash
42
- # Build the Rust native addon
43
- cargo build --release -p opencode-dcp-bridge
85
+ mkdir -p ~/.config/dynamic_context_pruning
86
+ cat > ~/.config/dynamic_context_pruning/config.jsonc << 'EOF'
87
+ {
88
+ "enabled": true,
89
+ "debug": false,
90
+
91
+ "compress": {
92
+ "mode": "range",
93
+ "permission": "allow",
94
+ "maxContextLimit": 100000,
95
+ "minContextLimit": 50000,
96
+ "protectedTools": ["task", "skill", "read", "write", "edit"],
97
+ "protectTags": true,
98
+ "maxSummaryChars": 32768
99
+ },
100
+
101
+ "strategies": {
102
+ "deduplication": { "enabled": true },
103
+ "purgeErrors": { "enabled": true, "turns": 4 },
104
+ "staleFileReads": { "enabled": true }
105
+ },
106
+
107
+ "turnProtection": {
108
+ "enabled": true,
109
+ "turns": 4
110
+ },
111
+
112
+ "commands": { "enabled": true },
113
+ "notification": { "level": "detailed", "kind": "chat" }
114
+ }
115
+ EOF
116
+ ```
117
+
118
+ ### Key Config Options
119
+
120
+ ```jsonc
121
+ {
122
+ // Master switch
123
+ "enabled": true,
124
+
125
+ // Compress tool configuration
126
+ "compress": {
127
+ "mode": "range", // "range" | "message"
128
+ "permission": "allow", // "ask" | "allow" | "deny"
129
+ "maxContextLimit": 100000, // Max context tokens before compression
130
+ "minContextLimit": 50000, // Min context tokens to maintain
131
+ "protectedTools": ["task"], // Tools whose output is preserved
132
+ "protectTags": true, // Preserve <dcp-protected> tags
133
+ "protectUserMessages": false, // Protect user messages from compression
134
+ "maxSummaryChars": 32768 // Max summary length per block
135
+ },
136
+
137
+ // Pruning strategies
138
+ "strategies": {
139
+ "deduplication": { "enabled": true },
140
+ "purgeErrors": { "enabled": true, "turns": 4 },
141
+ "staleFileReads": { "enabled": true, "trackedTools": ["read", "write", "edit"] }
142
+ },
143
+
144
+ // Turn protection
145
+ "turnProtection": {
146
+ "enabled": true,
147
+ "turns": 4 // Protect last 4 turns from compression
148
+ },
149
+
150
+ // Manual mode
151
+ "manualMode": {
152
+ "enabled": false,
153
+ "automaticStrategies": true
154
+ },
155
+
156
+ // Cache stability
157
+ "cacheStabilityMode": "agent-message", // "aggressive" | "agent-message" | "manual"
158
+
159
+ // Notification preferences
160
+ "notification": {
161
+ "level": "detailed", // "off" | "minimal" | "detailed"
162
+ "kind": "chat" // "chat" | "toast"
163
+ }
164
+ }
165
+ ```
166
+
167
+ ---
168
+
169
+ ## 🎮 Usage
170
+
171
+ ### Slash Commands
172
+
173
+ | Command | Description |
174
+ |---------|-------------|
175
+ | `/dcp` | Show help and available commands |
176
+ | `/dcp context` | Show context analysis (turns, blocks, tokens) |
177
+ | `/dcp stats` | Show pruning statistics |
178
+ | `/dcp sweep` | Flush pending prune strategies |
179
+ | `/dcp manual <on\|off>` | Toggle manual mode |
180
+ | `/dcp decompress <id>` | Restore a compressed block |
181
+ | `/dcp recompress <id>` | Re-activate a decompressed block |
182
+ | `/dcp-compress [focus]` | Trigger manual compression with optional focus topic |
183
+
184
+ ### LLM Tools
185
+
186
+ The plugin exposes these tools to the LLM:
187
+
188
+ - **`compress`** — Replace stale conversation content with technical summaries
189
+ - **`decompress`** — Restore a compressed block to its original messages
190
+ - **`recompress`** — Re-activate a user-decompressed block for future compression
191
+
192
+ ### Example Workflow
193
+
194
+ 1. **Start OpenCode** — DCP loads automatically and monitors context
195
+ 2. **Continue working** — DCP automatically deduplicates, purges errors, and removes stale reads
196
+ 3. **Context grows** — DCP nudges the model to compress stale content
197
+ 4. **Model compresses** — Stale content replaced with `<dcp-block>` summaries
198
+ 5. **Inspect** — Use `/dcp context` to see current state
199
+ 6. **Decompress if needed** — `/dcp decompress 1` to restore compressed block
200
+
201
+ ---
202
+
203
+ ## 🔧 Development
204
+
205
+ ### Prerequisites
206
+
207
+ - Rust 1.75+ (with `cargo`)
208
+ - Node.js 18+
209
+ - macOS (ARM64) or Linux (x64)
210
+
211
+ ### Build
212
+
213
+ ```bash
214
+ # Clone the repo
215
+ git clone https://github.com/quangdang46/dynamic_context_pruning.git
216
+ cd dynamic_context_pruning/opencode-dcp-plugin
217
+
218
+ # Build Rust native addon (debug)
219
+ npm run build
220
+
221
+ # Build Rust native addon (release)
222
+ npm run build:release
44
223
 
45
224
  # Compile TypeScript
46
- cd opencode-dcp-plugin && npx tsc
225
+ npx tsc
226
+
227
+ # Typecheck only
228
+ npm run typecheck
229
+ ```
230
+
231
+ ### Test
47
232
 
48
- # Test
233
+ ```bash
234
+ # Test native addon loading
49
235
  node -e "require('./opencode-dcp-bridge.darwin-arm64.node')"
236
+
237
+ # Test full plugin
238
+ cd ~/.config/opencode
239
+ node -e "
240
+ import('@qdang46/opencode-dcp-plugin').then(async (mod) => {
241
+ const plugin = mod.default;
242
+ const instance = await plugin.server({});
243
+ console.log('✅ Plugin loaded');
244
+ console.log('Hooks:', Object.keys(instance));
245
+ });
246
+ "
50
247
  ```
51
248
 
52
- ## License
249
+ ### Publish
250
+
251
+ ```bash
252
+ # Update version
253
+ npm version patch # or minor, major
254
+
255
+ # Build and publish
256
+ npm publish --access public
257
+
258
+ # Verify
259
+ npm view @qdang46/opencode-dcp-plugin
260
+ ```
261
+
262
+ ---
263
+
264
+ ## 📖 How It Works
265
+
266
+ ### Architecture
267
+
268
+ ```
269
+ ┌─────────────────────────────────────────────────────────────┐
270
+ │ OpenCode TUI │
271
+ ├─────────────────────────────────────────────────────────────┤
272
+ │ Plugin System │
273
+ │ ┌─────────────────────────────────────────────────────┐ │
274
+ │ │ @qdang46/opencode-dcp-plugin (TypeScript) │ │
275
+ │ │ ┌─────────────────────────────────────────────┐ │ │
276
+ │ │ │ opencode-dcp-bridge (Rust NAPI-RS) │ │ │
277
+ │ │ │ ┌───────────────────────────────────────┐ │ │ │
278
+ │ │ │ │ dcp-core / dcp-config / dcp-prune │ │ │ │
279
+ │ │ │ └───────────────────────────────────────┘ │ │ │
280
+ │ │ └─────────────────────────────────────────────┘ │ │
281
+ │ └─────────────────────────────────────────────────────┘ │
282
+ │ │
283
+ │ Hooks: │
284
+ │ • experimental.chat.messages.transform │
285
+ │ • experimental.chat.system.transform │
286
+ │ • command.execute.before │
287
+ │ • event │
288
+ │ • config │
289
+ │ • dispose │
290
+ │ • tool (compress, decompress, recompress) │
291
+ └─────────────────────────────────────────────────────────────┘
292
+ ```
293
+
294
+ ### Message Pipeline
295
+
296
+ 1. **Transform** — Each LLM request passes through `transformMessages()`
297
+ 2. **Strategies** — Deterministic strategies run:
298
+ - Deduplication — merge identical tool calls
299
+ - Purge errors — remove errored tool outputs after N turns
300
+ - Stale file reads — remove reads when files are modified
301
+ 3. **Compression** — If context exceeds limits, model can use `compress` tool
302
+ 4. **Injection** — DCP instructions appended to system prompt
303
+
304
+ ### Config Cascade
305
+
306
+ ```
307
+ Built-in defaults (compiled)
308
+
309
+ Global config (~/.config/dynamic_context_pruning/config.jsonc)
310
+
311
+ Custom config ($DCP_CONFIG_DIR/config.jsonc)
312
+
313
+ Project config (.dynamic_context_pruning/config.jsonc)
314
+ ```
315
+
316
+ Later layers override earlier ones per-key; arrays replace wholesale.
317
+
318
+ ---
319
+
320
+ ## 🐛 Troubleshooting
321
+
322
+ ### Plugin not loading
323
+
324
+ ```bash
325
+ # Check if plugin is in config
326
+ cat ~/.config/opencode/opencode.jsonc | grep plugin
327
+
328
+ # Check if package is installed
329
+ ls ~/.config/opencode/node_modules/@qdang46/opencode-dcp-plugin/
330
+
331
+ # Test native addon
332
+ cd ~/.config/opencode
333
+ node -e "require('./node_modules/@qdang46/opencode-dcp-plugin/opencode-dcp-bridge.darwin-arm64.node')"
334
+ ```
335
+
336
+ ### Config not loading
337
+
338
+ ```bash
339
+ # Check global config exists
340
+ cat ~/.config/dynamic_context_pruning/config.jsonc
341
+
342
+ # Check XDG_CONFIG_HOME
343
+ echo $XDG_CONFIG_HOME
344
+
345
+ # Create config if missing
346
+ mkdir -p ~/.config/dynamic_context_pruning
347
+ echo '{}' > ~/.config/dynamic_context_pruning/config.jsonc
348
+ ```
349
+
350
+ ### Performance issues
351
+
352
+ - Set `"debug": false` in config
353
+ - Use `"cacheStabilityMode": "agent-message"` (default)
354
+ - Reduce `"maxContextLimit"` if context grows too fast
355
+
356
+ ---
357
+
358
+ ## 📚 Resources
359
+
360
+ - [DCP Documentation](https://github.com/quangdang46/dynamic_context_pruning)
361
+ - [Config Schema](./dcp.schema.json)
362
+ - [OpenCode Plugin Docs](https://opencode.ai/plugins)
363
+ - [npm Package](https://www.npmjs.com/package/@qdang46/opencode-dcp-plugin)
364
+
365
+ ---
366
+
367
+ ## 📄 License
368
+
369
+ MIT — see [LICENSE](./LICENSE).
370
+
371
+ ---
372
+
373
+ <div align="center">
374
+
375
+ **Made with ❤️ by [quangdang46](https://github.com/quangdang46)**
53
376
 
54
- MIT
377
+ </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qdang46/opencode-dcp-plugin",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",