diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 801d73776..818c79c7b 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -15,6 +15,10 @@ - Fixed read-only collab sessions so prompting, interrupts, and other write actions are blocked with a read-only warning instead of being applied +### Fixed + +- Fixed the interactive Model scope startup banner so models without an explicit thinking level do not show `:undefined`, and entries that were scoped without a `:level` are no longer rendered with the global default thinking level (which `applyRootSessionOptions` pre-fills on the cycling array for Ctrl+P) ([#2385](https://github.com/can1357/oh-my-pi/issues/2385)). + ## [15.11.8] - 2026-06-12 ### Added diff --git a/packages/coding-agent/src/main.ts b/packages/coding-agent/src/main.ts index 61c128380..5b2608af9 100644 --- a/packages/coding-agent/src/main.ts +++ b/packages/coding-agent/src/main.ts @@ -245,7 +245,7 @@ export interface InteractiveModeNotify { } export function buildModelScopeNotification( - scopedModelsForDisplay: readonly Pick[], + scopedModelsForDisplay: readonly Pick[], startupQuiet: boolean, ): InteractiveModeNotify | null { if (startupQuiet || scopedModelsForDisplay.length === 0) { @@ -253,13 +253,15 @@ export function buildModelScopeNotification( } const modelList = scopedModelsForDisplay .map(scopedModel => { - const thinkingStr = scopedModel.thinkingLevel ? `:${scopedModel.thinkingLevel}` : ""; + const thinkingStr = + scopedModel.explicitThinkingLevel && scopedModel.thinkingLevel + ? `:${scopedModel.thinkingLevel}` + : ""; return `${scopedModel.model.id}${thinkingStr}`; }) .join(", "); return { kind: "info", message: `Model scope: ${modelList} (Ctrl+P to cycle)` }; } - export async function submitInteractiveInput( mode: Pick< InteractiveMode, @@ -1283,9 +1285,8 @@ export async function runRootCommand( const versionCheckPromise = checkForNewVersion(VERSION).catch(() => undefined); const changelogMarkdown = await logger.time("main:getChangelogForDisplay", getChangelogForDisplay, parsedArgs); - const scopedModelsForDisplay = sessionOptions.scopedModels ?? scopedModels; const modelScopeNotification = buildModelScopeNotification( - scopedModelsForDisplay, + scopedModels, settingsInstance.get("startup.quiet"), ); if (modelScopeNotification) { diff --git a/packages/coding-agent/test/main-model-scope-notification.test.ts b/packages/coding-agent/test/main-model-scope-notification.test.ts index 34bbde893..74ac039f8 100644 --- a/packages/coding-agent/test/main-model-scope-notification.test.ts +++ b/packages/coding-agent/test/main-model-scope-notification.test.ts @@ -1,8 +1,8 @@ import { describe, expect, it } from "bun:test"; import { buildModel } from "@oh-my-pi/pi-catalog/build"; import type { ScopedModel } from "@oh-my-pi/pi-coding-agent/config/model-resolver"; +import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core"; import { buildModelScopeNotification } from "@oh-my-pi/pi-coding-agent/main"; - function scopedModel(id: string): ScopedModel { return { model: buildModel({ @@ -32,4 +32,22 @@ describe("buildModelScopeNotification", () => { message: "Model scope: claude-sonnet-4-5 (Ctrl+P to cycle)", }); }); + it("includes thinking suffix only when explicitly scoped", () => { + const withExplicit = { ...scopedModel("claude-sonnet-4-5"), thinkingLevel: "high" as ThinkingLevel, explicitThinkingLevel: true }; + expect(buildModelScopeNotification([withExplicit], false)).toEqual({ + kind: "info", + message: "Model scope: claude-sonnet-4-5:high (Ctrl+P to cycle)", + }); + }); + + it("hides the suffix when the level was filled from the global default", () => { + // `applyRootSessionOptions` fills `sessionOptions.scopedModels[*].thinkingLevel` + // with the global default for Ctrl+P cycling — the banner must not surface that + // default as if the user had scoped `:high`. + const withDefault = { ...scopedModel("claude-sonnet-4-5"), thinkingLevel: "high" as ThinkingLevel, explicitThinkingLevel: false }; + expect(buildModelScopeNotification([withDefault], false)).toEqual({ + kind: "info", + message: "Model scope: claude-sonnet-4-5 (Ctrl+P to cycle)", + }); + }); });