Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
193 commits
Select commit Hold shift + click to select a range
43d6e7a
refactor: compress to rule them all
spoons-and-mirrors Feb 9, 2026
7e3fbed
tweaks
spoons-and-mirrors Feb 9, 2026
00ae4b4
3.0 release image
spoons-and-mirrors Feb 10, 2026
55f4f5f
prompt rewrite
spoons-and-mirrors Feb 10, 2026
8c28716
feat: annotate tool outputs with token counts
spoons-and-mirrors Feb 11, 2026
553ca89
pull prompts from dev for ref
spoons-and-mirrors Feb 11, 2026
6bdbd95
remove uid refs
spoons-and-mirrors Feb 11, 2026
8d21d58
refine tool format
spoons-and-mirrors Feb 11, 2026
15e4f17
prompts
spoons-and-mirrors Feb 11, 2026
a65d5db
rm dev prompts
spoons-and-mirrors Feb 11, 2026
9cffd3c
nudge
spoons-and-mirrors Feb 11, 2026
90318ce
changin token count wording
spoons-and-mirrors Feb 11, 2026
4c6b024
prompts: preserving user intent
spoons-and-mirrors Feb 11, 2026
1132af4
nudgeGap
spoons-and-mirrors Feb 12, 2026
da56861
feat: cLog
spoons-and-mirrors Feb 11, 2026
e391a8f
summary searching sucks
Tarquinen Feb 12, 2026
7741734
nudge
spoons-and-mirrors Feb 12, 2026
7a48c26
prompts
spoons-and-mirrors Feb 12, 2026
9b40772
cleanup context-limit hint injection architecture
Tarquinen Feb 12, 2026
ffc340d
token counts targets
spoons-and-mirrors Feb 12, 2026
701088b
range chronology badgering
spoons-and-mirrors Feb 12, 2026
13d622a
tool inputs badger
spoons-and-mirrors Feb 12, 2026
48d4729
refactor context-limit anchor lifecycle
Tarquinen Feb 12, 2026
eea6067
rename
Tarquinen Feb 12, 2026
3b19bb8
cleanup
Tarquinen Feb 12, 2026
e2b2797
cleanup
Tarquinen Feb 12, 2026
4025efe
cleanup
Tarquinen Feb 12, 2026
7608931
bargraph: v1
spoons-and-mirrors Feb 12, 2026
63bd217
bargraph v2
spoons-and-mirrors Feb 12, 2026
5c8e9b7
different shading for "new stuff since last compress use"
spoons-and-mirrors Feb 12, 2026
07eb6b5
cleanup
Tarquinen Feb 12, 2026
aa60c0d
remath proportional bargraph display
spoons-and-mirrors Feb 12, 2026
12c763a
cleanup
Tarquinen Feb 12, 2026
fca89fb
Merge branch 'refactor/one-tool-to-rule-them-all' into cleanup/contex…
Tarquinen Feb 12, 2026
83907c2
cleanup
Tarquinen Feb 12, 2026
38dc7f4
Merge pull request #386 from Opencode-DCP/cleanup/context-limit-hints
Tarquinen Feb 12, 2026
ed7e66f
use real nudge prompt
Tarquinen Feb 12, 2026
96e5b2e
add system prompt to bargraph session representation and use full bra…
spoons-and-mirrors Feb 12, 2026
96062b0
differentiate system prompt char
spoons-and-mirrors Feb 12, 2026
d4d637f
refactor: derive compress graph from token buckets
Tarquinen Feb 13, 2026
94f97bd
remove: unused contextPressure and compressContext config options
Tarquinen Feb 13, 2026
6c9c795
remove: unused nudgeEnabled and nudgeFrequency config options
Tarquinen Feb 13, 2026
bffa213
refactor: rename limitNudgeInterval to nudgeGap
Tarquinen Feb 13, 2026
e18f764
cleanup: remove dead prune/distill refs from prompts
Tarquinen Feb 13, 2026
acd72b9
cleanup: remove prune/distill remnants
spoons-and-mirrors Feb 13, 2026
7de0666
cleanup: simplify prompts to compress-only
Tarquinen Feb 13, 2026
8896aaa
cleanup: remove ToolFlags, simplify renderSystemPrompt
Tarquinen Feb 13, 2026
2399d1f
fix: fallback token accounting when api tokens missing
spoons-and-mirrors Feb 13, 2026
eaf25eb
cleanup: remove prompt loading indirection
Tarquinen Feb 13, 2026
43497b1
cleanup: rename applyAnchoredHints to applyAnchoredNudge
Tarquinen Feb 13, 2026
3684485
cleanup: remove unused nudgeCounter
Tarquinen Feb 13, 2026
e2cb885
cleanup: remove unused lastToolPrune
Tarquinen Feb 13, 2026
6ab7f24
feat(ui): render positional compress graph
Tarquinen Feb 13, 2026
65b016c
fix(compress): reject ambiguous summary matches
Tarquinen Feb 13, 2026
8af64d1
feat(ui): restore strict bargraph v2 compress map
Tarquinen Feb 13, 2026
0bdce2e
cleanup(ui): remove unused compression graph helpers
Tarquinen Feb 13, 2026
a600a10
cleanup: don't search reasoning parts for compress strings
Tarquinen Feb 13, 2026
65dcd21
chore: default nudgeGap to 5
Tarquinen Feb 13, 2026
302e901
format
Tarquinen Feb 13, 2026
53dee49
Merge pull request #381 from misterdas/fix/critical-bugs-and-improvem…
Tarquinen Feb 14, 2026
6ce2fb4
Merge remote-tracking branch 'origin/dev' into refactor/one-tool-to-r…
Tarquinen Feb 14, 2026
1394615
refactor: rework compress flow with block placeholders
Tarquinen Feb 15, 2026
3d867b3
docs: clarify compress placeholder guidance
Tarquinen Feb 15, 2026
80c8fd0
prompt: removing macro scale, try and force the model to compress sho…
spoons-and-mirrors Feb 15, 2026
8f57ea3
Merge branch 'refactor/one-tool-to-rule-them-all' into feat/compress-…
Tarquinen Feb 15, 2026
fd233eb
refactor: migrate scripts to OpenCode session API
Tarquinen Feb 15, 2026
eddf269
feat: migrate compress to injected ID boundaries
Tarquinen Feb 16, 2026
7b0dfea
Merge pull request #392 from Opencode-DCP/feat/compress-block-placeho…
Tarquinen Feb 16, 2026
385f361
refactor: migrate compress boundary resolution to injected IDs
Tarquinen Feb 17, 2026
27ed0b1
docs: update compress boundary guidance
Tarquinen Feb 17, 2026
0bd9771
refactor: inject assistant message IDs into last tool output
Tarquinen Feb 17, 2026
e59e216
docs: clarify dcp message-id metadata tags in prompts
Tarquinen Feb 17, 2026
66f4e66
refactor: inject IDs after compress
Tarquinen Feb 17, 2026
362352d
refactor: align compress blocks with bN metadata and placeholders
Tarquinen Feb 17, 2026
3c9ce68
docs: simplify and align compress/system ID guidance
Tarquinen Feb 17, 2026
12dc48c
refactor: make synthetic injection IDs deterministic
Tarquinen Feb 17, 2026
298d3eb
refactor: rename nudgeGap to nudgeFrequency and fix config inconsiste…
Tarquinen Feb 17, 2026
47017dc
refactor: remove tools.settings.protectedTools
Tarquinen Feb 18, 2026
e8e29e7
fix: preserve compress input schema when pruning
Tarquinen Feb 18, 2026
73220ff
refactor: gate ID injection on compress permission
Tarquinen Feb 18, 2026
2348e75
cleanup
Tarquinen Feb 18, 2026
3142eb9
feat: migrate opencode scripts from API to sqlite
Tarquinen Feb 18, 2026
506da6c
refactor: move inject helpers to messages utils
Tarquinen Feb 18, 2026
1a7442d
feat: add soft nudge anchors for context reminders
Tarquinen Feb 19, 2026
ea36818
refactor: stop generating non-system prompts from markdown
Tarquinen Feb 19, 2026
c75edaa
fix: guard malformed compress summaries
Tarquinen Feb 19, 2026
0752119
Merge branch 'dev' into refactor/one-tool-to-rule-them-all, resolving…
Tarquinen Feb 19, 2026
90889d0
refactor: simplify compress notification summary and rename header wr…
Tarquinen Feb 19, 2026
2fa382f
refactor: remove compress wrappers
Tarquinen Feb 19, 2026
ba4e7d4
fix(utils): skip thought signature validator for google and vertex mo…
Tarquinen Feb 21, 2026
c8d3404
feat(utils): add system note to synthetic tool part
Tarquinen Feb 21, 2026
f81d135
feat(utils): format synthetic tool system note as xml
Tarquinen Feb 21, 2026
418533b
feat(scripts): add summary statistics to session timeline
Tarquinen Feb 21, 2026
c9a8239
feat(logger): include tool title and metadata in context logs
Tarquinen Feb 21, 2026
9433f63
refactor(utils): replace claude check with text-part capability helper
Tarquinen Feb 21, 2026
7f86002
chore(prune): stop rewriting compress summaries
Tarquinen Feb 21, 2026
cd5bc53
refactor: rename remaining soft nudge references to turn nudge
Tarquinen Feb 22, 2026
fe92176
ui: expand compress progress bar to 75 chars and reposition
Tarquinen Feb 22, 2026
592cebf
refactor: remove redundant isIgnoredUserMessage check
Tarquinen Feb 22, 2026
66f5e3e
fix: strip hallucinated message-id and turn-nudge blocks
Tarquinen Feb 22, 2026
377ad29
feat: add iteration nudges and consolidate nudge state
Tarquinen Feb 22, 2026
dfa1f7a
refactor(config): flatten compress settings into top-level config
Tarquinen Feb 22, 2026
e80fc54
refactor(nudges): centralize anchored nudge application
Tarquinen Feb 22, 2026
b902968
ui: reduce compress progress bar to 50 chars
Tarquinen Feb 22, 2026
cdabdb7
fix(context): correct tool counts with compressed ranges
Tarquinen Feb 22, 2026
29f42b1
fix(nudges): anchor turn nudges to user messages
Tarquinen Feb 22, 2026
3b17792
fix(manual): skip nudge injection in manual mode
Tarquinen Feb 22, 2026
0aa9750
prompt wording
Tarquinen Feb 22, 2026
dbd00f5
v2.2.0-beta0 - Bump version
Tarquinen Feb 22, 2026
8bc4f6c
docs(readme): add beta notice
Tarquinen Feb 22, 2026
be1e68f
docs(readme): restore config collapse text
Tarquinen Feb 22, 2026
1bf2b4f
refactor: move message strategies to compress tool
Tarquinen Feb 23, 2026
95d76cb
fix: add deepseek models to rejectsTextParts
Tarquinen Feb 23, 2026
d524f24
disable supersede writes for now, causes llm confusion when write too…
Tarquinen Feb 23, 2026
bbd5909
fix(compress): filter out ignored user messages from session bar graph
Tarquinen Feb 23, 2026
d5f449c
chore: remove unused compress logger
Tarquinen Feb 23, 2026
a2d14b1
refactor: rename helper
Tarquinen Feb 23, 2026
17a3119
v2.2.1-beta0 - Bump version
Tarquinen Feb 23, 2026
933255a
refactor: rename internal utilities and clean up prune logic
Tarquinen Feb 24, 2026
0e8fce5
feat(nudge): add configurable user/assistant turn anchoring
Tarquinen Feb 24, 2026
1d836d7
refactor(prompts): simplify nudge and compress prompt imports
Tarquinen Feb 24, 2026
3f6c413
chore(prompts): clarify compress-tool wording
Tarquinen Feb 24, 2026
6ec8c2b
docs(config): simplify nudge descriptions
Tarquinen Feb 24, 2026
c15ffcb
v2.2.2-beta0 - Bump version
Tarquinen Feb 24, 2026
4484cd4
feat: add compress.protectedTools configuration
Tarquinen Feb 24, 2026
b94705b
docs: update schema and README for compress.protectedTools
Tarquinen Feb 24, 2026
e86c631
feat: append tools matching protectedFilePatterns to compression summ…
Tarquinen Feb 24, 2026
d8398f3
chore: disable rejectsTextParts logic for beta testing
Tarquinen Feb 24, 2026
291d5cc
v2.2.3-beta0 - Version bump
Tarquinen Feb 24, 2026
8f4c276
fix(hooks): append system prompt to last output part
Tarquinen Feb 25, 2026
f8e1a0f
v2.2.4-beta0 - Bump version
Tarquinen Feb 25, 2026
8975e50
refactor(compress): implement structured compression block state
Tarquinen Feb 26, 2026
527d81f
fix(hooks): reorder syncCompressionBlocks to handle undos correctly
Tarquinen Feb 27, 2026
afb58b9
Merge pull request #412 from Opencode-DCP/refactor/structured-compres…
Tarquinen Feb 27, 2026
90550d0
feat(config): add experimental subagent opt-in
Tarquinen Feb 27, 2026
b0f0d77
fix(config): gate primary compress tool for subagent opt-in
Tarquinen Feb 27, 2026
bbd3349
fix(logger): include tool state metadata in context logs
Tarquinen Feb 27, 2026
050e556
feat(subagents): enrich task outputs from child session results
Tarquinen Feb 27, 2026
70e968f
fix(subagents): gate result enrichment behind experimental flag
Tarquinen Feb 27, 2026
fc8ac20
fix(subagents): harden result cache and compress merge checks
Tarquinen Feb 27, 2026
79b1fa5
Merge pull request #413 from Opencode-DCP/feat/experimental-subagent-…
Tarquinen Feb 27, 2026
cbbd177
v2.2.5-beta0 - Bump version
Tarquinen Feb 27, 2026
9def114
fix(message-ids): skip refs for ignored user messages
Tarquinen Feb 28, 2026
3533b3c
fix(message-ids): skip ref for first subagent user message
Tarquinen Feb 28, 2026
ed1aad7
fix(nudges): add active block placeholder guidance
Tarquinen Feb 28, 2026
740dc45
fix(message-ids): start refs at m0001
Tarquinen Feb 28, 2026
f5590d8
fix(prompts): add subagent safety section
Tarquinen Feb 28, 2026
77922c2
feat(compress): add max/min nudge limits
Tarquinen Feb 28, 2026
23fc5c9
v2.2.6-beta0 - Bump version
Tarquinen Feb 28, 2026
d0a6fc9
refactor(messages): rename injectors
Tarquinen Feb 28, 2026
6b09c32
docs(contributing): clarify contribution quality
Tarquinen Feb 28, 2026
87ccb78
docs(readme): refresh compress and cache guidance
Tarquinen Feb 28, 2026
d8318f0
fix(messages): strip stale Claude reasoning
Tarquinen Feb 28, 2026
c159eae
replace reasoning strip with metadata stripping for mismatched model
Tarquinen Feb 28, 2026
137b29e
include metadata in text and reasoning debug log parts
Tarquinen Feb 28, 2026
d656b20
v2.2.7-beta0 - Bump version
Tarquinen Feb 28, 2026
de17918
feat: highlight most recently compressed messages in progress bar
Tarquinen Mar 1, 2026
8d0adef
feat: inject active compressed block guidance into manual compress tr…
Tarquinen Mar 1, 2026
d1f5de6
feat(decompress): add decompress command and restore workflow
Tarquinen Mar 1, 2026
3b67084
feat(notification): include compression IDs in compress status
Tarquinen Mar 1, 2026
01b544d
feat(prompts): rework context-limit nudge for max-limit recovery
Tarquinen Mar 1, 2026
97531c8
feat(compress): track newly compressed items for accurate notifications
Tarquinen Mar 2, 2026
8f39878
refactor(notification): derive compression details from block state
Tarquinen Mar 2, 2026
20f8546
readme install update
Tarquinen Mar 2, 2026
1dcbc6a
refactor(decompress): rename uncompress command and simplify usage ou…
Tarquinen Mar 2, 2026
13cc541
feat(recompress): add /dcp recompress command
Tarquinen Mar 2, 2026
0d70e09
refactor(tools): rename compress-utils module to utils
Tarquinen Mar 2, 2026
43ccb7b
feat(prompts): add runtime custom prompt overrides
Tarquinen Mar 2, 2026
3e181b5
docs(readme): document prompt overrides and protected skill tool
Tarquinen Mar 2, 2026
7cd0d2d
refactor(prompts): source system prompt from TypeScript
Tarquinen Mar 2, 2026
f26d424
docs(readme): update install tag and prompt override guidance
Tarquinen Mar 2, 2026
492d4a1
Merge pull request #414 from Opencode-DCP/feat/custom-prompts-runtime
Tarquinen Mar 2, 2026
3fc460d
fix(compress): avoid duplicate protected-tool injection in nested com…
Tarquinen Mar 2, 2026
9c6378f
fix(compress): graceful fallback
Tarquinen Mar 2, 2026
676cec0
v2.2.8-beta0 - Bump version
Tarquinen Mar 2, 2026
564bb43
feat(config): add wildcard/glob pattern support for protectedTools
Tarquinen Mar 4, 2026
82dbde2
cleanup
Tarquinen Mar 4, 2026
939a542
refactor: rename isProtected to isFilePathProtected for clarity
Tarquinen Mar 4, 2026
2e28894
fix(subagents): strip hallucinated tags from merged sub-agent results
Tarquinen Mar 4, 2026
6a5e2ef
Show raw LLM summary in showCompression notification
Tarquinen Mar 4, 2026
418a5d6
word change
Tarquinen Mar 4, 2026
29524b9
Rewrite README for clarity and conciseness
Tarquinen Mar 4, 2026
8f253ff
Exclude ignored messages from context logs
Tarquinen Mar 4, 2026
98bed9c
Consolidate user and assistant turn nudges into a single prompt
Tarquinen Mar 4, 2026
fe0d71c
simplify name
Tarquinen Mar 5, 2026
a05d856
fix: include cache.write in system prompt token calculation
Tarquinen Mar 6, 2026
8cab350
feat(manual): gate compress tool behind one-shot manual trigger
Tarquinen Mar 6, 2026
3ccc453
fix: insert injected text parts before tool parts in assistant messages
Tarquinen Mar 7, 2026
d5c6635
feat(compress): add flatSchema config option
Tarquinen Mar 7, 2026
0ab1849
readme flatSchema
Tarquinen Mar 7, 2026
0b3c111
feat(compress): add protectUserMessages config option
Tarquinen Mar 7, 2026
e58c647
readme protectUserMessages
Tarquinen Mar 7, 2026
7adc2c0
v2.2.9-beta0 - Bump version
Tarquinen Mar 8, 2026
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
5 changes: 4 additions & 1 deletion .repomixignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,7 @@ dist/
repomix-output.xml
bun.lock
package-lock.jsonc
LICENCE
LICENSE
scripts/
tests/
README.md
34 changes: 11 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ Restart OpenCode. The plugin will automatically start optimizing your sessions.

## How Pruning Works

DCP uses multiple tools and strategies to reduce context size:
DCP uses one user-facing tool and strategies to reduce context size:

### Tools
For model-facing behavior (prompts and tool calls), this capability is always addressed as `compress`.

**Distill** — Exposes a `distill` tool that the AI can call to distill valuable context into concise summaries before removing the tool content.
### Tool

**Compress** — Exposes a `compress` tool that the AI can call to collapse a large section of conversation (messages and tools) into a single summary.
**Compress** — Exposes a single `compress` tool with one method: match a conversation range using `startString` and `endString`, then replace it with a technical summary.

**Prune** — Exposes a `prune` tool that the AI can call to remove completed or noisy tool content from context.
The model can use that same method at different scales: tiny ranges for noise cleanup, focused ranges for preserving key findings, and full chapters for completed work.

### Strategies

Expand Down Expand Up @@ -105,11 +105,11 @@ DCP uses its own config file:
> // Protect file operations from pruning via glob patterns
> // Patterns match tool parameters.filePath (e.g. read/write/edit)
> "protectedFilePatterns": [],
> // LLM-driven context pruning tools
> // LLM-driven context management tool
> "tools": {
> // Shared settings for all prune tools
> // Shared settings for context management
> "settings": {
> // Nudge the LLM to use prune tools (every <nudgeFrequency> tool results)
> // Nudge the LLM to use context management (every <nudgeFrequency> tool results)
> "nudgeEnabled": true,
> "nudgeFrequency": 10,
> // Token limit at which the model compresses session context
Expand All @@ -126,25 +126,13 @@ DCP uses its own config file:
> // Additional tools to protect from pruning
> "protectedTools": [],
> },
> // Distills key findings into preserved knowledge before removing raw content
> "distill": {
> // Unified context compression tool
> "compress": {
> // Permission mode: "allow" (no prompt), "ask" (prompt), "deny" (tool not registered)
> "permission": "allow",
> // Show distillation content as an ignored message notification
> "showDistillation": false,
> },
> // Collapses a range of conversation content into a single summary
> "compress": {
> // Permission mode: "deny" (tool not registered), "ask" (prompt), "allow" (no prompt)
> "permission": "deny",
> // Show summary content as an ignored message notification
> "showCompression": false,
> },
> // Removes tool content from context without preservation (for completed tasks or noise)
> "prune": {
> // Permission mode: "allow" (no prompt), "ask" (prompt), "deny" (tool not registered)
> "permission": "allow",
> },
> },
> // Automatic pruning strategies
> "strategies": {
Expand Down Expand Up @@ -188,7 +176,7 @@ DCP provides a `/dcp` slash command:
### Protected Tools

By default, these tools are always protected from pruning:
`task`, `todowrite`, `todoread`, `distill`, `compress`, `prune`, `batch`, `plan_enter`, `plan_exit`
`task`, `todowrite`, `todoread`, `compress`, `batch`, `plan_enter`, `plan_exit`

The `protectedTools` arrays in each section add to this default list.

Expand Down
Binary file added assets/images/3.0 release.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
61 changes: 23 additions & 38 deletions dcp.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@
"type": "string",
"enum": ["off", "minimal", "detailed"],
"default": "detailed",
"description": "Level of notification shown when pruning occurs"
"description": "Level of notification shown when context management occurs"
},
"pruneNotificationType": {
"type": "string",
"enum": ["chat", "toast"],
"default": "chat",
"description": "Where to display prune notifications (chat message or toast notification)"
"description": "Where to display notifications (chat message or toast notification)"
},
"commands": {
"type": "object",
Expand Down Expand Up @@ -104,7 +104,7 @@
},
"tools": {
"type": "object",
"description": "Configuration for pruning tools",
"description": "Configuration for context-management tools",
"additionalProperties": false,
"properties": {
"settings": {
Expand All @@ -115,13 +115,19 @@
"nudgeEnabled": {
"type": "boolean",
"default": true,
"description": "Enable nudge reminders to prune context"
"description": "Enable nudge reminders to manage context"
},
"nudgeFrequency": {
"type": "number",
"default": 10,
"description": "Frequency of nudge reminders (in turns)"
},
"limitNudgeInterval": {
"type": "number",
"default": 1,
"minimum": 1,
"description": "How often the context-limit nudge fires when above contextLimit (1 = every fetch, 5 = every 5th fetch)"
},
"protectedTools": {
"type": "array",
"items": {
Expand All @@ -143,6 +149,16 @@
}
]
},
"contextPressureEnabled": {
"type": "boolean",
"default": true,
"description": "Inject a <context-pressure-tools> list of token-heavy tool outputs to guide compress decisions"
},
"compressContextEnabled": {
"type": "boolean",
"default": true,
"description": "Inject a <compress-context> block with message count and compress usage hints"
},
"modelLimits": {
"description": "Model-specific context limits by exact provider/model key. Examples: \"openai/gpt-5\", \"anthropic/claude-3-7-sonnet\", \"ollama/llama3.1\"",
"type": "object",
Expand All @@ -160,52 +176,21 @@
}
}
},
"distill": {
"type": "object",
"description": "Configuration for the distill tool",
"additionalProperties": false,
"properties": {
"permission": {
"type": "string",
"enum": ["ask", "allow", "deny"],
"default": "allow",
"description": "Permission mode (deny disables the tool)"
},
"showDistillation": {
"type": "boolean",
"default": false,
"description": "Show distillation output in the UI"
}
}
},
"compress": {
"type": "object",
"description": "Configuration for the compress tool",
"description": "Configuration for the unified compress tool",
"additionalProperties": false,
"properties": {
"permission": {
"type": "string",
"enum": ["ask", "allow", "deny"],
"default": "ask",
"default": "allow",
"description": "Permission mode (deny disables the tool)"
},
"showCompression": {
"type": "boolean",
"default": false,
"description": "Show summary output in the UI"
}
}
},
"prune": {
"type": "object",
"description": "Configuration for the prune tool",
"additionalProperties": false,
"properties": {
"permission": {
"type": "string",
"enum": ["ask", "allow", "deny"],
"default": "allow",
"description": "Permission mode (deny disables the tool)"
"description": "Show compression summaries in notifications"
}
}
}
Expand Down
24 changes: 1 addition & 23 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Plugin } from "@opencode-ai/plugin"
import { getConfig } from "./lib/config"
import { Logger } from "./lib/logger"
import { createSessionState } from "./lib/state"
import { createPruneTool, createDistillTool, createCompressTool } from "./lib/strategies"
import { createCompressTool } from "./lib/tools"
import {
createChatMessageTransformHandler,
createCommandExecuteHandler,
Expand Down Expand Up @@ -61,15 +61,6 @@ const plugin: Plugin = (async (ctx) => {
ctx.directory,
),
tool: {
...(config.tools.distill.permission !== "deny" && {
distill: createDistillTool({
client: ctx.client,
state,
logger,
config,
workingDirectory: ctx.directory,
}),
}),
...(config.tools.compress.permission !== "deny" && {
compress: createCompressTool({
client: ctx.client,
Expand All @@ -79,15 +70,6 @@ const plugin: Plugin = (async (ctx) => {
workingDirectory: ctx.directory,
}),
}),
...(config.tools.prune.permission !== "deny" && {
prune: createPruneTool({
client: ctx.client,
state,
logger,
config,
workingDirectory: ctx.directory,
}),
}),
},
config: async (opencodeConfig) => {
if (config.commands.enabled) {
Expand All @@ -99,9 +81,7 @@ const plugin: Plugin = (async (ctx) => {
}

const toolsToAdd: string[] = []
if (config.tools.distill.permission !== "deny") toolsToAdd.push("distill")
if (config.tools.compress.permission !== "deny") toolsToAdd.push("compress")
if (config.tools.prune.permission !== "deny") toolsToAdd.push("prune")

if (toolsToAdd.length > 0) {
const existingPrimaryTools = opencodeConfig.experimental?.primary_tools ?? []
Expand All @@ -118,9 +98,7 @@ const plugin: Plugin = (async (ctx) => {
const permission = opencodeConfig.permission ?? {}
opencodeConfig.permission = {
...permission,
distill: config.tools.distill.permission,
compress: config.tools.compress.permission,
prune: config.tools.prune.permission,
} as typeof permission
},
}
Expand Down
10 changes: 4 additions & 6 deletions lib/commands/help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,16 @@ const BASE_COMMANDS: [string, string][] = [
]

const TOOL_COMMANDS: Record<string, [string, string]> = {
prune: ["/dcp prune [focus]", "Trigger manual prune tool execution"],
distill: ["/dcp distill [focus]", "Trigger manual distill tool execution"],
compress: ["/dcp compress [focus]", "Trigger manual compress tool execution"],
}

function getVisibleCommands(config: PluginConfig): [string, string][] {
const commands = [...BASE_COMMANDS]
for (const tool of ["prune", "distill", "compress"] as const) {
if (config.tools[tool].permission !== "deny") {
commands.push(TOOL_COMMANDS[tool])
}

if (config.tools.compress.permission !== "deny") {
commands.push(TOOL_COMMANDS.compress)
}

return commands
}

Expand Down
61 changes: 5 additions & 56 deletions lib/commands/manual.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
*
* Usage:
* /dcp manual [on|off] - Toggle manual mode or set explicit state
* /dcp prune [focus] - Trigger manual prune execution
* /dcp distill [focus] - Trigger manual distill execution
* /dcp compress [focus] - Trigger manual compress execution
*/

Expand All @@ -14,33 +12,11 @@ import type { SessionState, WithParts } from "../state"
import type { PluginConfig } from "../config"
import { sendIgnoredMessage } from "../ui/notification"
import { getCurrentParams } from "../strategies/utils"
import { syncToolCache } from "../state/tool-cache"
import { buildToolIdList } from "../messages/utils"
import { buildPrunableToolsList } from "../messages/inject"

const MANUAL_MODE_ON =
"Manual mode is now ON. Use /dcp prune, /dcp distill, or /dcp compress to trigger context tools manually."
const MANUAL_MODE_ON = "Manual mode is now ON. Use /dcp compress to trigger context tools manually."

const MANUAL_MODE_OFF = "Manual mode is now OFF."

const NO_PRUNABLE_TOOLS = "No prunable tool outputs are currently available for manual triggering."

const PRUNE_TRIGGER_PROMPT = [
"<prune triggered manually>",
"Manual mode trigger received. You must now use the prune tool exactly once.",
"Find the most significant set of prunable tool outputs to remove safely.",
"Follow prune policy and avoid pruning outputs that may be needed later.",
"Return after prune with a brief explanation of what you pruned and why.",
].join("\n\n")

const DISTILL_TRIGGER_PROMPT = [
"<distill triggered manually>",
"Manual mode trigger received. You must now use the distill tool.",
"Select the most information-dense prunable outputs and distill them into complete technical substitutes.",
"Be exhaustive and preserve all critical technical details.",
"Return after distill with a brief explanation of what was distilled and why.",
].join("\n\n")

const COMPRESS_TRIGGER_PROMPT = [
"<compress triggered manually>",
"Manual mode trigger received. You must now use the compress tool.",
Expand All @@ -49,25 +25,13 @@ const COMPRESS_TRIGGER_PROMPT = [
"Return after compress with a brief explanation of what range was compressed.",
].join("\n\n")

function getTriggerPrompt(
tool: "prune" | "distill" | "compress",
context?: string,
userFocus?: string,
): string {
const base =
tool === "prune"
? PRUNE_TRIGGER_PROMPT
: tool === "distill"
? DISTILL_TRIGGER_PROMPT
: COMPRESS_TRIGGER_PROMPT
function getTriggerPrompt(tool: "compress", userFocus?: string): string {
const base = COMPRESS_TRIGGER_PROMPT

const sections = [base]
if (userFocus && userFocus.trim().length > 0) {
sections.push(`Additional user focus:\n${userFocus.trim()}`)
}
if (context) {
sections.push(context)
}

return sections.join("\n\n")
}
Expand Down Expand Up @@ -109,23 +73,8 @@ export async function handleManualToggleCommand(

export async function handleManualTriggerCommand(
ctx: ManualCommandContext,
tool: "prune" | "distill" | "compress",
tool: "compress",
userFocus?: string,
): Promise<string | null> {
const { client, state, config, logger, sessionId, messages } = ctx

if (tool === "prune" || tool === "distill") {
syncToolCache(state, config, logger, messages)
buildToolIdList(state, messages, logger)
const prunableToolsList = buildPrunableToolsList(state, config, logger)
if (!prunableToolsList) {
const params = getCurrentParams(state, messages, logger)
await sendIgnoredMessage(client, sessionId, NO_PRUNABLE_TOOLS, params, logger)
return null
}

return getTriggerPrompt(tool, prunableToolsList, userFocus)
}

return getTriggerPrompt("compress", undefined, userFocus)
return getTriggerPrompt(tool, userFocus)
}
Loading