Skip to content

fix(tui): copy reply text before empty assistant messages - #56287

Open
HootRock wants to merge 2 commits into
anomalyco:devfrom
HootRock:copy-reply-text
Open

HootRock wants to merge 2 commits into
anomalyco:devfrom
HootRock:copy-reply-text

Conversation

@HootRock

@HootRock HootRock commented Oct 17, 2026 •

Copy link
Copy Markdown

Issue for this PR

Closes #56281

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

/copy fails when an answer ends with an assistant message containing only reasoning, tools or blank text, even though its earlier message contains the reply.

Select the last text-bearing assistant message after the latest user prompt, respecting the existing revert cutoff. Completed compaction summaries remain eligible. This follows @fantisst's answer-block diagnosis; no argument features or plugin code are included. Synthetic-input turn boundaries retain their existing behavior. A current turn without copyable text now reports that directly.

How did you verify your code works?

AI-assisted implementation and independent local review on native Windows/Bun 1.4.2 with frozen dependencies:

  • Two retained real TUI cases cover fallback past a reasoning-only tail and refusal to copy a previous turn. Both pass; unchanged dev fails the fallback and updated error-toast expectations.
  • Five selected TUI modules pass 13 tests. The two retained cases also pass ten repetitions (20 passes).
  • TUI typecheck, scoped lint and test formatting pass.

Tests use fixture history and inspect the OSC52 writer payload. No live model, system clipboard, full repository suite or upstream CI validation was run.

reviewed and tested locally.

Screenshots / recordings

Command selection logic only; the tests drive the production TUI and assert the copied text.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Added by the opencode bot (AI-generated).

Related: #55924

@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good. I reproduced #56281 on the base with the issue's script, using a simulated model: a reply plus a tool call, then a step with only reasoning. /copy showed "No text content found…". With this change it copies the reply. The new tests pass here, and 5 of the 8 fail on the base. The TUI typecheck passes.

Public API impact: none. This only changes how the TUI /copy command picks the message to copy.

I left two non-blocking comments: the error toast wording now that the selection only finds messages with text, and the size of the new test file.

Related: #55924

Before

After

(msg.type === "compaction" && msg.status === "completed" && msg.summary.trim() !== ""),
)
if (!lastAssistantMessage) {
toast.show({ message: "No assistant messages found", variant: "error" })

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Now that the selection only finds messages with non-blank text, this toast also shows when the current turn has assistant messages but none with text (e.g. a reasoning-only turn), and "No assistant messages found" is misleading there. Also, the if (!text) "No text content found in last assistant message" branch below can no longer run. Could you merge the two into one accurate message (e.g. "No reply text found in the last turn")?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Updated in be343af: the missing-selection toast is now "No reply text found in the last turn", and the unreachable empty-text branch is removed. The retained empty-turn case asserts that message and that no clipboard write occurs. Selection, revert filtering and compaction handling are unchanged.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks, I checked be343af and it handles both points. The toast now says "No reply text found in the last turn", the unreachable empty-text branch is gone, and the test is down to two cases (reasoning-only last message, empty current turn). The selection logic hasn't changed since the version I verified. Nothing more from me.

@@ -0,0 +1,158 @@
import { expect, spyOn, test } from "bun:test"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is 158 lines of tests for a 12-line fix, and each of the 8 cases starts the whole TUI app. Could you keep only the core cases, e.g. a reasoning- or tool-only tail falls back to the earlier text, and an empty current turn does not copy the previous turn? Dropping the file would also be fine; the fix is small enough not to need it.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Reduced in be343af from eight full-app cases to the two core cases you suggested: fallback past a reasoning-only tail and no copy from a previous turn. The file is now 83 lines, with two app fixtures instead of eight. The original broader matrix is retained in my local evidence only.

The five selected TUI modules now pass 13 tests, and the retained pair passes ten repetitions (20 passes). TUI typecheck, scoped lint and test formatting pass. No full repository suite or upstream CI pass is claimed.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks, the trimmed test looks good. Its two cases (falling back past a reasoning-only last message, and no copy from an earlier turn) cover the fix, and each starts the app only once. Nothing more from me on the tests.

This branch has not been deployed

No deployments
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.

tui: /copy misses final reply text when the last assistant message has no text part (+ args proposal)

1 participant