fix(tui): show encrypted reasoning status (#43578)

Co-authored-by: Aiden <rekram1-node@users.noreply.github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
This commit is contained in:
opencode-agent[bot]
2026-08-20 00:23:20 -05:00
committed by GitHub
parent 5ccb1e88e1
commit e0e9bd7d5f
+13 -20
View File
@@ -1595,6 +1595,7 @@ function ReasoningPart(props: { last: boolean; part: ReasoningPart; message: Ass
// OpenRouter encrypts some reasoning blocks; drop the placeholder. // OpenRouter encrypts some reasoning blocks; drop the placeholder.
return props.part.text.replace("[REDACTED]", "").trim() return props.part.text.replace("[REDACTED]", "").trim()
}) })
const opaque = createMemo(() => !content() && Boolean(props.part.metadata))
// Reasoning is finalized when the server sets `time.end` (see processor.ts). // Reasoning is finalized when the server sets `time.end` (see processor.ts).
// Flips independently of the parent message completing. // Flips independently of the parent message completing.
const isDone = createMemo(() => props.part.time.end !== undefined) const isDone = createMemo(() => props.part.time.end !== undefined)
@@ -1607,12 +1608,12 @@ function ReasoningPart(props: { last: boolean; part: ReasoningPart; message: Ass
const syntax = createSyntaxStyleMemo(() => generateSubtleSyntax(theme)) const syntax = createSyntaxStyleMemo(() => generateSubtleSyntax(theme))
const toggle = () => { const toggle = () => {
if (!inMinimal()) return if (!inMinimal() || opaque()) return
setExpanded((prev) => !prev) setExpanded((prev) => !prev)
} }
return ( return (
<Show when={content()}> <Show when={content() || opaque()}>
<box <box
ref={(el: BoxRenderable) => alwaysSeparate.add(el)} ref={(el: BoxRenderable) => alwaysSeparate.add(el)}
paddingLeft={3} paddingLeft={3}
@@ -1622,14 +1623,15 @@ function ReasoningPart(props: { last: boolean; part: ReasoningPart; message: Ass
> >
<box onMouseUp={toggle}> <box onMouseUp={toggle}>
<ReasoningHeader <ReasoningHeader
toggleable={inMinimal()} toggleable={inMinimal() && !opaque()}
open={!inMinimal() || expanded()} open={!inMinimal() || expanded()}
done={isDone()} done={isDone()}
title={summary().title} title={summary().title}
duration={isDone() ? Locale.duration(duration()) : undefined} duration={isDone() ? Locale.duration(duration()) : undefined}
encrypted={opaque()}
/> />
</box> </box>
<Show when={(!inMinimal() || expanded()) && summary().body}> <Show when={!opaque() && (!inMinimal() || expanded()) && summary().body}>
<box paddingLeft={inMinimal() ? 2 : 0} marginTop={1}> <box paddingLeft={inMinimal() ? 2 : 0} marginTop={1}>
<code <code
filetype="markdown" filetype="markdown"
@@ -1653,12 +1655,18 @@ function ReasoningHeader(props: {
done: boolean done: boolean
title: string | null title: string | null
duration?: string duration?: string
encrypted?: boolean
}) { }) {
const { theme } = useTheme() const { theme } = useTheme()
const fg = () => const fg = () =>
props.open props.open
? RGBA.fromValues(theme.warning.r, theme.warning.g, theme.warning.b, theme.thinkingOpacity) ? RGBA.fromValues(theme.warning.r, theme.warning.g, theme.warning.b, theme.thinkingOpacity)
: theme.warning : theme.warning
const completed = () => {
if (props.encrypted) return `Thought (encrypted)${props.duration ? ` · ${props.duration}` : ""}`
const detail = [props.title, props.duration].filter(Boolean).join(" · ")
return `${props.toggleable ? (props.open ? "- " : "+ ") : ""}Thought${detail ? `: ${detail}` : ""}`
}
return ( return (
<Switch> <Switch>
@@ -1669,22 +1677,7 @@ function ReasoningHeader(props: {
</Match> </Match>
<Match when={true}> <Match when={true}>
<text fg={fg()} wrapMode="none"> <text fg={fg()} wrapMode="none">
<Show when={props.toggleable}> {completed()}
<span>{props.open ? "- " : "+ "}</span>
</Show>
<span>Thought</span>
<Show when={props.title || props.duration}>
<span>: </span>
</Show>
<Show when={props.title}>
<span>{props.title}</span>
</Show>
<Show when={props.duration}>
<span>
{props.title ? " · " : ""}
{props.duration}
</span>
</Show>
</text> </text>
</Match> </Match>
</Switch> </Switch>