mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-02 08:33:36 +00:00
feat(ui): Enhance AI model handling with Cursor support
- Refactor model handling to support both Claude and Cursor models across various components. - Introduce `stripProviderPrefix` utility for consistent model ID processing. - Update `CursorProvider` to utilize `isCursorModel` for model validation. - Implement model override functionality in GitHub issue validation and enhancement routes. - Add `useCursorStatusInit` hook to initialize Cursor CLI status on app startup. - Update UI components to reflect changes in model selection and validation processes. This update improves the flexibility of AI model usage and enhances user experience by allowing quick model overrides.
This commit is contained in:
@@ -23,7 +23,7 @@ import {
|
||||
SelectValue,
|
||||
} from '@/components/ui/select';
|
||||
import type { AIProfile } from '@/store/app-store';
|
||||
import type { AgentModel } from '@automaker/types';
|
||||
import type { ModelAlias } from '@automaker/types';
|
||||
|
||||
type PlanningMode = 'skip' | 'lite' | 'spec' | 'full';
|
||||
|
||||
@@ -36,7 +36,7 @@ interface FeatureDefaultsSectionProps {
|
||||
defaultRequirePlanApproval: boolean;
|
||||
defaultAIProfileId: string | null;
|
||||
aiProfiles: AIProfile[];
|
||||
validationModel: AgentModel;
|
||||
validationModel: ModelAlias;
|
||||
onShowProfilesOnlyChange: (value: boolean) => void;
|
||||
onDefaultSkipTestsChange: (value: boolean) => void;
|
||||
onEnableDependencyBlockingChange: (value: boolean) => void;
|
||||
@@ -44,7 +44,7 @@ interface FeatureDefaultsSectionProps {
|
||||
onDefaultPlanningModeChange: (value: PlanningMode) => void;
|
||||
onDefaultRequirePlanApprovalChange: (value: boolean) => void;
|
||||
onDefaultAIProfileIdChange: (value: string | null) => void;
|
||||
onValidationModelChange: (value: AgentModel) => void;
|
||||
onValidationModelChange: (value: ModelAlias) => void;
|
||||
}
|
||||
|
||||
export function FeatureDefaultsSection({
|
||||
@@ -243,7 +243,7 @@ export function FeatureDefaultsSection({
|
||||
<Label className="text-foreground font-medium">Issue Validation Model</Label>
|
||||
<Select
|
||||
value={validationModel}
|
||||
onValueChange={(v: string) => onValidationModelChange(v as AgentModel)}
|
||||
onValueChange={(v: string) => onValidationModelChange(v as ModelAlias)}
|
||||
>
|
||||
<SelectTrigger className="w-[140px] h-8" data-testid="validation-model-select">
|
||||
<SelectValue />
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
import type { AgentModel, CursorModelId } from '@automaker/types';
|
||||
import type { ModelAlias, CursorModelId } from '@automaker/types';
|
||||
import { stripProviderPrefix } from '@automaker/types';
|
||||
import { CLAUDE_MODELS, CURSOR_MODELS } from '@/components/views/board-view/shared/model-constants';
|
||||
|
||||
interface PhaseModelSelectorProps {
|
||||
label: string;
|
||||
description: string;
|
||||
value: AgentModel | CursorModelId;
|
||||
onChange: (model: AgentModel | CursorModelId) => void;
|
||||
value: ModelAlias | CursorModelId;
|
||||
onChange: (model: ModelAlias | CursorModelId) => void;
|
||||
}
|
||||
|
||||
export function PhaseModelSelector({
|
||||
@@ -20,13 +21,10 @@ export function PhaseModelSelector({
|
||||
|
||||
// Filter Cursor models to only show enabled ones
|
||||
const availableCursorModels = CURSOR_MODELS.filter((model) => {
|
||||
const cursorId = model.id.replace('cursor-', '') as CursorModelId;
|
||||
const cursorId = stripProviderPrefix(model.id) as CursorModelId;
|
||||
return enabledCursorModels.includes(cursorId);
|
||||
});
|
||||
|
||||
// Check if current value is a Claude model or Cursor model
|
||||
const isClaudeModel = (v: string) => ['haiku', 'sonnet', 'opus'].includes(v);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
@@ -50,7 +48,7 @@ export function PhaseModelSelector({
|
||||
return (
|
||||
<button
|
||||
key={model.id}
|
||||
onClick={() => onChange(model.id as AgentModel)}
|
||||
onClick={() => onChange(model.id as ModelAlias)}
|
||||
className={cn(
|
||||
'px-3 py-1.5 rounded-lg text-xs font-medium',
|
||||
'transition-all duration-150',
|
||||
@@ -75,7 +73,7 @@ export function PhaseModelSelector({
|
||||
|
||||
{/* Cursor Models */}
|
||||
{availableCursorModels.map((model) => {
|
||||
const cursorId = model.id.replace('cursor-', '') as CursorModelId;
|
||||
const cursorId = stripProviderPrefix(model.id) as CursorModelId;
|
||||
const isActive = value === cursorId;
|
||||
return (
|
||||
<button
|
||||
|
||||
@@ -13,6 +13,7 @@ import { Terminal, Info } from 'lucide-react';
|
||||
import { toast } from 'sonner';
|
||||
import { getHttpApiClient } from '@/lib/http-api-client';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
import { useSetupStore } from '@/store/setup-store';
|
||||
import { cn } from '@/lib/utils';
|
||||
import type { CursorModelId, CursorModelConfig } from '@automaker/types';
|
||||
import { CURSOR_MODEL_MAP } from '@automaker/types';
|
||||
@@ -33,6 +34,7 @@ export function CursorSettingsTab() {
|
||||
// Global settings from store
|
||||
const { enabledCursorModels, cursorDefaultModel, setCursorDefaultModel, toggleCursorModel } =
|
||||
useAppStore();
|
||||
const { setCursorCliStatus } = useSetupStore();
|
||||
|
||||
const [status, setStatus] = useState<CursorStatus | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
@@ -48,11 +50,24 @@ export function CursorSettingsTab() {
|
||||
const statusResult = await api.setup.getCursorStatus();
|
||||
|
||||
if (statusResult.success) {
|
||||
setStatus({
|
||||
const newStatus = {
|
||||
installed: statusResult.installed ?? false,
|
||||
version: statusResult.version ?? undefined,
|
||||
authenticated: statusResult.auth?.authenticated ?? false,
|
||||
method: statusResult.auth?.method,
|
||||
};
|
||||
setStatus(newStatus);
|
||||
|
||||
// Also update the global setup store so other components can access the status
|
||||
setCursorCliStatus({
|
||||
installed: newStatus.installed,
|
||||
version: newStatus.version,
|
||||
auth: newStatus.authenticated
|
||||
? {
|
||||
authenticated: true,
|
||||
method: newStatus.method || 'unknown',
|
||||
}
|
||||
: undefined,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -61,7 +76,7 @@ export function CursorSettingsTab() {
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, []);
|
||||
}, [setCursorCliStatus]);
|
||||
|
||||
useEffect(() => {
|
||||
loadData();
|
||||
|
||||
Reference in New Issue
Block a user