@mastra/core
Version:
1 lines • 10.5 kB
Source Map (JSON)
{"version":3,"file":"netlify-DDJM4IYB.cjs","names":["MastraModelGateway","InMemoryServerCache","MastraError","MASTRA_USER_AGENT","createOpenAI","createGoogleGenerativeAI","createAnthropic","createOpenAICompatible"],"sources":["../src/llm/model/gateways/netlify.ts"],"sourcesContent":["import { createAnthropic } from '@ai-sdk/anthropic-v6';\nimport { createGoogleGenerativeAI } from '@ai-sdk/google-v6';\nimport { createOpenAICompatible } from '@ai-sdk/openai-compatible-v6';\nimport { createOpenAI } from '@ai-sdk/openai-v6';\nimport { InMemoryServerCache } from '../../../cache/inmemory.js';\nimport { MastraError } from '../../../error/index.js';\nimport { MastraModelGateway } from './base.js';\nimport type { ProviderConfig, GatewayLanguageModel } from './base.js';\nimport { MASTRA_USER_AGENT } from './constants.js';\n\ninterface NetlifyProviderResponse {\n token_env_var: string;\n url_env_var: string;\n models: string[];\n}\ninterface NetlifyResponse {\n providers: Record<string, NetlifyProviderResponse>;\n}\n\ninterface NetlifyTokenResponse {\n token: string;\n url: string;\n expires_at: number;\n}\n\ninterface CachedToken {\n token: string;\n url: string;\n expiresAt: number;\n}\n\ninterface TokenData {\n token: string;\n url: string;\n}\n\nexport class NetlifyGateway extends MastraModelGateway {\n readonly id = 'netlify';\n readonly name = 'Netlify AI Gateway';\n private tokenCache = new InMemoryServerCache();\n\n async fetchProviders(): Promise<Record<string, ProviderConfig>> {\n const response = await fetch('https://api.netlify.com/api/v1/ai-gateway/providers');\n if (!response.ok) {\n throw new Error(`Failed to fetch from Netlify: ${response.statusText}`);\n }\n const data = (await response.json()) as NetlifyResponse;\n const config: ProviderConfig = {\n apiKeyEnvVar: ['NETLIFY_TOKEN', 'NETLIFY_SITE_ID'],\n apiKeyHeader: 'Authorization',\n name: `Netlify`,\n gateway: `netlify`,\n models: [],\n docUrl: 'https://docs.netlify.com/build/ai-gateway/overview/',\n };\n // Convert Netlify format to our standard format\n for (const [providerId, provider] of Object.entries(data.providers)) {\n for (const model of provider.models) {\n config.models.push(`${providerId}/${model}`);\n }\n }\n // Return with gateway ID as key - registry generator will detect this and avoid doubling the prefix\n return { netlify: config };\n }\n\n async buildUrl(routerId: string, envVars?: typeof process.env): Promise<string> {\n // Check for Netlify site ID first (for token exchange)\n const siteId = envVars?.['NETLIFY_SITE_ID'] || process.env['NETLIFY_SITE_ID'];\n const netlifyToken = envVars?.['NETLIFY_TOKEN'] || process.env['NETLIFY_TOKEN'];\n\n if (!netlifyToken) {\n throw new MastraError({\n id: 'NETLIFY_GATEWAY_NO_TOKEN',\n domain: 'LLM',\n category: 'UNKNOWN',\n text: `Missing NETLIFY_TOKEN environment variable required for model: ${routerId}`,\n });\n }\n\n if (!siteId) {\n throw new MastraError({\n id: 'NETLIFY_GATEWAY_NO_SITE_ID',\n domain: 'LLM',\n category: 'UNKNOWN',\n text: `Missing NETLIFY_SITE_ID environment variable required for model: ${routerId}`,\n });\n }\n\n try {\n const tokenData = await this.getOrFetchToken(siteId, netlifyToken);\n return tokenData.url.endsWith(`/`) ? tokenData.url.substring(0, tokenData.url.length - 1) : tokenData.url;\n } catch (error) {\n throw new MastraError({\n id: 'NETLIFY_GATEWAY_TOKEN_ERROR',\n domain: 'LLM',\n category: 'UNKNOWN',\n text: `Failed to get Netlify AI Gateway token for model ${routerId}: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n }\n\n /**\n * Get cached token or fetch a new site-specific AI Gateway token from Netlify\n */\n private async getOrFetchToken(siteId: string, netlifyToken: string): Promise<TokenData> {\n const cacheKey = `netlify-token:${siteId}:${netlifyToken}`;\n\n // Check cache first\n const cached = (await this.tokenCache.get(cacheKey)) as CachedToken | undefined;\n if (cached && cached.expiresAt > Date.now() / 1000 + 60) {\n // Return cached token if it won't expire in the next minute\n return { token: cached.token, url: cached.url };\n }\n\n // Fetch new token\n const response = await fetch(`https://api.netlify.com/api/v1/sites/${siteId}/ai-gateway/token`, {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${netlifyToken}`,\n },\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to get Netlify AI Gateway token: ${response.status} ${error}`);\n }\n\n const tokenResponse = (await response.json()) as NetlifyTokenResponse;\n\n // Cache the token - InMemoryServerCache will handle the TTL\n await this.tokenCache.set(cacheKey, {\n token: tokenResponse.token,\n url: tokenResponse.url,\n expiresAt: tokenResponse.expires_at,\n });\n\n return { token: tokenResponse.token, url: tokenResponse.url };\n }\n\n /**\n * Get cached token or fetch a new site-specific AI Gateway token from Netlify\n */\n async getApiKey(modelId: string): Promise<string> {\n const siteId = process.env['NETLIFY_SITE_ID'];\n const netlifyToken = process.env['NETLIFY_TOKEN'];\n\n if (!netlifyToken) {\n throw new MastraError({\n id: 'NETLIFY_GATEWAY_NO_TOKEN',\n domain: 'LLM',\n category: 'UNKNOWN',\n text: `Missing NETLIFY_TOKEN environment variable required for model: ${modelId}`,\n });\n }\n\n if (!siteId) {\n throw new MastraError({\n id: 'NETLIFY_GATEWAY_NO_SITE_ID',\n domain: 'LLM',\n category: 'UNKNOWN',\n text: `Missing NETLIFY_SITE_ID environment variable required for model: ${modelId}`,\n });\n }\n\n try {\n return (await this.getOrFetchToken(siteId, netlifyToken)).token;\n } catch (error) {\n throw new MastraError({\n id: 'NETLIFY_GATEWAY_TOKEN_ERROR',\n domain: 'LLM',\n category: 'UNKNOWN',\n text: `Failed to get Netlify AI Gateway token for model ${modelId}: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n }\n\n async resolveLanguageModel({\n modelId,\n providerId,\n apiKey,\n headers,\n }: {\n modelId: string;\n providerId: string;\n apiKey: string;\n headers?: Record<string, string>;\n }): Promise<GatewayLanguageModel> {\n const baseURL = await this.buildUrl(`${providerId}/${modelId}`);\n\n const mastraHeaders = { 'User-Agent': MASTRA_USER_AGENT, ...headers };\n\n switch (providerId) {\n case 'openai':\n return createOpenAI({ apiKey, baseURL, headers: mastraHeaders }).responses(modelId);\n case 'gemini':\n return createGoogleGenerativeAI({\n baseURL: `${baseURL}/v1beta/`,\n apiKey,\n headers: {\n 'user-agent': 'google-genai-sdk/',\n ...mastraHeaders,\n },\n }).chat(modelId);\n case 'anthropic':\n return createAnthropic({\n apiKey,\n baseURL: `${baseURL}/v1/`,\n headers: {\n 'anthropic-version': '2023-06-01',\n ...mastraHeaders,\n },\n })(modelId);\n default:\n return createOpenAICompatible({\n name: providerId,\n apiKey,\n baseURL,\n headers: mastraHeaders,\n supportsStructuredOutputs: true,\n }).chatModel(modelId);\n }\n }\n}\n"],"mappings":"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"}