Skip to content

Commit 73eb998

Browse files
author
kostiantyn-kugot
committed
fix: hide empty intermediate assistant messages in TUI
When using the Responses API, intermediate assistant messages with finish reason "other" were rendering empty footer bars and blank space. Two changes: 1. Add "other" to the excluded finish reasons in final() to align with the prompt loop logic that treats "other" as non-terminal. 2. Add a reactive visible() memo that hides the entire AssistantMessage when no parts would render and no footer/error is shown.
1 parent 168d7a9 commit 73eb998

File tree

1 file changed

+24
-4
lines changed
  • packages/opencode/src/cli/cmd/tui/routes/session

1 file changed

+24
-4
lines changed

packages/opencode/src/cli/cmd/tui/routes/session/index.tsx

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,7 +1349,7 @@ function AssistantMessage(props: { message: AssistantMessage; parts: Part[]; las
13491349
const model = createMemo(() => Model.name(ctx.providers(), props.message.providerID, props.message.modelID))
13501350

13511351
const final = createMemo(() => {
1352-
return props.message.finish && !["tool-calls", "unknown"].includes(props.message.finish)
1352+
return props.message.finish && !["tool-calls", "unknown", "other"].includes(props.message.finish)
13531353
})
13541354

13551355
const duration = createMemo(() => {
@@ -1362,8 +1362,28 @@ function AssistantMessage(props: { message: AssistantMessage; parts: Part[]; las
13621362

13631363
const keybind = useKeybind()
13641364

1365+
const footer = createMemo(
1366+
() => props.last || final() || props.message.error?.name === "MessageAbortedError",
1367+
)
1368+
1369+
const visible = createMemo(() => {
1370+
if (footer()) return true
1371+
if (props.message.error && props.message.error.name !== "MessageAbortedError") return true
1372+
for (const part of props.parts) {
1373+
if (part.type === "text" && (part as TextPart).text.trim()) return true
1374+
if (part.type === "tool" && (ctx.showDetails() || (part as ToolPart).state.status !== "completed")) return true
1375+
if (
1376+
part.type === "reasoning" &&
1377+
ctx.showThinking() &&
1378+
(part as ReasoningPart).text.replace("[REDACTED]", "").trim()
1379+
)
1380+
return true
1381+
}
1382+
return false
1383+
})
1384+
13651385
return (
1366-
<>
1386+
<Show when={visible()}>
13671387
<For each={props.parts}>
13681388
{(part, index) => {
13691389
const component = createMemo(() => PART_MAPPING[part.type as keyof typeof PART_MAPPING])
@@ -1402,7 +1422,7 @@ function AssistantMessage(props: { message: AssistantMessage; parts: Part[]; las
14021422
</box>
14031423
</Show>
14041424
<Switch>
1405-
<Match when={props.last || final() || props.message.error?.name === "MessageAbortedError"}>
1425+
<Match when={footer()}>
14061426
<box paddingLeft={3}>
14071427
<text marginTop={1}>
14081428
<span
@@ -1427,7 +1447,7 @@ function AssistantMessage(props: { message: AssistantMessage; parts: Part[]; las
14271447
</box>
14281448
</Match>
14291449
</Switch>
1430-
</>
1450+
</Show>
14311451
)
14321452
}
14331453

0 commit comments

Comments
 (0)