UNPKG

cloud-code-ai-provider

Version:

Google Cloud Code provider for the AI SDK

1,031 lines (1,022 loc) 32.9 kB
// src/google-cloud-code-provider.ts import { NoSuchModelError } from "@ai-sdk/provider"; import { resolve as resolve2, withoutTrailingSlash } from "@ai-sdk/provider-utils"; // src/google-cloud-code-language-model.ts import { combineHeaders, createEventSourceResponseHandler, createJsonResponseHandler, postJsonToApi, resolve, injectJsonInstructionIntoMessages } from "@ai-sdk/provider-utils"; import { z as z2 } from "zod/v4"; // src/convert-to-cloud-code-messages.ts import { UnsupportedFunctionalityError } from "@ai-sdk/provider"; import { convertUint8ArrayToBase64 } from "@ai-sdk/provider-utils"; function convertToCloudCodeMessages(prompt) { const messages = []; let systemInstruction; for (const message of prompt) { const { role, content } = message; switch (role) { case "system": { systemInstruction = systemInstruction ? `${systemInstruction} ${content}` : content; break; } case "user": { const parts = []; for (const part of content) { switch (part.type) { case "text": { const p = part; parts.push({ text: p.text }); break; } case "file": { const file = part; if (file.data instanceof URL) { throw new UnsupportedFunctionalityError({ functionality: "File URL parts in messages" }); } parts.push({ inlineData: { mimeType: file.mediaType ?? "application/octet-stream", data: typeof file.data === "string" ? file.data : convertUint8ArrayToBase64(file.data) } }); break; } } } messages.push({ role: "user", parts }); break; } case "assistant": { const parts = []; for (const part of content) { switch (part.type) { case "text": { const text = part.text; if (text.length > 0) { parts.push({ text }); } break; } case "tool-call": { const toolCall = part; parts.push({ functionCall: { name: toolCall.toolName, args: toolCall.input } }); break; } } } if (parts.length > 0) { messages.push({ role: "model", parts }); } break; } case "tool": { const parts = []; for (const toolResponse of content) { let response; if ("output" in toolResponse) { const out = toolResponse.output; switch (out.type) { case "text": response = out.value; break; case "json": response = out.value; break; case "error-text": response = { error: out.value }; break; case "error-json": response = { error: out.value }; break; case "content": response = out.value.map( (v) => v.type === "text" ? { text: v.text } : { inlineData: { mimeType: v.mediaType, data: v.data } } ); break; default: response = out; } } else if ("result" in toolResponse) { response = toolResponse.result; } parts.push({ functionResponse: { name: toolResponse.toolName, response } }); } messages.push({ role: "function", parts }); break; } default: { const _exhaustiveCheck = role; throw new Error(`Unsupported role: ${_exhaustiveCheck}`); } } } const result = { contents: messages }; if (systemInstruction) { result.systemInstruction = { role: "user", parts: [{ text: systemInstruction }] }; } return result; } // src/map-cloud-code-finish-reason.ts function mapCloudCodeFinishReason(finishReason) { switch (finishReason) { case "STOP": return "stop"; case "MAX_TOKENS": return "length"; case "SAFETY": return "content-filter"; case "RECITATION": return "content-filter"; case "OTHER": return "other"; default: return "unknown"; } } // src/google-cloud-code-error.ts import { createJsonErrorResponseHandler } from "@ai-sdk/provider-utils"; import { z } from "zod"; var cloudCodeErrorDataSchema = z.object({ error: z.object({ code: z.number(), message: z.string(), status: z.string().optional(), details: z.array(z.any()).optional() }) }); var cloudCodeFailedResponseHandler = createJsonErrorResponseHandler({ errorSchema: cloudCodeErrorDataSchema, errorToMessage: (data) => data.error.message }); // src/google-cloud-code-prepare-tools.ts function prepareTools(mode) { const toolWarnings = []; if (!mode.tools || mode.tools.length === 0) { return { toolWarnings }; } const functionDeclarations = mode.tools.map((tool) => { if (tool.type === "provider-defined") { toolWarnings.push({ type: "unsupported-tool", tool, details: "Provider-defined tools are not supported by this provider." }); return void 0; } let params = tool.inputSchema; if (params && typeof params === "object" && "$schema" in params) { const { $schema, ...cleanParams } = params; params = cleanParams; } return { name: tool.name, description: tool.description, parameters: params }; }).filter((decl) => decl != null); const tools = [{ functionDeclarations }]; let toolConfig; if (mode.toolChoice) { if (mode.toolChoice.type === "none") { toolConfig = { functionCallingConfig: { mode: "NONE" } }; } else if (mode.toolChoice.type === "required") { toolConfig = { functionCallingConfig: { mode: "ANY" } }; } else if (mode.toolChoice.type === "tool") { toolConfig = { functionCallingConfig: { mode: "ANY", allowedFunctionNames: [mode.toolChoice.toolName] } }; } else { toolConfig = { functionCallingConfig: { mode: "AUTO" } }; } } else { toolConfig = { functionCallingConfig: { mode: "AUTO" } }; } return { tools, toolConfig, toolWarnings }; } // src/google-cloud-code-language-model.ts var GoogleCloudCodeLanguageModel = class { specificationVersion = "v2"; supportedUrls = { "*/*": [/^https:\/\//] }; modelId; settings; config; constructor(modelId, settings, config) { this.modelId = modelId; this.settings = settings; this.config = config; } get provider() { return this.config.provider; } async getArgs(options) { const { prompt, maxOutputTokens, temperature, topP, topK, frequencyPenalty, presencePenalty, stopSequences, responseFormat, seed, tools, toolChoice, providerOptions } = options; const warnings = []; if (frequencyPenalty != null) { warnings.push({ type: "unsupported-setting", setting: "frequencyPenalty" }); } if (presencePenalty != null) { warnings.push({ type: "unsupported-setting", setting: "presencePenalty" }); } if (seed != null) { warnings.push({ type: "unsupported-setting", setting: "seed" }); } const projectId = await this.config.getProjectId(); if (!projectId) { throw new Error("Project ID is required for Google Cloud Code API"); } const googleProviderOptions = providerOptions?.["google-cloud-code"] ?? {}; const generationConfig = { temperature, topP, topK: topK ?? this.settings.topK, maxOutputTokens, stopSequences, responseMimeType: responseFormat?.type === "json" ? "application/json" : void 0, // Reduce thought tokens by default to avoid hitting MAX_TOKENS before tool calls/completions thinkingConfig: googleProviderOptions.thinkingConfig ?? { includeThoughts: false } }; const { tools: ccTools, toolConfig, toolWarnings } = prepareTools({ tools, toolChoice }); warnings.push(...toolWarnings); const promptWithSchema = responseFormat?.type === "json" ? injectJsonInstructionIntoMessages({ messages: prompt, schema: responseFormat.schema }) : prompt; const converted = convertToCloudCodeMessages(promptWithSchema); const baseRequest = { contents: converted.contents, systemInstruction: converted.systemInstruction, generationConfig, safetySettings: this.settings.safetySettings, tools: ccTools, toolConfig }; const args = { model: this.modelId, project: projectId, request: baseRequest }; return { args, warnings }; } async doGenerate(options) { const { args, warnings } = await this.getArgs(options); let headers; try { headers = await resolve(this.config.headers); } catch (error) { throw new Error( `Authentication failed: ${error instanceof Error ? error.message : "Unknown error"}` ); } const { responseHeaders, value: response, rawValue: rawResponse } = await postJsonToApi({ url: `${this.config.baseURL}/v1internal:generateContent`, headers: combineHeaders(headers, options.headers), body: args, failedResponseHandler: cloudCodeFailedResponseHandler, successfulResponseHandler: createJsonResponseHandler( cloudCodeGenerateContentResponseSchema ), abortSignal: options.abortSignal, fetch: this.config.fetch }); const actualResponse = response.response; const candidate = actualResponse.candidates?.[0]; if (!candidate) { throw new Error("No candidates in response"); } const content = candidate.content; if (!content || !Array.isArray(content.parts)) { return { content: [], finishReason: mapCloudCodeFinishReason(candidate.finishReason), usage: { inputTokens: actualResponse.usageMetadata?.promptTokenCount ?? void 0, outputTokens: actualResponse.usageMetadata?.candidatesTokenCount ?? void 0, totalTokens: actualResponse.usageMetadata?.totalTokenCount ?? void 0 }, request: { body: args }, response: { headers: responseHeaders, body: rawResponse }, warnings }; } const generatedContent = []; for (const part of content.parts) { if (part.text != null) { generatedContent.push({ type: "text", text: part.text }); } if (part.functionCall != null) { generatedContent.push({ type: "tool-call", toolCallId: crypto.randomUUID(), toolName: part.functionCall.name, input: JSON.stringify(part.functionCall.args ?? {}) }); } } return { content: generatedContent, finishReason: mapCloudCodeFinishReason(candidate.finishReason), usage: { inputTokens: actualResponse.usageMetadata?.promptTokenCount ?? void 0, outputTokens: actualResponse.usageMetadata?.candidatesTokenCount ?? void 0, totalTokens: actualResponse.usageMetadata?.totalTokenCount ?? void 0 }, request: { body: args }, response: { headers: responseHeaders, body: rawResponse }, warnings }; } async doStream(options) { const { args, warnings } = await this.getArgs(options); let headers; try { headers = await resolve(this.config.headers); } catch (error) { throw new Error( `Authentication failed: ${error instanceof Error ? error.message : "Unknown error"}` ); } const { responseHeaders, value: response } = await postJsonToApi({ url: `${this.config.baseURL}/v1internal:streamGenerateContent?alt=sse`, headers: combineHeaders(headers, options.headers), body: args, failedResponseHandler: cloudCodeFailedResponseHandler, successfulResponseHandler: createEventSourceResponseHandler( cloudCodeStreamContentChunkSchema ), abortSignal: options.abortSignal, fetch: this.config.fetch }); let finishReason = "unknown"; let usage = { inputTokens: void 0, outputTokens: void 0, totalTokens: void 0 }; const stream = new ReadableStream({ async start(controller) { controller.enqueue({ type: "stream-start", warnings }); const reader = response.getReader(); try { while (true) { const { value: chunk, done } = await reader.read(); if (done) break; if (!chunk.success) { controller.enqueue({ type: "error", error: chunk.error }); continue; } const value = chunk.value; const actualResponse = value.response; if (!actualResponse) continue; if (actualResponse.usageMetadata) { usage = { inputTokens: actualResponse.usageMetadata.promptTokenCount ?? void 0, outputTokens: actualResponse.usageMetadata.candidatesTokenCount ?? void 0, totalTokens: actualResponse.usageMetadata.totalTokenCount ?? void 0 }; } const candidate = actualResponse.candidates?.[0]; if (!candidate) continue; if (candidate.finishReason) { finishReason = mapCloudCodeFinishReason(candidate.finishReason); } const content = candidate.content; if (!content || !content.parts) continue; for (const part of content.parts) { if (part.text != null) { const id = crypto.randomUUID(); controller.enqueue({ type: "text-start", id }); controller.enqueue({ type: "text-delta", id, delta: part.text }); controller.enqueue({ type: "text-end", id }); } if (part.functionCall != null) { const toolCallId = crypto.randomUUID(); controller.enqueue({ type: "tool-call", toolCallId, toolName: part.functionCall.name, input: JSON.stringify(part.functionCall.args ?? {}) }); } } } } finally { controller.enqueue({ type: "finish", finishReason, usage }); controller.close(); } } }); return { stream, request: { body: args }, response: { headers: responseHeaders } }; } }; var cloudCodeContentSchema = z2.object({ role: z2.string(), parts: z2.array( z2.object({ text: z2.string().optional(), functionCall: z2.object({ name: z2.string(), args: z2.record(z2.string(), z2.any()).optional() }).optional() }) ).optional() }); var cloudCodeCandidateSchema = z2.object({ content: cloudCodeContentSchema, finishReason: z2.string().optional() }); var cloudCodeUsageMetadataSchema = z2.object({ promptTokenCount: z2.number().optional(), candidatesTokenCount: z2.number().optional(), totalTokenCount: z2.number().optional() }); var cloudCodeGenerateContentResponseSchema = z2.object({ response: z2.object({ candidates: z2.array(cloudCodeCandidateSchema).optional(), promptFeedback: z2.any().optional(), usageMetadata: cloudCodeUsageMetadataSchema.optional() }) }); var cloudCodeStreamContentChunkSchema = z2.object({ response: z2.object({ candidates: z2.array(cloudCodeCandidateSchema).optional(), usageMetadata: cloudCodeUsageMetadataSchema.optional() }).optional() }); // src/google-cloud-code-auth.ts import { OAuth2Client } from "google-auth-library"; import * as os from "os"; import * as path from "path"; import * as fs from "fs/promises"; import * as http from "http"; import * as url from "url"; import * as crypto2 from "crypto"; import * as net from "net"; import open from "open"; var CLIENT_ID = "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com"; var CLIENT_SECRET = "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"; var SCOPES = [ "https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile" ]; var CODE_ASSIST_ENDPOINT = process.env["CODE_ASSIST_ENDPOINT"] || "https://cloudcode-pa.googleapis.com"; var CODE_ASSIST_API_VERSION = "v1internal"; var DEFAULT_GEMINI_DIR = ".gemini"; var CREDENTIAL_FILENAME = "oauth_creds.json"; var GoogleCloudCodeAuth = class { static oauthClient = null; static cachedProjectId = null; static customCredentialDir = null; static async getOAuthClient() { if (!this.oauthClient) { this.oauthClient = new OAuth2Client({ clientId: CLIENT_ID, clientSecret: CLIENT_SECRET }); } if (await this.loadCachedCredentials()) { return this.oauthClient; } return this.oauthClient; } static async setCredentials(credentials) { const client = await this.getOAuthClient(); client.setCredentials(credentials); await this.cacheCredentials(credentials); } static async getAccessToken() { const client = await this.getOAuthClient(); try { const { token } = await client.getAccessToken(); return token || void 0; } catch { return void 0; } } static generateAuthUrl(redirectUri, state) { const client = new OAuth2Client({ clientId: CLIENT_ID, clientSecret: CLIENT_SECRET }); return client.generateAuthUrl({ redirect_uri: redirectUri, access_type: "offline", scope: SCOPES, state }); } // Cloud Code Assist API methods static async callEndpoint(client, method, body) { const res = await client.request({ url: `${CODE_ASSIST_ENDPOINT}/${CODE_ASSIST_API_VERSION}:${method}`, method: "POST", headers: { "Content-Type": "application/json" }, data: body }); return res.data; } static async loadCodeAssist(client, projectId) { const metadata = this.getClientMetadata(projectId); const request = { cloudaicompanionProject: projectId, metadata }; return this.callEndpoint(client, "loadCodeAssist", request); } static async onboardUser(client, tierId, projectId) { const metadata = this.getClientMetadata(projectId); const request = { tierId, cloudaicompanionProject: projectId, metadata }; return this.callEndpoint(client, "onboardUser", request); } static getClientMetadata(projectId) { const platform2 = this.getPlatform(); return { ideType: "IDE_UNSPECIFIED", platform: platform2, pluginType: "GEMINI", duetProject: projectId }; } static getPlatform() { const platform2 = os.platform(); const arch2 = os.arch(); if (platform2 === "darwin") { return arch2 === "arm64" ? "DARWIN_ARM64" : "DARWIN_AMD64"; } else if (platform2 === "linux") { return arch2 === "arm64" ? "LINUX_ARM64" : "LINUX_AMD64"; } else if (platform2 === "win32") { return "WINDOWS_AMD64"; } return "PLATFORM_UNSPECIFIED"; } static async setupUser() { if (this.cachedProjectId) { return this.cachedProjectId; } const envProjectId = process.env["GOOGLE_CLOUD_PROJECT"]; if (envProjectId) { this.cachedProjectId = envProjectId; return envProjectId; } const client = await this.getOAuthClient(); try { const loadRes = await this.loadCodeAssist(client, envProjectId); if (!loadRes.allowedTiers || loadRes.allowedTiers.length === 0) { throw new Error("No available tiers for Code Assist. Your account may not have access."); } const defaultTier = loadRes.allowedTiers.find((tier) => tier.isDefault); const selectedTier = defaultTier || loadRes.allowedTiers[0]; const projectId = loadRes.cloudaicompanionProject || envProjectId || ""; let operation = await this.onboardUser(client, selectedTier.id, projectId); const maxAttempts = 12; let attempts = 0; while (!operation.done && attempts < maxAttempts) { await new Promise((resolve3) => setTimeout(resolve3, 5e3)); operation = await this.onboardUser(client, selectedTier.id, projectId); attempts++; } if (!operation.done) { throw new Error("Onboarding timeout - operation did not complete"); } if (operation.error) { throw new Error(`Onboarding failed: ${operation.error.message}`); } const resolvedProjectId = operation.response?.cloudaicompanionProject?.id; if (!resolvedProjectId) { throw new Error("No project ID returned from onboarding"); } this.cachedProjectId = resolvedProjectId; return resolvedProjectId; } catch (error) { if (error instanceof Error && error.message.includes("Workspace")) { throw new Error( "Google Workspace Account detected. Please set GOOGLE_CLOUD_PROJECT environment variable." ); } console.error("Failed to setup Code Assist:", error); const fallbackProjectId = "elegant-machine-vq6tl"; this.cachedProjectId = fallbackProjectId; return fallbackProjectId; } } static async getProjectId() { return this.setupUser(); } static async clearCache() { this.cachedProjectId = null; try { await fs.unlink(this.getCachedCredentialPath()); } catch { } } /** * Complete OAuth authentication flow with browser * Opens browser for authentication and handles the OAuth callback * @param options - Optional configuration for the auth flow * @returns Promise that resolves when authentication is complete */ static async authenticate(options) { const { force = false, successUrl = "https://developers.google.com/gemini-code-assist/auth_success_gemini", failureUrl = "https://developers.google.com/gemini-code-assist/auth_failure_gemini", skipBrowser = false, credentialDirectory } = options || {}; if (credentialDirectory) { this.setCredentialDirectory(credentialDirectory); } if (!force && await this.loadCachedCredentials()) { console.log("\u2705 Already authenticated. Use { force: true } to re-authenticate."); return; } if (force) { await this.clearCache(); } const port = await this.getAvailablePort(); const redirectUri = `http://localhost:${port}/oauth2callback`; const state = crypto2.randomBytes(32).toString("hex"); const authUrl = this.generateAuthUrl(redirectUri, state); const authPromise = this.createOAuthCallbackServer(port, state, redirectUri, successUrl, failureUrl); if (!skipBrowser) { console.log("\n\u{1F510} Google Cloud Code Authentication"); console.log("Opening browser for authentication...\n"); try { await open(authUrl); } catch (e) { console.log("Failed to open browser automatically."); } } console.log("Visit this URL to authenticate:"); console.log(` ${authUrl} `); console.log("Waiting for authentication..."); try { await authPromise; console.log("\n\u2705 Authentication successful!"); const projectId = await this.setupUser(); console.log(`\u{1F4C1} Project ID: ${projectId}`); console.log(`\u{1F4C2} Credentials saved to: ${this.getCachedCredentialPath()} `); } catch (error) { console.error("\n\u274C Authentication failed:", error); throw error; } } /** * Check if the user is authenticated * @returns True if authenticated with valid credentials */ static async isAuthenticated() { try { const client = await this.getOAuthClient(); const hasCredentials = await this.loadCachedCredentials(); if (!hasCredentials) return false; const { token } = await client.getAccessToken(); return !!token; } catch { return false; } } /** * Get information about the authenticated user * @returns User information including email */ static async getUserInfo() { const client = await this.getOAuthClient(); const { token } = await client.getAccessToken(); if (!token) { throw new Error("Not authenticated"); } const res = await client.request({ url: "https://www.googleapis.com/oauth2/v1/userinfo" }); return res.data; } /** * Find an available port for the OAuth callback server */ static getAvailablePort() { return new Promise((resolve3, reject) => { let port = 0; try { const server = net.createServer(); server.listen(0, () => { const address = server.address(); port = address.port; }); server.on("listening", () => { server.close(); server.unref(); }); server.on("error", (e) => reject(e)); server.on("close", () => resolve3(port)); } catch (e) { reject(e); } }); } /** * Create OAuth callback server */ static createOAuthCallbackServer(port, expectedState, redirectUri, successUrl, failureUrl) { return new Promise((resolve3, reject) => { const server = http.createServer(async (req, res) => { try { const parsedUrl = new url.URL(req.url, `http://localhost:${port}`); console.log(`OAuth callback received: ${req.url}`); if (parsedUrl.pathname !== "/oauth2callback") { res.writeHead(404); res.end("Not found"); return; } const code = parsedUrl.searchParams.get("code"); const state = parsedUrl.searchParams.get("state"); const error = parsedUrl.searchParams.get("error"); if (error) { res.writeHead(301, { Location: failureUrl }); res.end(); server.close(() => reject(new Error(`OAuth error: ${error}`))); return; } if (state !== expectedState) { res.writeHead(301, { Location: failureUrl }); res.end(); server.close(() => reject(new Error("State mismatch - possible CSRF attack"))); return; } if (!code) { res.writeHead(301, { Location: failureUrl }); res.end(); server.close(() => reject(new Error("No authorization code received"))); return; } console.log("Exchanging authorization code for tokens..."); const client = new OAuth2Client({ clientId: CLIENT_ID, clientSecret: CLIENT_SECRET, redirectUri }); const { tokens } = await client.getToken(code); console.log("Token exchange successful"); await this.setCredentials(tokens); console.log("Credentials saved"); res.writeHead(301, { Location: successUrl }); res.end(); setImmediate(() => { server.close(() => { console.log("OAuth server closed"); resolve3(); }); }); } catch (error) { console.error("OAuth callback error:", error); res.writeHead(500, { "Content-Type": "text/html" }); res.end(` <html> <body style="font-family: system-ui; padding: 40px; text-align: center;"> <h1>\u274C Authentication Error</h1> <p>An error occurred during authentication. Please check the console and try again.</p> <p style="color: #666; font-size: 14px;">${error instanceof Error ? error.message : "Unknown error"}</p> </body> </html> `); server.close(() => reject(error)); } }); server.listen(port, () => { console.log(`OAuth callback server listening on port ${port}`); }); const timeout = setTimeout(() => { server.close(() => reject(new Error("Authentication timeout"))); }, 5 * 60 * 1e3); server.on("close", () => { clearTimeout(timeout); }); }); } static setCredentialDirectory(directory) { this.customCredentialDir = directory; } static getCredentialDirectory() { return this.customCredentialDir || DEFAULT_GEMINI_DIR; } static getCachedCredentialPath() { if (process.env.GOOGLE_APPLICATION_CREDENTIALS) { return process.env.GOOGLE_APPLICATION_CREDENTIALS; } const baseDir = this.customCredentialDir || DEFAULT_GEMINI_DIR; return path.join(os.homedir(), baseDir, CREDENTIAL_FILENAME); } static async loadCachedCredentials() { try { const keyFile = process.env.GOOGLE_APPLICATION_CREDENTIALS || this.getCachedCredentialPath(); const creds = await fs.readFile(keyFile, "utf-8"); this.oauthClient.setCredentials(JSON.parse(creds)); const { token } = await this.oauthClient.getAccessToken(); if (!token) { return false; } await this.oauthClient.getTokenInfo(token); return true; } catch { return false; } } static async cacheCredentials(credentials) { const filePath = this.getCachedCredentialPath(); await fs.mkdir(path.dirname(filePath), { recursive: true }); const credString = JSON.stringify(credentials, null, 2); await fs.writeFile(filePath, credString); } }; // src/google-cloud-code-provider.ts function createGoogleCloudCode(options = {}) { const baseURL = withoutTrailingSlash( options.baseURL ?? "https://cloudcode-pa.googleapis.com" ); if (options.credentialDirectory) { GoogleCloudCodeAuth.setCredentialDirectory(options.credentialDirectory); } if (options.credentials) { GoogleCloudCodeAuth.setCredentials(options.credentials); } const getHeaders = async () => { const headers = await resolve2(options.headers); const directAccessToken = await resolve2(options.accessToken); if (directAccessToken) { return { ...headers, Authorization: `Bearer ${directAccessToken}` }; } const useOAuth = options.useOAuth !== false; if (useOAuth) { const oauthToken = await GoogleCloudCodeAuth.getAccessToken(); if (oauthToken) { return { ...headers, Authorization: `Bearer ${oauthToken}` }; } throw new Error( "Authentication required. Please run the auth flow first or provide an access token." ); } throw new Error( "No authentication credentials provided. Either enable OAuth or provide an access token." ); }; const getProjectId = async () => { const directProjectId = await resolve2(options.projectId); if (directProjectId) { return directProjectId; } const useOAuth = options.useOAuth !== false; if (useOAuth) { try { return await GoogleCloudCodeAuth.getProjectId(); } catch (error) { console.warn("Failed to get project ID through OAuth:", error); } } return void 0; }; const createLanguageModel = (modelId, settings = {}) => new GoogleCloudCodeLanguageModel(modelId, settings, { provider: "google-cloud-code", baseURL: baseURL ?? "https://cloudcode-pa.googleapis.com", headers: getHeaders, getProjectId, fetch: options.fetch }); const createTextEmbeddingModel = () => { throw new NoSuchModelError({ errorName: "NoSuchModelError", modelId: "text-embedding-001", modelType: "textEmbeddingModel", message: "Text embedding model not supported" }); }; const provider = function(modelId, settings) { if (new.target) { throw new Error( "The Google Cloud Code model function cannot be called with the new keyword." ); } return createLanguageModel(modelId, settings); }; provider.languageModel = createLanguageModel; provider.textEmbeddingModel = createTextEmbeddingModel; provider.imageModel = () => { throw new NoSuchModelError({ modelId: "image-generation", modelType: "imageModel", message: "Image model not supported" }); }; return provider; } var googleCloudCode = createGoogleCloudCode(); export { GoogleCloudCodeAuth, createGoogleCloudCode, googleCloudCode }; //# sourceMappingURL=index.js.map