// biome-ignore-all assist/source/organizeImports: ANT-ONLY import markers must not be reorderedimport { MODEL_ALIASES } from './aliases.js'import { isModelAllowed } from './modelAllowlist.js'import { getAPIProvider } from './providers.js'import { sideQuery } from '../sideQuery.js'import {NotFoundError,APIError,APIConnectionError,AuthenticationError,} from '@anthropic-ai/sdk'import { getModelStrings } from './modelStrings.js'// Cache valid models to avoid repeated API callsconst validModelCache = new Map<string, boolean>()/*** Validates a model by attempting an actual API call.*/export async function validateModel(model: string,): Promise<{ valid: boolean; error?: string }> {const normalizedModel = model.trim()// Empty model is invalidif (!normalizedModel) {return { valid: false, error: 'Model name cannot be empty' }}// Check against availableModels allowlist before any API callif (!isModelAllowed(normalizedModel)) {return {valid: false,error: `Model '${normalizedModel}' is not in the list of available models`,}}// Check if it's a known alias (these are always valid)const lowerModel = normalizedModel.toLowerCase()if ((MODEL_ALIASES as readonly string[]).includes(lowerModel)) {return { valid: true }}// Check if it matches ANTHROPIC_CUSTOM_MODEL_OPTION (pre-validated by the user)if (normalizedModel === process.env.ANTHROPIC_CUSTOM_MODEL_OPTION) {return { valid: true }}// Check cache firstif (validModelCache.has(normalizedModel)) {return { valid: true }}// Try to make an actual API call with minimal parameterstry {await sideQuery({model: normalizedModel,max_tokens: 1,maxRetries: 0,querySource: 'model_validation',messages: [{role: 'user',content: [{type: 'text',text: 'Hi',cache_control: { type: 'ephemeral' },},],},],})// If we got here, the model is validvalidModelCache.set(normalizedModel, true)return { valid: true }} catch (error) {return handleValidationError(error, normalizedModel)}}function handleValidationError(error: unknown,modelName: string,): { valid: boolean; error: string } {// NotFoundError (404) means the model doesn't existif (error instanceof NotFoundError) {const fallback = get3PFallbackSuggestion(modelName)const suggestion = fallback ? `. Try '${fallback}' instead` : ''return {valid: false,error: `Model '${modelName}' not found${suggestion}`,}}// For other API errors, provide context-specific messagesif (error instanceof APIError) {if (error instanceof AuthenticationError) {return {valid: false,error: 'Authentication failed. Please check your API credentials.',}}if (error instanceof APIConnectionError) {return {valid: false,error: 'Network error. Please check your internet connection.',}}// Check error body for model-specific errorsconst errorBody = error.error as unknownif (errorBody &&typeof errorBody === 'object' &&'type' in errorBody &&errorBody.type === 'not_found_error' &&'message' in errorBody &&typeof errorBody.message === 'string' &&errorBody.message.includes('model:')) {return { valid: false, error: `Model '${modelName}' not found` }}// Generic API errorreturn { valid: false, error: `API error: ${error.message}` }}// For unknown errors, be safe and rejectconst errorMessage = error instanceof Error ? error.message : String(error)return {valid: false,error: `Unable to validate model: ${errorMessage}`,}}// @[MODEL LAUNCH]: Add a fallback suggestion chain for the new model → previous version/*** Suggest a fallback model for 3P users when the selected model is unavailable.*/function get3PFallbackSuggestion(model: string): string | undefined {if (getAPIProvider() === 'firstParty') {return undefined}const lowerModel = model.toLowerCase()if (lowerModel.includes('opus-4-6') || lowerModel.includes('opus_4_6')) {return getModelStrings().opus41}if (lowerModel.includes('sonnet-4-6') || lowerModel.includes('sonnet_4_6')) {return getModelStrings().sonnet45}if (lowerModel.includes('sonnet-4-5') || lowerModel.includes('sonnet_4_5')) {return getModelStrings().sonnet40}return undefined}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。