diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index f7e2c134a3..7fb48e950f 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -113,6 +113,7 @@ export const layer = Layer.effect( question: "deny", plan_enter: "deny", plan_exit: "deny", + edit: "ask", repo_clone: "deny", repo_overview: "deny", // mirrors github.com/github/gitignore Node.gitignore pattern for .env files diff --git a/packages/opencode/src/cli/cmd/run.ts b/packages/opencode/src/cli/cmd/run.ts index b80a2389ef..d354b7e0cd 100644 --- a/packages/opencode/src/cli/cmd/run.ts +++ b/packages/opencode/src/cli/cmd/run.ts @@ -385,6 +385,11 @@ export const RunCommand = effectCmd({ action: "deny", pattern: "*", }, + { + permission: "edit", + action: "allow", + pattern: "*", + }, ] function title() { diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx index bd2b0e352b..179569521a 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx @@ -157,6 +157,7 @@ export function Prompt(props: PromptProps) { const dimensions = useTerminalDimensions() const { theme, syntax } = useTheme() const kv = useKV() + const [autoaccept, setAutoaccept] = kv.signal<"none" | "edit">("permission_auto_accept", "edit") const animationsEnabled = createMemo(() => kv.get("animations_enabled", true)) const list = createMemo(() => props.placeholders?.normal ?? []) const shell = createMemo(() => props.placeholders?.shell ?? []) @@ -404,6 +405,16 @@ export function Prompt(props: PromptProps) { const promptCommands = createMemo(() => [ + { + title: autoaccept() === "none" ? "Enable autoedit" : "Disable autoedit", + name: "permission.auto_accept.toggle", + keybind: "permission_auto_accept_toggle", + category: "Agent", + run: () => { + setAutoaccept((value) => (value === "none" ? "edit" : "none")) + dialog.clear() + }, + }, { title: "Clear prompt", name: "prompt.clear", @@ -1585,8 +1596,13 @@ export function Prompt(props: PromptProps) { )} - + + + + autoedit + + {props.right} diff --git a/packages/opencode/src/cli/cmd/tui/context/sync.tsx b/packages/opencode/src/cli/cmd/tui/context/sync.tsx index 9f8a384f77..40d74f5613 100644 --- a/packages/opencode/src/cli/cmd/tui/context/sync.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/sync.tsx @@ -111,6 +111,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ const project = useProject() const sdk = useSDK() const kv = useKV() + const [autoaccept] = kv.signal<"none" | "edit">("permission_auto_accept", "edit") const fullSyncedSessions = new Set() @@ -152,6 +153,13 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ case "permission.asked": { const request = event.properties + if (autoaccept() === "edit" && request.permission === "edit") { + void sdk.client.permission.reply({ + reply: "once", + requestID: request.id, + }) + break + } const requests = store.permission[request.sessionID] if (!requests) { setStore("permission", request.sessionID, [request]) diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx index 700735d38c..e318309c6b 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx @@ -51,6 +51,7 @@ export interface DialogSelectOption { title: string value: T description?: string + search?: string footer?: JSX.Element | string category?: string categoryView?: JSX.Element @@ -126,8 +127,8 @@ export function DialogSelect(props: DialogSelectProps) { // users typically search by the item name, and not its category. const result = fuzzysort .go(needle, options, { - keys: ["title", "category"], - scoreFn: (r) => r[0].score * 2 + r[1].score, + keys: ["title", "category", "search"], + scoreFn: (r) => r[0].score * 2 + r[1].score + r[2].score, }) .map((x) => x.obj) diff --git a/packages/opencode/test/agent/agent.test.ts b/packages/opencode/test/agent/agent.test.ts index e0defc1386..9e517d5571 100644 --- a/packages/opencode/test/agent/agent.test.ts +++ b/packages/opencode/test/agent/agent.test.ts @@ -68,7 +68,7 @@ it.instance("build agent has correct default properties", () => expect(build).toBeDefined() expect(build?.mode).toBe("primary") expect(build?.native).toBe(true) - expect(evalPerm(build, "edit")).toBe("allow") + expect(evalPerm(build, "edit")).toBe("ask") expect(evalPerm(build, "bash")).toBe("allow") expect(evalPerm(build, "repo_clone")).toBe("deny") expect(evalPerm(build, "repo_overview")).toBe("deny") @@ -259,8 +259,8 @@ it.instance( expect(build).toBeDefined() // Specific pattern is denied expect(Permission.evaluate("bash", "rm -rf *", build!.permission).action).toBe("deny") - // Edit still allowed - expect(evalPerm(build, "edit")).toBe("allow") + // Edit still asks by default + expect(evalPerm(build, "edit")).toBe("ask") }), { config: {