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