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.
This commit is contained in:
Dax Raad
2026-04-25 09:48:09 -04:00
parent d748c71845
commit 1b92c95425
3 changed files with 137 additions and 34 deletions

View File

@@ -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, {

View File

@@ -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

View File

@@ -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/PermissionActionConfig"
}
"additionalProperties": {
"$ref": "#/components/schemas/PermissionRuleConfig"
}
]
}
},
{
"type": "object",
"properties": {
"read": {
"$ref": "#/components/schemas/PermissionRuleConfig"
},
"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"
}
}
]
}
]
},