fix(model): respect task_metadata.json model selection (#415)

Model selection from UI was ignored because cli/main.py always
defaulted to Opus when no CLI arg was provided. This caused
get_phase_model() to bypass task_metadata.json since it treats
any non-None cli_model as an explicit override.

Backend fixes:
- Remove DEFAULT_MODEL fallback in cli/main.py so model is None
  when not explicitly set
- Update planner.py to use get_phase_model() like other agents

Frontend fixes:
- Sync defaultModel with selectedAgentProfile on save
- Add migration for existing users to fix stuck defaultModel

Closes #414

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Andy
2025-12-30 07:10:08 +01:00
committed by GitHub
parent 230de5fc03
commit e7e6b52128
4 changed files with 32 additions and 6 deletions
+5 -3
View File
@@ -9,7 +9,7 @@ import logging
from pathlib import Path
from core.client import create_client
from phase_config import get_phase_thinking_budget
from phase_config import get_phase_model, get_phase_thinking_budget
from phase_event import ExecutionPhase, emit_phase
from task_logger import (
LogPhase,
@@ -91,12 +91,14 @@ async def run_followup_planner(
task_logger.start_phase(LogPhase.PLANNING, "Starting follow-up planning...")
task_logger.set_session(1)
# Create client (fresh context) with planning phase thinking budget
# Create client with phase-specific model and thinking budget
# Respects task_metadata.json configuration when no CLI override
planning_model = get_phase_model(spec_dir, "planning", model)
planning_thinking_budget = get_phase_thinking_budget(spec_dir, "planning")
client = create_client(
project_dir,
spec_dir,
model,
planning_model,
max_thinking_tokens=planning_thinking_budget,
)
+3 -2
View File
@@ -276,8 +276,9 @@ def main() -> None:
project_dir = get_project_dir(args.project_dir)
debug("run.py", f"Using project directory: {project_dir}")
# Get model (with env var fallback)
model = args.model or os.environ.get("AUTO_BUILD_MODEL", DEFAULT_MODEL)
# Get model from CLI arg or env var (None if not explicitly set)
# This allows get_phase_model() to fall back to task_metadata.json
model = args.model or os.environ.get("AUTO_BUILD_MODEL")
# Handle --list command
if args.list:
@@ -3,7 +3,7 @@ import { existsSync, writeFileSync, mkdirSync, statSync } from 'fs';
import { execFileSync } from 'node:child_process';
import path from 'path';
import { is } from '@electron-toolkit/utils';
import { IPC_CHANNELS, DEFAULT_APP_SETTINGS } from '../../shared/constants';
import { IPC_CHANNELS, DEFAULT_APP_SETTINGS, DEFAULT_AGENT_PROFILES } from '../../shared/constants';
import type {
AppSettings,
IPCResult
@@ -111,6 +111,19 @@ export function registerSettingsHandlers(
needsSave = true;
}
// Migration: Sync defaultModel with selectedAgentProfile (#414)
// Fixes bug where defaultModel was stuck at 'opus' regardless of profile selection
if (!settings._migratedDefaultModelSync) {
if (settings.selectedAgentProfile) {
const profile = DEFAULT_AGENT_PROFILES.find(p => p.id === settings.selectedAgentProfile);
if (profile) {
settings.defaultModel = profile.model;
}
}
settings._migratedDefaultModelSync = true;
needsSave = true;
}
// If no manual autoBuildPath is set, try to auto-detect
if (!settings.autoBuildPath) {
const detectedPath = detectAutoBuildSourcePath();
@@ -149,6 +162,15 @@ export function registerSettingsHandlers(
const savedSettings = readSettingsFile();
const currentSettings = { ...DEFAULT_APP_SETTINGS, ...savedSettings };
const newSettings = { ...currentSettings, ...settings };
// Sync defaultModel when agent profile changes (#414)
if (settings.selectedAgentProfile) {
const profile = DEFAULT_AGENT_PROFILES.find(p => p.id === settings.selectedAgentProfile);
if (profile) {
newSettings.defaultModel = profile.model;
}
}
writeFileSync(settingsPath, JSON.stringify(newSettings, null, 2));
// Apply Python path if changed
@@ -255,6 +255,7 @@ export interface AppSettings {
betaUpdates?: boolean;
// Migration flags (internal use)
_migratedAgentProfileToAuto?: boolean;
_migratedDefaultModelSync?: boolean;
// Language preference for UI (i18n)
language?: SupportedLanguage;
// Developer tools preferences