summaryrefslogtreecommitdiffhomepage
path: root/packages
diff options
context:
space:
mode:
authorDax Raad <[email protected]>2026-04-25 09:48:09 -0400
committerDax Raad <[email protected]>2026-04-25 09:48:09 -0400
commit1b92c95425e5725b9908e13c92b98201e8debe8d (patch)
tree1432d730b62edbec7e6affc8d7219990c38e001f /packages
parentd748c718457f64f6eeef02f406ebca67f78864fa (diff)
downloadopencode-1b92c95425e5725b9908e13c92b98201e8debe8d.tar.gz
opencode-1b92c95425e5725b9908e13c92b98201e8debe8d.zip
core: permission config schema now provides full IntelliSense for all tool permission keys
The permission configuration previously used a generic record type that didn't offer editor completions. Updated the schema to explicitly list all tool permission keys (read, edit, glob, grep, list, bash, task, external_directory, lsp, skill, todowrite, question, webfetch, websearch, codesearch, doom_loop) with proper types, enabling autocomplete when editing permission files.
Diffstat (limited to 'packages')
-rw-r--r--packages/opencode/src/config/permission.ts35
-rw-r--r--packages/sdk/js/src/v2/gen/types.gen.ts34
-rw-r--r--packages/sdk/openapi.json96
3 files changed, 134 insertions, 31 deletions
diff --git a/packages/opencode/src/config/permission.ts b/packages/opencode/src/config/permission.ts
index 909112c7c..a7390e953 100644
--- a/packages/opencode/src/config/permission.ts
+++ b/packages/opencode/src/config/permission.ts
@@ -53,17 +53,34 @@ const InputSchema = Schema.Union([Action, InputObject])
const normalizeInput = (input: Schema.Schema.Type<typeof InputSchema>): Schema.Schema.Type<typeof InputObject> =>
typeof input === "string" ? { "*": input } : input
-const ACTION_ONLY = new Set(["todowrite", "question", "webfetch", "websearch", "codesearch", "doom_loop"])
-
const InfoZod = z
- .union([zod(Action), z.record(z.string(), z.union([zod(Action), z.record(z.string(), zod(Action))]))])
+ .union([
+ zod(Action),
+ z.intersection(
+ z.record(z.string(), zod(Rule)),
+ z
+ .object({
+ read: zod(Rule).optional(),
+ edit: zod(Rule).optional(),
+ glob: zod(Rule).optional(),
+ grep: zod(Rule).optional(),
+ list: zod(Rule).optional(),
+ bash: zod(Rule).optional(),
+ task: zod(Rule).optional(),
+ external_directory: zod(Rule).optional(),
+ todowrite: zod(Action).optional(),
+ question: zod(Action).optional(),
+ webfetch: zod(Action).optional(),
+ websearch: zod(Action).optional(),
+ codesearch: zod(Action).optional(),
+ lsp: zod(Rule).optional(),
+ doom_loop: zod(Action).optional(),
+ skill: zod(Rule).optional(),
+ })
+ .catchall(zod(Rule)),
+ ),
+ ])
.transform(normalizeInput)
- .superRefine((input, ctx) => {
- for (const [key, value] of globalThis.Object.entries(input)) {
- if (!ACTION_ONLY.has(key) || typeof value === "string") continue
- ctx.addIssue({ code: "custom", message: `${key} must be a permission action`, path: [key] })
- }
- })
export const Info = InputSchema.pipe(
Schema.decodeTo(InputObject, {
diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts
index 51a79d99d..0ad88bb50 100644
--- a/packages/sdk/js/src/v2/gen/types.gen.ts
+++ b/packages/sdk/js/src/v2/gen/types.gen.ts
@@ -1198,15 +1198,35 @@ export type ServerConfig = {
export type PermissionActionConfig = "ask" | "allow" | "deny"
+export type PermissionObjectConfig = {
+ [key: string]: PermissionActionConfig
+}
+
+export type PermissionRuleConfig = PermissionActionConfig | PermissionObjectConfig
+
export type PermissionConfig =
| PermissionActionConfig
- | {
- [key: string]:
- | PermissionActionConfig
- | {
- [key: string]: PermissionActionConfig
- }
- }
+ | ({
+ [key: string]: PermissionRuleConfig
+ } & {
+ read?: PermissionRuleConfig
+ edit?: PermissionRuleConfig
+ glob?: PermissionRuleConfig
+ grep?: PermissionRuleConfig
+ list?: PermissionRuleConfig
+ bash?: PermissionRuleConfig
+ task?: PermissionRuleConfig
+ external_directory?: PermissionRuleConfig
+ todowrite?: PermissionActionConfig
+ question?: PermissionActionConfig
+ webfetch?: PermissionActionConfig
+ websearch?: PermissionActionConfig
+ codesearch?: PermissionActionConfig
+ lsp?: PermissionRuleConfig
+ doom_loop?: PermissionActionConfig
+ skill?: PermissionRuleConfig
+ [key: string]: PermissionRuleConfig | PermissionActionConfig | undefined
+ })
export type AgentConfig = {
model?: string
diff --git a/packages/sdk/openapi.json b/packages/sdk/openapi.json
index cbb9aaecc..7be58195b 100644
--- a/packages/sdk/openapi.json
+++ b/packages/sdk/openapi.json
@@ -10926,32 +10926,98 @@
"type": "string",
"enum": ["ask", "allow", "deny"]
},
+ "PermissionObjectConfig": {
+ "type": "object",
+ "propertyNames": {
+ "type": "string"
+ },
+ "additionalProperties": {
+ "$ref": "#/components/schemas/PermissionActionConfig"
+ }
+ },
+ "PermissionRuleConfig": {
+ "anyOf": [
+ {
+ "$ref": "#/components/schemas/PermissionActionConfig"
+ },
+ {
+ "$ref": "#/components/schemas/PermissionObjectConfig"
+ }
+ ]
+ },
"PermissionConfig": {
"anyOf": [
{
"$ref": "#/components/schemas/PermissionActionConfig"
},
{
- "type": "object",
- "propertyNames": {
- "type": "string"
- },
- "additionalProperties": {
- "anyOf": [
- {
- "$ref": "#/components/schemas/PermissionActionConfig"
+ "allOf": [
+ {
+ "type": "object",
+ "propertyNames": {
+ "type": "string"
},
- {
- "type": "object",
- "propertyNames": {
- "type": "string"
+ "additionalProperties": {
+ "$ref": "#/components/schemas/PermissionRuleConfig"
+ }
+ },
+ {
+ "type": "object",
+ "properties": {
+ "read": {
+ "$ref": "#/components/schemas/PermissionRuleConfig"
},
- "additionalProperties": {
+ "edit": {
+ "$ref": "#/components/schemas/PermissionRuleConfig"
+ },
+ "glob": {
+ "$ref": "#/components/schemas/PermissionRuleConfig"
+ },
+ "grep": {
+ "$ref": "#/components/schemas/PermissionRuleConfig"
+ },
+ "list": {
+ "$ref": "#/components/schemas/PermissionRuleConfig"
+ },
+ "bash": {
+ "$ref": "#/components/schemas/PermissionRuleConfig"
+ },
+ "task": {
+ "$ref": "#/components/schemas/PermissionRuleConfig"
+ },
+ "external_directory": {
+ "$ref": "#/components/schemas/PermissionRuleConfig"
+ },
+ "todowrite": {
+ "$ref": "#/components/schemas/PermissionActionConfig"
+ },
+ "question": {
"$ref": "#/components/schemas/PermissionActionConfig"
+ },
+ "webfetch": {
+ "$ref": "#/components/schemas/PermissionActionConfig"
+ },
+ "websearch": {
+ "$ref": "#/components/schemas/PermissionActionConfig"
+ },
+ "codesearch": {
+ "$ref": "#/components/schemas/PermissionActionConfig"
+ },
+ "lsp": {
+ "$ref": "#/components/schemas/PermissionRuleConfig"
+ },
+ "doom_loop": {
+ "$ref": "#/components/schemas/PermissionActionConfig"
+ },
+ "skill": {
+ "$ref": "#/components/schemas/PermissionRuleConfig"
}
+ },
+ "additionalProperties": {
+ "$ref": "#/components/schemas/PermissionRuleConfig"
}
- ]
- }
+ }
+ ]
}
]
},