Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ file is the human-readable summary of what changed and why.

## Unreleased

### TUI

- **Permission mode is always shown, and `shift+tab` toggles it** — the prompt
footer now labels the mode next to the agent name: gray `manual` in normal
mode, red `auto` when permissions are auto-approved (`--auto`, previously a
gray `auto` shown only in that mode). `shift+tab` cycles between the two,
configurable as the new `permission_mode_cycle` keybind, and the idle footer
advertises it with a `shift+tab modes` hint next to `tab agents`. Its former default,
previous-agent (`agent_cycle_reverse`), is now unbound by default — `tab`
still cycles agents forward.

## 1.18.4-1

### CodeGraph
Expand Down
1 change: 1 addition & 0 deletions DIVERGENCES.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ from the squash message first, or use a plain merge.
| `packages/app/src/context/language.tsx`, `packages/app/src/entry.tsx`, `packages/desktop/src/renderer/i18n/index.ts`, `packages/console/app/src/i18n/index.ts`, `packages/console/app/src/lib/language.ts`, `packages/console/app/src/component/footer.tsx`, `packages/stats/app/src/i18n.ts`, `packages/enterprise/src/app.tsx`, `packages/app/e2e/regression/session-timeline-locale-projection.spec.ts` | Locale registries trimmed to `en` + `es`: `Locale` types, LOCALES/LABEL/TAG/DOCS maps, dict loaders, accept-language matchers; enterprise/entry `zh` special cases now use `es`; console footer always links Discord (Feishu was zh-only); e2e locale-projection spec tests `es` ("Explorado") instead of de/ar | Fork ships English + Spanish only. | Keep our trimmed lists; take upstream's structural changes and re-trim any new locale entries. |
| `packages/tui/src/component/prompt/autocomplete.tsx`, `packages/app/src/components/prompt-input.tsx`, `packages/opencode/src/cli/cmd/run/footer.prompt.tsx`, `packages/core/src/filesystem/search.ts`, `packages/tui/test/fixture/tui-sdk.ts`, `packages/opencode/test/cli/run/footer.view.test.tsx`, `packages/core/test/filesystem/search.test.ts` | `@` mention autocomplete lists file/directory results before references/agents/MCP resources; TUI and run-CLI menus cap the leading files so up to 3 non-file matches stay in the first visible page; web app group rank reordered to recent → file → reference → agent → resource (extracted into fork-only `prompt-input/at-options.ts`). TUI and run-CLI file resources track menu visibility so opening on an empty query fetches (previously nothing refetched until the query changed); core's ripgrep-fallback `find` returns its first entries for an empty query to mirror fff. Tests: tui-sdk fixture's `FetchHandler` gains an optional `method` arg, `renderFooter` accepts `findFiles`/`agents` overrides + a mention-menu ordering test, core search tests cover the fallback's empty query (fork-only test files: `packages/tui/test/prompt-autocomplete.test.tsx`, `packages/app/test-browser/prompt-at-options.test.ts`, `packages/app/src/components/prompt-input/at-options{,.test}.ts`) | Files are the dominant `@` use case; they should rank first and appear on a bare `@`. | Keep our ordering/reserve logic, resource source tracking, empty-query branch, fixture/test additions; take upstream's surrounding changes. |
| `packages/slack/.gitignore`, `sdks/vscode/.gitignore` | Added the missing trailing newline (content unchanged) | Upstream's copies end without a newline; POSIX text files should end with one, and tools that concatenate or append to these files misbehave without it. | Whitespace-only: keep the trailing newline; take upstream's entries. |
| `packages/tui/src/config/keybind.ts`, `packages/tui/src/component/prompt/index.tsx`, `packages/tui/src/app.tsx` | Permission-mode indicator + shift+tab cycle. keybind.ts: added `permission_mode_cycle: keybind("shift+tab", ...)` + its `permission.mode` CommandMap entry; `agent_cycle_reverse` default `"shift+tab"` → `"none"` (tab still cycles agents forward; previous-agent stays rebindable). prompt/index.tsx: the footer badge next to the agent name always renders in prompt mode — gray `manual` (`theme.textMuted`) in normal mode, red `auto` (`theme.error`) in auto mode (upstream only showed gray `auto`); the idle footer's shortcut hints gain a `shift+tab modes` text (via a `modeShortcut` `useCommandShortcut("permission.mode")` memo) left of `tab agents`, in the same no-usage `Match` arm. app.tsx: `"permission.mode"` added to `appBindingCommands` so the binding is gathered. | The permission mode is always visible (manual/auto) with auto in red as a danger signal, and shift+tab toggles it without opening the palette. | Keep the `permission_mode_cycle` definition + mapping, the `agent_cycle_reverse` `"none"` default, the badge `Show` block, the `modeShortcut` memo + hint text, and the `appBindingCommands` entry; take upstream's surrounding changes. If upstream reworks the auto badge or rebinds shift+tab, re-apply on top and re-audit the shift+tab conflict. |

## Known rebrand gaps

Expand Down
1 change: 1 addition & 0 deletions packages/tui/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ const appBindingCommands = [
"app.toggle.diffwrap",
"app.toggle.paste_summary",
"app.toggle.session_directory_filter",
"permission.mode",
] as const

export type TuiInput = {
Expand Down
15 changes: 13 additions & 2 deletions packages/tui/src/component/prompt/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ export function Prompt(props: PromptProps) {
const stash = usePromptStash()
const keymap = useOpencodeKeymap()
const agentShortcut = useCommandShortcut("agent.cycle")
const modeShortcut = useCommandShortcut("permission.mode")
const paletteShortcut = useCommandShortcut("command.palette.show")
const interruptSequence = useCommandShortcut("session.interrupt")
const interruptNowSequence = useCommandShortcut("session.interrupt.now")
Expand Down Expand Up @@ -1435,8 +1436,15 @@ export function Prompt(props: PromptProps) {
<text fg={fadeColor(highlight(), agentMetaAlpha())}>
{store.mode === "shell" ? "Shell" : Locale.titlecase(agent().name)}
</text>
<Show when={store.mode === "normal" && local.permission.mode === "auto"}>
<text fg={fadeColor(theme.textMuted, agentMetaAlpha())}>auto</text>
<Show when={store.mode === "normal"}>
<text
fg={fadeColor(
local.permission.mode === "auto" ? theme.error : theme.textMuted,
agentMetaAlpha(),
)}
>
{local.permission.mode === "auto" ? "auto" : "manual"}
</text>
</Show>
<Show when={store.mode === "normal" && connected()}>
<box flexDirection="row" gap={1}>
Expand Down Expand Up @@ -1644,6 +1652,9 @@ export function Prompt(props: PromptProps) {
)}
</Match>
<Match when={true}>
<text fg={theme.text}>
{modeShortcut()} <span style={{ fg: theme.textMuted }}>modes</span>
</text>
<text fg={theme.text}>
{agentShortcut()} <span style={{ fg: theme.textMuted }}>agents</span>
</text>
Expand Down
4 changes: 3 additions & 1 deletion packages/tui/src/config/keybind.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ export const Definitions = {
console_org_switch: keybind("none", "Switch console organization"),
agent_list: keybind("<leader>a", "List agents"),
agent_cycle: keybind("tab", "Next agent"),
agent_cycle_reverse: keybind("shift+tab", "Previous agent"),
agent_cycle_reverse: keybind("none", "Previous agent"),
permission_mode_cycle: keybind("shift+tab", "Cycle permission mode (manual/auto)"),
variant_cycle: keybind("ctrl+t", "Cycle model variants"),
variant_list: keybind("none", "List model variants"),

Expand Down Expand Up @@ -339,6 +340,7 @@ export const CommandMap = {
agent_list: "agent.list",
agent_cycle: "agent.cycle",
agent_cycle_reverse: "agent.cycle.reverse",
permission_mode_cycle: "permission.mode",
variant_cycle: "variant.cycle",
variant_list: "variant.list",
messages_page_up: "session.page.up",
Expand Down
Loading