Feat/mid thread provider switching - #9392
Conversation
…t handoff Previously, threads were locked to their initial provider instance, preventing users from switching between Codex, Claude, and OpenCode mid-conversation. Attempting to switch would either be blocked in the UI or fail with a hard driver-mismatch error. This unlocks provider switching in the UI for providers without explicit thread-locking requirements. When switching providers mid-thread, the server cleanly stops the previous provider session, starts a fresh session without incompatible driver cursors, and injects a synthesized Markdown conversation history block into the initial turn prompt.
…n handoff context
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit dfd70ed. Configure here.
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This PR introduces cross-provider mid-thread handoffs with session restarts, synthesized conversation context, attachment propagation, and coordinated web/mobile UI changes, rather than a small isolated adjustment. An unresolved high-severity finding also identifies a concrete request-size failure risk for handoffs carrying attachments. Not approved because:
Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more. |
…doffs Two review findings on the mid-thread provider switching PR: the handoff flag was set before rejectStartedThreadModelChangeIfRequired could reject the switch, leaving it stuck for the next ordinary turn; and it was cleared as soon as the handoff prompt was built, so a listSessions/getCapabilities failure after the session was already rebound lost conversation history on retry. Move both the set and the clear past every fallible step they depend on.

What Changed
Unlocks mid-thread provider switching. Previously threads were locked to their initial provider instance, switching Codex/Claude/OpenCode mid-conversation was either blocked in the UI or failed with a hard driver-mismatch error. Now the server stops the previous provider session cleanly, starts a fresh one without incompatible driver cursors, and injects a synthesized Markdown conversation-history block into the initial turn prompt so the new provider has context. Follow-up fixes keep skill chips intact across the switch, keep the handoff transparent to the user (no "previous agent" leakage), and preserve session state correctly across switches.
Why
Users want to change providers mid-conversation, e.g. moving from Codex to Claude when they hit a subscription usage limit,without losing thread history or starting over. The previous hard-block/driver-mismatch failure made that impossible.
UI Changes
NONE
Note
High Risk
Changes core turn/session orchestration and injects large synthesized prompts on provider handoff; regressions could affect session binding, input limits, or continuity on retry/failure paths.
Overview
Mid-thread provider switching is now supported end-to-end. The server no longer rejects cross-driver or incompatible-continuation switches; on handoff it stops the prior session, starts the new provider with an explicit clean resume (
resumeCursor: null), and on the first post-switch turn prepends a bounded[Thread Continuity Context]block (prior user/assistant text, re-carried attachments, escaped$skilltokens) plus Current Request. Failed sends that included that context re-queue the handoff so retries still carry history.ProviderService treats
resumeCursor: nullas a forced fresh session; omitting the field still reuses a persisted cursor when the instance matches.Clients unlock the provider picker for started threads unless the active instance sets
requiresNewThreadForModelChange. Composers and timelines useresolveProviderSkillsForCwdAcrossProviders(with per-provider fallback in slash menus) so skills stay visible after a switch.Reviewed by Cursor Bugbot for commit 2bfe908. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Add mid-thread provider switching with conversation continuity and cross-provider skills
ProviderCommandReactor.ensureSessionForThreadreplaces rejection of cross-driver model switches with handoff handling: stops the old session, starts the new provider with a null resume cursor, and builds a bounded continuity prompt from prior user/assistant messages and attachments.ProviderService.startSessiondistinguishes omitted vs explicitnullresume cursors, forcing a clean adapter session whennullis passed so persisted cursors are not reused.deriveLockedProviderinChatView.logic.tsnow uses provider snapshots to lock a started thread only when the current provider explicitly requires a new thread for model changes.resolveProviderSkillsForCwdAcrossProvidersto show deduplicated skills from all configured providers, falling back when the selected provider has no cwd-resolved skills.escapeThreadContinuitySkillTokensprefixes standalone dollar skill tokens with a backslash so continuity prompts do not trigger skill execution on the replacement provider.buildSendTurnRequestForThreadclears the pending-continuity flag only after session/capability checks; a send failure restores it via the turn-start processor. Reviewers should verify the flag lifecycle inProviderCommandReactor.tsto ensure retries rebuild context and that no path leaves the flag stuck.Macroscope summarized 2bfe908.