tui: help users read thinking blocks and trust todo syncs

This commit is contained in:
Dax Raad
2025-11-10 20:33:53 -05:00
parent 1bc3e92376
commit dea668b0ea

View File

@@ -17,7 +17,7 @@ import { useRoute, useRouteData } from "@tui/context/route"
import { useSync } from "@tui/context/sync" import { useSync } from "@tui/context/sync"
import { SplitBorder } from "@tui/component/border" import { SplitBorder } from "@tui/component/border"
import { useTheme } from "@tui/context/theme" import { useTheme } from "@tui/context/theme"
import { BoxRenderable, ScrollBoxRenderable, addDefaultParsers } from "@opentui/core" import { BoxRenderable, ScrollBoxRenderable, TextAttributes, addDefaultParsers } from "@opentui/core"
import { Prompt, type PromptRef } from "@tui/component/prompt" import { Prompt, type PromptRef } from "@tui/component/prompt"
import type { AssistantMessage, Part, ToolPart, UserMessage, TextPart, ReasoningPart } from "@opencode-ai/sdk" import type { AssistantMessage, Part, ToolPart, UserMessage, TextPart, ReasoningPart } from "@opencode-ai/sdk"
import { useLocal } from "@tui/context/local" import { useLocal } from "@tui/context/local"
@@ -950,14 +950,14 @@ const PART_MAPPING = {
function ReasoningPart(props: { last: boolean; part: ReasoningPart; message: AssistantMessage }) { function ReasoningPart(props: { last: boolean; part: ReasoningPart; message: AssistantMessage }) {
const { theme, syntax } = useTheme() const { theme, syntax } = useTheme()
const ctx = use() const ctx = use()
const content = createMemo(() => props.part.text.trim())
return ( return (
<Show when={props.part.text.trim()}> <Show when={content()}>
<box <box
id={"text-" + props.part.id} id={"text-" + props.part.id}
paddingLeft={2} paddingLeft={2}
marginTop={1} marginTop={1}
flexDirection="row" flexDirection="column"
gap={1}
border={["left"]} border={["left"]}
customBorderChars={SplitBorder.customBorderChars} customBorderChars={SplitBorder.customBorderChars}
borderColor={theme.backgroundElement} borderColor={theme.backgroundElement}
@@ -967,7 +967,7 @@ function ReasoningPart(props: { last: boolean; part: ReasoningPart; message: Ass
drawUnstyledText={false} drawUnstyledText={false}
streaming={true} streaming={true}
syntaxStyle={syntax()} syntaxStyle={syntax()}
content={props.part.text.trim()} content={"_Thinking:_ " + content()}
conceal={ctx.conceal()} conceal={ctx.conceal()}
fg={theme.text} fg={theme.text}
/> />
@@ -1450,15 +1450,24 @@ ToolRegistry.register<typeof TodoWriteTool>({
render(props) { render(props) {
const { theme } = useTheme() const { theme } = useTheme()
return ( return (
<box> <>
<For each={props.input.todos ?? []}> <Show when={!props.input.todos?.length}>
{(todo) => ( <ToolTitle icon="⚙" fallback="Updating todos..." when={true}>
<text style={{ fg: todo.status === "in_progress" ? theme.success : theme.textMuted }}> Updating todos...
[{todo.status === "completed" ? "✓" : " "}] {todo.content} </ToolTitle>
</text> </Show>
)} <Show when={props.metadata.todos?.length}>
</For> <box>
</box> <For each={props.input.todos ?? []}>
{(todo) => (
<text style={{ fg: todo.status === "in_progress" ? theme.success : theme.textMuted }}>
[{todo.status === "completed" ? "✓" : " "}] {todo.content}
</text>
)}
</For>
</box>
</Show>
</>
) )
}, },
}) })