From 20967e2f980bcdaf4a8ea93d495f0777bf640d74 Mon Sep 17 00:00:00 2001 From: Courtney Richard Pitcher Date: Wed, 9 Sep 2026 14:56:04 +0100 Subject: [PATCH] fix(server): preserve reasoning effort after restart --- ...ProviderSessionStartup.integration.test.ts | 10 ++++++++-- .../Layers/CodexSessionRuntime.test.ts | 20 +++++++++++++++++++ .../serverRuntimeStartup.reconcile.test.ts | 20 +++++++++++++++++-- apps/server/src/serverRuntimeStartup.ts | 1 + 4 files changed, 47 insertions(+), 4 deletions(-) diff --git a/apps/server/integration/orphanedProviderSessionStartup.integration.test.ts b/apps/server/integration/orphanedProviderSessionStartup.integration.test.ts index e07681ae153b..86289308d483 100644 --- a/apps/server/integration/orphanedProviderSessionStartup.integration.test.ts +++ b/apps/server/integration/orphanedProviderSessionStartup.integration.test.ts @@ -374,6 +374,11 @@ it.effect.each(["opt-in desktop restart", "marked remote update"] as const)( const activeTurnId = TurnId.make("turn-started-after-original-send"); const originalTurnId = TurnId.make("turn-from-original-send"); const sent = yield* Deferred.make(); + const modelSelection = { + instanceId: providerInstanceId, + model: "gpt-5", + options: [{ id: "reasoningEffort", value: "high" }], + }; yield* Effect.gen(function* () { const engine = yield* OrchestrationEngine.OrchestrationEngineService; @@ -384,7 +389,7 @@ it.effect.each(["opt-in desktop restart", "marked remote update"] as const)( projectId, title: "Restart continuation", workspaceRoot: "/tmp/startup-orphan-project", - defaultModelSelection: { instanceId: providerInstanceId, model: "gpt-5" }, + defaultModelSelection: modelSelection, createdAt, }); yield* engine.dispatch({ @@ -393,7 +398,7 @@ it.effect.each(["opt-in desktop restart", "marked remote update"] as const)( threadId, projectId, title: "Newer running turn", - modelSelection: { instanceId: providerInstanceId, model: "gpt-5" }, + modelSelection, interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, runtimeMode: "full-access", branch: null, @@ -469,6 +474,7 @@ it.effect.each(["opt-in desktop restart", "marked remote update"] as const)( assert.deepStrictEqual(yield* Deferred.await(sent), { threadId, continuation: true, + modelSelection, interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, }); }).pipe( diff --git a/apps/server/src/provider/Layers/CodexSessionRuntime.test.ts b/apps/server/src/provider/Layers/CodexSessionRuntime.test.ts index 3385137a2dae..c6df5a24fed0 100644 --- a/apps/server/src/provider/Layers/CodexSessionRuntime.test.ts +++ b/apps/server/src/provider/Layers/CodexSessionRuntime.test.ts @@ -179,6 +179,26 @@ describe("buildTurnStartParams", () => { }); }); + it.effect("preserves a non-default reasoning effort in collaboration mode", () => + Effect.gen(function* () { + const params = yield* buildTurnStartParams({ + threadId: "provider-thread-1", + runtimeMode: "full-access", + prompt: "Continue the task", + model: "gpt-5.3-codex", + effort: "high", + interactionMode: "default", + }); + + NodeAssert.equal(params.effort, "high"); + NodeAssert.equal(params.collaborationMode?.settings.reasoning_effort, "high"); + NodeAssert.match( + params.collaborationMode?.settings.developer_instructions ?? "", + /with high reasoning effort/, + ); + }), + ); + it("reports the same fallback model and effort in settings and instructions", () => { const params = Effect.runSync( buildTurnStartParams({ diff --git a/apps/server/src/serverRuntimeStartup.reconcile.test.ts b/apps/server/src/serverRuntimeStartup.reconcile.test.ts index 37fd210ee6da..91b3c2f9f106 100644 --- a/apps/server/src/serverRuntimeStartup.reconcile.test.ts +++ b/apps/server/src/serverRuntimeStartup.reconcile.test.ts @@ -41,6 +41,11 @@ const makeThread = ( id: ThreadId.make(id), archivedAt, deletedAt, + modelSelection: { + instanceId: providerInstanceId, + model: "gpt-5.3-codex", + options: [{ id: "reasoningEffort", value: "high" }], + }, interactionMode: "default" as const, session: { threadId: ThreadId.make(id), @@ -304,10 +309,16 @@ it.effect.each( String(left.threadId).localeCompare(String(right.threadId)), ), [ - { threadId: codex.id, continuation: true, interactionMode: "default" }, + { + threadId: codex.id, + continuation: true, + modelSelection: codex.modelSelection, + interactionMode: "default", + }, { threadId: fallback.id, input: "Continue where you left off.", + modelSelection: fallback.modelSelection, interactionMode: "default", }, ], @@ -906,7 +917,12 @@ for (const preparedStatus of [ yield* runReconciliation(input); yield* Deferred.await(cleared); assert.deepStrictEqual(sends, [ - { threadId: thread.id, continuation: true, interactionMode: "default" }, + { + threadId: thread.id, + continuation: true, + modelSelection: thread.modelSelection, + interactionMode: "default", + }, ]); assert.deepStrictEqual(binding.runtimePayload, { activeTurnId: null, diff --git a/apps/server/src/serverRuntimeStartup.ts b/apps/server/src/serverRuntimeStartup.ts index 3d04abaa1914..390fa5042db2 100644 --- a/apps/server/src/serverRuntimeStartup.ts +++ b/apps/server/src/serverRuntimeStartup.ts @@ -694,6 +694,7 @@ export const reconcileProviderSessions = Effect.gen(function* () { ...(capabilities.promptlessTurnContinuation === true ? { continuation: true } : { input: SERVER_UPDATE_CONTINUATION_PROMPT }), + modelSelection: thread.modelSelection, interactionMode: thread.interactionMode, }); });