From 7971886f4a92b5f792b14ea901e37ee08acbfbf5 Mon Sep 17 00:00:00 2001 From: Spoon <212802214+spoons-and-mirrors@users.noreply.github.com> Date: Thu, 5 Feb 2026 01:10:40 +0100 Subject: [PATCH 1/2] Replace compress enabled with permission enum (ask/allow/deny) --- README.md | 3 ++- dcp.schema.json | 9 +++++---- index.ts | 18 ++++++++---------- lib/config.ts | 26 +++++++++++++------------- lib/hooks.ts | 2 +- lib/messages/inject.ts | 6 +++--- 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 9ca3ba58..90609410 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,8 @@ DCP uses its own config file: > }, > // Collapses a range of conversation content into a single summary > "compress": { -> "enabled": true, +> // Permission mode: "ask" (prompt), "allow" (no prompt), "deny" (tool not registered) +> "permission": "ask", > // Show summary content as an ignored message notification > "showCompression": false, > }, diff --git a/dcp.schema.json b/dcp.schema.json index 32a1398f..fcfe2e68 100644 --- a/dcp.schema.json +++ b/dcp.schema.json @@ -146,10 +146,11 @@ "description": "Configuration for the compress tool", "additionalProperties": false, "properties": { - "enabled": { - "type": "boolean", - "default": true, - "description": "Enable the compress tool" + "permission": { + "type": "string", + "enum": ["ask", "allow", "deny"], + "default": "ask", + "description": "Permission mode (deny disables the tool)" }, "showCompression": { "type": "boolean", diff --git a/index.ts b/index.ts index 8aafd5c5..def671bd 100644 --- a/index.ts +++ b/index.ts @@ -70,7 +70,7 @@ const plugin: Plugin = (async (ctx) => { workingDirectory: ctx.directory, }), }), - ...(config.tools.compress.enabled && { + ...(config.tools.compress.permission !== "deny" && { compress: createCompressTool({ client: ctx.client, state, @@ -100,7 +100,7 @@ const plugin: Plugin = (async (ctx) => { const toolsToAdd: string[] = [] if (config.tools.distill.enabled) toolsToAdd.push("distill") - if (config.tools.compress.enabled) toolsToAdd.push("compress") + if (config.tools.compress.permission !== "deny") toolsToAdd.push("compress") if (config.tools.prune.enabled) toolsToAdd.push("prune") if (toolsToAdd.length > 0) { @@ -113,15 +113,13 @@ const plugin: Plugin = (async (ctx) => { `Added ${toolsToAdd.map((t) => `'${t}'`).join(" and ")} to experimental.primary_tools via config mutation`, ) - // Set compress permission to ask (only if not already configured) - if (config.tools.compress.enabled) { + // Set compress permission from DCP config + if (config.tools.compress.permission !== "deny") { const permission = opencodeConfig.permission ?? {} - if (!("compress" in permission)) { - opencodeConfig.permission = { - ...permission, - compress: "ask", - } as typeof permission - } + opencodeConfig.permission = { + ...permission, + compress: config.tools.compress.permission, + } as typeof permission } } }, diff --git a/lib/config.ts b/lib/config.ts index f786eb7b..1e772293 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -19,7 +19,7 @@ export interface DistillTool { } export interface CompressTool { - enabled: boolean + permission: "ask" | "allow" | "deny" showCompression: boolean } @@ -111,7 +111,7 @@ export const VALID_CONFIG_KEYS = new Set([ "tools.distill.enabled", "tools.distill.showDistillation", "tools.compress", - "tools.compress.enabled", + "tools.compress.permission", "tools.compress.showCompression", "tools.prune", "tools.prune.enabled", @@ -322,15 +322,15 @@ function validateConfigTypes(config: Record): ValidationError[] { } } if (tools.compress) { - if ( - tools.compress.enabled !== undefined && - typeof tools.compress.enabled !== "boolean" - ) { - errors.push({ - key: "tools.compress.enabled", - expected: "boolean", - actual: typeof tools.compress.enabled, - }) + if (tools.compress.permission !== undefined) { + const validValues = ["ask", "allow", "deny"] + if (!validValues.includes(tools.compress.permission)) { + errors.push({ + key: "tools.compress.permission", + expected: '"ask" | "allow" | "deny"', + actual: JSON.stringify(tools.compress.permission), + }) + } } if ( tools.compress.showCompression !== undefined && @@ -503,7 +503,7 @@ const defaultConfig: PluginConfig = { showDistillation: false, }, compress: { - enabled: true, + permission: "ask", showCompression: false, }, prune: { @@ -680,7 +680,7 @@ function mergeTools( showDistillation: override.distill?.showDistillation ?? base.distill.showDistillation, }, compress: { - enabled: override.compress?.enabled ?? base.compress.enabled, + permission: override.compress?.permission ?? base.compress.permission, showCompression: override.compress?.showCompression ?? base.compress.showCompression, }, prune: { diff --git a/lib/hooks.ts b/lib/hooks.ts index 508b98f0..6e113705 100644 --- a/lib/hooks.ts +++ b/lib/hooks.ts @@ -45,7 +45,7 @@ export function createSystemPromptHandler( const flags = { prune: config.tools.prune.enabled, distill: config.tools.distill.enabled, - compress: config.tools.compress.enabled, + compress: config.tools.compress.permission !== "deny", } if (!flags.prune && !flags.distill && !flags.compress) { diff --git a/lib/messages/inject.ts b/lib/messages/inject.ts index daa00e72..b327b675 100644 --- a/lib/messages/inject.ts +++ b/lib/messages/inject.ts @@ -59,7 +59,7 @@ const getNudgeString = (config: PluginConfig): string => { const flags = { prune: config.tools.prune.enabled, distill: config.tools.distill.enabled, - compress: config.tools.compress.enabled, + compress: config.tools.compress.permission !== "deny", } if (!flags.prune && !flags.distill && !flags.compress) { @@ -73,7 +73,7 @@ const getCooldownMessage = (config: PluginConfig): string => { return wrapCooldownMessage({ prune: config.tools.prune.enabled, distill: config.tools.distill.enabled, - compress: config.tools.compress.enabled, + compress: config.tools.compress.permission !== "deny", }) } @@ -159,7 +159,7 @@ export const insertPruneToolContext = ( ): void => { const pruneEnabled = config.tools.prune.enabled const distillEnabled = config.tools.distill.enabled - const compressEnabled = config.tools.compress.enabled + const compressEnabled = config.tools.compress.permission !== "deny" if (!pruneEnabled && !distillEnabled && !compressEnabled) { return From 59d2f98565f00786aaa4fd4035820f2b9abd1bb2 Mon Sep 17 00:00:00 2001 From: Spoon <212802214+spoons-and-mirrors@users.noreply.github.com> Date: Thu, 5 Feb 2026 02:44:26 +0100 Subject: [PATCH 2/2] distill and prune --- README.md | 6 ++++-- dcp.schema.json | 18 +++++++++-------- index.ts | 26 ++++++++++++------------ lib/config.ts | 46 ++++++++++++++++++++++++------------------ lib/hooks.ts | 4 ++-- lib/messages/inject.ts | 12 +++++------ 6 files changed, 61 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index 90609410..63754b61 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,8 @@ DCP uses its own config file: > }, > // Distills key findings into preserved knowledge before removing raw content > "distill": { -> "enabled": true, +> // Permission mode: "allow" (no prompt), "ask" (prompt), "deny" (tool not registered) +> "permission": "allow", > // Show distillation content as an ignored message notification > "showDistillation": false, > }, @@ -124,7 +125,8 @@ DCP uses its own config file: > }, > // Removes tool content from context without preservation (for completed tasks or noise) > "prune": { -> "enabled": true, +> // Permission mode: "allow" (no prompt), "ask" (prompt), "deny" (tool not registered) +> "permission": "allow", > }, > }, > // Automatic pruning strategies diff --git a/dcp.schema.json b/dcp.schema.json index fcfe2e68..82c85733 100644 --- a/dcp.schema.json +++ b/dcp.schema.json @@ -129,10 +129,11 @@ "description": "Configuration for the distill tool", "additionalProperties": false, "properties": { - "enabled": { - "type": "boolean", - "default": true, - "description": "Enable the distill tool" + "permission": { + "type": "string", + "enum": ["ask", "allow", "deny"], + "default": "allow", + "description": "Permission mode (deny disables the tool)" }, "showDistillation": { "type": "boolean", @@ -164,10 +165,11 @@ "description": "Configuration for the prune tool", "additionalProperties": false, "properties": { - "enabled": { - "type": "boolean", - "default": true, - "description": "Enable the prune tool" + "permission": { + "type": "string", + "enum": ["ask", "allow", "deny"], + "default": "allow", + "description": "Permission mode (deny disables the tool)" } } } diff --git a/index.ts b/index.ts index def671bd..60c1b3ec 100644 --- a/index.ts +++ b/index.ts @@ -61,7 +61,7 @@ const plugin: Plugin = (async (ctx) => { ctx.directory, ), tool: { - ...(config.tools.distill.enabled && { + ...(config.tools.distill.permission !== "deny" && { distill: createDistillTool({ client: ctx.client, state, @@ -79,7 +79,7 @@ const plugin: Plugin = (async (ctx) => { workingDirectory: ctx.directory, }), }), - ...(config.tools.prune.enabled && { + ...(config.tools.prune.permission !== "deny" && { prune: createPruneTool({ client: ctx.client, state, @@ -99,9 +99,9 @@ const plugin: Plugin = (async (ctx) => { } const toolsToAdd: string[] = [] - if (config.tools.distill.enabled) toolsToAdd.push("distill") + if (config.tools.distill.permission !== "deny") toolsToAdd.push("distill") if (config.tools.compress.permission !== "deny") toolsToAdd.push("compress") - if (config.tools.prune.enabled) toolsToAdd.push("prune") + if (config.tools.prune.permission !== "deny") toolsToAdd.push("prune") if (toolsToAdd.length > 0) { const existingPrimaryTools = opencodeConfig.experimental?.primary_tools ?? [] @@ -112,16 +112,16 @@ const plugin: Plugin = (async (ctx) => { logger.info( `Added ${toolsToAdd.map((t) => `'${t}'`).join(" and ")} to experimental.primary_tools via config mutation`, ) - - // Set compress permission from DCP config - if (config.tools.compress.permission !== "deny") { - const permission = opencodeConfig.permission ?? {} - opencodeConfig.permission = { - ...permission, - compress: config.tools.compress.permission, - } as typeof permission - } } + + // Set tool permissions from DCP config + 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 }, } }) satisfies Plugin diff --git a/lib/config.ts b/lib/config.ts index 1e772293..89bacd6e 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -10,11 +10,11 @@ export interface Deduplication { } export interface PruneTool { - enabled: boolean + permission: "ask" | "allow" | "deny" } export interface DistillTool { - enabled: boolean + permission: "ask" | "allow" | "deny" showDistillation: boolean } @@ -108,13 +108,13 @@ export const VALID_CONFIG_KEYS = new Set([ "tools.settings.protectedTools", "tools.settings.contextLimit", "tools.distill", - "tools.distill.enabled", + "tools.distill.permission", "tools.distill.showDistillation", "tools.compress", "tools.compress.permission", "tools.compress.showCompression", "tools.prune", - "tools.prune.enabled", + "tools.prune.permission", "strategies", // strategies.deduplication "strategies.deduplication", @@ -303,12 +303,15 @@ function validateConfigTypes(config: Record): ValidationError[] { } } if (tools.distill) { - if (tools.distill.enabled !== undefined && typeof tools.distill.enabled !== "boolean") { - errors.push({ - key: "tools.distill.enabled", - expected: "boolean", - actual: typeof tools.distill.enabled, - }) + if (tools.distill.permission !== undefined) { + const validValues = ["ask", "allow", "deny"] + if (!validValues.includes(tools.distill.permission)) { + errors.push({ + key: "tools.distill.permission", + expected: '"ask" | "allow" | "deny"', + actual: JSON.stringify(tools.distill.permission), + }) + } } if ( tools.distill.showDistillation !== undefined && @@ -344,12 +347,15 @@ function validateConfigTypes(config: Record): ValidationError[] { } } if (tools.prune) { - if (tools.prune.enabled !== undefined && typeof tools.prune.enabled !== "boolean") { - errors.push({ - key: "tools.prune.enabled", - expected: "boolean", - actual: typeof tools.prune.enabled, - }) + if (tools.prune.permission !== undefined) { + const validValues = ["ask", "allow", "deny"] + if (!validValues.includes(tools.prune.permission)) { + errors.push({ + key: "tools.prune.permission", + expected: '"ask" | "allow" | "deny"', + actual: JSON.stringify(tools.prune.permission), + }) + } } } } @@ -499,7 +505,7 @@ const defaultConfig: PluginConfig = { contextLimit: 100000, }, distill: { - enabled: true, + permission: "allow", showDistillation: false, }, compress: { @@ -507,7 +513,7 @@ const defaultConfig: PluginConfig = { showCompression: false, }, prune: { - enabled: true, + permission: "allow", }, }, strategies: { @@ -676,7 +682,7 @@ function mergeTools( contextLimit: override.settings?.contextLimit ?? base.settings.contextLimit, }, distill: { - enabled: override.distill?.enabled ?? base.distill.enabled, + permission: override.distill?.permission ?? base.distill.permission, showDistillation: override.distill?.showDistillation ?? base.distill.showDistillation, }, compress: { @@ -684,7 +690,7 @@ function mergeTools( showCompression: override.compress?.showCompression ?? base.compress.showCompression, }, prune: { - enabled: override.prune?.enabled ?? base.prune.enabled, + permission: override.prune?.permission ?? base.prune.permission, }, } } diff --git a/lib/hooks.ts b/lib/hooks.ts index 6e113705..b3ecf7ff 100644 --- a/lib/hooks.ts +++ b/lib/hooks.ts @@ -43,8 +43,8 @@ export function createSystemPromptHandler( } const flags = { - prune: config.tools.prune.enabled, - distill: config.tools.distill.enabled, + prune: config.tools.prune.permission !== "deny", + distill: config.tools.distill.permission !== "deny", compress: config.tools.compress.permission !== "deny", } diff --git a/lib/messages/inject.ts b/lib/messages/inject.ts index b327b675..28d9854c 100644 --- a/lib/messages/inject.ts +++ b/lib/messages/inject.ts @@ -57,8 +57,8 @@ Context management was just performed. Do NOT use the ${toolName} again. A fresh const getNudgeString = (config: PluginConfig): string => { const flags = { - prune: config.tools.prune.enabled, - distill: config.tools.distill.enabled, + prune: config.tools.prune.permission !== "deny", + distill: config.tools.distill.permission !== "deny", compress: config.tools.compress.permission !== "deny", } @@ -71,8 +71,8 @@ const getNudgeString = (config: PluginConfig): string => { const getCooldownMessage = (config: PluginConfig): string => { return wrapCooldownMessage({ - prune: config.tools.prune.enabled, - distill: config.tools.distill.enabled, + prune: config.tools.prune.permission !== "deny", + distill: config.tools.distill.permission !== "deny", compress: config.tools.compress.permission !== "deny", }) } @@ -157,8 +157,8 @@ export const insertPruneToolContext = ( logger: Logger, messages: WithParts[], ): void => { - const pruneEnabled = config.tools.prune.enabled - const distillEnabled = config.tools.distill.enabled + const pruneEnabled = config.tools.prune.permission !== "deny" + const distillEnabled = config.tools.distill.permission !== "deny" const compressEnabled = config.tools.compress.permission !== "deny" if (!pruneEnabled && !distillEnabled && !compressEnabled) {