UNPKG

@ai-sdk/google-vertex

Version:
217 lines (216 loc) • 7.42 kB
import { getRuntimeEnvironmentUserAgent, loadOptionalSetting, loadSetting, resolve, withUserAgentSuffix, withoutTrailingSlash } from "@ai-sdk/provider-utils"; import { NoSuchModelError } from "@ai-sdk/provider"; import { createOpenAICompatible } from "@ai-sdk/openai-compatible"; //#region src/version.ts const VERSION = "5.0.141"; //#endregion //#region src/edge/google-vertex-auth-edge.ts const loadCredentials = async () => { try { return { clientEmail: loadSetting({ settingValue: void 0, settingName: "clientEmail", environmentVariableName: "GOOGLE_CLIENT_EMAIL", description: "Google client email" }), privateKey: loadSetting({ settingValue: void 0, settingName: "privateKey", environmentVariableName: "GOOGLE_PRIVATE_KEY", description: "Google private key" }), privateKeyId: loadOptionalSetting({ settingValue: void 0, environmentVariableName: "GOOGLE_PRIVATE_KEY_ID" }) }; } catch (error) { throw new Error(`Failed to load Google credentials: ${error.message}`); } }; const base64url = (str) => { return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, ""); }; const importPrivateKey = async (pemKey) => { const pemContents = pemKey.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "").replace(/\s/g, ""); const binaryString = atob(pemContents); const binaryData = new Uint8Array(binaryString.length); for (let i = 0; i < binaryString.length; i++) binaryData[i] = binaryString.charCodeAt(i); return await crypto.subtle.importKey("pkcs8", binaryData, { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, true, ["sign"]); }; const buildJwt = async (credentials) => { const now = Math.floor(Date.now() / 1e3); const header = { alg: "RS256", typ: "JWT" }; if (credentials.privateKeyId) header.kid = credentials.privateKeyId; const payload = { iss: credentials.clientEmail, scope: "https://www.googleapis.com/auth/cloud-platform", aud: "https://oauth2.googleapis.com/token", exp: now + 3600, iat: now }; const privateKey = await importPrivateKey(credentials.privateKey); const signingInput = `${base64url(JSON.stringify(header))}.${base64url(JSON.stringify(payload))}`; const data = new TextEncoder().encode(signingInput); const signature = await crypto.subtle.sign("RSASSA-PKCS1-v1_5", privateKey, data); const signatureBase64 = base64url(String.fromCharCode(...new Uint8Array(signature))); return `${base64url(JSON.stringify(header))}.${base64url(JSON.stringify(payload))}.${signatureBase64}`; }; /** * Generate an authentication token for Google Vertex AI in a manner compatible * with the Edge runtime. */ async function generateAuthToken(credentials) { const creds = credentials || await loadCredentials(); const jwt = await buildJwt(creds); const response = await fetch("https://oauth2.googleapis.com/token", { method: "POST", headers: withUserAgentSuffix({ "Content-Type": "application/x-www-form-urlencoded" }, `ai-sdk-google-vertex/${VERSION}`, getRuntimeEnvironmentUserAgent()), body: new URLSearchParams({ grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer", assertion: jwt }) }); if (!response.ok) throw new Error(`Token request failed: ${response.statusText}`); return (await response.json()).access_token; } //#endregion //#region src/xai/google-vertex-xai-provider.ts function convertGoogleVertexXaiUsage(usage) { if (usage == null) return { inputTokens: { total: void 0, noCache: void 0, cacheRead: void 0, cacheWrite: void 0 }, outputTokens: { total: void 0, text: void 0, reasoning: void 0 }, raw: void 0 }; const promptTokens = usage.prompt_tokens ?? 0; const completionTokens = usage.completion_tokens ?? 0; const cacheReadTokens = usage.prompt_tokens_details?.cached_tokens ?? 0; const reasoningTokens = usage.completion_tokens_details?.reasoning_tokens ?? 0; return { inputTokens: { total: promptTokens, noCache: promptTokens - cacheReadTokens, cacheRead: cacheReadTokens, cacheWrite: void 0 }, outputTokens: { total: completionTokens + reasoningTokens, text: completionTokens, reasoning: reasoningTokens }, raw: usage }; } function transformGoogleVertexXaiRequestBody(args) { const { reasoning_effort: _reasoningEffort, ...rest } = args; return rest; } /** * Create a Google Vertex AI xAI provider instance. * Uses the OpenAI-compatible Chat Completions API for Grok partner models. * * @see https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/grok */ function createGoogleVertexXai$1(options = {}) { const loadLocation = () => loadOptionalSetting({ settingValue: options.location, environmentVariableName: "GOOGLE_VERTEX_LOCATION" }); const loadProject = () => loadSetting({ settingValue: options.project, settingName: "project", environmentVariableName: "GOOGLE_VERTEX_PROJECT", description: "Google Vertex project" }); const constructBaseURL = () => { return `https://aiplatform.googleapis.com/v1/projects/${loadProject()}/locations/${loadLocation() ?? "global"}/endpoints/openapi`; }; const loadBaseURL = () => withoutTrailingSlash(options.baseURL ?? "") || constructBaseURL(); let cachedProvider; const getProvider = () => cachedProvider ??= createOpenAICompatible({ name: "googleVertex.xai", baseURL: loadBaseURL(), fetch: options.fetch, includeUsage: true, supportsStructuredOutputs: true, supportedUrls: () => ({ "image/*": [/^https?:\/\/.*$/] }), transformRequestBody: transformGoogleVertexXaiRequestBody, convertUsage: convertGoogleVertexXaiUsage }); const createChatModel = (modelId) => getProvider().languageModel(modelId); const provider = function(modelId) { if (new.target) throw new Error("The Google Vertex xAI model function cannot be called with the new keyword."); return createChatModel(modelId); }; provider.specificationVersion = "v4"; provider.languageModel = createChatModel; provider.chatModel = (modelId) => getProvider().chatModel(modelId); provider.embeddingModel = (modelId) => { throw new NoSuchModelError({ modelId, modelType: "embeddingModel" }); }; provider.textEmbeddingModel = provider.embeddingModel; provider.imageModel = (modelId) => { throw new NoSuchModelError({ modelId, modelType: "imageModel" }); }; return provider; } //#endregion //#region src/xai/edge/google-vertex-xai-provider-edge.ts /** * Create a Google Vertex AI xAI provider instance for Edge runtimes. * Uses the OpenAI-compatible Chat Completions API for Grok partner models. * Automatically handles Google Cloud authentication. * * @see https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/grok */ function createGoogleVertexXai(options = {}) { const customFetch = async (url, init) => { const token = await generateAuthToken(options.googleCredentials); const authHeaders = { ...await resolve(options.headers), Authorization: `Bearer ${token}` }; const fetchInit = { ...init, headers: { ...init?.headers, ...authHeaders } }; return (options.fetch ?? fetch)(url, fetchInit); }; return createGoogleVertexXai$1({ ...options, fetch: customFetch, headers: void 0 }); } /** * Default Google Vertex AI xAI provider instance for Edge runtimes. */ const googleVertexXai = createGoogleVertexXai(); //#endregion export { createGoogleVertexXai, googleVertexXai }; //# sourceMappingURL=index.js.map