'use client'; import { cn } from '@/lib/utils'; import { useState, useEffect } from 'react'; import { AlertCircle } from 'lucide-react'; // Claude 模型卡片配置 const CLAUDE_MODEL_CARDS = [ { id: 'haiku', name: 'Haiku', description: 'Fast & efficient', modelIdPattern: 'haiku', }, { id: 'sonnet', name: 'Sonnet', description: 'Balanced', modelIdPattern: 'sonnet', }, { id: 'opus', name: 'Opus', description: 'Most capable', modelIdPattern: 'opus', }, ]; // Codex 模型卡片配置 const CODEX_MODEL_CARDS = [ { id: 'gpt-5.1-codex', name: 'Codex', description: 'Standard', modelIdPattern: 'gpt-5.1-codex', }, { id: 'gpt-5.1-codex-max', name: 'Codex Max', description: 'Enhanced', modelIdPattern: 'gpt-5.1-codex-max', }, { id: 'gpt-5.2-codex', name: 'Codex Pro', description: 'Latest', modelIdPattern: 'gpt-5.2-codex', }, ]; // 模型类型 type ModelType = 'claude' | 'codex'; interface ModelCardSelectorProps { value: string; onChange: (modelId: string) => void; disabled?: boolean; models?: { modelId: string; displayName: string; modelType?: string }[]; } export function ModelCardSelector({ value, onChange, disabled = false, models = [], }: ModelCardSelectorProps) { // 当前选中的模型类型 const [showModelChangeHint, setShowModelChangeHint] = useState(false); const [previousModelType, setPreviousModelType] = useState(null); // 判断模型类型 const getModelType = (modelId: string): ModelType => { if (modelId.startsWith('gpt-') && modelId.includes('codex')) { return 'codex'; } return 'claude'; }; // 根据当前选中的模型ID判断选中的卡片(Claude) const getSelectedClaudeCard = (modelId: string): string | null => { const lowerModelId = modelId.toLowerCase(); if (lowerModelId.includes('haiku')) return 'haiku'; if (lowerModelId.includes('opus')) return 'opus'; if (lowerModelId.includes('sonnet')) return 'sonnet'; return null; }; // 根据当前选中的模型ID判断选中的卡片(Codex) const getSelectedCodexCard = (modelId: string): string | null => { if (modelId === 'gpt-5.1-codex') return 'gpt-5.1-codex'; if (modelId === 'gpt-5.1-codex-max') return 'gpt-5.1-codex-max'; if (modelId === 'gpt-5.2-codex') return 'gpt-5.2-codex'; return null; }; // 根据卡片类型找到对应的实际模型ID(Claude) const findClaudeModelIdByCard = (cardId: string): string => { const model = models.find((m) => m.modelId.toLowerCase().includes(cardId) ); return model?.modelId || value; }; // 根据卡片类型找到对应的实际模型ID(Codex) const findCodexModelIdByCard = (cardId: string): string => { const model = models.find((m) => m.modelId === cardId); return model?.modelId || cardId; }; const currentModelType = getModelType(value); const selectedClaudeCard = getSelectedClaudeCard(value); const selectedCodexCard = getSelectedCodexCard(value); // 处理模型选择 const handleModelSelect = (modelId: string, modelType: ModelType) => { if (disabled) return; const newModelType = modelType; // 检测模型类型切换 if (previousModelType && previousModelType !== newModelType) { setShowModelChangeHint(true); setTimeout(() => setShowModelChangeHint(false), 5000); } setPreviousModelType(newModelType); onChange(modelId); }; // 初始化时设置 previousModelType useEffect(() => { if (value && !previousModelType) { setPreviousModelType(getModelType(value)); } }, [value, previousModelType]); // 检查是否有 Codex 模型可用 const hasCodexModels = models.some(m => m.modelType === 'codex' || (m.modelId.startsWith('gpt-') && m.modelId.includes('codex'))); return (
{/* 模型切换提示 */} {showModelChangeHint && (

模型类型已切换

{currentModelType === 'codex' ? 'Codex 模型不支持思考模式(Thinking),但支持工具调用。' : 'Claude 模型支持思考模式和工具调用。'}

)} {/* Claude 模型组 */}
Claude 模型
{CLAUDE_MODEL_CARDS.map((card) => { const isSelected = selectedClaudeCard === card.id; return ( ); })}
{/* Codex 模型组 */} {hasCodexModels && (
Codex 模型 OpenAI
{CODEX_MODEL_CARDS.map((card) => { const isSelected = selectedCodexCard === card.id; // 检查该模型是否在可用模型列表中 const isAvailable = models.some(m => m.modelId === card.id); if (!isAvailable) return null; return ( ); })}
)}
); }