diff --git a/packages/coding-agent/src/main.ts b/packages/coding-agent/src/main.ts index 954c206ec..ee25259b0 100644 --- a/packages/coding-agent/src/main.ts +++ b/packages/coding-agent/src/main.ts @@ -789,7 +789,8 @@ export function applyResolvedSystemPromptInputs( } } -async function buildSessionOptions( +/** Builds startup session options from parsed CLI flags, scoped models, and resolved session lineage. */ +export async function buildSessionOptions( parsed: Args, scopedModels: ScopedModel[], sessionManager: SessionManager | undefined, @@ -825,7 +826,9 @@ async function buildSessionOptions( options.providerPromptCacheKeySource = "explicit"; } else { const header = sessionManager?.getHeader(); + const scopedModelOverride = scopedModels.length > 0 && !parsed.continue && !parsed.resume; const forkCacheShapeChanged = + scopedModelOverride || parsed.model !== undefined || parsed.thinking !== undefined || parsed.systemPrompt !== undefined || diff --git a/packages/coding-agent/test/session-fork-prompt-cache-key.test.ts b/packages/coding-agent/test/session-fork-prompt-cache-key.test.ts index f16fd84d9..1c64a15e4 100644 --- a/packages/coding-agent/test/session-fork-prompt-cache-key.test.ts +++ b/packages/coding-agent/test/session-fork-prompt-cache-key.test.ts @@ -4,7 +4,10 @@ import * as path from "node:path"; import { ThinkingLevel } from "@oh-my-pi/pi-agent-core"; import { getBundledModel } from "@oh-my-pi/pi-catalog/models"; import { type Args, parseArgs } from "@oh-my-pi/pi-coding-agent/cli/args"; +import { ModelRegistry } from "@oh-my-pi/pi-coding-agent/config/model-registry"; +import type { ScopedModel } from "@oh-my-pi/pi-coding-agent/config/model-resolver"; import { Settings } from "@oh-my-pi/pi-coding-agent/config/settings"; +import { buildSessionOptions } from "@oh-my-pi/pi-coding-agent/main"; import { type CreateAgentSessionOptions, createAgentSession } from "@oh-my-pi/pi-coding-agent/sdk"; import type { AgentSession } from "@oh-my-pi/pi-coding-agent/session/agent-session"; import { AuthStorage } from "@oh-my-pi/pi-coding-agent/session/auth-storage"; @@ -191,4 +194,40 @@ describe("provider prompt-cache key session affinity", () => { } } }); + + it("does not pre-pin parent prompt-cache affinity when a scoped model selects the startup route", async () => { + using tempDir = TempDir.createSync("@omp-prompt-cache-scoped-model-"); + const source = await createSourceSessionFixture(tempDir, "parent-cache-session-scoped"); + const forkedManager = await SessionManager.forkFrom(source.sourceFile, source.cwd, source.forkSessionDir); + const authStorage = await AuthStorage.create(tempDir.join("scoped-auth.db")); + authStorage.setRuntimeApiKey(OPENAI_TEST_MODEL.provider, "test-key"); + try { + const modelRegistry = new ModelRegistry(authStorage, tempDir.join("models.yml")); + const parsed = parseArgs([ + "--cwd", + source.cwd, + "--models", + `${OPENAI_TEST_MODEL.provider}/${OPENAI_TEST_MODEL.id}`, + ]); + const scopedModels: ScopedModel[] = [ + { + model: OPENAI_TEST_MODEL, + explicitThinkingLevel: false, + }, + ]; + + const options = await buildSessionOptions( + parsed, + scopedModels, + forkedManager, + modelRegistry, + Settings.isolated({ "marketplace.autoUpdate": "off" }), + ); + + expect(options.model).toBe(OPENAI_TEST_MODEL); + expect(options.providerPromptCacheKey).toBeUndefined(); + } finally { + authStorage.close(); + } + }); });