瀏覽代碼

Fix thinking toggle defaults

Dax Raad 3 月之前
父節點
當前提交
2385123f03

+ 0 - 1
packages/core/src/flag/flag.ts

@@ -38,7 +38,6 @@ export const Flag = {
   ),
   OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT:
     copy === undefined ? process.platform === "win32" : truthy("OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT"),
-  OPENCODE_EXPERIMENTAL_MINIMAL_THINKING: truthy("OPENCODE_EXPERIMENTAL_MINIMAL_THINKING"),
   OPENCODE_MODELS_URL: process.env["OPENCODE_MODELS_URL"],
   OPENCODE_MODELS_PATH: process.env["OPENCODE_MODELS_PATH"],
   OPENCODE_DB: process.env["OPENCODE_DB"],

+ 8 - 9
packages/opencode/src/cli/cmd/tui/context/thinking.ts

@@ -1,10 +1,9 @@
 import { createMemo, type Setter } from "solid-js"
-import { Flag } from "@opencode-ai/core/flag/flag"
 import { useKV } from "./kv"
 
-export type ThinkingMode = "show" | "minimal" | "hide"
+export type ThinkingMode = "show" | "hide"
 
-const MODES: readonly ThinkingMode[] = ["show", "minimal", "hide"] as const
+const MODES: readonly ThinkingMode[] = ["show", "hide"] as const
 
 // OpenAI's Responses API surfaces reasoning summaries that start with a bolded
 // title line: "**Inspecting PR workflow**\n\n<body>". GitHub Copilot routes
@@ -20,7 +19,7 @@ export function isThinkingMode(value: unknown): value is ThinkingMode {
   return typeof value === "string" && (MODES as readonly string[]).includes(value)
 }
 
-// Cycle order matches the slash command: show → minimal → hide → show.
+// Cycle order matches the slash command: show → hide → show.
 export function nextThinkingMode(current: ThinkingMode): ThinkingMode {
   const idx = MODES.indexOf(current)
   return MODES[(idx + 1) % MODES.length] ?? "show"
@@ -33,7 +32,7 @@ export function useThinkingMode() {
   // The KVProvider only renders children once kv.ready, so reads here are safe.
   const hadStored = kv.get("thinking_mode") !== undefined
   const legacy = kv.get("thinking_visibility")
-  const [stored, setStored] = kv.signal<ThinkingMode>("thinking_mode", "minimal")
+  const [stored, setStored] = kv.signal<ThinkingMode>("thinking_mode", "hide")
 
   // The kv signal exposes its setter typed as `Setter<T>` which carries Solid's
   // overload set; passing an updater fn through a property access loses the
@@ -47,21 +46,21 @@ export function useThinkingMode() {
 
   // Preserve previous experience for users who had explicitly toggled the
   // legacy `thinking_visibility` boolean. First-time users (no legacy key)
-  // get the new "minimal" default.
+  // get the new "hide" default (collapsed thinking).
   if (!hadStored) {
     if (legacy === true) set("show")
     else if (legacy === false) set("hide")
   }
 
+  if ((stored() as string) === "minimal") set("hide")
+
   const mode = createMemo<ThinkingMode>(() => {
-    if (Flag.OPENCODE_EXPERIMENTAL_MINIMAL_THINKING) return "minimal"
     const value = stored()
-    return isThinkingMode(value) ? value : "minimal"
+    return isThinkingMode(value) ? value : "hide"
   })
 
   return {
     mode,
     set,
-    locked: () => Flag.OPENCODE_EXPERIMENTAL_MINIMAL_THINKING === true,
   }
 }

+ 2 - 2
packages/opencode/src/cli/cmd/tui/feature-plugins/system/session-v2.tsx

@@ -392,7 +392,7 @@ function AssistantReasoning(props: {
   const thinking = useThinkingMode()
   const [expanded, setExpanded] = createSignal(false)
   const content = createMemo(() => props.part.text.replace("[REDACTED]", "").trim())
-  const inMinimal = createMemo(() => thinking.mode() === "minimal")
+  const inMinimal = createMemo(() => thinking.mode() === "hide")
   // v2 reasoning parts have no per-part `time.end` (see SessionMessageAssistantReasoning
   // in the v2 SDK); we settle on parent-message completion instead.
   const isDone = createMemo(() => props.completedAt() !== undefined)
@@ -404,7 +404,7 @@ function AssistantReasoning(props: {
   }
 
   return (
-    <Show when={content() && thinking.mode() !== "hide"}>
+    <Show when={content()}>
       <Switch>
         <Match when={!inMinimal() || expanded()}>
           <box

+ 8 - 19
packages/opencode/src/cli/cmd/tui/routes/session/index.tsx

@@ -218,7 +218,7 @@ export function Session() {
   const [conceal, setConceal] = createSignal(true)
   const thinking = useThinkingMode()
   const thinkingMode = thinking.mode
-  const showThinking = createMemo(() => thinkingMode() !== "hide")
+  const showThinking = createMemo(() => true)
   const [timestamps, setTimestamps] = kv.signal<"hide" | "show">("timestamps", "hide")
   const [showDetails, setShowDetails] = kv.signal("tool_details_visibility", true)
   const [showAssistantMetadata, _setShowAssistantMetadata] = kv.signal("assistant_metadata_visibility", true)
@@ -689,9 +689,8 @@ export function Session() {
     {
       title: (() => {
         const next = nextThinkingMode(thinkingMode())
-        if (next === "minimal") return "Switch thinking to minimal"
-        if (next === "hide") return "Hide thinking"
-        return "Show thinking"
+        if (next === "hide") return "Collapse thinking"
+        return "Expand thinking"
       })(),
       value: "session.toggle.thinking",
       category: "Session",
@@ -700,16 +699,6 @@ export function Session() {
         aliases: ["toggle-thinking"],
       },
       run: () => {
-        // Env override forces minimal for the process. Updating KV here would
-        // silently diverge from what's rendered; tell the user instead.
-        if (thinking.locked()) {
-          toast.show({
-            message: "Thinking mode is locked to minimal by OPENCODE_EXPERIMENTAL_MINIMAL_THINKING",
-            variant: "info",
-          })
-          dialog.clear()
-          return
-        }
         thinking.set(nextThinkingMode(thinkingMode()))
         dialog.clear()
       },
@@ -1512,7 +1501,7 @@ const PART_MAPPING = {
 function ReasoningPart(props: { last: boolean; part: ReasoningPart; message: AssistantMessage }) {
   const { theme, subtleSyntax } = useTheme()
   const ctx = use()
-  // Collapsed by default in minimal mode: a single line throughout, so the
+  // Collapsed by default in hide mode: a single line throughout, so the
   // layout never shifts. Click to open the full markdown block, click to close.
   const [expanded, setExpanded] = createSignal(false)
 
@@ -1523,7 +1512,7 @@ function ReasoningPart(props: { last: boolean; part: ReasoningPart; message: Ass
   // Reasoning is finalized when the server sets `time.end` (see processor.ts).
   // Flips independently of the parent message completing.
   const isDone = createMemo(() => props.part.time.end !== undefined)
-  const inMinimal = createMemo(() => ctx.thinkingMode() === "minimal")
+  const inMinimal = createMemo(() => ctx.thinkingMode() === "hide")
   const duration = createMemo(() => {
     const end = props.part.time.end
     return end === undefined ? 0 : Math.max(0, end - props.part.time.start)
@@ -1539,10 +1528,10 @@ function ReasoningPart(props: { last: boolean; part: ReasoningPart; message: Ass
   }
 
   return (
-    <Show when={content() && ctx.thinkingMode() !== "hide"}>
+    <Show when={content()}>
       <Switch>
         <Match when={!inMinimal() || expanded()}>
-          {/* Full markdown block: `show` mode, or `minimal` after the user opens it. */}
+          {/* Full markdown block: `show` mode, or `hide` after the user opens it. */}
           <box
             id={"text-" + props.part.id}
             paddingLeft={2}
@@ -1558,7 +1547,7 @@ function ReasoningPart(props: { last: boolean; part: ReasoningPart; message: Ass
               drawUnstyledText={false}
               streaming={true}
               syntaxStyle={subtleSyntax()}
-              content={(inMinimal() ? "▼ " : "") + "_Thinking:_ " + content()}
+              content={(inMinimal() ? "▼ " : "") + (isDone() ? "_Thought:_ " : "_Thinking:_ ") + content()}
               conceal={ctx.conceal()}
               fg={theme.textMuted}
             />