Skip to content

Commit fe2a4f2

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

7 files changed

Lines changed: 51 additions & 11 deletions

File tree

packages/opencode/src/cli/cmd/run.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,6 @@ export const RunCommand = effectCmd({
325325
const files: { type: "file"; url: string; filename: string; mime: string }[] = []
326326
if (args.file) {
327327
const list = Array.isArray(args.file) ? args.file : [args.file]
328-
329328
for (const filePath of list) {
330329
const resolvedPath = path.resolve(process.cwd(), filePath)
331330
if (!(await Filesystem.exists(resolvedPath))) {

packages/opencode/src/cli/cmd/tui/app.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,7 @@ function App(props: { onSnapshot?: () => Promise<string[]> }) {
510510
{
511511
title: "Toggle MCPs",
512512
value: "mcp.list",
513+
search: "toggle mcps",
513514
category: "Agent",
514515
slash: {
515516
name: "mcps",
@@ -616,6 +617,7 @@ function App(props: { onSnapshot?: () => Promise<string[]> }) {
616617
{
617618
title: mode() === "dark" ? "Switch to light mode" : "Switch to dark mode",
618619
value: "theme.switch_mode",
620+
search: "toggle appearance",
619621
onSelect: (dialog) => {
620622
setMode(mode() === "dark" ? "light" : "dark")
621623
dialog.clear()
@@ -664,6 +666,7 @@ function App(props: { onSnapshot?: () => Promise<string[]> }) {
664666
},
665667
{
666668
title: "Toggle debug panel",
669+
search: "toggle debug",
667670
category: "System",
668671
value: "app.debug",
669672
onSelect: (dialog) => {
@@ -673,6 +676,7 @@ function App(props: { onSnapshot?: () => Promise<string[]> }) {
673676
},
674677
{
675678
title: "Toggle console",
679+
search: "toggle console",
676680
category: "System",
677681
value: "app.console",
678682
onSelect: (dialog) => {
@@ -714,6 +718,7 @@ function App(props: { onSnapshot?: () => Promise<string[]> }) {
714718
{
715719
title: terminalTitleEnabled() ? "Disable terminal title" : "Enable terminal title",
716720
value: "terminal.title.toggle",
721+
search: "toggle terminal title",
717722
keybind: "terminal_title_toggle",
718723
category: "System",
719724
onSelect: (dialog) => {
@@ -729,6 +734,7 @@ function App(props: { onSnapshot?: () => Promise<string[]> }) {
729734
{
730735
title: kv.get("animations_enabled", true) ? "Disable animations" : "Enable animations",
731736
value: "app.toggle.animations",
737+
search: "toggle animations",
732738
category: "System",
733739
onSelect: (dialog) => {
734740
kv.set("animations_enabled", !kv.get("animations_enabled", true))
@@ -772,6 +778,7 @@ function App(props: { onSnapshot?: () => Promise<string[]> }) {
772778
{
773779
title: kv.get("diff_wrap_mode", "word") === "word" ? "Disable diff wrapping" : "Enable diff wrapping",
774780
value: "app.toggle.diffwrap",
781+
search: "toggle diff wrapping",
775782
category: "System",
776783
onSelect: (dialog) => {
777784
const current = kv.get("diff_wrap_mode", "word")

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

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ export function Prompt(props: PromptProps) {
271271
const timer = setInterval(() => setWorkspaceCreatingDots((dots) => (dots % 3) + 1), 1000)
272272
onCleanup(() => clearInterval(timer))
273273
})
274+
const [autoaccept, setAutoaccept] = kv.signal<"none" | "edit">("permission_auto_accept", "edit")
274275

275276
function promptModelWarning() {
276277
toast.show({
@@ -393,6 +394,17 @@ export function Prompt(props: PromptProps) {
393394

394395
command.register(() => {
395396
return [
397+
{
398+
title: autoaccept() === "none" ? "Enable autoedit" : "Disable autoedit",
399+
value: "permission.auto_accept.toggle",
400+
search: "toggle permissions",
401+
keybind: "permission_auto_accept_toggle",
402+
category: "Agent",
403+
onSelect: (dialog) => {
404+
setAutoaccept(() => (autoaccept() === "none" ? "edit" : "none"))
405+
dialog.clear()
406+
},
407+
},
396408
{
397409
title: "Clear prompt",
398410
value: "prompt.clear",
@@ -1480,11 +1492,18 @@ export function Prompt(props: PromptProps) {
14801492
)}
14811493
</Show>
14821494
</box>
1483-
<Show when={hasRightContent()}>
14841495
<box flexDirection="row" gap={1} alignItems="center">
1485-
{props.right}
1496+
<Show when={autoaccept() === "edit"}>
1497+
<text>
1498+
<span style={{ fg: theme.warning }}>autoedit</span>
1499+
</text>
1500+
</Show>
1501+
<Show when={hasRightContent()}>
1502+
<box flexDirection="row" gap={1} alignItems="center">
1503+
{props.right}
1504+
</box>
1505+
</Show>
14861506
</box>
1487-
</Show>
14881507
</box>
14891508
</box>
14901509
</box>

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ import { createSimpleContext } from "./helper"
2727
import type { Snapshot } from "@/snapshot"
2828
import { useExit } from "./exit"
2929
import { useArgs } from "./args"
30+
import { useKV } from "./kv"
3031
import { batch, onMount } from "solid-js"
3132
import * as Log from "@opencode-ai/core/util/log"
3233
import { emptyConsoleState, type ConsoleState } from "@/config/console-state"
3334
import path from "path"
34-
import { useKV } from "./kv"
3535

3636
export const { use: useSync, provider: SyncProvider } = createSimpleContext({
3737
name: "Sync",
@@ -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+
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: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,7 @@ export function Session() {
608608
{
609609
title: sidebarVisible() ? "Hide sidebar" : "Show sidebar",
610610
value: "session.sidebar.toggle",
611+
search: "toggle sidebar",
611612
keybind: "sidebar_toggle",
612613
category: "Session",
613614
onSelect: (dialog) => {
@@ -622,6 +623,7 @@ 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) => {
@@ -632,6 +634,7 @@ export function Session() {
632634
{
633635
title: showTimestamps() ? "Hide timestamps" : "Show timestamps",
634636
value: "session.toggle.timestamps",
637+
search: "toggle timestamps",
635638
category: "Session",
636639
slash: {
637640
name: "timestamps",
@@ -645,6 +648,7 @@ export function Session() {
645648
{
646649
title: showThinking() ? "Hide thinking" : "Show thinking",
647650
value: "session.toggle.thinking",
651+
search: "toggle thinking",
648652
keybind: "display_thinking",
649653
category: "Session",
650654
slash: {
@@ -659,6 +663,7 @@ export function Session() {
659663
{
660664
title: showDetails() ? "Hide tool details" : "Show tool details",
661665
value: "session.toggle.actions",
666+
search: "toggle tool details",
662667
keybind: "tool_details",
663668
category: "Session",
664669
onSelect: (dialog) => {
@@ -667,8 +672,9 @@ export function Session() {
667672
},
668673
},
669674
{
670-
title: "Toggle session scrollbar",
675+
title: showScrollbar() ? "Hide session scrollbar" : "Show session scrollbar",
671676
value: "session.toggle.scrollbar",
677+
search: "toggle session scrollbar",
672678
keybind: "scrollbar_toggle",
673679
category: "Session",
674680
onSelect: (dialog) => {

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/test/agent/agent.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ test("build agent has correct default properties", async () => {
4949
expect(build).toBeDefined()
5050
expect(build?.mode).toBe("primary")
5151
expect(build?.native).toBe(true)
52-
expect(evalPerm(build, "edit")).toBe("allow")
52+
expect(evalPerm(build, "edit")).toBe("ask")
5353
expect(evalPerm(build, "bash")).toBe("allow")
5454
},
5555
})
@@ -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)