Repository navigation
feat(dashboard): Steer a queued message into the running Turn - #2422
Conversation
Show the author avatar, image thumbnails, and one truncated line for each queued message. Add an edit action on the reader's own queued web messages that takes the message out of the queue and puts its text and images back in the composer. Co-Authored-By: adm <aditya.mathur@sentry.io>
Add a steer action on the reader's own queued web messages. It marks the message as an interrupt, and the running web Turn of the same author reads it at its next model boundary. A message steered while another person's Turn runs starts the next Turn ahead of other queued input, so it never runs with that person's credentials. The worker now lets a message that was deferred at attempt start join the attempt once it is steered. Steered web messages keep their stored images. Co-Authored-By: adm <aditya.mathur@sentry.io>
Co-Authored-By: adm <aditya.mathur@sentry.io>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Leave the message queued when the reader leaves during the image read. If the reader leaves during the cancel, put the text in the saved draft. Do not add a leading newline when an image-only message comes back. Co-Authored-By: adm <aditya.mathur@sentry.io>
…-queued Co-Authored-By: adm <aditya.mathur@sentry.io>
A dashboard steer during a Slack Turn made a web interrupt that the Slack drain tried to restore as a Slack message, so the Turn failed. The Slack drain now offers only Slack records. Other records stay pending for their own Turn.
A steered web message is an interrupt, and interrupts were selected before the paused check. A web message steered during a yielded slice then started a second Turn while the first Turn still waited to resume. While a Turn is paused, web interrupts no longer start an attempt. They stay eligible for the resumed Turn's drain, or start the next attempt. Co-Authored-By: adm <aditya.mathur@sentry.io>
Check that the queued images fit in the draft before the cancel. After the cancel, images that do not fit are lost. An image read that finishes after an edit restore now adds to the restored images instead of replacing them. A second click during the image read no longer starts a second edit. The author avatar has an img role so screen readers announce its name. Co-Authored-By: adm <aditya.mathur@sentry.io>
…-queued # Conflicts: # packages/junior-dashboard/e2e/conversation-send.spec.ts Co-Authored-By: adm <aditya.mathur@sentry.io>
Queued rows are one line now, so the stack shows up to five rows. With six or more, desktop shows four rows and a control for the rest. Co-Authored-By: Aditya Mathur <aditya.mathur@sentry.io>
…-queued Co-Authored-By: Aditya Mathur <aditya.mathur@sentry.io>
A drop or paste during the edit cancel can fill the draft after the fit check. The queued images already left the queue, so they now win. Draft images that no longer fit are dropped with an error.
A live poll that read the mailbox before the steer could land after it and restore defer delivery. Then the Steer button came back.
ScreenshotsFrameshift did not run here. CI runs only for PRs into Before steer. Your own queued rows show Queued (clock), Steer, Edit, and Delete. After steering "Already read". The row shows Interrupt, and Steer is gone. |
The image size check and the data URL for local previews were written out in several places. Keep one helper for each so the composer, the queue, and the transcript count and show images the same way. Co-Authored-By: Aditya Mathur <aditya.mathur@sentry.io>
…-queued Co-Authored-By: Aditya Mathur <aditya.mathur@sentry.io>
The web steering drain rebuilt the transcript author from the Actor with the same fields that the mailbox Turn input already holds. Pass that author in so both transcript Messages come from one source. Co-Authored-By: Aditya Mathur <aditya.mathur@sentry.io>
The steer change pushed worker.ts past the 1,000-line limit. Attempt input selection is a self-contained rule, so it moves to its own module. Document how a dashboard steer changes mailbox delivery in the module README. Co-Authored-By: Aditya Mathur <aditya.mathur@sentry.io>
…2419) The queued message stack above the composer used a full email heading and up to three lines of text per row, so a few queued messages took a lot of space. Each row is now one line: - The author shows as the same avatar the conversation header uses. Hover or focus shows the name and email. - Image attachments show as small thumbnails that open the image preview. Other files show a file icon with the name on hover. - The text is one truncated line. The full text is in the hover title. There is also a new **Edit** action. It shows only on the reader's own accepted web messages. Edit reads the message images first, then cancels the message in the queue, then puts the text ahead of the current draft and adds the images back to the composer. Edit uses the existing cancel endpoint, so: - If Junior finishes before the reader sends the edited message, nothing is sent, because the message is no longer in the queue. - When the reader sends the edited message, it is a new message at the back of the queue. - If Junior already read the message before the cancel landed, the cancel returns no ids. The composer shows "Junior already read that message." and the draft does not change. The **Steer** action (send a queued message into the running turn now) is in the stacked follow-up #2422. <!-- junior-request-attribution:start --> via **adm**. <!-- junior-request-attribution:end --> <!-- junior-session-footer:start --> <!-- junior-conversation-id:local%3Aweb%3A6574fc16dd6453b581112066 --> -- [View Session in Sentry](https://sentry.sentry.io/explore/conversations/local%3Aweb%3A6574fc16dd6453b581112066/?project=4510944073809921) <!-- junior-session-footer:end --> --------- Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com> Co-authored-by: adm <aditya.mathur@sentry.io>
…queued # Conflicts: # packages/junior-dashboard/e2e/conversation-send.spec.ts # packages/junior-dashboard/src/client/conversations/ComposerImages.tsx # packages/junior-dashboard/src/client/conversations/ConversationPage.tsx # packages/junior-dashboard/src/client/conversations/PendingMailboxStack.tsx Co-Authored-By: Aditya Mathur <aditya.mathur@sentry.io>
The steer button used the same skip icon as the interrupt status, and the tooltips repeated the button names. Steer now uses a bolt icon, and a steered row shows that icon with a Steered status. Each tooltip now says what the action does. Actions use the shared icon button, so a disabled action keeps its tooltip and delete gets the danger hover. Co-Authored-By: Aditya Mathur <aditya.mathur@sentry.io>
|
7 screenshot changes — 7 changed · 0 added · 0 removed Review screenshots in Frameshift |
Sentry Evalsjunior-behavioral
Base commit junior-integration
Base commit |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit e881b41. Configure here.
…r send (#2423) Stacked on #2422 (which is stacked on #2419). When Junior is idle and the queue is empty, a dashboard send used to show in the queue stack first. Then it jumped into the transcript once Junior read it. That jump looked laggy. **A. Inline send.** If no Turn is running and no queued rows are waiting, the send now goes straight to the transcript tail. It stays there until history has the same message id, so it does not flash back into the queue when the mailbox copy arrives. - A failed send moves to the queue, which owns Retry. A retry stays in the queue. - Conversations without available history (for example, expired history) keep the queue path. Otherwise the transcript could not show the send. - First messages of new conversations and forks are inline. - Inline rows have no fork action (they use the existing `pending` transcript rows). **B. Fast poll after send.** For 6 seconds after the latest send, the detail query polls every 500ms. After that it uses the normal 2s / 10s interval. Changes: - `conversationOutbox.ts`: `inline` flag on outbox rows, `isInlineOutboxMessage`, `splitInlineMailboxMessages` (server copy wins). - `queries.ts`: fast poll window, inline cleanup waits for history, returns `inlineMessages` apart from `pendingMessages`. - `ConversationPage.tsx`, `TranscriptView.tsx`, `ConversationTranscript.tsx`: decide inline at send time and pass inline rows to the transcript. Tests: - `e2e/conversation-send.spec.ts`: the queue-to-history handoff test now expects the send in the transcript, never in the queue, through mailbox and history changes. The expired-history test keeps the queue assertions. - `tests/conversation-outbox.test.ts`: inline split and failure-to-queue. - `pnpm --filter @sentry/junior-dashboard typecheck`, `pnpm lint`, dashboard vitest (322 tests), and `conversation-send` + `conversations` Playwright specs (20 tests) pass locally. <!-- junior-request-attribution:start --> via **adm**. <!-- junior-request-attribution:end --> <!-- junior-session-footer:start --> <!-- junior-conversation-id:local%3Aweb%3A6574fc16dd6453b581112066 --> -- [View Session in Sentry](https://sentry.sentry.io/explore/conversations/local%3Aweb%3A6574fc16dd6453b581112066/?project=4510944073809921) <!-- junior-session-footer:end --> --------- Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com> Co-authored-by: adm <aditya.mathur@sentry.io>




Stacked on #2419.
Adds a steer action to the reader's own queued web messages in the dashboard. Steering marks the message as an interrupt. When the running web Turn belongs to the same author, it reads the message at its next model boundary, in the same Turn, with its images. When another person's Turn is running, the message does not join it, so it never runs with that person's credentials. It starts the next Turn ahead of other queued input. If Junior already read the message, steering does nothing.
Before this change, the worker did not let a message that was pending at attempt start join that attempt. So a message steered mid-Turn would not arrive. Now a message that is steered after the attempt starts can join it.
API:
POST /api/conversations/:id/pending-messages/steer. Only the author can steer their own queued web messages.Also replaces the queue's remove (×) action with a delete (trash) action.
The new integration eval
Dashboard Turn Steeringhas no recording yet. CI records it on its first run.via adm.
--
View Session in Sentry