Hand off to another provider from the follow-up composer - #3434
Merged
Conversation
… is selected The follow-up composer locked its model picker to the thread's provider, so handing work to a different model meant leaving the thread through the "Handoff to new thread" footer action and re-typing the prompt in root compose. The bottom follow-up composer now exposes the same provider tabs as the new-thread picker. Selecting a provider other than the thread's own provider shows a toast explaining that submitting will create a new thread, retitles the submit control to "Create new thread", and on submit creates a thread on the selected provider and model that reuses the source environment and starts with "Continue from @thread:<source>" followed by the typed follow-up, then navigates to it. Same-provider model changes still send follow-ups to the current thread. Queued-message inline editors, sent-message edits, and side chats keep the provider-locked picker; beginning a sent-message edit reverts a pending cross-provider selection so that edit stays on the thread's provider. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…read Selecting another provider in the follow-up composer now creates and opens the new thread directly, so the "Handoff to new thread" footer action in the model picker duplicated that flow with a worse one: it left the thread and seeded root compose with a draft that dropped anything already typed. Remove the footer action and everything that existed only to serve it: the model picker's footer action slot and its menu action button, the ExecutionControls prop that forwarded it, root compose's handoff seed handling, and client-core's handoff location-state helpers. The ThreadHandoffCreateSeed type and the "Continue from" draft builder stay because the inline handoff still uses them. Also fix the CI failures from the previous commit: the provider-switch test queried a test id that the nested inline editor duplicated, the create-thread test fixture omitted a required runtime field, and the keystrokes test's mutation mock lacked useCreateThread. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… submit Submitting a cross-provider follow-up silently prepended "Continue from @thread:<source>" to whatever the user typed, so the message that started the new thread was never the message they saw in the composer. Selecting another provider now inserts that reference into the draft itself, followed by a blank line, and focuses the composer so the user can edit or delete it before submitting. Switching back to the thread's provider removes the reference again, but only while it is still exactly as inserted. The create-thread request sends the draft as typed, and the toast now says the reference was added and can be edited. client-core gains stripThreadHandoffPrefix as the counterpart of buildThreadHandoffFollowUpDraft, which also leaves a draft alone when the reference is already present so re-entering handoff mode never duplicates it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…line The composer editor stores the seeded "Continue from @thread:<source>" line followed by a single newline once the user types below it, so the exact two-newline match never fired: switching back to the thread's provider left the reference in place and re-entering handoff mode inserted a second copy. Detect the reference by its intact mention and its own line instead, and treat any run of newlines after it as the separator when stripping it or deciding not to insert it again. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Resolves the conflict in PluginNewThreadComposer.test.tsx by keeping the upstream tests and dropping the root-compose handoff test again, since the location-state helpers it used were removed on this branch. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Bring back the "Handoff to new thread" entry at the bottom of the follow-up composer's model picker, but keep it inside the thread: clicking it turns the picker into a two-step flow that lists the other providers, then that provider's models, with a header showing the step and the chosen provider. Picking a model commits provider, model, and reasoning atomically through setProviderModelReasoning, closes the picker, and hands the composer to the existing handoff mode, which seeds the source-thread reference and explains that submitting will create a new thread. Back returns to the provider step and the close control cancels without touching the thread's selection. The picker reuses its provider preview catalog, menu rows, and hover chrome for the flow, and only the bottom composer passes the handoff config; inline queued-message and sent-message editors keep the locked picker. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The step-2 line crammed the provider name and "Choose a model" into one truncating row. Show the step on its own line and the chosen provider with its icon on the line below so neither is cut off. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…nd a toast The stepped flow read like onboarding, and the toast overlapped the submit button while saying something the composer itself should show. The picker's "Handoff to new thread" entry now switches the picker into a handoff mode that keeps the familiar layout: a header replaces the top chrome, the provider tabs stay with the thread's own provider struck through and disabled, the first other provider is previewed, and search, models, and reasoning work as usual. Reasoning changes are held locally until a model is picked, which commits provider, model, and reasoning atomically, closes the picker, and enters handoff mode in the composer. The back control returns to the normal picker without touching the thread's selection. The composer now shows a cap above the prompt box, built on the same card chrome as the editing cap, naming the target provider and model and offering a cancel control that restores the thread's provider and removes the seeded reference. The submit button reads "New thread" in that state. The toast is gone. Draft seeding and stripping moved from an effect into the provider handlers, and a mount-time cleanup removes a stale reference after a remount. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The compact composer sizes its action buttons with a square utility that outranked the width override, so "New thread" was clipped on phones. Reset the square size explicitly and keep the height when a label is present. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…izing The compact-container rule pins the submit action to a two-rem square with no padding, which clipped the "New thread" label on phones. Mark the button when it carries a label and give that case auto width with inline padding. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…eanup The handoff-mode rewrite dropped the picker's plain provider-tab handler, so tab clicks and provider cycling referenced an undefined function. Bring it back. Let the composer test's draft mock keep what setDraft writes so the switch-back and create-thread cases start from an unseeded draft, as they do in the product now that a stale reference is stripped on mount, and expect the trigger to keep showing the current model while the picker previews the handoff target. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The header title already says what the mode is; the second line repeated it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The labeled "New thread" submit button already says what will happen, and a cap above the composer would collide with the queued-message drawer. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The compact composer drops the label and keeps only the icon so the button no longer overlaps the draft on narrow layouts. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Clicking the struck-through tab for the thread's own provider now exits handoff mode and, when the composer was on another provider, switches it back so the seeded reference and submit button return to normal. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The footer placement was easy to miss. The entry now sits above the provider tabs as a full-width row filled with the shared selection grey, with the new-thread icon and a chevron marking that it opens the nested handoff mode. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This reverts commit c4a84e7.
The header marking that submitting creates a new thread blended into the picker's own chrome. It now carries the shared selection fill so the mode is obvious, with its layout and controls unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
In the compact drawer the grab-handle strip sat above the handoff header in the plain panel colour, cutting the tinted band off from the top edge. It now carries the same fill and the drawer's top rounding. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…handoff-pr-merge-ready-thr_sk6uxnxuh8
…he-follow-up-handoff-pr-merge-ready-thr_sk6uxnxuh8
…handoff-pr-merge-ready-thr_sk6uxnxuh8
…handoff-pr-merge-ready-thr_sk6uxnxuh8
…eady-thr_sk6uxnxuh8 # Conflicts: # apps/app/src/views/thread-detail/ThreadDetailPromptArea.test.tsx
…eady-thr_sk6uxnxuh8
…eady-thr_sk6uxnxuh8
…handoff-pr-merge-ready-thr_sk6uxnxuh8
…handoff-pr-merge-ready-thr_sk6uxnxuh8
…handoff-pr-merge-ready-thr_sk6uxnxuh8
…handoff-pr-merge-ready-thr_sk6uxnxuh8 # Conflicts: # apps/app/src/components/pickers/ModelReasoningPicker.test.tsx # apps/app/src/components/pickers/ModelReasoningPicker.tsx
This reverts commit c7e1c4d.
…handoff-pr-merge-ready-thr_sk6uxnxuh8
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Human comments
What was wrong
The follow-up picker was provider-locked, and handoff opened root compose without carrying over the draft.
What changed
How you verified
9a32f8d07, including all test shards and both package smoke jobs.9a32f8d07.Before / after screenshots
Branch web app, light theme, 2× pixel density. Mobile: 390×844; desktop: 1280×900.
Handoff header — after
BB-Thread-ID: thr_rmmwartzsr
🤖 Generated with Claude Code