Skip to content

Commit ca7df39

Browse files
fix(server): steers keep the newest next-turn selection (#14725)
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent bf7121d commit ca7df39

3 files changed

Lines changed: 288 additions & 157 deletions

File tree

‎apps/server/src/orchestration-v2/EffectWorker.ts‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,12 @@ export const executorLayer: Layer.Layer<
244244
text: message.text,
245245
...(message.context ? { context: message.context } : {}),
246246
attachments: message.attachments,
247-
modelSelection: run.modelSelection,
247+
// A user's follow-up starts on the thread's saved selection,
248+
// which already holds the steer's choice. A delegated
249+
// completion stays pinned to the run it reports to.
250+
...(message.delegatedCompletion === undefined
251+
? {}
252+
: { modelSelection: run.modelSelection }),
248253
dispatchMode: {
249254
type:
250255
message.delegatedCompletion === undefined

‎apps/server/src/orchestration-v2/Orchestrator.ts‎

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3631,17 +3631,25 @@ const makeOrchestrator = Effect.fn("orchestrationV2.Orchestrator.layer")(functio
36313631
);
36323632

36333633
if (steeringPolicy === "active_steering") {
3634+
// The steer's selection becomes the saved next-turn choice, even when it
3635+
// matches the running run again. A delegated completion carries the
3636+
// run's selection, not a user choice, so it never replaces the saved one.
3637+
// The saved choice may name another instance, so it moves with the steer.
3638+
const instanceChanged =
3639+
input.projection.thread.providerInstanceId !== input.modelSelection.instanceId;
36343640
if (
3635-
selectionChanged &&
3636-
!modelSelectionsEqual(input.projection.thread.modelSelection, input.modelSelection)
3641+
input.delegatedCompletion === undefined &&
3642+
(instanceChanged ||
3643+
!modelSelectionsEqual(input.projection.thread.modelSelection, input.modelSelection))
36373644
) {
36383645
yield* emitEvent({
3639-
type: "thread.model-selection-updated",
3646+
type: instanceChanged ? "thread.provider-switched" : "thread.model-selection-updated",
36403647
threadId: input.command.threadId,
36413648
providerInstanceId: input.modelSelection.instanceId,
36423649
occurredAt: now,
36433650
payload: {
36443651
...input.projection.thread,
3652+
providerInstanceId: input.modelSelection.instanceId,
36453653
modelSelection: input.modelSelection,
36463654
updatedAt: now,
36473655
},

0 commit comments

Comments
 (0)