Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 37 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,35 @@ DCP uses its own config file:
"enabled": true,
// Enable debug logging to ~/.config/opencode/logs/dcp/
"debug": false,
// Summary display: "off", "minimal", or "detailed"
"pruningSummary": "detailed",
// Strategies for pruning tokens from chat history
// Notification display: "off", "minimal", or "detailed"
"pruneNotification": "detailed",
// Protect from pruning for <turns> message turns
"turnProtection": {
"enabled": false,
"turns": 4
},
// LLM-driven context pruning tools
"tools": {
// Shared settings for all prune tools
"settings": {
// Nudge the LLM to use prune tools (every <nudgeFrequency> tool results)
"nudgeEnabled": true,
"nudgeFrequency": 10,
// Additional tools to protect from pruning
"protectedTools": []
},
// Removes tool content from context without preservation (for completed tasks or noise)
"discard": {
"enabled": true
},
// Distills key findings into preserved knowledge before removing raw content
"extract": {
"enabled": true,
// Show distillation content as an ignored message notification
"showDistillation": false
}
},
// Automatic pruning strategies
"strategies": {
// Remove duplicate tool calls (same tool with same arguments)
"deduplication": {
Expand All @@ -74,40 +100,6 @@ DCP uses its own config file:
"supersedeWrites": {
"enabled": true
},
// Removes tool content from context without preservation (for completed tasks or noise)
"discardTool": {
"enabled": true,
// Additional tools to protect from pruning
"protectedTools": [],
// Protect from pruning for <turn protection> message turns
"turnProtection": {
"enabled": false,
"turns": 4
},
// Nudge the LLM to use the discard tool (every <frequency> tool results)
"nudge": {
"enabled": true,
"frequency": 10
}
},
// Distills key findings into preserved knowledge before removing raw content
"extractTool": {
"enabled": true,
// Additional tools to protect from pruning
"protectedTools": [],
// Protect from pruning for <turn protection> message turns
"turnProtection": {
"enabled": false,
"turns": 4
},
// Nudge the LLM to use the extract tool (every <frequency> tool results)
"nudge": {
"enabled": true,
"frequency": 10
},
// Show distillation content as an ignored message notification
"showDistillation": false
},
// (Legacy) Run an LLM to analyze what tool calls are no longer relevant on idle
"onIdle": {
"enabled": false,
Expand All @@ -126,12 +118,19 @@ DCP uses its own config file:

</details>

### Turn Protection

When enabled, turn protection prevents tool outputs from being pruned for a configurable number of message turns. This gives the AI time to reference recent tool outputs before they become prunable. Applies to both `discard` and `extract` tools, as well as automatic strategies.

### Protected Tools

By default, these tools are always protected from pruning across all strategies:
`task`, `todowrite`, `todoread`, `discard`, `extract`, `batch`

The `protectedTools` arrays in each strategy add to this default list.
The `protectedTools` arrays in each section add to this default list:
- `tools.settings.protectedTools` — Protects tools from the `discard` and `extract` tools
- `strategies.deduplication.protectedTools` — Protects tools from deduplication
- `strategies.onIdle.protectedTools` — Protects tools from on-idle analysis

### Config Precedence

Expand Down
12 changes: 6 additions & 6 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ const plugin: Plugin = (async (ctx) => {

return {
"experimental.chat.system.transform": async (_input: unknown, output: { system: string[] }) => {
const discardEnabled = config.strategies.discardTool.enabled
const extractEnabled = config.strategies.extractTool.enabled
const discardEnabled = config.tools.discard.enabled
const extractEnabled = config.tools.extract.enabled

let promptName: string
if (discardEnabled && extractEnabled) {
Expand All @@ -51,7 +51,7 @@ const plugin: Plugin = (async (ctx) => {
config
),
tool: {
...(config.strategies.discardTool.enabled && {
...(config.tools.discard.enabled && {
discard: createDiscardTool({
client: ctx.client,
state,
Expand All @@ -60,7 +60,7 @@ const plugin: Plugin = (async (ctx) => {
workingDirectory: ctx.directory
}),
}),
...(config.strategies.extractTool.enabled && {
...(config.tools.extract.enabled && {
extract: createExtractTool({
client: ctx.client,
state,
Expand All @@ -74,8 +74,8 @@ const plugin: Plugin = (async (ctx) => {
// Add enabled tools to primary_tools by mutating the opencode config
// This works because config is cached and passed by reference
const toolsToAdd: string[] = []
if (config.strategies.discardTool.enabled) toolsToAdd.push("discard")
if (config.strategies.extractTool.enabled) toolsToAdd.push("extract")
if (config.tools.discard.enabled) toolsToAdd.push("discard")
if (config.tools.extract.enabled) toolsToAdd.push("extract")

if (toolsToAdd.length > 0) {
const existingPrimaryTools = opencodeConfig.experimental?.primary_tools ?? []
Expand Down
Loading