# Phase 8: AI Profiles Integration **Status:** `completed` **Dependencies:** Phase 1 (Types), Phase 7 (Settings) **Estimated Effort:** Medium (UI + types) --- ## Objective Extend the AI Profiles system to support Cursor as a provider, with proper handling of Cursor's embedded thinking mode (via model ID) vs Claude's separate thinking level. --- ## Key Concept: Thinking Mode Handling ### Claude Approach - Separate `thinkingLevel` property: `'none' | 'low' | 'medium' | 'high' | 'ultrathink'` - Applied to any Claude model ### Cursor Approach - Thinking is **embedded in the model ID** - Examples: `claude-sonnet-4` (no thinking) vs `claude-sonnet-4-thinking` (with thinking) - No separate thinking level selector needed for Cursor profiles --- ## Tasks ### Task 8.1: Update AIProfile Type **Status:** `completed` **File:** `libs/types/src/settings.ts` Update the AIProfile interface: ```typescript import { CursorModelId } from './cursor-models'; /** * AI Profile - saved configuration for different use cases */ export interface AIProfile { id: string; name: string; description: string; isBuiltIn: boolean; icon?: string; // Provider selection provider: ModelProvider; // 'claude' | 'cursor' // Claude-specific model?: AgentModel; // 'opus' | 'sonnet' | 'haiku' thinkingLevel?: ThinkingLevel; // 'none' | 'low' | 'medium' | 'high' | 'ultrathink' // Cursor-specific cursorModel?: CursorModelId; // 'auto' | 'claude-sonnet-4' | 'gpt-4o' | etc. // Note: For Cursor, thinking is in the model ID (e.g., 'claude-sonnet-4-thinking') } /** * Helper to determine if a profile uses thinking mode */ export function profileHasThinking(profile: AIProfile): boolean { if (profile.provider === 'claude') { return profile.thinkingLevel !== undefined && profile.thinkingLevel !== 'none'; } if (profile.provider === 'cursor') { const model = profile.cursorModel || 'auto'; return model.includes('thinking') || model === 'o3-mini'; } return false; } /** * Get effective model string for execution */ export function getProfileModelString(profile: AIProfile): string { if (profile.provider === 'cursor') { return `cursor-${profile.cursorModel || 'auto'}`; } // Claude return profile.model || 'sonnet'; } ``` ### Task 8.2: Update Profile Form Component **Status:** `completed` **File:** `apps/ui/src/components/views/profiles-view/components/profile-form.tsx` Add Cursor-specific fields: ```tsx import React, { useState } from 'react'; import { Bot, Terminal } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Textarea } from '@/components/ui/textarea'; import { Badge } from '@/components/ui/badge'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { AIProfile, AgentModel, ModelProvider, ThinkingLevel, CursorModelId, CURSOR_MODEL_MAP, cursorModelHasThinking, } from '@automaker/types'; interface ProfileFormProps { profile: AIProfile; onSave: (profile: AIProfile) => void; onCancel: () => void; } export function ProfileForm({ profile, onSave, onCancel }: ProfileFormProps) { const [formData, setFormData] = useState(profile); const handleProviderChange = (provider: ModelProvider) => { setFormData((prev) => ({ ...prev, provider, // Reset provider-specific fields model: provider === 'claude' ? 'sonnet' : undefined, thinkingLevel: provider === 'claude' ? 'none' : undefined, cursorModel: provider === 'cursor' ? 'auto' : undefined, })); }; return (
{/* Name & Description */}
setFormData((p) => ({ ...p, name: e.target.value }))} placeholder="My Profile" />