Add agent-level permissions with whitelist/blacklist support (#1862)

This commit is contained in:
Dax
2025-08-12 11:39:39 -04:00
committed by GitHub
parent ccaebdcd16
commit 10735f93ca
18 changed files with 344 additions and 54 deletions

View File

@@ -5,6 +5,7 @@ import { Provider } from "../provider/provider"
import { generateObject, type ModelMessage } from "ai"
import PROMPT_GENERATE from "./generate.txt"
import { SystemPrompt } from "../session/system"
import { mergeDeep } from "remeda"
export namespace Agent {
export const Info = z
@@ -14,6 +15,11 @@ export namespace Agent {
mode: z.union([z.literal("subagent"), z.literal("primary"), z.literal("all")]),
topP: z.number().optional(),
temperature: z.number().optional(),
permission: z.object({
edit: Config.Permission,
bash: z.record(z.string(), Config.Permission),
webfetch: Config.Permission.optional(),
}),
model: z
.object({
modelID: z.string(),
@@ -31,6 +37,13 @@ export namespace Agent {
const state = App.state("agent", async () => {
const cfg = await Config.get()
const defaultPermission: Info["permission"] = {
edit: "allow",
bash: {
"*": "allow",
},
webfetch: "allow",
}
const result: Record<string, Info> = {
general: {
name: "general",
@@ -41,17 +54,20 @@ export namespace Agent {
todowrite: false,
},
options: {},
permission: defaultPermission,
mode: "subagent",
},
build: {
name: "build",
tools: {},
options: {},
permission: defaultPermission,
mode: "primary",
},
plan: {
name: "plan",
options: {},
permission: defaultPermission,
tools: {
write: false,
edit: false,
@@ -70,25 +86,48 @@ export namespace Agent {
item = result[key] = {
name: key,
mode: "all",
permission: defaultPermission,
options: {},
tools: {},
}
const { model, prompt, tools, description, temperature, top_p, mode, ...extra } = value
const { model, prompt, tools, description, temperature, top_p, mode, permission, ...extra } = value
item.options = {
...item.options,
...extra,
}
if (value.model) item.model = Provider.parseModel(value.model)
if (value.prompt) item.prompt = value.prompt
if (value.tools)
if (model) item.model = Provider.parseModel(model)
if (prompt) item.prompt = prompt
if (tools)
item.tools = {
...item.tools,
...value.tools,
...tools,
}
if (value.description) item.description = value.description
if (value.temperature != undefined) item.temperature = value.temperature
if (value.top_p != undefined) item.topP = value.top_p
if (value.mode) item.mode = value.mode
if (description) item.description = description
if (temperature != undefined) item.temperature = temperature
if (top_p != undefined) item.topP = top_p
if (mode) item.mode = mode
if (permission ?? cfg.permission) {
const merged = mergeDeep(cfg.permission ?? {}, permission ?? {})
if (merged.edit) item.permission.edit = merged.edit
if (merged.webfetch) item.permission.webfetch = merged.webfetch
if (merged.bash) {
if (typeof merged.bash === "string") {
item.permission.bash = {
"*": merged.bash,
}
}
// if granular permissions are provided, default to "ask"
if (typeof merged.bash === "object") {
item.permission.bash = mergeDeep(
{
"*": "ask",
},
merged.bash,
)
}
}
}
}
return result
})