fix(tui): surface non-stop finish reasons in assistant header#25557
fix(tui): surface non-stop finish reasons in assistant header#25557truffle-dev wants to merge 1 commit into
Conversation
The assistant header status bar already shows " · interrupted" when the message ended with MessageAbortedError. When the model truncates the response itself (length limit, content filter, error), the message is still considered final but the user sees no indication of why the output stopped. This adds a similar suffix for length / content-filter / error finish reasons in both the TUI status bar and the markdown transcript export. Refs anomalyco#23928.
|
Thanks for your contribution! This PR doesn't have a linked issue. All PRs must reference an existing issue. Please:
See CONTRIBUTING.md for details. |
|
Thanks for updating your PR! It now meets our contributing guidelines. 👍 |
|
Just checking in on this one. Eight days since open, still mergeable, all CI green against current |
|
Automated PR Cleanup Thank you for contributing to opencode. Due to the high volume of PRs from users and AI agents, we periodically close older PRs using automated criteria so maintainers can focus review time on the most active and community-supported contributions. This PR was closed because it matched the following cleanup criteria:
PRs created within the last month are not affected by this cleanup. If you believe this PR was closed incorrectly, or if you are still actively working on it, please leave a comment explaining why it should be reopened. A maintainer can review and reopen it if appropriate. Thanks again for taking the time to contribute. |
Issue for this PR
Closes #23928
Type of change
What does this PR do?
The assistant header status bar already shows
· interruptedwhen the message ended withMessageAbortedError. When the model itself ends a response abnormally (length limit hit, content filter triggered, error during streaming),message.finishis set tolength/content-filter/error, the message is treated as final, and the user sees no indication of why the output stopped.In #23928 the reporter confirmed via SQL query against
partthat storage matches the TUI cut-off (text in storage ends at the same character the TUI shows). The stream/storage path is doing the right thing — the model is returning a truncated response and opencode persists exactly what was returned. Surfacing the cause in the header is the missing piece.Mirrors the existing
interruptedindicator pattern in both:AssistantMessageTUI status bar (packages/opencode/src/cli/cmd/tui/routes/session/index.tsx)formatAssistantHeadermarkdown transcript export (packages/opencode/src/cli/cmd/tui/util/transcript.ts)Header examples after this change:
▣ Plan · MiniMax M2.5 · 41.0s · truncated by length limit▣ Build · gpt-4o · 12.3s · stopped by content filter▣ Build · claude-3-5-sonnet · 5.4s · ended with error▣ Build · claude-3-5-sonnet · 5.4s(unchanged)How did you verify your code works?
bun test packages/opencode/test/cli/tui/transcript.test.ts— 29/29 pass (13 new cases covering length/content-filter/error/stop/tool-calls/other/unknown/undefined plus the metadata-disabled path)bun test packages/opencode— 150/150 passbun typecheckcleaninterruptedindicator path is unchanged (same<Show>block above the new one)Screenshots / recordings
Text-only TUI change — captured in the four header examples above.
Checklist