Skip to content

Commit 575d3ac

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

4 files changed

Lines changed: 42 additions & 5 deletions

File tree

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ export function Prompt(props: PromptProps) {
157157
const dimensions = useTerminalDimensions()
158158
const { theme, syntax } = useTheme()
159159
const kv = useKV()
160+
const [autoaccept, setAutoaccept] = kv.signal<"none" | "edit">("permission_auto_accept", "edit")
160161
const animationsEnabled = createMemo(() => kv.get("animations_enabled", true))
161162
const list = createMemo(() => props.placeholders?.normal ?? [])
162163
const shell = createMemo(() => props.placeholders?.shell ?? [])
@@ -404,6 +405,17 @@ export function Prompt(props: PromptProps) {
404405

405406
const promptCommands = createMemo(() =>
406407
[
408+
{
409+
title: autoaccept() === "none" ? "Enable autoedit" : "Disable autoedit",
410+
value: "permission.auto_accept.toggle",
411+
search: "toggle permissions",
412+
keybind: "permission_auto_accept_toggle",
413+
category: "Agent",
414+
onSelect: () => {
415+
setAutoaccept(() => (autoaccept() === "none" ? "edit" : "none"))
416+
dialog.clear()
417+
},
418+
},
407419
{
408420
title: "Clear prompt",
409421
name: "prompt.clear",
@@ -1596,8 +1608,13 @@ export function Prompt(props: PromptProps) {
15961608
)}
15971609
</Show>
15981610
</box>
1599-
<Show when={hasRightContent()}>
1611+
<Show when={hasRightContent() || autoaccept() === "edit"}>
16001612
<box flexDirection="row" gap={1} alignItems="center">
1613+
<Show when={autoaccept() === "edit"}>
1614+
<text>
1615+
<span style={{ fg: fadeColor(theme.warning, modelMetaAlpha()) }}>autoedit</span>
1616+
</text>
1617+
</Show>
16011618
{props.right}
16021619
</box>
16031620
</Show>

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
import { aggregateFailures } from "./aggregate-failures"
3636

3737
export const { use: useSync, provider: SyncProvider } = createSimpleContext({
@@ -111,6 +111,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
111111
const project = useProject()
112112
const sdk = useSDK()
113113
const kv = useKV()
114+
const [autoaccept] = kv.signal<"none" | "edit">("permission_auto_accept", "edit")
114115

115116
const fullSyncedSessions = new Set<string>()
116117

@@ -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: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,8 @@ export function Session() {
658658
{
659659
title: sidebarVisible() ? "Hide sidebar" : "Show sidebar",
660660
value: "session.sidebar.toggle",
661+
search: "toggle sidebar",
662+
keybind: "sidebar_toggle",
661663
category: "Session",
662664
run: () => {
663665
batch(() => {
@@ -671,6 +673,8 @@ export function Session() {
671673
{
672674
title: conceal() ? "Disable code concealment" : "Enable code concealment",
673675
value: "session.toggle.conceal",
676+
search: "toggle code concealment",
677+
keybind: "messages_toggle_conceal" as any,
674678
category: "Session",
675679
run: () => {
676680
setConceal((prev) => !prev)
@@ -680,6 +684,7 @@ export function Session() {
680684
{
681685
title: showTimestamps() ? "Hide timestamps" : "Show timestamps",
682686
value: "session.toggle.timestamps",
687+
search: "toggle timestamps",
683688
category: "Session",
684689
slash: {
685690
name: "timestamps",
@@ -697,6 +702,8 @@ export function Session() {
697702
return "Expand thinking"
698703
})(),
699704
value: "session.toggle.thinking",
705+
search: "toggle thinking",
706+
keybind: "display_thinking",
700707
category: "Session",
701708
slash: {
702709
name: "thinking",
@@ -710,15 +717,19 @@ export function Session() {
710717
{
711718
title: showDetails() ? "Hide tool details" : "Show tool details",
712719
value: "session.toggle.actions",
720+
search: "toggle tool details",
721+
keybind: "tool_details",
713722
category: "Session",
714723
run: () => {
715724
setShowDetails((prev) => !prev)
716725
dialog.clear()
717726
},
718727
},
719728
{
720-
title: "Toggle session scrollbar",
729+
title: showScrollbar() ? "Hide session scrollbar" : "Show session scrollbar",
721730
value: "session.toggle.scrollbar",
731+
search: "toggle session scrollbar",
732+
keybind: "scrollbar_toggle",
722733
category: "Session",
723734
run: () => {
724735
setShowScrollbar((prev) => !prev)

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export interface DialogSelectOption<T = any> {
5252
value: T
5353
description?: string
5454
details?: string[]
55+
search?: string
5556
footer?: JSX.Element | string
5657
category?: string
5758
categoryView?: JSX.Element
@@ -127,8 +128,8 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
127128
// users typically search by the item name, and not its category.
128129
const result = fuzzysort
129130
.go(needle, options, {
130-
keys: ["title", "category"],
131-
scoreFn: (r) => r[0].score * 2 + r[1].score,
131+
keys: ["title", "category", "search"],
132+
scoreFn: (r) => r[0].score * 2 + r[1].score + r[2].score,
132133
})
133134
.map((x) => x.obj)
134135

0 commit comments

Comments
 (0)