fix(server): preserve active turns when switching provider instances#22754

open6
main
fix/issue-22748
opened3d agobyJJulius Marminge
View on GitHubTwo-way sync enabledPR last imported 2d ago
Selected thread: apps/server/src/orchestration-v2/Orchestrator.ts:2964 — <!-- MURMUR_IGNORE --> `orchestration-v2/Orchestrator.ts:2964` This is a domain rejection, not a wrapped failure, but the retry guidance is stored as a synthetic `cause` while `OrchestratorDispatchError.message` remains generic. Please represent the active-turn rejection as a structured tagged error without a cause, derive its caller-visible message from its attributes, and update the focused assertion that currently reads `.cause`. This also lets callers distinguish the retryable rejection from an unexpected dispatch failure. No longer relevant as of 6b3bdce4a6278924d6236d892f8179b434a7df80 <!-- macroscope-meta: {"kind":"code_review"} -->
0 / 4 viewed4 files changedLine totals unavailable

apps/server/src/orchestration-v2/Orchestrator.ts · Earlier revision 896c0e10 · right 2964

Original diff
@@ -2947,12 +2947,26 @@ const makeOrchestrator = Effect.fn("orchestrationV2.Orchestrator.layer")(functio
                   }),
               ),
             );
-            return yield* providerSwitchService
+            const plan = yield* providerSwitchService
               .plan({
                 projection: providerContext!,
                 targetModelSelection: command.modelSelection,
               })
               .pipe(mapDispatchError(command));
+            if (plan.instanceChanged || plan.releaseProviderSessionIds.length > 0) {
+              const projection = yield* loadProjectionForCommand(command, ["runs"], {
+                turnItemTypes: [],
+              });
+              if (projection.runs.some(isBlockingRun)) {
+                return yield* new OrchestratorDispatchError({
+                  commandId: command.commandId,
+                  commandType: command.type,
+                  cause: