You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug] Turns whose final assistant message has no text block render no branch or copy actions at all
#7215
There are turns from which a session cannot be forked at all, and the UI gives no hint why:
If a turn's final assistant message contains no non-empty text block (for example a length stop that produced only a reasoning block), closing is null, and TurnTailNodeView returns before rendering MessageIconActions — so neither the branch nor the copy action exists in the DOM.
If a turn ended with reason.kind === "error", branchUnavailable is true and the branch action renders but is inert.
In the attached session that is turns 20–26 of 26: the last seven turns have no reachable fork point. The remaining turns are not the latest turn, so their actions are revealed only on hover.
Environment
dsh 0.1.6-alpha.2, commit ddefc45fbc7f8e46dd73185e68295696d1297887, web profile
Drive a turn to a length stop that returns a reasoning block only — e.g. the five one-token turns in the attached log (turns 22–26), or any truncated reasoning-only reply.
Look at that turn's footer: there is no branch icon and no copy icon. The whole action row is missing.
Separately, end a turn with a runtime error (turns 20–21 in the log). The branch icon renders but aria-disabled is set and clicking does nothing.
hasText requires block.kind === 'text' && block.text.trim() !== ''. A reasoning-only assistant message fails it, so closing is null — even though a finalized assistant node does exist (finalized includes it).
The early return skips the entire <MessageIconActions … onBranch={…} /> block, so the user loses copy and branch on exactly the turns that are most likely to be unusable — a truncated turn is the moment you most want to branch away from it.
For error turns, latestTranscriptSeq is advanced past the closing node by the error event itself:
so branchUnavailable is true and the control is dead.
Expected behavior
Keep the action row rendered whenever a finalized assistant node exists, independent of whether it produced text; branchUnavailable can stay for the enabled/disabled decision without removing the row.
On a turn that ended in an error, the fork target should be the last transcript seq, not "nothing" — that turn is precisely where a user wants to retry from.
Some affordance should explain where forking is possible (the current rule — "last message of a completed turn" — is only discoverable from a hover tooltip).
https://gist.github.com/gorban/4725c87390cb391047a2f14b56b98d28 — EVIDENCE.md section 4; the session log shows the reasoning-only assistant messages for turns 22–26 and the two reason.kind: "error" turn ends for turns 20–21.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Summary
There are turns from which a session cannot be forked at all, and the UI gives no hint why:
lengthstop that produced only areasoningblock),closingisnull, andTurnTailNodeViewreturns before renderingMessageIconActions— so neither the branch nor the copy action exists in the DOM.reason.kind === "error",branchUnavailableis true and the branch action renders but is inert.In the attached session that is turns 20–26 of 26: the last seven turns have no reachable fork point. The remaining turns are not the latest turn, so their actions are revealed only on hover.
Environment
0.1.6-alpha.2, commitddefc45fbc7f8e46dd73185e68295696d1297887, web profilesession-2496881f-8d36-4ce6-93d9-1954a31930c7Reproduction
lengthstop that returns a reasoning block only — e.g. the five one-token turns in the attached log (turns 22–26), or any truncated reasoning-only reply.aria-disabledis set and clicking does nothing.Current behavior
packages/client/ui-chat/src/client/conversation-nodes/turn-tail.ts:hasTextrequiresblock.kind === 'text' && block.text.trim() !== ''. A reasoning-only assistant message fails it, soclosingisnull— even though a finalized assistant node does exist (finalizedincludes it).packages/client/ui-chat/src/client/chat/TurnTailNodeView.tsx:The early return skips the entire
<MessageIconActions … onBranch={…} />block, so the user loses copy and branch on exactly the turns that are most likely to be unusable — a truncated turn is the moment you most want to branch away from it.For error turns,
latestTranscriptSeqis advanced past the closing node by the error event itself:so
branchUnavailableis true and the control is dead.Expected behavior
branchUnavailablecan stay for the enabled/disabled decision without removing the row.Relation to existing reports
forkAt/forkSession), and I am not re-reporting it. This report is the separate defect that on some turns the control is never rendered or is unconditionally disabled, so the swallow is never even reached.Evidence bundle
https://gist.github.com/gorban/4725c87390cb391047a2f14b56b98d28—EVIDENCE.mdsection 4; the session log shows the reasoning-only assistant messages for turns 22–26 and the tworeason.kind: "error"turn ends for turns 20–21.All reactions