@mastra/core
Version:
Mastra is a framework for building AI-powered applications and agents with a modern TypeScript stack.
1 lines • 10.8 kB
Source Map (JSON)
{"version":3,"sources":["../src/llm/model/registry-generator.ts"],"names":["fs","path"],"mappings":"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","file":"registry-generator-DL42NMBM.cjs","sourcesContent":["/**\n * Shared provider registry generation logic\n * Used by both the CLI generation script and runtime refresh\n */\n\nimport fs from 'fs/promises';\nimport path from 'path';\nimport type { MastraModelGateway, ProviderConfig } from './gateways/base.js';\n\n/**\n * Write a file atomically using the write-to-temp-then-rename pattern.\n * This prevents file corruption when multiple processes write to the same file concurrently.\n *\n * The rename operation is atomic on POSIX systems when source and destination\n * are on the same filesystem.\n *\n * @param filePath - The target file path\n * @param content - The content to write\n * @param encoding - The encoding to use (default: 'utf-8')\n */\nexport async function atomicWriteFile(\n filePath: string,\n content: string,\n encoding: BufferEncoding = 'utf-8',\n): Promise<void> {\n // Create a unique temp file name using PID, timestamp, and random suffix to avoid collisions\n const randomSuffix = Math.random().toString(36).substring(2, 15);\n const tempPath = `${filePath}.${process.pid}.${Date.now()}.${randomSuffix}.tmp`;\n\n try {\n // Write to temp file first\n await fs.writeFile(tempPath, content, encoding);\n\n // Atomically rename temp file to target path\n // This is atomic on POSIX when both paths are on the same filesystem\n await fs.rename(tempPath, filePath);\n } catch (error) {\n // Clean up temp file if it exists\n try {\n await fs.unlink(tempPath);\n } catch {\n // Ignore cleanup errors\n }\n throw error;\n }\n}\n\n/**\n * Fetch providers from all gateways with retry logic\n * @param gateways - Array of gateway instances to fetch from\n * @returns Object containing providers and models records\n */\nexport async function fetchProvidersFromGateways(\n gateways: MastraModelGateway[],\n): Promise<{ providers: Record<string, ProviderConfig>; models: Record<string, string[]> }> {\n const allProviders: Record<string, ProviderConfig> = {};\n const allModels: Record<string, string[]> = {};\n\n const maxRetries = 3;\n\n for (const gateway of gateways) {\n let lastError: Error | null = null;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n const providers = await gateway.fetchProviders();\n\n // models.dev is a provider registry, not a true gateway - don't prefix its providers\n const isProviderRegistry = gateway.id === 'models.dev';\n\n for (const [providerId, config] of Object.entries(providers)) {\n // For true gateways, use gateway.id as prefix (e.g., \"netlify/anthropic\")\n // Special case: if providerId matches gateway.id, it's a unified gateway (e.g., netlify returning {netlify: {...}})\n // In this case, use just the gateway ID to avoid duplication (netlify, not netlify/netlify)\n const typeProviderId = isProviderRegistry\n ? providerId\n : providerId === gateway.id\n ? gateway.id\n : `${gateway.id}/${providerId}`;\n\n allProviders[typeProviderId] = config;\n // Sort models alphabetically for consistent ordering\n allModels[typeProviderId] = config.models.sort();\n }\n\n lastError = null;\n break; // Success, exit retry loop\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n if (attempt < maxRetries) {\n // Wait before retrying (exponential backoff)\n const delayMs = Math.min(1000 * Math.pow(2, attempt - 1), 5000);\n await new Promise(resolve => setTimeout(resolve, delayMs));\n }\n }\n }\n\n // If all retries failed, throw the last error\n if (lastError) {\n throw lastError;\n }\n }\n\n return { providers: allProviders, models: allModels };\n}\n\n/**\n * Generate TypeScript type definitions content\n * @param models - Record of provider IDs to model arrays\n * @returns Generated TypeScript type definitions as a string\n */\nexport function generateTypesContent(models: Record<string, string[]>): string {\n const providerModelsEntries = Object.entries(models)\n .map(([provider, modelList]) => {\n const modelsList = modelList.map(m => `'${m}'`);\n\n // Only quote provider key if it contains special characters (like dashes)\n const needsQuotes = /[^a-zA-Z0-9_$]/.test(provider);\n const providerKey = needsQuotes ? `'${provider}'` : provider;\n\n // Format array based on length (prettier printWidth: 120)\n const singleLine = ` readonly ${providerKey}: readonly [${modelsList.join(', ')}];`;\n\n // If single line exceeds 120 chars, format as multi-line\n if (singleLine.length > 120) {\n const formattedModels = modelList.map(m => ` '${m}',`).join('\\n');\n return ` readonly ${providerKey}: readonly [\\n${formattedModels}\\n ];`;\n }\n\n return singleLine;\n })\n .join('\\n');\n\n return `/**\n * THIS FILE IS AUTO-GENERATED - DO NOT EDIT\n * Generated from model gateway providers\n */\n\n/**\n * Provider models mapping type\n * This is derived from the JSON data and provides type-safe access\n */\nexport type ProviderModelsMap = {\n${providerModelsEntries}\n};\n\n/**\n * Union type of all registered provider IDs\n */\nexport type Provider = keyof ProviderModelsMap;\n\n/**\n * Provider models mapping interface\n */\nexport interface ProviderModels {\n [key: string]: string[];\n}\n\n/**\n * OpenAI-compatible model ID type\n * Dynamically derived from ProviderModelsMap\n * Full provider/model paths (e.g., \"openai/gpt-4o\", \"anthropic/claude-3-5-sonnet-20241022\")\n */\nexport type ModelRouterModelId =\n | {\n [P in Provider]: \\`\\${P}/\\${ProviderModelsMap[P][number]}\\`;\n }[Provider]\n | (string & {});\n\n/**\n * Extract the model part from a ModelRouterModelId for a specific provider\n * Dynamically derived from ProviderModelsMap\n * Example: ModelForProvider<'openai'> = 'gpt-4o' | 'gpt-4-turbo' | ...\n */\nexport type ModelForProvider<P extends Provider> = ProviderModelsMap[P][number];\n`;\n}\n\n/**\n * Write registry files to disk (JSON and .d.ts)\n * @param jsonPath - Path to write the JSON file\n * @param typesPath - Path to write the .d.ts file\n * @param providers - Provider configurations\n * @param models - Model lists by provider\n */\nexport async function writeRegistryFiles(\n jsonPath: string,\n typesPath: string,\n providers: Record<string, ProviderConfig>,\n models: Record<string, string[]>,\n): Promise<void> {\n // 0. Ensure directories exist\n const jsonDir = path.dirname(jsonPath);\n const typesDir = path.dirname(typesPath);\n await fs.mkdir(jsonDir, { recursive: true });\n await fs.mkdir(typesDir, { recursive: true });\n\n // 1. Write JSON file atomically to prevent corruption from concurrent writes\n const registryData = {\n providers,\n models,\n version: '1.0.0',\n };\n\n await atomicWriteFile(jsonPath, JSON.stringify(registryData, null, 2), 'utf-8');\n\n // 2. Generate .d.ts file with type-only declarations (also atomic)\n const typeContent = generateTypesContent(models);\n await atomicWriteFile(typesPath, typeContent, 'utf-8');\n}\n"]}