Skip to content

Commit 47b1703

Browse files
authored
Merge pull request #351 from Opencode-DCP/permissions
Mirroring opencode permissions mechanic for dcp config
2 parents f968fb9 + c9b41c2 commit 47b1703

File tree

6 files changed

+87
-77
lines changed

6 files changed

+87
-77
lines changed

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,19 +111,22 @@ DCP uses its own config file:
111111
> },
112112
> // Distills key findings into preserved knowledge before removing raw content
113113
> "distill": {
114-
> "enabled": true,
114+
> // Permission mode: "allow" (no prompt), "ask" (prompt), "deny" (tool not registered)
115+
> "permission": "allow",
115116
> // Show distillation content as an ignored message notification
116117
> "showDistillation": false,
117118
> },
118119
> // Collapses a range of conversation content into a single summary
119120
> "compress": {
120-
> "enabled": true,
121+
> // Permission mode: "ask" (prompt), "allow" (no prompt), "deny" (tool not registered)
122+
> "permission": "ask",
121123
> // Show summary content as an ignored message notification
122124
> "showCompression": false,
123125
> },
124126
> // Removes tool content from context without preservation (for completed tasks or noise)
125127
> "prune": {
126-
> "enabled": true,
128+
> // Permission mode: "allow" (no prompt), "ask" (prompt), "deny" (tool not registered)
129+
> "permission": "allow",
127130
> },
128131
> },
129132
> // Automatic pruning strategies

dcp.schema.json

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,11 @@
129129
"description": "Configuration for the distill tool",
130130
"additionalProperties": false,
131131
"properties": {
132-
"enabled": {
133-
"type": "boolean",
134-
"default": true,
135-
"description": "Enable the distill tool"
132+
"permission": {
133+
"type": "string",
134+
"enum": ["ask", "allow", "deny"],
135+
"default": "allow",
136+
"description": "Permission mode (deny disables the tool)"
136137
},
137138
"showDistillation": {
138139
"type": "boolean",
@@ -146,10 +147,11 @@
146147
"description": "Configuration for the compress tool",
147148
"additionalProperties": false,
148149
"properties": {
149-
"enabled": {
150-
"type": "boolean",
151-
"default": true,
152-
"description": "Enable the compress tool"
150+
"permission": {
151+
"type": "string",
152+
"enum": ["ask", "allow", "deny"],
153+
"default": "ask",
154+
"description": "Permission mode (deny disables the tool)"
153155
},
154156
"showCompression": {
155157
"type": "boolean",
@@ -163,10 +165,11 @@
163165
"description": "Configuration for the prune tool",
164166
"additionalProperties": false,
165167
"properties": {
166-
"enabled": {
167-
"type": "boolean",
168-
"default": true,
169-
"description": "Enable the prune tool"
168+
"permission": {
169+
"type": "string",
170+
"enum": ["ask", "allow", "deny"],
171+
"default": "allow",
172+
"description": "Permission mode (deny disables the tool)"
170173
}
171174
}
172175
}

index.ts

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const plugin: Plugin = (async (ctx) => {
6161
ctx.directory,
6262
),
6363
tool: {
64-
...(config.tools.distill.enabled && {
64+
...(config.tools.distill.permission !== "deny" && {
6565
distill: createDistillTool({
6666
client: ctx.client,
6767
state,
@@ -70,7 +70,7 @@ const plugin: Plugin = (async (ctx) => {
7070
workingDirectory: ctx.directory,
7171
}),
7272
}),
73-
...(config.tools.compress.enabled && {
73+
...(config.tools.compress.permission !== "deny" && {
7474
compress: createCompressTool({
7575
client: ctx.client,
7676
state,
@@ -79,7 +79,7 @@ const plugin: Plugin = (async (ctx) => {
7979
workingDirectory: ctx.directory,
8080
}),
8181
}),
82-
...(config.tools.prune.enabled && {
82+
...(config.tools.prune.permission !== "deny" && {
8383
prune: createPruneTool({
8484
client: ctx.client,
8585
state,
@@ -99,9 +99,9 @@ const plugin: Plugin = (async (ctx) => {
9999
}
100100

101101
const toolsToAdd: string[] = []
102-
if (config.tools.distill.enabled) toolsToAdd.push("distill")
103-
if (config.tools.compress.enabled) toolsToAdd.push("compress")
104-
if (config.tools.prune.enabled) toolsToAdd.push("prune")
102+
if (config.tools.distill.permission !== "deny") toolsToAdd.push("distill")
103+
if (config.tools.compress.permission !== "deny") toolsToAdd.push("compress")
104+
if (config.tools.prune.permission !== "deny") toolsToAdd.push("prune")
105105

106106
if (toolsToAdd.length > 0) {
107107
const existingPrimaryTools = opencodeConfig.experimental?.primary_tools ?? []
@@ -112,18 +112,16 @@ const plugin: Plugin = (async (ctx) => {
112112
logger.info(
113113
`Added ${toolsToAdd.map((t) => `'${t}'`).join(" and ")} to experimental.primary_tools via config mutation`,
114114
)
115-
116-
// Set compress permission to ask (only if not already configured)
117-
if (config.tools.compress.enabled) {
118-
const permission = opencodeConfig.permission ?? {}
119-
if (!("compress" in permission)) {
120-
opencodeConfig.permission = {
121-
...permission,
122-
compress: "ask",
123-
} as typeof permission
124-
}
125-
}
126115
}
116+
117+
// Set tool permissions from DCP config
118+
const permission = opencodeConfig.permission ?? {}
119+
opencodeConfig.permission = {
120+
...permission,
121+
distill: config.tools.distill.permission,
122+
compress: config.tools.compress.permission,
123+
prune: config.tools.prune.permission,
124+
} as typeof permission
127125
},
128126
}
129127
}) satisfies Plugin

lib/config.ts

Lines changed: 39 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@ export interface Deduplication {
1010
}
1111

1212
export interface PruneTool {
13-
enabled: boolean
13+
permission: "ask" | "allow" | "deny"
1414
}
1515

1616
export interface DistillTool {
17-
enabled: boolean
17+
permission: "ask" | "allow" | "deny"
1818
showDistillation: boolean
1919
}
2020

2121
export interface CompressTool {
22-
enabled: boolean
22+
permission: "ask" | "allow" | "deny"
2323
showCompression: boolean
2424
}
2525

@@ -108,13 +108,13 @@ export const VALID_CONFIG_KEYS = new Set([
108108
"tools.settings.protectedTools",
109109
"tools.settings.contextLimit",
110110
"tools.distill",
111-
"tools.distill.enabled",
111+
"tools.distill.permission",
112112
"tools.distill.showDistillation",
113113
"tools.compress",
114-
"tools.compress.enabled",
114+
"tools.compress.permission",
115115
"tools.compress.showCompression",
116116
"tools.prune",
117-
"tools.prune.enabled",
117+
"tools.prune.permission",
118118
"strategies",
119119
// strategies.deduplication
120120
"strategies.deduplication",
@@ -303,12 +303,15 @@ function validateConfigTypes(config: Record<string, any>): ValidationError[] {
303303
}
304304
}
305305
if (tools.distill) {
306-
if (tools.distill.enabled !== undefined && typeof tools.distill.enabled !== "boolean") {
307-
errors.push({
308-
key: "tools.distill.enabled",
309-
expected: "boolean",
310-
actual: typeof tools.distill.enabled,
311-
})
306+
if (tools.distill.permission !== undefined) {
307+
const validValues = ["ask", "allow", "deny"]
308+
if (!validValues.includes(tools.distill.permission)) {
309+
errors.push({
310+
key: "tools.distill.permission",
311+
expected: '"ask" | "allow" | "deny"',
312+
actual: JSON.stringify(tools.distill.permission),
313+
})
314+
}
312315
}
313316
if (
314317
tools.distill.showDistillation !== undefined &&
@@ -322,15 +325,15 @@ function validateConfigTypes(config: Record<string, any>): ValidationError[] {
322325
}
323326
}
324327
if (tools.compress) {
325-
if (
326-
tools.compress.enabled !== undefined &&
327-
typeof tools.compress.enabled !== "boolean"
328-
) {
329-
errors.push({
330-
key: "tools.compress.enabled",
331-
expected: "boolean",
332-
actual: typeof tools.compress.enabled,
333-
})
328+
if (tools.compress.permission !== undefined) {
329+
const validValues = ["ask", "allow", "deny"]
330+
if (!validValues.includes(tools.compress.permission)) {
331+
errors.push({
332+
key: "tools.compress.permission",
333+
expected: '"ask" | "allow" | "deny"',
334+
actual: JSON.stringify(tools.compress.permission),
335+
})
336+
}
334337
}
335338
if (
336339
tools.compress.showCompression !== undefined &&
@@ -344,12 +347,15 @@ function validateConfigTypes(config: Record<string, any>): ValidationError[] {
344347
}
345348
}
346349
if (tools.prune) {
347-
if (tools.prune.enabled !== undefined && typeof tools.prune.enabled !== "boolean") {
348-
errors.push({
349-
key: "tools.prune.enabled",
350-
expected: "boolean",
351-
actual: typeof tools.prune.enabled,
352-
})
350+
if (tools.prune.permission !== undefined) {
351+
const validValues = ["ask", "allow", "deny"]
352+
if (!validValues.includes(tools.prune.permission)) {
353+
errors.push({
354+
key: "tools.prune.permission",
355+
expected: '"ask" | "allow" | "deny"',
356+
actual: JSON.stringify(tools.prune.permission),
357+
})
358+
}
353359
}
354360
}
355361
}
@@ -499,15 +505,15 @@ const defaultConfig: PluginConfig = {
499505
contextLimit: 100000,
500506
},
501507
distill: {
502-
enabled: true,
508+
permission: "allow",
503509
showDistillation: false,
504510
},
505511
compress: {
506-
enabled: true,
512+
permission: "ask",
507513
showCompression: false,
508514
},
509515
prune: {
510-
enabled: true,
516+
permission: "allow",
511517
},
512518
},
513519
strategies: {
@@ -678,15 +684,15 @@ function mergeTools(
678684
contextLimit: override.settings?.contextLimit ?? base.settings.contextLimit,
679685
},
680686
distill: {
681-
enabled: override.distill?.enabled ?? base.distill.enabled,
687+
permission: override.distill?.permission ?? base.distill.permission,
682688
showDistillation: override.distill?.showDistillation ?? base.distill.showDistillation,
683689
},
684690
compress: {
685-
enabled: override.compress?.enabled ?? base.compress.enabled,
691+
permission: override.compress?.permission ?? base.compress.permission,
686692
showCompression: override.compress?.showCompression ?? base.compress.showCompression,
687693
},
688694
prune: {
689-
enabled: override.prune?.enabled ?? base.prune.enabled,
695+
permission: override.prune?.permission ?? base.prune.permission,
690696
},
691697
}
692698
}

lib/hooks.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ export function createSystemPromptHandler(
4343
}
4444

4545
const flags = {
46-
prune: config.tools.prune.enabled,
47-
distill: config.tools.distill.enabled,
48-
compress: config.tools.compress.enabled,
46+
prune: config.tools.prune.permission !== "deny",
47+
distill: config.tools.distill.permission !== "deny",
48+
compress: config.tools.compress.permission !== "deny",
4949
}
5050

5151
if (!flags.prune && !flags.distill && !flags.compress) {

lib/messages/inject.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ Context management was just performed. Do NOT use the ${toolName} again. A fresh
5757

5858
const getNudgeString = (config: PluginConfig): string => {
5959
const flags = {
60-
prune: config.tools.prune.enabled,
61-
distill: config.tools.distill.enabled,
62-
compress: config.tools.compress.enabled,
60+
prune: config.tools.prune.permission !== "deny",
61+
distill: config.tools.distill.permission !== "deny",
62+
compress: config.tools.compress.permission !== "deny",
6363
}
6464

6565
if (!flags.prune && !flags.distill && !flags.compress) {
@@ -71,9 +71,9 @@ const getNudgeString = (config: PluginConfig): string => {
7171

7272
const getCooldownMessage = (config: PluginConfig): string => {
7373
return wrapCooldownMessage({
74-
prune: config.tools.prune.enabled,
75-
distill: config.tools.distill.enabled,
76-
compress: config.tools.compress.enabled,
74+
prune: config.tools.prune.permission !== "deny",
75+
distill: config.tools.distill.permission !== "deny",
76+
compress: config.tools.compress.permission !== "deny",
7777
})
7878
}
7979

@@ -157,9 +157,9 @@ export const insertPruneToolContext = (
157157
logger: Logger,
158158
messages: WithParts[],
159159
): void => {
160-
const pruneEnabled = config.tools.prune.enabled
161-
const distillEnabled = config.tools.distill.enabled
162-
const compressEnabled = config.tools.compress.enabled
160+
const pruneEnabled = config.tools.prune.permission !== "deny"
161+
const distillEnabled = config.tools.distill.permission !== "deny"
162+
const compressEnabled = config.tools.compress.permission !== "deny"
163163

164164
if (!pruneEnabled && !distillEnabled && !compressEnabled) {
165165
return

0 commit comments

Comments
 (0)