Skip to content

feat(desktop): add steer/queue follow-up messages while agent is busy#2004

Merged
src-opn merged 2 commits into
devfrom
add-followup-messages
May 29, 2026
Merged

feat(desktop): add steer/queue follow-up messages while agent is busy#2004
src-opn merged 2 commits into
devfrom
add-followup-messages

Conversation

@src-opn
Copy link
Copy Markdown
Collaborator

@src-opn src-opn commented May 29, 2026

Summary

While the agent is running, the composer now offers Steer, Queue, and an outline Stop instead of a single Stop button:

  • Steer — sends the message immediately. opencode accepts a mid-run user turn and injects it into the running loop (as a <system-reminder>), so the agent adjusts mid-task.
  • Queue — opencode has no server-side queue, so messages are held client-side and auto-sent once the session goes idle. Multiple queued messages are merged and delivered as a single message.
  • Stop — aborts the run (session.abort), styled as an outline button.

Queued messages appear in a panel above the composer (mirroring the question panel). Each entry has an X to remove it, and the panel hides when the queue is empty.

Keyboard behavior (only while busy)

  • Enter does not submit; it shakes the Steer/Queue buttons to prompt an explicit choice.
  • Escape arms a "Hit Escape again to stop the agent" message for 3s; a second Escape stops the agent.

Implementation notes

  • Steer/Queue are disabled until there's text; Stop is always active.
  • mergeDrafts concatenates queued drafts (text + parts + attachments) into one send; on failure the queue is restored.
  • Steered/queued messages render as normal user-message bubbles via the existing snapshot+SSE transcript path (no special styling). Note: there is no optimistic echo, so the bubble appears once the server echoes it back over SSE (sub-second).

Files

  • composer.tsx — Steer/Queue/Stop UI, shake + Escape-to-stop logic.
  • session-surface.tsxhandleSteer/handleQueue, local queue state, idle-drain effect, mergeDrafts.
  • queued-messages-panel.tsx — new panel listing queued messages with per-item remove.
  • index.cssanimate-shake keyframe/utility.
  • en.ts — new i18n keys (English is the fallback for all locales).

Testing

Commands run from apps/app:

  • pnpm typecheck — passes.
  • pnpm build — succeeds.

I have not captured an end-to-end video/screenshots yet. To reproduce manually: start a session, send a prompt, and while the agent is streaming, type a follow-up and try Steer / Queue / Stop, plus Enter (shake) and Escape-Escape (stop).

Replace the single Stop button with Steer, Queue, and an outline Stop when
the agent is running. Steer sends immediately (opencode injects it mid-turn);
Queue holds messages client-side and auto-sends them merged into one message
once the session goes idle. Enter while busy shakes the buttons to prompt an
explicit choice, and Escape arms a "hit Escape again to stop" confirmation.

Queued messages show in a panel above the composer (mirroring the question
panel) where each can be removed; the panel hides when empty.
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 29, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
openwork-app Ready Ready Preview, Comment May 29, 2026 3:37pm
openwork-den Ready Ready Preview, Comment May 29, 2026 3:37pm
openwork-den-worker-proxy Ready Ready Preview, Comment May 29, 2026 3:37pm
openwork-landing Ready Ready Preview, Comment, Open in v0 May 29, 2026 3:37pm

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 5 files

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread apps/app/src/react-app/domains/session/surface/session-surface.tsx Outdated
The panel labels filtered out empty (attachment-only) drafts, so the remove
action could target the wrong queued draft. Map one label per draft instead,
falling back to an attachment count when there's no text. Also drop an unused
i18n key.
@src-opn
Copy link
Copy Markdown
Collaborator Author

src-opn commented May 29, 2026

CI test failures: pre-existing / infra, not from this PR

The OpenWork Tests job fails with Timed out waiting for /global/health: fetch failed — the embedded opencode server didn't finish booting in the e2e harness. This is not related to this PR:

Local verification on this branch:

  • pnpm typecheck — passes
  • pnpm build — succeeds
  • node scripts/i18n-audit.mjs — no dangling/dynamic key errors

Fixed cubic's finding (index alignment)

cubic correctly flagged that queuedMessages filtered out empty (attachment-only) drafts before rendering, breaking index alignment with queuedDrafts so the remove action could target the wrong entry. Fixed in 20164db by mapping one label per draft (no filtering), with an attachment-count fallback when there's no text. Removed an unused i18n key too.

@src-opn src-opn merged commit 411f584 into dev May 29, 2026
9 of 10 checks passed
src-opn added a commit that referenced this pull request May 29, 2026
* feat(app): add new message list

* feat(desktop): add steer/queue follow-up messages while agent is busy (#2004)

* feat(desktop): add steer/queue follow-up messages while agent is busy

Replace the single Stop button with Steer, Queue, and an outline Stop when
the agent is running. Steer sends immediately (opencode injects it mid-turn);
Queue holds messages client-side and auto-sends them merged into one message
once the session goes idle. Enter while busy shakes the buttons to prompt an
explicit choice, and Escape arms a "hit Escape again to stop" confirmation.

Queued messages show in a panel above the composer (mirroring the question
panel) where each can be removed; the panel hides when empty.

* fix(desktop): keep queued-message labels index-aligned with drafts

The panel labels filtered out empty (attachment-only) drafts, so the remove
action could target the wrong queued draft. Map one label per draft instead,
falling back to an attachment count when there's no text. Also drop an unused
i18n key.

---------

Co-authored-by: Source Open <gh2@mcadam.io>
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.

1 participant