mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-03 21:03:08 +00:00
Revert "Wire provider model enablement into selectors"
This reverts commit 8f1740c0f5.
This commit is contained in:
@@ -4,6 +4,7 @@ import { Badge } from '@/components/ui/badge';
|
|||||||
import { Brain, AlertTriangle } from 'lucide-react';
|
import { Brain, AlertTriangle } from 'lucide-react';
|
||||||
import { AnthropicIcon, CursorIcon, OpenAIIcon } from '@/components/ui/provider-icon';
|
import { AnthropicIcon, CursorIcon, OpenAIIcon } from '@/components/ui/provider-icon';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
|
import type { ModelAlias } from '@/store/app-store';
|
||||||
import { useAppStore } from '@/store/app-store';
|
import { useAppStore } from '@/store/app-store';
|
||||||
import { useSetupStore } from '@/store/setup-store';
|
import { useSetupStore } from '@/store/setup-store';
|
||||||
import { getModelProvider, PROVIDER_PREFIXES, stripProviderPrefix } from '@automaker/types';
|
import { getModelProvider, PROVIDER_PREFIXES, stripProviderPrefix } from '@automaker/types';
|
||||||
@@ -18,10 +19,6 @@ interface ModelSelectorProps {
|
|||||||
testIdPrefix?: string;
|
testIdPrefix?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CODEX_EMPTY_AVAILABLE_MESSAGE = 'No Codex models available';
|
|
||||||
const CODEX_EMPTY_ENABLED_MESSAGE =
|
|
||||||
'No Codex models enabled. Enable models in Settings → AI Providers.';
|
|
||||||
|
|
||||||
export function ModelSelector({
|
export function ModelSelector({
|
||||||
selectedModel,
|
selectedModel,
|
||||||
onModelSelect,
|
onModelSelect,
|
||||||
@@ -30,8 +27,6 @@ export function ModelSelector({
|
|||||||
const {
|
const {
|
||||||
enabledCursorModels,
|
enabledCursorModels,
|
||||||
cursorDefaultModel,
|
cursorDefaultModel,
|
||||||
enabledCodexModels,
|
|
||||||
codexDefaultModel,
|
|
||||||
codexModels,
|
codexModels,
|
||||||
codexModelsLoading,
|
codexModelsLoading,
|
||||||
codexModelsError,
|
codexModelsError,
|
||||||
@@ -54,10 +49,8 @@ export function ModelSelector({
|
|||||||
}
|
}
|
||||||
}, [isCodexAvailable, codexModels.length, codexModelsLoading, fetchCodexModels]);
|
}, [isCodexAvailable, codexModels.length, codexModelsLoading, fetchCodexModels]);
|
||||||
|
|
||||||
const enabledCodexModelIds = new Set(enabledCodexModels);
|
|
||||||
|
|
||||||
// Transform codex models from store to ModelOption format
|
// Transform codex models from store to ModelOption format
|
||||||
const codexModelOptions: ModelOption[] = codexModels.map((model) => {
|
const dynamicCodexModels: ModelOption[] = codexModels.map((model) => {
|
||||||
// Infer badge based on tier
|
// Infer badge based on tier
|
||||||
let badge: string | undefined;
|
let badge: string | undefined;
|
||||||
if (model.tier === 'premium') badge = 'Premium';
|
if (model.tier === 'premium') badge = 'Premium';
|
||||||
@@ -74,10 +67,6 @@ export function ModelSelector({
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const enabledCodexModelOptions = codexModelOptions.filter((model) =>
|
|
||||||
enabledCodexModelIds.has(model.id)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Filter Cursor models based on enabled models from global settings
|
// Filter Cursor models based on enabled models from global settings
|
||||||
const filteredCursorModels = CURSOR_MODELS.filter((model) => {
|
const filteredCursorModels = CURSOR_MODELS.filter((model) => {
|
||||||
// Extract the cursor model ID from the prefixed ID (e.g., "cursor-auto" -> "auto")
|
// Extract the cursor model ID from the prefixed ID (e.g., "cursor-auto" -> "auto")
|
||||||
@@ -85,36 +74,21 @@ export function ModelSelector({
|
|||||||
return enabledCursorModels.includes(cursorModelId as any);
|
return enabledCursorModels.includes(cursorModelId as any);
|
||||||
});
|
});
|
||||||
|
|
||||||
const hasEnabledCodexModels = enabledCodexModelOptions.length > 0;
|
|
||||||
const codexDefaultSelection =
|
|
||||||
codexModelOptions.find((model) => model.id === codexDefaultModel)?.id ||
|
|
||||||
enabledCodexModelOptions[0]?.id ||
|
|
||||||
codexModelOptions[0]?.id;
|
|
||||||
|
|
||||||
const handleProviderChange = (provider: ModelProvider) => {
|
const handleProviderChange = (provider: ModelProvider) => {
|
||||||
if (provider === 'cursor' && selectedProvider !== 'cursor') {
|
if (provider === 'cursor' && selectedProvider !== 'cursor') {
|
||||||
// Switch to Cursor's default model (from global settings)
|
// Switch to Cursor's default model (from global settings)
|
||||||
onModelSelect(`${PROVIDER_PREFIXES.cursor}${cursorDefaultModel}`);
|
onModelSelect(`${PROVIDER_PREFIXES.cursor}${cursorDefaultModel}`);
|
||||||
} else if (provider === 'codex' && selectedProvider !== 'codex') {
|
} else if (provider === 'codex' && selectedProvider !== 'codex') {
|
||||||
// Switch to Codex's default model (from global settings)
|
// Switch to Codex's default model (use isDefault flag from dynamic models)
|
||||||
if (codexDefaultSelection) {
|
const defaultModel = codexModels.find((m) => m.isDefault);
|
||||||
onModelSelect(codexDefaultSelection);
|
const defaultModelId = defaultModel?.id || codexModels[0]?.id || 'codex-gpt-5.2-codex';
|
||||||
}
|
onModelSelect(defaultModelId);
|
||||||
} else if (provider === 'claude' && selectedProvider !== 'claude') {
|
} else if (provider === 'claude' && selectedProvider !== 'claude') {
|
||||||
// Switch to Claude's default model
|
// Switch to Claude's default model
|
||||||
onModelSelect('sonnet');
|
onModelSelect('sonnet');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const showCodexAvailableEmpty =
|
|
||||||
!codexModelsLoading && !codexModelsError && codexModelOptions.length === 0;
|
|
||||||
const showCodexEnabledEmpty =
|
|
||||||
!codexModelsLoading &&
|
|
||||||
!codexModelsError &&
|
|
||||||
codexModelOptions.length > 0 &&
|
|
||||||
!hasEnabledCodexModels;
|
|
||||||
const showCodexList = !codexModelsLoading && !codexModelsError && hasEnabledCodexModels;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{/* Provider Selection */}
|
{/* Provider Selection */}
|
||||||
@@ -298,7 +272,7 @@ export function ModelSelector({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Loading state */}
|
{/* Loading state */}
|
||||||
{codexModelsLoading && codexModelOptions.length === 0 && (
|
{codexModelsLoading && dynamicCodexModels.length === 0 && (
|
||||||
<div className="flex items-center justify-center gap-2 p-6 text-sm text-muted-foreground">
|
<div className="flex items-center justify-center gap-2 p-6 text-sm text-muted-foreground">
|
||||||
<RefreshCw className="w-4 h-4 animate-spin" />
|
<RefreshCw className="w-4 h-4 animate-spin" />
|
||||||
Loading models...
|
Loading models...
|
||||||
@@ -323,21 +297,15 @@ export function ModelSelector({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Model list */}
|
{/* Model list */}
|
||||||
{showCodexAvailableEmpty && (
|
{!codexModelsLoading && !codexModelsError && dynamicCodexModels.length === 0 && (
|
||||||
<div className="text-sm text-muted-foreground p-3 border border-dashed rounded-md text-center">
|
<div className="text-sm text-muted-foreground p-3 border border-dashed rounded-md text-center">
|
||||||
{CODEX_EMPTY_AVAILABLE_MESSAGE}
|
No Codex models available
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{showCodexEnabledEmpty && (
|
{!codexModelsLoading && dynamicCodexModels.length > 0 && (
|
||||||
<div className="text-sm text-muted-foreground p-3 border border-dashed rounded-md text-center">
|
|
||||||
{CODEX_EMPTY_ENABLED_MESSAGE}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{showCodexList && (
|
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
{enabledCodexModelOptions.map((option) => {
|
{dynamicCodexModels.map((option) => {
|
||||||
const isSelected = selectedModel === option.id;
|
const isSelected = selectedModel === option.id;
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -159,9 +159,6 @@ export function PhaseModelSelector({
|
|||||||
const expandedCodexTriggerRef = useRef<HTMLDivElement>(null);
|
const expandedCodexTriggerRef = useRef<HTMLDivElement>(null);
|
||||||
const {
|
const {
|
||||||
enabledCursorModels,
|
enabledCursorModels,
|
||||||
enabledCodexModels,
|
|
||||||
enabledOpencodeModels,
|
|
||||||
enabledDynamicModelIds,
|
|
||||||
favoriteModels,
|
favoriteModels,
|
||||||
toggleFavoriteModel,
|
toggleFavoriteModel,
|
||||||
codexModels,
|
codexModels,
|
||||||
@@ -264,14 +261,6 @@ export function PhaseModelSelector({
|
|||||||
}));
|
}));
|
||||||
}, [codexModels]);
|
}, [codexModels]);
|
||||||
|
|
||||||
const availableCodexModels = useMemo(
|
|
||||||
() =>
|
|
||||||
transformedCodexModels.filter((model) =>
|
|
||||||
enabledCodexModels.includes(model.id as CodexModelId)
|
|
||||||
),
|
|
||||||
[transformedCodexModels, enabledCodexModels]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Filter Cursor models to only show enabled ones
|
// Filter Cursor models to only show enabled ones
|
||||||
const availableCursorModels = CURSOR_MODELS.filter((model) => {
|
const availableCursorModels = CURSOR_MODELS.filter((model) => {
|
||||||
const cursorId = stripProviderPrefix(model.id) as CursorModelId;
|
const cursorId = stripProviderPrefix(model.id) as CursorModelId;
|
||||||
@@ -377,20 +366,16 @@ export function PhaseModelSelector({
|
|||||||
// Combine static and dynamic OpenCode models
|
// Combine static and dynamic OpenCode models
|
||||||
const allOpencodeModels: ModelOption[] = useMemo(() => {
|
const allOpencodeModels: ModelOption[] = useMemo(() => {
|
||||||
// Start with static models
|
// Start with static models
|
||||||
const staticModels = OPENCODE_MODELS.filter((model) =>
|
const staticModels = [...OPENCODE_MODELS];
|
||||||
enabledOpencodeModels.includes(model.id)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add dynamic models (convert ModelDefinition to ModelOption)
|
// Add dynamic models (convert ModelDefinition to ModelOption)
|
||||||
const dynamicModelOptions: ModelOption[] = dynamicOpencodeModels
|
const dynamicModelOptions: ModelOption[] = dynamicOpencodeModels.map((model) => ({
|
||||||
.filter((model) => enabledDynamicModelIds.includes(model.id))
|
id: model.id,
|
||||||
.map((model) => ({
|
label: model.name,
|
||||||
id: model.id,
|
description: model.description,
|
||||||
label: model.name,
|
badge: model.tier === 'premium' ? 'Premium' : model.tier === 'basic' ? 'Free' : undefined,
|
||||||
description: model.description,
|
provider: 'opencode' as const,
|
||||||
badge: model.tier === 'premium' ? 'Premium' : model.tier === 'basic' ? 'Free' : undefined,
|
}));
|
||||||
provider: 'opencode' as const,
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Merge, avoiding duplicates (static models take precedence for same ID)
|
// Merge, avoiding duplicates (static models take precedence for same ID)
|
||||||
// In practice, static and dynamic IDs don't overlap
|
// In practice, static and dynamic IDs don't overlap
|
||||||
@@ -398,14 +383,14 @@ export function PhaseModelSelector({
|
|||||||
const uniqueDynamic = dynamicModelOptions.filter((m) => !staticIds.has(m.id));
|
const uniqueDynamic = dynamicModelOptions.filter((m) => !staticIds.has(m.id));
|
||||||
|
|
||||||
return [...staticModels, ...uniqueDynamic];
|
return [...staticModels, ...uniqueDynamic];
|
||||||
}, [dynamicOpencodeModels, enabledOpencodeModels, enabledDynamicModelIds]);
|
}, [dynamicOpencodeModels]);
|
||||||
|
|
||||||
// Group models
|
// Group models
|
||||||
const { favorites, claude, cursor, codex, opencode } = useMemo(() => {
|
const { favorites, claude, cursor, codex, opencode } = useMemo(() => {
|
||||||
const favs: typeof CLAUDE_MODELS = [];
|
const favs: typeof CLAUDE_MODELS = [];
|
||||||
const cModels: typeof CLAUDE_MODELS = [];
|
const cModels: typeof CLAUDE_MODELS = [];
|
||||||
const curModels: typeof CURSOR_MODELS = [];
|
const curModels: typeof CURSOR_MODELS = [];
|
||||||
const codModels: typeof availableCodexModels = [];
|
const codModels: typeof transformedCodexModels = [];
|
||||||
const ocModels: ModelOption[] = [];
|
const ocModels: ModelOption[] = [];
|
||||||
|
|
||||||
// Process Claude Models
|
// Process Claude Models
|
||||||
@@ -427,7 +412,7 @@ export function PhaseModelSelector({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Process Codex Models
|
// Process Codex Models
|
||||||
availableCodexModels.forEach((model) => {
|
transformedCodexModels.forEach((model) => {
|
||||||
if (favoriteModels.includes(model.id)) {
|
if (favoriteModels.includes(model.id)) {
|
||||||
favs.push(model);
|
favs.push(model);
|
||||||
} else {
|
} else {
|
||||||
@@ -451,7 +436,7 @@ export function PhaseModelSelector({
|
|||||||
codex: codModels,
|
codex: codModels,
|
||||||
opencode: ocModels,
|
opencode: ocModels,
|
||||||
};
|
};
|
||||||
}, [favoriteModels, availableCursorModels, availableCodexModels, allOpencodeModels]);
|
}, [favoriteModels, availableCursorModels, transformedCodexModels, allOpencodeModels]);
|
||||||
|
|
||||||
// Group OpenCode models by model type for better organization
|
// Group OpenCode models by model type for better organization
|
||||||
const opencodeSections = useMemo(() => {
|
const opencodeSections = useMemo(() => {
|
||||||
@@ -468,11 +453,8 @@ export function PhaseModelSelector({
|
|||||||
free: {},
|
free: {},
|
||||||
dynamic: {},
|
dynamic: {},
|
||||||
};
|
};
|
||||||
const enabledDynamicProviders = dynamicOpencodeModels.filter((model) =>
|
|
||||||
enabledDynamicModelIds.includes(model.id)
|
|
||||||
);
|
|
||||||
const dynamicProviderById = new Map(
|
const dynamicProviderById = new Map(
|
||||||
enabledDynamicProviders.map((model) => [model.id, model.provider])
|
dynamicOpencodeModels.map((model) => [model.id, model.provider])
|
||||||
);
|
);
|
||||||
|
|
||||||
const resolveProviderKey = (modelId: string): string => {
|
const resolveProviderKey = (modelId: string): string => {
|
||||||
@@ -542,10 +524,10 @@ export function PhaseModelSelector({
|
|||||||
}).filter(Boolean) as OpencodeSection[];
|
}).filter(Boolean) as OpencodeSection[];
|
||||||
|
|
||||||
return builtSections;
|
return builtSections;
|
||||||
}, [opencode, dynamicOpencodeModels, enabledDynamicModelIds]);
|
}, [opencode, dynamicOpencodeModels]);
|
||||||
|
|
||||||
// Render Codex model item with secondary popover for reasoning effort (only for models that support it)
|
// Render Codex model item with secondary popover for reasoning effort (only for models that support it)
|
||||||
const renderCodexModelItem = (model: (typeof availableCodexModels)[0]) => {
|
const renderCodexModelItem = (model: (typeof transformedCodexModels)[0]) => {
|
||||||
const isSelected = selectedModel === model.id;
|
const isSelected = selectedModel === model.id;
|
||||||
const isFavorite = favoriteModels.includes(model.id);
|
const isFavorite = favoriteModels.includes(model.id);
|
||||||
const hasReasoning = codexModelHasThinking(model.id as CodexModelId);
|
const hasReasoning = codexModelHasThinking(model.id as CodexModelId);
|
||||||
@@ -726,7 +708,7 @@ export function PhaseModelSelector({
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Render OpenCode model item (simple selector, no thinking/reasoning options)
|
// Render OpenCode model item (simple selector, no thinking/reasoning options)
|
||||||
const renderOpencodeModelItem = (model: ModelOption) => {
|
const renderOpencodeModelItem = (model: (typeof OPENCODE_MODELS)[0]) => {
|
||||||
const isSelected = selectedModel === model.id;
|
const isSelected = selectedModel === model.id;
|
||||||
const isFavorite = favoriteModels.includes(model.id);
|
const isFavorite = favoriteModels.includes(model.id);
|
||||||
|
|
||||||
@@ -1172,7 +1154,7 @@ export function PhaseModelSelector({
|
|||||||
}
|
}
|
||||||
// Codex model
|
// Codex model
|
||||||
if (model.provider === 'codex') {
|
if (model.provider === 'codex') {
|
||||||
return renderCodexModelItem(model as (typeof availableCodexModels)[0]);
|
return renderCodexModelItem(model as (typeof transformedCodexModels)[0]);
|
||||||
}
|
}
|
||||||
// OpenCode model
|
// OpenCode model
|
||||||
if (model.provider === 'opencode') {
|
if (model.provider === 'opencode') {
|
||||||
|
|||||||
Reference in New Issue
Block a user