Skip to content

Comments

🤖 feat: add stream-end queue dispatch mode and send controls#2541

Open
ethanndickson wants to merge 15 commits intomainfrom
ethan/stream-end-queueing
Open

🤖 feat: add stream-end queue dispatch mode and send controls#2541
ethanndickson wants to merge 15 commits intomainfrom
ethan/stream-end-queueing

Conversation

@ethanndickson
Copy link
Member

Summary

Add dual queued-send dispatch behavior for chat messages and expose it in the UI. When sending during an active stream, users can now choose between dispatching at the next step boundary (tool-end) or after the current turn fully completes (turn-end).

Background

Queued sends previously always dispatched at step boundaries, which made it impossible to intentionally let the current stream complete naturally before dispatching the queued message.

Implementation

  • Added queueDispatchMode ("tool-end" | "turn-end") to send options schema and queue plumbing.
  • Updated queue semantics so mixed batches prioritize tool-end behavior.
  • Gated early-stop/queued-dispatch behavior in session handling so turn-end does not trigger step-boundary dispatch.
  • Added keybind behavior:
    • Enter → send/queue as tool-end
    • Ctrl/Cmd+Enter → send/queue as turn-end
  • Promoted dispatch mode to a first-class frontend callback signal (onMessageSent(dispatchMode)), wired through ChatInput/ChatPane/chatCommands.
  • Fixed auto-background policy: foreground bash auto-background now runs only for tool-end sends.
  • Added SendModeDropdown in chat controls using inline rendering (test-friendly), with keybind chips and outside-click/Escape close.
  • Iterated UI behavior based on review:
    • dropdown sits to the right of send button,
    • compact caret styling,
    • wider popup + no wrapping,
    • caret always visible in workspace mode,
    • caret disabled when unavailable (not streaming / empty input / cannot send).

Validation

  • make static-check
  • make typecheck
  • bun test ./tests/ui/chat/sendModeDropdown.test.ts
  • bun test ./tests/ui/compaction/compaction.test.ts
  • bun test src/browser/utils/ui/keybinds.test.ts
  • bun test src/node/services/messageQueue.test.ts

Risks

  • Main risk area is chat send-control UX around disabled/visible states while stream and input state change quickly.
  • Coverage includes targeted UI integration tests for dropdown behavior and backgrounding semantics, plus queue and keybind unit tests.

Generated with mux • Model: openai:gpt-5.3-codex • Thinking: xhigh • Cost: $18.21

Keep the send-mode caret always visible in workspace chat while disabled whenever it would previously be hidden (not streaming) or unusable (empty input / cannot send). Also shrink the caret icon slightly and update UI tests for the new visibility contract.

---

_Generated with `mux` • Model: `openai:gpt-5.3-codex` • Thinking: `xhigh` • Cost: `$18.21`_

<!-- mux-attribution: model=openai:gpt-5.3-codex thinking=xhigh costs=18.21 -->
@ethanndickson
Copy link
Member Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c6c189a044

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Merge latest `origin/main` into `ethan/stream-end-queueing` and resolve conflicts in chat send controls and queue dispatch internals.

Resolved conflict files:
- src/browser/components/ChatInput/index.tsx
- src/browser/components/ChatPane.tsx
- src/node/services/messageQueue.ts

---

_Generated with `mux` • Model: `openai:gpt-5.3-codex` • Thinking: `xhigh` • Cost: `$18.21`_

<!-- mux-attribution: model=openai:gpt-5.3-codex thinking=xhigh costs=18.21 -->
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0906054579

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson
Copy link
Member Author

@codex review

Addressed the previous review feedback:

  • Made MessageQueue.addInternal() dispatch-mode updates transactional, so rejected enqueue attempts no longer mutate the existing queued mode.
  • Added regression tests for the rejected compaction and rejected agent-skill paths to assert mode/messages remain unchanged.
  • Removed the stale enableAutoRetryPreference merge leftover in ChatPane that was breaking typecheck.

Validation run locally: bun test src/node/services/messageQueue.test.ts, make typecheck, and make static-check all pass.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f6bd8d6272

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson
Copy link
Member Author

@codex review

Latest push propagates the user's selected queue dispatch mode through /compact command execution:

  • Extended executeParsedCommand to accept queueDispatchMode and forward it from handleSend overrides.
  • Replaced the hardcoded onMessageSent?.("tool-end") in the compact success branch with the actual selected mode, so Ctrl/Cmd+Enter ("Send after turn") correctly skips auto-backgrounding foreground bash.
  • Threaded the mode into commandSendMessageOptions so backend queued sends also honor it.
  • Added a regression test in compaction.test.ts: /compact with Ctrl+Enter (turn-end) does NOT auto-background foreground bash — verified it fails without the production fix and passes with it.

Local validation: make typecheck ✅, make static-check ✅, bun test tests/ui/compaction/compaction.test.ts ✅ (8 pass, 1 skip, 0 fail).

chatgpt-codex-connector[bot]

This comment was marked as resolved.

@ethanndickson
Copy link
Member Author

@codex review

Latest push (0c9365d36): gate send mode dropdown by sendability and harden UI tests

Production fix:

  • Introduced canChooseDispatchMode = canInterrupt && canSend as the single derived state for dropdown enablement
  • Removed the extra !hasTypedText gate that blocked non-text sendable drafts (attachment-only, review-only) from choosing dispatch mode during streaming
  • canSend already covers hasTypedText || hasImages || hasReviews, so this aligns dropdown with send button semantics

Test stabilization:

  • Added openSendModeMenu() helper that wraps click in act() and waits for aria-expanded="true" — fixes the ~70% flake rate on "dropdown menu shows labels and keybind chips"
  • Previously-flaky test now passes 5/5 in loop
  • Added regression test: "dropdown enabled with review-only draft during streaming (no typed text)" — seeds attached review via persisted state, verifies dropdown enables without typed text

Validation: typecheck ✓, all 6 sendModeDropdown tests pass, 5/5 flake loop ✓, 9 compaction tests pass

@ethanndickson
Copy link
Member Author

@codex review

Resolved the P2 thread — the latest commit 0c9365d36 directly addresses that comment by replacing !hasTypedText with canChooseDispatchMode = canInterrupt && canSend. Please re-review.

@chatgpt-codex-connector
Copy link

Codex Review: Didn't find any major issues. Hooray!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

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