@happyvertical/ai 0.103.2 → 0.103.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +71 -0
  2. package/dist/chunks/{anthropic-CdbK9Jl-.js → anthropic-DhNGsQpl.js} +3 -3
  3. package/dist/chunks/{anthropic-CdbK9Jl-.js.map → anthropic-DhNGsQpl.js.map} +1 -1
  4. package/dist/chunks/{bedrock-DNkxz3ow.js → bedrock-CrtUO8yx.js} +3 -3
  5. package/dist/chunks/{bedrock-DNkxz3ow.js.map → bedrock-CrtUO8yx.js.map} +1 -1
  6. package/dist/chunks/{bifrost-DmbaXObX.js → bifrost-DZxTeE1Q.js} +4 -4
  7. package/dist/chunks/{bifrost-DmbaXObX.js.map → bifrost-DZxTeE1Q.js.map} +1 -1
  8. package/dist/chunks/{byteplus-modelark-BAi0y9SK.js → byteplus-modelark-gG941oea.js} +3 -3
  9. package/dist/chunks/{byteplus-modelark-BAi0y9SK.js.map → byteplus-modelark-gG941oea.js.map} +1 -1
  10. package/dist/chunks/{claude-cli-C40pIzrp.js → claude-cli-CW_gIocm.js} +3 -3
  11. package/dist/chunks/{claude-cli-C40pIzrp.js.map → claude-cli-CW_gIocm.js.map} +1 -1
  12. package/dist/chunks/{continuation-L5KnnE9R.js → continuation-KdrnmvzP.js} +2 -2
  13. package/dist/chunks/{continuation-L5KnnE9R.js.map → continuation-KdrnmvzP.js.map} +1 -1
  14. package/dist/chunks/{gateway-audio-models-B1tGNv1H.js → gateway-audio-models-DuXbi_2q.js} +2 -2
  15. package/dist/chunks/{gateway-audio-models-B1tGNv1H.js.map → gateway-audio-models-DuXbi_2q.js.map} +1 -1
  16. package/dist/chunks/{gemini-C-r6c4N9.js → gemini-DCo6d-n1.js} +3 -3
  17. package/dist/chunks/{gemini-C-r6c4N9.js.map → gemini-DCo6d-n1.js.map} +1 -1
  18. package/dist/chunks/{huggingface-DtuYF1vb.js → huggingface-jqjeFPdr.js} +3 -3
  19. package/dist/chunks/{huggingface-DtuYF1vb.js.map → huggingface-jqjeFPdr.js.map} +1 -1
  20. package/dist/chunks/{laya-D-P82D0h.js → laya-D8o5TEO7.js} +3 -3
  21. package/dist/chunks/{laya-D-P82D0h.js.map → laya-D8o5TEO7.js.map} +1 -1
  22. package/dist/chunks/{litellm-BaGgWzHR.js → litellm-8k7PMuh_.js} +4 -4
  23. package/dist/chunks/{litellm-BaGgWzHR.js.map → litellm-8k7PMuh_.js.map} +1 -1
  24. package/dist/chunks/{ollama-C3T3mn68.js → ollama-DHbYj2lH.js} +4 -4
  25. package/dist/chunks/{ollama-C3T3mn68.js.map → ollama-DHbYj2lH.js.map} +1 -1
  26. package/dist/chunks/{openai-compat-video-CwFsKAxR.js → openai-compat-video-ByTC2nzb.js} +3 -3
  27. package/dist/chunks/{openai-compat-video-CwFsKAxR.js.map → openai-compat-video-ByTC2nzb.js.map} +1 -1
  28. package/dist/chunks/{qwen-tts-DqMxfA54.js → qwen-tts-CWdO07D_.js} +2 -2
  29. package/dist/chunks/{qwen-tts-DqMxfA54.js.map → qwen-tts-CWdO07D_.js.map} +1 -1
  30. package/dist/chunks/{rate-limit-BkK4-hXY.js → rate-limit-Dwyde1BY.js} +2 -2
  31. package/dist/chunks/{rate-limit-BkK4-hXY.js.map → rate-limit-Dwyde1BY.js.map} +1 -1
  32. package/dist/chunks/{seevio-EzC6eKz-.js → seevio-B9V2nZtr.js} +3 -3
  33. package/dist/chunks/{seevio-EzC6eKz-.js.map → seevio-B9V2nZtr.js.map} +1 -1
  34. package/dist/chunks/{src-Cc5yFnnQ.js → src-BnMUshQt.js} +462 -20
  35. package/dist/chunks/src-BnMUshQt.js.map +1 -0
  36. package/dist/chunks/{typesafe-D7ZmI9-n.js → typesafe-B1_jGusy.js} +3 -3
  37. package/dist/chunks/{typesafe-D7ZmI9-n.js.map → typesafe-B1_jGusy.js.map} +1 -1
  38. package/dist/chunks/{usage-B9gPCWSa.js → usage-DS7uDhi1.js} +2 -1
  39. package/dist/chunks/usage-DS7uDhi1.js.map +1 -0
  40. package/dist/chunks/{webllm-DT31sqUY.js → webllm-DVDsgVT7.js} +2 -2
  41. package/dist/chunks/{webllm-DT31sqUY.js.map → webllm-DVDsgVT7.js.map} +1 -1
  42. package/dist/index.d.ts +1 -0
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +3 -3
  45. package/dist/local.js +2 -2
  46. package/dist/node.js +4 -4
  47. package/dist/shared/factory.d.ts.map +1 -1
  48. package/dist/shared/providers/chatgpt-plan.d.ts +60 -0
  49. package/dist/shared/providers/chatgpt-plan.d.ts.map +1 -0
  50. package/dist/shared/types.d.ts +28 -2
  51. package/dist/shared/types.d.ts.map +1 -1
  52. package/package.json +2 -2
  53. package/dist/chunks/src-Cc5yFnnQ.js.map +0 -1
  54. package/dist/chunks/usage-B9gPCWSa.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"gateway-audio-models-B1tGNv1H.js","names":[],"sources":["../../src/shared/providers/gateway-admin.ts","../../src/shared/providers/gateway-audio-models.ts"],"sourcesContent":["import type {\n AIAdminBudget,\n AIAdminInterface,\n AIAdminProject,\n AIAdminProviderConfig,\n AIAdminRateLimit,\n AIVirtualKey,\n CreateAIProjectOptions,\n CreateAIVirtualKeyOptions,\n} from '../types';\nimport { AIError } from '../types';\n\ninterface GatewayAdminTransportOptions {\n provider: string;\n baseUrl: string;\n apiKey?: string;\n username?: string;\n password?: string;\n headers?: Record<string, string>;\n timeout?: number;\n}\n\ntype JsonRecord = Record<string, unknown>;\n\nfunction stripTrailingSlash(value: string): string {\n return value.endsWith('/') ? value.slice(0, -1) : value;\n}\n\nexport function normalizeGatewayBaseUrl(baseUrl: string): string {\n return stripTrailingSlash(baseUrl.trim());\n}\n\n/**\n * Derive the gateway root URL for admin APIs from an OpenAI-compatible base URL.\n *\n * Strips known inference path suffixes iteratively so that a baseUrl such as\n * `http://host/openai/v1` collapses to the gateway root rather than to the\n * partial `http://host/openai`.\n */\nexport function deriveGatewayAdminBaseUrl(baseUrl: string): string {\n let normalized = normalizeGatewayBaseUrl(baseUrl);\n const suffixes = ['/pydanticai/v1', '/openai', '/v1'];\n let stripped = true;\n\n while (stripped) {\n stripped = false;\n for (const suffix of suffixes) {\n if (normalized.endsWith(suffix)) {\n normalized = normalized.slice(0, -suffix.length);\n stripped = true;\n break;\n }\n }\n }\n\n return normalized || normalizeGatewayBaseUrl(baseUrl);\n}\n\nexport function resolveGatewayAdminBaseUrl(\n baseUrl: string | undefined,\n adminBaseUrl: string | undefined,\n provider: string,\n): string {\n const configuredBaseUrl = adminBaseUrl || baseUrl;\n if (!configuredBaseUrl?.trim()) {\n throw new AIError(\n `${provider} baseUrl is required for admin operations`,\n 'ADMIN_BASE_URL_REQUIRED',\n provider,\n );\n }\n\n return adminBaseUrl\n ? normalizeGatewayBaseUrl(adminBaseUrl)\n : deriveGatewayAdminBaseUrl(configuredBaseUrl);\n}\n\nexport function slugifyProjectId(name: string, tenantId?: string): string {\n const value = [tenantId, name].filter(Boolean).join('-');\n const slug = value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n\n return slug || 'ai-project';\n}\n\nfunction toJsonRecord(value: unknown): JsonRecord {\n return value && typeof value === 'object' && !Array.isArray(value)\n ? (value as JsonRecord)\n : {};\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction encodeBasicCredentials(username: string, password: string): string {\n const value = `${username}:${password}`;\n\n if (typeof btoa === 'function') {\n return btoa(value);\n }\n\n return Buffer.from(value, 'utf8').toString('base64');\n}\n\nfunction removeUndefinedValues<T extends JsonRecord>(value: T): T {\n for (const key of Object.keys(value)) {\n if (value[key] === undefined) {\n delete value[key];\n }\n }\n\n return value;\n}\n\nfunction createMetadata(\n options: {\n tenantId?: string;\n description?: string;\n metadata?: Record<string, unknown>;\n },\n tenantField = 'tenant_id',\n): Record<string, unknown> | undefined {\n const metadata = {\n ...options.metadata,\n };\n\n if (options.tenantId) {\n metadata[tenantField] = options.tenantId;\n }\n\n if (options.description) {\n metadata.description = options.description;\n }\n\n return Object.keys(metadata).length > 0 ? metadata : undefined;\n}\n\nfunction responseMessage(body: unknown, fallback: string): string {\n const record = toJsonRecord(body);\n const error = toJsonRecord(record.error);\n\n return (\n stringValue(error.message) ||\n stringValue(record.message) ||\n stringValue(record.detail) ||\n fallback\n );\n}\n\nclass GatewayAdminTransport {\n private readonly baseUrl: string;\n private readonly provider: string;\n private readonly apiKey?: string;\n private readonly username?: string;\n private readonly password?: string;\n private readonly headers?: Record<string, string>;\n private readonly timeout?: number;\n\n constructor(options: GatewayAdminTransportOptions) {\n this.provider = options.provider;\n this.baseUrl = normalizeGatewayBaseUrl(options.baseUrl);\n this.apiKey = options.apiKey;\n this.username = options.username;\n this.password = options.password;\n this.headers = options.headers;\n this.timeout = options.timeout;\n }\n\n async request<T>(\n method: string,\n path: string,\n body?: unknown,\n query?: Record<string, string | undefined>,\n ): Promise<T> {\n const url = new URL(\n `${this.baseUrl}${path.startsWith('/') ? path : `/${path}`}`,\n );\n\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined) {\n url.searchParams.set(key, value);\n }\n }\n }\n\n const controller =\n typeof AbortController === 'undefined'\n ? undefined\n : new AbortController();\n const timeoutHandle =\n controller && this.timeout\n ? setTimeout(() => controller.abort(), this.timeout)\n : undefined;\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n Accept: 'application/json',\n ...(body !== undefined ? { 'Content-Type': 'application/json' } : {}),\n ...this.headers,\n ...this.createAuthHeaders(),\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n signal: controller?.signal,\n });\n\n const text = await response.text();\n const parsed = text ? this.parseJson(text) : undefined;\n\n if (!response.ok) {\n throw this.mapResponseError(response, parsed);\n }\n\n return parsed as T;\n } catch (error) {\n if (error instanceof AIError) {\n throw error;\n }\n\n throw new AIError(\n `${this.provider} admin request failed: ${\n error instanceof Error ? error.message : String(error)\n }`,\n 'ADMIN_REQUEST_FAILED',\n this.provider,\n );\n } finally {\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n }\n }\n\n private createAuthHeaders(): Record<string, string> {\n if (this.username && this.password) {\n return {\n Authorization: `Basic ${encodeBasicCredentials(\n this.username,\n this.password,\n )}`,\n };\n }\n\n return this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {};\n }\n\n private parseJson(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch (_error) {\n return { message: text };\n }\n }\n\n private mapResponseError(response: Response, body: unknown): AIError {\n const message = responseMessage(\n body,\n `${this.provider} admin request failed with ${response.status}`,\n );\n\n if (response.status === 401 || response.status === 403) {\n return new AIError(message, 'AUTH_ERROR', this.provider);\n }\n\n if (response.status === 429) {\n return new AIError(message, 'RATE_LIMIT', this.provider, undefined, true);\n }\n\n return new AIError(\n message,\n `ADMIN_HTTP_${response.status}`,\n this.provider,\n undefined,\n response.status >= 500,\n );\n }\n}\n\nfunction mapBifrostBudget(budget?: AIAdminBudget): JsonRecord | undefined {\n if (!budget) return undefined;\n\n return removeUndefinedValues({\n max_limit: budget.maxLimit,\n reset_duration: budget.resetDuration,\n calendar_aligned: budget.calendarAligned,\n });\n}\n\nfunction mapBifrostRateLimit(\n rateLimit?: AIAdminRateLimit,\n): JsonRecord | undefined {\n if (!rateLimit) return undefined;\n\n return removeUndefinedValues({\n token_max_limit: rateLimit.tokenMaxLimit ?? rateLimit.tpmLimit,\n token_reset_duration: rateLimit.tokenResetDuration,\n request_max_limit: rateLimit.requestMaxLimit ?? rateLimit.rpmLimit,\n request_reset_duration: rateLimit.requestResetDuration,\n });\n}\n\nfunction mapBifrostProviderConfigs(\n configs?: AIAdminProviderConfig[],\n): JsonRecord[] | undefined {\n if (!configs) return undefined;\n\n return configs.map((config) =>\n removeUndefinedValues({\n provider: config.provider,\n weight: config.weight,\n allowed_models: config.allowedModels,\n key_ids: config.keyIds,\n }),\n );\n}\n\nfunction mapLiteLLMBudget(\n budget?: AIAdminBudget,\n): Pick<JsonRecord, 'max_budget' | 'budget_duration'> {\n return removeUndefinedValues({\n max_budget: budget?.maxLimit,\n budget_duration: budget?.resetDuration,\n });\n}\n\nfunction mapLiteLLMRateLimit(\n rateLimit?: AIAdminRateLimit,\n): Pick<JsonRecord, 'tpm_limit' | 'rpm_limit'> {\n return removeUndefinedValues({\n tpm_limit: rateLimit?.tpmLimit ?? rateLimit?.tokenMaxLimit,\n rpm_limit: rateLimit?.rpmLimit ?? rateLimit?.requestMaxLimit,\n });\n}\n\nexport class BifrostAdmin implements AIAdminInterface {\n private readonly transport: GatewayAdminTransport;\n\n constructor(options: GatewayAdminTransportOptions) {\n this.transport = new GatewayAdminTransport(options);\n }\n\n async createProject(\n options: CreateAIProjectOptions,\n ): Promise<AIAdminProject> {\n const body = removeUndefinedValues({\n name: options.name,\n customer_id: options.tenantId,\n budget: mapBifrostBudget(options.budget),\n ...options.raw,\n });\n\n const response = await this.transport.request<JsonRecord>(\n 'POST',\n '/api/governance/teams',\n body,\n );\n const team = toJsonRecord(response.team ?? response);\n const id = stringValue(team.id) || stringValue(team.team_id);\n\n if (!id) {\n throw new AIError(\n 'Bifrost did not return a project id',\n 'ADMIN_INVALID_RESPONSE',\n 'bifrost',\n );\n }\n\n return {\n id,\n name:\n stringValue(team.name) || stringValue(team.team_alias) || options.name,\n tenantId: stringValue(team.customer_id) || options.tenantId,\n budgetId: stringValue(team.budget_id),\n provider: 'bifrost',\n raw: response,\n };\n }\n\n async createVirtualKey(\n options: CreateAIVirtualKeyOptions,\n ): Promise<AIVirtualKey> {\n const body = removeUndefinedValues({\n name: options.name,\n description: options.description,\n provider_configs: mapBifrostProviderConfigs(options.providerConfigs),\n team_id: options.projectId,\n customer_id: options.projectId ? undefined : options.tenantId,\n budget: mapBifrostBudget(options.budget),\n rate_limit: mapBifrostRateLimit(options.rateLimit),\n key_ids: options.keyIds,\n is_active: options.isActive ?? true,\n ...options.raw,\n });\n\n const response = await this.transport.request<JsonRecord>(\n 'POST',\n '/api/governance/virtual-keys',\n body,\n );\n const virtualKey = toJsonRecord(\n response.virtual_key ?? response.virtualKey ?? response,\n );\n\n return {\n id: stringValue(virtualKey.id) || stringValue(virtualKey.key_id),\n name: stringValue(virtualKey.name) || options.name,\n key: stringValue(virtualKey.value) || stringValue(virtualKey.key),\n maskedKey:\n stringValue(virtualKey.key_name) || stringValue(virtualKey.masked_key),\n projectId: stringValue(virtualKey.team_id) || options.projectId,\n tenantId: stringValue(virtualKey.customer_id) || options.tenantId,\n expiresAt:\n stringValue(virtualKey.expires) || stringValue(virtualKey.expires_at),\n provider: 'bifrost',\n raw: response,\n };\n }\n}\n\nexport class LiteLLMAdmin implements AIAdminInterface {\n private readonly transport: GatewayAdminTransport;\n\n constructor(options: GatewayAdminTransportOptions) {\n this.transport = new GatewayAdminTransport(options);\n }\n\n async createProject(\n options: CreateAIProjectOptions,\n ): Promise<AIAdminProject> {\n const projectId =\n options.id || slugifyProjectId(options.name, options.tenantId);\n const body = removeUndefinedValues({\n team_id: projectId,\n team_alias: options.name,\n models: options.models,\n ...mapLiteLLMBudget(options.budget),\n ...mapLiteLLMRateLimit(options.rateLimit),\n metadata: createMetadata(options),\n blocked: options.isBlocked,\n ...options.raw,\n });\n\n const response = await this.transport.request<JsonRecord>(\n 'POST',\n '/team/new',\n body,\n );\n const team = toJsonRecord(response.team ?? response);\n\n return {\n id: stringValue(team.team_id) || projectId,\n name:\n stringValue(team.team_alias) || stringValue(team.name) || options.name,\n tenantId: options.tenantId,\n provider: 'litellm',\n raw: response,\n };\n }\n\n async createVirtualKey(\n options: CreateAIVirtualKeyOptions,\n ): Promise<AIVirtualKey> {\n const body = removeUndefinedValues({\n key_alias: options.name,\n team_id: options.projectId,\n user_id: options.userId,\n models: options.models,\n duration: options.duration,\n ...mapLiteLLMBudget(options.budget),\n ...mapLiteLLMRateLimit(options.rateLimit),\n metadata: createMetadata(options),\n aliases: options.aliases,\n config: options.config,\n permissions: options.permissions,\n blocked: options.isActive === undefined ? undefined : !options.isActive,\n ...options.raw,\n });\n\n const response = await this.transport.request<JsonRecord>(\n 'POST',\n '/key/generate',\n body,\n );\n\n return {\n id: stringValue(response.token_id) || stringValue(response.key_id),\n name:\n stringValue(response.key_alias) ||\n stringValue(response.key_name) ||\n options.name,\n key: stringValue(response.key),\n maskedKey: stringValue(response.key_name),\n projectId: stringValue(response.team_id) || options.projectId,\n tenantId: options.tenantId,\n expiresAt: stringValue(response.expires),\n provider: 'litellm',\n raw: response,\n };\n }\n}\n","/**\n * Audio model classification shared by the Bifrost and LiteLLM gateway\n * providers.\n *\n * Markers are matched as whole model-ID tokens (split on `/`, `-`, `_`, `.`,\n * `:` and whitespace), never as raw substrings, so an author or model segment\n * that merely contains a marker (e.g. `tts` inside `mattshumer`) is not\n * classified as audio.\n */\n\nfunction modelIdTokens(modelId: string): string[] {\n return modelId\n .toLowerCase()\n .split(/[/_.:\\s-]+/)\n .filter(Boolean);\n}\n\nfunction hasTokenSequence(tokens: string[], sequence: string[]): boolean {\n for (let i = 0; i + sequence.length <= tokens.length; i++) {\n if (sequence.every((token, offset) => tokens[i + offset] === token)) {\n return true;\n }\n }\n return false;\n}\n\nconst TRANSCRIPTION_TOKENS = new Set([\n 'transcribe',\n 'transcriber',\n 'transcription',\n 'whisper',\n]);\n\nconst SPEECH_TOKENS = new Set(['tts', 'speech']);\n\n/**\n * Speech-to-text models (e.g. `whisper-1`, `gpt-4o-transcribe`,\n * `speech-to-text-v1`, `voxtral-mini-4b-realtime`). Listed with the\n * `transcription` capability so gateway consumers can route audio to them;\n * never eligible for chat, vision, embeddings, or image generation.\n */\nexport function isTranscriptionModel(modelId: string): boolean {\n const tokens = modelIdTokens(modelId);\n return (\n tokens.some((token) => TRANSCRIPTION_TOKENS.has(token)) ||\n hasTokenSequence(tokens, ['speech', 'to', 'text']) ||\n // Voxtral realtime checkpoints are streaming speech-to-text only; other\n // Voxtral models are audio-understanding chat models.\n (tokens.includes('voxtral') && tokens.includes('realtime'))\n );\n}\n\n/**\n * Text-to-speech models (e.g. `tts-1`, `gpt-4o-mini-tts`). Listed with the\n * `speech` capability; never eligible for chat, vision, embeddings, or image\n * generation.\n */\nexport function isSpeechModel(modelId: string): boolean {\n return (\n !isTranscriptionModel(modelId) &&\n modelIdTokens(modelId).some((token) => SPEECH_TOKENS.has(token))\n );\n}\n\nexport function isAudioModel(modelId: string): boolean {\n return isTranscriptionModel(modelId) || isSpeechModel(modelId);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"gateway-audio-models-DuXbi_2q.js","names":[],"sources":["../../src/shared/providers/gateway-admin.ts","../../src/shared/providers/gateway-audio-models.ts"],"sourcesContent":["import type {\n AIAdminBudget,\n AIAdminInterface,\n AIAdminProject,\n AIAdminProviderConfig,\n AIAdminRateLimit,\n AIVirtualKey,\n CreateAIProjectOptions,\n CreateAIVirtualKeyOptions,\n} from '../types';\nimport { AIError } from '../types';\n\ninterface GatewayAdminTransportOptions {\n provider: string;\n baseUrl: string;\n apiKey?: string;\n username?: string;\n password?: string;\n headers?: Record<string, string>;\n timeout?: number;\n}\n\ntype JsonRecord = Record<string, unknown>;\n\nfunction stripTrailingSlash(value: string): string {\n return value.endsWith('/') ? value.slice(0, -1) : value;\n}\n\nexport function normalizeGatewayBaseUrl(baseUrl: string): string {\n return stripTrailingSlash(baseUrl.trim());\n}\n\n/**\n * Derive the gateway root URL for admin APIs from an OpenAI-compatible base URL.\n *\n * Strips known inference path suffixes iteratively so that a baseUrl such as\n * `http://host/openai/v1` collapses to the gateway root rather than to the\n * partial `http://host/openai`.\n */\nexport function deriveGatewayAdminBaseUrl(baseUrl: string): string {\n let normalized = normalizeGatewayBaseUrl(baseUrl);\n const suffixes = ['/pydanticai/v1', '/openai', '/v1'];\n let stripped = true;\n\n while (stripped) {\n stripped = false;\n for (const suffix of suffixes) {\n if (normalized.endsWith(suffix)) {\n normalized = normalized.slice(0, -suffix.length);\n stripped = true;\n break;\n }\n }\n }\n\n return normalized || normalizeGatewayBaseUrl(baseUrl);\n}\n\nexport function resolveGatewayAdminBaseUrl(\n baseUrl: string | undefined,\n adminBaseUrl: string | undefined,\n provider: string,\n): string {\n const configuredBaseUrl = adminBaseUrl || baseUrl;\n if (!configuredBaseUrl?.trim()) {\n throw new AIError(\n `${provider} baseUrl is required for admin operations`,\n 'ADMIN_BASE_URL_REQUIRED',\n provider,\n );\n }\n\n return adminBaseUrl\n ? normalizeGatewayBaseUrl(adminBaseUrl)\n : deriveGatewayAdminBaseUrl(configuredBaseUrl);\n}\n\nexport function slugifyProjectId(name: string, tenantId?: string): string {\n const value = [tenantId, name].filter(Boolean).join('-');\n const slug = value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n\n return slug || 'ai-project';\n}\n\nfunction toJsonRecord(value: unknown): JsonRecord {\n return value && typeof value === 'object' && !Array.isArray(value)\n ? (value as JsonRecord)\n : {};\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction encodeBasicCredentials(username: string, password: string): string {\n const value = `${username}:${password}`;\n\n if (typeof btoa === 'function') {\n return btoa(value);\n }\n\n return Buffer.from(value, 'utf8').toString('base64');\n}\n\nfunction removeUndefinedValues<T extends JsonRecord>(value: T): T {\n for (const key of Object.keys(value)) {\n if (value[key] === undefined) {\n delete value[key];\n }\n }\n\n return value;\n}\n\nfunction createMetadata(\n options: {\n tenantId?: string;\n description?: string;\n metadata?: Record<string, unknown>;\n },\n tenantField = 'tenant_id',\n): Record<string, unknown> | undefined {\n const metadata = {\n ...options.metadata,\n };\n\n if (options.tenantId) {\n metadata[tenantField] = options.tenantId;\n }\n\n if (options.description) {\n metadata.description = options.description;\n }\n\n return Object.keys(metadata).length > 0 ? metadata : undefined;\n}\n\nfunction responseMessage(body: unknown, fallback: string): string {\n const record = toJsonRecord(body);\n const error = toJsonRecord(record.error);\n\n return (\n stringValue(error.message) ||\n stringValue(record.message) ||\n stringValue(record.detail) ||\n fallback\n );\n}\n\nclass GatewayAdminTransport {\n private readonly baseUrl: string;\n private readonly provider: string;\n private readonly apiKey?: string;\n private readonly username?: string;\n private readonly password?: string;\n private readonly headers?: Record<string, string>;\n private readonly timeout?: number;\n\n constructor(options: GatewayAdminTransportOptions) {\n this.provider = options.provider;\n this.baseUrl = normalizeGatewayBaseUrl(options.baseUrl);\n this.apiKey = options.apiKey;\n this.username = options.username;\n this.password = options.password;\n this.headers = options.headers;\n this.timeout = options.timeout;\n }\n\n async request<T>(\n method: string,\n path: string,\n body?: unknown,\n query?: Record<string, string | undefined>,\n ): Promise<T> {\n const url = new URL(\n `${this.baseUrl}${path.startsWith('/') ? path : `/${path}`}`,\n );\n\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined) {\n url.searchParams.set(key, value);\n }\n }\n }\n\n const controller =\n typeof AbortController === 'undefined'\n ? undefined\n : new AbortController();\n const timeoutHandle =\n controller && this.timeout\n ? setTimeout(() => controller.abort(), this.timeout)\n : undefined;\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n Accept: 'application/json',\n ...(body !== undefined ? { 'Content-Type': 'application/json' } : {}),\n ...this.headers,\n ...this.createAuthHeaders(),\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n signal: controller?.signal,\n });\n\n const text = await response.text();\n const parsed = text ? this.parseJson(text) : undefined;\n\n if (!response.ok) {\n throw this.mapResponseError(response, parsed);\n }\n\n return parsed as T;\n } catch (error) {\n if (error instanceof AIError) {\n throw error;\n }\n\n throw new AIError(\n `${this.provider} admin request failed: ${\n error instanceof Error ? error.message : String(error)\n }`,\n 'ADMIN_REQUEST_FAILED',\n this.provider,\n );\n } finally {\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n }\n }\n\n private createAuthHeaders(): Record<string, string> {\n if (this.username && this.password) {\n return {\n Authorization: `Basic ${encodeBasicCredentials(\n this.username,\n this.password,\n )}`,\n };\n }\n\n return this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {};\n }\n\n private parseJson(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch (_error) {\n return { message: text };\n }\n }\n\n private mapResponseError(response: Response, body: unknown): AIError {\n const message = responseMessage(\n body,\n `${this.provider} admin request failed with ${response.status}`,\n );\n\n if (response.status === 401 || response.status === 403) {\n return new AIError(message, 'AUTH_ERROR', this.provider);\n }\n\n if (response.status === 429) {\n return new AIError(message, 'RATE_LIMIT', this.provider, undefined, true);\n }\n\n return new AIError(\n message,\n `ADMIN_HTTP_${response.status}`,\n this.provider,\n undefined,\n response.status >= 500,\n );\n }\n}\n\nfunction mapBifrostBudget(budget?: AIAdminBudget): JsonRecord | undefined {\n if (!budget) return undefined;\n\n return removeUndefinedValues({\n max_limit: budget.maxLimit,\n reset_duration: budget.resetDuration,\n calendar_aligned: budget.calendarAligned,\n });\n}\n\nfunction mapBifrostRateLimit(\n rateLimit?: AIAdminRateLimit,\n): JsonRecord | undefined {\n if (!rateLimit) return undefined;\n\n return removeUndefinedValues({\n token_max_limit: rateLimit.tokenMaxLimit ?? rateLimit.tpmLimit,\n token_reset_duration: rateLimit.tokenResetDuration,\n request_max_limit: rateLimit.requestMaxLimit ?? rateLimit.rpmLimit,\n request_reset_duration: rateLimit.requestResetDuration,\n });\n}\n\nfunction mapBifrostProviderConfigs(\n configs?: AIAdminProviderConfig[],\n): JsonRecord[] | undefined {\n if (!configs) return undefined;\n\n return configs.map((config) =>\n removeUndefinedValues({\n provider: config.provider,\n weight: config.weight,\n allowed_models: config.allowedModels,\n key_ids: config.keyIds,\n }),\n );\n}\n\nfunction mapLiteLLMBudget(\n budget?: AIAdminBudget,\n): Pick<JsonRecord, 'max_budget' | 'budget_duration'> {\n return removeUndefinedValues({\n max_budget: budget?.maxLimit,\n budget_duration: budget?.resetDuration,\n });\n}\n\nfunction mapLiteLLMRateLimit(\n rateLimit?: AIAdminRateLimit,\n): Pick<JsonRecord, 'tpm_limit' | 'rpm_limit'> {\n return removeUndefinedValues({\n tpm_limit: rateLimit?.tpmLimit ?? rateLimit?.tokenMaxLimit,\n rpm_limit: rateLimit?.rpmLimit ?? rateLimit?.requestMaxLimit,\n });\n}\n\nexport class BifrostAdmin implements AIAdminInterface {\n private readonly transport: GatewayAdminTransport;\n\n constructor(options: GatewayAdminTransportOptions) {\n this.transport = new GatewayAdminTransport(options);\n }\n\n async createProject(\n options: CreateAIProjectOptions,\n ): Promise<AIAdminProject> {\n const body = removeUndefinedValues({\n name: options.name,\n customer_id: options.tenantId,\n budget: mapBifrostBudget(options.budget),\n ...options.raw,\n });\n\n const response = await this.transport.request<JsonRecord>(\n 'POST',\n '/api/governance/teams',\n body,\n );\n const team = toJsonRecord(response.team ?? response);\n const id = stringValue(team.id) || stringValue(team.team_id);\n\n if (!id) {\n throw new AIError(\n 'Bifrost did not return a project id',\n 'ADMIN_INVALID_RESPONSE',\n 'bifrost',\n );\n }\n\n return {\n id,\n name:\n stringValue(team.name) || stringValue(team.team_alias) || options.name,\n tenantId: stringValue(team.customer_id) || options.tenantId,\n budgetId: stringValue(team.budget_id),\n provider: 'bifrost',\n raw: response,\n };\n }\n\n async createVirtualKey(\n options: CreateAIVirtualKeyOptions,\n ): Promise<AIVirtualKey> {\n const body = removeUndefinedValues({\n name: options.name,\n description: options.description,\n provider_configs: mapBifrostProviderConfigs(options.providerConfigs),\n team_id: options.projectId,\n customer_id: options.projectId ? undefined : options.tenantId,\n budget: mapBifrostBudget(options.budget),\n rate_limit: mapBifrostRateLimit(options.rateLimit),\n key_ids: options.keyIds,\n is_active: options.isActive ?? true,\n ...options.raw,\n });\n\n const response = await this.transport.request<JsonRecord>(\n 'POST',\n '/api/governance/virtual-keys',\n body,\n );\n const virtualKey = toJsonRecord(\n response.virtual_key ?? response.virtualKey ?? response,\n );\n\n return {\n id: stringValue(virtualKey.id) || stringValue(virtualKey.key_id),\n name: stringValue(virtualKey.name) || options.name,\n key: stringValue(virtualKey.value) || stringValue(virtualKey.key),\n maskedKey:\n stringValue(virtualKey.key_name) || stringValue(virtualKey.masked_key),\n projectId: stringValue(virtualKey.team_id) || options.projectId,\n tenantId: stringValue(virtualKey.customer_id) || options.tenantId,\n expiresAt:\n stringValue(virtualKey.expires) || stringValue(virtualKey.expires_at),\n provider: 'bifrost',\n raw: response,\n };\n }\n}\n\nexport class LiteLLMAdmin implements AIAdminInterface {\n private readonly transport: GatewayAdminTransport;\n\n constructor(options: GatewayAdminTransportOptions) {\n this.transport = new GatewayAdminTransport(options);\n }\n\n async createProject(\n options: CreateAIProjectOptions,\n ): Promise<AIAdminProject> {\n const projectId =\n options.id || slugifyProjectId(options.name, options.tenantId);\n const body = removeUndefinedValues({\n team_id: projectId,\n team_alias: options.name,\n models: options.models,\n ...mapLiteLLMBudget(options.budget),\n ...mapLiteLLMRateLimit(options.rateLimit),\n metadata: createMetadata(options),\n blocked: options.isBlocked,\n ...options.raw,\n });\n\n const response = await this.transport.request<JsonRecord>(\n 'POST',\n '/team/new',\n body,\n );\n const team = toJsonRecord(response.team ?? response);\n\n return {\n id: stringValue(team.team_id) || projectId,\n name:\n stringValue(team.team_alias) || stringValue(team.name) || options.name,\n tenantId: options.tenantId,\n provider: 'litellm',\n raw: response,\n };\n }\n\n async createVirtualKey(\n options: CreateAIVirtualKeyOptions,\n ): Promise<AIVirtualKey> {\n const body = removeUndefinedValues({\n key_alias: options.name,\n team_id: options.projectId,\n user_id: options.userId,\n models: options.models,\n duration: options.duration,\n ...mapLiteLLMBudget(options.budget),\n ...mapLiteLLMRateLimit(options.rateLimit),\n metadata: createMetadata(options),\n aliases: options.aliases,\n config: options.config,\n permissions: options.permissions,\n blocked: options.isActive === undefined ? undefined : !options.isActive,\n ...options.raw,\n });\n\n const response = await this.transport.request<JsonRecord>(\n 'POST',\n '/key/generate',\n body,\n );\n\n return {\n id: stringValue(response.token_id) || stringValue(response.key_id),\n name:\n stringValue(response.key_alias) ||\n stringValue(response.key_name) ||\n options.name,\n key: stringValue(response.key),\n maskedKey: stringValue(response.key_name),\n projectId: stringValue(response.team_id) || options.projectId,\n tenantId: options.tenantId,\n expiresAt: stringValue(response.expires),\n provider: 'litellm',\n raw: response,\n };\n }\n}\n","/**\n * Audio model classification shared by the Bifrost and LiteLLM gateway\n * providers.\n *\n * Markers are matched as whole model-ID tokens (split on `/`, `-`, `_`, `.`,\n * `:` and whitespace), never as raw substrings, so an author or model segment\n * that merely contains a marker (e.g. `tts` inside `mattshumer`) is not\n * classified as audio.\n */\n\nfunction modelIdTokens(modelId: string): string[] {\n return modelId\n .toLowerCase()\n .split(/[/_.:\\s-]+/)\n .filter(Boolean);\n}\n\nfunction hasTokenSequence(tokens: string[], sequence: string[]): boolean {\n for (let i = 0; i + sequence.length <= tokens.length; i++) {\n if (sequence.every((token, offset) => tokens[i + offset] === token)) {\n return true;\n }\n }\n return false;\n}\n\nconst TRANSCRIPTION_TOKENS = new Set([\n 'transcribe',\n 'transcriber',\n 'transcription',\n 'whisper',\n]);\n\nconst SPEECH_TOKENS = new Set(['tts', 'speech']);\n\n/**\n * Speech-to-text models (e.g. `whisper-1`, `gpt-4o-transcribe`,\n * `speech-to-text-v1`, `voxtral-mini-4b-realtime`). Listed with the\n * `transcription` capability so gateway consumers can route audio to them;\n * never eligible for chat, vision, embeddings, or image generation.\n */\nexport function isTranscriptionModel(modelId: string): boolean {\n const tokens = modelIdTokens(modelId);\n return (\n tokens.some((token) => TRANSCRIPTION_TOKENS.has(token)) ||\n hasTokenSequence(tokens, ['speech', 'to', 'text']) ||\n // Voxtral realtime checkpoints are streaming speech-to-text only; other\n // Voxtral models are audio-understanding chat models.\n (tokens.includes('voxtral') && tokens.includes('realtime'))\n );\n}\n\n/**\n * Text-to-speech models (e.g. `tts-1`, `gpt-4o-mini-tts`). Listed with the\n * `speech` capability; never eligible for chat, vision, embeddings, or image\n * generation.\n */\nexport function isSpeechModel(modelId: string): boolean {\n return (\n !isTranscriptionModel(modelId) &&\n modelIdTokens(modelId).some((token) => SPEECH_TOKENS.has(token))\n );\n}\n\nexport function isAudioModel(modelId: string): boolean {\n return isTranscriptionModel(modelId) || isSpeechModel(modelId);\n}\n"],"mappings":";;AAwBA,SAAS,mBAAmB,OAAuB;CACjD,OAAO,MAAM,SAAS,GAAG,IAAI,MAAM,MAAM,GAAG,EAAE,IAAI;AACpD;AAEA,SAAgB,wBAAwB,SAAyB;CAC/D,OAAO,mBAAmB,QAAQ,KAAK,CAAC;AAC1C;;;;;;;;AASA,SAAgB,0BAA0B,SAAyB;CACjE,IAAI,aAAa,wBAAwB,OAAO;CAChD,MAAM,WAAW;EAAC;EAAkB;EAAW;CAAK;CACpD,IAAI,WAAW;CAEf,OAAO,UAAU;EACf,WAAW;EACX,KAAK,MAAM,UAAU,UACnB,IAAI,WAAW,SAAS,MAAM,GAAG;GAC/B,aAAa,WAAW,MAAM,GAAG,CAAC,OAAO,MAAM;GAC/C,WAAW;GACX;EACF;CAEJ;CAEA,OAAO,cAAc,wBAAwB,OAAO;AACtD;AAEA,SAAgB,2BACd,SACA,cACA,UACQ;CACR,MAAM,oBAAoB,gBAAgB;CAC1C,IAAI,CAAC,mBAAmB,KAAK,GAC3B,MAAM,IAAI,QACR,GAAG,SAAS,4CACZ,2BACA,QACF;CAGF,OAAO,eACH,wBAAwB,YAAY,IACpC,0BAA0B,iBAAiB;AACjD;AAEA,SAAgB,iBAAiB,MAAc,UAA2B;CAOxE,OANc,CAAC,UAAU,IAAI,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GACvC,CAAA,CACV,YAAY,CAAC,CACb,QAAQ,eAAe,GAAG,CAAC,CAC3B,QAAQ,YAAY,EAEhB,KAAQ;AACjB;AAEA,SAAS,aAAa,OAA4B;CAChD,OAAO,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAC5D,QACD,CAAC;AACP;AAEA,SAAS,YAAY,OAAoC;CACvD,OAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ,KAAA;AACjE;AAEA,SAAS,uBAAuB,UAAkB,UAA0B;CAC1E,MAAM,QAAQ,GAAG,SAAS,GAAG;CAE7B,IAAI,OAAO,SAAS,YAClB,OAAO,KAAK,KAAK;CAGnB,OAAO,OAAO,KAAK,OAAO,MAAM,CAAC,CAAC,SAAS,QAAQ;AACrD;AAEA,SAAS,sBAA4C,OAAa;CAChE,KAAK,MAAM,OAAO,OAAO,KAAK,KAAK,GACjC,IAAI,MAAM,SAAS,KAAA,GACjB,OAAO,MAAM;CAIjB,OAAO;AACT;AAEA,SAAS,eACP,SAKA,cAAc,aACuB;CACrC,MAAM,WAAW,EACf,GAAG,QAAQ,SACb;CAEA,IAAI,QAAQ,UACV,SAAS,eAAe,QAAQ;CAGlC,IAAI,QAAQ,aACV,SAAS,cAAc,QAAQ;CAGjC,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,SAAS,IAAI,WAAW,KAAA;AACvD;AAEA,SAAS,gBAAgB,MAAe,UAA0B;CAChE,MAAM,SAAS,aAAa,IAAI;CAGhC,OACE,YAHY,aAAa,OAAO,KAGpB,CAAA,CAAM,OAAO,KACzB,YAAY,OAAO,OAAO,KAC1B,YAAY,OAAO,MAAM,KACzB;AAEJ;AAEA,IAAM,wBAAN,MAA4B;CAC1B;CACA;CACA;CACA;CACA;CACA;CACA;CAEA,YAAY,SAAuC;EACjD,KAAK,WAAW,QAAQ;EACxB,KAAK,UAAU,wBAAwB,QAAQ,OAAO;EACtD,KAAK,SAAS,QAAQ;EACtB,KAAK,WAAW,QAAQ;EACxB,KAAK,WAAW,QAAQ;EACxB,KAAK,UAAU,QAAQ;EACvB,KAAK,UAAU,QAAQ;CACzB;CAEA,MAAM,QACJ,QACA,MACA,MACA,OACY;EACZ,MAAM,MAAM,IAAI,IACd,GAAG,KAAK,UAAU,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,QACtD;EAEA,IAAI;QACG,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,GAC7C,IAAI,UAAU,KAAA,GACZ,IAAI,aAAa,IAAI,KAAK,KAAK;EAAA;EAKrC,MAAM,aACJ,OAAO,oBAAoB,cACvB,KAAA,IACA,IAAI,gBAAgB;EAC1B,MAAM,gBACJ,cAAc,KAAK,UACf,iBAAiB,WAAW,MAAM,GAAG,KAAK,OAAO,IACjD,KAAA;EAEN,IAAI;GACF,MAAM,WAAW,MAAM,MAAM,KAAK;IAChC;IACA,SAAS;KACP,QAAQ;KACR,GAAI,SAAS,KAAA,IAAY,EAAE,gBAAgB,mBAAmB,IAAI,CAAC;KACnE,GAAG,KAAK;KACR,GAAG,KAAK,kBAAkB;IAC5B;IACA,MAAM,SAAS,KAAA,IAAY,KAAA,IAAY,KAAK,UAAU,IAAI;IAC1D,QAAQ,YAAY;GACtB,CAAC;GAED,MAAM,OAAO,MAAM,SAAS,KAAK;GACjC,MAAM,SAAS,OAAO,KAAK,UAAU,IAAI,IAAI,KAAA;GAE7C,IAAI,CAAC,SAAS,IACZ,MAAM,KAAK,iBAAiB,UAAU,MAAM;GAG9C,OAAO;EACT,SAAS,OAAO;GACd,IAAI,iBAAiB,SACnB,MAAM;GAGR,MAAM,IAAI,QACR,GAAG,KAAK,SAAS,yBACf,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,KAEvD,wBACA,KAAK,QACP;EACF,UAAU;GACR,IAAI,eACF,aAAa,aAAa;EAE9B;CACF;CAEA,oBAAoD;EAClD,IAAI,KAAK,YAAY,KAAK,UACxB,OAAO,EACL,eAAe,SAAS,uBACtB,KAAK,UACL,KAAK,QACP,IACF;EAGF,OAAO,KAAK,SAAS,EAAE,eAAe,UAAU,KAAK,SAAS,IAAI,CAAC;CACrE;CAEA,UAAkB,MAAuB;EACvC,IAAI;GACF,OAAO,KAAK,MAAM,IAAI;EACxB,SAAS,QAAQ;GACf,OAAO,EAAE,SAAS,KAAK;EACzB;CACF;CAEA,iBAAyB,UAAoB,MAAwB;EACnE,MAAM,UAAU,gBACd,MACA,GAAG,KAAK,SAAS,6BAA6B,SAAS,QACzD;EAEA,IAAI,SAAS,WAAW,OAAO,SAAS,WAAW,KACjD,OAAO,IAAI,QAAQ,SAAS,cAAc,KAAK,QAAQ;EAGzD,IAAI,SAAS,WAAW,KACtB,OAAO,IAAI,QAAQ,SAAS,cAAc,KAAK,UAAU,KAAA,GAAW,IAAI;EAG1E,OAAO,IAAI,QACT,SACA,cAAc,SAAS,UACvB,KAAK,UACL,KAAA,GACA,SAAS,UAAU,GACrB;CACF;AACF;AAEA,SAAS,iBAAiB,QAAgD;CACxE,IAAI,CAAC,QAAQ,OAAO,KAAA;CAEpB,OAAO,sBAAsB;EAC3B,WAAW,OAAO;EAClB,gBAAgB,OAAO;EACvB,kBAAkB,OAAO;CAC3B,CAAC;AACH;AAEA,SAAS,oBACP,WACwB;CACxB,IAAI,CAAC,WAAW,OAAO,KAAA;CAEvB,OAAO,sBAAsB;EAC3B,iBAAiB,UAAU,iBAAiB,UAAU;EACtD,sBAAsB,UAAU;EAChC,mBAAmB,UAAU,mBAAmB,UAAU;EAC1D,wBAAwB,UAAU;CACpC,CAAC;AACH;AAEA,SAAS,0BACP,SAC0B;CAC1B,IAAI,CAAC,SAAS,OAAO,KAAA;CAErB,OAAO,QAAQ,KAAK,WAClB,sBAAsB;EACpB,UAAU,OAAO;EACjB,QAAQ,OAAO;EACf,gBAAgB,OAAO;EACvB,SAAS,OAAO;CAClB,CAAC,CACH;AACF;AAEA,SAAS,iBACP,QACoD;CACpD,OAAO,sBAAsB;EAC3B,YAAY,QAAQ;EACpB,iBAAiB,QAAQ;CAC3B,CAAC;AACH;AAEA,SAAS,oBACP,WAC6C;CAC7C,OAAO,sBAAsB;EAC3B,WAAW,WAAW,YAAY,WAAW;EAC7C,WAAW,WAAW,YAAY,WAAW;CAC/C,CAAC;AACH;AAEA,IAAa,eAAb,MAAsD;CACpD;CAEA,YAAY,SAAuC;EACjD,KAAK,YAAY,IAAI,sBAAsB,OAAO;CACpD;CAEA,MAAM,cACJ,SACyB;EACzB,MAAM,OAAO,sBAAsB;GACjC,MAAM,QAAQ;GACd,aAAa,QAAQ;GACrB,QAAQ,iBAAiB,QAAQ,MAAM;GACvC,GAAG,QAAQ;EACb,CAAC;EAED,MAAM,WAAW,MAAM,KAAK,UAAU,QACpC,QACA,yBACA,IACF;EACA,MAAM,OAAO,aAAa,SAAS,QAAQ,QAAQ;EACnD,MAAM,KAAK,YAAY,KAAK,EAAE,KAAK,YAAY,KAAK,OAAO;EAE3D,IAAI,CAAC,IACH,MAAM,IAAI,QACR,uCACA,0BACA,SACF;EAGF,OAAO;GACL;GACA,MACE,YAAY,KAAK,IAAI,KAAK,YAAY,KAAK,UAAU,KAAK,QAAQ;GACpE,UAAU,YAAY,KAAK,WAAW,KAAK,QAAQ;GACnD,UAAU,YAAY,KAAK,SAAS;GACpC,UAAU;GACV,KAAK;EACP;CACF;CAEA,MAAM,iBACJ,SACuB;EACvB,MAAM,OAAO,sBAAsB;GACjC,MAAM,QAAQ;GACd,aAAa,QAAQ;GACrB,kBAAkB,0BAA0B,QAAQ,eAAe;GACnE,SAAS,QAAQ;GACjB,aAAa,QAAQ,YAAY,KAAA,IAAY,QAAQ;GACrD,QAAQ,iBAAiB,QAAQ,MAAM;GACvC,YAAY,oBAAoB,QAAQ,SAAS;GACjD,SAAS,QAAQ;GACjB,WAAW,QAAQ,YAAY;GAC/B,GAAG,QAAQ;EACb,CAAC;EAED,MAAM,WAAW,MAAM,KAAK,UAAU,QACpC,QACA,gCACA,IACF;EACA,MAAM,aAAa,aACjB,SAAS,eAAe,SAAS,cAAc,QACjD;EAEA,OAAO;GACL,IAAI,YAAY,WAAW,EAAE,KAAK,YAAY,WAAW,MAAM;GAC/D,MAAM,YAAY,WAAW,IAAI,KAAK,QAAQ;GAC9C,KAAK,YAAY,WAAW,KAAK,KAAK,YAAY,WAAW,GAAG;GAChE,WACE,YAAY,WAAW,QAAQ,KAAK,YAAY,WAAW,UAAU;GACvE,WAAW,YAAY,WAAW,OAAO,KAAK,QAAQ;GACtD,UAAU,YAAY,WAAW,WAAW,KAAK,QAAQ;GACzD,WACE,YAAY,WAAW,OAAO,KAAK,YAAY,WAAW,UAAU;GACtE,UAAU;GACV,KAAK;EACP;CACF;AACF;AAEA,IAAa,eAAb,MAAsD;CACpD;CAEA,YAAY,SAAuC;EACjD,KAAK,YAAY,IAAI,sBAAsB,OAAO;CACpD;CAEA,MAAM,cACJ,SACyB;EACzB,MAAM,YACJ,QAAQ,MAAM,iBAAiB,QAAQ,MAAM,QAAQ,QAAQ;EAC/D,MAAM,OAAO,sBAAsB;GACjC,SAAS;GACT,YAAY,QAAQ;GACpB,QAAQ,QAAQ;GAChB,GAAG,iBAAiB,QAAQ,MAAM;GAClC,GAAG,oBAAoB,QAAQ,SAAS;GACxC,UAAU,eAAe,OAAO;GAChC,SAAS,QAAQ;GACjB,GAAG,QAAQ;EACb,CAAC;EAED,MAAM,WAAW,MAAM,KAAK,UAAU,QACpC,QACA,aACA,IACF;EACA,MAAM,OAAO,aAAa,SAAS,QAAQ,QAAQ;EAEnD,OAAO;GACL,IAAI,YAAY,KAAK,OAAO,KAAK;GACjC,MACE,YAAY,KAAK,UAAU,KAAK,YAAY,KAAK,IAAI,KAAK,QAAQ;GACpE,UAAU,QAAQ;GAClB,UAAU;GACV,KAAK;EACP;CACF;CAEA,MAAM,iBACJ,SACuB;EACvB,MAAM,OAAO,sBAAsB;GACjC,WAAW,QAAQ;GACnB,SAAS,QAAQ;GACjB,SAAS,QAAQ;GACjB,QAAQ,QAAQ;GAChB,UAAU,QAAQ;GAClB,GAAG,iBAAiB,QAAQ,MAAM;GAClC,GAAG,oBAAoB,QAAQ,SAAS;GACxC,UAAU,eAAe,OAAO;GAChC,SAAS,QAAQ;GACjB,QAAQ,QAAQ;GAChB,aAAa,QAAQ;GACrB,SAAS,QAAQ,aAAa,KAAA,IAAY,KAAA,IAAY,CAAC,QAAQ;GAC/D,GAAG,QAAQ;EACb,CAAC;EAED,MAAM,WAAW,MAAM,KAAK,UAAU,QACpC,QACA,iBACA,IACF;EAEA,OAAO;GACL,IAAI,YAAY,SAAS,QAAQ,KAAK,YAAY,SAAS,MAAM;GACjE,MACE,YAAY,SAAS,SAAS,KAC9B,YAAY,SAAS,QAAQ,KAC7B,QAAQ;GACV,KAAK,YAAY,SAAS,GAAG;GAC7B,WAAW,YAAY,SAAS,QAAQ;GACxC,WAAW,YAAY,SAAS,OAAO,KAAK,QAAQ;GACpD,UAAU,QAAQ;GAClB,WAAW,YAAY,SAAS,OAAO;GACvC,UAAU;GACV,KAAK;EACP;CACF;AACF;;;;;;;;;;;;AC9eA,SAAS,cAAc,SAA2B;CAChD,OAAO,QACJ,YAAY,CAAC,CACb,MAAM,YAAY,CAAC,CACnB,OAAO,OAAO;AACnB;AAEA,SAAS,iBAAiB,QAAkB,UAA6B;CACvE,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,UAAU,OAAO,QAAQ,KACpD,IAAI,SAAS,OAAO,OAAO,WAAW,OAAO,IAAI,YAAY,KAAK,GAChE,OAAO;CAGX,OAAO;AACT;AAEA,IAAM,uCAAuB,IAAI,IAAI;CACnC;CACA;CACA;CACA;AACF,CAAC;AAED,IAAM,gCAAgB,IAAI,IAAI,CAAC,OAAO,QAAQ,CAAC;;;;;;;AAQ/C,SAAgB,qBAAqB,SAA0B;CAC7D,MAAM,SAAS,cAAc,OAAO;CACpC,OACE,OAAO,MAAM,UAAU,qBAAqB,IAAI,KAAK,CAAC,KACtD,iBAAiB,QAAQ;EAAC;EAAU;EAAM;CAAM,CAAC,KAGhD,OAAO,SAAS,SAAS,KAAK,OAAO,SAAS,UAAU;AAE7D;;;;;;AAOA,SAAgB,cAAc,SAA0B;CACtD,OACE,CAAC,qBAAqB,OAAO,KAC7B,cAAc,OAAO,CAAC,CAAC,MAAM,UAAU,cAAc,IAAI,KAAK,CAAC;AAEnE;AAEA,SAAgB,aAAa,SAA0B;CACrD,OAAO,qBAAqB,OAAO,KAAK,cAAc,OAAO;AAC/D"}
@@ -1,5 +1,5 @@
1
- import { b as extractTextContent, c as normalizeImageGenerationOptions, f as AuthenticationError, g as ModelNotFoundError, l as prepareRequestControls, o as normalizeBaseAIOptions, s as normalizeChatOptions, t as emitUsage, u as AIError } from "./usage-B9gPCWSa.js";
2
- import { n as rateLimitErrorFrom } from "./rate-limit-BkK4-hXY.js";
1
+ import { b as extractTextContent, c as normalizeImageGenerationOptions, f as AuthenticationError, g as ModelNotFoundError, l as prepareRequestControls, o as normalizeBaseAIOptions, s as normalizeChatOptions, t as emitUsage, u as AIError } from "./usage-DS7uDhi1.js";
2
+ import { n as rateLimitErrorFrom } from "./rate-limit-Dwyde1BY.js";
3
3
  import { a as toolResultObject, i as resolveToolResultName, n as indexToolCallNames, r as parseToolArguments, t as hasToolTraffic } from "./tool-messages-0ND35mYX.js";
4
4
  import { join } from "node:path";
5
5
  import crypto from "node:crypto";
@@ -990,4 +990,4 @@ var GeminiProvider = class {
990
990
  //#endregion
991
991
  export { GeminiProvider };
992
992
 
993
- //# sourceMappingURL=gemini-C-r6c4N9.js.map
993
+ //# sourceMappingURL=gemini-DCo6d-n1.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"gemini-C-r6c4N9.js","names":[],"sources":["../../src/shared/providers/gemini.ts"],"sourcesContent":["/**\n * Google Gemini provider implementation\n */\n\nimport crypto from 'node:crypto';\nimport { mkdtemp, readFile, rm } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { rateLimitErrorFrom } from '../rate-limit';\nimport {\n normalizeBaseAIOptions,\n normalizeChatOptions,\n normalizeImageGenerationOptions,\n type PreparedRequestControls,\n prepareRequestControls,\n} from '../safety';\nimport {\n hasToolTraffic,\n indexToolCallNames,\n parseToolArguments,\n resolveToolResultName,\n toolResultObject,\n} from '../tool-messages';\nimport type {\n AICapabilities,\n AIInterface,\n AIMessage,\n AIModel,\n AIResponse,\n ChatOptions,\n CompletionOptions,\n EmbeddingOptions,\n EmbeddingResponse,\n GeminiOptions,\n ImageDescriptionOptions,\n ImageEmbeddingOptions,\n ImageGenerationOptions,\n ImageGenerationResponse,\n MessageOptions,\n TokenUsage,\n TTSOptions,\n TTSResponse,\n VideoGenerationJob,\n VideoGenerationOptions,\n VideoGenerationResult,\n VideoGenerationStatusResult,\n Voice,\n VoiceCloneOptions,\n VoiceDesignOptions,\n VoiceListOptions,\n} from '../types';\nimport {\n AIError,\n AuthenticationError,\n extractTextContent,\n ModelNotFoundError,\n} from '../types';\nimport { emitUsage } from './usage';\n\n// Note: This implementation uses the new @google/genai package\n// @google/generative-ai is deprecated - migrated to @google/genai\n\ninterface GeminiPart {\n text?: string;\n functionCall?: { name: string; args: Record<string, unknown> };\n functionResponse?: { name: string; response: Record<string, unknown> };\n thoughtSignature?: string;\n}\n\ninterface GeminiContent {\n role: 'user' | 'model';\n parts: GeminiPart[];\n}\n\n/**\n * Default Veo model for video generation. Veo 2 / Veo 3.0 are deprecated in\n * favor of Veo 3.1 (still \"preview\" in its model id, but the current\n * non-deprecated generation per Google's docs as of this writing). Veo 3.1\n * supports the `resolution` config field this provider forwards; Veo 2 does\n * not, so callers pinning back to Veo 2 should omit `resolution`.\n */\nconst DEFAULT_VEO_MODEL = 'veo-3.1-generate-preview';\n\n/**\n * Placeholder thought signatures Google documents for Gemini 3\n * `functionCall` parts that have no real signature (history transferred from\n * another model, or injected calls). They bypass strict signature validation\n * and degrade reasoning quality, so real signatures are always preferred.\n *\n * - Gemini API: https://ai.google.dev/gemini-api/docs/generate-content/gemini-3\n * (\"Migrating from other models\")\n * - Vertex AI: https://docs.cloud.google.com/vertex-ai/generative-ai/docs/thought-signatures\n */\nconst GEMINI_API_PLACEHOLDER_THOUGHT_SIGNATURE =\n 'context_engineering_is_the_way_to_go';\nconst VERTEX_PLACEHOLDER_THOUGHT_SIGNATURE = 'skip_thought_signature_validator';\n\n/** Gemini 3 model ids (for example `gemini-3-flash-preview`). */\nfunction isGemini3Model(model: string): boolean {\n return /(^|\\/)gemini-3([.-]|$)/.test(model);\n}\n\n/**\n * Type-only reference to the real `GenerateVideosOperation` class. The\n * `@google/genai` SDK's `operations.getVideosOperation` calls\n * `operation._fromAPIResponse(...)`, an instance method — passing a plain\n * `{ name }` object literal throws at runtime. Typing the constructed\n * operation against this type (rather than `any`) makes tsc reject a\n * regression back to a plain literal, since `_fromAPIResponse` is a\n * required member of the real class's public shape.\n */\ntype VideosOperation = import('@google/genai').GenerateVideosOperation;\n\nexport class GeminiProvider implements AIInterface {\n private options: GeminiOptions;\n private client: any; // GoogleGenAI instance from @google/genai\n private operationCtor?: new () => VideosOperation;\n\n constructor(options: GeminiOptions) {\n this.options = normalizeBaseAIOptions({\n defaultModel: 'gemini-2.5-flash',\n ...options,\n });\n\n // Initialize Google Generative AI client\n this.initializeClientSync();\n }\n\n private initializeClientSync() {\n try {\n // Dynamic import in constructor - this will work if the package is installed\n import('@google/genai')\n .then(({ GoogleGenAI, GenerateVideosOperation }) => {\n this.client = new GoogleGenAI(this.buildClientConfig());\n this.operationCtor = GenerateVideosOperation;\n })\n .catch(() => {\n // Client will be null and we'll handle it in methods\n });\n } catch (_error) {\n // Client will be null and we'll handle it in methods\n }\n }\n\n private async ensureClient() {\n if (!this.client) {\n try {\n const { GoogleGenAI, GenerateVideosOperation } = await import(\n '@google/genai'\n );\n this.client = new GoogleGenAI(this.buildClientConfig());\n this.operationCtor = GenerateVideosOperation;\n } catch (_error) {\n throw new AIError(\n 'Failed to initialize Gemini client. Make sure @google/genai is installed.',\n 'INITIALIZATION_ERROR',\n 'gemini',\n );\n }\n }\n }\n\n /**\n * Build the GoogleGenAI client configuration based on provided options.\n * Supports both Google AI Studio (apiKey only) and Vertex AI (projectId + location).\n */\n private buildClientConfig(): Record<string, any> {\n // If projectId and location are provided, use Vertex AI mode\n if (this.options.projectId && this.options.location) {\n return {\n vertexai: true,\n project: this.options.projectId,\n location: this.options.location,\n apiKey: this.options.apiKey, // Optional for Vertex AI with ADC\n httpOptions: {\n timeout: this.options.timeout,\n retryOptions: { attempts: (this.options.maxRetries || 0) + 1 },\n },\n };\n }\n\n // Default to Google AI Studio mode with API key\n return {\n apiKey: this.options.apiKey,\n httpOptions: {\n timeout: this.options.timeout,\n retryOptions: { attempts: (this.options.maxRetries || 0) + 1 },\n },\n };\n }\n\n async chat(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): Promise<AIResponse> {\n const startTime = Date.now();\n let controls: PreparedRequestControls | undefined;\n try {\n await this.ensureClient();\n\n const model = options.model || this.options.defaultModel;\n options = normalizeChatOptions(this.options, options, 'gemini', model);\n controls = prepareRequestControls(this.options, options);\n const requestConfig: Record<string, any> = {\n model,\n ...this.buildContentsRequest(messages, options, controls, model),\n };\n\n // Call new SDK API: ai.models.generateContent()\n const result = await this.client.models.generateContent(requestConfig);\n\n // Extract tool calls from response\n let toolCalls: AIResponse['toolCalls'];\n const firstCandidate = result.candidates?.[0];\n if (firstCandidate?.content?.parts) {\n const functionCalls = firstCandidate.content.parts.filter(\n (part: any) => part.functionCall,\n );\n if (functionCalls.length > 0) {\n toolCalls = functionCalls.map((part: any) => ({\n id: part.functionCall.id || `call_${crypto.randomUUID()}`,\n type: 'function' as const,\n function: {\n name: part.functionCall.name,\n arguments: JSON.stringify(part.functionCall.args || {}),\n },\n // Gemini 3 requires the signature back when the call is replayed.\n ...(part.thoughtSignature\n ? { thoughtSignature: part.thoughtSignature }\n : {}),\n }));\n }\n }\n\n // Clean content - remove markdown code blocks if JSON mode was requested\n let content = result.text || '';\n if (options.responseFormat?.type === 'json_object') {\n content = this.stripMarkdownCodeBlock(content);\n }\n\n const usage: TokenUsage = {\n promptTokens: result.usageMetadata?.promptTokenCount || 0,\n completionTokens: result.usageMetadata?.candidatesTokenCount || 0,\n totalTokens: result.usageMetadata?.totalTokenCount || 0,\n };\n emitUsage(\n this.options,\n 'gemini',\n 'chat',\n model!,\n usage,\n startTime,\n options.usageTags,\n );\n\n return {\n content,\n model,\n finishReason: this.mapFinishReason(result),\n usage,\n toolCalls: toolCalls && toolCalls.length > 0 ? toolCalls : undefined,\n };\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'gemini',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'gemini',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n async complete(\n prompt: string,\n options: CompletionOptions = {},\n ): Promise<AIResponse> {\n return this.chat([{ role: 'user', content: prompt }], {\n model: options.model,\n maxTokens: options.maxTokens,\n temperature: options.temperature,\n topP: options.topP,\n n: options.n,\n stop: options.stop,\n stream: options.stream,\n onProgress: options.onProgress,\n signal: options.signal,\n timeout: options.timeout,\n reasoning: options.reasoning,\n usageTags: options.usageTags,\n continueOnLength: options.continueOnLength,\n });\n }\n\n /**\n * Simple message interface for single-turn interactions with optional history\n *\n * @param text - The message text to send\n * @param options - Configuration options including history, model, etc.\n * @returns Promise resolving to the response content string\n *\n * @example\n * ```typescript\n * // Simple usage\n * const response = await provider.message('Hello!');\n *\n * // With history\n * const response = await provider.message('What was my question?', {\n * history: [\n * { role: 'user', content: 'What is 2+2?' },\n * { role: 'assistant', content: '4' }\n * ]\n * });\n * ```\n */\n async message(text: string, options: MessageOptions = {}): Promise<string> {\n // Build messages array from history + current message\n const messages: AIMessage[] = [\n ...(options.history || []),\n { role: options.role || 'user', content: text },\n ];\n\n const response = await this.chat(messages, {\n model: options.model,\n maxTokens: options.maxTokens,\n temperature: options.temperature,\n topP: options.topP,\n stop: options.stop,\n stream: options.stream,\n frequencyPenalty: options.frequencyPenalty,\n presencePenalty: options.presencePenalty,\n responseFormat: options.responseFormat,\n seed: options.seed,\n tools: options.tools,\n toolChoice: options.toolChoice,\n onProgress: options.onProgress,\n signal: options.signal,\n timeout: options.timeout,\n reasoning: options.reasoning,\n usageTags: options.usageTags,\n continueOnLength: options.continueOnLength,\n });\n\n return response.content;\n }\n\n /**\n * Generate embeddings for text using Gemini embedding models\n * @param text - Single text string or array of texts to embed\n * @param options - Optional configuration for embeddings\n * @returns Promise resolving to embeddings response\n *\n * @example\n * ```typescript\n * const embedding = await provider.embed('Hello world');\n * const embeddings = await provider.embed(['Text 1', 'Text 2']);\n * ```\n */\n async embed(\n text: string | string[],\n options: EmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n const startTime = Date.now();\n try {\n await this.ensureClient();\n\n const model = options.model || 'text-embedding-004';\n const input = Array.isArray(text) ? text : [text];\n\n const embeddings: number[][] = [];\n let totalTokens = 0;\n\n for (const content of input) {\n const config: Record<string, any> = {};\n if (options.dimensions) {\n config.outputDimensionality = options.dimensions;\n }\n\n const result = await this.client.models.embedContent({\n model,\n contents: content,\n config: Object.keys(config).length > 0 ? config : undefined,\n });\n\n if (result.embeddings?.[0]?.values) {\n embeddings.push(result.embeddings[0].values);\n }\n if (result.metadata?.tokenCount) {\n totalTokens += result.metadata.tokenCount;\n }\n }\n\n const usage: TokenUsage | undefined =\n totalTokens > 0\n ? {\n promptTokens: totalTokens,\n completionTokens: 0,\n totalTokens,\n }\n : undefined;\n emitUsage(\n this.options,\n 'gemini',\n 'embed',\n model,\n usage,\n startTime,\n options.usageTags,\n );\n\n return {\n embeddings,\n model,\n usage,\n };\n } catch (error) {\n throw this.mapError(error);\n }\n }\n\n /**\n * Decode an image input (URL, base64 data URL, or Buffer) to raw bytes.\n * Shared by the chat/vision inline-data format and the video-generation\n * `imageBytes` format, which use different wrapper shapes around the same\n * base64 payload.\n * @private\n */\n private async decodeImageInput(\n image: string | Buffer,\n signal?: AbortSignal,\n ): Promise<{ mimeType: string; base64Data: string }> {\n let mimeType = 'image/png';\n let base64Data: string;\n\n if (Buffer.isBuffer(image)) {\n base64Data = image.toString('base64');\n } else if (image.startsWith('data:')) {\n // Parse data URL\n const match = image.match(/^data:([^;]+);base64,(.+)$/);\n if (match) {\n mimeType = match[1];\n base64Data = match[2];\n } else {\n throw new AIError(\n 'Invalid base64 data URL format',\n 'INVALID_INPUT',\n 'gemini',\n );\n }\n } else {\n // Fetch from URL\n const response = await fetch(image, { signal });\n if (!response.ok) {\n throw new AIError(\n `Failed to fetch image: ${response.status} ${response.statusText}`,\n 'IMAGE_FETCH_ERROR',\n 'gemini',\n );\n }\n const arrayBuffer = await response.arrayBuffer();\n base64Data = Buffer.from(arrayBuffer).toString('base64');\n mimeType = response.headers.get('content-type') || 'image/png';\n }\n\n return { mimeType, base64Data };\n }\n\n /**\n * Convert an image to Gemini's inline-data format, used by chat/vision\n * `contents` parts (`generateContent`, `embedContent`).\n * @param image - Image as URL, base64 data URL, or Buffer\n * @returns Gemini inline data format\n * @private\n */\n private async imageToGeminiFormat(\n image: string | Buffer,\n signal?: AbortSignal,\n ): Promise<{ inlineData: { mimeType: string; data: string } }> {\n const { mimeType, base64Data } = await this.decodeImageInput(image, signal);\n return {\n inlineData: { mimeType, data: base64Data },\n };\n }\n\n /**\n * Convert a reference image to the shape `generateVideos`'s `image`\n * parameter expects: `{ imageBytes, mimeType }` (or `{ gcsUri }` for a\n * `gs://` URI in Vertex AI mode). This is a different shape than\n * {@link imageToGeminiFormat}'s `{ inlineData: {...} }` — the SDK's video\n * converters read `imageBytes`/`mimeType`/`gcsUri` directly and silently\n * drop anything else, which previously caused image-to-video requests to\n * convert to `{}` and fall back to text-to-video.\n * @private\n */\n private async imageToGeminiVideoFormat(\n image: string | Buffer,\n signal?: AbortSignal,\n ): Promise<{ imageBytes: string; mimeType: string } | { gcsUri: string }> {\n if (typeof image === 'string' && image.startsWith('gs://')) {\n return { gcsUri: image };\n }\n const { mimeType, base64Data } = await this.decodeImageInput(image, signal);\n return { imageBytes: base64Data, mimeType };\n }\n\n /**\n * Generate a text description of an image\n * @param image - Image as URL, base64 data URL, or Buffer\n * @param prompt - Custom prompt for description (optional)\n * @param options - Optional configuration\n * @returns Promise resolving to the description string\n *\n * @example\n * ```typescript\n * const description = await provider.describeImage('https://example.com/image.jpg');\n * ```\n */\n async describeImage(\n image: string | Buffer,\n prompt?: string,\n options: ImageDescriptionOptions = {},\n ): Promise<string> {\n let controls: PreparedRequestControls | undefined;\n try {\n await this.ensureClient();\n\n const defaultPrompt =\n 'Describe this image for a search index. Include objects, mood, lighting, and any visible text.';\n\n const model =\n options.model || this.options.defaultModel || 'gemini-2.5-flash';\n const normalized = normalizeChatOptions(\n this.options,\n { ...options, maxTokens: options.maxTokens ?? 500 },\n 'gemini',\n model,\n );\n controls = prepareRequestControls(this.options, normalized);\n const imageData = await this.imageToGeminiFormat(image, controls.signal);\n\n const response = await this.client.models.generateContent({\n model,\n contents: [{ text: prompt || defaultPrompt }, imageData],\n config: this.buildGenerateContentConfig(normalized, controls),\n });\n\n return response.text || '';\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'gemini',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'gemini',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n /**\n * Generate embeddings for an image using native multimodal embeddings\n * @param image - Image as URL, base64 data URL, or Buffer\n * @param options - Optional configuration for image embeddings\n * @returns Promise resolving to embeddings response\n *\n * @example\n * ```typescript\n * const embedding = await provider.embedImage('https://example.com/image.jpg');\n * ```\n */\n async embedImage(\n image: string | Buffer,\n options: ImageEmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n try {\n await this.ensureClient();\n\n // Gemini uses multimodal embedding model\n const model = options.model || 'multimodalembedding@001';\n const imageData = await this.imageToGeminiFormat(image);\n\n const config: Record<string, any> = {};\n if (options.dimensions) {\n config.outputDimensionality = options.dimensions;\n }\n\n const result = await this.client.models.embedContent({\n model,\n contents: [imageData],\n config: Object.keys(config).length > 0 ? config : undefined,\n });\n\n return {\n embeddings: result.embeddings?.[0]?.values\n ? [result.embeddings[0].values]\n : [],\n model,\n };\n } catch (error) {\n throw this.mapError(error);\n }\n }\n\n /**\n * Generate an image from a text prompt using Imagen 3\n * @param prompt - Text description of the image to generate\n * @param options - Optional configuration for image generation\n * @returns Promise resolving to generated image(s)\n *\n * @example\n * ```typescript\n * const result = await provider.generateImage('A sunset over mountains');\n * fs.writeFileSync('image.png', result.images[0].data);\n * ```\n */\n async generateImage(\n prompt: string,\n options: ImageGenerationOptions = {},\n ): Promise<ImageGenerationResponse> {\n let controls: PreparedRequestControls | undefined;\n try {\n await this.ensureClient();\n\n const model = options.model || 'imagen-3.0-generate-002';\n options = normalizeImageGenerationOptions(\n this.options,\n options,\n 'gemini',\n model,\n );\n controls = prepareRequestControls(this.options, options);\n\n const config: Record<string, any> = {\n numberOfImages: options.n,\n abortSignal: controls.signal,\n httpOptions: {\n timeout: controls.timeout,\n retryOptions: { attempts: (this.options.maxRetries || 0) + 1 },\n },\n };\n\n if (options.aspectRatio) {\n config.aspectRatio = options.aspectRatio;\n }\n\n const response = await this.client.models.generateImages({\n model,\n prompt,\n config,\n });\n\n const images = (response.generatedImages || []).map((img: any) => {\n let data: Buffer | string;\n const mimeType = 'image/png';\n const imageBytes = img.image?.imageBytes;\n\n if (options.outputFormat === 'base64') {\n data =\n typeof imageBytes === 'string'\n ? imageBytes\n : Buffer.from(imageBytes).toString('base64');\n } else if (options.outputFormat === 'url') {\n // Gemini Imagen doesn't provide URLs, return as base64 data URL\n const b64 =\n typeof imageBytes === 'string'\n ? imageBytes\n : Buffer.from(imageBytes).toString('base64');\n data = `data:${mimeType};base64,${b64}`;\n } else {\n // Default: buffer\n data =\n typeof imageBytes === 'string'\n ? Buffer.from(imageBytes, 'base64')\n : Buffer.from(imageBytes);\n }\n\n return {\n data,\n mimeType,\n };\n });\n\n return {\n images,\n model,\n };\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'gemini',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'gemini',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n // ============================================================================\n // Video Generation Methods (Veo, via long-running operations)\n // ============================================================================\n\n /**\n * Submit an asynchronous video-generation job using Veo.\n *\n * Uses the same `@google/genai` client and credentials as {@link generateImage}.\n * Returns a serializable handle immediately; the render itself runs as a\n * long-running operation that callers poll via {@link getVideoGenerationJob}.\n *\n * @param options - Prompt, reference image(s), and generation parameters\n * @returns Promise resolving to a serializable job handle\n *\n * @example\n * ```typescript\n * const job = await provider.submitVideoGenerationJob({\n * prompt: 'A neon hologram of a cat driving at top speed',\n * durationSeconds: 8,\n * });\n * ```\n */\n async submitVideoGenerationJob(\n options: VideoGenerationOptions,\n ): Promise<VideoGenerationJob> {\n const startTime = Date.now();\n let controls: PreparedRequestControls | undefined;\n try {\n await this.ensureClient();\n\n const model = options.model || DEFAULT_VEO_MODEL;\n controls = prepareRequestControls(this.options, options);\n\n let image:\n | { imageBytes: string; mimeType: string }\n | { gcsUri: string }\n | undefined;\n const firstReference = options.referenceImages?.[0];\n if (firstReference) {\n image = await this.imageToGeminiVideoFormat(\n firstReference.image,\n controls.signal,\n );\n }\n\n const config = Object.fromEntries(\n Object.entries({\n abortSignal: controls.signal,\n httpOptions: {\n timeout: controls.timeout,\n retryOptions: { attempts: (this.options.maxRetries || 0) + 1 },\n },\n numberOfVideos: 1,\n durationSeconds: options.durationSeconds,\n fps: options.fps,\n seed: options.seed,\n aspectRatio: options.aspectRatio,\n resolution: options.resolution,\n negativePrompt: options.negativePrompt,\n }).filter(([, value]) => value !== undefined),\n );\n\n const operation = await this.client.models.generateVideos({\n model,\n prompt: options.prompt,\n image,\n config,\n });\n\n if (!operation.name) {\n throw new AIError(\n 'Gemini did not return an operation name for the video-generation job',\n 'VIDEO_JOB_SUBMIT_FAILED',\n 'gemini',\n model,\n );\n }\n\n emitUsage(\n this.options,\n 'gemini',\n 'submitVideoGenerationJob',\n model,\n undefined,\n startTime,\n {\n ...(options.durationSeconds !== undefined\n ? { durationSeconds: String(options.durationSeconds) }\n : {}),\n ...(options.resolution ? { resolution: options.resolution } : {}),\n ...(options.aspectRatio ? { aspectRatio: options.aspectRatio } : {}),\n ...options.usageTags,\n },\n );\n\n return {\n jobId: operation.name,\n provider: 'gemini',\n model,\n createdAt: new Date().toISOString(),\n raw: {\n vertexai: Boolean(this.options.projectId && this.options.location),\n },\n };\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'gemini',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'gemini',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n /**\n * Build a real `GenerateVideosOperation` instance for polling, and assert\n * the handle is being resumed against a provider configured in the same\n * mode (Google AI Studio vs. Vertex AI) it was submitted in.\n * @private\n */\n private buildVideoOperation(handle: VideoGenerationJob): VideosOperation {\n if (!this.operationCtor) {\n throw new AIError(\n 'Gemini client failed to initialize the video-operation constructor. Make sure @google/genai is installed.',\n 'INITIALIZATION_ERROR',\n 'gemini',\n handle.model,\n );\n }\n this.assertResumeModeMatches(handle);\n\n const operation = new this.operationCtor();\n operation.name = handle.jobId;\n return operation;\n }\n\n /**\n * A handle submitted in Vertex AI mode cannot be resumed against a\n * provider configured for Google AI Studio (or vice versa): the SDK\n * routes `operations.getVideosOperation` based on how *this* client was\n * constructed, not how the job was submitted, so a mode mismatch would\n * otherwise surface as a confusing 404 deep in the SDK.\n * @private\n */\n private assertResumeModeMatches(handle: VideoGenerationJob): void {\n const submittedVertexAI = handle.raw?.vertexai;\n if (typeof submittedVertexAI !== 'boolean') {\n // Unknown/legacy handle shape: best effort, let the request proceed.\n return;\n }\n\n const currentVertexAI = Boolean(\n this.options.projectId && this.options.location,\n );\n if (submittedVertexAI !== currentVertexAI) {\n throw new AIError(\n `Video-generation job ${handle.jobId} was submitted in ${\n submittedVertexAI ? 'Vertex AI' : 'Google AI Studio'\n } mode, but this provider instance is configured for ${\n currentVertexAI ? 'Vertex AI' : 'Google AI Studio'\n } mode. Resume with a provider configured the same way it was submitted.`,\n 'VIDEO_JOB_MODE_MISMATCH',\n 'gemini',\n handle.model,\n );\n }\n }\n\n /**\n * Poll the status of a Veo video-generation job.\n *\n * On success, `result` carries the provider's `url` (a `files/*:download`\n * resource the caller cannot fetch directly without this provider's API\n * key) plus `mimeType`, but not `data` — call\n * {@link fetchVideoGenerationResult} to download the bytes.\n *\n * @param handle - The job handle returned by {@link submitVideoGenerationJob}\n * @returns Promise resolving to the current status, and result once succeeded\n */\n async getVideoGenerationJob(\n handle: VideoGenerationJob,\n ): Promise<VideoGenerationStatusResult> {\n try {\n await this.ensureClient();\n const operation = this.buildVideoOperation(handle);\n const updated = await this.client.operations.getVideosOperation({\n operation,\n });\n return this.mapVideoOperation(updated);\n } catch (error) {\n throw this.mapError(error);\n }\n }\n\n /**\n * Fetch the result of a completed Veo video-generation job, downloading\n * the rendered bytes with this provider's API key (the `uri` Gemini\n * returns is a `files/*:download` resource that requires the same\n * credentials this provider already holds; a bare consumer cannot fetch\n * it directly).\n *\n * @param handle - The job handle returned by {@link submitVideoGenerationJob}\n * @returns Promise resolving to the generated video's bytes and metadata\n * @throws {AIError} When the job has not succeeded yet\n */\n async fetchVideoGenerationResult(\n handle: VideoGenerationJob,\n ): Promise<VideoGenerationResult> {\n try {\n await this.ensureClient();\n const operation = this.buildVideoOperation(handle);\n const updated = await this.client.operations.getVideosOperation({\n operation,\n });\n const status = this.mapVideoOperation(updated);\n if (status.status !== 'succeeded' || !status.result) {\n throw new AIError(\n `Gemini video-generation job ${handle.jobId} has not succeeded (status: ${status.status})`,\n 'VIDEO_JOB_NOT_READY',\n 'gemini',\n handle.model,\n );\n }\n\n const video = updated.response?.generatedVideos?.[0]?.video;\n const mimeType = status.result.mimeType;\n\n if (video?.videoBytes) {\n // Already inline (e.g. Vertex AI bytesBase64Encoded) — no download needed.\n return {\n url: status.result.url,\n data: Buffer.from(video.videoBytes, 'base64'),\n mimeType,\n };\n }\n\n return {\n url: status.result.url,\n data: await this.downloadGeneratedVideo(video),\n mimeType,\n };\n } catch (error) {\n throw this.mapError(error);\n }\n }\n\n /**\n * Download a generated video's bytes via `ai.files.download`, which\n * resolves the `files/*:download` resource with this provider's API key\n * (matching Google's own documented usage pattern). The SDK's `download`\n * method only writes to a filesystem path, so this round-trips through a\n * temporary file and reads it back into memory.\n * @private\n */\n private async downloadGeneratedVideo(\n video: { uri?: string; videoBytes?: string; mimeType?: string } | undefined,\n ): Promise<Buffer> {\n if (!video?.uri) {\n throw new AIError(\n 'Gemini video-generation job succeeded with no downloadable output',\n 'VIDEO_JOB_NOT_READY',\n 'gemini',\n );\n }\n\n const dir = await mkdtemp(join(tmpdir(), 'have-ai-veo-'));\n const filePath = join(dir, 'video.mp4');\n try {\n await this.client.files.download({ file: video, downloadPath: filePath });\n return await readFile(filePath);\n } finally {\n await rm(dir, { recursive: true, force: true }).catch(() => {});\n }\n }\n\n /**\n * Cancel an in-flight Veo video-generation job.\n *\n * **The Gemini API has no cancel endpoint for video-generation\n * operations.** The generativelanguage v1beta discovery document only\n * defines `batches.cancel` (unrelated to video jobs); there is no\n * `models.operations.cancel`. This always throws — cancellation of a\n * Veo render is unsupported by the provider itself, not merely by this\n * client. Callers must treat cancellation as best-effort across all\n * video-generation providers and tolerate this failure (e.g. by simply\n * discarding the handle and not billing for further polling).\n *\n * @param handle - The job handle returned by {@link submitVideoGenerationJob}\n * @throws {AIError} Always — cancellation is unsupported by the Gemini API\n */\n async cancelVideoGenerationJob(handle: VideoGenerationJob): Promise<void> {\n if (this.options.projectId && this.options.location) {\n throw new AIError(\n 'Cancelling Gemini video-generation jobs is not implemented for Vertex AI mode by this provider (it requires OAuth credentials this provider does not manage).',\n 'NOT_IMPLEMENTED',\n 'gemini',\n handle.model,\n );\n }\n\n throw new AIError(\n 'The Gemini API has no cancel endpoint for video-generation operations (only batches.cancel exists, which does not apply to Veo jobs). ' +\n 'cancelVideoGenerationJob cannot stop an in-flight Veo render on this provider; treat cancellation as best-effort and stop polling / discard the handle instead.',\n 'VIDEO_CANCEL_UNSUPPORTED',\n 'gemini',\n handle.model,\n );\n }\n\n /**\n * Cheap auth-shaped check for Veo access: lists models with a page size\n * of 1. Callers on a hot path must cache the result themselves.\n *\n * @returns Promise resolving to true when access looks valid\n */\n async validateVideoGenerationAccess(): Promise<boolean> {\n try {\n await this.ensureClient();\n await this.client.models.list({ config: { pageSize: 1 } });\n return true;\n } catch (error) {\n throw this.mapError(error);\n }\n }\n\n private mapVideoOperation(operation: {\n done?: boolean;\n error?: Record<string, unknown>;\n response?: {\n generatedVideos?: Array<{\n video?: { uri?: string; videoBytes?: string; mimeType?: string };\n }>;\n };\n }): VideoGenerationStatusResult {\n if (!operation.done) {\n return { status: 'running' };\n }\n\n if (operation.error) {\n const errorInfo = operation.error as { code?: number; message?: unknown };\n const message =\n typeof errorInfo.message === 'string'\n ? errorInfo.message\n : JSON.stringify(operation.error);\n // google.rpc.Code.CANCELLED === 1; fall back to a message regex for\n // error shapes that don't carry a structured code.\n const cancelled = errorInfo.code === 1 || /cancel/i.test(message);\n return cancelled\n ? { status: 'cancelled' }\n : { status: 'failed', error: message };\n }\n\n const video = operation.response?.generatedVideos?.[0]?.video;\n if (!video) {\n return {\n status: 'failed',\n error:\n 'Gemini reported the video-generation job as done with no output',\n };\n }\n\n // Metadata only here — `data` requires a separate authenticated\n // download; see fetchVideoGenerationResult.\n const result: VideoGenerationResult = {\n url: video.uri,\n mimeType: video.mimeType || 'video/mp4',\n };\n\n return { status: 'succeeded', result };\n }\n\n async *stream(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): AsyncIterable<string> {\n const startTime = Date.now();\n let controls: PreparedRequestControls | undefined;\n try {\n await this.ensureClient();\n\n const model = options.model || this.options.defaultModel;\n options = normalizeChatOptions(this.options, options, 'gemini', model);\n controls = prepareRequestControls(this.options, options);\n const stream = await this.client.models.generateContentStream({\n model,\n ...this.buildContentsRequest(messages, options, controls, model),\n });\n\n let usage: TokenUsage | undefined;\n let streamFinish: AIResponse['finishReason'] = 'stop';\n\n for await (const chunk of stream) {\n if (chunk.candidates?.[0]?.finishReason === 'MAX_TOKENS') {\n streamFinish = 'length';\n }\n if (chunk.usageMetadata) {\n usage = {\n promptTokens: chunk.usageMetadata.promptTokenCount || 0,\n completionTokens: chunk.usageMetadata.candidatesTokenCount || 0,\n totalTokens: chunk.usageMetadata.totalTokenCount || 0,\n };\n }\n\n const text = chunk.text || '';\n if (!text) {\n continue;\n }\n\n if (options.onProgress) {\n options.onProgress(text);\n }\n yield text;\n }\n options.onFinishReason?.(streamFinish ?? 'stop');\n\n emitUsage(\n this.options,\n 'gemini',\n 'stream',\n model!,\n usage,\n startTime,\n options.usageTags,\n );\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'gemini',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'gemini',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n async countTokens(text: string): Promise<number> {\n try {\n await this.ensureClient();\n\n const model = this.options.defaultModel || 'gemini-2.5-flash';\n const response = await this.client.models.countTokens({\n model,\n contents: text,\n });\n\n return response.totalTokens || Math.ceil(text.length / 4);\n } catch (error) {\n throw this.mapError(error);\n }\n }\n\n async getModels(): Promise<AIModel[]> {\n // Return static list of known Gemini models\n return [\n {\n id: 'gemini-3-flash-preview',\n name: 'Gemini 3 Flash Preview',\n description:\n 'Preview of Gemini 3 Flash model. Available on Vertex AI in us-central1 only.',\n contextLength: 1000000,\n capabilities: ['text', 'chat', 'vision', 'functions'],\n supportsFunctions: true,\n supportsVision: true,\n },\n {\n id: 'gemini-2.0-flash-001',\n name: 'Gemini 2.0 Flash',\n description:\n 'Latest fast and efficient Gemini model with function calling',\n contextLength: 1000000,\n capabilities: ['text', 'chat', 'vision', 'functions'],\n supportsFunctions: true,\n supportsVision: true,\n },\n {\n id: 'gemini-2.5-flash',\n name: 'Gemini 2.5 Flash',\n description: 'Experimental next-generation Gemini model',\n contextLength: 1000000,\n capabilities: ['text', 'chat', 'vision', 'functions'],\n supportsFunctions: true,\n supportsVision: true,\n },\n {\n id: 'gemini-1.5-pro',\n name: 'Gemini 1.5 Pro (Legacy)',\n description: 'Previous generation model (may not be available)',\n contextLength: 2000000,\n capabilities: ['text', 'chat', 'vision', 'functions'],\n supportsFunctions: true,\n supportsVision: true,\n },\n ];\n }\n\n async getCapabilities(): Promise<AICapabilities> {\n return {\n chat: true,\n completion: true,\n embeddings: true,\n streaming: true,\n functions: true,\n vision: true,\n fineTuning: false,\n imageEmbeddings: true,\n imageGeneration: true,\n videoGeneration: true,\n tts: false,\n voiceCloning: false,\n voiceDesign: false,\n maxContextLength: 2000000,\n supportedOperations: [\n 'chat',\n 'completion',\n 'embedding',\n 'streaming',\n 'functions',\n 'vision',\n 'image_embedding',\n 'image_generation',\n 'video_generation',\n ],\n };\n }\n\n // ============================================================================\n // TTS Methods (Not supported - use Qwen3-TTS provider)\n // ============================================================================\n\n async synthesizeSpeech(\n _text: string,\n _options?: TTSOptions,\n ): Promise<TTSResponse> {\n throw new AIError(\n 'TTS is not supported by Gemini provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'gemini',\n );\n }\n\n streamSpeech(_text: string, _options?: TTSOptions): AsyncIterable<Buffer> {\n const error = new AIError(\n 'TTS streaming is not supported by Gemini provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'gemini',\n );\n return {\n [Symbol.asyncIterator]: () => ({\n next: () => Promise.reject(error),\n }),\n };\n }\n\n async cloneVoice(_options: VoiceCloneOptions): Promise<Voice> {\n throw new AIError(\n 'Voice cloning is not supported by Gemini provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'gemini',\n );\n }\n\n async designVoice(_options: VoiceDesignOptions): Promise<Voice> {\n throw new AIError(\n 'Voice design is not supported by Gemini provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'gemini',\n );\n }\n\n async getVoices(_options?: VoiceListOptions): Promise<Voice[]> {\n throw new AIError(\n 'Voice listing is not supported by Gemini provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'gemini',\n );\n }\n\n private mapToolChoice(\n toolChoice?:\n | 'auto'\n | 'none'\n | { type: 'function'; function: { name: string } },\n ): any {\n if (!toolChoice || toolChoice === 'auto') {\n return { functionCallingConfig: { mode: 'AUTO' } };\n }\n\n if (toolChoice === 'none') {\n return { functionCallingConfig: { mode: 'NONE' } };\n }\n\n if (typeof toolChoice === 'object' && toolChoice.type === 'function') {\n return {\n functionCallingConfig: {\n mode: 'ANY',\n allowedFunctionNames: [toolChoice.function.name],\n },\n };\n }\n\n return { functionCallingConfig: { mode: 'AUTO' } };\n }\n\n private buildGenerateContentConfig(\n options: ChatOptions,\n controls: PreparedRequestControls,\n ): Record<string, any> {\n const config: Record<string, any> = {\n abortSignal: controls.signal,\n httpOptions: {\n timeout: controls.timeout,\n retryOptions: { attempts: (this.options.maxRetries || 0) + 1 },\n },\n maxOutputTokens: options.maxTokens,\n temperature: options.temperature,\n topP: options.topP,\n stopSequences: Array.isArray(options.stop)\n ? options.stop\n : options.stop\n ? [options.stop]\n : undefined,\n responseMimeType:\n options.responseFormat?.type === 'json_object'\n ? 'application/json'\n : undefined,\n frequencyPenalty: options.frequencyPenalty,\n presencePenalty: options.presencePenalty,\n seed: options.seed,\n };\n\n if (options.tools && options.tools.length > 0) {\n config.tools = [\n {\n functionDeclarations: options.tools.map((tool) => ({\n name: tool.function.name,\n description: tool.function.description || '',\n parameters: tool.function.parameters || { type: 'object' },\n })),\n },\n ];\n config.toolConfig = this.mapToolChoice(options.toolChoice);\n }\n\n const reasoning = options.reasoning;\n if (reasoning?.maxTokens !== undefined && reasoning.maxTokens > 0) {\n config.thinkingConfig = {\n thinkingBudget: reasoning.maxTokens,\n includeThoughts: reasoning.includeThoughts,\n };\n }\n\n return Object.fromEntries(\n Object.entries(config).filter(([, value]) => value !== undefined),\n );\n }\n\n private mapFinishReason(response: any): AIResponse['finishReason'] {\n // Check if response has function calls in any candidate\n const firstCandidate = response.candidates?.[0];\n if (firstCandidate?.content?.parts) {\n const hasFunctionCall = firstCandidate.content.parts.some(\n (part: any) => part.functionCall,\n );\n if (hasFunctionCall) {\n return 'tool_calls';\n }\n }\n\n if (firstCandidate?.finishReason === 'MAX_TOKENS') {\n return 'length';\n }\n\n return 'stop';\n }\n\n /**\n * Builds the `contents` + `config` pair for generateContent.\n *\n * Plain conversations keep the flattened text prompt. Conversations with\n * tool traffic need structured turns so Gemini can pair each\n * `functionResponse` with the `functionCall` that requested it.\n */\n private buildContentsRequest(\n messages: AIMessage[],\n options: ChatOptions,\n controls: PreparedRequestControls,\n model?: string,\n ): { contents: string | GeminiContent[]; config: Record<string, any> } {\n const config = this.buildGenerateContentConfig(options, controls);\n if (!hasToolTraffic(messages)) {\n return { contents: this.messagesToGeminiFormat(messages), config };\n }\n\n const { systemInstruction, contents } = this.messagesToGeminiContents(\n messages,\n model,\n );\n if (systemInstruction) {\n config.systemInstruction = systemInstruction;\n }\n return { contents, config };\n }\n\n /**\n * Maps a tool-calling conversation to structured Gemini turns.\n *\n * Assistant `tool_calls` become `functionCall` parts (replaying any\n * recorded thought signature); `role: 'tool'` results become\n * `functionResponse` parts named after the call their `tool_call_id`\n * answers. Consecutive results share one user turn.\n *\n * Only answered calls are replayed: a `functionCall` without a matching\n * `functionResponse` is rejected. A call counts as answered when a result\n * carries its id, or (legacy results without `tool_call_id`) its name.\n *\n * Gemini 3 strictly validates the thought signature on the first\n * `functionCall` of each model step and returns 400 when it is missing.\n * Consumers should persist `AIToolCall.thoughtSignature` with their\n * history; when a Gemini 3 step has none (history from another model or\n * a store that dropped it), the first call gets Google's documented\n * placeholder signature, which skips validation at some quality cost.\n */\n private messagesToGeminiContents(\n messages: AIMessage[],\n model?: string,\n ): {\n systemInstruction?: string;\n contents: GeminiContent[];\n } {\n const toolCallNames = indexToolCallNames(messages);\n const answeredIds = new Set<string>();\n const answeredLegacyNames = new Set<string>();\n for (const message of messages) {\n if (message.role !== 'tool' && message.role !== 'function') continue;\n if (message.tool_call_id) answeredIds.add(message.tool_call_id);\n else if (message.name) answeredLegacyNames.add(message.name);\n }\n const placeholderSignature =\n model && isGemini3Model(model)\n ? this.options.projectId && this.options.location\n ? VERTEX_PLACEHOLDER_THOUGHT_SIGNATURE\n : GEMINI_API_PLACEHOLDER_THOUGHT_SIGNATURE\n : undefined;\n const contents: GeminiContent[] = [];\n let systemInstruction: string | undefined;\n\n for (const message of messages) {\n const textContent = extractTextContent(message.content);\n\n if (message.role === 'system') {\n systemInstruction = systemInstruction\n ? `${systemInstruction}\\n\\n${textContent}`\n : textContent;\n continue;\n }\n\n if (message.role === 'tool' || message.role === 'function') {\n const name = resolveToolResultName(message, toolCallNames);\n const part: GeminiPart = name\n ? {\n functionResponse: {\n name,\n response: toolResultObject(textContent),\n },\n }\n : { text: textContent };\n const previous = contents[contents.length - 1];\n if (\n name &&\n previous?.role === 'user' &&\n previous.parts.every((existing) => existing.functionResponse)\n ) {\n previous.parts.push(part);\n } else {\n contents.push({ role: 'user', parts: [part] });\n }\n continue;\n }\n\n const parts: GeminiPart[] = textContent ? [{ text: textContent }] : [];\n if (message.role === 'assistant') {\n const answered = (message.tool_calls || []).filter(\n (toolCall) =>\n answeredIds.has(toolCall.id) ||\n answeredLegacyNames.has(toolCall.function.name),\n );\n const signed = answered.some((toolCall) => toolCall.thoughtSignature);\n answered.forEach((toolCall, index) => {\n const thoughtSignature =\n toolCall.thoughtSignature ||\n (index === 0 && !signed ? placeholderSignature : undefined);\n parts.push({\n functionCall: {\n name: toolCall.function.name,\n args: parseToolArguments(toolCall.function.arguments),\n },\n ...(thoughtSignature ? { thoughtSignature } : {}),\n });\n });\n }\n if (parts.length === 0) continue;\n\n contents.push({\n role: message.role === 'assistant' ? 'model' : 'user',\n parts,\n });\n }\n\n return { systemInstruction, contents };\n }\n\n private messagesToGeminiFormat(messages: AIMessage[]): string {\n // Convert messages to a simple text prompt\n // The new SDK expects a string for the contents field\n return messages\n .map((message) => {\n const textContent = extractTextContent(message.content);\n switch (message.role) {\n case 'system':\n return `Instructions: ${textContent}`;\n case 'user':\n return `Human: ${textContent}`;\n case 'assistant':\n return `Assistant: ${textContent}`;\n default:\n return textContent;\n }\n })\n .join('\\n\\n');\n }\n\n private stripMarkdownCodeBlock(text: string): string {\n // Remove markdown code blocks like ```json\\n...\\n```\n const codeBlockRegex =\n /^```(?:json|javascript|typescript)?\\s*\\n?([\\s\\S]*?)\\n?```\\s*$/;\n const match = text.match(codeBlockRegex);\n return match ? match[1].trim() : text.trim();\n }\n\n private mapError(error: unknown): AIError {\n if (error instanceof AIError) {\n return error;\n }\n\n // Map common Gemini error patterns\n const message =\n error instanceof Error ? error.message : 'Unknown Gemini error occurred';\n\n if (message.includes('API_KEY_INVALID') || message.includes('401')) {\n return new AuthenticationError('gemini');\n }\n\n if (message.includes('QUOTA_EXCEEDED') || message.includes('429')) {\n return rateLimitErrorFrom('gemini', error);\n }\n\n if (message.includes('MODEL_NOT_FOUND') || message.includes('404')) {\n return new ModelNotFoundError(message, 'gemini');\n }\n\n return new AIError(message, 'UNKNOWN_ERROR', 'gemini');\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"gemini-DCo6d-n1.js","names":[],"sources":["../../src/shared/providers/gemini.ts"],"sourcesContent":["/**\n * Google Gemini provider implementation\n */\n\nimport crypto from 'node:crypto';\nimport { mkdtemp, readFile, rm } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { rateLimitErrorFrom } from '../rate-limit';\nimport {\n normalizeBaseAIOptions,\n normalizeChatOptions,\n normalizeImageGenerationOptions,\n type PreparedRequestControls,\n prepareRequestControls,\n} from '../safety';\nimport {\n hasToolTraffic,\n indexToolCallNames,\n parseToolArguments,\n resolveToolResultName,\n toolResultObject,\n} from '../tool-messages';\nimport type {\n AICapabilities,\n AIInterface,\n AIMessage,\n AIModel,\n AIResponse,\n ChatOptions,\n CompletionOptions,\n EmbeddingOptions,\n EmbeddingResponse,\n GeminiOptions,\n ImageDescriptionOptions,\n ImageEmbeddingOptions,\n ImageGenerationOptions,\n ImageGenerationResponse,\n MessageOptions,\n TokenUsage,\n TTSOptions,\n TTSResponse,\n VideoGenerationJob,\n VideoGenerationOptions,\n VideoGenerationResult,\n VideoGenerationStatusResult,\n Voice,\n VoiceCloneOptions,\n VoiceDesignOptions,\n VoiceListOptions,\n} from '../types';\nimport {\n AIError,\n AuthenticationError,\n extractTextContent,\n ModelNotFoundError,\n} from '../types';\nimport { emitUsage } from './usage';\n\n// Note: This implementation uses the new @google/genai package\n// @google/generative-ai is deprecated - migrated to @google/genai\n\ninterface GeminiPart {\n text?: string;\n functionCall?: { name: string; args: Record<string, unknown> };\n functionResponse?: { name: string; response: Record<string, unknown> };\n thoughtSignature?: string;\n}\n\ninterface GeminiContent {\n role: 'user' | 'model';\n parts: GeminiPart[];\n}\n\n/**\n * Default Veo model for video generation. Veo 2 / Veo 3.0 are deprecated in\n * favor of Veo 3.1 (still \"preview\" in its model id, but the current\n * non-deprecated generation per Google's docs as of this writing). Veo 3.1\n * supports the `resolution` config field this provider forwards; Veo 2 does\n * not, so callers pinning back to Veo 2 should omit `resolution`.\n */\nconst DEFAULT_VEO_MODEL = 'veo-3.1-generate-preview';\n\n/**\n * Placeholder thought signatures Google documents for Gemini 3\n * `functionCall` parts that have no real signature (history transferred from\n * another model, or injected calls). They bypass strict signature validation\n * and degrade reasoning quality, so real signatures are always preferred.\n *\n * - Gemini API: https://ai.google.dev/gemini-api/docs/generate-content/gemini-3\n * (\"Migrating from other models\")\n * - Vertex AI: https://docs.cloud.google.com/vertex-ai/generative-ai/docs/thought-signatures\n */\nconst GEMINI_API_PLACEHOLDER_THOUGHT_SIGNATURE =\n 'context_engineering_is_the_way_to_go';\nconst VERTEX_PLACEHOLDER_THOUGHT_SIGNATURE = 'skip_thought_signature_validator';\n\n/** Gemini 3 model ids (for example `gemini-3-flash-preview`). */\nfunction isGemini3Model(model: string): boolean {\n return /(^|\\/)gemini-3([.-]|$)/.test(model);\n}\n\n/**\n * Type-only reference to the real `GenerateVideosOperation` class. The\n * `@google/genai` SDK's `operations.getVideosOperation` calls\n * `operation._fromAPIResponse(...)`, an instance method — passing a plain\n * `{ name }` object literal throws at runtime. Typing the constructed\n * operation against this type (rather than `any`) makes tsc reject a\n * regression back to a plain literal, since `_fromAPIResponse` is a\n * required member of the real class's public shape.\n */\ntype VideosOperation = import('@google/genai').GenerateVideosOperation;\n\nexport class GeminiProvider implements AIInterface {\n private options: GeminiOptions;\n private client: any; // GoogleGenAI instance from @google/genai\n private operationCtor?: new () => VideosOperation;\n\n constructor(options: GeminiOptions) {\n this.options = normalizeBaseAIOptions({\n defaultModel: 'gemini-2.5-flash',\n ...options,\n });\n\n // Initialize Google Generative AI client\n this.initializeClientSync();\n }\n\n private initializeClientSync() {\n try {\n // Dynamic import in constructor - this will work if the package is installed\n import('@google/genai')\n .then(({ GoogleGenAI, GenerateVideosOperation }) => {\n this.client = new GoogleGenAI(this.buildClientConfig());\n this.operationCtor = GenerateVideosOperation;\n })\n .catch(() => {\n // Client will be null and we'll handle it in methods\n });\n } catch (_error) {\n // Client will be null and we'll handle it in methods\n }\n }\n\n private async ensureClient() {\n if (!this.client) {\n try {\n const { GoogleGenAI, GenerateVideosOperation } = await import(\n '@google/genai'\n );\n this.client = new GoogleGenAI(this.buildClientConfig());\n this.operationCtor = GenerateVideosOperation;\n } catch (_error) {\n throw new AIError(\n 'Failed to initialize Gemini client. Make sure @google/genai is installed.',\n 'INITIALIZATION_ERROR',\n 'gemini',\n );\n }\n }\n }\n\n /**\n * Build the GoogleGenAI client configuration based on provided options.\n * Supports both Google AI Studio (apiKey only) and Vertex AI (projectId + location).\n */\n private buildClientConfig(): Record<string, any> {\n // If projectId and location are provided, use Vertex AI mode\n if (this.options.projectId && this.options.location) {\n return {\n vertexai: true,\n project: this.options.projectId,\n location: this.options.location,\n apiKey: this.options.apiKey, // Optional for Vertex AI with ADC\n httpOptions: {\n timeout: this.options.timeout,\n retryOptions: { attempts: (this.options.maxRetries || 0) + 1 },\n },\n };\n }\n\n // Default to Google AI Studio mode with API key\n return {\n apiKey: this.options.apiKey,\n httpOptions: {\n timeout: this.options.timeout,\n retryOptions: { attempts: (this.options.maxRetries || 0) + 1 },\n },\n };\n }\n\n async chat(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): Promise<AIResponse> {\n const startTime = Date.now();\n let controls: PreparedRequestControls | undefined;\n try {\n await this.ensureClient();\n\n const model = options.model || this.options.defaultModel;\n options = normalizeChatOptions(this.options, options, 'gemini', model);\n controls = prepareRequestControls(this.options, options);\n const requestConfig: Record<string, any> = {\n model,\n ...this.buildContentsRequest(messages, options, controls, model),\n };\n\n // Call new SDK API: ai.models.generateContent()\n const result = await this.client.models.generateContent(requestConfig);\n\n // Extract tool calls from response\n let toolCalls: AIResponse['toolCalls'];\n const firstCandidate = result.candidates?.[0];\n if (firstCandidate?.content?.parts) {\n const functionCalls = firstCandidate.content.parts.filter(\n (part: any) => part.functionCall,\n );\n if (functionCalls.length > 0) {\n toolCalls = functionCalls.map((part: any) => ({\n id: part.functionCall.id || `call_${crypto.randomUUID()}`,\n type: 'function' as const,\n function: {\n name: part.functionCall.name,\n arguments: JSON.stringify(part.functionCall.args || {}),\n },\n // Gemini 3 requires the signature back when the call is replayed.\n ...(part.thoughtSignature\n ? { thoughtSignature: part.thoughtSignature }\n : {}),\n }));\n }\n }\n\n // Clean content - remove markdown code blocks if JSON mode was requested\n let content = result.text || '';\n if (options.responseFormat?.type === 'json_object') {\n content = this.stripMarkdownCodeBlock(content);\n }\n\n const usage: TokenUsage = {\n promptTokens: result.usageMetadata?.promptTokenCount || 0,\n completionTokens: result.usageMetadata?.candidatesTokenCount || 0,\n totalTokens: result.usageMetadata?.totalTokenCount || 0,\n };\n emitUsage(\n this.options,\n 'gemini',\n 'chat',\n model!,\n usage,\n startTime,\n options.usageTags,\n );\n\n return {\n content,\n model,\n finishReason: this.mapFinishReason(result),\n usage,\n toolCalls: toolCalls && toolCalls.length > 0 ? toolCalls : undefined,\n };\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'gemini',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'gemini',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n async complete(\n prompt: string,\n options: CompletionOptions = {},\n ): Promise<AIResponse> {\n return this.chat([{ role: 'user', content: prompt }], {\n model: options.model,\n maxTokens: options.maxTokens,\n temperature: options.temperature,\n topP: options.topP,\n n: options.n,\n stop: options.stop,\n stream: options.stream,\n onProgress: options.onProgress,\n signal: options.signal,\n timeout: options.timeout,\n reasoning: options.reasoning,\n usageTags: options.usageTags,\n continueOnLength: options.continueOnLength,\n });\n }\n\n /**\n * Simple message interface for single-turn interactions with optional history\n *\n * @param text - The message text to send\n * @param options - Configuration options including history, model, etc.\n * @returns Promise resolving to the response content string\n *\n * @example\n * ```typescript\n * // Simple usage\n * const response = await provider.message('Hello!');\n *\n * // With history\n * const response = await provider.message('What was my question?', {\n * history: [\n * { role: 'user', content: 'What is 2+2?' },\n * { role: 'assistant', content: '4' }\n * ]\n * });\n * ```\n */\n async message(text: string, options: MessageOptions = {}): Promise<string> {\n // Build messages array from history + current message\n const messages: AIMessage[] = [\n ...(options.history || []),\n { role: options.role || 'user', content: text },\n ];\n\n const response = await this.chat(messages, {\n model: options.model,\n maxTokens: options.maxTokens,\n temperature: options.temperature,\n topP: options.topP,\n stop: options.stop,\n stream: options.stream,\n frequencyPenalty: options.frequencyPenalty,\n presencePenalty: options.presencePenalty,\n responseFormat: options.responseFormat,\n seed: options.seed,\n tools: options.tools,\n toolChoice: options.toolChoice,\n onProgress: options.onProgress,\n signal: options.signal,\n timeout: options.timeout,\n reasoning: options.reasoning,\n usageTags: options.usageTags,\n continueOnLength: options.continueOnLength,\n });\n\n return response.content;\n }\n\n /**\n * Generate embeddings for text using Gemini embedding models\n * @param text - Single text string or array of texts to embed\n * @param options - Optional configuration for embeddings\n * @returns Promise resolving to embeddings response\n *\n * @example\n * ```typescript\n * const embedding = await provider.embed('Hello world');\n * const embeddings = await provider.embed(['Text 1', 'Text 2']);\n * ```\n */\n async embed(\n text: string | string[],\n options: EmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n const startTime = Date.now();\n try {\n await this.ensureClient();\n\n const model = options.model || 'text-embedding-004';\n const input = Array.isArray(text) ? text : [text];\n\n const embeddings: number[][] = [];\n let totalTokens = 0;\n\n for (const content of input) {\n const config: Record<string, any> = {};\n if (options.dimensions) {\n config.outputDimensionality = options.dimensions;\n }\n\n const result = await this.client.models.embedContent({\n model,\n contents: content,\n config: Object.keys(config).length > 0 ? config : undefined,\n });\n\n if (result.embeddings?.[0]?.values) {\n embeddings.push(result.embeddings[0].values);\n }\n if (result.metadata?.tokenCount) {\n totalTokens += result.metadata.tokenCount;\n }\n }\n\n const usage: TokenUsage | undefined =\n totalTokens > 0\n ? {\n promptTokens: totalTokens,\n completionTokens: 0,\n totalTokens,\n }\n : undefined;\n emitUsage(\n this.options,\n 'gemini',\n 'embed',\n model,\n usage,\n startTime,\n options.usageTags,\n );\n\n return {\n embeddings,\n model,\n usage,\n };\n } catch (error) {\n throw this.mapError(error);\n }\n }\n\n /**\n * Decode an image input (URL, base64 data URL, or Buffer) to raw bytes.\n * Shared by the chat/vision inline-data format and the video-generation\n * `imageBytes` format, which use different wrapper shapes around the same\n * base64 payload.\n * @private\n */\n private async decodeImageInput(\n image: string | Buffer,\n signal?: AbortSignal,\n ): Promise<{ mimeType: string; base64Data: string }> {\n let mimeType = 'image/png';\n let base64Data: string;\n\n if (Buffer.isBuffer(image)) {\n base64Data = image.toString('base64');\n } else if (image.startsWith('data:')) {\n // Parse data URL\n const match = image.match(/^data:([^;]+);base64,(.+)$/);\n if (match) {\n mimeType = match[1];\n base64Data = match[2];\n } else {\n throw new AIError(\n 'Invalid base64 data URL format',\n 'INVALID_INPUT',\n 'gemini',\n );\n }\n } else {\n // Fetch from URL\n const response = await fetch(image, { signal });\n if (!response.ok) {\n throw new AIError(\n `Failed to fetch image: ${response.status} ${response.statusText}`,\n 'IMAGE_FETCH_ERROR',\n 'gemini',\n );\n }\n const arrayBuffer = await response.arrayBuffer();\n base64Data = Buffer.from(arrayBuffer).toString('base64');\n mimeType = response.headers.get('content-type') || 'image/png';\n }\n\n return { mimeType, base64Data };\n }\n\n /**\n * Convert an image to Gemini's inline-data format, used by chat/vision\n * `contents` parts (`generateContent`, `embedContent`).\n * @param image - Image as URL, base64 data URL, or Buffer\n * @returns Gemini inline data format\n * @private\n */\n private async imageToGeminiFormat(\n image: string | Buffer,\n signal?: AbortSignal,\n ): Promise<{ inlineData: { mimeType: string; data: string } }> {\n const { mimeType, base64Data } = await this.decodeImageInput(image, signal);\n return {\n inlineData: { mimeType, data: base64Data },\n };\n }\n\n /**\n * Convert a reference image to the shape `generateVideos`'s `image`\n * parameter expects: `{ imageBytes, mimeType }` (or `{ gcsUri }` for a\n * `gs://` URI in Vertex AI mode). This is a different shape than\n * {@link imageToGeminiFormat}'s `{ inlineData: {...} }` — the SDK's video\n * converters read `imageBytes`/`mimeType`/`gcsUri` directly and silently\n * drop anything else, which previously caused image-to-video requests to\n * convert to `{}` and fall back to text-to-video.\n * @private\n */\n private async imageToGeminiVideoFormat(\n image: string | Buffer,\n signal?: AbortSignal,\n ): Promise<{ imageBytes: string; mimeType: string } | { gcsUri: string }> {\n if (typeof image === 'string' && image.startsWith('gs://')) {\n return { gcsUri: image };\n }\n const { mimeType, base64Data } = await this.decodeImageInput(image, signal);\n return { imageBytes: base64Data, mimeType };\n }\n\n /**\n * Generate a text description of an image\n * @param image - Image as URL, base64 data URL, or Buffer\n * @param prompt - Custom prompt for description (optional)\n * @param options - Optional configuration\n * @returns Promise resolving to the description string\n *\n * @example\n * ```typescript\n * const description = await provider.describeImage('https://example.com/image.jpg');\n * ```\n */\n async describeImage(\n image: string | Buffer,\n prompt?: string,\n options: ImageDescriptionOptions = {},\n ): Promise<string> {\n let controls: PreparedRequestControls | undefined;\n try {\n await this.ensureClient();\n\n const defaultPrompt =\n 'Describe this image for a search index. Include objects, mood, lighting, and any visible text.';\n\n const model =\n options.model || this.options.defaultModel || 'gemini-2.5-flash';\n const normalized = normalizeChatOptions(\n this.options,\n { ...options, maxTokens: options.maxTokens ?? 500 },\n 'gemini',\n model,\n );\n controls = prepareRequestControls(this.options, normalized);\n const imageData = await this.imageToGeminiFormat(image, controls.signal);\n\n const response = await this.client.models.generateContent({\n model,\n contents: [{ text: prompt || defaultPrompt }, imageData],\n config: this.buildGenerateContentConfig(normalized, controls),\n });\n\n return response.text || '';\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'gemini',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'gemini',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n /**\n * Generate embeddings for an image using native multimodal embeddings\n * @param image - Image as URL, base64 data URL, or Buffer\n * @param options - Optional configuration for image embeddings\n * @returns Promise resolving to embeddings response\n *\n * @example\n * ```typescript\n * const embedding = await provider.embedImage('https://example.com/image.jpg');\n * ```\n */\n async embedImage(\n image: string | Buffer,\n options: ImageEmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n try {\n await this.ensureClient();\n\n // Gemini uses multimodal embedding model\n const model = options.model || 'multimodalembedding@001';\n const imageData = await this.imageToGeminiFormat(image);\n\n const config: Record<string, any> = {};\n if (options.dimensions) {\n config.outputDimensionality = options.dimensions;\n }\n\n const result = await this.client.models.embedContent({\n model,\n contents: [imageData],\n config: Object.keys(config).length > 0 ? config : undefined,\n });\n\n return {\n embeddings: result.embeddings?.[0]?.values\n ? [result.embeddings[0].values]\n : [],\n model,\n };\n } catch (error) {\n throw this.mapError(error);\n }\n }\n\n /**\n * Generate an image from a text prompt using Imagen 3\n * @param prompt - Text description of the image to generate\n * @param options - Optional configuration for image generation\n * @returns Promise resolving to generated image(s)\n *\n * @example\n * ```typescript\n * const result = await provider.generateImage('A sunset over mountains');\n * fs.writeFileSync('image.png', result.images[0].data);\n * ```\n */\n async generateImage(\n prompt: string,\n options: ImageGenerationOptions = {},\n ): Promise<ImageGenerationResponse> {\n let controls: PreparedRequestControls | undefined;\n try {\n await this.ensureClient();\n\n const model = options.model || 'imagen-3.0-generate-002';\n options = normalizeImageGenerationOptions(\n this.options,\n options,\n 'gemini',\n model,\n );\n controls = prepareRequestControls(this.options, options);\n\n const config: Record<string, any> = {\n numberOfImages: options.n,\n abortSignal: controls.signal,\n httpOptions: {\n timeout: controls.timeout,\n retryOptions: { attempts: (this.options.maxRetries || 0) + 1 },\n },\n };\n\n if (options.aspectRatio) {\n config.aspectRatio = options.aspectRatio;\n }\n\n const response = await this.client.models.generateImages({\n model,\n prompt,\n config,\n });\n\n const images = (response.generatedImages || []).map((img: any) => {\n let data: Buffer | string;\n const mimeType = 'image/png';\n const imageBytes = img.image?.imageBytes;\n\n if (options.outputFormat === 'base64') {\n data =\n typeof imageBytes === 'string'\n ? imageBytes\n : Buffer.from(imageBytes).toString('base64');\n } else if (options.outputFormat === 'url') {\n // Gemini Imagen doesn't provide URLs, return as base64 data URL\n const b64 =\n typeof imageBytes === 'string'\n ? imageBytes\n : Buffer.from(imageBytes).toString('base64');\n data = `data:${mimeType};base64,${b64}`;\n } else {\n // Default: buffer\n data =\n typeof imageBytes === 'string'\n ? Buffer.from(imageBytes, 'base64')\n : Buffer.from(imageBytes);\n }\n\n return {\n data,\n mimeType,\n };\n });\n\n return {\n images,\n model,\n };\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'gemini',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'gemini',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n // ============================================================================\n // Video Generation Methods (Veo, via long-running operations)\n // ============================================================================\n\n /**\n * Submit an asynchronous video-generation job using Veo.\n *\n * Uses the same `@google/genai` client and credentials as {@link generateImage}.\n * Returns a serializable handle immediately; the render itself runs as a\n * long-running operation that callers poll via {@link getVideoGenerationJob}.\n *\n * @param options - Prompt, reference image(s), and generation parameters\n * @returns Promise resolving to a serializable job handle\n *\n * @example\n * ```typescript\n * const job = await provider.submitVideoGenerationJob({\n * prompt: 'A neon hologram of a cat driving at top speed',\n * durationSeconds: 8,\n * });\n * ```\n */\n async submitVideoGenerationJob(\n options: VideoGenerationOptions,\n ): Promise<VideoGenerationJob> {\n const startTime = Date.now();\n let controls: PreparedRequestControls | undefined;\n try {\n await this.ensureClient();\n\n const model = options.model || DEFAULT_VEO_MODEL;\n controls = prepareRequestControls(this.options, options);\n\n let image:\n | { imageBytes: string; mimeType: string }\n | { gcsUri: string }\n | undefined;\n const firstReference = options.referenceImages?.[0];\n if (firstReference) {\n image = await this.imageToGeminiVideoFormat(\n firstReference.image,\n controls.signal,\n );\n }\n\n const config = Object.fromEntries(\n Object.entries({\n abortSignal: controls.signal,\n httpOptions: {\n timeout: controls.timeout,\n retryOptions: { attempts: (this.options.maxRetries || 0) + 1 },\n },\n numberOfVideos: 1,\n durationSeconds: options.durationSeconds,\n fps: options.fps,\n seed: options.seed,\n aspectRatio: options.aspectRatio,\n resolution: options.resolution,\n negativePrompt: options.negativePrompt,\n }).filter(([, value]) => value !== undefined),\n );\n\n const operation = await this.client.models.generateVideos({\n model,\n prompt: options.prompt,\n image,\n config,\n });\n\n if (!operation.name) {\n throw new AIError(\n 'Gemini did not return an operation name for the video-generation job',\n 'VIDEO_JOB_SUBMIT_FAILED',\n 'gemini',\n model,\n );\n }\n\n emitUsage(\n this.options,\n 'gemini',\n 'submitVideoGenerationJob',\n model,\n undefined,\n startTime,\n {\n ...(options.durationSeconds !== undefined\n ? { durationSeconds: String(options.durationSeconds) }\n : {}),\n ...(options.resolution ? { resolution: options.resolution } : {}),\n ...(options.aspectRatio ? { aspectRatio: options.aspectRatio } : {}),\n ...options.usageTags,\n },\n );\n\n return {\n jobId: operation.name,\n provider: 'gemini',\n model,\n createdAt: new Date().toISOString(),\n raw: {\n vertexai: Boolean(this.options.projectId && this.options.location),\n },\n };\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'gemini',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'gemini',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n /**\n * Build a real `GenerateVideosOperation` instance for polling, and assert\n * the handle is being resumed against a provider configured in the same\n * mode (Google AI Studio vs. Vertex AI) it was submitted in.\n * @private\n */\n private buildVideoOperation(handle: VideoGenerationJob): VideosOperation {\n if (!this.operationCtor) {\n throw new AIError(\n 'Gemini client failed to initialize the video-operation constructor. Make sure @google/genai is installed.',\n 'INITIALIZATION_ERROR',\n 'gemini',\n handle.model,\n );\n }\n this.assertResumeModeMatches(handle);\n\n const operation = new this.operationCtor();\n operation.name = handle.jobId;\n return operation;\n }\n\n /**\n * A handle submitted in Vertex AI mode cannot be resumed against a\n * provider configured for Google AI Studio (or vice versa): the SDK\n * routes `operations.getVideosOperation` based on how *this* client was\n * constructed, not how the job was submitted, so a mode mismatch would\n * otherwise surface as a confusing 404 deep in the SDK.\n * @private\n */\n private assertResumeModeMatches(handle: VideoGenerationJob): void {\n const submittedVertexAI = handle.raw?.vertexai;\n if (typeof submittedVertexAI !== 'boolean') {\n // Unknown/legacy handle shape: best effort, let the request proceed.\n return;\n }\n\n const currentVertexAI = Boolean(\n this.options.projectId && this.options.location,\n );\n if (submittedVertexAI !== currentVertexAI) {\n throw new AIError(\n `Video-generation job ${handle.jobId} was submitted in ${\n submittedVertexAI ? 'Vertex AI' : 'Google AI Studio'\n } mode, but this provider instance is configured for ${\n currentVertexAI ? 'Vertex AI' : 'Google AI Studio'\n } mode. Resume with a provider configured the same way it was submitted.`,\n 'VIDEO_JOB_MODE_MISMATCH',\n 'gemini',\n handle.model,\n );\n }\n }\n\n /**\n * Poll the status of a Veo video-generation job.\n *\n * On success, `result` carries the provider's `url` (a `files/*:download`\n * resource the caller cannot fetch directly without this provider's API\n * key) plus `mimeType`, but not `data` — call\n * {@link fetchVideoGenerationResult} to download the bytes.\n *\n * @param handle - The job handle returned by {@link submitVideoGenerationJob}\n * @returns Promise resolving to the current status, and result once succeeded\n */\n async getVideoGenerationJob(\n handle: VideoGenerationJob,\n ): Promise<VideoGenerationStatusResult> {\n try {\n await this.ensureClient();\n const operation = this.buildVideoOperation(handle);\n const updated = await this.client.operations.getVideosOperation({\n operation,\n });\n return this.mapVideoOperation(updated);\n } catch (error) {\n throw this.mapError(error);\n }\n }\n\n /**\n * Fetch the result of a completed Veo video-generation job, downloading\n * the rendered bytes with this provider's API key (the `uri` Gemini\n * returns is a `files/*:download` resource that requires the same\n * credentials this provider already holds; a bare consumer cannot fetch\n * it directly).\n *\n * @param handle - The job handle returned by {@link submitVideoGenerationJob}\n * @returns Promise resolving to the generated video's bytes and metadata\n * @throws {AIError} When the job has not succeeded yet\n */\n async fetchVideoGenerationResult(\n handle: VideoGenerationJob,\n ): Promise<VideoGenerationResult> {\n try {\n await this.ensureClient();\n const operation = this.buildVideoOperation(handle);\n const updated = await this.client.operations.getVideosOperation({\n operation,\n });\n const status = this.mapVideoOperation(updated);\n if (status.status !== 'succeeded' || !status.result) {\n throw new AIError(\n `Gemini video-generation job ${handle.jobId} has not succeeded (status: ${status.status})`,\n 'VIDEO_JOB_NOT_READY',\n 'gemini',\n handle.model,\n );\n }\n\n const video = updated.response?.generatedVideos?.[0]?.video;\n const mimeType = status.result.mimeType;\n\n if (video?.videoBytes) {\n // Already inline (e.g. Vertex AI bytesBase64Encoded) — no download needed.\n return {\n url: status.result.url,\n data: Buffer.from(video.videoBytes, 'base64'),\n mimeType,\n };\n }\n\n return {\n url: status.result.url,\n data: await this.downloadGeneratedVideo(video),\n mimeType,\n };\n } catch (error) {\n throw this.mapError(error);\n }\n }\n\n /**\n * Download a generated video's bytes via `ai.files.download`, which\n * resolves the `files/*:download` resource with this provider's API key\n * (matching Google's own documented usage pattern). The SDK's `download`\n * method only writes to a filesystem path, so this round-trips through a\n * temporary file and reads it back into memory.\n * @private\n */\n private async downloadGeneratedVideo(\n video: { uri?: string; videoBytes?: string; mimeType?: string } | undefined,\n ): Promise<Buffer> {\n if (!video?.uri) {\n throw new AIError(\n 'Gemini video-generation job succeeded with no downloadable output',\n 'VIDEO_JOB_NOT_READY',\n 'gemini',\n );\n }\n\n const dir = await mkdtemp(join(tmpdir(), 'have-ai-veo-'));\n const filePath = join(dir, 'video.mp4');\n try {\n await this.client.files.download({ file: video, downloadPath: filePath });\n return await readFile(filePath);\n } finally {\n await rm(dir, { recursive: true, force: true }).catch(() => {});\n }\n }\n\n /**\n * Cancel an in-flight Veo video-generation job.\n *\n * **The Gemini API has no cancel endpoint for video-generation\n * operations.** The generativelanguage v1beta discovery document only\n * defines `batches.cancel` (unrelated to video jobs); there is no\n * `models.operations.cancel`. This always throws — cancellation of a\n * Veo render is unsupported by the provider itself, not merely by this\n * client. Callers must treat cancellation as best-effort across all\n * video-generation providers and tolerate this failure (e.g. by simply\n * discarding the handle and not billing for further polling).\n *\n * @param handle - The job handle returned by {@link submitVideoGenerationJob}\n * @throws {AIError} Always — cancellation is unsupported by the Gemini API\n */\n async cancelVideoGenerationJob(handle: VideoGenerationJob): Promise<void> {\n if (this.options.projectId && this.options.location) {\n throw new AIError(\n 'Cancelling Gemini video-generation jobs is not implemented for Vertex AI mode by this provider (it requires OAuth credentials this provider does not manage).',\n 'NOT_IMPLEMENTED',\n 'gemini',\n handle.model,\n );\n }\n\n throw new AIError(\n 'The Gemini API has no cancel endpoint for video-generation operations (only batches.cancel exists, which does not apply to Veo jobs). ' +\n 'cancelVideoGenerationJob cannot stop an in-flight Veo render on this provider; treat cancellation as best-effort and stop polling / discard the handle instead.',\n 'VIDEO_CANCEL_UNSUPPORTED',\n 'gemini',\n handle.model,\n );\n }\n\n /**\n * Cheap auth-shaped check for Veo access: lists models with a page size\n * of 1. Callers on a hot path must cache the result themselves.\n *\n * @returns Promise resolving to true when access looks valid\n */\n async validateVideoGenerationAccess(): Promise<boolean> {\n try {\n await this.ensureClient();\n await this.client.models.list({ config: { pageSize: 1 } });\n return true;\n } catch (error) {\n throw this.mapError(error);\n }\n }\n\n private mapVideoOperation(operation: {\n done?: boolean;\n error?: Record<string, unknown>;\n response?: {\n generatedVideos?: Array<{\n video?: { uri?: string; videoBytes?: string; mimeType?: string };\n }>;\n };\n }): VideoGenerationStatusResult {\n if (!operation.done) {\n return { status: 'running' };\n }\n\n if (operation.error) {\n const errorInfo = operation.error as { code?: number; message?: unknown };\n const message =\n typeof errorInfo.message === 'string'\n ? errorInfo.message\n : JSON.stringify(operation.error);\n // google.rpc.Code.CANCELLED === 1; fall back to a message regex for\n // error shapes that don't carry a structured code.\n const cancelled = errorInfo.code === 1 || /cancel/i.test(message);\n return cancelled\n ? { status: 'cancelled' }\n : { status: 'failed', error: message };\n }\n\n const video = operation.response?.generatedVideos?.[0]?.video;\n if (!video) {\n return {\n status: 'failed',\n error:\n 'Gemini reported the video-generation job as done with no output',\n };\n }\n\n // Metadata only here — `data` requires a separate authenticated\n // download; see fetchVideoGenerationResult.\n const result: VideoGenerationResult = {\n url: video.uri,\n mimeType: video.mimeType || 'video/mp4',\n };\n\n return { status: 'succeeded', result };\n }\n\n async *stream(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): AsyncIterable<string> {\n const startTime = Date.now();\n let controls: PreparedRequestControls | undefined;\n try {\n await this.ensureClient();\n\n const model = options.model || this.options.defaultModel;\n options = normalizeChatOptions(this.options, options, 'gemini', model);\n controls = prepareRequestControls(this.options, options);\n const stream = await this.client.models.generateContentStream({\n model,\n ...this.buildContentsRequest(messages, options, controls, model),\n });\n\n let usage: TokenUsage | undefined;\n let streamFinish: AIResponse['finishReason'] = 'stop';\n\n for await (const chunk of stream) {\n if (chunk.candidates?.[0]?.finishReason === 'MAX_TOKENS') {\n streamFinish = 'length';\n }\n if (chunk.usageMetadata) {\n usage = {\n promptTokens: chunk.usageMetadata.promptTokenCount || 0,\n completionTokens: chunk.usageMetadata.candidatesTokenCount || 0,\n totalTokens: chunk.usageMetadata.totalTokenCount || 0,\n };\n }\n\n const text = chunk.text || '';\n if (!text) {\n continue;\n }\n\n if (options.onProgress) {\n options.onProgress(text);\n }\n yield text;\n }\n options.onFinishReason?.(streamFinish ?? 'stop');\n\n emitUsage(\n this.options,\n 'gemini',\n 'stream',\n model!,\n usage,\n startTime,\n options.usageTags,\n );\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'gemini',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'gemini',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n async countTokens(text: string): Promise<number> {\n try {\n await this.ensureClient();\n\n const model = this.options.defaultModel || 'gemini-2.5-flash';\n const response = await this.client.models.countTokens({\n model,\n contents: text,\n });\n\n return response.totalTokens || Math.ceil(text.length / 4);\n } catch (error) {\n throw this.mapError(error);\n }\n }\n\n async getModels(): Promise<AIModel[]> {\n // Return static list of known Gemini models\n return [\n {\n id: 'gemini-3-flash-preview',\n name: 'Gemini 3 Flash Preview',\n description:\n 'Preview of Gemini 3 Flash model. Available on Vertex AI in us-central1 only.',\n contextLength: 1000000,\n capabilities: ['text', 'chat', 'vision', 'functions'],\n supportsFunctions: true,\n supportsVision: true,\n },\n {\n id: 'gemini-2.0-flash-001',\n name: 'Gemini 2.0 Flash',\n description:\n 'Latest fast and efficient Gemini model with function calling',\n contextLength: 1000000,\n capabilities: ['text', 'chat', 'vision', 'functions'],\n supportsFunctions: true,\n supportsVision: true,\n },\n {\n id: 'gemini-2.5-flash',\n name: 'Gemini 2.5 Flash',\n description: 'Experimental next-generation Gemini model',\n contextLength: 1000000,\n capabilities: ['text', 'chat', 'vision', 'functions'],\n supportsFunctions: true,\n supportsVision: true,\n },\n {\n id: 'gemini-1.5-pro',\n name: 'Gemini 1.5 Pro (Legacy)',\n description: 'Previous generation model (may not be available)',\n contextLength: 2000000,\n capabilities: ['text', 'chat', 'vision', 'functions'],\n supportsFunctions: true,\n supportsVision: true,\n },\n ];\n }\n\n async getCapabilities(): Promise<AICapabilities> {\n return {\n chat: true,\n completion: true,\n embeddings: true,\n streaming: true,\n functions: true,\n vision: true,\n fineTuning: false,\n imageEmbeddings: true,\n imageGeneration: true,\n videoGeneration: true,\n tts: false,\n voiceCloning: false,\n voiceDesign: false,\n maxContextLength: 2000000,\n supportedOperations: [\n 'chat',\n 'completion',\n 'embedding',\n 'streaming',\n 'functions',\n 'vision',\n 'image_embedding',\n 'image_generation',\n 'video_generation',\n ],\n };\n }\n\n // ============================================================================\n // TTS Methods (Not supported - use Qwen3-TTS provider)\n // ============================================================================\n\n async synthesizeSpeech(\n _text: string,\n _options?: TTSOptions,\n ): Promise<TTSResponse> {\n throw new AIError(\n 'TTS is not supported by Gemini provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'gemini',\n );\n }\n\n streamSpeech(_text: string, _options?: TTSOptions): AsyncIterable<Buffer> {\n const error = new AIError(\n 'TTS streaming is not supported by Gemini provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'gemini',\n );\n return {\n [Symbol.asyncIterator]: () => ({\n next: () => Promise.reject(error),\n }),\n };\n }\n\n async cloneVoice(_options: VoiceCloneOptions): Promise<Voice> {\n throw new AIError(\n 'Voice cloning is not supported by Gemini provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'gemini',\n );\n }\n\n async designVoice(_options: VoiceDesignOptions): Promise<Voice> {\n throw new AIError(\n 'Voice design is not supported by Gemini provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'gemini',\n );\n }\n\n async getVoices(_options?: VoiceListOptions): Promise<Voice[]> {\n throw new AIError(\n 'Voice listing is not supported by Gemini provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'gemini',\n );\n }\n\n private mapToolChoice(\n toolChoice?:\n | 'auto'\n | 'none'\n | { type: 'function'; function: { name: string } },\n ): any {\n if (!toolChoice || toolChoice === 'auto') {\n return { functionCallingConfig: { mode: 'AUTO' } };\n }\n\n if (toolChoice === 'none') {\n return { functionCallingConfig: { mode: 'NONE' } };\n }\n\n if (typeof toolChoice === 'object' && toolChoice.type === 'function') {\n return {\n functionCallingConfig: {\n mode: 'ANY',\n allowedFunctionNames: [toolChoice.function.name],\n },\n };\n }\n\n return { functionCallingConfig: { mode: 'AUTO' } };\n }\n\n private buildGenerateContentConfig(\n options: ChatOptions,\n controls: PreparedRequestControls,\n ): Record<string, any> {\n const config: Record<string, any> = {\n abortSignal: controls.signal,\n httpOptions: {\n timeout: controls.timeout,\n retryOptions: { attempts: (this.options.maxRetries || 0) + 1 },\n },\n maxOutputTokens: options.maxTokens,\n temperature: options.temperature,\n topP: options.topP,\n stopSequences: Array.isArray(options.stop)\n ? options.stop\n : options.stop\n ? [options.stop]\n : undefined,\n responseMimeType:\n options.responseFormat?.type === 'json_object'\n ? 'application/json'\n : undefined,\n frequencyPenalty: options.frequencyPenalty,\n presencePenalty: options.presencePenalty,\n seed: options.seed,\n };\n\n if (options.tools && options.tools.length > 0) {\n config.tools = [\n {\n functionDeclarations: options.tools.map((tool) => ({\n name: tool.function.name,\n description: tool.function.description || '',\n parameters: tool.function.parameters || { type: 'object' },\n })),\n },\n ];\n config.toolConfig = this.mapToolChoice(options.toolChoice);\n }\n\n const reasoning = options.reasoning;\n if (reasoning?.maxTokens !== undefined && reasoning.maxTokens > 0) {\n config.thinkingConfig = {\n thinkingBudget: reasoning.maxTokens,\n includeThoughts: reasoning.includeThoughts,\n };\n }\n\n return Object.fromEntries(\n Object.entries(config).filter(([, value]) => value !== undefined),\n );\n }\n\n private mapFinishReason(response: any): AIResponse['finishReason'] {\n // Check if response has function calls in any candidate\n const firstCandidate = response.candidates?.[0];\n if (firstCandidate?.content?.parts) {\n const hasFunctionCall = firstCandidate.content.parts.some(\n (part: any) => part.functionCall,\n );\n if (hasFunctionCall) {\n return 'tool_calls';\n }\n }\n\n if (firstCandidate?.finishReason === 'MAX_TOKENS') {\n return 'length';\n }\n\n return 'stop';\n }\n\n /**\n * Builds the `contents` + `config` pair for generateContent.\n *\n * Plain conversations keep the flattened text prompt. Conversations with\n * tool traffic need structured turns so Gemini can pair each\n * `functionResponse` with the `functionCall` that requested it.\n */\n private buildContentsRequest(\n messages: AIMessage[],\n options: ChatOptions,\n controls: PreparedRequestControls,\n model?: string,\n ): { contents: string | GeminiContent[]; config: Record<string, any> } {\n const config = this.buildGenerateContentConfig(options, controls);\n if (!hasToolTraffic(messages)) {\n return { contents: this.messagesToGeminiFormat(messages), config };\n }\n\n const { systemInstruction, contents } = this.messagesToGeminiContents(\n messages,\n model,\n );\n if (systemInstruction) {\n config.systemInstruction = systemInstruction;\n }\n return { contents, config };\n }\n\n /**\n * Maps a tool-calling conversation to structured Gemini turns.\n *\n * Assistant `tool_calls` become `functionCall` parts (replaying any\n * recorded thought signature); `role: 'tool'` results become\n * `functionResponse` parts named after the call their `tool_call_id`\n * answers. Consecutive results share one user turn.\n *\n * Only answered calls are replayed: a `functionCall` without a matching\n * `functionResponse` is rejected. A call counts as answered when a result\n * carries its id, or (legacy results without `tool_call_id`) its name.\n *\n * Gemini 3 strictly validates the thought signature on the first\n * `functionCall` of each model step and returns 400 when it is missing.\n * Consumers should persist `AIToolCall.thoughtSignature` with their\n * history; when a Gemini 3 step has none (history from another model or\n * a store that dropped it), the first call gets Google's documented\n * placeholder signature, which skips validation at some quality cost.\n */\n private messagesToGeminiContents(\n messages: AIMessage[],\n model?: string,\n ): {\n systemInstruction?: string;\n contents: GeminiContent[];\n } {\n const toolCallNames = indexToolCallNames(messages);\n const answeredIds = new Set<string>();\n const answeredLegacyNames = new Set<string>();\n for (const message of messages) {\n if (message.role !== 'tool' && message.role !== 'function') continue;\n if (message.tool_call_id) answeredIds.add(message.tool_call_id);\n else if (message.name) answeredLegacyNames.add(message.name);\n }\n const placeholderSignature =\n model && isGemini3Model(model)\n ? this.options.projectId && this.options.location\n ? VERTEX_PLACEHOLDER_THOUGHT_SIGNATURE\n : GEMINI_API_PLACEHOLDER_THOUGHT_SIGNATURE\n : undefined;\n const contents: GeminiContent[] = [];\n let systemInstruction: string | undefined;\n\n for (const message of messages) {\n const textContent = extractTextContent(message.content);\n\n if (message.role === 'system') {\n systemInstruction = systemInstruction\n ? `${systemInstruction}\\n\\n${textContent}`\n : textContent;\n continue;\n }\n\n if (message.role === 'tool' || message.role === 'function') {\n const name = resolveToolResultName(message, toolCallNames);\n const part: GeminiPart = name\n ? {\n functionResponse: {\n name,\n response: toolResultObject(textContent),\n },\n }\n : { text: textContent };\n const previous = contents[contents.length - 1];\n if (\n name &&\n previous?.role === 'user' &&\n previous.parts.every((existing) => existing.functionResponse)\n ) {\n previous.parts.push(part);\n } else {\n contents.push({ role: 'user', parts: [part] });\n }\n continue;\n }\n\n const parts: GeminiPart[] = textContent ? [{ text: textContent }] : [];\n if (message.role === 'assistant') {\n const answered = (message.tool_calls || []).filter(\n (toolCall) =>\n answeredIds.has(toolCall.id) ||\n answeredLegacyNames.has(toolCall.function.name),\n );\n const signed = answered.some((toolCall) => toolCall.thoughtSignature);\n answered.forEach((toolCall, index) => {\n const thoughtSignature =\n toolCall.thoughtSignature ||\n (index === 0 && !signed ? placeholderSignature : undefined);\n parts.push({\n functionCall: {\n name: toolCall.function.name,\n args: parseToolArguments(toolCall.function.arguments),\n },\n ...(thoughtSignature ? { thoughtSignature } : {}),\n });\n });\n }\n if (parts.length === 0) continue;\n\n contents.push({\n role: message.role === 'assistant' ? 'model' : 'user',\n parts,\n });\n }\n\n return { systemInstruction, contents };\n }\n\n private messagesToGeminiFormat(messages: AIMessage[]): string {\n // Convert messages to a simple text prompt\n // The new SDK expects a string for the contents field\n return messages\n .map((message) => {\n const textContent = extractTextContent(message.content);\n switch (message.role) {\n case 'system':\n return `Instructions: ${textContent}`;\n case 'user':\n return `Human: ${textContent}`;\n case 'assistant':\n return `Assistant: ${textContent}`;\n default:\n return textContent;\n }\n })\n .join('\\n\\n');\n }\n\n private stripMarkdownCodeBlock(text: string): string {\n // Remove markdown code blocks like ```json\\n...\\n```\n const codeBlockRegex =\n /^```(?:json|javascript|typescript)?\\s*\\n?([\\s\\S]*?)\\n?```\\s*$/;\n const match = text.match(codeBlockRegex);\n return match ? match[1].trim() : text.trim();\n }\n\n private mapError(error: unknown): AIError {\n if (error instanceof AIError) {\n return error;\n }\n\n // Map common Gemini error patterns\n const message =\n error instanceof Error ? error.message : 'Unknown Gemini error occurred';\n\n if (message.includes('API_KEY_INVALID') || message.includes('401')) {\n return new AuthenticationError('gemini');\n }\n\n if (message.includes('QUOTA_EXCEEDED') || message.includes('429')) {\n return rateLimitErrorFrom('gemini', error);\n }\n\n if (message.includes('MODEL_NOT_FOUND') || message.includes('404')) {\n return new ModelNotFoundError(message, 'gemini');\n }\n\n return new AIError(message, 'UNKNOWN_ERROR', 'gemini');\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { b as extractTextContent, f as AuthenticationError, g as ModelNotFoundError, l as prepareRequestControls, m as ContextLengthError, o as normalizeBaseAIOptions, s as normalizeChatOptions, t as emitUsage, u as AIError } from "./usage-B9gPCWSa.js";
2
- import { n as rateLimitErrorFrom } from "./rate-limit-BkK4-hXY.js";
1
+ import { b as extractTextContent, f as AuthenticationError, g as ModelNotFoundError, l as prepareRequestControls, m as ContextLengthError, o as normalizeBaseAIOptions, s as normalizeChatOptions, t as emitUsage, u as AIError } from "./usage-DS7uDhi1.js";
2
+ import { n as rateLimitErrorFrom } from "./rate-limit-Dwyde1BY.js";
3
3
  //#region src/shared/providers/huggingface.ts
4
4
  /**
5
5
  * Hugging Face provider implementation
@@ -309,4 +309,4 @@ var HuggingFaceProvider = class {
309
309
  //#endregion
310
310
  export { HuggingFaceProvider };
311
311
 
312
- //# sourceMappingURL=huggingface-DtuYF1vb.js.map
312
+ //# sourceMappingURL=huggingface-jqjeFPdr.js.map