feat(web): add configurable queue/steer follow-up behavior#1479
feat(web): add configurable queue/steer follow-up behavior#1479leonardoxr wants to merge 14 commits intopingdotgg:mainfrom
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
I want this behavior to be server side. I shouldn't need to keep my client open for the queing to work |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 11ec9d73f3
ℹ️ 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".
|
|
@juliusmarminge A question about the Steer behavior. Should the steer wait for the AI to finish its "step/thinking/action" before sending(like claude code does) or should it interrupt indeed. Or, should it also be an option? Like Queue / Steer / "Force Steer" |
|
Follow-up update on this PR after the review and manual testing: I moved queued follow-ups out of the client draft store and into server-owned orchestration state. What changed:
I also fixed two regressions uncovered while testing:
Coverage added/updated for:
Validation I ran before pushing this update:
|
|
Addressed the remaining review items in this branch:
Validation rerun after these fixes:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 775ee4286c
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cace8fccce
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f4587c9d87
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 06d68cdfaf
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 46f95dac9d
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d92e28bc8e
ℹ️ 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".
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| }), | ||
| ), | ||
| ); | ||
| } |
There was a problem hiding this comment.
Double dispatch when both remove and send-failed fail
Medium Severity
When thread.turn.start succeeds but the subsequent thread.queued-follow-up.remove dispatch fails, the reactor tries to record a send-failed event. If that nested dispatch also fails, the error is swallowed by Effect.catchCause. The queued follow-up remains in the queue without a lastSendError marker. Once the dispatched turn completes, hasQueuedDispatchSettled returns true, the pendingQueuedDispatchByThreadId entry is cleared, and canDispatchQueuedFollowUp sees no error — so the reactor dispatches the same follow-up again, creating a duplicate turn.
Additional Locations (1)
|
|
||
| it.live("replays queued follow-ups after orchestration restarts", () => | ||
| Effect.gen(function* () { | ||
| const rootDir = fs.mkdtempSync(path.join(os.tmpdir(), "t3-orchestration-queue-restart-")); |
There was a problem hiding this comment.
Integration test leaks temp directory on disk
Low Severity
The rootDir created via fs.mkdtempSync is never cleaned up. When rootDir is provided externally to makeOrchestrationIntegrationHarness, the scoped temp-directory cleanup from makeTempDirectoryScoped is skipped, and the harness dispose does not remove it. Each test run accumulates an orphaned temp directory under the OS temp folder.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f049043dd4
ℹ️ 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".
| })), | ||
| ); | ||
| return buildQueuedFollowUpDraft({ | ||
| prompt: trimmedPrompt, |
There was a problem hiding this comment.
Preserve inline terminal markers in follow-up snapshots
createFollowUpSnapshotFromComposer stores trimmedPrompt, which is derived via deriveComposerSendState and strips inline terminal-context placeholders. In running queue/steer flows this means prompts that referenced terminal context inline lose those markers before dispatch, so the sent text differs from normal send behavior and can change the user's intent (e.g., inline references disappear while only the trailing context block remains). Use a prompt representation that preserves/materializes inline context markers before snapshotting.
Useful? React with 👍 / 👎.


Closes #1462
Summary
Adds explicit follow-up behavior while a thread is already running.
Users can now choose a global
Follow-up behaviorsetting:Steer: send the follow-up as guidance for the active runQueue: hold the follow-up and auto-send it after the current run settlesThe composer also supports a one-off opposite behavior shortcut for a single message.
What changed
followUpBehaviorto client settings with a default ofsteerQueuevsSteerCtrl+Shift+EnterCmd+Shift+EnterWhy
This makes follow-up delivery explicit and predictable while a run is active, which is the core problem described in #1462.
Verification
bun fmtbun lintbun typecheckbun run test -- src/composerDraftStore.test.tsbun run test:browser -- src/components/ChatView.browser.tsx --testNamePattern "queued|follow-up"Media
Settings
Before
After
Before/after comparison
Preview
Note
Medium Risk
Adds new queued-follow-up persistence, projection logic, and an always-on reactor that can auto-dispatch turns after a run settles; mistakes could cause unexpected sends, attachment leaks, or projection/cleanup bugs. Includes a DB migration and new attachment normalization/validation paths in
wsServer, increasing surface area for regressions.Overview
Adds a persisted per-thread queued follow-up queue and a new
QueuedFollowUpReactorthat replays/auto-dispatches the queue head by issuingthread.turn.startand then removing it once the thread becomes sendable again (including after server restarts).Extends orchestration with new queued follow-up commands/events and full support across
decider, in-memoryprojector,ProjectionPipeline(including attachment pruning on revert/remove/upsert and touching threadupdatedAt), andProjectionSnapshotQueryso snapshots now includequeuedFollowUps.Updates
wsServerto normalize queued follow-up image attachments the same way as turn sends (persist data URLs, validate persisted ids are thread-scoped, and serve attachments by id), adds the newprojection_thread_queued_follow_upstable via migration019, and expands integration/unit/browser tests plus a harness option to control reactor startup.Written by Cursor Bugbot for commit f049043. This will update automatically on new commits. Configure here.
Note
Add configurable queue/steer follow-up behavior for running chat threads
followUpBehaviorsetting (queueorsteer, defaultsteer) that controls what happens when the user submits a message while a thread turn is running.QueuedFollowUp; a newQueuedFollowUpReactorautomatically dispatches the head queued follow-up when the thread becomes sendable.ComposerQueuedFollowUpsPanelUI with drag-and-drop reorder, edit, delete, and steer-now actions per queued follow-up.thread.queued-follow-up.{enqueue,update,remove,reorder,send-failed,send-error-cleared}), a new DB table (projection_thread_queued_follow_ups) via migration 19, and full decider/projector/projection-pipeline support.COMPOSER_DRAFT_STORAGE_VERSIONto 4, invalidating previously persisted composer drafts.Macroscope summarized f049043.