diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx index 549c7c34a7e..3fdf1236dd6 100644 --- a/packages/opencode/src/cli/cmd/tui/app.tsx +++ b/packages/opencode/src/cli/cmd/tui/app.tsx @@ -687,6 +687,83 @@ function App() { dialog.clear() }, }, + { + title: kv.get("timestamps", "hide") === "show" ? "Hide timestamps" : "Show timestamps", + value: "app.toggle.timestamps", + category: "System", + slash: { + name: "timestamps", + aliases: ["toggle-timestamps"], + }, + onSelect: (dialog) => { + const current = kv.get("timestamps", "hide") + kv.set("timestamps", current === "show" ? "hide" : "show") + dialog.clear() + }, + }, + { + title: kv.get("thinking_visibility", true) ? "Hide thinking" : "Show thinking", + value: "app.toggle.thinking", + keybind: "display_thinking", + category: "System", + slash: { + name: "thinking", + aliases: ["toggle-thinking"], + }, + onSelect: (dialog) => { + kv.set("thinking_visibility", !kv.get("thinking_visibility", true)) + dialog.clear() + }, + }, + { + title: kv.get("tool_details_visibility", true) ? "Hide tool details" : "Show tool details", + value: "app.toggle.tooldetails", + keybind: "tool_details", + category: "System", + onSelect: (dialog) => { + kv.set("tool_details_visibility", !kv.get("tool_details_visibility", true)) + dialog.clear() + }, + }, + { + title: kv.get("header_visible", true) ? "Hide header" : "Show header", + value: "app.toggle.header", + category: "System", + onSelect: (dialog) => { + kv.set("header_visible", !kv.get("header_visible", true)) + dialog.clear() + }, + }, + { + title: kv.get("scrollbar_visible", true) ? "Hide session scrollbar" : "Show session scrollbar", + value: "app.toggle.scrollbar", + keybind: "scrollbar_toggle", + category: "System", + onSelect: (dialog) => { + kv.set("scrollbar_visible", !kv.get("scrollbar_visible", true)) + dialog.clear() + }, + }, + { + title: kv.get("generic_tool_output_visibility", false) ? "Hide generic tool output" : "Show generic tool output", + value: "app.toggle.generic_tool_output", + category: "System", + onSelect: (dialog) => { + kv.set("generic_tool_output_visibility", !kv.get("generic_tool_output_visibility", false)) + dialog.clear() + }, + }, + { + title: kv.get("sidebar", "auto") === "auto" ? "Hide sidebar" : "Show sidebar", + value: "app.toggle.sidebar", + keybind: "sidebar_toggle", + category: "System", + onSelect: (dialog) => { + const current = kv.get("sidebar", "auto") + kv.set("sidebar", current === "auto" ? "hide" : "auto") + dialog.clear() + }, + }, ]) sdk.event.on(TuiEvent.CommandExecute.type, (evt) => { diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index 0d9ddc746c2..1bfcb8a4572 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -565,20 +565,6 @@ export function Session() { }) }, }, - { - title: sidebarVisible() ? "Hide sidebar" : "Show sidebar", - value: "session.sidebar.toggle", - keybind: "sidebar_toggle", - category: "Session", - onSelect: (dialog) => { - batch(() => { - const isVisible = sidebarVisible() - setSidebar(() => (isVisible ? "hide" : "auto")) - setSidebarOpen(!isVisible) - }) - dialog.clear() - }, - }, { title: conceal() ? "Disable code concealment" : "Enable code concealment", value: "session.toggle.conceal", @@ -589,71 +575,6 @@ export function Session() { dialog.clear() }, }, - { - title: showTimestamps() ? "Hide timestamps" : "Show timestamps", - value: "session.toggle.timestamps", - category: "Session", - slash: { - name: "timestamps", - aliases: ["toggle-timestamps"], - }, - onSelect: (dialog) => { - setTimestamps((prev) => (prev === "show" ? "hide" : "show")) - dialog.clear() - }, - }, - { - title: showThinking() ? "Hide thinking" : "Show thinking", - value: "session.toggle.thinking", - keybind: "display_thinking", - category: "Session", - slash: { - name: "thinking", - aliases: ["toggle-thinking"], - }, - onSelect: (dialog) => { - setShowThinking((prev) => !prev) - dialog.clear() - }, - }, - { - title: showDetails() ? "Hide tool details" : "Show tool details", - value: "session.toggle.actions", - keybind: "tool_details", - category: "Session", - onSelect: (dialog) => { - setShowDetails((prev) => !prev) - dialog.clear() - }, - }, - { - title: "Toggle session scrollbar", - value: "session.toggle.scrollbar", - keybind: "scrollbar_toggle", - category: "Session", - onSelect: (dialog) => { - setShowScrollbar((prev) => !prev) - dialog.clear() - }, - }, - { - title: showHeader() ? "Hide header" : "Show header", - value: "session.toggle.header", - category: "Session", - onSelect: (dialog) => { - setShowHeader((prev) => !prev) - dialog.clear() - }, - }, - { - title: showGenericToolOutput() ? "Hide generic tool output" : "Show generic tool output", - value: "session.toggle.generic_tool_output", - category: "Session", - onSelect: (dialog) => { - setShowGenericToolOutput((prev) => !prev) - dialog.clear() - }, - }, { title: "Page up", value: "session.page.up", diff --git a/packages/opencode/test/cli/cmd/tui/command-palette-consistency.test.ts b/packages/opencode/test/cli/cmd/tui/command-palette-consistency.test.ts new file mode 100644 index 00000000000..6f18f588d74 --- /dev/null +++ b/packages/opencode/test/cli/cmd/tui/command-palette-consistency.test.ts @@ -0,0 +1,53 @@ +import { describe, expect, test } from "bun:test" +import { readFileSync } from "fs" +import { join } from "path" + +describe("command palette consistency", () => { + const sessionPath = join( + __dirname, + "../../../../src/cli/cmd/tui/routes/session/index.tsx", + ) + const appPath = join( + __dirname, + "../../../../src/cli/cmd/tui/app.tsx", + ) + + test("session/index.tsx should not have session.toggle.* or session.sidebar.toggle commands", () => { + const content = readFileSync(sessionPath, "utf-8") + + // These patterns should NOT exist in session/index.tsx + // They should be in app.tsx as app.toggle.* + const forbiddenPatterns = [ + 'value: "session.toggle.timestamps"', + 'value: "session.toggle.thinking"', + 'value: "session.toggle.actions"', + 'value: "session.toggle.scrollbar"', + 'value: "session.toggle.header"', + 'value: "session.toggle.generic_tool_output"', + 'value: "session.sidebar.toggle"', + ] + + for (const pattern of forbiddenPatterns) { + expect(content).not.toContain(pattern) + } + }) + + test("app.tsx should have corresponding app.toggle.* commands", () => { + const content = readFileSync(appPath, "utf-8") + + // These patterns should exist in app.tsx + const expectedPatterns = [ + 'value: "app.toggle.timestamps"', + 'value: "app.toggle.thinking"', + 'value: "app.toggle.tooldetails"', + 'value: "app.toggle.scrollbar"', + 'value: "app.toggle.header"', + 'value: "app.toggle.generic_tool_output"', + 'value: "app.toggle.sidebar"', + ] + + for (const pattern of expectedPatterns) { + expect(content).toContain(pattern) + } + }) +})