Skip to content

fix: surface when a response is truncated by the output limit - #830

Merged
agegr merged 2 commits into
agegr:mainfrom
northwang-lucky:fix/surface-output-limit-truncation
Sep 19, 2026
Merged

agegr merged 2 commits into
agegr:mainfrom
northwang-lucky:fix/surface-output-limit-truncation

Conversation

@northwang-lucky

Copy link
Copy Markdown
Contributor

The problem (observed in real use). When an assistant turn ends on stopReason: "length" — e.g. a thinking model spending the entire output budget on reasoning — the conversation stops with no visible answer and no warning; the UI just sits on the last thinking block. It reads exactly like a hung session. We hit this with a 128K-token reasoning-only truncation on a long session: the model never produced a final message, and nothing in the UI said so.

The fix. Mirrors the existing provider-error handling:

  • getAssistantTruncationNotice() in lib/message-display.ts — a pure function beside getAssistantErrorMessage(): non-streaming + stopReason === "length" -> a short notice. stopReason reaches MessageView intact on both the live event path (normalizeToolCalls preserves it through the spread) and the history path (verified).
  • Rendered as an inline notice beside the existing error banner (MessageView), including the thinking-only-truncated case; classified alongside errors in the final-answer logic (ChatWindow) so the message is never silently dropped.

Notice copy: "This response was cut off after reaching the model's output limit. Send a follow-up to continue."

Tests. 5 new cases (3 on the pure function covering the discriminating states, 2 real-render cases on MessageView including thinking-only). tsc / eslint clean; 1025 tests pass on this branch.

Found while building the programmatic dispatch API discussed in #829 — unrelated to that design, so it ships standalone.

@agegr agegr left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Real gap: a stopReason: "length" turn with reasoning-only output looked exactly like a hung session. Mirroring the provider-error path is the right shape, and the ChatWindow final-answer classification fix means the message is not silently dropped.

One change pushed to the branch: the notice copy was a hardcoded English string in lib/message-display.ts; all UI copy here goes through i18n. The helper is now isAssistantTruncated(message, opts): boolean and MessageView renders t("chat.truncatedByOutputLimit") (en / zh-CN / zh-TW added). Tests adjusted; the render tests still assert the English copy through I18nProvider.

Merged current main; tsc, eslint, and message-display / MessageView / ChatWindow tests pass. Approving.

northwang-lucky and others added 2 commits September 19, 2026 20:46
- Add getAssistantTruncationNotice() pure function mirroring getAssistantErrorMessage()
- Render a yellow inline banner on assistant messages with stopReason=length
- Fix the empty-content guard so thinking-only truncated messages are not hidden
- Fix ChatWindow finalAnswerMessage classification to treat truncation as terminal
- Add 5 test cases (3 pure-function, 2 component-rendering) for the new seam
…stantTruncated

Co-authored-by: Cursor <cursoragent@cursor.com>
@agegr
agegr force-pushed the fix/surface-output-limit-truncation branch from 82bab97 to 09b4d97 Compare September 19, 2026 12:49
@agegr
agegr merged commit c844973 into agegr:main Sep 19, 2026
2 checks passed
lclichen pushed a commit to lclichen/pi-web that referenced this pull request Sep 21, 2026
)

* feat: surface when a response is truncated by the output limit

- Add getAssistantTruncationNotice() pure function mirroring getAssistantErrorMessage()
- Render a yellow inline banner on assistant messages with stopReason=length
- Fix the empty-content guard so thinking-only truncated messages are not hidden
- Fix ChatWindow finalAnswerMessage classification to treat truncation as terminal
- Add 5 test cases (3 pure-function, 2 component-rendering) for the new seam

* Move the truncation notice copy into i18n; expose the check as isAssistantTruncated

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Alex Yang <agegcn@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants