Skip to content

Commit 69a8020

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

5 files changed

Lines changed: 32 additions & 4 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
@@ -136,6 +136,7 @@ export function Prompt(props: PromptProps) {
136136
const dimensions = useTerminalDimensions()
137137
const { theme, syntax } = useTheme()
138138
const kv = useKV()
139+
const [autoaccept, setAutoaccept] = kv.signal<"none" | "edit">("permission_auto_accept", "edit")
139140
const animationsEnabled = createMemo(() => kv.get("animations_enabled", true))
140141
const list = createMemo(() => props.placeholders?.normal ?? [])
141142
const shell = createMemo(() => props.placeholders?.shell ?? [])
@@ -174,7 +175,7 @@ export function Prompt(props: PromptProps) {
174175
let lastSubmittedEditorSelectionKey: string | undefined
175176
const [auto, setAuto] = createSignal<AutocompleteRef>()
176177
const currentProviderLabel = createMemo(() => local.model.parsed().provider)
177-
const hasRightContent = createMemo(() => Boolean(props.right))
178+
const hasRightContent = createMemo(() => Boolean(props.right) || autoaccept() === "edit")
178179

179180
function promptModelWarning() {
180181
toast.show({
@@ -296,6 +297,17 @@ export function Prompt(props: PromptProps) {
296297

297298
command.register(() => {
298299
return [
300+
{
301+
title: autoaccept() === "none" ? "Enable autoedit" : "Disable autoedit",
302+
value: "permission.auto_accept.toggle",
303+
search: "toggle permissions",
304+
keybind: "permission_auto_accept_toggle",
305+
category: "Agent",
306+
onSelect: (dialog) => {
307+
setAutoaccept(() => (autoaccept() === "none" ? "edit" : "none"))
308+
dialog.clear()
309+
},
310+
},
299311
{
300312
title: "Clear prompt",
301313
value: "prompt.clear",
@@ -1324,6 +1336,11 @@ export function Prompt(props: PromptProps) {
13241336
</box>
13251337
<Show when={hasRightContent()}>
13261338
<box flexDirection="row" gap={1} alignItems="center">
1339+
<Show when={autoaccept() === "edit"}>
1340+
<text>
1341+
<span style={{ fg: theme.warning }}>autoedit</span>
1342+
</text>
1343+
</Show>
13271344
{props.right}
13281345
</box>
13291346
</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+
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: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,7 @@ export function Session() {
622622
{
623623
title: conceal() ? "Disable code concealment" : "Enable code concealment",
624624
value: "session.toggle.conceal",
625+
search: "toggle code concealment",
625626
keybind: "messages_toggle_conceal",
626627
category: "Session",
627628
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
@@ -37,6 +37,7 @@ export interface DialogSelectOption<T = any> {
3737
title: string
3838
value: T
3939
description?: string
40+
search?: string
4041
footer?: JSX.Element | string
4142
category?: string
4243
categoryView?: JSX.Element
@@ -93,8 +94,8 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
9394
// users typically search by the item name, and not its category.
9495
const result = fuzzysort
9596
.go(needle, options, {
96-
keys: ["title", "category"],
97-
scoreFn: (r) => r[0].score * 2 + r[1].score,
97+
keys: ["title", "category", "search"],
98+
scoreFn: (r) => r[0].score * 2 + r[1].score + r[2].score,
9899
})
99100
.map((x) => x.obj)
100101

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"),

0 commit comments

Comments
 (0)