Skip to content

fix(input): gate stop branch on live processing state; never send ghost suggestion on stop click#343

Merged
chadbyte merged 1 commit intochadbyte:mainfrom
akuehner:upstream-pr/stop-honors-button-mode
Apr 29, 2026
Merged

fix(input): gate stop branch on live processing state; never send ghost suggestion on stop click#343
chadbyte merged 1 commit intochadbyte:mainfrom
akuehner:upstream-pr/stop-honors-button-mode

Conversation

@akuehner
Copy link
Copy Markdown
Contributor

Summary

Regression after #337 / 0753833 (ghost-text suggestion pattern). The sendBtn click handler in lib/public/modules/input.js checks hasSendableContent() and the ghost suggestion before the processing-stop branch, so clicking the visible Stop button while a ghost suggestion is queued sends the stale suggestion instead of stopping the SDK loop. Same shape on the Enter handler: pressing Enter while waiting on Claude adopts the ghost.

This PR adds a (ctx.processing && !hasSendableContent()) guard at the top of both handlers. In that state the click/Enter is a Stop (or no-op for Enter) and never adopts a ghost suggestion. Otherwise the original send paths run unchanged.

The guard predicates on live state rather than the button's stop CSS class — that class lives on a state machine that can drift on mobile (backgrounding, ws reconnect) and would wedge the input if its class got stuck.

Repro

  1. Send a message and wait until Claude is processing (button shows the stop square)
  2. A ghost suggestion is visible (textarea is empty, server has sent a suggestion)
  3. Click Stop

Before: the ghost suggestion is sent as a new message; the SDK loop keeps running.
After: the SDK loop stops; the ghost is not sent.

Test plan

  • Manual: stop with ghost visible -> SDK stops, suggestion not sent
  • Regression: idle + ghost + empty textarea -> click send-up sends ghost (unchanged)
  • Regression: typed text + processing -> button shows send -> click sends typed text (unchanged)
  • Regression: fix(input): prevent ghost-text suggestion from swallowing pasted content on Enter #337 path — pasted image + Enter sends image, not ghost (unchanged)
  • Manual mobile: send works after the SDK has gone processing->idle once

…st suggestion on stop click

Regression after chadbyte#337 / 0753833 (ghost-text suggestion pattern). The
sendBtn click handler checked hasSendableContent() and the ghost
suggestion before the processing-stop branch, so clicking the visible
Stop button while a ghost suggestion was queued sent the stale
suggestion instead of stopping the SDK loop. Same shape on the Enter
handler: pressing Enter while waiting on Claude adopted the ghost.

Both paths now check (ctx.processing && !hasSendableContent()) up front:
in that state the click/Enter is a Stop (or no-op for Enter) and never
adopts a ghost suggestion. Otherwise the original send paths run
unchanged.

Predicating on live state instead of the button's "stop" CSS class
avoids tying user-facing send behavior to the button-state machine in
app-connection.js, which can drift on mobile (backgrounding, ws
reconnect) and would wedge the input if its class got stuck.
@chadbyte chadbyte closed this Apr 29, 2026
@chadbyte chadbyte reopened this Apr 29, 2026
@chadbyte
Copy link
Copy Markdown
Owner

Reviewed and looks good — merging. Thanks!

(Side note: the earlier failing check was a flaw in our PR-checks workflow, not your code — the script it runs only existed on main and wasn't present at your PR's head. Fixed on main and the rerun came back green.)

@chadbyte chadbyte merged commit 6722ef5 into chadbyte:main Apr 29, 2026
1 of 2 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

This issue has been resolved in version 2.36.1-beta.3 (main).

To update, run:

npx clay-server@2.36.1-beta.3

-- Clay Deploy Bot

Build anything, with anyone, in one place.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants