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] Copy button on a turn only copies the last text-bearing step — mid-turn prose and deliverable file links are silently dropped
#11829
Version:@deepseek-ai/dsh0.2.1-rc.2 (Web GUI, macOS, Electron shell)Related:#6254, #8002, #7215, #9129, and #11780 (filed 2026-11-01, a different defect on the same copy path — inline code gains stray newlines when a message body is copied)
Summary
On a long-running turn, the copy action at the tail of the turn writes onlythe last assistant step that contains a text blockto the clipboard. Every earlier user-facing paragraph from the same turn is dropped, and so are the file paths frompresentdeliverable cards.
This is the copy-side face of the folding bug reported in #6254 / #8002. Those reports cover what isdisplayed; nobody has yet reported what the copy buttonproduces, which is the more damaging case because the user has no visible signal that text is missing — the clipboard just looks short.
Repro
Ask for a task that produces several user-facing paragraphs within a single turn, with tool calls interleaved, and that ends by callingpresentto deliver a document.
Wait for the turn to finish.
Click the copy button at the tail of the turn.
Paste into a text editor.
Actual: only the closing sentence is pasted. Expected: the whole answer for that turn — every assistant text block, plus the delivered file paths.
Measured on a real session
One turn (turn 18) contained four assistant text blocks and seven tool calls. The log (session.v4.jsonl.zstd) holds all of it; the clipboard got the last block only:
step | text length | content | reaches clipboard
-- | -- | -- | --
1 | 40 chars | "let me measure the data first…" | no
4 | 71 chars | "one safety step before I write the table…" | no
7 | 2185 chars | the actual deliverable summary: a stage table, a disk map, a three-tier cleanup menu, and the inline Markdown link to the delivered document | no
8 | 87 chars | "the document has been delivered to you… I won't act on the cleanup without your say-so." | yes — this only
So the copy result keeps the sentence that merelypoints atthe work, and loses the work itself, including the file link.
Where it comes from
@deepseek-ai/dsh-client-ui-chat/lib/client.js:
js
// turn tail: which node is the copy sourceconst closing = finalized.findLast(hasText) ?? null; // :11100 — last step with non-empty text only// the copy actiontext: assistantText(closing.blocks) // :6994// and the extractorfunction assistantText(blocks) { // :6919 return blocks.flatMap((block) => (block.kind === "text" ? [block.text] : [])).join("");}
assistantTextmerges blockswithin one step, but a tool call ends a step, so a turn that interleaves prose and tool calls necessarily spans several steps — andfindLastkeeps only the final one. The filterkind === "text"additionally excludes reasoning, tool calls, tool results, images, and the file paths carried by apresentdeliverable card (a card is not a text block).
hasTextrequiresfinalNodeand a non-empty text block, which is the same predicate family behind the folding boundary in #6254 (latestAnswer()looks only atturn.steps.at(-1), and returnsnullwhen the last step is a tool call, leavinganswerAnchorSeq: null). Fixing the copy source and the fold anchor together would keep the two behaviours consistent.
Two secondary findings from the same code path
Manually selecting text does not work around it. Folded process groups are rendered withhidden="until-found"(chat:1271-1273, gated byprocessHidden = foldable && processMember && !processOpen), and collapsed reasoning and tool cards unmount their body entirely (content = expanded ? … : void 0). Non-rendered subtrees are unreachable to a selection, so expanding everything is the only manual route — and it has to be a global display setting (verboseis the sole policy withfoldCompletedTurns: false), not a per-turn affordance.
Per [Feature proposal] Preserve file links when copying selected response text #9129, even when the right paragraph is copied, an inline file reference loses its target: the filename renders as a preview button, so only the label reaches the clipboard. In this case the link happened to be plain inline Markdown and survived, which is how I noticed it was missing from the copy in the first place.
Version check I ran locally
I extractedfinalized.findLast(hasText),assistantText(closing.blocks)and theassistantTextbody from both 0.2.1-rc.2 and 0.2.1-rc.5 — byte-identical. So this is not a regression introduced in rc.2, and rc.3/rc.4/rc.5 do not change it.
I extracted the same three symbols from0.2.2-alpha.2and they are still unchanged:const closing = finalized.findLast(hasText) ?? null(:13149),text: assistantText(closing.blocks)(:8952), and the identicalassistantTextbody at:8892-8894with the same comment, "Collect visible prose from one Assistant lifecycle." So the turn-tail copy button behaves the same way in the alpha line too.
What 0.2.2-alpha.2 does add is adjacent, not this: a separateCopy Session as Markdownaction on the Session header (useSessionMarkdownCopy/menu.copyMarkdownin@deepseek-ai/dsh-session-log-export), a newdeliverable-file-referencesplugin, and folding that keeps all assistant text replies visible. Those give the user a correct way to get the whole transcript out, but none of them change what the turn-tail copy button puts on the clipboard — which is why I am filing this separately rather than as a "please upgrade" note.
Impact
Long agentic turns are exactly the ones where the intermediate paragraphs carry the substance (measurements, tables, commands, file paths). The copy button is what people reach for to hand that result to someone else, and it silently returns a fraction of it.
What I'd expect
The turn-tail copy action should serializeallassistant text blocks of the turn, in order, not just the last step.
Delivered file paths (and, where a card carries them, write/edit paths from the same turn) should be included, so the paste is self-contained without the folded detail rows.
If "final answer only" is the intended semantic, it should be opt-in, and the copy affordance should say so.
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.
Version:
@deepseek-ai/dsh0.2.1-rc.2 (Web GUI, macOS, Electron shell) Related: #6254, #8002, #7215, #9129, and #11780 (filed 2026-11-01, a different defect on the same copy path — inline code gains stray newlines when a message body is copied)Summary
On a long-running turn, the copy action at the tail of the turn writes only the last assistant step that contains a text block to the clipboard. Every earlier user-facing paragraph from the same turn is dropped, and so are the file paths from
presentdeliverable cards.This is the copy-side face of the folding bug reported in #6254 / #8002. Those reports cover what is displayed; nobody has yet reported what the copy button produces, which is the more damaging case because the user has no visible signal that text is missing — the clipboard just looks short.
Repro
presentto deliver a document.Actual: only the closing sentence is pasted. Expected: the whole answer for that turn — every assistant text block, plus the delivered file paths.
Measured on a real session
One turn (turn 18) contained four assistant text blocks and seven tool calls. The log (
session.v4.jsonl.zstd) holds all of it; the clipboard got the last block only:So the copy result keeps the sentence that merely points at the work, and loses the work itself, including the file link.
Where it comes from
@deepseek-ai/dsh-client-ui-chat/lib/client.js:assistantTextmerges blocks within one step, but a tool call ends a step, so a turn that interleaves prose and tool calls necessarily spans several steps — andfindLastkeeps only the final one. The filterkind === "text"additionally excludes reasoning, tool calls, tool results, images, and the file paths carried by apresentdeliverable card (a card is not a text block).hasTextrequiresfinalNodeand a non-empty text block, which is the same predicate family behind the folding boundary in #6254 (latestAnswer()looks only atturn.steps.at(-1), and returnsnullwhen the last step is a tool call, leavinganswerAnchorSeq: null). Fixing the copy source and the fold anchor together would keep the two behaviours consistent.Two secondary findings from the same code path
hidden="until-found"(chat:1271-1273, gated byprocessHidden = foldable && processMember && !processOpen), and collapsed reasoning and tool cards unmount their body entirely (content = expanded ? … : void 0). Non-rendered subtrees are unreachable to a selection, so expanding everything is the only manual route — and it has to be a global display setting (verboseis the sole policy withfoldCompletedTurns: false), not a per-turn affordance.Version check I ran locally
I extracted
finalized.findLast(hasText),assistantText(closing.blocks)and theassistantTextbody from both 0.2.1-rc.2 and 0.2.1-rc.5 — byte-identical. So this is not a regression introduced in rc.2, and rc.3/rc.4/rc.5 do not change it.I extracted the same three symbols from
0.2.2-alpha.2and they are still unchanged:const closing = finalized.findLast(hasText) ?? null(:13149),text: assistantText(closing.blocks)(:8952), and the identicalassistantTextbody at:8892-8894with the same comment, "Collect visible prose from one Assistant lifecycle." So the turn-tail copy button behaves the same way in the alpha line too.What 0.2.2-alpha.2 does add is adjacent, not this: a separate
Copy Session as Markdownaction on the Session header (useSessionMarkdownCopy/menu.copyMarkdownin@deepseek-ai/dsh-session-log-export), a newdeliverable-file-referencesplugin, and folding that keeps all assistant text replies visible. Those give the user a correct way to get the whole transcript out, but none of them change what the turn-tail copy button puts on the clipboard — which is why I am filing this separately rather than as a "please upgrade" note.Impact
Long agentic turns are exactly the ones where the intermediate paragraphs carry the substance (measurements, tables, commands, file paths). The copy button is what people reach for to hand that result to someone else, and it silently returns a fraction of it.
What I'd expect
All reactions