diff --git a/src/App.tsx b/src/App.tsx index fe5d21a9..6bc28dcd 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -13,6 +13,7 @@ import { initMarkdown } from "./lib/markdown" import { createCommandRegistry } from "./lib/commands" import type { Command } from "./lib/commands" import { hasInstances, isSelectingFolder, setIsSelectingFolder, setHasInstances } from "./stores/ui" +import { toggleShowThinkingBlocks, preferences } from "./stores/preferences" import { createInstance, instances, @@ -588,13 +589,11 @@ const App: Component = () => { commandRegistry.register({ id: "thinking", - label: "Toggle Thinking Blocks", + label: () => `${preferences().showThinkingBlocks ? "Hide" : "Show"} Thinking Blocks`, description: "Show/hide AI thinking process", category: "System", keywords: ["/thinking", "toggle", "show", "hide"], - action: () => { - console.log("Toggle thinking blocks (not implemented)") - }, + action: toggleShowThinkingBlocks, }) commandRegistry.register({ diff --git a/src/components/command-palette.tsx b/src/components/command-palette.tsx index 20573eef..bd6bc5d9 100644 --- a/src/components/command-palette.tsx +++ b/src/components/command-palette.tsx @@ -34,7 +34,8 @@ const CommandPalette: Component = (props) => { if (!q) return props.commands return props.commands.filter((cmd) => { - const labelMatch = cmd.label.toLowerCase().includes(q) + const label = typeof cmd.label === "function" ? cmd.label() : cmd.label + const labelMatch = label.toLowerCase().includes(q) const descMatch = cmd.description.toLowerCase().includes(q) const keywordMatch = cmd.keywords?.some((k) => k.toLowerCase().includes(q)) const categoryMatch = cmd.category?.toLowerCase().includes(q) @@ -190,7 +191,9 @@ const CommandPalette: Component = (props) => { onMouseEnter={() => setSelectedIndex(commandIndex)} >
-
{command.label}
+
+ {typeof command.label === "function" ? command.label() : command.label} +
{command.description}
diff --git a/src/components/message-part.tsx b/src/components/message-part.tsx index b59a2822..521ab99b 100644 --- a/src/components/message-part.tsx +++ b/src/components/message-part.tsx @@ -3,6 +3,7 @@ import ToolCall from "./tool-call" import { isItemExpanded, toggleItemExpanded } from "../stores/tool-call-state" import { Markdown } from "./markdown" import { useTheme } from "../lib/theme" +import { preferences } from "../stores/preferences" interface MessagePartProps { part: any @@ -38,19 +39,21 @@ export default function MessagePart(props: MessagePartProps) { -
-
-
- {isReasoningExpanded() ? "▼" : "▶"} - Reasoning -
- -
- + +
+
+
+ {isReasoningExpanded() ? "▼" : "▶"} + Reasoning
- + +
+ +
+
+
-
+
) diff --git a/src/components/message-stream.tsx b/src/components/message-stream.tsx index 0e334cfc..3b4abad2 100644 --- a/src/components/message-stream.tsx +++ b/src/components/message-stream.tsx @@ -4,6 +4,7 @@ import MessageItem from "./message-item" import ToolCall from "./tool-call" import { sseManager } from "../lib/sse-manager" import Kbd from "./kbd" +import { preferences } from "../stores/preferences" interface MessageStreamProps { instanceId: string @@ -72,7 +73,7 @@ export default function MessageStream(props: MessageStreamProps) { const textParts = message.parts.filter((p) => p.type === "text" && !p.synthetic) const toolParts = message.parts.filter((p) => p.type === "tool") - const reasoningParts = message.parts.filter((p) => p.type === "reasoning") + const reasoningParts = preferences().showThinkingBlocks ? message.parts.filter((p) => p.type === "reasoning") : [] const isQueued = message.type === "user" && message.id > lastAssistantMessageId diff --git a/src/lib/commands.ts b/src/lib/commands.ts index f09106ae..f65d5df6 100644 --- a/src/lib/commands.ts +++ b/src/lib/commands.ts @@ -8,7 +8,7 @@ export interface KeyboardShortcut { export interface Command { id: string - label: string + label: string | (() => string) description: string keywords?: string[] shortcut?: KeyboardShortcut @@ -47,7 +47,8 @@ export function createCommandRegistry() { const lowerQuery = query.toLowerCase() return getAll().filter((cmd) => { - const labelMatch = cmd.label.toLowerCase().includes(lowerQuery) + const label = typeof cmd.label === "function" ? cmd.label() : cmd.label + const labelMatch = label.toLowerCase().includes(lowerQuery) const descMatch = cmd.description.toLowerCase().includes(lowerQuery) const keywordMatch = cmd.keywords?.some((k) => k.toLowerCase().includes(lowerQuery)) return labelMatch || descMatch || keywordMatch diff --git a/src/stores/preferences.ts b/src/stores/preferences.ts new file mode 100644 index 00000000..ff7b2abc --- /dev/null +++ b/src/stores/preferences.ts @@ -0,0 +1,45 @@ +import { createSignal } from "solid-js" + +const STORAGE_KEY = "opencode-preferences" + +interface Preferences { + showThinkingBlocks: boolean +} + +const defaultPreferences: Preferences = { + showThinkingBlocks: false, +} + +function loadPreferences(): Preferences { + try { + const stored = localStorage.getItem(STORAGE_KEY) + if (stored) { + return { ...defaultPreferences, ...JSON.parse(stored) } + } + } catch (error) { + console.error("Failed to load preferences:", error) + } + return defaultPreferences +} + +function savePreferences(prefs: Preferences): void { + try { + localStorage.setItem(STORAGE_KEY, JSON.stringify(prefs)) + } catch (error) { + console.error("Failed to save preferences:", error) + } +} + +const [preferences, setPreferences] = createSignal(loadPreferences()) + +function updatePreferences(updates: Partial): void { + const updated = { ...preferences(), ...updates } + setPreferences(updated) + savePreferences(updated) +} + +function toggleShowThinkingBlocks(): void { + updatePreferences({ showThinkingBlocks: !preferences().showThinkingBlocks }) +} + +export { preferences, updatePreferences, toggleShowThinkingBlocks }