How opencode-dcp/opencode-dynamic-context-pruning works
1. What this repo is
- This is a TypeScript plugin for OpenCode that manages conversation context by pruning, compressing, and summarizing messages before they are sent to the model.
- The core architectural boundary is between OpenCode’s session/message stream and DCP’s context-management layer, which rewrites context in a way that preserves session history semantics without deleting the original conversation.
2. Entry points and plugin wiring
- index.ts and tui.tsx are the main package entry surfaces.
- lib/hooks.ts is the runtime integration point where DCP attaches to OpenCode lifecycle events.
- lib/commands/* registers slash commands and manual controls, while lib/tui/* provides the interactive panel shown by /dcp.
3. Context-management pipeline
- The main pruning/compression flow lives under lib/compress/.
- pipeline.ts orchestrates the overall pass: inspect session state, choose targets, apply strategies, generate summaries, and emit replacements/placeholders.
- Supporting modules split the work into range selection, message lookup, protected content handling, timing, and state reconstruction.
4. Two compression modes
- The repo supports range mode and message mode.
- Range mode compresses contiguous spans of conversation into summaries; message mode compresses individual messages independently.
- This choice affects the shape of data that flows through the compression pipeline and how placeholders and nested summaries are produced.
5. Message model and transformation layer
- lib/messages/* contains the data-shaping logic that understands OpenCode message types, priorities, queries, pruning markers, sync behavior, and injected subagent results.
- This layer is responsible for turning raw session messages into DCP’s internal compression/pruning representation and back into the form OpenCode can consume.
6. Automatic pruning strategies
- lib/strategies/ contains non-compression cleanup passes such as deduplication and purge-errors.
- These are recalculated on compression-triggering events, so the pruning model is “recompute from session state” rather than incrementally mutating historical data.
- The readme’s “automatic cleanup” corresponds to this subsystem.
7. State, persistence, and caching
- lib/state/ tracks plugin runtime state, persistent configuration-derived state, and tool/result caches.
- This is where DCP remembers prior compression state, active summaries, and any bookkeeping needed across turns or restarts.
- The plugin appears designed to regenerate derived pruning results from durable state rather than relying only on in-memory history.
8. Configuration and policy boundaries
- lib/config.ts loads and merges config from global, custom, and project scopes described in the readme.
- dcp.schema.json defines the configuration schema used for validation and editor support.
- Policy modules such as lib/host-permissions.ts, lib/compress-permission.ts, and lib/auth.ts gate whether actions are allowed, need approval, or should be hidden entirely.
9. Prompt generation and override system
- lib/prompts/ holds the system prompt and the specialized prompts used for compression nudges and summaries.
- Prompt files are treated as first-class behavior inputs: the plugin can emit prompt text to steer the model toward compression at the right time.
- lib/prompts/store.ts plus the prompt override feature in the readme indicate a managed-defaults + user-overrides model.
10. Nudging and timing
- lib/compress/timing.ts, lib/messages/priority.ts, and the prompt modules work together to decide when the model should be reminded to compress.
- This is how DCP implements soft context thresholds, iteration-based nudges, and turn-based reminders rather than relying only on hard context limits.
- The result is proactive behavior: the model is encouraged to compress before the session becomes too large.
11. User interface and observability
- lib/tui/ implements the DCP panel: context view, stats, dialogs, and manual-mode controls.
- lib/ui/notification.ts and lib/logger.ts handle user-facing feedback and debug output.
- The UI is a control/visibility layer only; the actual pruning decisions still come from the compression and strategy subsystems.
12. Utilities, update path, and external behavior
- lib/update.ts supports auto-update behavior mentioned in the config.
- lib/token-utils.ts and related utilities support token counting and context-limit calculations.
- The scripts/ directory provides operational tooling for inspecting sessions, token usage, and cached DCP state, which is useful for debugging and validating the pruning behavior.
13. Tests as architecture clues
- The tests/ suite covers compression behavior, placeholder behavior, permissions, prompt generation, message IDs, token counting, and update logic.
- This strongly suggests the repo’s critical correctness boundary is deterministic transformation of session data, not network I/O or persistent server state.
14. Overall data flow
- OpenCode emits session events and tool calls.
- DCP hooks inspect those events, apply permissions and config, then run strategies and/or compression.
- The result is a rewritten context package with placeholders, summaries, and protected content preserved, plus optional notifications and TUI updates.
- The original session remains intact; DCP only changes what gets forwarded to the model.
15. Main architectural boundary to diagram
- The key box to draw is a middleware-like plugin layer sitting between OpenCode session history and LLM request context.
- Around that core are three supporting rings: policy/config, prompt/UI, and state/strategy subsystems.
Main entry points: pipeline.ts Pipeline · hooks.ts Hooks · index.ts Message model · ui.tsx TUI
Components 22
Entry points
Package surfaces and runtime wiring
Context pruning
Compression pipeline and message transformation
- Pipeline · Coordinates inspection, target selection, strategy application, and replacement emission
lib/compress/pipeline.ts - Range mode · Compresses spans of conversation into summaries and placeholders
lib/compress/range.ts - Message mode · Compresses individual messages independently
lib/compress/message.ts - Selection · Finds targets, ranges, and message matches for compression
lib/compress/search.ts - Protected content · Preserves pinned or protected material during rewriting
lib/compress/protected-content.ts - Message model · Transforms OpenCode messages into DCP compression and pruning structures
lib/messages/index.ts - Injection · Handles injected tool and subagent results in the message stream
lib/messages/inject/inject.ts - Pruning rules · Normalizes priorities, queries, sync markers, and prune markers
lib/messages/prune.ts - Strategies · Recomputed automatic cleanup such as deduplication and error purging
lib/strategies/index.ts
Policy and config
Configuration, permissions, and prompt inputs
- Config · Loads and merges global, project, and custom configuration
lib/config.ts - Permissions · Decides whether compression and host actions are allowed or hidden
lib/compress-permission.ts - Prompts · System prompt, compression nudges, and overrideable prompt text
lib/prompts/index.ts
UI and controls
Interactive panel, commands, and feedback
State and ops
Persistence, caches, utilities, and update support
- State · Persistent compression state, bookkeeping, and caches
lib/state/index.ts - Token utils · Token counting and context-limit calculations
lib/token-utils.ts - Update · Supports plugin update behavior and release checks
lib/update.ts
Connections 25
- OpenCode → Hooks: session events · OpenCode lifecycle events are intercepted by the plugin
- index.ts → Hooks: wire runtime · Main package entry initializes hook integration
- tui.tsx → TUI: mount UI · Standalone TUI entry loads the interactive panel
- Hooks → Config: load policy · Runtime decisions use merged configuration
- Hooks → Permissions: gate actions · Compression and host actions are checked against policy
- Hooks → State: read/write · Plugin state and caches are updated across turns
- Hooks → Pipeline: trigger compression · Compression runs when session events require rewriting
- Pipeline → Selection: pick targets · Pipeline identifies spans or messages to compress
- Pipeline → Protected content: preserve content · Protected content is excluded from destructive rewriting
- Pipeline → Range mode: range flow · Contiguous spans are summarized in range mode
- Pipeline → Message mode: message flow · Independent messages are summarized in message mode
- Pipeline → Message model: shape data · Pipeline converts raw session messages into DCP structures
- Message model → Injection: handle injections · Injected tool and subagent outputs are normalized
- Message model → Pruning rules: normalize markers · Priority, query, sync, and prune metadata are interpreted
- Message model → Strategies: cleanup passes · Message-level cleanup can be recomputed from session state
- Strategies → State: derive state · Cleanup results are recalculated from durable state
- Config → Prompts: select text · Configuration controls prompt defaults and overrides
- Prompts → Pipeline: nudge model · Prompt text steers the model toward timely compression
- Token utils → Prompts: thresholds · Token sizing and context limits inform nudge timing
- Token utils → Pipeline: size context · Compression decisions consider context budget
- Commands → Pipeline: manual control · Slash commands can trigger recompress, decompress, sweep, and stats
- Commands → TUI: open panel · Manual controls are exposed in the interactive UI
- TUI → State: inspect state · Panel renders current compression state and cached results
- TUI → Notify: surface feedback · UI actions produce notifications and logs
- State → Update: support ops · Runtime state includes update-related behavior and bookkeeping