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
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1595,6 +1595,7 @@ function ReasoningPart(props: { last: boolean; part: ReasoningPart; message: Ass
// OpenRouter encrypts some reasoning blocks; drop the placeholder.
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).
// Flips independently of the parent message completing.
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 toggle = () => {
if (!inMinimal()) return
if (!inMinimal() || opaque()) return
setExpanded((prev) => !prev)
}
return (
<Show when={content()}>
<Show when={content() || opaque()}>
<box
ref={(el: BoxRenderable) => alwaysSeparate.add(el)}
paddingLeft={3}
@ -1622,14 +1623,15 @@ function ReasoningPart(props: { last: boolean; part: ReasoningPart; message: Ass
>
<box onMouseUp={toggle}>
<ReasoningHeader
toggleable={inMinimal()}
toggleable={inMinimal() && !opaque()}
open={!inMinimal() || expanded()}
done={isDone()}
title={summary().title}
duration={isDone() ? Locale.duration(duration()) : undefined}
encrypted={opaque()}
/>
</box>
<Show when={(!inMinimal() || expanded()) && summary().body}>
<Show when={!opaque() && (!inMinimal() || expanded()) && summary().body}>
<box paddingLeft={inMinimal() ? 2 : 0} marginTop={1}>
<code
filetype="markdown"
@ -1653,12 +1655,18 @@ function ReasoningHeader(props: {
done: boolean
title: string | null
duration?: string
encrypted?: boolean
}) {
const { theme } = useTheme()
const fg = () =>
props.open
? RGBA.fromValues(theme.warning.r, theme.warning.g, theme.warning.b, theme.thinkingOpacity)
: 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 (
<Switch>
@ -1669,22 +1677,7 @@ function ReasoningHeader(props: {
</Match>
<Match when={true}>
<text fg={fg()} wrapMode="none">
<Show when={props.toggleable}>
<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>
{completed()}
</text>
</Match>
</Switch>