diff --git a/src/server/api/models.ts b/src/server/api/models.ts index 480741b4..edbb3ec5 100644 --- a/src/server/api/models.ts +++ b/src/server/api/models.ts @@ -107,27 +107,58 @@ async function handleModelsList(): Promise { async function handleCurrentModel(req: Request): Promise { if (req.method === 'GET') { const settings = await settingsService.getUserSettings() - const baseModelId = (settings.model as string) || DEFAULT_MODEL + const explicitModel = (settings.model as string) || '' const contextTier = (settings.modelContext as string) || undefined + const env = (settings.env as Record) || {} // Build the full model list: prefer active provider's models, fall back to defaults const { providers, activeId } = await providerService.listProviders() const activeProvider = activeId ? providers.find((p) => p.id === activeId) : null + + let currentModelId: string + let currentModelName: string + + if (activeProvider) { + // Provider is active — use the model from env (set by syncToSettings when provider was activated) + // unless user explicitly set a different model ID in settings + const providerEnvModel = env.ANTHROPIC_MODEL + if (providerEnvModel && (!explicitModel || explicitModel === DEFAULT_MODEL)) { + // No explicit model override — use the provider's configured model + currentModelId = providerEnvModel + currentModelName = providerEnvModel + } else { + // User explicitly set a model (possibly from the provider's model list) + currentModelId = explicitModel || providerEnvModel || activeProvider.models.main + currentModelName = currentModelId + } + } else { + // No provider — use settings model with context tier + currentModelId = explicitModel || DEFAULT_MODEL + currentModelName = currentModelId + } + + const lookupId = contextTier ? `${currentModelId}:${contextTier}` : currentModelId + + // Build available models for name lookup const availableModels = activeProvider - ? [{ id: activeProvider.models.main, name: activeProvider.models.main, description: 'Main model', context: '' }] + ? [ + { id: activeProvider.models.main, name: activeProvider.models.main, description: 'Main model', context: '' }, + ...(activeProvider.models.haiku && activeProvider.models.haiku !== activeProvider.models.main ? [{ id: activeProvider.models.haiku, name: activeProvider.models.haiku, description: 'Haiku model', context: '' }] : []), + ...(activeProvider.models.sonnet && activeProvider.models.sonnet !== activeProvider.models.main ? [{ id: activeProvider.models.sonnet, name: activeProvider.models.sonnet, description: 'Sonnet model', context: '' }] : []), + ...(activeProvider.models.opus && activeProvider.models.opus !== activeProvider.models.main ? [{ id: activeProvider.models.opus, name: activeProvider.models.opus, description: 'Opus model', context: '' }] : []), + ] : DEFAULT_MODELS - // Reconstruct composite ID for lookup (e.g. 'claude-opus-4-6-20250610:1m') - const lookupId = contextTier ? `${baseModelId}:${contextTier}` : baseModelId - const model = availableModels.find((m) => m.id === lookupId) - || availableModels.find((m) => m.id === baseModelId) + const modelEntry = availableModels.find((m) => m.id === lookupId) + || availableModels.find((m) => m.id === currentModelId) || { - id: baseModelId, - name: baseModelId, + id: currentModelId, + name: currentModelName, description: 'Custom model', - context: 'unknown', + context: contextTier || 'unknown', } - return Response.json({ model }) + + return Response.json({ model: { ...modelEntry, context: contextTier || modelEntry.context } }) } if (req.method === 'PUT') { diff --git a/src/server/ws/handler.ts b/src/server/ws/handler.ts index dbf3a70a..684a8eb6 100644 --- a/src/server/ws/handler.ts +++ b/src/server/ws/handler.ts @@ -14,8 +14,10 @@ import { } from '../services/conversationService.js' import { sessionService } from '../services/sessionService.js' import { SettingsService } from '../services/settingsService.js' +import { ProviderService } from '../services/providerService.js' const settingsService = new SettingsService() +const providerService = new ProviderService() /** * Cache slash commands from CLI init messages, keyed by sessionId. @@ -566,10 +568,6 @@ async function getRuntimeSettings(): Promise<{ effort?: string }> { const userSettings = await settingsService.getUserSettings() - const baseModel = - typeof userSettings.model === 'string' && userSettings.model.trim() - ? userSettings.model - : undefined const modelContext = typeof userSettings.modelContext === 'string' && userSettings.modelContext.trim() ? userSettings.modelContext @@ -579,9 +577,32 @@ async function getRuntimeSettings(): Promise<{ ? userSettings.effort : undefined + // Check if a custom provider is active + const { activeId } = await providerService.listProviders() + + let model: string | undefined + if (activeId) { + // Provider is active — only pass --model if user explicitly selected a non-default model. + // Otherwise the CLI should use ANTHROPIC_MODEL from env (set by syncToSettings). + // Default Anthropic model should be overridden by the provider's model. + const baseModel = (userSettings.model as string) || '' + if (baseModel && baseModel !== 'claude-sonnet-4-6-20250514') { + // User explicitly selected a different model — pass it through + model = baseModel + if (modelContext) model += `:${modelContext}` + } + } else { + // No provider — pass model normally + const baseModel = + typeof userSettings.model === 'string' && userSettings.model.trim() + ? userSettings.model + : undefined + model = baseModel ? (modelContext ? `${baseModel}:${modelContext}` : baseModel) : undefined + } + return { permissionMode: await settingsService.getPermissionMode().catch(() => undefined), - model: baseModel ? (modelContext ? `${baseModel}:${modelContext}` : baseModel) : undefined, + model, effort, } }