@ai-sdk/google-vertex
Version:
224 lines (223 loc) • 8.73 kB
JavaScript
import { fetchWithValidatedEndpoint, getRuntimeEnvironmentUserAgent, isBrowserRuntime, isSameOrigin, isValidHostnamePart, loadOptionalSetting, loadSetting, resolve, withUserAgentSuffix, withoutTrailingSlash } from "@ai-sdk/provider-utils";
import { InvalidArgumentError } 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/google-vertex-model-catalog-config.ts
function requestConfig(modelId) {
const embedContent = modelId === "gemini-embedding-2" || modelId === "gemini-embedding-2-preview";
return {
language: {
endpoint: modelId.startsWith("endpoints/"),
maxOutputTokens: modelId === "meta/llama-4-maverick-17b-128e-instruct-maas" || modelId === "meta/llama-4-scout-17b-16e-instruct-maas" ? 8192 : void 0
},
image: { gemini: modelId.startsWith("gemini-") },
embedding: {
endpoint: embedContent ? "embedContent" : "predict",
maxEmbeddingsPerCall: embedContent ? 1 : 250
},
speech: { api: modelId.startsWith("chirp") ? "cloud-tts" : "gemini" },
transcription: {
api: modelId.startsWith("gemini") ? "gemini" : "cloud-speech",
live: modelId.includes("-live")
}
};
}
function getGoogleVertexRequestConfig(modelId) {
return requestConfig(modelId);
}
//#endregion
//#region src/maas/google-vertex-maas-provider.ts
function transformGoogleVertexMaasRequestBody(args) {
const maxOutputTokens = getGoogleVertexRequestConfig(args.model).language?.maxOutputTokens;
return maxOutputTokens != null && args.max_tokens === void 0 ? {
...args,
max_tokens: maxOutputTokens
} : args;
}
/**
* Loads the base URL of the MaaS API from the settings or from the project and
* location. Settings are loaded on each call so environment variables are read
* at runtime.
*/
function loadGoogleVertexMaasBaseURL(options) {
const loadLocation = () => {
const location = loadOptionalSetting({
settingValue: options.location,
environmentVariableName: "GOOGLE_VERTEX_LOCATION"
}) ?? "global";
if (!isValidHostnamePart(location)) throw new InvalidArgumentError({
argument: "location",
message: "Invalid Google Vertex location. Expected a single DNS label (letters, digits, and hyphens). Use `baseURL` for custom endpoints."
});
return location;
};
const loadProject = () => loadSetting({
settingValue: options.project,
settingName: "project",
environmentVariableName: "GOOGLE_VERTEX_PROJECT",
description: "Google Vertex project"
});
const getHost = (location) => {
if (location === "global") return "aiplatform.googleapis.com";
else if (location === "eu" || location === "us") return `aiplatform.${location}.rep.googleapis.com`;
else return `${location}-aiplatform.googleapis.com`;
};
const constructBaseURL = () => {
const projectId = loadProject();
const location = loadLocation();
return `https://${getHost(location)}/v1/projects/${projectId}/locations/${location}/endpoints/openapi`;
};
return withoutTrailingSlash(options.baseURL ?? "") || constructBaseURL();
}
/**
* Create a Google Vertex AI MaaS (Model as a Service) provider instance.
* Uses the OpenAI-compatible Chat Completions API for partner and open models.
*
* @see https://cloud.google.com/vertex-ai/generative-ai/docs/maas/use-open-models
*/
function createGoogleVertexMaas$1(options = {}) {
let cachedProvider;
const getProvider = () => cachedProvider ??= createOpenAICompatible({
name: "vertex.maas",
baseURL: loadGoogleVertexMaasBaseURL(options),
fetch: options.fetch,
transformRequestBody: transformGoogleVertexMaasRequestBody
});
const provider = (modelId) => getProvider()(modelId);
provider.specificationVersion = "v4";
provider.languageModel = (modelId) => getProvider().languageModel(modelId);
provider.chatModel = (modelId) => getProvider().chatModel(modelId);
provider.completionModel = (modelId) => getProvider().completionModel(modelId);
provider.embeddingModel = (modelId) => getProvider().embeddingModel(modelId);
provider.textEmbeddingModel = (modelId) => getProvider().textEmbeddingModel(modelId);
provider.imageModel = (modelId) => getProvider().imageModel(modelId);
return provider;
}
//#endregion
//#region src/maas/edge/google-vertex-maas-provider-edge.ts
/**
* Create a Google Vertex AI MaaS (Model as a Service) provider instance for Edge runtimes.
* Uses the OpenAI-compatible Chat Completions API for partner and open models.
* Automatically handles Google Cloud authentication.
*
* @see https://cloud.google.com/vertex-ai/generative-ai/docs/maas/use-open-models
*/
function createGoogleVertexMaas(options = {}) {
const customFetch = async (url, init) => {
const href = typeof url === "string" ? url : url instanceof URL ? url.href : url.url;
if (!isSameOrigin(href, loadGoogleVertexMaasBaseURL(options))) {
if (isBrowserRuntime() && init?.redirect === "follow") return (options.fetch ?? fetch)(url, init);
return fetchWithValidatedEndpoint({
url: href,
init,
fetch: options.fetch,
redirect: "manual"
});
}
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 createGoogleVertexMaas$1({
...options,
fetch: customFetch,
headers: void 0
});
}
/**
* Default Google Vertex AI MaaS provider instance for Edge runtimes.
*/
const googleVertexMaas = createGoogleVertexMaas();
//#endregion
export { createGoogleVertexMaas, createGoogleVertexMaas as createVertexMaas, googleVertexMaas, googleVertexMaas as vertexMaas };
//# sourceMappingURL=index.js.map