diff --git a/auto-claude-ui/src/main/insights-service.ts b/auto-claude-ui/src/main/insights-service.ts index 3a76d00d..59fe3cb2 100644 --- a/auto-claude-ui/src/main/insights-service.ts +++ b/auto-claude-ui/src/main/insights-service.ts @@ -2,7 +2,8 @@ import { EventEmitter } from 'events'; import type { InsightsSession, InsightsSessionSummary, - InsightsChatMessage + InsightsChatMessage, + InsightsModelConfig } from '../shared/types'; import { InsightsConfig } from './insights/config'; import { InsightsPaths } from './insights/paths'; @@ -111,7 +112,12 @@ export class InsightsService extends EventEmitter { /** * Send a message and get AI response */ - async sendMessage(projectId: string, projectPath: string, message: string): Promise { + async sendMessage( + projectId: string, + projectPath: string, + message: string, + modelConfig?: InsightsModelConfig + ): Promise { // Cancel any existing session this.executor.cancelSession(projectId); @@ -150,13 +156,17 @@ export class InsightsService extends EventEmitter { content: m.content })); + // Use provided modelConfig or fall back to session's config + const configToUse = modelConfig || session.modelConfig; + try { // Execute insights query const result = await this.executor.execute( projectId, projectPath, message, - conversationHistory + conversationHistory, + configToUse ); // Add assistant message to session @@ -177,6 +187,13 @@ export class InsightsService extends EventEmitter { console.error('[InsightsService] Error executing insights:', error); } } + + /** + * Update model configuration for a session + */ + updateSessionModelConfig(projectPath: string, sessionId: string, modelConfig: InsightsModelConfig): boolean { + return this.sessionManager.updateSessionModelConfig(projectPath, sessionId, modelConfig); + } } // Singleton instance diff --git a/auto-claude-ui/src/main/insights/insights-executor.ts b/auto-claude-ui/src/main/insights/insights-executor.ts index cf45fa90..ec0c01bf 100644 --- a/auto-claude-ui/src/main/insights/insights-executor.ts +++ b/auto-claude-ui/src/main/insights/insights-executor.ts @@ -6,8 +6,10 @@ import type { InsightsChatMessage, InsightsChatStatus, InsightsStreamChunk, - InsightsToolUsage + InsightsToolUsage, + InsightsModelConfig } from '../../shared/types'; +import { MODEL_ID_MAP } from '../../shared/constants'; import { InsightsConfig } from './config'; import { detectRateLimit, createSDKRateLimitInfo } from '../rate-limit-detector'; @@ -59,7 +61,8 @@ export class InsightsExecutor extends EventEmitter { projectId: string, projectPath: string, message: string, - conversationHistory: Array<{ role: string; content: string }> + conversationHistory: Array<{ role: string; content: string }>, + modelConfig?: InsightsModelConfig ): Promise { // Cancel any existing session this.cancelSession(projectId); @@ -69,7 +72,7 @@ export class InsightsExecutor extends EventEmitter { throw new Error('Auto Claude source not found'); } - const runnerPath = path.join(autoBuildSource, 'insights_runner.py'); + const runnerPath = path.join(autoBuildSource, 'runners', 'insights_runner.py'); if (!existsSync(runnerPath)) { throw new Error('insights_runner.py not found in auto-claude directory'); } @@ -83,13 +86,23 @@ export class InsightsExecutor extends EventEmitter { // Get process environment const processEnv = this.config.getProcessEnv(); - // Spawn Python process - const proc = spawn(this.config.getPythonPath(), [ + // Build command arguments + const args = [ runnerPath, '--project-dir', projectPath, '--message', message, '--history', JSON.stringify(conversationHistory) - ], { + ]; + + // Add model config if provided + if (modelConfig) { + const modelId = MODEL_ID_MAP[modelConfig.model] || MODEL_ID_MAP['sonnet']; + args.push('--model', modelId); + args.push('--thinking-level', modelConfig.thinkingLevel); + } + + // Spawn Python process + const proc = spawn(this.config.getPythonPath(), args, { cwd: autoBuildSource, env: processEnv }); diff --git a/auto-claude-ui/src/main/insights/session-manager.ts b/auto-claude-ui/src/main/insights/session-manager.ts index 7be98682..7293d527 100644 --- a/auto-claude-ui/src/main/insights/session-manager.ts +++ b/auto-claude-ui/src/main/insights/session-manager.ts @@ -1,4 +1,4 @@ -import type { InsightsSession, InsightsSessionSummary } from '../../shared/types'; +import type { InsightsSession, InsightsSessionSummary, InsightsModelConfig } from '../../shared/types'; import { SessionStorage } from './session-storage'; import { InsightsPaths } from './paths'; @@ -119,6 +119,30 @@ export class SessionManager { return true; } + /** + * Update model configuration for a session + */ + updateSessionModelConfig(projectPath: string, sessionId: string, modelConfig: InsightsModelConfig): boolean { + const session = this.storage.loadSessionById(projectPath, sessionId); + if (!session) return false; + + session.modelConfig = modelConfig; + session.updatedAt = new Date(); + this.storage.saveSession(projectPath, session); + + // Update cache if this session is cached + for (const [projectId, cachedSession] of this.sessions) { + if (cachedSession.id === sessionId) { + cachedSession.modelConfig = modelConfig; + cachedSession.updatedAt = new Date(); + this.sessions.set(projectId, cachedSession); + break; + } + } + + return true; + } + /** * Save session to disk and update cache */ diff --git a/auto-claude-ui/src/main/ipc-handlers/insights-handlers.ts b/auto-claude-ui/src/main/ipc-handlers/insights-handlers.ts index 8db91bc3..cef96a6d 100644 --- a/auto-claude-ui/src/main/ipc-handlers/insights-handlers.ts +++ b/auto-claude-ui/src/main/ipc-handlers/insights-handlers.ts @@ -3,7 +3,7 @@ import type { BrowserWindow } from 'electron'; import path from 'path'; import { existsSync, readdirSync, mkdirSync, writeFileSync } from 'fs'; import { IPC_CHANNELS, getSpecsDir, AUTO_BUILD_PATHS } from '../../shared/constants'; -import type { IPCResult, InsightsSession, InsightsSessionSummary, Task, TaskMetadata } from '../../shared/types'; +import type { IPCResult, InsightsSession, InsightsSessionSummary, InsightsModelConfig, Task, TaskMetadata } from '../../shared/types'; import { projectStore } from '../project-store'; import { insightsService } from '../insights-service'; @@ -32,7 +32,7 @@ export function registerInsightsHandlers( ipcMain.on( IPC_CHANNELS.INSIGHTS_SEND_MESSAGE, - async (_, projectId: string, message: string) => { + async (_, projectId: string, message: string, modelConfig?: InsightsModelConfig) => { const project = projectStore.getProject(projectId); if (!project) { const mainWindow = getMainWindow(); @@ -44,7 +44,7 @@ export function registerInsightsHandlers( // Note: Python environment initialization should be handled by insightsService // or added here with proper dependency injection if needed - insightsService.sendMessage(projectId, project.path, message); + insightsService.sendMessage(projectId, project.path, message, modelConfig); } ); @@ -241,4 +241,57 @@ export function registerInsightsHandlers( } ); + // Update model configuration for a session + ipcMain.handle( + IPC_CHANNELS.INSIGHTS_UPDATE_MODEL_CONFIG, + async (_, projectId: string, sessionId: string, modelConfig: InsightsModelConfig): Promise => { + const project = projectStore.getProject(projectId); + if (!project) { + return { success: false, error: 'Project not found' }; + } + + const success = insightsService.updateSessionModelConfig(project.path, sessionId, modelConfig); + if (success) { + return { success: true }; + } + return { success: false, error: 'Failed to update model configuration' }; + } + ); + + // ============================================ + // Insights Event Forwarding (Service -> Renderer) + // ============================================ + + // Forward streaming chunks to renderer + insightsService.on('stream-chunk', (projectId: string, chunk: unknown) => { + const mainWindow = getMainWindow(); + if (mainWindow) { + mainWindow.webContents.send(IPC_CHANNELS.INSIGHTS_STREAM_CHUNK, projectId, chunk); + } + }); + + // Forward status updates to renderer + insightsService.on('status', (projectId: string, status: unknown) => { + const mainWindow = getMainWindow(); + if (mainWindow) { + mainWindow.webContents.send(IPC_CHANNELS.INSIGHTS_STATUS, projectId, status); + } + }); + + // Forward errors to renderer + insightsService.on('error', (projectId: string, error: string) => { + const mainWindow = getMainWindow(); + if (mainWindow) { + mainWindow.webContents.send(IPC_CHANNELS.INSIGHTS_ERROR, projectId, error); + } + }); + + // Forward SDK rate limit events to renderer + insightsService.on('sdk-rate-limit', (rateLimitInfo: unknown) => { + const mainWindow = getMainWindow(); + if (mainWindow) { + mainWindow.webContents.send(IPC_CHANNELS.CLAUDE_SDK_RATE_LIMIT, rateLimitInfo); + } + }); + } diff --git a/auto-claude-ui/src/preload/api/modules/insights-api.ts b/auto-claude-ui/src/preload/api/modules/insights-api.ts index a058b4c6..0dc258f8 100644 --- a/auto-claude-ui/src/preload/api/modules/insights-api.ts +++ b/auto-claude-ui/src/preload/api/modules/insights-api.ts @@ -4,6 +4,7 @@ import type { InsightsSessionSummary, InsightsChatStatus, InsightsStreamChunk, + InsightsModelConfig, Task, TaskMetadata, IPCResult @@ -16,7 +17,7 @@ import { createIpcListener, invokeIpc, sendIpc, IpcListenerCleanup } from './ipc export interface InsightsAPI { // Operations getInsightsSession: (projectId: string) => Promise>; - sendInsightsMessage: (projectId: string, message: string) => void; + sendInsightsMessage: (projectId: string, message: string, modelConfig?: InsightsModelConfig) => void; clearInsightsSession: (projectId: string) => Promise; createTaskFromInsights: ( projectId: string, @@ -29,6 +30,7 @@ export interface InsightsAPI { switchInsightsSession: (projectId: string, sessionId: string) => Promise>; deleteInsightsSession: (projectId: string, sessionId: string) => Promise; renameInsightsSession: (projectId: string, sessionId: string, newTitle: string) => Promise; + updateInsightsModelConfig: (projectId: string, sessionId: string, modelConfig: InsightsModelConfig) => Promise; // Event Listeners onInsightsStreamChunk: ( @@ -50,8 +52,8 @@ export const createInsightsAPI = (): InsightsAPI => ({ getInsightsSession: (projectId: string): Promise> => invokeIpc(IPC_CHANNELS.INSIGHTS_GET_SESSION, projectId), - sendInsightsMessage: (projectId: string, message: string): void => - sendIpc(IPC_CHANNELS.INSIGHTS_SEND_MESSAGE, projectId, message), + sendInsightsMessage: (projectId: string, message: string, modelConfig?: InsightsModelConfig): void => + sendIpc(IPC_CHANNELS.INSIGHTS_SEND_MESSAGE, projectId, message, modelConfig), clearInsightsSession: (projectId: string): Promise => invokeIpc(IPC_CHANNELS.INSIGHTS_CLEAR_SESSION, projectId), @@ -79,6 +81,9 @@ export const createInsightsAPI = (): InsightsAPI => ({ renameInsightsSession: (projectId: string, sessionId: string, newTitle: string): Promise => invokeIpc(IPC_CHANNELS.INSIGHTS_RENAME_SESSION, projectId, sessionId, newTitle), + updateInsightsModelConfig: (projectId: string, sessionId: string, modelConfig: InsightsModelConfig): Promise => + invokeIpc(IPC_CHANNELS.INSIGHTS_UPDATE_MODEL_CONFIG, projectId, sessionId, modelConfig), + // Event Listeners onInsightsStreamChunk: ( callback: (projectId: string, chunk: InsightsStreamChunk) => void diff --git a/auto-claude-ui/src/renderer/components/CustomModelModal.tsx b/auto-claude-ui/src/renderer/components/CustomModelModal.tsx new file mode 100644 index 00000000..8e6d0072 --- /dev/null +++ b/auto-claude-ui/src/renderer/components/CustomModelModal.tsx @@ -0,0 +1,105 @@ +import { useState } from 'react'; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogFooter, + DialogDescription +} from './ui/dialog'; +import { Button } from './ui/button'; +import { Label } from './ui/label'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue +} from './ui/select'; +import { AVAILABLE_MODELS, THINKING_LEVELS } from '../../shared/constants'; +import type { InsightsModelConfig } from '../../shared/types'; +import type { ModelType, ThinkingLevel } from '../../shared/types'; + +interface CustomModelModalProps { + currentConfig?: InsightsModelConfig; + onSave: (config: InsightsModelConfig) => void; + onClose: () => void; +} + +export function CustomModelModal({ currentConfig, onSave, onClose }: CustomModelModalProps) { + const [model, setModel] = useState( + currentConfig?.model || 'sonnet' + ); + const [thinkingLevel, setThinkingLevel] = useState( + currentConfig?.thinkingLevel || 'medium' + ); + + const handleSave = () => { + onSave({ + profileId: 'custom', + model, + thinkingLevel + }); + }; + + return ( + + + + Custom Model Configuration + + Configure the model and thinking level for this chat session. + + + +
+
+ + +
+ +
+ + +
+
+ + + + + +
+
+ ); +} diff --git a/auto-claude-ui/src/renderer/components/Insights.tsx b/auto-claude-ui/src/renderer/components/Insights.tsx index d410812b..9ed75b31 100644 --- a/auto-claude-ui/src/renderer/components/Insights.tsx +++ b/auto-claude-ui/src/renderer/components/Insights.tsx @@ -29,12 +29,14 @@ import { switchSession, deleteSession, renameSession, + updateModelConfig, createTaskFromSuggestion, setupInsightsListeners } from '../stores/insights-store'; import { loadTasks } from '../stores/task-store'; import { ChatHistorySidebar } from './ChatHistorySidebar'; -import type { InsightsChatMessage } from '../../shared/types'; +import { InsightsModelSelector } from './InsightsModelSelector'; +import type { InsightsChatMessage, InsightsModelConfig } from '../../shared/types'; import { TASK_CATEGORY_LABELS, TASK_CATEGORY_COLORS, @@ -141,6 +143,13 @@ export function Insights({ projectId }: InsightsProps) { } }; + const handleModelConfigChange = async (config: InsightsModelConfig) => { + // If we have a session, persist the config + if (session?.id) { + await updateModelConfig(projectId, session.id, config); + } + }; + const isLoading = status.phase === 'thinking' || status.phase === 'streaming'; const messages = session?.messages || []; @@ -187,14 +196,21 @@ export function Insights({ projectId }: InsightsProps) {

- +
+ + +
{/* Messages */} diff --git a/auto-claude-ui/src/renderer/components/InsightsModelSelector.tsx b/auto-claude-ui/src/renderer/components/InsightsModelSelector.tsx new file mode 100644 index 00000000..12bcf76a --- /dev/null +++ b/auto-claude-ui/src/renderer/components/InsightsModelSelector.tsx @@ -0,0 +1,144 @@ +import { useState } from 'react'; +import { Brain, Scale, Zap, Sliders, Check } from 'lucide-react'; +import { Button } from './ui/button'; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, + DropdownMenuLabel +} from './ui/dropdown-menu'; +import { DEFAULT_AGENT_PROFILES, AVAILABLE_MODELS } from '../../shared/constants'; +import type { InsightsModelConfig } from '../../shared/types'; +import { CustomModelModal } from './CustomModelModal'; + +interface InsightsModelSelectorProps { + currentConfig?: InsightsModelConfig; + onConfigChange: (config: InsightsModelConfig) => void; + disabled?: boolean; +} + +const iconMap: Record = { + Brain, + Scale, + Zap +}; + +export function InsightsModelSelector({ + currentConfig, + onConfigChange, + disabled +}: InsightsModelSelectorProps) { + const [showCustomModal, setShowCustomModal] = useState(false); + + // Default to 'balanced' if no config + const selectedProfileId = currentConfig?.profileId || 'balanced'; + const profile = DEFAULT_AGENT_PROFILES.find(p => p.id === selectedProfileId); + + // Get the appropriate icon + const Icon = selectedProfileId === 'custom' + ? Sliders + : (profile?.icon ? iconMap[profile.icon] : Scale); + + const handleSelectProfile = (profileId: string) => { + if (profileId === 'custom') { + setShowCustomModal(true); + return; + } + + const selected = DEFAULT_AGENT_PROFILES.find(p => p.id === profileId); + if (selected) { + onConfigChange({ + profileId: selected.id, + model: selected.model, + thinkingLevel: selected.thinkingLevel + }); + } + }; + + const handleCustomSave = (config: InsightsModelConfig) => { + onConfigChange(config); + setShowCustomModal(false); + }; + + // Build display text for current selection + const getDisplayText = () => { + if (selectedProfileId === 'custom' && currentConfig) { + const modelLabel = AVAILABLE_MODELS.find(m => m.value === currentConfig.model)?.label || currentConfig.model; + return `${modelLabel} + ${currentConfig.thinkingLevel}`; + } + return profile?.name || 'Balanced'; + }; + + return ( + <> + + + + + + Agent Profile + {DEFAULT_AGENT_PROFILES.map((p) => { + const ProfileIcon = iconMap[p.icon || 'Brain']; + const isSelected = selectedProfileId === p.id; + const modelLabel = AVAILABLE_MODELS.find(m => m.value === p.model)?.label; + return ( + handleSelectProfile(p.id)} + className="flex cursor-pointer items-center gap-2" + > + +
+
{p.name}
+
+ {modelLabel} + {p.thinkingLevel} +
+
+ {isSelected && ( + + )} +
+ ); + })} + + handleSelectProfile('custom')} + className="flex cursor-pointer items-center gap-2" + > + +
+
Custom...
+
+ Choose model & thinking level +
+
+ {selectedProfileId === 'custom' && ( + + )} +
+
+
+ + {showCustomModal && ( + setShowCustomModal(false)} + /> + )} + + ); +} diff --git a/auto-claude-ui/src/renderer/stores/insights-store.ts b/auto-claude-ui/src/renderer/stores/insights-store.ts index b2f875a9..09ee971c 100644 --- a/auto-claude-ui/src/renderer/stores/insights-store.ts +++ b/auto-claude-ui/src/renderer/stores/insights-store.ts @@ -6,6 +6,7 @@ import type { InsightsChatStatus, InsightsStreamChunk, InsightsToolUsage, + InsightsModelConfig, TaskMetadata, Task } from '../../shared/types'; @@ -221,8 +222,9 @@ export async function loadInsightsSession(projectId: string): Promise { await loadInsightsSessions(projectId); } -export function sendMessage(projectId: string, message: string): void { +export function sendMessage(projectId: string, message: string, modelConfig?: InsightsModelConfig): void { const store = useInsightsStore.getState(); + const session = store.session; // Add user message to session const userMessage: InsightsChatMessage = { @@ -242,8 +244,11 @@ export function sendMessage(projectId: string, message: string): void { message: 'Processing your message...' }); + // Use provided modelConfig, or fall back to session's config + const configToUse = modelConfig || session?.modelConfig; + // Send to main process - window.electronAPI.sendInsightsMessage(projectId, message); + window.electronAPI.sendInsightsMessage(projectId, message, configToUse); } export async function clearSession(projectId: string): Promise { @@ -296,6 +301,25 @@ export async function renameSession(projectId: string, sessionId: string, newTit return false; } +export async function updateModelConfig(projectId: string, sessionId: string, modelConfig: InsightsModelConfig): Promise { + const result = await window.electronAPI.updateInsightsModelConfig(projectId, sessionId, modelConfig); + if (result.success) { + // Update local session state + const store = useInsightsStore.getState(); + if (store.session?.id === sessionId) { + store.setSession({ + ...store.session, + modelConfig, + updatedAt: new Date() + }); + } + // Reload sessions list to reflect the change + await loadInsightsSessions(projectId); + return true; + } + return false; +} + export async function createTaskFromSuggestion( projectId: string, title: string, diff --git a/auto-claude-ui/src/shared/constants/ipc.ts b/auto-claude-ui/src/shared/constants/ipc.ts index f5ec0ab0..dfb3ebda 100644 --- a/auto-claude-ui/src/shared/constants/ipc.ts +++ b/auto-claude-ui/src/shared/constants/ipc.ts @@ -248,6 +248,7 @@ export const IPC_CHANNELS = { INSIGHTS_SWITCH_SESSION: 'insights:switchSession', INSIGHTS_DELETE_SESSION: 'insights:deleteSession', INSIGHTS_RENAME_SESSION: 'insights:renameSession', + INSIGHTS_UPDATE_MODEL_CONFIG: 'insights:updateModelConfig', // Insights events (main -> renderer) INSIGHTS_STREAM_CHUNK: 'insights:streamChunk', diff --git a/auto-claude-ui/src/shared/constants/models.ts b/auto-claude-ui/src/shared/constants/models.ts index 3f987f2d..ce832c2c 100644 --- a/auto-claude-ui/src/shared/constants/models.ts +++ b/auto-claude-ui/src/shared/constants/models.ts @@ -15,6 +15,22 @@ export const AVAILABLE_MODELS = [ { value: 'haiku', label: 'Claude Haiku 4.5' } ] as const; +// Maps model shorthand to actual Claude model IDs +export const MODEL_ID_MAP: Record = { + opus: 'claude-opus-4-5-20251101', + sonnet: 'claude-sonnet-4-5-20250929', + haiku: 'claude-haiku-4-5-20250929' +} as const; + +// Maps thinking levels to budget tokens (null = no extended thinking) +export const THINKING_BUDGET_MAP: Record = { + none: null, + low: 1024, + medium: 4096, + high: 16384, + ultrathink: 65536 +} as const; + // ============================================ // Thinking Levels // ============================================ diff --git a/auto-claude-ui/src/shared/types/insights.ts b/auto-claude-ui/src/shared/types/insights.ts index c76892fc..ea8903f8 100644 --- a/auto-claude-ui/src/shared/types/insights.ts +++ b/auto-claude-ui/src/shared/types/insights.ts @@ -154,6 +154,16 @@ export interface IdeationSummary { // Insights Chat Types // ============================================ +import type { ThinkingLevel } from './settings'; +import type { ModelType } from './task'; + +// Model configuration for insights sessions +export interface InsightsModelConfig { + profileId: string; // 'complex' | 'balanced' | 'quick' | 'custom' + model: ModelType; // 'haiku' | 'sonnet' | 'opus' + thinkingLevel: ThinkingLevel; +} + export type InsightsChatRole = 'user' | 'assistant'; // Tool usage record for showing what tools the AI used @@ -183,6 +193,7 @@ export interface InsightsSession { projectId: string; title?: string; // Auto-generated from first message or user-set messages: InsightsChatMessage[]; + modelConfig?: InsightsModelConfig; // Per-session model configuration createdAt: Date; updatedAt: Date; } @@ -193,6 +204,7 @@ export interface InsightsSessionSummary { projectId: string; title: string; messageCount: number; + modelConfig?: InsightsModelConfig; // For displaying model indicator in sidebar createdAt: Date; updatedAt: Date; } diff --git a/auto-claude/runners/insights_runner.py b/auto-claude/runners/insights_runner.py index 55762f2f..81217061 100644 --- a/auto-claude/runners/insights_runner.py +++ b/auto-claude/runners/insights_runner.py @@ -128,7 +128,13 @@ Be conversational and helpful. Focus on providing actionable insights and clear Keep responses concise but informative.""" -async def run_with_sdk(project_dir: str, message: str, history: list) -> None: +async def run_with_sdk( + project_dir: str, + message: str, + history: list, + model: str = "claude-sonnet-4-5-20250929", + thinking_level: str = "medium" +) -> None: """Run the chat using Claude SDK with streaming.""" if not SDK_AVAILABLE: print("Claude SDK not available, falling back to simple mode", file=sys.stderr) @@ -163,11 +169,18 @@ async def run_with_sdk(project_dir: str, message: str, history: list) -> None: Current question: {message}""" + debug( + "insights_runner", + "Using model configuration", + model=model, + thinking_level=thinking_level, + ) + try: # Create Claude SDK client with appropriate settings for insights client = ClaudeSDKClient( options=ClaudeAgentOptions( - model="claude-opus-4-5-20251101", # Opus 4.5 for quality analysis + model=model, # Use configured model system_prompt=system_prompt, allowed_tools=[ "Read", @@ -318,18 +331,33 @@ def main(): parser.add_argument("--project-dir", required=True, help="Project directory path") parser.add_argument("--message", required=True, help="User message") parser.add_argument("--history", default="[]", help="JSON conversation history") + parser.add_argument( + "--model", + default="claude-sonnet-4-5-20250929", + help="Claude model ID (default: claude-sonnet-4-5-20250929)" + ) + parser.add_argument( + "--thinking-level", + default="medium", + choices=["none", "low", "medium", "high", "ultrathink"], + help="Thinking level for extended reasoning (default: medium)" + ) args = parser.parse_args() debug_section("insights_runner", "Starting Insights Chat") project_dir = args.project_dir user_message = args.message + model = args.model + thinking_level = args.thinking_level debug( "insights_runner", "Arguments", project_dir=project_dir, message_length=len(user_message), + model=model, + thinking_level=thinking_level, ) try: @@ -341,7 +369,7 @@ def main(): # Run the async SDK function debug("insights_runner", "Running SDK query") - asyncio.run(run_with_sdk(project_dir, user_message, history)) + asyncio.run(run_with_sdk(project_dir, user_message, history, model, thinking_level)) debug_success("insights_runner", "Query completed")