### DCP CLI Examples Source: https://github.com/opencode-dcp/opencode-dynamic-context-pruning/blob/master/scripts/README.md Demonstrates common usage patterns for the DCP CLI tool. These examples show how to run the CLI with different prompt types. ```bash bun run dcp --system ``` ```bash bun run dcp --nudge ``` ```bash bun run dcp --context-tools ``` -------------------------------- ### Install DCP Plugin Globally Source: https://github.com/opencode-dcp/opencode-dynamic-context-pruning/blob/master/README.md Installs the DCP plugin and adds it to your global OpenCode configuration. Use this command to set up the plugin for system-wide use. ```bash opencode plugin @tarquinen/opencode-dcp@latest --global ``` -------------------------------- ### Configure Dynamic Context Pruning Plugin Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt Example JSON configuration for the DCP plugin. This file defines settings for compression, automatic pruning strategies, manual mode, and protection rules. It can be placed in `~/.config/opencode/dcp.jsonc` for global settings or `.opencode/dcp.jsonc` for project-specific settings. ```jsonc { "$schema": "https://raw.githubusercontent.com/Opencode-DCP/opencode-dynamic-context-pruning/master/dcp.schema.json", // ── Top-level ───────────────────────────────────────────────────────── "enabled": true, // Disable the entire plugin "debug": false, // Write debug logs to ~/.config/opencode/logs/dcp/ "pruneNotification": "detailed", // "off" | "minimal" | "detailed" "pruneNotificationType": "chat", // "chat" | "toast" // ── Compression tool ────────────────────────────────────────────────── "compress": { "mode": "range", // "range" (default) | "message" (experimental) "permission": "allow", // "allow" | "ask" | "deny" "maxContextLimit": 100000, // or "80%" — nudges fire hard above this "minContextLimit": 50000, // or "25%" — nudges fire softly above this "nudgeFrequency": 5, // inject nudge every N fetches above maxContextLimit "iterationNudgeThreshold": 15, // nudge after N iterations without user input "nudgeForce": "soft", // "strong" | "soft" "summaryBuffer": true, // let active summary tokens extend the effective limit "protectedTools": [], // tools whose outputs are always appended to summaries "protectUserMessages": false, // preserve user messages verbatim during compression "showCompression": false, // show compression content in a chat notification // Per-model overrides (optional): "modelMaxLimits": { "anthropic/claude-sonnet-4-5": "80%", "openai/gpt-4o": 90000 } }, // ── Automatic pruning strategies ────────────────────────────────────── "strategies": { "deduplication": { "enabled": true, "protectedTools": [] }, "purgeErrors": { "enabled": true, "turns": 4, // prune error-tool inputs after this many turns "protectedTools": [] } }, // ── Manual mode ─────────────────────────────────────────────────────── "manualMode": { "enabled": false, // start sessions in manual mode "automaticStrategies": true // dedup/purgeErrors still run in manual mode }, // ── Turn protection ─────────────────────────────────────────────────── "turnProtection": { "enabled": false, "turns": 4 // protect tool outputs for N turns after invocation }, // ── File/tool protection ────────────────────────────────────────────── "protectedFilePatterns": [ "src/core/**/*.ts", "**/.env" ], // ── Commands ────────────────────────────────────────────────────────── "commands": { "enabled": true, "protectedTools": [] // additional tools skipped by /dcp sweep }, // ── Experimental ────────────────────────────────────────────────────── "experimental": { "allowSubAgents": false, // enable DCP inside sub-agent sessions "customPrompts": false // enable editable prompt overrides } } ``` -------------------------------- ### Create Event Handler Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt Tracks compression timing by listening for 'message.part.updated' events on the 'compress' tool. Records start and duration of compression. ```typescript // Event handler — tracks compression timing: const eventHandler = createEventHandler(state, logger) // Listens for "message.part.updated" events on the "compress" tool. // Records start time on "pending", calculates durationMs on "completed", // and attaches durationMs to the matching CompressionBlock via // applyPendingCompressionDurations(). ``` -------------------------------- ### Ensure Session Initialized Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt Initializes or re-initializes session state for a specific session ID. This function is idempotent and handles various session setup steps. ```typescript // Initialize / reinitialize for a specific session (idempotent): await ensureSessionInitialized( client, state, "session-id-abc123", logger, messages, /* manualModeEnabled */ false, ) // Steps: // 1. Returns immediately if state.sessionId already matches // 2. Calls resetSessionState(state) // 3. Sets state.manualMode from manualModeEnabled config // 4. Detects sub-agent via client.session.get() metadata // 5. Finds last OpenCode compaction timestamp in messages // 6. Counts current turn number // 7. Collects turn nudge anchors from existing messages // 8. Loads and merges PersistedSessionState from disk: // - prune.tools, prune.messages, nudges, stats ``` -------------------------------- ### Token Utilities Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt Low-level token accounting functions using the '@anthropic-ai/tokenizer' package, with a character-based fallback. Includes functions to count tokens in strings, get current token usage, and sum estimated tokens for pruned tool calls. ```typescript import { countTokens, getCurrentTokenUsage, getTotalToolTokens, countToolTokens } from "./lib/token-utils" // Count tokens in any string (uses Anthropic's CL100k tokenizer): const tokens = countTokens("Hello, world!") // → 4 // Get total context size from the last assistant message's API-reported usage: // (input + output + reasoning + cache.read + cache.write) const totalContext = getCurrentTokenUsage(state, messages) // → e.g. 87_432 // Sum token estimates for a list of pruned tool call IDs: const savedTokens = getTotalToolTokens(state, ["call_abc", "call_def"]) // → e.g. 3_200 // Count tokens for a single tool part (input + output): const toolTokens = countToolTokens(toolPart) // → e.g. 1_800 // countTokens fallback behavior (when tokenizer unavailable): // return Math.round(text.length / 4) ``` -------------------------------- ### DCP Command Help Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt Lists all available `/dcp` commands and their basic functions. Use `/dcp` to display this help message. ```bash /dcp → show help /dcp context → token breakdown by category (system/user/assistant/tools) /dcp stats → session + all-time pruning statistics /dcp sweep → prune all tools since the previous user message /dcp sweep 10 → prune the last 10 tools /dcp manual → toggle manual mode on/off /dcp manual on → enable manual mode explicitly /dcp manual off → disable manual mode explicitly /dcp compress → trigger a single compress tool execution /dcp compress "focus text" → trigger compress with a hint about what to compress /dcp decompress → list active compressions with IDs and token sizes /dcp decompress 2 → restore (undo) compression #2 /dcp recompress → list user-decompressed compressions eligible for re-apply /dcp recompress 2 → re-apply previously undone compression #2 ``` -------------------------------- ### Plugin Entry Point - index.ts Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt This TypeScript file demonstrates how the DCP plugin is loaded by OpenCode. It shows the import of the Plugin type and outlines the structure of the context object provided to the plugin, as well as the expected return map of hooks. ```typescript // index.ts — how OpenCode loads the plugin import type { Plugin } from "@opencode-ai/plugin" // DCP's default export satisfies the Plugin type: // const server: Plugin = async (ctx) => { ... returns hook map } // ctx provides: // ctx.client — OpenCode API client (session, tui, etc.) // ctx.directory — working directory of the current project // Returned hook map: // { // "experimental.chat.system.transform" → injects DCP system prompt // "experimental.chat.messages.transform" → applies all pruning before LLM calls // "experimental.text.complete" → strips hallucinated DCP tags from output // "command.execute.before" → handles /dcp slash commands // "event" → tracks compress tool timing // "tool.compress" → the compress tool (if not denied) // "config" → wires permissions and primary_tools // } ``` -------------------------------- ### Run DCP CLI with Type Source: https://github.com/opencode-dcp/opencode-dynamic-context-pruning/blob/master/scripts/README.md Execute the DCP CLI tool to preview prompt outputs. Specify the prompt type as an argument. ```bash bun run dcp [TYPE] ``` -------------------------------- ### Compression Tool Construction and Logic Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt This snippet shows the internal construction of the `compress` tool, selecting between range and message modes based on configuration. It also outlines the key steps the tool performs, from session preparation to state persistence. ```typescript // Tool construction (internal): import { createCompressRangeTool, createCompressMessageTool } from "./lib/compress" const compressTool = config.compress.mode === "message" ? createCompressMessageTool({ client, state, logger, config, prompts }) : createCompressRangeTool({ client, state, logger, config, prompts }) // The tool: // 1. Calls prepareSession() → runs deduplication + purgeErrors first // 2. Resolves startId/endId to actual message indices via searchContext // 3. Injects nested block summaries for overlapping compressions // 4. Appends protected tool outputs and user messages to summary // 5. Calls applyCompressionState() to register the new CompressionBlock // 6. Sends a chat/toast notification with the summary // 7. Persists state to disk via saveSessionState() ``` -------------------------------- ### Create System Prompt Handler Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt Appends DCP guidance to the model's system prompt. Caches model context limit and skips internal OpenCode agents. ```typescript import { createSystemPromptHandler, createChatMessageTransformHandler, createEventHandler, createCommandExecuteHandler, createTextCompleteHandler, } from "./lib/hooks" // System prompt handler — appends DCP guidance to the model's system prompt: const systemHandler = createSystemPromptHandler(state, logger, config, prompts) // Called with: (input: { sessionID, model: { limit: { context } } }, output: { system: string[] }) // - Caches model.limit.context into state.modelContextLimit // - Skips internal OpenCode agents (title generator, summarizer) // - Appends renderSystemPrompt(...) to output.system ``` -------------------------------- ### Prompt Store Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt Manages the six editable DCP prompts, handling default and user-override configurations. ```APIDOC ## PromptStore ### Description Manages the six editable DCP prompts (`system`, `compress-range`, `compress-message`, `context-limit-nudge`, `turn-nudge`, `iteration-nudge`). When `experimental.customPrompts` is enabled, it writes defaults to `~/.config/opencode/dcp-prompts/defaults/` and reads user overrides from `overrides/` directories with project → config-dir → global precedence. ### Usage ```typescript new PromptStore(logger, projectPath, customPromptsEnabled) ``` ### Methods #### getRuntimePrompts ##### Description Gets the current runtime prompts. Returns a copy. ##### Returns An object containing the current runtime prompts: - `system`: DCP system instruction block. - `compressRange`: Range-mode tool description. - `compressMessage`: Message-mode tool description. - `contextLimitNudge`: Injected when context > maxContextLimit. - `turnNudge`: Injected at turn boundaries between min/max. - `iterationNudge`: Injected after iterationNudgeThreshold iterations. - `manualExtension`: Appended when manualMode is active. - `subagentExtension`: Appended inside sub-agent sessions. #### reload ##### Description Reloads prompts from disk, re-reading override files. ### Configuration Structure When `customPrompts = true`, the override directory structure is: `~/.config/opencode/dcp-prompts/` `defaults/` `system.md` `compress-range.md` `compress-message.md` `context-limit-nudge.md` `turn-nudge.md` `iteration-nudge.md` `README.md` `overrides/` `system.md` (user-editable) Project-level overrides have the highest priority: `.opencode/dcp-prompts/overrides/system.md` ``` -------------------------------- ### Compression Tool - Range Mode Invocation Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt Demonstrates how the `compress` tool is invoked in range mode by the model. It shows how to specify a topic and content with `startId` and `endId` boundaries, including referencing existing compression blocks. ```typescript // Range-mode invocation (called by the model, not directly by users): // compress({ // topic: "Auth System Exploration", // content: [ // { // startId: "m0001", // endId: "m0012", // summary: "Explored OAuth2 flow. Decided on PKCE for SPA. Key files: src/auth/pkce.ts" // }, // { // startId: "b2", // reference an existing compression block as start boundary // endId: "m0025", // summary: "Refactored token refresh; added 401 retry with exponential back-off." // } // ] // }) // → "Compressed 14 messages into [Compressed Block]." ``` -------------------------------- ### Session State Creation and Fields Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt This snippet shows how to create the session state object using `createSessionState` and lists its key fields for tracking pruning decisions, compression, and token statistics. It also details the structure of prune registries and compression blocks. ```typescript import { createSessionState } from "./lib/state" const state = createSessionState() // Key fields: state.sessionId // string | null — current session ID state.isSubAgent // boolean — true inside sub-agent contexts state.manualMode // false | "active" | "compress-pending" state.compressPermission // "ask" | "allow" | "deny" | undefined state.currentTurn // number — turn counter used by purgeErrors state.modelContextLimit // number | undefined — context window from model metadata state.stats // { pruneTokenCounter, totalPruneTokens } // Prune registries: state.prune.tools // Map — pruned tool call IDs state.prune.messages // PruneMessagesState — active compression blocks // Compression blocks (CompressionBlock shape): // { // blockId, runId, active, topic, startId, endId, // compressedTokens, summaryTokens, durationMs, // summary, directMessageIds, directToolIds, // includedBlockIds, consumedBlockIds, parentBlockIds // } ``` -------------------------------- ### Manage Editable DCP Prompts with PromptStore Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt The `PromptStore` class manages the six editable DCP prompts. It handles default prompt storage and user overrides, respecting a specific precedence order when custom prompts are enabled. ```typescript import { PromptStore } from "./lib/prompts/store" const prompts = new PromptStore(logger, "/project/root", /* customPromptsEnabled */ false) // Get current runtime prompts (returns a copy): const rp = prompts.getRuntimePrompts() // rp.system → DCP system instruction block // rp.compressRange → range-mode tool description // rp.compressMessage → message-mode tool description // rp.contextLimitNudge → injected when context > maxContextLimit // rp.turnNudge → injected at turn boundaries between min/max // rp.iterationNudge → injected after iterationNudgeThreshold iterations // rp.manualExtension → appended when manualMode is active // rp.subagentExtension → appended inside sub-agent sessions // Reload prompts from disk (re-reads override files): prompts.reload() // Override directory structure when customPrompts = true: // ~/.config/opencode/dcp-prompts/ // defaults/ ← written by DCP; reference only // system.md // compress-range.md // compress-message.md // context-limit-nudge.md // turn-nudge.md // iteration-nudge.md // README.md // overrides/ ← user-editable; copied from defaults // system.md ← edit to customize system instructions // // Project-level overrides (highest priority): // .opencode/dcp-prompts/overrides/system.md ``` -------------------------------- ### DCP Context Analysis Output Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt Displays a detailed breakdown of the current session's token usage by category. This output is generated by the `handleContextCommand`. ```text ╭─────────────────────────────────────────────────────────────╮ │ DCP Context Analysis │ ╰─────────────────────────────────────────────────────────────╯ Session Context Breakdown: ──────────────────────────────────────────────────────────── System 57.3% │████████████████████ │ 49.8 K User 2.1% │█ │ 1.8 K Assistant 8.4% │███ │ 7.3 K Tools (9) 32.2% │████████████ │ 28.0 K Summary: Pruned: 12 tools, 3 messages (~14.2 K) Current context: ~86.9 K Without DCP: ~101.1 K ``` -------------------------------- ### DCP Statistics Output Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt Shows compression statistics for the current session and all-time usage. This output is generated by the `handleStatsCommand`. ```text ╭─────────────────────────────────────────────────────────────╮ │ DCP Statistics │ ╰─────────────────────────────────────────────────────────────╯ Compression: ──────────────────────────────────────────────────────────── Tokens in|out: ~14.2 K | ~2.1 K Ratio: 7:1 Time: 4.3 s Messages: 3 Tools: 12 All-time: ──────────────────────────────────────────────────────────── Tokens saved: ~1.2 M Tools pruned: 8,300 Messages pruned: 420 Sessions: 37 ``` -------------------------------- ### Configure Deduplication and Error Purging Strategies Source: https://github.com/opencode-dcp/opencode-dynamic-context-pruning/blob/master/README.md Enable and configure automatic pruning strategies like deduplication and error purging. Specify protected tools to prevent them from being pruned. ```json { "strategies": { "deduplication": { "enabled": true, "protectedTools": [] }, "purgeErrors": { "enabled": true, "turns": 4, "protectedTools": [] } } } ``` -------------------------------- ### State Persistence Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt Utilities for saving and loading session state, enabling persistence across restarts and cross-session statistics. ```APIDOC ## State Persistence ### Description Reads and writes per-session JSON files under `~/.local/share/opencode/storage/plugin/dcp/`. This enables prune state to survive OpenCode restarts and supports cross-session statistics. ### Functions #### saveSessionState ##### Description Saves the current session state to disk. ##### Usage ```typescript await saveSessionState(state, logger) ``` ##### File Location `~/.local/share/opencode/storage/plugin/dcp/{sessionId}.json` ##### File Format ```json { "prune": { "tools": { "call_abc": 1200, "call_def": 400 }, "messages": { "byMessageId": {...}, "blocksById": {...}, ... } }, "nudges": { "contextLimitAnchors": [...], ... }, "stats": { "pruneTokenCounter": 0, "totalPruneTokens": 14200 }, "lastUpdated": "2025-07-14T10:30:00.000Z" } ``` #### loadSessionState ##### Description Loads a session's persisted state. Returns `null` if not found or invalid. ##### Usage ```typescript await loadSessionState(sessionId: string, logger) ``` ##### Example Usage ```typescript const persisted = await loadSessionState("session-id-abc123", logger) if (persisted) { // Merge into live state: state.prune.tools = loadPruneMap(persisted.prune.tools) state.stats = persisted.stats } ``` #### loadAllSessionStats ##### Description Aggregates statistics across ALL stored sessions. ##### Usage ```typescript await loadAllSessionStats(logger) ``` ##### Returns An object containing aggregated statistics: ```json { "totalTokens": 1_200_000, "totalTools": 8_300, "totalMessages": 420, "sessionCount": 37 } ``` ``` -------------------------------- ### Create Session State Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt Creates a blank in-memory state object, typically called once at plugin startup. ```typescript import { createSessionState, ensureSessionInitialized } from "./lib/state" // Create a blank state (called once at plugin startup): const state = createSessionState() ``` -------------------------------- ### Compression Tool - Message Mode Invocation Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt Illustrates the invocation of the `compress` tool in message mode. This mode allows for summarizing individual messages by providing their `messageId` and a summary. ```typescript // Message-mode invocation: // compress({ // topic: "Closed Research Notes", // content: [ // { // messageId: "m0008", // topic: "Webpack Config Research", // summary: "Investigated webpack tree-shaking. sideEffects:false in package.json resolves issue." // } // ] // }) ``` -------------------------------- ### Default DCP Configuration Source: https://github.com/opencode-dcp/opencode-dynamic-context-pruning/blob/master/README.md This is the default JSONC configuration for DCP. Adjust settings like 'enabled', 'debug', 'pruneNotification', and context limits to match your environment and preferences. Note the 'modelMaxLimits' and 'modelMinLimits' for per-model overrides. ```jsonc { "$schema": "https://raw.githubusercontent.com/Opencode-DCP/opencode-dynamic-context-pruning/master/dcp.schema.json", // Enable or disable the plugin "enabled": true, // Enable debug logging to ~/.config/opencode/logs/dcp/ "debug": false, // Notification display: "off", "minimal", or "detailed" "pruneNotification": "detailed", // Notification type: "chat" (in-conversation) or "toast" (system toast) "pruneNotificationType": "chat", // Slash commands configuration "commands": { "enabled": true, // Additional tools to protect from pruning via commands (e.g. /dcp sweep) "protectedTools": [], }, // Manual mode: disables autonomous context management, // tools only run when explicitly triggered via /dcp commands "manualMode": { "enabled": false, // When true, automatic cleanup (deduplication, purgeErrors) // still runs even in manual mode "automaticStrategies": true, }, // Protect from pruning for message turns past tool invocation "turnProtection": { "enabled": false, "turns": 4, }, // Experimental settings "experimental": { // Allow DCP processing in subagent sessions "allowSubAgents": false, // Enable user-editable prompt overrides under dcp-prompts directories // When false (default), prompt override files/directories are ignored "customPrompts": false, }, // Protect file operations from pruning via glob patterns // Patterns match tool parameters.filePath (e.g. read/write/edit) "protectedFilePatterns": [], // Unified context compression tool and behavior settings "compress": { // Compression mode: "range" (compress spans into block summaries) // or experimental "message" (compress individual raw messages) "mode": "range", // Permission mode: "allow" (no prompt), "ask" (prompt), "deny" (tool not registered) "permission": "allow", // Show compression content in a chat notification "showCompression": false, // Let active summary tokens extend the effective maxContextLimit "summaryBuffer": true, // Soft upper threshold: above this, DCP keeps injecting strong // compression nudges (based on nudgeFrequency), so compression is // much more likely. Accepts: number or "X%" of model context window. "maxContextLimit": 100000, // Soft lower threshold for reminder nudges: below this, turn/iteration // reminders are off (compression less likely). At/above this, reminders // are on. Accepts: number or "X%" of model context window. "minContextLimit": 50000, // Optional per-model override for maxContextLimit by providerID/modelID. // If present, this wins over the global maxContextLimit. // Accepts: number or "X%". // Example: // "modelMaxLimits": { // "openai/gpt-5.3-codex": 120000, // "anthropic/claude-sonnet-4.6": "80%" // }, // Optional per-model override for minContextLimit. // If present, this wins over the global minContextLimit. // "modelMinLimits": { // "openai/gpt-5.3-codex": 50000, // "anthropic/claude-sonnet-4.6": "25%" // }, // How often the context-limit nudge fires (1 = every fetch, 5 = every 5th) "nudgeFrequency": 5, // Start adding compression reminders after this many // messages have happened since the last user message "iterationNudgeThreshold": 15, // Controls how likely compression is after user messages // ("strong" = more likely, "soft" = less likely) "nudgeForce": "soft", // Tool names whose completed outputs are appended to the compression "protectedTools": [], // Preserve your messages during compression. // Warning: large copy-pasted prompts will never be compressed away "protectUserMessages": false, } } ``` -------------------------------- ### Create Text Complete Handler Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt Sanitizes model output by stripping any hallucinated DCP XML tags from assistant text output. ```typescript // Text complete handler — sanitizes model output: const textHandler = createTextCompleteHandler() // Strips any hallucinated DCP XML tags from assistant text output. ``` -------------------------------- ### Check Protected Tool Names and File Paths with Glob Matching Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt Use these functions to determine if a tool name or file path is exempt from pruning based on provided glob patterns. Ensure the correct patterns are supplied for accurate matching. ```typescript import { isToolNameProtected, isFilePathProtected, matchesGlob } from "./lib/protected-patterns" // Tool name protection (exact match + glob): isToolNameProtected("Bash", ["Bash", "Write", "Edit"]) // → true isToolNameProtected("ReadFile", ["Read*"]) // → true isToolNameProtected("Bash", ["task", "skill"]) // → false // File path protection (any filePath in parameters matches any pattern): isFilePathProtected( ["/home/user/project/src/core/auth.ts"], ["src/core/**/*.ts", "**/.env"] ) // → true isFilePathProtected( ["/home/user/project/tests/auth.test.ts"], ["src/core/**/*.ts"] ) // → false // Raw glob matching: matchesGlob("src/core/auth.ts", "src/**/*.ts") // → true matchesGlob("src/core/auth.ts", "src/core/*") // → true matchesGlob("src/deep/nested/file.ts", "src/core/*") // → false ``` ```typescript // getFilePathsFromParameters extracts paths from tool params: import { getFilePathsFromParameters } from "./lib/protected-patterns" getFilePathsFromParameters("read", { filePath: "/foo/bar.ts" }) // → ["/foo/bar.ts"] getFilePathsFromParameters("multiedit", { filePath: "/a.ts", edits: [{ filePath: "/b.ts" }] }) // → ["/a.ts", "/b.ts"] ``` -------------------------------- ### Persist and Load Session State for Pruning Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt Utilize these functions to save and load the state of pruning operations for individual sessions. This allows prune state to persist across OpenCode restarts and enables cross-session statistics. ```typescript import { saveSessionState, loadSessionState, loadAllSessionStats } from "./lib/state/persistence" // Save current session state to disk: await saveSessionState(state, logger) // Writes: ~/.local/share/opencode/storage/plugin/dcp/{sessionId}.json // File format: // { // "prune": { // "tools": { "call_abc": 1200, "call_def": 400 }, // "messages": { "byMessageId": {...}, "blocksById": {...}, ... } // }, // "nudges": { "contextLimitAnchors": [...], ... }, // "stats": { "pruneTokenCounter": 0, "totalPruneTokens": 14200 }, // "lastUpdated": "2025-07-14T10:30:00.000Z" // } // Load a session's persisted state (returns null if not found or invalid): const persisted = await loadSessionState("session-id-abc123", logger) if (persisted) { // Merge into live state: state.prune.tools = loadPruneMap(persisted.prune.tools) state.stats = persisted.stats } // Aggregate stats across ALL stored sessions: const allTime = await loadAllSessionStats(logger) // allTime: { totalTokens: 1_200_000, totalTools: 8_300, totalMessages: 420, sessionCount: 37 } ``` -------------------------------- ### Protected Patterns Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt Utilities to determine if a tool name or file path is protected from pruning using glob-based matching. ```APIDOC ## isToolNameProtected ### Description Checks if a given tool name is present in a list of protected tool names or matches any of the provided glob patterns. ### Usage ```typescript isToolNameProtected(toolName: string, protectedPatterns: string[]) ``` ### Examples ```typescript isToolNameProtected("Bash", ["Bash", "Write", "Edit"]) // → true isToolNameProtected("ReadFile", ["Read*"]) // → true isToolNameProtected("Bash", ["task", "skill"]) // → false ``` ## isFilePathProtected ### Description Determines if any of the provided file paths match any of the given glob patterns, indicating protection from pruning. ### Usage ```typescript isFilePathProtected(filePaths: string[], protectedPatterns: string[]) ``` ### Examples ```typescript isFilePathProtected( ["/home/user/project/src/core/auth.ts"], ["src/core/**/*.ts", "**/.env"] ) // → true isFilePathProtected( ["/home/user/project/tests/auth.test.ts"], ["src/core/**/*.ts"] ) // → false ``` ## matchesGlob ### Description Performs raw glob matching against a single file path. ### Usage ```typescript matchesGlob(filePath: string, globPattern: string) ``` ### Examples ```typescript matchesGlob("src/core/auth.ts", "src/**/*.ts") // → true matchesGlob("src/core/auth.ts", "src/core/*") // → true matchesGlob("src/deep/nested/file.ts", "src/core/*") // → false ``` ## getFilePathsFromParameters ### Description Extracts file paths from tool parameters, handling single `filePath` and multiple `edits` with `filePath`. ### Usage ```typescript getFilePathsFromParameters(toolName: string, parameters: any) ``` ### Examples ```typescript getFilePathsFromParameters("read", { filePath: "/foo/bar.ts" }) // → ["/foo/bar.ts"] getFilePathsFromParameters("multiedit", { filePath: "/a.ts", edits: [{ filePath: "/b.ts" }] }) // → ["/a.ts", "/b.ts"] ``` ``` -------------------------------- ### Deduplicate Tool Calls Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt Prunes older identical tool calls, keeping only the most recent. Configuration in dcp.jsonc can protect specific tools or file patterns from deduplication. ```typescript import { deduplicate } from "./lib/strategies/deduplication" // Runs automatically; also called inside compress pipeline. // Configuration drives behavior — no manual call needed in normal usage. // Example: if "Bash" was called 5 times with identical args, 4 older ones are pruned. // state.prune.tools is updated in-place: Map // state.stats.totalPruneTokens accumulates saved tokens. // Signature signature used internally: function createToolSignature(tool: string, parameters: any): string { // Normalizes (strips nulls/undefined) and sorts keys deterministically // Returns "toolName::{"arg1":"val1","arg2":"val2"}" } // To protect a tool from deduplication: // dcp.jsonc: { "strategies": { "deduplication": { "protectedTools": ["MyTool"] } } } // To protect files from deduplication: // dcp.jsonc: { "protectedFilePatterns": ["src/critical/**/*.ts"] } ``` -------------------------------- ### Create Message Transform Handler Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt The main pruning pipeline for chat messages. It processes messages through a series of steps including filtering, session checking, hallucination stripping, and pruning. ```typescript // Message transform handler — the main pruning pipeline: const msgHandler = createChatMessageTransformHandler(client, state, logger, config, prompts, hostPerms) // Called with: ({}, output: { messages: WithParts[] }) // Pipeline order: // 1. filterMessagesInPlace → discard unexpected shapes // 2. checkSession → detect session change / OpenCode compaction // 3. syncCompressPermissionState→ update compress permission from host config // 4. stripHallucinations → remove hallucinated tags from messages // 5. cacheSystemPromptTokens → record system token count // 6. assignMessageRefs → assign stable m0001/m0002 IDs to messages // 7. syncCompressionBlocks → reconcile block state with live messages // 8. syncToolCache → update toolParameters map from parts // 9. buildToolIdList → ordered list of all tool callIDs // 10. prune → apply all pruning (compression + tool pruning) // 11. injectExtendedSubAgentResults → attach sub-agent outputs if allowSubAgents // 12. buildPriorityMap → message priority for message-mode compress nudges // 13. injectCompressNudges → inject context-limit / turn / iteration nudges // 14. injectMessageIds → inject metadata into messages // 15. applyPendingManualTrigger → swap /dcp compress prompt into latest user message // 16. stripStaleMetadata → remove outdated DCP metadata tags // 17. logger.saveContext → write debug snapshot if debug=true ``` -------------------------------- ### Message Prune Pipeline Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt The central pruning function applied before LLM fetches. It handles compression summary injection, pruned tool output replacement, cleared errored tool inputs, and cleared 'question' tool inputs. ```typescript import { prune } from "./lib/messages/prune" // Called automatically inside createChatMessageTransformHandler. // Step 1 — filterCompressedRanges: // For each message in state.prune.messages.activeByAnchorMessageId, // replaces the compressed span with a synthetic user message carrying // the stored summary. Skips the original messages that were compressed. // Step 2 — pruneToolOutputs: // For every callID in state.prune.tools where status === "completed": // part.state.output = "[Output removed to save context...]" // (Skips: "question", "edit", "write" tools) // Step 3 — pruneToolInputs: // For completed "question" tools in prune list: // part.state.input.questions = "[questions removed - see output for user's answers]" // Step 4 — pruneToolErrors: // For errored tools in prune list, replaces all string input values with: // "[input removed due to failed tool call]" ``` -------------------------------- ### Purge Errors Strategy Source: https://context7.com/opencode-dcp/opencode-dynamic-context-pruning/llms.txt Removes input payloads from errored tool calls older than a specified number of turns. The error message is preserved, but input fields are replaced with a placeholder. ```typescript import { purgeErrors } from "./lib/strategies/purge-errors" // Automatically called on every message transform and in compress pipeline. // Behavior: // - Iterates unpruned tool IDs whose status === "error" // - If (currentTurn - metadata.turn) >= turnThreshold → mark for pruning // - Replaces all string fields in part.state.input with: // "[input removed due to failed tool call]" // - Preserves part.state.error text // Example: turnThreshold = 4 // Turn 5: tool "Write" errors // Turn 9: "Write" input is eligible for purging (9 - 5 = 4 >= 4) // Configuration: // { "strategies": { "purgeErrors": { "enabled": true, "turns": 4 } } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.