From 04fe4be40f88db94ee701dbd7148c4bf04283d35 Mon Sep 17 00:00:00 2001 From: "paseo-bot[bot]" <266920839+paseo-bot[bot]@users.noreply.github.com> Date: Sun, 1 Nov 2026 18:59:04 +0000 Subject: [PATCH] fix(claude): retain configured model metadata before a turn (#8465) Rebuilding an idle session cleared its observed model and published null despite retaining an explicit model in its configuration. Fall back to that configuration until the next turn supplies an observed model. Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com> --- .../claude/agent.runtime-info.test.ts | 48 +++++++++++++++++++ .../server/agent/providers/claude/agent.ts | 2 +- 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 packages/server/src/server/agent/providers/claude/agent.runtime-info.test.ts diff --git a/packages/server/src/server/agent/providers/claude/agent.runtime-info.test.ts b/packages/server/src/server/agent/providers/claude/agent.runtime-info.test.ts new file mode 100644 index 0000000000..a23c95bc64 --- /dev/null +++ b/packages/server/src/server/agent/providers/claude/agent.runtime-info.test.ts @@ -0,0 +1,48 @@ +import pino from "pino"; +import { describe, expect, test } from "vitest"; + +import { ClaudeAgentClient } from "./agent.js"; + +describe("Claude runtime info before a turn", () => { + const client = new ClaudeAgentClient({ logger: pino({ level: "silent" }) }); + + test("reports the explicitly configured model before the first turn", async () => { + const session = await client.createSession({ + provider: "claude", + cwd: process.cwd(), + model: "claude-haiku-5-5", + }); + try { + expect(await session.getRuntimeInfo()).toMatchObject({ model: "claude-haiku-5-5" }); + } finally { + await session.close(); + } + }); + + test("reports the persisted configured model after rebuilding an idle session", async () => { + const session = await client.resumeSession({ + provider: "claude", + sessionId: "runtime-model-before-turn", + metadata: { cwd: process.cwd(), model: "claude-haiku-5-5" }, + }); + try { + expect(await session.getRuntimeInfo()).toMatchObject({ + sessionId: "runtime-model-before-turn", + model: "claude-haiku-5-5", + }); + expect((await session.getRuntimeInfo()).model).toBe("claude-haiku-5-5"); + expect((await session.getRuntimeInfo()).extra?.runtimeModel).toBeUndefined(); + } finally { + await session.close(); + } + }); + + test("leaves the model unknown when Claude will choose its default", async () => { + const session = await client.createSession({ provider: "claude", cwd: process.cwd() }); + try { + expect((await session.getRuntimeInfo()).model).toBeNull(); + } finally { + await session.close(); + } + }); +}); diff --git a/packages/server/src/server/agent/providers/claude/agent.ts b/packages/server/src/server/agent/providers/claude/agent.ts index ebb37e13f8..9895f433a8 100644 --- a/packages/server/src/server/agent/providers/claude/agent.ts +++ b/packages/server/src/server/agent/providers/claude/agent.ts @@ -2460,7 +2460,7 @@ class ClaudeAgentSession implements AgentSession { const info: AgentRuntimeInfo = { provider: "claude", sessionId: this.claudeSessionId, - model: this.lastOptionsModel, + model: this.lastOptionsModel ?? this.config.model ?? null, modeId: this.currentMode ?? null, ...(this.lastRuntimeModel ? {