Skip to content

Feat/mid thread provider switching - #9392

Open
BandaySajid wants to merge 7 commits into
pingdotgg:mainfrom
BandaySajid:feat/mid-thread-provider-switching
Open

Feat/mid thread provider switching#9392
BandaySajid wants to merge 7 commits into
pingdotgg:mainfrom
BandaySajid:feat/mid-thread-provider-switching

Conversation

@BandaySajid

@BandaySajid BandaySajid commented Sep 3, 2026

Copy link
Copy Markdown

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 $skill tokens) plus Current Request. Failed sends that included that context re-queue the handoff so retries still carry history.

ProviderService treats resumeCursor: null as 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 use resolveProviderSkillsForCwdAcrossProviders (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.ensureSessionForThread replaces 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.startSession distinguishes omitted vs explicit null resume cursors, forcing a clean adapter session when null is passed so persisted cursors are not reused.
  • deriveLockedProvider in ChatView.logic.ts now uses provider snapshots to lock a started thread only when the current provider explicitly requires a new thread for model changes.
  • Web and mobile composers and timelines use the new resolveProviderSkillsForCwdAcrossProviders to show deduplicated skills from all configured providers, falling back when the selected provider has no cwd-resolved skills.
  • escapeThreadContinuitySkillTokens prefixes standalone dollar skill tokens with a backslash so continuity prompts do not trigger skill execution on the replacement provider.
  • Risk: buildSendTurnRequestForThread clears 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 in ProviderCommandReactor.ts to ensure retries rebuild context and that no path leaves the flag stuck.

Macroscope summarized 2bfe908.

…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.
@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Sep 3, 2026
Comment thread apps/server/src/orchestration/Layers/ProviderCommandReactor.ts Outdated
Comment thread apps/server/src/orchestration/Layers/ProviderCommandReactor.ts

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ 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.

Comment thread apps/server/src/orchestration/Layers/ProviderCommandReactor.ts
@macroscopeapp

macroscopeapp Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: 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:

  • 1 blocking correctness issue found at or above your repo's Minimum Blocking Severity

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.
Comment thread apps/server/src/orchestration/Layers/ProviderCommandReactor.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant