@lexwdex-org/opencode-dcp 3.4.9 → 3.4.11

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 (142) hide show
  1. package/README.en.md +28 -258
  2. package/README.md +44 -242
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +488 -7344
  5. package/dist/index.js.map +1 -1
  6. package/dist/lib/config.d.ts +6 -55
  7. package/dist/lib/config.d.ts.map +1 -1
  8. package/dist/lib/hooks.d.ts +13 -30
  9. package/dist/lib/hooks.d.ts.map +1 -1
  10. package/dist/lib/prompts/compaction.d.ts +2 -0
  11. package/dist/lib/prompts/compaction.d.ts.map +1 -0
  12. package/dist/lib/prompts/store.d.ts +4 -14
  13. package/dist/lib/prompts/store.d.ts.map +1 -1
  14. package/dist/lib/summarize.d.ts +35 -0
  15. package/dist/lib/summarize.d.ts.map +1 -0
  16. package/package.json +2 -3
  17. package/dist/lib/commands/compression-targets.d.ts +0 -14
  18. package/dist/lib/commands/compression-targets.d.ts.map +0 -1
  19. package/dist/lib/commands/context.d.ts +0 -53
  20. package/dist/lib/commands/context.d.ts.map +0 -1
  21. package/dist/lib/commands/decompress.d.ts +0 -13
  22. package/dist/lib/commands/decompress.d.ts.map +0 -1
  23. package/dist/lib/commands/help.d.ts +0 -18
  24. package/dist/lib/commands/help.d.ts.map +0 -1
  25. package/dist/lib/commands/index.d.ts +0 -8
  26. package/dist/lib/commands/index.d.ts.map +0 -1
  27. package/dist/lib/commands/manual.d.ts +0 -24
  28. package/dist/lib/commands/manual.d.ts.map +0 -1
  29. package/dist/lib/commands/recompress.d.ts +0 -13
  30. package/dist/lib/commands/recompress.d.ts.map +0 -1
  31. package/dist/lib/commands/stats.d.ts +0 -16
  32. package/dist/lib/commands/stats.d.ts.map +0 -1
  33. package/dist/lib/commands/sweep.d.ts +0 -24
  34. package/dist/lib/commands/sweep.d.ts.map +0 -1
  35. package/dist/lib/compress/external-content.d.ts +0 -4
  36. package/dist/lib/compress/external-content.d.ts.map +0 -1
  37. package/dist/lib/compress/external-inference.d.ts +0 -15
  38. package/dist/lib/compress/external-inference.d.ts.map +0 -1
  39. package/dist/lib/compress/index.d.ts +0 -4
  40. package/dist/lib/compress/index.d.ts.map +0 -1
  41. package/dist/lib/compress/message-utils.d.ts +0 -8
  42. package/dist/lib/compress/message-utils.d.ts.map +0 -1
  43. package/dist/lib/compress/message.d.ts +0 -4
  44. package/dist/lib/compress/message.d.ts.map +0 -1
  45. package/dist/lib/compress/pipeline.d.ts +0 -30
  46. package/dist/lib/compress/pipeline.d.ts.map +0 -1
  47. package/dist/lib/compress/protected-content.d.ts +0 -8
  48. package/dist/lib/compress/protected-content.d.ts.map +0 -1
  49. package/dist/lib/compress/range-utils.d.ts +0 -10
  50. package/dist/lib/compress/range-utils.d.ts.map +0 -1
  51. package/dist/lib/compress/range.d.ts +0 -4
  52. package/dist/lib/compress/range.d.ts.map +0 -1
  53. package/dist/lib/compress/search.d.ts +0 -12
  54. package/dist/lib/compress/search.d.ts.map +0 -1
  55. package/dist/lib/compress/state.d.ts +0 -9
  56. package/dist/lib/compress/state.d.ts.map +0 -1
  57. package/dist/lib/compress/timing.d.ts +0 -20
  58. package/dist/lib/compress/timing.d.ts.map +0 -1
  59. package/dist/lib/compress/types.d.ts +0 -95
  60. package/dist/lib/compress/types.d.ts.map +0 -1
  61. package/dist/lib/compress-permission.d.ts +0 -6
  62. package/dist/lib/compress-permission.d.ts.map +0 -1
  63. package/dist/lib/concurrency.d.ts +0 -2
  64. package/dist/lib/concurrency.d.ts.map +0 -1
  65. package/dist/lib/config-env-override.d.ts +0 -3
  66. package/dist/lib/config-env-override.d.ts.map +0 -1
  67. package/dist/lib/host-permissions.d.ts +0 -11
  68. package/dist/lib/host-permissions.d.ts.map +0 -1
  69. package/dist/lib/message-ids.d.ts +0 -19
  70. package/dist/lib/message-ids.d.ts.map +0 -1
  71. package/dist/lib/messages/index.d.ts +0 -9
  72. package/dist/lib/messages/index.d.ts.map +0 -1
  73. package/dist/lib/messages/inject/inject.d.ts +0 -8
  74. package/dist/lib/messages/inject/inject.d.ts.map +0 -1
  75. package/dist/lib/messages/inject/subagent-results.d.ts +0 -5
  76. package/dist/lib/messages/inject/subagent-results.d.ts.map +0 -1
  77. package/dist/lib/messages/inject/utils.d.ts +0 -24
  78. package/dist/lib/messages/inject/utils.d.ts.map +0 -1
  79. package/dist/lib/messages/priority.d.ts +0 -13
  80. package/dist/lib/messages/priority.d.ts.map +0 -1
  81. package/dist/lib/messages/prune.d.ts +0 -5
  82. package/dist/lib/messages/prune.d.ts.map +0 -1
  83. package/dist/lib/messages/query.d.ts +0 -7
  84. package/dist/lib/messages/query.d.ts.map +0 -1
  85. package/dist/lib/messages/reasoning-strip.d.ts +0 -8
  86. package/dist/lib/messages/reasoning-strip.d.ts.map +0 -1
  87. package/dist/lib/messages/shape.d.ts +0 -5
  88. package/dist/lib/messages/shape.d.ts.map +0 -1
  89. package/dist/lib/messages/sync.d.ts +0 -4
  90. package/dist/lib/messages/sync.d.ts.map +0 -1
  91. package/dist/lib/messages/utils.d.ts +0 -27
  92. package/dist/lib/messages/utils.d.ts.map +0 -1
  93. package/dist/lib/prompts/compress-message.d.ts +0 -2
  94. package/dist/lib/prompts/compress-message.d.ts.map +0 -1
  95. package/dist/lib/prompts/compress-range.d.ts +0 -2
  96. package/dist/lib/prompts/compress-range.d.ts.map +0 -1
  97. package/dist/lib/prompts/context-limit-nudge.d.ts +0 -2
  98. package/dist/lib/prompts/context-limit-nudge.d.ts.map +0 -1
  99. package/dist/lib/prompts/extensions/nudge.d.ts +0 -7
  100. package/dist/lib/prompts/extensions/nudge.d.ts.map +0 -1
  101. package/dist/lib/prompts/extensions/system.d.ts +0 -4
  102. package/dist/lib/prompts/extensions/system.d.ts.map +0 -1
  103. package/dist/lib/prompts/extensions/tool.d.ts +0 -5
  104. package/dist/lib/prompts/extensions/tool.d.ts.map +0 -1
  105. package/dist/lib/prompts/index.d.ts +0 -4
  106. package/dist/lib/prompts/index.d.ts.map +0 -1
  107. package/dist/lib/prompts/iteration-nudge.d.ts +0 -2
  108. package/dist/lib/prompts/iteration-nudge.d.ts.map +0 -1
  109. package/dist/lib/prompts/system.d.ts +0 -2
  110. package/dist/lib/prompts/system.d.ts.map +0 -1
  111. package/dist/lib/prompts/turn-nudge.d.ts +0 -2
  112. package/dist/lib/prompts/turn-nudge.d.ts.map +0 -1
  113. package/dist/lib/protected-patterns.d.ts +0 -5
  114. package/dist/lib/protected-patterns.d.ts.map +0 -1
  115. package/dist/lib/state/index.d.ts +0 -6
  116. package/dist/lib/state/index.d.ts.map +0 -1
  117. package/dist/lib/state/persistence.d.ts +0 -50
  118. package/dist/lib/state/persistence.d.ts.map +0 -1
  119. package/dist/lib/state/state.d.ts +0 -10
  120. package/dist/lib/state/state.d.ts.map +0 -1
  121. package/dist/lib/state/store.d.ts +0 -37
  122. package/dist/lib/state/store.d.ts.map +0 -1
  123. package/dist/lib/state/tool-cache.d.ts +0 -13
  124. package/dist/lib/state/tool-cache.d.ts.map +0 -1
  125. package/dist/lib/state/types.d.ts +0 -99
  126. package/dist/lib/state/types.d.ts.map +0 -1
  127. package/dist/lib/state/utils.d.ts +0 -25
  128. package/dist/lib/state/utils.d.ts.map +0 -1
  129. package/dist/lib/strategies/deduplication.d.ts +0 -10
  130. package/dist/lib/strategies/deduplication.d.ts.map +0 -1
  131. package/dist/lib/strategies/index.d.ts +0 -3
  132. package/dist/lib/strategies/index.d.ts.map +0 -1
  133. package/dist/lib/strategies/purge-errors.d.ts +0 -13
  134. package/dist/lib/strategies/purge-errors.d.ts.map +0 -1
  135. package/dist/lib/subagents/subagent-results.d.ts +0 -5
  136. package/dist/lib/subagents/subagent-results.d.ts.map +0 -1
  137. package/dist/lib/token-utils.d.ts +0 -18
  138. package/dist/lib/token-utils.d.ts.map +0 -1
  139. package/dist/lib/ui/notification.d.ts +0 -18
  140. package/dist/lib/ui/notification.d.ts.map +0 -1
  141. package/dist/lib/ui/utils.d.ts +0 -10
  142. package/dist/lib/ui/utils.d.ts.map +0 -1
package/README.en.md CHANGED
@@ -1,290 +1,60 @@
1
- # Dynamic Context Pruning Plugin
1
+ # Dynamic Context Pruning for OpenCode
2
2
 
3
- [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/dansmolsky)
4
3
  [![npm version](https://img.shields.io/npm/v/@lexwdex-org/opencode-dcp.svg)](https://www.npmjs.com/package/@lexwdex-org/opencode-dcp)
5
4
 
6
- [**中文文档**](./README.md) | **English**
5
+ **English** | [中文](./README.md)
7
6
 
8
- Automatically reduces token usage in OpenCode by managing conversation context.
7
+ DCP supplies a semantic-pruning policy to OpenCode's native compaction lifecycle. It no longer owns message markers, message IDs, compression blocks, anchors, placeholders, or a second summary state machine.
9
8
 
10
- ![DCP in action](assets/images/dcp-demo9.png)
9
+ ## How it works
11
10
 
12
- ## Installation
11
+ OpenCode owns one rolling checkpoint. After compaction, the model sees only:
13
12
 
14
- Install from the CLI:
15
-
16
- ```bash
17
- opencode plugin @lexwdex-org/opencode-dcp@latest --global
13
+ ```text
14
+ latest pruned checkpoint + uncompacted recent tail
18
15
  ```
19
16
 
20
- This installs the package and adds it to your global OpenCode config.
21
-
22
- ## How It Works
23
-
24
- DCP reduces context size through a compress tool and automatic cleanup. Your session history is never modified — DCP replaces pruned content with placeholders before sending requests to your LLM.
25
-
26
- ### Compress
27
-
28
- Compress is a tool exposed to your model that replaces closed, stale conversation content with high-fidelity technical summaries. You can think of this as a much smarter version of Opencode's compaction process. Instead of triggering statically when your session reaches its maximum context and on the entire coding session, Compress allows the model to pick when to activate based on task completion, and to only compress the specific messages that are no longer needed verbatim.
17
+ During `experimental.session.compacting`, DCP asks the summarizer to remove unrelated chat and other-project context, fold tool retries into the final successful result, fold repeated edits into the final state and valid decisions, and reduce small completed topics to short outcomes. Continuation-critical goals, constraints, decisions, implementation state, risks, and next steps remain.
29
18
 
30
- DCP supports two compression modes:
19
+ Pruned prefixes stop being sent to the model, but the original session history is not physically deleted from OpenCode's database. A later compaction replaces the previous checkpoint with one merged checkpoint instead of nesting summaries or building a compression-block graph.
31
20
 
32
- - `range` mode compresses contiguous spans of conversation into one or more summaries.
33
- - `message` mode (experimental) compresses individual raw messages independently, letting the model manage context much more surgically.
21
+ ## Install
34
22
 
35
- In `range` mode, when a new compression overlaps an earlier one, the earlier summary is nested inside the new one so information is preserved through layers of compression rather than diluted away. In both modes, protected tool outputs (such as subagents and skills) and protected file patterns are kept in compression summaries, ensuring that the most important information is never lost. You can also enable `protectUserMessages` to preserve your messages verbatim during compression, though note that large prompts (e.g. copy-pasting log files in the prompt) will then never be compressed away.
36
-
37
- ### Deduplication
23
+ ```bash
24
+ opencode plugin @lexwdex-org/opencode-dcp@latest --global
25
+ ```
38
26
 
39
- Identifies repeated tool calls (same tool, same arguments) and keeps only the most recent output. Recalculated when the compress tool runs, so prompt cache is only impacted alongside compression.
27
+ ## Trigger compaction
40
28
 
41
- ### Purge Errors
29
+ - OpenCode automatic compaction uses the policy automatically.
30
+ - OpenCode's native `/compact` command uses the same path.
31
+ - `/dcp summarize` calls native `session.summarize()` for one-step semantic pruning.
42
32
 
43
- Prunes inputs from errored tool calls after a configurable number of turns (default: 4). Error messages are preserved; only the potentially large input content is removed. Recalculated on compress tool use.
33
+ Concurrent requests for the same session share one native call. A failed call is fail-open and keeps the original context; retries are cooled down for 30 seconds by default.
44
34
 
45
35
  ## Configuration
46
36
 
47
- DCP uses its own config file, searched in order:
48
-
49
- 1. Global: `~/.config/opencode/dcp.jsonc` (or `dcp.json`), created automatically on first run
50
- 2. Custom config directory: `$OPENCODE_CONFIG_DIR/dcp.jsonc` (or `dcp.json`), if `OPENCODE_CONFIG_DIR` is set
51
- 3. Project: `.opencode/dcp.jsonc` (or `dcp.json`) in your project's `.opencode` directory
52
-
53
- Each level overrides the previous, so project settings take priority over global. Restart OpenCode after making config changes.
54
-
55
- > [!NOTE]
56
- > If you use models with smaller context windows, such as GitHub Copilot models or local models, lower `compress.minContextLimit` and `compress.maxContextLimit` in your configuration to match the available context.
57
-
58
- > [!IMPORTANT]
59
- > Defaults are applied automatically. Expand this if you want to review or override settings.
60
-
61
- <details>
62
- <summary><strong>Default Configuration</strong> (click to expand)</summary>
37
+ DCP loads global, custom-config-directory, then project configuration:
63
38
 
64
39
  ```jsonc
65
40
  {
66
41
  "$schema": "https://raw.githubusercontent.com/LeXwDeX/opencode-dynamic-context-pruning/master/dcp.schema.json",
67
- // Enable or disable the plugin
68
42
  "enabled": true,
69
- // Check npm for a newer DCP release and show an update notification.
70
- // The plugin never deletes or replaces its active installation.
71
43
  "autoUpdate": true,
72
- // Enable debug logging to ~/.config/opencode/logs/dcp/
73
44
  "debug": false,
74
- // Notification display: "off", "minimal", or "detailed"
75
- "pruneNotification": "detailed",
76
- // Notification type: "chat" (in-conversation) or "toast" (system toast)
77
- "pruneNotificationType": "chat",
78
- // Slash commands configuration
79
- "commands": {
80
- "enabled": true,
81
- // Additional tools to protect from pruning via commands (e.g., /dcp sweep)
82
- "protectedTools": [],
83
- },
84
- // Manual mode: disables autonomous context management,
85
- // tools only run when explicitly triggered via /dcp commands
86
- "manualMode": {
87
- "enabled": false,
88
- // When true, automatic cleanup (deduplication, purgeErrors)
89
- // still runs even in manual mode
90
- "automaticStrategies": true,
91
- },
92
- // Protect from pruning for <turns> message turns past tool invocation
93
- "turnProtection": {
94
- "enabled": false,
95
- "turns": 4,
96
- },
97
- // Experimental settings
98
- "experimental": {
99
- // Allow DCP processing in subagent sessions
100
- "allowSubAgents": false,
101
- // Enable user-editable prompt overrides under dcp-prompts directories
102
- // When false (default), prompt override files/directories are ignored
103
- "customPrompts": false,
104
- },
105
- // Protect file operations from pruning via glob patterns
106
- // Patterns match tool parameters.filePath (e.g. read/write/edit)
107
- "protectedFilePatterns": [],
108
- // Unified context compression tool and behavior settings
109
- "compress": {
110
- // Compression mode: "range" (compress spans into block summaries)
111
- // or experimental "message" (compress individual raw messages)
112
- "mode": "range",
113
- // Permission mode: "allow" (no prompt), "ask" (prompt), "deny" (tool not registered)
114
- "permission": "allow",
115
- // Show compression content in a chat notification
116
- "showCompression": false,
117
- // Let active summary tokens extend the effective maxContextLimit
118
- "summaryBuffer": true,
119
- // Soft upper threshold: above this, DCP keeps injecting strong
120
- // compression nudges (based on nudgeFrequency), so compression is
121
- // much more likely. Accepts: number or "X%" of model context window.
122
- "maxContextLimit": "85%",
123
- // Soft lower threshold for reminder nudges: below this, turn/iteration
124
- // reminders are off (compression less likely). At/above this, reminders
125
- // are on. Accepts: number or "X%" of model context window.
126
- "minContextLimit": "50%",
127
- // Optional per-model override for maxContextLimit by providerID/modelID.
128
- // If present, this wins over the global maxContextLimit.
129
- // Accepts: number or "X%".
130
- // Example:
131
- // "modelMaxLimits": {
132
- // "openai/gpt-5.3-codex": 120000,
133
- // "anthropic/claude-sonnet-4.6": "80%"
134
- // },
135
- // Optional per-model override for minContextLimit.
136
- // If present, this wins over the global minContextLimit.
137
- // "modelMinLimits": {
138
- // "openai/gpt-5.3-codex": 50000,
139
- // "anthropic/claude-sonnet-4.6": "25%"
140
- // },
141
- // How often the context-limit nudge fires (1 = every fetch, 2 = every 2nd)
142
- "nudgeFrequency": 2,
143
- // Start adding compression reminders after this many
144
- // messages have happened since the last user message
145
- "iterationNudgeThreshold": 15,
146
- // Controls how likely compression is after user messages
147
- // ("strong" = more likely, "soft" = less likely)
148
- "nudgeForce": "strong",
149
- // Tool names whose completed outputs are appended to the compression
150
- "protectedTools": [],
151
- // Preserve text wrapped in <protect>...</protect> when compressed
152
- "protectTags": false,
153
- // Preserve your messages during compression.
154
- // Warning: large copy-pasted prompts will never be compressed away
155
- "protectUserMessages": false,
156
- },
157
- // Automatic pruning strategies
158
- "strategies": {
159
- // Remove duplicate tool calls (same tool with same arguments)
160
- "deduplication": {
161
- "enabled": true,
162
- // Additional tools to protect from pruning
163
- "protectedTools": [],
164
- },
165
- // Prune tool inputs for errored tools after X turns
166
- "purgeErrors": {
167
- "enabled": true,
168
- // Number of turns before errored tool inputs are pruned
169
- "turns": 4,
170
- // Additional tools to protect from pruning
171
- "protectedTools": [],
172
- },
173
- },
174
- }
175
- ```
176
-
177
- </details>
178
-
179
- ### Commands
180
-
181
- DCP provides a `/dcp` slash command:
182
-
183
- - `/dcp` — Shows available DCP commands
184
- - `/dcp context` — Shows a breakdown of your current session's token usage by category (system, user, assistant, tools, etc.) and how much has been saved through pruning.
185
- - `/dcp stats` — Shows cumulative pruning statistics across all sessions.
186
- - `/dcp sweep` — Prunes all tools since the last user message. Accepts an optional count: `/dcp sweep 10` prunes the last 10 tools. Respects `commands.protectedTools`.
187
- - `/dcp manual [on|off]` — Toggle manual mode or set explicit state. When on, the AI will not autonomously use context management tools.
188
- - `/dcp compress [focus]` — Trigger a single compress tool execution. Optional focus text directs what content to compress, following the active `compress.mode`.
189
- - `/dcp decompress <n>` — Restore a specific active compression by ID (for example `/dcp decompress 2`). Running without an argument shows available compression IDs, token sizes, and topics.
190
- - `/dcp recompress <n>` — Re-apply a user-decompressed compression by ID (for example `/dcp recompress 2`). Running without an argument shows recompressible IDs, token sizes, and topics.
191
-
192
- ### Prompt Overrides
193
-
194
- DCP exposes six editable prompts:
195
-
196
- - `system`
197
- - `compress-range`
198
- - `compress-message`
199
- - `context-limit-nudge`
200
- - `turn-nudge`
201
- - `iteration-nudge`
202
-
203
- This feature is disabled by default. Set `experimental.customPrompts` to `true` in your DCP config to activate it.
204
-
205
- When enabled, managed defaults are written to `~/.config/opencode/dcp-prompts/defaults/` as plain-text prompt files. A single `README.md` in that directory explains each prompt and how to create overrides.
206
-
207
- To customize behavior, add a file with the same name under an overrides directory and edit it as plain text.
208
-
209
- To reset an override, delete the matching file from your overrides directory.
210
-
211
- ### Protected Tools
212
-
213
- By default, these tools are always protected from pruning:
214
- `task`, `skill`, `todowrite`, `todoread`, `compress`, `batch`, `plan_enter`, `plan_exit`, `write`, `edit`
215
-
216
- The `protectedTools` arrays in `commands` and `strategies` add to this default list.
217
-
218
- For the `compress` tool, `compress.protectedTools` ensures specific tool outputs are appended to the compressed summary. By default it includes `task`, `skill`, `todowrite`, and `todoread`.
219
-
220
- ### External Model Compression
221
-
222
- Offload compression summaries to a cheaper model instead of using the expensive main model.
223
-
224
- #### Priority Chain
225
-
226
- | Priority | Source | Description |
227
- | ------------ | --------------------- | ------------------------------------------------------ |
228
- | 1 (highest) | Environment variables | `OPENCODE_DCP_EXTERNAL_COMPRESS_*` |
229
- | 2 | Project config | `<project>/.opencode/dcp.jsonc:compress.externalModel` |
230
- | 3 | Global config | `~/.config/opencode/dcp.jsonc:compress.externalModel` |
231
- | 4 (fallback) | Main model | Original behavior unchanged |
232
-
233
- #### Usage
234
-
235
- **Method 1 — Environment variables (recommended for quick setup):**
236
-
237
- ```bash
238
- export OPENCODE_DCP_EXTERNAL_COMPRESS_URL="http://your-proxy-url/v1"
239
- export OPENCODE_DCP_EXTERNAL_COMPRESS_MODEL="your-model-name"
240
- # Optional:
241
- export OPENCODE_DCP_EXTERNAL_COMPRESS_KEY="your-api-key"
242
- export OPENCODE_DCP_EXTERNAL_COMPRESS_TIMEOUT="120000"
243
- export OPENCODE_DCP_EXTERNAL_COMPRESS_RETRIES="1"
244
- ```
245
-
246
- Persist in shell RC (`~/.zshrc`, `~/.bashrc`) for automatic availability across sessions.
247
-
248
- **Method 2 — Config file (`dcp.jsonc`):**
249
-
250
- ```jsonc
251
- {
252
- "compress": {
253
- "externalModel": {
254
- "url": "http://your-proxy-url/v1",
255
- "model": "your-model-name",
256
- "apiKey": "your-api-key",
257
- "timeout": 120000,
258
- "retries": 1,
259
- },
260
- },
45
+ "commands": { "enabled": true },
46
+ "experimental": { "customPrompts": false },
47
+ "summarize": { "failureCooldownMs": 30000 },
261
48
  }
262
49
  ```
263
50
 
264
- #### Behavior
265
-
266
- | Scenario | Behavior |
267
- | ---------------------------------------------- | ------------------------------------------------------------------------------ |
268
- | External model configured + `summary` omitted | Plugin fetches range content → calls external model → stores generated summary |
269
- | External model configured + `summary` provided | Plugin uses provided `summary` directly (backward compatible) |
270
- | External model call fails | Tool throws error; main model retries with fallback summary |
271
- | Not configured | Everything unchanged — main model writes summaries as before |
272
- | `url` is not OpenAI-compatible | External model call fails → falls to error path above |
273
-
274
- **Compatibility:** Only OpenAI-compatible `/chat/completions` endpoints are supported (local proxies, OpenAI, DeepSeek, etc.).
275
-
276
- ## Impact on Prompt Caching
277
-
278
- LLM providers cache prompts based on exact prefix matching. When DCP prunes content, it changes messages, which invalidates cached prefixes from that point forward.
279
-
280
- **Trade-off:** You lose some cache reads but gain token savings from reduced context size and fewer hallucinations from stale context. In most cases, especially in long sessions, the savings outweigh the cache miss cost.
51
+ When `experimental.customPrompts` is enabled, copy the generated
52
+ `~/.config/opencode/dcp-prompts/defaults/compaction.md` to a project, custom-config, or global `dcp-prompts/overrides/compaction.md` path.
281
53
 
282
- > [!NOTE]
283
- > In testing, cache hit rates were approximately 85% with DCP vs 90% without.
54
+ ## Migrating from the legacy 3.x pipeline
284
55
 
285
- **No impact for:**
56
+ Legacy `compress`, `manualMode`, `strategies`, `turnProtection`, notification, protected-file, and command-protection settings are removed. DCP reports them as deprecated and ignores them.
286
57
 
287
- - **Request-based billing** Providers like GitHub Copilot that charge per request, not tokens.
288
- - **Uniform token pricing** — Providers like Cerebras that bill cached and uncached tokens at the same rate.
58
+ The old model tools, range/message compression, `/dcp compress`, decompression/recompression/sweep commands, message markers, nudges, and plugin compression persistence are gone. Existing legacy DCP state files are neither read nor modified; remove them manually only after deciding that you will not roll back.
289
59
 
290
- ## License
60
+ License: AGPL-3.0-or-later.
package/README.md CHANGED
@@ -1,290 +1,92 @@
1
1
  # 动态上下文剪枝插件
2
2
 
3
- [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/dansmolsky)
4
3
  [![npm version](https://img.shields.io/npm/v/@lexwdex-org/opencode-dcp.svg)](https://www.npmjs.com/package/@lexwdex-org/opencode-dcp)
5
4
 
6
5
  [**English**](./README.en.md) | **中文**
7
6
 
8
- 通过管理对话上下文,自动减少 OpenCode 中的 token 消耗。
9
-
10
- ![DCP in action](assets/images/dcp-demo9.png)
11
-
12
- ## 安装
13
-
14
- 从 CLI 安装:
15
-
16
- ```bash
17
- opencode plugin @lexwdex-org/opencode-dcp@latest --global
18
- ```
19
-
20
- 这会安装该包并将其添加到全局 OpenCode 配置中。
7
+ DCP OpenCode 原生 compaction 提供语义剪枝策略。它不再维护消息标记、消息 ID、压缩块、锚点、占位符或第二套摘要状态机。
21
8
 
22
9
  ## 工作原理
23
10
 
24
- DCP 通过压缩工具和自动清理来减小上下文大小。会话历史记录不会被修改——DCP 会在向 LLM 发送请求之前用占位符替换已剪枝的内容。
11
+ OpenCode 原生 compaction 负责生成和保存一个滚动检查点,并在后续模型请求中只发送:
25
12
 
26
- ### 压缩
13
+ ```text
14
+ 最新剪枝检查点 + 尚未压缩的近期尾部
15
+ ```
27
16
 
28
- Compress 是一个暴露给模型的工具,它会将已关闭的、过时的对话内容替换为高保真度的技术摘要。你可以将其视为 OpenCode 原生合并过程的更智能版本。它不是在你的会话达到最大上下文时才静态触发并对整个编码会话生效,而是允许模型根据任务完成情况自主选择何时激活,并且只压缩那些不再需要逐字保留的特定消息。
17
+ DCP 只在 `experimental.session.compacting` 阶段提供专用提示词。提示词会:
29
18
 
30
- DCP 支持两种压缩模式:
19
+ - 删除无关闲聊、其他项目内容、重复解释和已推翻方案;
20
+ - 把多次工具试错折叠为最终成功结果,必要时保留一次根因;
21
+ - 把同一内容的重复修改折叠为最终状态和仍有效的决策;
22
+ - 把小型已完成主题压缩为一句结果;
23
+ - 保留继续工作需要的目标、约束、决策、实现状态、风险和下一步。
31
24
 
32
- - `range` 模式将连续的多段对话压缩为一个或多个摘要。
33
- - `message` 模式(实验性)独立压缩单条原始消息,让模型能够更精细地管理上下文。
25
+ 压缩后的旧前缀不会再发送给模型,但 OpenCode 数据库中的原始会话历史不会被物理删除。下一次压缩会把旧检查点和新增尾部合并为一个新检查点,不会形成嵌套摘要或压缩块 DAG。
34
26
 
35
- `range` 模式下,当新的压缩与先前的压缩重叠时,先前的摘要会被嵌套到新的摘要中,这样信息在多层压缩中得到保留而非被稀释。在两种模式下,受保护的工具输出(如子 agent 和技能)以及受保护的文件模式都会保留在压缩摘要中,确保最重要的信息永不会丢失。你还可以启用 `protectUserMessages` 来在压缩期间保留你的消息原样,但请注意,大型提示(例如在提示中粘贴日志文件)将永远不会被压缩掉。
27
+ ## 安装
36
28
 
37
- ### 去重
29
+ ```bash
30
+ opencode plugin @lexwdex-org/opencode-dcp@latest --global
31
+ ```
38
32
 
39
- 识别重复的工具调用(相同工具、相同参数),只保留最近一次的输出。在压缩工具运行时重新计算,因此提示缓存仅在与压缩同时发生时受到影响。
33
+ ## 触发压缩
40
34
 
41
- ### 清除错误
35
+ - OpenCode 自动 compaction:达到宿主阈值时自动运行。
36
+ - OpenCode 原生 `/compact`:手动触发同一条 compaction 路径。
37
+ - `/dcp summarize`:调用原生 `session.summarize()`,一次完成语义摘要和真实上下文剪枝。
42
38
 
43
- 在可配置的消息轮次后(默认:4 轮),修剪出错工具调用的输入。错误消息会被保留,仅移除可能较大的输入内容。在使用压缩工具时重新计算。
39
+ 同一会话的并发 `/dcp summarize` 会合并为一次原生调用。失败不会提交半成品检查点,原始上下文保持可用;默认 30 秒内不会重复调用失败的请求。
44
40
 
45
41
  ## 配置
46
42
 
47
- DCP 使用自己的配置文件,按以下顺序搜索:
43
+ DCP 依次读取以下配置,后面的层覆盖前面的层:
48
44
 
49
- 1. 全局:`~/.config/opencode/dcp.jsonc`(或 `dcp.json`),首次运行时自动创建
50
- 2. 自定义配置目录:`$OPENCODE_CONFIG_DIR/dcp.jsonc`(或 `dcp.json`),如果设置了 `OPENCODE_CONFIG_DIR`
51
- 3. 项目:`.opencode/dcp.jsonc`(或 `dcp.json`),位于项目的 `.opencode` 目录中
52
-
53
- 每个层级覆盖前一个层级,因此项目设置优先于全局设置。修改配置后请重启 OpenCode。
54
-
55
- > [!NOTE]
56
- > 如果你使用的是较小上下文窗口的模型,例如 GitHub Copilot 模型或本地模型,请在配置中降低 `compress.minContextLimit` 和 `compress.maxContextLimit` 以匹配可用上下文。
57
-
58
- > [!IMPORTANT]
59
- > 默认值会自动应用。展开此项可查看或覆盖设置。
60
-
61
- <details>
62
- <summary><strong>默认配置</strong>(点击展开)</summary>
45
+ 1. `~/.config/opencode/dcp.jsonc` `dcp.json`
46
+ 2. `$OPENCODE_CONFIG_DIR/dcp.jsonc` `dcp.json`
47
+ 3. 项目的 `.opencode/dcp.jsonc` `dcp.json`
63
48
 
64
49
  ```jsonc
65
50
  {
66
51
  "$schema": "https://raw.githubusercontent.com/LeXwDeX/opencode-dynamic-context-pruning/master/dcp.schema.json",
67
- // Enable or disable the plugin
68
52
  "enabled": true,
69
- // Check npm for a newer DCP release and show an update notification.
70
- // The plugin never deletes or replaces its active installation.
71
53
  "autoUpdate": true,
72
- // Enable debug logging to ~/.config/opencode/logs/dcp/
73
54
  "debug": false,
74
- // Notification display: "off", "minimal", or "detailed"
75
- "pruneNotification": "detailed",
76
- // Notification type: "chat" (in-conversation) or "toast" (system toast)
77
- "pruneNotificationType": "chat",
78
- // Slash commands configuration
79
55
  "commands": {
80
56
  "enabled": true,
81
- // Additional tools to protect from pruning via commands (e.g., /dcp sweep)
82
- "protectedTools": [],
83
57
  },
84
- // Manual mode: disables autonomous context management,
85
- // tools only run when explicitly triggered via /dcp commands
86
- "manualMode": {
87
- "enabled": false,
88
- // When true, automatic cleanup (deduplication, purgeErrors)
89
- // still runs even in manual mode
90
- "automaticStrategies": true,
91
- },
92
- // Protect from pruning for <turns> message turns past tool invocation
93
- "turnProtection": {
94
- "enabled": false,
95
- "turns": 4,
96
- },
97
- // Experimental settings
98
58
  "experimental": {
99
- // Allow DCP processing in subagent sessions
100
- "allowSubAgents": false,
101
- // Enable user-editable prompt overrides under dcp-prompts directories
102
- // When false (default), prompt override files/directories are ignored
103
59
  "customPrompts": false,
104
60
  },
105
- // Protect file operations from pruning via glob patterns
106
- // Patterns match tool parameters.filePath (e.g. read/write/edit)
107
- "protectedFilePatterns": [],
108
- // Unified context compression tool and behavior settings
109
- "compress": {
110
- // Compression mode: "range" (compress spans into block summaries)
111
- // or experimental "message" (compress individual raw messages)
112
- "mode": "range",
113
- // Permission mode: "allow" (no prompt), "ask" (prompt), "deny" (tool not registered)
114
- "permission": "allow",
115
- // Show compression content in a chat notification
116
- "showCompression": false,
117
- // Let active summary tokens extend the effective maxContextLimit
118
- "summaryBuffer": true,
119
- // Soft upper threshold: above this, DCP keeps injecting strong
120
- // compression nudges (based on nudgeFrequency), so compression is
121
- // much more likely. Accepts: number or "X%" of model context window.
122
- "maxContextLimit": "85%",
123
- // Soft lower threshold for reminder nudges: below this, turn/iteration
124
- // reminders are off (compression less likely). At/above this, reminders
125
- // are on. Accepts: number or "X%" of model context window.
126
- "minContextLimit": "50%",
127
- // Optional per-model override for maxContextLimit by providerID/modelID.
128
- // If present, this wins over the global maxContextLimit.
129
- // Accepts: number or "X%".
130
- // Example:
131
- // "modelMaxLimits": {
132
- // "openai/gpt-5.3-codex": 120000,
133
- // "anthropic/claude-sonnet-4.6": "80%"
134
- // },
135
- // Optional per-model override for minContextLimit.
136
- // If present, this wins over the global minContextLimit.
137
- // "modelMinLimits": {
138
- // "openai/gpt-5.3-codex": 50000,
139
- // "anthropic/claude-sonnet-4.6": "25%"
140
- // },
141
- // How often the context-limit nudge fires (1 = every fetch, 2 = every 2nd)
142
- "nudgeFrequency": 2,
143
- // Start adding compression reminders after this many
144
- // messages have happened since the last user message
145
- "iterationNudgeThreshold": 15,
146
- // Controls how likely compression is after user messages
147
- // ("strong" = more likely, "soft" = less likely)
148
- "nudgeForce": "strong",
149
- // Tool names whose completed outputs are appended to the compression
150
- "protectedTools": [],
151
- // Preserve text wrapped in <protect>...</protect> when compressed
152
- "protectTags": false,
153
- // Preserve your messages during compression.
154
- // Warning: large copy-pasted prompts will never be compressed away
155
- "protectUserMessages": false,
156
- },
157
- // Automatic pruning strategies
158
- "strategies": {
159
- // Remove duplicate tool calls (same tool with same arguments)
160
- "deduplication": {
161
- "enabled": true,
162
- // Additional tools to protect from pruning
163
- "protectedTools": [],
164
- },
165
- // Prune tool inputs for errored tools after X turns
166
- "purgeErrors": {
167
- "enabled": true,
168
- // Number of turns before errored tool inputs are pruned
169
- "turns": 4,
170
- // Additional tools to protect from pruning
171
- "protectedTools": [],
172
- },
61
+ "summarize": {
62
+ "failureCooldownMs": 30000,
173
63
  },
174
64
  }
175
65
  ```
176
66
 
177
- </details>
178
-
179
- ### 命令
180
-
181
- DCP 提供 `/dcp` 斜杠命令:
182
-
183
- - `/dcp` — 显示可用的 DCP 命令
184
- - `/dcp context` — 显示当前会话按类别(system、user、assistant、tools 等)划分的 token 使用明细以及通过剪枝节省的量。
185
- - `/dcp stats` — 显示跨所有会话的累积剪枝统计信息。
186
- - `/dcp sweep` — 修剪自上次用户消息以来的所有工具。接受可选数量:`/dcp sweep 10` 修剪最后 10 个工具。遵循 `commands.protectedTools`。
187
- - `/dcp manual [on|off]` — 切换手动模式或设置显式状态。开启时,AI 不会自主使用上下文管理工具。
188
- - `/dcp compress [focus]` — 触发一次压缩工具执行。可选的 focus 文本指示要压缩的内容,遵循当前的 `compress.mode`。
189
- - `/dcp decompress <n>` — 按 ID 恢复特定的活跃压缩(例如 `/dcp decompress 2`)。不加参数运行时显示可用的压缩 ID、token 大小和主题。
190
- - `/dcp recompress <n>` — 按 ID 重新压缩用户已解压的压缩(例如 `/dcp recompress 2`)。不加参数运行时显示可重新压缩的 ID、token 大小和主题。
191
-
192
- ### 提示词覆盖
193
-
194
- DCP 暴露了六个可编辑的提示词:
195
-
196
- - `system`
197
- - `compress-range`
198
- - `compress-message`
199
- - `context-limit-nudge`
200
- - `turn-nudge`
201
- - `iteration-nudge`
67
+ 启用 `experimental.customPrompts` 后,可将生成的
68
+ `~/.config/opencode/dcp-prompts/defaults/compaction.md` 复制到以下任一覆盖位置:
202
69
 
203
- 此功能默认禁用。在你的 DCP 配置中将 `experimental.customPrompts` 设置为 `true` 来激活它。
70
+ - 项目:`.opencode/dcp-prompts/overrides/compaction.md`
71
+ - 自定义配置目录:`$OPENCODE_CONFIG_DIR/dcp-prompts/overrides/compaction.md`
72
+ - 全局:`~/.config/opencode/dcp-prompts/overrides/compaction.md`
204
73
 
205
- 启用后,管理的默认值会以纯文本提示词文件的形式写入 `~/.config/opencode/dcp-prompts/defaults/`。该目录中的 `README.md` 文件会解释每个提示词以及如何创建覆盖。
74
+ ## 3.x 旧压缩管线迁移
206
75
 
207
- 如需自定义行为,请在覆盖目录下添加同名文件并编辑为纯文本。
76
+ 旧配置 `compress`、`manualMode`、`strategies`、`turnProtection`、
77
+ `pruneNotification`、`protectedFilePatterns` 及旧命令保护字段均已删除。DCP 会显示迁移警告并忽略这些字段,不会静默继续旧行为。
208
78
 
209
- 要重置覆盖,请从覆盖目录中删除对应的文件。
79
+ 以下功能已删除:`compress` / `compress_range` 模型工具、`/dcp compress`、
80
+ `/dcp decompress`、`/dcp recompress`、`/dcp sweep`、消息标记、nudge 和插件压缩状态持久化。磁盘上已有的旧 DCP 会话状态文件不会被读取、改写或删除,可在确认不再回退旧版本后自行清理。
210
81
 
211
- ### 受保护工具
212
-
213
- 默认情况下,以下工具始终受保护不被修剪:
214
- `task`、`skill`、`todowrite`、`todoread`、`compress`、`batch`、`plan_enter`、`plan_exit`、`write`、`edit`
215
-
216
- `commands` 和 `strategies` 中的 `protectedTools` 数组会追加到这个默认列表。
217
-
218
- 对于 `compress` 工具,`compress.protectedTools` 确保特定工具的输出会被附加到压缩摘要中。默认包含 `task`、`skill`、`todowrite` 和 `todoread`。
219
-
220
- ### 外部模型压缩
221
-
222
- 将压缩摘要的生成工作卸载到更便宜的模型,而不是使用昂贵的主模型。
223
-
224
- #### 优先级链
225
-
226
- | 优先级 | 来源 | 说明 |
227
- | --------- | -------- | ------------------------------------------------------ |
228
- | 1(最高) | 环境变量 | `OPENCODE_DCP_EXTERNAL_COMPRESS_*` |
229
- | 2 | 项目配置 | `<project>/.opencode/dcp.jsonc:compress.externalModel` |
230
- | 3 | 全局配置 | `~/.config/opencode/dcp.jsonc:compress.externalModel` |
231
- | 4(兜底) | 主模型 | 原始行为不变 |
232
-
233
- #### 使用方法
234
-
235
- **方法 1 — 环境变量(推荐用于快速设置):**
82
+ ## 开发验证
236
83
 
237
84
  ```bash
238
- export OPENCODE_DCP_EXTERNAL_COMPRESS_URL="http://your-proxy-url/v1"
239
- export OPENCODE_DCP_EXTERNAL_COMPRESS_MODEL="your-model-name"
240
- # Optional:
241
- export OPENCODE_DCP_EXTERNAL_COMPRESS_KEY="your-api-key"
242
- export OPENCODE_DCP_EXTERNAL_COMPRESS_TIMEOUT="120000"
243
- export OPENCODE_DCP_EXTERNAL_COMPRESS_RETRIES="1"
244
- ```
245
-
246
- 在 shell RC 文件(`~/.zshrc`、`~/.bashrc`)中持久化,以便跨会话自动可用。
247
-
248
- **方法 2 — 配置文件(`dcp.jsonc`):**
249
-
250
- ```jsonc
251
- {
252
- "compress": {
253
- "externalModel": {
254
- "url": "http://your-proxy-url/v1",
255
- "model": "your-model-name",
256
- "apiKey": "your-api-key",
257
- "timeout": 120000,
258
- "retries": 1,
259
- },
260
- },
261
- }
85
+ npm test
86
+ npm run typecheck
87
+ npm run build
88
+ npm run format:check
89
+ npm run check:package
262
90
  ```
263
91
 
264
- #### 行为说明
265
-
266
- | 场景 | 行为 |
267
- | --------------------------------- | ------------------------------------------------ |
268
- | 配置了外部模型 + 未提供 `summary` | 插件获取范围内容 → 调用外部模型 → 存储生成的摘要 |
269
- | 配置了外部模型 + 提供了 `summary` | 插件直接使用提供的 `summary`(向后兼容) |
270
- | 外部模型调用失败 | 工具抛出错误;主模型使用回退摘要重试 |
271
- | 未配置 | 一切不变——主模型像以前一样编写摘要 |
272
- | `url` 不兼容 OpenAI | 外部模型调用失败 → 进入上述错误路径 |
273
-
274
- **兼容性:** 仅支持兼容 OpenAI 的 `/chat/completions` 端点(本地代理、OpenAI、DeepSeek 等)。
275
-
276
- ## 对提示词缓存的影响
277
-
278
- LLM 提供商基于精确前缀匹配来缓存提示词。当 DCP 剪枝内容时,它会修改消息,从而从该位置开始使缓存的提示词前缀失效。
279
-
280
- **权衡:** 你会损失一些缓存命中,但通过减小上下文尺寸和减少因过时上下文导致的幻觉来获得 token 节省。在大多数情况下,尤其是在长会话中,节省量超过了缓存未命中的成本。
281
-
282
- > [!NOTE]
283
- > 测试中,使用 DCP 的缓存命中率约为 85%,而未使用时约为 90%。
284
-
285
- **无影响的情况:**
286
-
287
- - **按请求计费** — 按请求收费而非按 token 收费的提供商,如 GitHub Copilot。
288
- - **统一 token 定价** — 对缓存和未缓存 token 按相同费率计费的提供商,如 Cerebras。
289
-
290
- ## License
92
+ 许可:AGPL-3.0-or-later。