Skip to content

Commit 2a20c2d

Browse files
Apply PR #12633: feat(tui): add auto-accept mode for permission requests
2 parents 2513dfc + 5792a80 commit 2a20c2d

6 files changed

Lines changed: 35 additions & 6 deletions

File tree

packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ export function Prompt(props: PromptProps) {
139139
const dimensions = useTerminalDimensions()
140140
const { theme, syntax } = useTheme()
141141
const kv = useKV()
142+
const [autoaccept] = kv.signal<"none" | "edit">("permission_auto_accept", "edit")
142143
const animationsEnabled = createMemo(() => kv.get("animations_enabled", true))
143144
const list = createMemo(() => props.placeholders?.normal ?? [])
144145
const shell = createMemo(() => props.placeholders?.shell ?? [])
@@ -1459,8 +1460,13 @@ export function Prompt(props: PromptProps) {
14591460
)}
14601461
</Show>
14611462
</box>
1462-
<Show when={hasRightContent()}>
1463+
<Show when={hasRightContent() || autoaccept() === "edit"}>
14631464
<box flexDirection="row" gap={1} alignItems="center">
1465+
<Show when={autoaccept() === "edit"}>
1466+
<text>
1467+
<span style={{ fg: theme.warning }}>autoedit</span>
1468+
</text>
1469+
</Show>
14641470
{props.right}
14651471
</box>
14661472
</Show>

packages/opencode/src/cli/cmd/tui/context/sync.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
110110
const project = useProject()
111111
const sdk = useSDK()
112112
const kv = useKV()
113+
const [autoaccept] = kv.signal<"none" | "edit">("permission_auto_accept", "edit")
113114

114115
const fullSyncedSessions = new Set<string>()
115116
let syncedWorkspace = project.workspace.current()
@@ -152,6 +153,13 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
152153

153154
case "permission.asked": {
154155
const request = event.properties
156+
if (autoaccept() === "edit" && request.permission === "edit") {
157+
void sdk.client.permission.reply({
158+
reply: "once",
159+
requestID: request.id,
160+
})
161+
break
162+
}
155163
const requests = store.permission[request.sessionID]
156164
if (!requests) {
157165
setStore("permission", request.sessionID, [request])

packages/opencode/src/cli/cmd/tui/routes/session/index.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ export function Session() {
165165
const [showScrollbar, setShowScrollbar] = kv.signal("scrollbar_visible", false)
166166
const [diffWrapMode] = kv.signal<"word" | "none">("diff_wrap_mode", "word")
167167
const [_animationsEnabled, _setAnimationsEnabled] = kv.signal("animations_enabled", true)
168+
const [autoaccept, setAutoaccept] = kv.signal<"none" | "edit">("permission_auto_accept", "edit")
168169
const [showGenericToolOutput, setShowGenericToolOutput] = kv.signal("generic_tool_output_visibility", false)
169170

170171
const wide = createMemo(() => dimensions().width > 120)
@@ -622,13 +623,25 @@ export function Session() {
622623
{
623624
title: conceal() ? "Disable code concealment" : "Enable code concealment",
624625
value: "session.toggle.conceal",
626+
search: "toggle code concealment",
625627
keybind: "messages_toggle_conceal",
626628
category: "Session",
627629
onSelect: (dialog) => {
628630
setConceal((prev) => !prev)
629631
dialog.clear()
630632
},
631633
},
634+
{
635+
title: autoaccept() === "edit" ? "Disable auto-accept for edit permissions" : "Enable auto-accept for edit permissions",
636+
value: "session.permission.auto_accept",
637+
search: "toggle permission auto accept autoedit",
638+
keybind: "permission_auto_accept_toggle",
639+
category: "Session",
640+
onSelect: (dialog) => {
641+
setAutoaccept((value) => (value === "edit" ? "none" : "edit"))
642+
dialog.clear()
643+
},
644+
},
632645
{
633646
title: showTimestamps() ? "Hide timestamps" : "Show timestamps",
634647
value: "session.toggle.timestamps",

packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export interface DialogSelectOption<T = any> {
3838
title: string
3939
value: T
4040
description?: string
41+
search?: string
4142
footer?: JSX.Element | string
4243
category?: string
4344
categoryView?: JSX.Element
@@ -94,8 +95,8 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
9495
// users typically search by the item name, and not its category.
9596
const result = fuzzysort
9697
.go(needle, options, {
97-
keys: ["title", "category"],
98-
scoreFn: (r) => r[0].score * 2 + r[1].score,
98+
keys: ["title", "category", "search"],
99+
scoreFn: (r) => r[0].score * 2 + r[1].score + r[2].score,
99100
})
100101
.map((x) => x.obj)
101102

packages/opencode/src/config/keybinds.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ const KeybindsSchema = Schema.Struct({
6161
command_list: keybind("ctrl+p", "List available commands"),
6262
agent_list: keybind("<leader>a", "List agents"),
6363
agent_cycle: keybind("tab", "Next agent"),
64-
agent_cycle_reverse: keybind("shift+tab", "Previous agent"),
64+
agent_cycle_reverse: keybind("none", "Previous agent"),
65+
permission_auto_accept_toggle: keybind("shift+tab", "Toggle auto-accept mode for permissions"),
6566
variant_cycle: keybind("ctrl+t", "Cycle model variants"),
6667
variant_list: keybind("none", "List model variants"),
6768
input_clear: keybind("ctrl+c", "Clear input field"),

packages/opencode/test/agent/agent.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,8 @@ test("agent permission config merges with defaults", async () => {
229229
expect(build).toBeDefined()
230230
// Specific pattern is denied
231231
expect(Permission.evaluate("bash", "rm -rf *", build!.permission).action).toBe("deny")
232-
// Edit still allowed
233-
expect(evalPerm(build, "edit")).toBe("allow")
232+
// Edit still asks (default behavior)
233+
expect(evalPerm(build, "edit")).toBe("ask")
234234
},
235235
})
236236
})

0 commit comments

Comments
 (0)