feat(sessions): reorder and edit queued messages in place#3242
Conversation
Let users drag queued follow-ups to reorder them (the queue drains in array order, so the order shown is the order they send) and edit a queued message in the composer without pulling it out of the queue. - Add moveQueuedMessage and updateQueuedMessage store setters - Add SessionService.updateQueuedMessage mirroring enqueue normalization (cloud recomputes transport display + raw payload; local stores text) - Track the active edit target in sessionViewStore; the composer's next submit updates the message in place, falling back to a fresh send if it already drained or was discarded - Make each queued card a dnd-kit drag handle; highlight the card being edited with a cancel affordance Generated-By: PostHog Code Task-Id: 96d2978d-909b-4bbf-a45b-44ede597a1b8
|
Merging to
After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here |
|
React Doctor found 1 issue in 1 file · 1 warning. 1 warning
Reviewed by React Doctor for commit |
🖥️ macOS test build (Apple Silicon)A signed macOS build for this PR is ready to download and run. ⬇️ Open this run and download the Unzip it to get the This build is signed but not notarized, so macOS quarantines it on download and Gatekeeper reports "PostHog Code is damaged and can't be opened". That is the missing notarization, not a corrupt file — clear the quarantine flag once and it launches: xattr -dr com.apple.quarantine "/Applications/PostHog Code.app"Then open PostHog Code normally. (Fully notarized, double-click-to-run builds ship only from the tagged release pipeline.) Built from ec91f3d · rebuilds on each push while the |
|
hey @gantoine, what's the status of this one? |
|
i'm still wresting with the UX a bit, namely around multiple stacked prompts executing as sa group and cutting off the edit (racing to save before the prompt is sent) |
When a queued message is open for an in-place edit, it now acts as a drain boundary: on turn end the messages queued before it still send, but it and everything after stay queued until the edit is saved or cancelled. Saving/cancelling while the agent is already idle re-drains the now-unblocked queue. The "which message is being edited" fact moves from the UI view store into domain state (AgentSession.editingQueuedId) since it now gates the send behavior, with a pure sendableQueuePrefixLength() helper. The auto-drain paths pass stopAtEdited; cancel/recall still drain everything. Generated-By: PostHog Code Task-Id: 5cf31c6c-1ba0-4137-88c1-3a369f3acf36
Resolve QueuedMessageView conflict: keep main's font-medium text styling and drop the obsolete fadeColor prop (main refactored the collapsed-fade to a paint-only CSS mask, so the editing highlight no longer needs a matching background color). Generated-By: PostHog Code Task-Id: 5cf31c6c-1ba0-4137-88c1-3a369f3acf36
While editing a queued message in place, Escape now abandons the edit (clearing the hold and emptying the composer) instead of stopping the running turn. Cancel-edit takes priority over stop-run, and the escape hotkey is enabled whenever an edit is in progress — including while the agent is idle. Generated-By: PostHog Code Task-Id: 5cf31c6c-1ba0-4137-88c1-3a369f3acf36
The editing (purple) state collapsed shorter than the default state because its actions are all ghost icon buttons (fit-content height), with no fixed-height Steer button to anchor the row. Pin the row to min-h-6 so both states match. Also widen the action gap (gap-1 -> gap-2) and add breathing room after the "Editing in composer" label. Generated-By: PostHog Code Task-Id: 5cf31c6c-1ba0-4137-88c1-3a369f3acf36
Previously the whole queue was merged into a single prompt when the turn ended, so multiple queued messages landed in one turn. Drain just the head message instead (max: 1) — when that turn completes, the existing turn-end drain fires again for the next one, so the queue sends sequentially. The in-place edit boundary still applies: the cutoff is min(max, sendable-prefix). Cancel/recall paths still pull the whole queue into the composer. Generated-By: PostHog Code Task-Id: 5cf31c6c-1ba0-4137-88c1-3a369f3acf36
The quality job's `biome ci` failed on organizeImports: the new export sorts after `type SessionStatus` (case-sensitive S < s), not before. Generated-By: PostHog Code Task-Id: 5cf31c6c-1ba0-4137-88c1-3a369f3acf36
|
Reviews (1): Last reviewed commit: "fix(shared): sort sendableQueuePrefixLen..." | Re-trigger Greptile |
There was a problem hiding this comment.
Pull request overview
Adds interactive queue management to the Sessions queued-messages dock: users can drag queued follow-ups to reorder send order, and can edit a queued message “in place” (without removing it) while the queue drain respects an edit hold boundary.
Changes:
- Implement drag-to-reorder for queued messages using the existing
@dnd-kit/reactsortable pattern. - Implement in-place queued-message editing: mark an
editingQueuedId, route composer submit toSessionService.updateQueuedMessage, and provide cancel/highlight UX. - Update core/shared queue semantics: add edit-boundary drain logic (
sendableQueuePrefixLength,stopAtEdited,max) and add store setters + tests.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| packages/ui/src/features/sessions/sessionServiceHost.test.ts | Adds tests/mocks covering edit-hold release behavior and updated dequeue options. |
| packages/ui/src/features/sessions/hooks/useSessionCallbacks.ts | Routes composer submit to updateQueuedMessage when editing a queued item. |
| packages/ui/src/features/sessions/hooks/useReturnQueuedMessageToEditor.ts | Removes the old “pull from queue back to editor” hook (replaced by in-place edit). |
| packages/ui/src/features/sessions/hooks/useEditQueuedMessage.ts | New hooks to start/cancel in-place queued-message edits and restore content into composer. |
| packages/ui/src/features/sessions/components/SessionView.tsx | Plumbs “editing queued” state into the composer to support Escape-to-cancel editing. |
| packages/ui/src/features/sessions/components/session-update/QueuedMessageView.tsx | Updates queued-card UI: drag handle, edit/cancel affordances, and editing highlight state. |
| packages/ui/src/features/sessions/components/QueuedMessagesDock.tsx | Adds sortable drag/drop wrapper, edit/cancel wiring, and stale-edit cleanup. |
| packages/ui/src/features/sessions/components/QueuedMessagesDock.test.tsx | Updates mocks for new hooks/setters and drag support. |
| packages/ui/src/features/message-editor/components/PromptInput.tsx | Adds Escape handling to cancel an in-progress queued-message edit. |
| packages/ui/src/features/message-editor/components/PromptInput.test.tsx | Adds tests for Escape behavior when editing vs when a run is loading. |
| packages/shared/src/sessions.ts | Adds editingQueuedId to AgentSession and introduces sendableQueuePrefixLength. |
| packages/shared/src/index.ts | Re-exports sendableQueuePrefixLength. |
| packages/core/src/sessions/sessionStore.ts | Adds moveQueuedMessage, updateQueuedMessage, edit-hold setters, and drain cutoff options. |
| packages/core/src/sessions/sessionService.ts | Updates drain behavior (stop-at-edit, max=1) and adds edit-hold/update APIs. |
| packages/core/src/sessions/sessionQueueEditing.test.ts | New unit tests for reorder/update/edit-hold and sequential drain behavior. |
| apps/web/vite.config.ts | Adds @posthog/git/* aliasing to source for Rollup/Vite resolution parity. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…edit Cancelling a queued-message edit unconditionally set the composer to empty content, wiping any draft the user had typed before clicking Edit. Snapshot the composer content when the edit begins and restore it on cancel, falling back to clearing only when there was no prior draft. The snapshot is refreshed at each edit and taken (removed) on cancel, so it can never restore stale content on a later edit. Generated-By: PostHog Code Task-Id: 5cf31c6c-1ba0-4137-88c1-3a369f3acf36
updateQueuedMessage awaited resolveCloudPrompt before writing to the store. If the message drained during that await (a turn completed and sent it), the store update became a no-op but the method still returned true, so the caller treated the edit as saved and never fell back to sending it as a fresh message -- losing the edit. Re-read fresh session state after the await and return false if the target is no longer queued. Also read fresh state for the edit-hold clear, since the pre-await snapshot may be stale. Generated-By: PostHog Code Task-Id: 5cf31c6c-1ba0-4137-88c1-3a369f3acf36
On a failed updateQueuedMessage the catch cleared editingQueuedId, which releases the hold and can flush the queue when the run is idle — sending the original, unedited message, the opposite of what the user intended. Keep the hold on failure so the message stays queued and unsent, and restore the edited text to the composer (unless the user already started typing) so they can retry the save or cancel the edit explicitly. Generated-By: PostHog Code Task-Id: 5cf31c6c-1ba0-4137-88c1-3a369f3acf36
Ports the desktop queued-messages improvements to the mobile app. - Reorder queued messages with per-card move up/down controls. - Edit a queued message in place: pull it into the composer while it stays in the queue, then save it back into position (or cancel unchanged). - Drain boundary: while a message is being edited, only the messages queued before it auto-send when the turn ends; the edited message and everything after it stay queued until the edit is saved or cancelled. Generated-By: PostHog Code Task-Id: 8d0379e9-fb51-4ce7-9eb9-8f5b7a508bf0
What
Two additions to the queued-messages dock (the follow-ups pinned above the composer while a turn is running):
@dnd-kit/reactsortable pattern (same as sidebar folders / browser tabs), with aPointerSensormovement threshold so the card's buttons still take clicks.Previously the pencil ("return to editor") pulled the message out of the queue entirely; that hook (
useReturnQueuedMessageToEditor) is replaced byuseEditQueuedMessage/useCancelQueuedMessageEdit.How
moveQueuedMessageandupdateQueuedMessagestore setters;SessionService.updateQueuedMessagemirrors the enqueue normalization (cloud recomputes transport display + raw payload viagetCloudPromptTransport; local stores the serialized text).sessionViewStoretracks the active edit target per task (editingQueuedIdByTaskId);useSessionCallbacks.handleSendPromptroutes toupdateQueuedMessagewhen an edit is in progress;QueuedMessagesDockwires theDragDropProvider+ sortable cards and clears a stale edit target if the message leaves the queue.Testing
pnpm --filter @posthog/core typecheck+@posthog/ui typecheck— cleanpackages/core/src/sessions/sessionQueueEditing.test.ts(9 tests) for the store setters; updatedQueuedMessagesDock.test.tsxNot yet dogfooded in the running app — happy to do that next.
Created with PostHog Code