Something went wrong. Try again.
source dump of claude code forked from oppi.li/claude-code
Something went wrong. Try again.
4.6 kB · 159 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160// 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 invalid if (!normalizedModel) { return { valid: false, error: 'Model name cannot be empty' } }
// Check against availableModels allowlist before any API call if (!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 first if (validModelCache.has(normalizedModel)) { return { valid: true } }
// Try to make an actual API call with minimal parameters try { 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 valid validModelCache.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 exist if (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 messages if (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 errors const errorBody = error.error as unknown if ( 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 error return { valid: false, error: `API error: ${error.message}` } }
// For unknown errors, be safe and reject const 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}