From 252c337456260c76db48b5e3dc4fb5176d94108f Mon Sep 17 00:00:00 2001 From: Junichi Kato Date: Sat, 28 Feb 2026 12:54:32 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20Global/Project=E3=81=AEmodel=E3=81=8CMod?= =?UTF-8?q?el=E3=83=AD=E3=82=B0=E3=81=AB=E5=8F=8D=E6=98=A0=E3=81=95?= =?UTF-8?q?=E3=82=8C=E3=81=AA=E3=81=84=E4=B8=8D=E5=85=B7=E5=90=88=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3=20(#417)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test: add regression for movement model log fallback * fix: use configured model for movement model logging --- .../pieceExecution-session-loading.test.ts | 27 +++++++++++++++++++ src/features/tasks/execute/pieceExecution.ts | 7 +++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/__tests__/pieceExecution-session-loading.test.ts b/src/__tests__/pieceExecution-session-loading.test.ts index bcc952c..5664378 100644 --- a/src/__tests__/pieceExecution-session-loading.test.ts +++ b/src/__tests__/pieceExecution-session-loading.test.ts @@ -155,8 +155,20 @@ vi.mock('../shared/exitCodes.js', () => ({ })); import { executePiece } from '../features/tasks/execute/pieceExecution.js'; +import { resolvePieceConfigValues } from '../infra/config/index.js'; import { info } from '../shared/ui/index.js'; +const defaultResolvedConfigValues = { + notificationSound: true, + notificationSoundEvents: {}, + provider: 'claude', + runtime: undefined, + preventSleep: false, + model: undefined, + observability: undefined, + analytics: undefined, +}; + function makeConfig(): PieceConfig { return { name: 'test-piece', @@ -178,6 +190,7 @@ function makeConfig(): PieceConfig { describe('executePiece session loading', () => { beforeEach(() => { vi.clearAllMocks(); + vi.mocked(resolvePieceConfigValues).mockReturnValue({ ...defaultResolvedConfigValues }); mockLoadPersonaSessions.mockReturnValue({ coder: 'saved-session-id' }); mockLoadWorktreeSessions.mockReturnValue({ coder: 'worktree-session-id' }); }); @@ -261,6 +274,20 @@ describe('executePiece session loading', () => { expect(mockInfo).toHaveBeenCalledWith('Model: (default)'); }); + it('should log configured model from global/project settings when movement model is unresolved', async () => { + vi.mocked(resolvePieceConfigValues).mockReturnValue({ + ...defaultResolvedConfigValues, + model: 'gpt-4.1', + }); + + await executePiece(makeConfig(), 'task', '/tmp/project', { + projectCwd: '/tmp/project', + }); + + const mockInfo = vi.mocked(info); + expect(mockInfo).toHaveBeenCalledWith('Model: gpt-4.1'); + }); + it('should log provider and model per movement with overrides', async () => { await executePiece(makeConfig(), 'task', '/tmp/project', { projectCwd: '/tmp/project', diff --git a/src/features/tasks/execute/pieceExecution.ts b/src/features/tasks/execute/pieceExecution.ts index b7a33d6..b386169 100644 --- a/src/features/tasks/execute/pieceExecution.ts +++ b/src/features/tasks/execute/pieceExecution.ts @@ -339,6 +339,7 @@ export async function executePiece( const shouldNotifyPieceComplete = shouldNotify && notificationSoundEvents?.pieceComplete !== false; const shouldNotifyPieceAbort = shouldNotify && notificationSoundEvents?.pieceAbort !== false; const currentProvider = globalConfig.provider; + const configuredModel = options.model ?? globalConfig.model; if (!currentProvider) { throw new Error('No provider configured. Set "provider" in ~/.takt/config.yaml'); } @@ -453,7 +454,7 @@ export async function executePiece( let lastMovementName: string | undefined; let currentIteration = 0; let currentMovementProvider = currentProvider; - let currentMovementModel = globalConfig.model ?? '(default)'; + let currentMovementModel = configuredModel ?? '(default)'; const phasePrompts = new Map(); const movementIterations = new Map(); let engine: PieceEngine | null = null; @@ -552,7 +553,9 @@ export async function executePiece( }); out.info(`[${iteration}/${pieceConfig.maxMovements}] ${step.name} (${step.personaDisplayName})`); const movementProvider = providerInfo.provider ?? currentProvider; - const movementModel = providerInfo.model ?? '(default)'; + const movementModel = providerInfo.model + ?? (movementProvider === currentProvider ? configuredModel : undefined) + ?? '(default)'; currentMovementProvider = movementProvider; currentMovementModel = movementModel; providerEventLogger.setMovement(step.name);