diff --git a/packages/ai/test/openai-responses-history-payload.test.ts b/packages/ai/test/openai-responses-history-payload.test.ts index 78886cc84..583455d78 100644 --- a/packages/ai/test/openai-responses-history-payload.test.ts +++ b/packages/ai/test/openai-responses-history-payload.test.ts @@ -108,7 +108,7 @@ const assistantSnapshotContext: Context = { const codexAssistantSnapshotContext: Context = { messages: [ { role: "user", content: "generic history that should be replaced", timestamp: Date.now() }, - makeAssistantMessage(snapshotHistoryItems, false, "openai-codex", "gpt-5.2-codex"), + makeAssistantMessage(snapshotHistoryItems, false, "openai-codex", "gpt-5.5"), { role: "user", content: "follow-up user", timestamp: Date.now() }, ], }; @@ -117,7 +117,7 @@ const codexToCopilotContext: Context = { messages: [ { role: "user", content: "generic user before switch", timestamp: Date.now() }, { - ...makeAssistantMessage([], false, "openai-codex", "gpt-5.2-codex"), + ...makeAssistantMessage([], false, "openai-codex", "gpt-5.5"), content: [{ type: "text", text: "generic assistant that should be rebuilt" }], providerPayload: createOpenAIResponsesHistoryPayload("openai-codex", [ { type: "reasoning", encrypted_content: "enc_123" }, @@ -267,7 +267,7 @@ function makeAssistantMessage( items: Record[], incremental = false, provider: "openai" | "openai-codex" | "github-copilot" = "openai", - model = provider === "openai-codex" ? "gpt-5.2-codex" : provider === "github-copilot" ? "gpt-5.4" : "gpt-5-mini", + model = provider === "openai-codex" ? "gpt-5.5" : provider === "github-copilot" ? "gpt-5.4" : "gpt-5-mini", ) { return { role: "assistant" as const, @@ -428,7 +428,7 @@ describe("OpenAI responses history payload", () => { }); assertWireOrder(openaiItems); - const codexModel = getBundledModel<"openai-codex-responses">("openai-codex", "gpt-5.2-codex"); + const codexModel = getBundledModel<"openai-codex-responses">("openai-codex", "gpt-5.5"); const codexItems = convertCodexResponsesMessages(codexModel, makeContext("openai-codex")); assertWireOrder(codexItems); }); @@ -810,7 +810,7 @@ describe("OpenAI responses history payload", () => { }); it("prefers assistant native history snapshots for openai-codex-responses", async () => { - const model = getBundledModel("openai-codex", "gpt-5.2-codex") as Model<"openai-codex-responses">; + const model = getBundledModel("openai-codex", "gpt-5.5") as Model<"openai-codex-responses">; const payload = (await captureCodexPayload(model, codexAssistantSnapshotContext)) as { input?: unknown[] }; expect(payload.input).toEqual([ ...snapshotHistoryItems, @@ -1279,7 +1279,7 @@ describe("OpenAI responses history payload", () => { content: [{ type: "toolCall", id: callId, name: "read", arguments: { path: "README.md" } }], api: "openai-codex-responses", provider: "openai-codex", - model: "gpt-5.2-codex", + model: "gpt-5.5", usage: { input: 0, output: 0, @@ -1303,7 +1303,7 @@ describe("OpenAI responses history payload", () => { { role: "user", content: "Resume", timestamp: Date.now() }, ], }; - const model = getBundledModel<"openai-codex-responses">("openai-codex", "gpt-5.2-codex"); + const model = getBundledModel<"openai-codex-responses">("openai-codex", "gpt-5.5"); const payload = (await captureCodexPayload(model, context)) as { input?: unknown[] }; const functionCallItem = findResponsesInputItem(payload.input, "function_call"); const functionCallOutputItem = findResponsesInputItem(payload.input, "function_call_output"); diff --git a/packages/catalog/test/gateway-reference.test.ts b/packages/catalog/test/gateway-reference.test.ts index e084e1986..227cd5a65 100644 --- a/packages/catalog/test/gateway-reference.test.ts +++ b/packages/catalog/test/gateway-reference.test.ts @@ -10,8 +10,9 @@ describe("Portkey gateway model references", () => { test("cross-provider references do not inherit wire routing thinking", () => { const index = getBundledModelReferenceIndex(); - const devinGlm = resolveModelReference("glm-5-2", index); - expect(devinGlm?.provider).toBe("devin"); - expect(inheritReferenceThinking(undefined, devinGlm, "gateway")).toBeUndefined(); + const kiloGigaPotato = resolveModelReference("giga-potato", index); + expect(kiloGigaPotato?.provider).toBe("kilo"); + expect(kiloGigaPotato?.thinking?.effortRouting).toBeDefined(); + expect(inheritReferenceThinking(undefined, kiloGigaPotato, "gateway")).toBeUndefined(); }); }); diff --git a/packages/coding-agent/test/agent-session-concurrent.test.ts b/packages/coding-agent/test/agent-session-concurrent.test.ts index 953b22f72..93b937d24 100644 --- a/packages/coding-agent/test/agent-session-concurrent.test.ts +++ b/packages/coding-agent/test/agent-session-concurrent.test.ts @@ -2221,12 +2221,28 @@ describe("AgentSession TTSR resume gate", () => { const authStorage = await AuthStorage.create(path.join(tempDir, "testauth-promo.db")); authStorages.push(authStorage); authStorage.setRuntimeApiKey("openai-codex", "test-key"); - const modelRegistry = new ModelRegistry(authStorage, path.join(tempDir, "models.yml")); + // The bundled catalog has no codex model whose promotion target carries a + // strictly larger window (gpt-5.5's bundled target gpt-5.4 is same-window), + // so pin gpt-5.5 (272k) -> gpt-5.6-sol (372k) via modelOverrides. + const modelsConfigPath = path.join(tempDir, "models-promo.json"); + await Bun.write( + modelsConfigPath, + JSON.stringify({ + providers: { + "openai-codex": { + modelOverrides: { + "gpt-5.5": { contextPromotionTarget: "openai-codex/gpt-5.6-sol" }, + }, + }, + }, + }), + ); + const modelRegistry = new ModelRegistry(authStorage, modelsConfigPath); - const sparkModel = modelRegistry.find("openai-codex", "gpt-5.3-codex-spark"); - const codexModel = modelRegistry.find("openai-codex", "gpt-5.5"); - if (!sparkModel || !codexModel) { - throw new Error("Expected codex spark and codex models to exist"); + const smallModel = modelRegistry.find("openai-codex", "gpt-5.5"); + const largeModel = modelRegistry.find("openai-codex", "gpt-5.6-sol"); + if (!smallModel || !largeModel) { + throw new Error("Expected small and large codex models to exist"); } let streamCallCount = 0; @@ -2235,9 +2251,9 @@ describe("AgentSession TTSR resume gate", () => { const makeOverflowMessage = (): AssistantMessage => ({ role: "assistant", content: [{ type: "text", text: "" }], - api: sparkModel.api, - provider: sparkModel.provider, - model: sparkModel.id, + api: smallModel.api, + provider: smallModel.provider, + model: smallModel.id, usage: { input: 0, output: 0, @@ -2254,9 +2270,9 @@ describe("AgentSession TTSR resume gate", () => { const makeSuccessMessage = (): AssistantMessage => ({ role: "assistant", content: [{ type: "text", text: "Recovered after promotion" }], - api: codexModel.api, - provider: codexModel.provider, - model: codexModel.id, + api: largeModel.api, + provider: largeModel.provider, + model: largeModel.id, usage: { input: 0, output: 0, @@ -2271,7 +2287,7 @@ describe("AgentSession TTSR resume gate", () => { const agent = new Agent({ getApiKey: () => "test-key", - initialState: { model: sparkModel, systemPrompt: ["Test"], tools: [] }, + initialState: { model: smallModel, systemPrompt: ["Test"], tools: [] }, streamFn: () => { streamCallCount++; const stream = new AssistantMessageEventStream(); @@ -2312,7 +2328,7 @@ describe("AgentSession TTSR resume gate", () => { expect(continuationCompleted).toBe(true); expect(streamCallCount).toBeGreaterThanOrEqual(2); - expect(session.model?.id).toBe(codexModel.id); + expect(session.model?.id).toBe(largeModel.id); expect(session.isStreaming).toBe(false); expect(extensionRunner.emitSessionStop).toHaveBeenCalledTimes(1); }); diff --git a/packages/coding-agent/test/agent-session-context-promotion.test.ts b/packages/coding-agent/test/agent-session-context-promotion.test.ts index 5a88b666d..227e70f6a 100644 --- a/packages/coding-agent/test/agent-session-context-promotion.test.ts +++ b/packages/coding-agent/test/agent-session-context-promotion.test.ts @@ -21,10 +21,32 @@ describe("AgentSession context promotion", () => { // constructor (~100ms). The catalog and auth fixture never change between // tests here (tests only read models and add benign extra runtime keys), // so build them once instead of paying ~950ms across the 9 cases. + // + // The bundled catalog no longer ships a codex model whose configured + // promotion target has a strictly larger window (gpt-5.5's bundled target + // gpt-5.4 is a same-window no-op the runtime rejects), so pin + // gpt-5.5 (272k) -> gpt-5.6-sol (372k) via modelOverrides — the same + // mechanism users configure promotion pairs with. gpt-5.4-mini is pinned + // text-only so the snapcompact-fallback case has a codex model on which + // snapcompact (vision-based) cannot run. tempDir = TempDir.createSync("@pi-context-promotion-"); + const modelsConfigPath = path.join(tempDir.path(), "models.json"); + await Bun.write( + modelsConfigPath, + JSON.stringify({ + providers: { + "openai-codex": { + modelOverrides: { + "gpt-5.5": { contextPromotionTarget: "openai-codex/gpt-5.6-sol" }, + "gpt-5.4-mini": { input: ["text"] }, + }, + }, + }, + }), + ); authStorage = await AuthStorage.create(path.join(tempDir.path(), "testauth.db")); authStorage.setRuntimeApiKey("openai-codex", "test-key"); - modelRegistry = new ModelRegistry(authStorage); + modelRegistry = new ModelRegistry(authStorage, modelsConfigPath); }); afterAll(() => { @@ -134,10 +156,10 @@ describe("AgentSession context promotion", () => { } it("promotes to a larger-context model on overflow and clears codex websocket session state", async () => { - const sparkModel = modelRegistry.find("openai-codex", "gpt-5.3-codex-spark"); - const codexModel = modelRegistry.find("openai-codex", "gpt-5.5"); - if (!sparkModel || !codexModel) { - throw new Error("Expected codex spark and codex models to exist"); + const smallModel = modelRegistry.find("openai-codex", "gpt-5.5"); + const largeModel = modelRegistry.find("openai-codex", "gpt-5.6-sol"); + if (!smallModel || !largeModel) { + throw new Error("Expected small and large codex models to exist"); } const settings = Settings.isolated({ @@ -147,7 +169,7 @@ describe("AgentSession context promotion", () => { const agent = new Agent({ initialState: { - model: sparkModel, + model: smallModel, systemPrompt: ["Test"], tools: [], messages: [], @@ -166,23 +188,23 @@ describe("AgentSession context promotion", () => { close: closeSpy, } satisfies ProviderSessionState); - const overflowMessage = createOverflowMessage(sparkModel); + const overflowMessage = createOverflowMessage(smallModel); session.agent.emitExternalEvent({ type: "message_end", message: overflowMessage }); session.agent.emitExternalEvent({ type: "agent_end", messages: [overflowMessage] }); - await waitFor(() => session.model?.id === codexModel.id); + await waitFor(() => session.model?.id === largeModel.id); - expect(session.model?.provider).toBe(codexModel.provider); - expect(session.model?.id).toBe(codexModel.id); + expect(session.model?.provider).toBe(largeModel.provider); + expect(session.model?.id).toBe(largeModel.id); expect(closeSpy).toHaveBeenCalledTimes(1); expect(session.providerSessionState.size).toBe(0); }); it("promotes on 413 payload-too-large overflow errors", async () => { - const sparkModel = modelRegistry.find("openai-codex", "gpt-5.3-codex-spark"); - const codexModel = modelRegistry.find("openai-codex", "gpt-5.5"); - if (!sparkModel || !codexModel) { - throw new Error("Expected codex spark and codex models to exist"); + const smallModel = modelRegistry.find("openai-codex", "gpt-5.5"); + const largeModel = modelRegistry.find("openai-codex", "gpt-5.6-sol"); + if (!smallModel || !largeModel) { + throw new Error("Expected small and large codex models to exist"); } const settings = Settings.isolated({ @@ -192,7 +214,7 @@ describe("AgentSession context promotion", () => { const agent = new Agent({ initialState: { - model: sparkModel, + model: smallModel, systemPrompt: ["Test"], tools: [], messages: [], @@ -207,19 +229,19 @@ describe("AgentSession context promotion", () => { }); const overflowMessage = createOverflowMessage( - sparkModel, + smallModel, "413 Request Entity Too Large: payload too large for model request body", ); session.agent.emitExternalEvent({ type: "message_end", message: overflowMessage }); session.agent.emitExternalEvent({ type: "agent_end", messages: [overflowMessage] }); - await waitFor(() => session.model?.id === codexModel.id); + await waitFor(() => session.model?.id === largeModel.id); - expect(session.model?.provider).toBe(codexModel.provider); - expect(session.model?.id).toBe(codexModel.id); + expect(session.model?.provider).toBe(largeModel.provider); + expect(session.model?.id).toBe(largeModel.id); }); it("clears codex provider session state on manual setModel switch away from codex", async () => { - const codexModel = modelRegistry.find("openai-codex", "gpt-5.3-codex"); + const codexModel = modelRegistry.find("openai-codex", "gpt-5.4"); const nonCodexModel = modelRegistry.getAll().find(model => model.api !== "openai-codex-responses"); if (!codexModel || !nonCodexModel) { throw new Error("Expected codex and non-codex models to exist"); @@ -256,7 +278,7 @@ describe("AgentSession context promotion", () => { }); it("clears codex provider session state on manual temporary switch into codex", async () => { - const codexModel = modelRegistry.find("openai-codex", "gpt-5.3-codex"); + const codexModel = modelRegistry.find("openai-codex", "gpt-5.4"); const nonCodexModel = modelRegistry.getAll().find(model => model.api !== "openai-codex-responses"); if (!codexModel || !nonCodexModel) { throw new Error("Expected codex and non-codex models to exist"); @@ -293,7 +315,7 @@ describe("AgentSession context promotion", () => { }); it("clears codex provider session state when branching rewrites history", async () => { - const codexModel = modelRegistry.find("openai-codex", "gpt-5.3-codex"); + const codexModel = modelRegistry.find("openai-codex", "gpt-5.4"); if (!codexModel) { throw new Error("Expected codex model to exist"); } @@ -334,7 +356,7 @@ describe("AgentSession context promotion", () => { }); it("clears codex provider session state when tree navigation rewrites history", async () => { - const codexModel = modelRegistry.find("openai-codex", "gpt-5.3-codex"); + const codexModel = modelRegistry.find("openai-codex", "gpt-5.4"); if (!codexModel) { throw new Error("Expected codex model to exist"); } @@ -375,9 +397,9 @@ describe("AgentSession context promotion", () => { }); it("does not promote when promotion is disabled", async () => { - const sparkModel = modelRegistry.find("openai-codex", "gpt-5.3-codex-spark"); - if (!sparkModel) { - throw new Error("Expected codex spark model to exist"); + const smallModel = modelRegistry.find("openai-codex", "gpt-5.5"); + if (!smallModel) { + throw new Error("Expected small codex model to exist"); } const settings = Settings.isolated({ @@ -387,7 +409,7 @@ describe("AgentSession context promotion", () => { const agent = new Agent({ initialState: { - model: sparkModel, + model: smallModel, systemPrompt: ["Test"], tools: [], messages: [], @@ -406,27 +428,27 @@ describe("AgentSession context promotion", () => { close: closeSpy, } satisfies ProviderSessionState); - const overflowMessage = createOverflowMessage(sparkModel); + const overflowMessage = createOverflowMessage(smallModel); session.agent.emitExternalEvent({ type: "message_end", message: overflowMessage }); session.agent.emitExternalEvent({ type: "agent_end", messages: [overflowMessage] }); await settle(); - expect(session.model?.provider).toBe(sparkModel.provider); - expect(session.model?.id).toBe(sparkModel.id); + expect(session.model?.provider).toBe(smallModel.provider); + expect(session.model?.id).toBe(smallModel.id); expect(closeSpy).not.toHaveBeenCalled(); expect(session.providerSessionState.size).toBe(1); }); it("does not promote by default", async () => { - const sparkModel = modelRegistry.find("openai-codex", "gpt-5.3-codex-spark"); - if (!sparkModel) { - throw new Error("Expected codex spark model to exist"); + const smallModel = modelRegistry.find("openai-codex", "gpt-5.5"); + if (!smallModel) { + throw new Error("Expected small codex model to exist"); } const agent = new Agent({ initialState: { - model: sparkModel, + model: smallModel, systemPrompt: ["Test"], tools: [], messages: [], @@ -440,20 +462,20 @@ describe("AgentSession context promotion", () => { modelRegistry, }); - const overflowMessage = createOverflowMessage(sparkModel); + const overflowMessage = createOverflowMessage(smallModel); session.agent.emitExternalEvent({ type: "message_end", message: overflowMessage }); session.agent.emitExternalEvent({ type: "agent_end", messages: [overflowMessage] }); await settle(); - expect(session.model?.provider).toBe(sparkModel.provider); - expect(session.model?.id).toBe(sparkModel.id); + expect(session.model?.provider).toBe(smallModel.provider); + expect(session.model?.id).toBe(smallModel.id); }); it("falls back to LLM compaction when snapcompact cannot run during overflow recovery", async () => { - const model = modelRegistry.find("openai-codex", "gpt-5.3-codex-spark"); + const model = modelRegistry.find("openai-codex", "gpt-5.4-mini"); if (!model) { - throw new Error("Expected codex spark model to exist"); + throw new Error("Expected codex model to exist"); } const settings = Settings.isolated({ "compaction.enabled": true, @@ -512,10 +534,10 @@ describe("AgentSession context promotion", () => { }); it("promotes to a larger-context model on response.incomplete (length stop)", async () => { - const sparkModel = modelRegistry.find("openai-codex", "gpt-5.3-codex-spark"); - const codexModel = modelRegistry.find("openai-codex", "gpt-5.5"); - if (!sparkModel || !codexModel) { - throw new Error("Expected codex spark and codex models to exist"); + const smallModel = modelRegistry.find("openai-codex", "gpt-5.5"); + const largeModel = modelRegistry.find("openai-codex", "gpt-5.6-sol"); + if (!smallModel || !largeModel) { + throw new Error("Expected small and large codex models to exist"); } const settings = Settings.isolated({ @@ -525,7 +547,7 @@ describe("AgentSession context promotion", () => { const agent = new Agent({ initialState: { - model: sparkModel, + model: smallModel, systemPrompt: ["Test"], tools: [], messages: [], @@ -539,24 +561,24 @@ describe("AgentSession context promotion", () => { modelRegistry, }); - const incompleteMessage = createIncompleteMessage(sparkModel); + const incompleteMessage = createIncompleteMessage(smallModel); session.agent.emitExternalEvent({ type: "message_end", message: incompleteMessage }); session.agent.emitExternalEvent({ type: "agent_end", messages: [incompleteMessage] }); - await waitFor(() => session.model?.id === codexModel.id); + await waitFor(() => session.model?.id === largeModel.id); - expect(session.model?.provider).toBe(codexModel.provider); - expect(session.model?.id).toBe(codexModel.id); + expect(session.model?.provider).toBe(largeModel.provider); + expect(session.model?.id).toBe(largeModel.id); }); it("does not promote on length stop when message is from a different model", async () => { // Switching from a small-context model to a larger one and then receiving a // stale length-stop event for the previous model must NOT trigger promotion // or compaction on the new model — same guard as the overflow path. - const sparkModel = modelRegistry.find("openai-codex", "gpt-5.3-codex-spark"); - const codexModel = modelRegistry.find("openai-codex", "gpt-5.5"); - if (!sparkModel || !codexModel) { - throw new Error("Expected codex spark and codex models to exist"); + const smallModel = modelRegistry.find("openai-codex", "gpt-5.5"); + const largeModel = modelRegistry.find("openai-codex", "gpt-5.6-sol"); + if (!smallModel || !largeModel) { + throw new Error("Expected small and large codex models to exist"); } const settings = Settings.isolated({ @@ -566,7 +588,7 @@ describe("AgentSession context promotion", () => { const agent = new Agent({ initialState: { - model: codexModel, + model: largeModel, systemPrompt: ["Test"], tools: [], messages: [], @@ -580,14 +602,14 @@ describe("AgentSession context promotion", () => { modelRegistry, }); - // Stale incomplete from the smaller model — current session is already on codex. - const staleIncomplete = createIncompleteMessage(sparkModel); + // Stale incomplete from the smaller model — current session is already on the large model. + const staleIncomplete = createIncompleteMessage(smallModel); session.agent.emitExternalEvent({ type: "message_end", message: staleIncomplete }); session.agent.emitExternalEvent({ type: "agent_end", messages: [staleIncomplete] }); await settle(); - expect(session.model?.provider).toBe(codexModel.provider); - expect(session.model?.id).toBe(codexModel.id); + expect(session.model?.provider).toBe(largeModel.provider); + expect(session.model?.id).toBe(largeModel.id); }); }); diff --git a/packages/coding-agent/test/agent-session-openai-responses-replay.test.ts b/packages/coding-agent/test/agent-session-openai-responses-replay.test.ts index 78257a81a..cff424b55 100644 --- a/packages/coding-agent/test/agent-session-openai-responses-replay.test.ts +++ b/packages/coding-agent/test/agent-session-openai-responses-replay.test.ts @@ -371,7 +371,7 @@ describe("AgentSession OpenAI Responses replay boundaries", () => { appendStaleAssistantTurn(sessionManager, assistantText, { api: "openai-codex-responses", provider: "openai-codex", - model: "gpt-5.2-codex", + model: "gpt-5.5", }); }); @@ -422,12 +422,12 @@ describe("AgentSession OpenAI Responses replay boundaries", () => { const assistantText = "Reloaded assistant response"; const { sessionFile } = await createPersistedSession(tempDir, sessionManager => { - sessionManager.appendModelChange("openai-codex/gpt-5.2-codex"); + sessionManager.appendModelChange("openai-codex/gpt-5.5"); sessionManager.appendMessage({ role: "user", content: "Reload summary", timestamp: Date.now() - 2 }); appendStaleAssistantTurn(sessionManager, assistantText, { api: "openai-codex-responses", provider: "openai-codex", - model: "gpt-5.2-codex", + model: "gpt-5.5", }); sessionManager.appendMessage({ role: "user", content: "Reload follow-up", timestamp: Date.now() - 1 }); }); @@ -435,7 +435,7 @@ describe("AgentSession OpenAI Responses replay boundaries", () => { const reloadedSessionManager = await SessionManager.open(sessionFile, tempDir); const { session } = await createSessionHarness(tempDir, reloadedSessionManager, { provider: "openai-codex", - modelId: "gpt-5.2-codex", + modelId: "gpt-5.5", }); sessions.push(session); @@ -461,18 +461,18 @@ describe("AgentSession OpenAI Responses replay boundaries", () => { const assistantText = "Reloaded metadata-only response"; const { sessionFile } = await createPersistedSession(tempDir, sessionManager => { - sessionManager.appendModelChange("openai-codex/gpt-5.2-codex"); + sessionManager.appendModelChange("openai-codex/gpt-5.5"); appendStaleAssistantTurn(sessionManager, assistantText, { api: "openai-codex-responses", provider: "openai-codex", - model: "gpt-5.2-codex", + model: "gpt-5.5", }); }); const reloadedSessionManager = await SessionManager.open(sessionFile, tempDir); const { session } = await createSessionHarness(tempDir, reloadedSessionManager, { provider: "openai-codex", - modelId: "gpt-5.2-codex", + modelId: "gpt-5.5", }); sessions.push(session); @@ -497,7 +497,7 @@ describe("AgentSession OpenAI Responses replay boundaries", () => { expect(closeSpy).not.toHaveBeenCalled(); expect(session.providerSessionState.size).toBe(1); expect(session.model?.provider).toBe("openai-codex"); - expect(session.model?.id).toBe("gpt-5.2-codex"); + expect(session.model?.id).toBe("gpt-5.5"); expectAssistantReplayMetadataPreserved(findRuntimeAssistant(session, assistantText)); }); @@ -552,18 +552,18 @@ describe("AgentSession OpenAI Responses replay boundaries", () => { const assistantText = "Reloaded content change response"; const { sessionFile } = await createPersistedSession(tempDir, sessionManager => { - sessionManager.appendModelChange("openai-codex/gpt-5.2-codex"); + sessionManager.appendModelChange("openai-codex/gpt-5.5"); appendStaleAssistantTurn(sessionManager, assistantText, { api: "openai-codex-responses", provider: "openai-codex", - model: "gpt-5.2-codex", + model: "gpt-5.5", }); }); const reloadedSessionManager = await SessionManager.open(sessionFile, tempDir); const { session } = await createSessionHarness(tempDir, reloadedSessionManager, { provider: "openai-codex", - modelId: "gpt-5.2-codex", + modelId: "gpt-5.5", }); sessions.push(session); @@ -584,7 +584,7 @@ describe("AgentSession OpenAI Responses replay boundaries", () => { expect(closeSpy).toHaveBeenCalledTimes(1); expect(session.providerSessionState.size).toBe(0); expect(session.model?.provider).toBe("openai-codex"); - expect(session.model?.id).toBe("gpt-5.2-codex"); + expect(session.model?.id).toBe("gpt-5.5"); expect( session.messages.some( message => message.role === "user" && getTextContent(message) === "Externally appended follow-up", @@ -598,18 +598,18 @@ describe("AgentSession OpenAI Responses replay boundaries", () => { const assistantText = "Reloaded model change response"; const { sessionFile } = await createPersistedSession(tempDir, sessionManager => { - sessionManager.appendModelChange("openai-codex/gpt-5.2-codex"); + sessionManager.appendModelChange("openai-codex/gpt-5.5"); appendStaleAssistantTurn(sessionManager, assistantText, { api: "openai-codex-responses", provider: "openai-codex", - model: "gpt-5.2-codex", + model: "gpt-5.5", }); }); const reloadedSessionManager = await SessionManager.open(sessionFile, tempDir); const { session } = await createSessionHarness(tempDir, reloadedSessionManager, { provider: "openai-codex", - modelId: "gpt-5.2-codex", + modelId: "gpt-5.5", }); sessions.push(session); diff --git a/packages/coding-agent/test/agent-session-retry-fallback.test.ts b/packages/coding-agent/test/agent-session-retry-fallback.test.ts index 55b0bc1c0..59bf8da64 100644 --- a/packages/coding-agent/test/agent-session-retry-fallback.test.ts +++ b/packages/coding-agent/test/agent-session-retry-fallback.test.ts @@ -300,7 +300,7 @@ describe("AgentSession retry fallback", () => { it("applies a model-keyed fallback chain to advisor quota failures", async () => { const mainModel = getBundledModel("openai", "gpt-4o-mini"); - const advisorPrimary = getBundledModel("devin", "gpt-5-6-sol"); + const advisorPrimary = getBundledModel("devin", "swe-1-6-slow"); const advisorFallback = getBundledModel("openai-codex", "gpt-5.6-sol"); if (!mainModel || !advisorPrimary || !advisorFallback) { throw new Error("Expected bundled advisor fallback models to exist"); @@ -390,7 +390,9 @@ describe("AgentSession retry fallback", () => { expect(fallbackAppliedEvents).toEqual([ { type: "retry_fallback_applied", - from: `${advisorPrimarySelector}:medium`, + // devin-agent models expose no controllable effort (#4579), so the + // advisor selector renders without a `:level` suffix. + from: advisorPrimarySelector, to: advisorFallbackSelector, role: advisorPrimarySelector, }, @@ -398,7 +400,9 @@ describe("AgentSession retry fallback", () => { expect(fallbackSucceededEvents).toEqual([ { type: "retry_fallback_succeeded", - model: `${advisorFallbackSelector}:medium`, + // The fallback inherits the primary's (effort-less) thinking level, + // so its selector renders without a suffix too. + model: advisorFallbackSelector, role: advisorPrimarySelector, }, ]);