From 73e152aa8d98c3f7657b6b934415975fa508bdb9 Mon Sep 17 00:00:00 2001 From: Jay Zhou Date: Fri, 16 Jan 2026 03:30:39 -0800 Subject: [PATCH] feat(ideation): add dedicated ideationModel setting and fix task model defaults Add a separate ideationModel configuration to give users granular control over which AI model powers the Ideation pane, distinct from suggestionsModel. Changes for ideationModel setting: - Add ideationModel to PhaseModelConfig interface (libs/types) - Add default value (sonnet) in DEFAULT_PHASE_MODELS - Add UI entry 'Ideation & Brainstorming' in Model Defaults settings - Update ideation-service.ts to use ideationModel for interactive chat Fix for task model defaults from ideation: - Pass settingsService to ideation routes - Update add-suggestion.ts to get defaultFeatureModel from settings - Features created from ideation suggestions now use the configured model This ensures: 1. Ideation chat uses the user's configured ideationModel 2. Tasks created from ideation use the user's defaultFeatureModel 3. No more hardcoded Anthropic model fallbacks --- apps/server/src/index.ts | 5 +++- apps/server/src/routes/ideation/index.ts | 6 +++-- .../routes/ideation/routes/add-suggestion.ts | 20 ++++++++++++++-- apps/server/src/services/ideation-service.ts | 24 +++++++++++++++++-- .../model-defaults/model-defaults-section.tsx | 5 ++++ libs/types/src/settings.ts | 3 +++ 6 files changed, 56 insertions(+), 7 deletions(-) diff --git a/apps/server/src/index.ts b/apps/server/src/index.ts index 3a59d4d3e..6cd509010 100644 --- a/apps/server/src/index.ts +++ b/apps/server/src/index.ts @@ -284,7 +284,10 @@ app.use('/api/context', createContextRoutes(settingsService)); app.use('/api/backlog-plan', createBacklogPlanRoutes(events, settingsService)); app.use('/api/mcp', createMCPRoutes(mcpTestService)); app.use('/api/pipeline', createPipelineRoutes(pipelineService)); -app.use('/api/ideation', createIdeationRoutes(events, ideationService, featureLoader)); +app.use( + '/api/ideation', + createIdeationRoutes(events, ideationService, featureLoader, settingsService) +); // Create HTTP server const server = createServer(app); diff --git a/apps/server/src/routes/ideation/index.ts b/apps/server/src/routes/ideation/index.ts index 95fe128be..91e7327e0 100644 --- a/apps/server/src/routes/ideation/index.ts +++ b/apps/server/src/routes/ideation/index.ts @@ -7,6 +7,7 @@ import type { EventEmitter } from '../../lib/events.js'; import { validatePathParams } from '../../middleware/validate-paths.js'; import type { IdeationService } from '../../services/ideation-service.js'; import type { FeatureLoader } from '../../services/feature-loader.js'; +import type { SettingsService } from '../../services/settings-service.js'; // Route handlers import { createSessionStartHandler } from './routes/session-start.js'; @@ -27,7 +28,8 @@ import { createSuggestionsGenerateHandler } from './routes/suggestions-generate. export function createIdeationRoutes( events: EventEmitter, ideationService: IdeationService, - featureLoader: FeatureLoader + featureLoader: FeatureLoader, + settingsService: SettingsService ): Router { const router = Router(); @@ -91,7 +93,7 @@ export function createIdeationRoutes( router.post( '/add-suggestion', validatePathParams('projectPath'), - createAddSuggestionHandler(ideationService, featureLoader) + createAddSuggestionHandler(ideationService, featureLoader, settingsService) ); // Guided prompts (no validation needed - static data) diff --git a/apps/server/src/routes/ideation/routes/add-suggestion.ts b/apps/server/src/routes/ideation/routes/add-suggestion.ts index 3326bfc38..0e54cb05c 100644 --- a/apps/server/src/routes/ideation/routes/add-suggestion.ts +++ b/apps/server/src/routes/ideation/routes/add-suggestion.ts @@ -4,17 +4,22 @@ * This endpoint converts an AnalysisSuggestion to a Feature using the * IdeationService's mapIdeaCategoryToFeatureCategory for consistent category mapping. * This ensures a single source of truth for the conversion logic. + * + * The feature is created with the user's configured defaultFeatureModel from settings, + * ensuring consistency with manually created features. */ import type { Request, Response } from 'express'; import type { IdeationService } from '../../../services/ideation-service.js'; import type { FeatureLoader } from '../../../services/feature-loader.js'; +import type { SettingsService } from '../../../services/settings-service.js'; import type { AnalysisSuggestion } from '@automaker/types'; import { getErrorMessage, logError } from '../common.js'; export function createAddSuggestionHandler( ideationService: IdeationService, - featureLoader: FeatureLoader + featureLoader: FeatureLoader, + settingsService: SettingsService ) { return async (req: Request, res: Response): Promise => { try { @@ -53,12 +58,23 @@ export function createAddSuggestionHandler( suggestion.category ); - // Create the feature + // Get the default feature model from user settings + let model: string | undefined; + try { + const settings = await settingsService.getGlobalSettings(); + model = settings.defaultFeatureModel?.model; + } catch (error) { + // If settings fail to load, proceed without a model (will use system default) + logError(error, 'Failed to get default feature model from settings'); + } + + // Create the feature with the configured default model const feature = await featureLoader.create(projectPath, { title: suggestion.title, description, category: featureCategory, status: 'backlog', + ...(model && { model }), // Only include model if it was retrieved }); res.json({ success: true, featureId: feature.id }); diff --git a/apps/server/src/services/ideation-service.ts b/apps/server/src/services/ideation-service.ts index 4ef3d8a8e..bfd65b122 100644 --- a/apps/server/src/services/ideation-service.ts +++ b/apps/server/src/services/ideation-service.ts @@ -208,7 +208,17 @@ export class IdeationService { ); // Resolve model alias to canonical identifier (with prefix) - const modelId = resolveModelString(options?.model ?? 'sonnet'); + let defaultModel = 'sonnet'; + if (this.settingsService) { + try { + const settings = await this.settingsService.getGlobalSettings(); + defaultModel = settings.phaseModels.ideationModel.model; + } catch (error) { + logger.warn('Failed to get settings for model selection, using default', error); + } + } + + const modelId = resolveModelString(options?.model ?? defaultModel); // Create SDK options const sdkOptions = createChatOptions({ @@ -663,7 +673,17 @@ export class IdeationService { ); // Resolve model alias to canonical identifier (with prefix) - const modelId = resolveModelString('sonnet'); + let modelToUse = 'sonnet'; + if (this.settingsService) { + try { + const settings = await this.settingsService.getGlobalSettings(); + modelToUse = settings.phaseModels.suggestionsModel.model; + } catch (error) { + logger.warn('Failed to get settings for model selection, using default', error); + } + } + + const modelId = resolveModelString(modelToUse); // Create SDK options const sdkOptions = createChatOptions({ diff --git a/apps/ui/src/components/views/settings-view/model-defaults/model-defaults-section.tsx b/apps/ui/src/components/views/settings-view/model-defaults/model-defaults-section.tsx index 37f3e72d5..c607cde2b 100644 --- a/apps/ui/src/components/views/settings-view/model-defaults/model-defaults-section.tsx +++ b/apps/ui/src/components/views/settings-view/model-defaults/model-defaults-section.tsx @@ -69,6 +69,11 @@ const GENERATION_TASKS: PhaseConfig[] = [ label: 'AI Suggestions', description: 'Model for feature, refactoring, security, and performance suggestions', }, + { + key: 'ideationModel', + label: 'Ideation & Brainstorming', + description: 'Interactive brainstorming and idea generation sessions', + }, ]; const MEMORY_TASKS: PhaseConfig[] = [ diff --git a/libs/types/src/settings.ts b/libs/types/src/settings.ts index 6e807f665..f10f81bf8 100644 --- a/libs/types/src/settings.ts +++ b/libs/types/src/settings.ts @@ -247,6 +247,8 @@ export interface PhaseModelConfig { projectAnalysisModel: PhaseModelEntry; /** Model for AI suggestions (feature, refactoring, security, performance) */ suggestionsModel: PhaseModelEntry; + /** Model for interactive ideation and brainstorming sessions */ + ideationModel: PhaseModelEntry; // Memory tasks - for learning extraction and memory operations /** Model for extracting learnings from completed agent sessions */ @@ -777,6 +779,7 @@ export const DEFAULT_PHASE_MODELS: PhaseModelConfig = { backlogPlanningModel: { model: 'sonnet' }, projectAnalysisModel: { model: 'sonnet' }, suggestionsModel: { model: 'sonnet' }, + ideationModel: { model: 'sonnet' }, // Memory - use fast model for learning extraction (cost-effective) memoryExtractionModel: { model: 'haiku' },