@happyvertical/ai 0.85.4 → 0.85.5

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 (84) hide show
  1. package/README.md +87 -1
  2. package/dist/chunks/{anthropic-DA8sdt12.js → anthropic-DuYUnw8j.js} +20 -4
  3. package/dist/chunks/anthropic-DuYUnw8j.js.map +1 -0
  4. package/dist/chunks/{bedrock-DDiYFUw0.js → bedrock-ikQJAwWB.js} +19 -3
  5. package/dist/chunks/bedrock-ikQJAwWB.js.map +1 -0
  6. package/dist/chunks/{bifrost-fM9FpW_w.js → bifrost-CaYhelVL.js} +5 -4
  7. package/dist/chunks/bifrost-CaYhelVL.js.map +1 -0
  8. package/dist/chunks/byteplus-modelark-B8l8sPXu.js +473 -0
  9. package/dist/chunks/byteplus-modelark-B8l8sPXu.js.map +1 -0
  10. package/dist/chunks/{claude-cli-CnJh5KQT.js → claude-cli-DeTKk9nu.js} +19 -3
  11. package/dist/chunks/claude-cli-DeTKk9nu.js.map +1 -0
  12. package/dist/chunks/{gateway-admin-CiKvHst7.js → gateway-admin-DJXEDpUP.js} +2 -2
  13. package/dist/chunks/{gateway-admin-CiKvHst7.js.map → gateway-admin-DJXEDpUP.js.map} +1 -1
  14. package/dist/chunks/{gemini-Bu7Fke7c.js → gemini-BT8fjXWz.js} +294 -11
  15. package/dist/chunks/gemini-BT8fjXWz.js.map +1 -0
  16. package/dist/chunks/{huggingface-B07_6wHW.js → huggingface-CqzyxeLB.js} +19 -3
  17. package/dist/chunks/huggingface-CqzyxeLB.js.map +1 -0
  18. package/dist/chunks/{litellm-D_Oo9OQ_.js → litellm-viqTuSY8.js} +5 -4
  19. package/dist/chunks/litellm-viqTuSY8.js.map +1 -0
  20. package/dist/chunks/{ollama-D4ksOTO8.js → ollama-CdWqwZ05.js} +19 -3
  21. package/dist/chunks/ollama-CdWqwZ05.js.map +1 -0
  22. package/dist/chunks/{openai--F38QHiJ.js → openai-BgrK3OfW.js} +20 -4
  23. package/dist/chunks/openai-BgrK3OfW.js.map +1 -0
  24. package/dist/chunks/openai-compat-video-D_U7jo0d.js +369 -0
  25. package/dist/chunks/openai-compat-video-D_U7jo0d.js.map +1 -0
  26. package/dist/chunks/{qwen-tts-DRRbOrhA.js → qwen-tts-BXjzY7DX.js} +21 -4
  27. package/dist/chunks/qwen-tts-BXjzY7DX.js.map +1 -0
  28. package/dist/chunks/{rate-limit-BwyPGXFW.js → rate-limit-DgEhanDL.js} +4 -3
  29. package/dist/chunks/rate-limit-DgEhanDL.js.map +1 -0
  30. package/dist/chunks/{safety-CEnoJS6X.js → safety-C415clBm.js} +25 -7
  31. package/dist/chunks/safety-C415clBm.js.map +1 -0
  32. package/dist/chunks/src-CU4qWJ2c.js +740 -0
  33. package/dist/chunks/src-CU4qWJ2c.js.map +1 -0
  34. package/dist/chunks/{types-FHs-KbGL.js → types-CINwUPDo.js} +4 -2
  35. package/dist/chunks/types-CINwUPDo.js.map +1 -0
  36. package/dist/index.js +3 -717
  37. package/dist/node/factory.d.ts +9 -0
  38. package/dist/node/factory.d.ts.map +1 -1
  39. package/dist/node.d.ts +29 -0
  40. package/dist/node.d.ts.map +1 -0
  41. package/dist/node.js +198 -0
  42. package/dist/node.js.map +1 -0
  43. package/dist/shared/factory.d.ts.map +1 -1
  44. package/dist/shared/providers/anthropic.d.ts +6 -1
  45. package/dist/shared/providers/anthropic.d.ts.map +1 -1
  46. package/dist/shared/providers/bedrock.d.ts +6 -1
  47. package/dist/shared/providers/bedrock.d.ts.map +1 -1
  48. package/dist/shared/providers/bifrost.d.ts.map +1 -1
  49. package/dist/shared/providers/byteplus-modelark.d.ts +91 -0
  50. package/dist/shared/providers/byteplus-modelark.d.ts.map +1 -0
  51. package/dist/shared/providers/claude-cli.d.ts +6 -1
  52. package/dist/shared/providers/claude-cli.d.ts.map +1 -1
  53. package/dist/shared/providers/gemini.d.ts +115 -2
  54. package/dist/shared/providers/gemini.d.ts.map +1 -1
  55. package/dist/shared/providers/huggingface.d.ts +6 -1
  56. package/dist/shared/providers/huggingface.d.ts.map +1 -1
  57. package/dist/shared/providers/litellm.d.ts.map +1 -1
  58. package/dist/shared/providers/ollama.d.ts +6 -1
  59. package/dist/shared/providers/ollama.d.ts.map +1 -1
  60. package/dist/shared/providers/openai-compat-video.d.ts +98 -0
  61. package/dist/shared/providers/openai-compat-video.d.ts.map +1 -0
  62. package/dist/shared/providers/openai.d.ts +6 -1
  63. package/dist/shared/providers/openai.d.ts.map +1 -1
  64. package/dist/shared/providers/qwen-tts.d.ts +6 -1
  65. package/dist/shared/providers/qwen-tts.d.ts.map +1 -1
  66. package/dist/shared/rate-limit.d.ts.map +1 -1
  67. package/dist/shared/safety.d.ts.map +1 -1
  68. package/dist/shared/types.d.ts +343 -5
  69. package/dist/shared/types.d.ts.map +1 -1
  70. package/package.json +7 -3
  71. package/dist/chunks/anthropic-DA8sdt12.js.map +0 -1
  72. package/dist/chunks/bedrock-DDiYFUw0.js.map +0 -1
  73. package/dist/chunks/bifrost-fM9FpW_w.js.map +0 -1
  74. package/dist/chunks/claude-cli-CnJh5KQT.js.map +0 -1
  75. package/dist/chunks/gemini-Bu7Fke7c.js.map +0 -1
  76. package/dist/chunks/huggingface-B07_6wHW.js.map +0 -1
  77. package/dist/chunks/litellm-D_Oo9OQ_.js.map +0 -1
  78. package/dist/chunks/ollama-D4ksOTO8.js.map +0 -1
  79. package/dist/chunks/openai--F38QHiJ.js.map +0 -1
  80. package/dist/chunks/qwen-tts-DRRbOrhA.js.map +0 -1
  81. package/dist/chunks/rate-limit-BwyPGXFW.js.map +0 -1
  82. package/dist/chunks/safety-CEnoJS6X.js.map +0 -1
  83. package/dist/chunks/types-FHs-KbGL.js.map +0 -1
  84. package/dist/index.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"bedrock-DDiYFUw0.js","names":[],"sources":["../../src/shared/providers/bedrock.ts"],"sourcesContent":["/**\n * AWS Bedrock provider implementation\n */\n\nimport {\n normalizeBaseAIOptions,\n normalizeChatOptions,\n normalizeImageGenerationOptions,\n type PreparedRequestControls,\n prepareRequestControls,\n} from '../safety';\nimport type {\n AICapabilities,\n AIInterface,\n AIMessage,\n AIModel,\n AIResponse,\n BedrockOptions,\n ChatOptions,\n CompletionOptions,\n EmbeddingOptions,\n EmbeddingResponse,\n ImageDescriptionOptions,\n ImageEmbeddingOptions,\n ImageGenerationOptions,\n ImageGenerationResponse,\n MessageOptions,\n TokenUsage,\n TTSOptions,\n TTSResponse,\n Voice,\n VoiceCloneOptions,\n VoiceDesignOptions,\n VoiceListOptions,\n} from '../types';\nimport {\n AIError,\n AuthenticationError,\n ContextLengthError,\n extractTextContent,\n ModelNotFoundError,\n RateLimitError,\n} from '../types';\nimport { emitUsage } from './usage';\n\nconst BEDROCK_DEFAULT_CHAT_MODEL = 'anthropic.claude-3-5-sonnet-20241022-v2:0';\nconst BEDROCK_TEXT_EMBEDDING_MODEL = 'amazon.titan-embed-text-v2:0';\nconst BEDROCK_IMAGE_EMBEDDING_MODEL = 'amazon.titan-embed-image-v1';\nconst BEDROCK_IMAGE_GENERATION_MODEL = 'amazon.titan-image-generator-v2:0';\n\nexport class BedrockProvider implements AIInterface {\n private options: BedrockOptions;\n private client: any; // Will be BedrockRuntimeClient instance from @aws-sdk/client-bedrock-runtime\n\n constructor(options: BedrockOptions) {\n this.options = normalizeBaseAIOptions({\n defaultModel: BEDROCK_DEFAULT_CHAT_MODEL,\n ...options,\n });\n\n // Initialize AWS Bedrock 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('@aws-sdk/client-bedrock-runtime')\n .then(({ BedrockRuntimeClient }) => {\n this.client = new BedrockRuntimeClient({\n region: this.options.region,\n credentials: this.options.credentials,\n endpoint: this.options.endpoint,\n maxAttempts: (this.options.maxRetries || 0) + 1,\n });\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 { BedrockRuntimeClient } = await import(\n '@aws-sdk/client-bedrock-runtime'\n );\n this.client = new BedrockRuntimeClient({\n region: this.options.region,\n credentials: this.options.credentials,\n endpoint: this.options.endpoint,\n maxAttempts: (this.options.maxRetries || 0) + 1,\n });\n } catch (_error) {\n throw new AIError(\n 'Failed to initialize Bedrock client. Make sure @aws-sdk/client-bedrock-runtime is installed.',\n 'INITIALIZATION_ERROR',\n 'bedrock',\n );\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 modelId = options.model || this.options.defaultModel;\n options = normalizeChatOptions(this.options, options, 'bedrock', modelId);\n controls = prepareRequestControls(this.options, options);\n const response = this.mapConverseResponse(\n await this.client.converse(\n await this.buildConverseRequest(\n messages,\n options,\n modelId!,\n controls.signal,\n ),\n { abortSignal: controls.signal },\n ),\n modelId!,\n );\n\n emitUsage(\n this.options,\n 'bedrock',\n 'chat',\n response.model || modelId || 'unknown',\n response.usage,\n startTime,\n options.usageTags,\n );\n return response;\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'bedrock',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'bedrock',\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 });\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 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 });\n\n return response.content;\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 || BEDROCK_TEXT_EMBEDDING_MODEL;\n const inputs = Array.isArray(text) ? text : [text];\n const embeddings: number[][] = [];\n let totalTokens = 0;\n\n for (const inputText of inputs) {\n const response = await this.client.invokeModel({\n modelId: model,\n contentType: 'application/json',\n accept: 'application/json',\n body: JSON.stringify({\n inputText,\n ...(options.dimensions && { dimensions: options.dimensions }),\n normalize: true,\n }),\n });\n\n const payload = await this.parseInvokeModelBody(response.body);\n const embedding = this.extractEmbeddingVector(payload);\n if (embedding) {\n embeddings.push(embedding);\n }\n\n totalTokens +=\n payload.inputTextTokenCount ||\n payload.inputTokenCount ||\n payload.tokenCount ||\n 0;\n }\n\n const usage: TokenUsage | undefined =\n totalTokens > 0\n ? {\n promptTokens: totalTokens,\n completionTokens: 0,\n totalTokens,\n }\n : undefined;\n\n emitUsage(\n this.options,\n 'bedrock',\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 async embedImage(\n image: string | Buffer,\n options: ImageEmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n const startTime = Date.now();\n try {\n await this.ensureClient();\n\n const model = options.model || BEDROCK_IMAGE_EMBEDDING_MODEL;\n const response = await this.client.invokeModel({\n modelId: model,\n contentType: 'application/json',\n accept: 'application/json',\n body: JSON.stringify({\n inputImage: await this.imageToBase64(image),\n ...(options.dimensions && {\n embeddingConfig: {\n outputEmbeddingLength: options.dimensions,\n },\n }),\n }),\n });\n\n const payload = await this.parseInvokeModelBody(response.body);\n const embedding = this.extractEmbeddingVector(payload);\n\n emitUsage(\n this.options,\n 'bedrock',\n 'embedImage',\n model,\n undefined,\n startTime,\n );\n\n return {\n embeddings: embedding ? [embedding] : [],\n model,\n };\n } catch (error) {\n throw this.mapError(error);\n }\n }\n\n async describeImage(\n image: string | Buffer,\n prompt?: string,\n options: ImageDescriptionOptions = {},\n ): Promise<string> {\n const imageUrl = await this.imageToDataUrl(image, options.signal);\n const response = await this.chat(\n [\n {\n role: 'user',\n content: [\n {\n type: 'text',\n text:\n prompt ||\n 'Describe this image for a search index. Include objects, mood, lighting, and any visible text.',\n },\n {\n type: 'image_url',\n image_url: { url: imageUrl },\n },\n ],\n },\n ],\n {\n model: options.model || this.options.defaultModel,\n maxTokens: options.maxTokens ?? 500,\n signal: options.signal,\n timeout: options.timeout,\n reasoning: options.reasoning,\n usageTags: options.usageTags,\n },\n );\n\n return response.content;\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 || BEDROCK_IMAGE_GENERATION_MODEL;\n options = normalizeImageGenerationOptions(\n this.options,\n options,\n 'bedrock',\n model,\n );\n controls = prepareRequestControls(this.options, options);\n const size = this.resolveImageSize(options);\n const response = await this.client.invokeModel(\n {\n modelId: model,\n contentType: 'application/json',\n accept: 'application/json',\n body: JSON.stringify({\n taskType: 'TEXT_IMAGE',\n textToImageParams: {\n text: prompt,\n ...(options.imageInput && {\n conditionImage: await this.imageToBase64(\n options.imageInput,\n controls.signal,\n ),\n }),\n },\n imageGenerationConfig: {\n numberOfImages: options.n,\n quality: this.mapImageQuality(options.quality),\n ...size,\n },\n }),\n },\n { abortSignal: controls.signal },\n );\n\n const payload = await this.parseInvokeModelBody(response.body);\n if (payload.error) {\n throw new AIError(payload.error, 'API_ERROR', 'bedrock');\n }\n\n const images = (payload.images || []).map((encoded: string) => {\n const mimeType = 'image/png';\n if (options.outputFormat === 'base64') {\n return { data: encoded, mimeType };\n }\n if (options.outputFormat === 'url') {\n return { data: `data:${mimeType};base64,${encoded}`, mimeType };\n }\n return {\n data: Buffer.from(encoded, 'base64'),\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 'bedrock',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'bedrock',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\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 modelId = options.model || this.options.defaultModel;\n options = normalizeChatOptions(this.options, options, 'bedrock', modelId);\n controls = prepareRequestControls(this.options, options);\n const response = await this.client.converseStream(\n await this.buildConverseRequest(\n messages,\n options,\n modelId!,\n controls.signal,\n ),\n { abortSignal: controls.signal },\n );\n\n let usage: TokenUsage | undefined;\n\n for await (const event of response.stream || []) {\n const text = event.contentBlockDelta?.delta?.text;\n if (text) {\n if (options.onProgress) {\n options.onProgress(text);\n }\n yield text;\n }\n\n if (event.metadata?.usage) {\n usage = {\n promptTokens: event.metadata.usage.inputTokens || 0,\n completionTokens: event.metadata.usage.outputTokens || 0,\n totalTokens: event.metadata.usage.totalTokens || 0,\n };\n }\n }\n\n emitUsage(\n this.options,\n 'bedrock',\n 'stream',\n modelId || 'unknown',\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 'bedrock',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'bedrock',\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 modelId = this.options.defaultModel || BEDROCK_DEFAULT_CHAT_MODEL;\n const response = await this.client.countTokens({\n modelId,\n input: {\n converse: {\n messages: [\n {\n role: 'user',\n content: [{ text }],\n },\n ],\n },\n },\n });\n\n return response.inputTokens || 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 popular Bedrock models\n return [\n // Anthropic Claude models\n {\n id: 'anthropic.claude-3-5-sonnet-20241022-v2:0',\n name: 'Claude 3.5 Sonnet v2',\n description: 'Latest Claude 3.5 Sonnet model on Bedrock',\n contextLength: 200000,\n capabilities: ['text', 'chat', 'vision', 'functions'],\n supportsFunctions: true,\n supportsVision: true,\n },\n {\n id: 'anthropic.claude-3-opus-20240229-v1:0',\n name: 'Claude 3 Opus',\n description: 'Most powerful Claude model on Bedrock',\n contextLength: 200000,\n capabilities: ['text', 'chat', 'vision'],\n supportsFunctions: false,\n supportsVision: true,\n },\n // Amazon Titan models\n {\n id: 'amazon.titan-text-premier-v1:0',\n name: 'Titan Text Premier',\n description: 'Premier Amazon Titan text model',\n contextLength: 32000,\n capabilities: ['text', 'chat'],\n supportsFunctions: false,\n supportsVision: false,\n },\n {\n id: 'amazon.titan-embed-text-v1',\n name: 'Titan Embeddings Text',\n description: 'Amazon Titan text embeddings model',\n contextLength: 8192,\n capabilities: ['embeddings'],\n supportsFunctions: false,\n supportsVision: false,\n },\n {\n id: BEDROCK_TEXT_EMBEDDING_MODEL,\n name: 'Titan Embeddings Text V2',\n description: 'Amazon Titan text embeddings v2 model',\n contextLength: 8192,\n capabilities: ['embeddings'],\n supportsFunctions: false,\n supportsVision: false,\n },\n {\n id: BEDROCK_IMAGE_EMBEDDING_MODEL,\n name: 'Titan Multimodal Embeddings G1',\n description:\n 'Amazon Titan multimodal embeddings model for image similarity',\n contextLength: 256,\n capabilities: ['embeddings', 'image_embedding'],\n supportsFunctions: false,\n supportsVision: false,\n },\n {\n id: BEDROCK_IMAGE_GENERATION_MODEL,\n name: 'Titan Image Generator V2',\n description: 'Amazon Titan image generation model',\n contextLength: 0,\n capabilities: ['image_generation'],\n supportsFunctions: false,\n supportsVision: false,\n },\n // Cohere models\n {\n id: 'cohere.command-r-plus-v1:0',\n name: 'Command R+',\n description: 'Cohere Command R+ model with advanced capabilities',\n contextLength: 128000,\n capabilities: ['text', 'chat', 'functions'],\n supportsFunctions: true,\n supportsVision: false,\n },\n // Meta Llama models\n {\n id: 'meta.llama3-1-405b-instruct-v1:0',\n name: 'Llama 3.1 405B Instruct',\n description: 'Meta Llama 3.1 405B instruction-tuned model',\n contextLength: 128000,\n capabilities: ['text', 'chat'],\n supportsFunctions: false,\n supportsVision: false,\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, // Some models support function calling\n vision: true, // Some models support vision\n fineTuning: true, // Via Bedrock fine-tuning\n imageEmbeddings: true,\n imageGeneration: true,\n tts: false,\n voiceCloning: false,\n voiceDesign: false,\n maxContextLength: 200000,\n supportedOperations: [\n 'chat',\n 'completion',\n 'embedding',\n 'streaming',\n 'functions',\n 'vision',\n 'image_embedding',\n 'image_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 Bedrock provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'bedrock',\n );\n }\n\n streamSpeech(_text: string, _options?: TTSOptions): AsyncIterable<Buffer> {\n const error = new AIError(\n 'TTS streaming is not supported by Bedrock provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'bedrock',\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 Bedrock provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'bedrock',\n );\n }\n\n async designVoice(_options: VoiceDesignOptions): Promise<Voice> {\n throw new AIError(\n 'Voice design is not supported by Bedrock provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'bedrock',\n );\n }\n\n async getVoices(_options?: VoiceListOptions): Promise<Voice[]> {\n throw new AIError(\n 'Voice listing is not supported by Bedrock provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'bedrock',\n );\n }\n\n private async buildConverseRequest(\n messages: AIMessage[],\n options: ChatOptions,\n modelId: string,\n signal?: AbortSignal,\n ): Promise<Record<string, any>> {\n const { system, bedrockMessages } = await this.mapMessagesToBedrock(\n messages,\n signal,\n );\n const systemPrompt =\n options.responseFormat?.type === 'json_object'\n ? [\n system,\n 'Respond with valid JSON only. Do not include explanatory text outside the JSON object.',\n ]\n .filter(Boolean)\n .join('\\n\\n')\n : system;\n\n const inferenceConfig = Object.fromEntries(\n Object.entries({\n maxTokens: 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 }).filter(([, value]) => value !== undefined),\n );\n\n const request: Record<string, any> = {\n modelId,\n messages: bedrockMessages,\n ...(Object.keys(inferenceConfig).length > 0 && { inferenceConfig }),\n ...(systemPrompt && { system: [{ text: systemPrompt }] }),\n };\n if ((options.reasoning?.maxTokens || 0) > 0) {\n request.additionalModelRequestFields = {\n thinking: {\n type: 'enabled',\n budget_tokens: options.reasoning?.maxTokens,\n },\n };\n }\n\n const toolConfig = this.mapToolConfig(options);\n if (toolConfig) {\n request.toolConfig = toolConfig;\n }\n\n return request;\n }\n\n private async mapMessagesToBedrock(\n messages: AIMessage[],\n signal?: AbortSignal,\n ): Promise<{\n system?: string;\n bedrockMessages: Array<{ role: 'user' | 'assistant'; content: any[] }>;\n }> {\n let system: string | undefined;\n const bedrockMessages: Array<{\n role: 'user' | 'assistant';\n content: any[];\n }> = [];\n\n for (const message of messages) {\n const textContent = extractTextContent(message.content);\n if (message.role === 'system') {\n system = system ? `${system}\\n\\n${textContent}` : textContent;\n continue;\n }\n\n const content: any[] = [];\n if (typeof message.content === 'string') {\n content.push({ text: message.content });\n } else {\n for (const part of message.content) {\n if (part.type === 'text') {\n content.push({ text: part.text });\n continue;\n }\n\n const image = await this.imageUrlToBedrockImage(\n part.image_url.url,\n signal,\n );\n content.push({ image });\n }\n }\n\n if (message.role === 'assistant' && message.tool_calls) {\n for (const toolCall of message.tool_calls) {\n content.push({\n toolUse: {\n toolUseId: toolCall.id,\n name: toolCall.function.name,\n input: this.safeJsonParse(toolCall.function.arguments),\n },\n });\n }\n }\n\n if (content.length === 0 && textContent) {\n content.push({ text: textContent });\n }\n\n bedrockMessages.push({\n role: message.role === 'assistant' ? 'assistant' : 'user',\n content,\n });\n }\n\n return { system, bedrockMessages };\n }\n\n private mapConverseResponse(response: any, modelId: string): AIResponse {\n const contentBlocks = response.output?.message?.content || [];\n const textContent = contentBlocks\n .filter((block: any) => typeof block.text === 'string')\n .map((block: any) => block.text)\n .join('');\n\n const toolCalls = contentBlocks\n .filter((block: any) => block.toolUse)\n .map((block: any) => ({\n id: block.toolUse.toolUseId,\n type: 'function' as const,\n function: {\n name: block.toolUse.name,\n arguments: JSON.stringify(block.toolUse.input || {}),\n },\n }));\n\n const usage =\n response.usage &&\n ({\n promptTokens: response.usage.inputTokens || 0,\n completionTokens: response.usage.outputTokens || 0,\n totalTokens: response.usage.totalTokens || 0,\n } satisfies TokenUsage);\n\n return {\n content: textContent,\n model: modelId,\n finishReason: this.mapBedrockFinishReason(response.stopReason),\n usage,\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n };\n }\n\n private mapBedrockFinishReason(\n reason: string | null | undefined,\n ): AIResponse['finishReason'] {\n switch (reason) {\n case 'end_turn':\n return 'stop';\n case 'max_tokens':\n return 'length';\n case 'stop_sequence':\n return 'stop';\n case 'tool_use':\n return 'tool_calls';\n default:\n return 'stop';\n }\n }\n\n private mapToolConfig(options: ChatOptions): Record<string, any> | undefined {\n if (!options.tools || options.tools.length === 0) {\n return undefined;\n }\n\n if (options.toolChoice === 'none') {\n return undefined;\n }\n\n return {\n tools: options.tools.map((tool) => ({\n toolSpec: {\n name: tool.function.name,\n description: tool.function.description || '',\n inputSchema: {\n json: tool.function.parameters || { type: 'object' },\n },\n },\n })),\n ...(options.toolChoice && {\n toolChoice: this.mapToolChoice(options.toolChoice),\n }),\n };\n }\n\n private mapToolChoice(\n toolChoice?:\n | 'auto'\n | 'none'\n | { type: 'function'; function: { name: string } },\n ): Record<string, any> | undefined {\n if (!toolChoice || toolChoice === 'auto') {\n return { auto: {} };\n }\n\n if (toolChoice === 'none') {\n return undefined;\n }\n\n return {\n tool: {\n name: toolChoice.function.name,\n },\n };\n }\n\n private async parseInvokeModelBody(body: unknown): Promise<any> {\n const bytes =\n typeof (body as any)?.transformToByteArray === 'function'\n ? await (body as any).transformToByteArray()\n : body instanceof Uint8Array\n ? body\n : Buffer.isBuffer(body)\n ? body\n : new Uint8Array(body as ArrayBuffer);\n return JSON.parse(new TextDecoder().decode(bytes));\n }\n\n private extractEmbeddingVector(payload: any): number[] | undefined {\n if (Array.isArray(payload.embedding)) {\n return payload.embedding;\n }\n\n if (Array.isArray(payload.embeddings?.[0])) {\n return payload.embeddings[0];\n }\n\n if (Array.isArray(payload.embeddingsByType?.float)) {\n return payload.embeddingsByType.float;\n }\n\n if (Array.isArray(payload.vector)) {\n return payload.vector;\n }\n\n return undefined;\n }\n\n private async imageUrlToBedrockImage(\n imageUrl: string,\n signal?: AbortSignal,\n ): Promise<any> {\n const { bytes, mimeType } = await this.imageToBytes(imageUrl, signal);\n return {\n format: this.mimeTypeToBedrockImageFormat(mimeType),\n source: { bytes },\n };\n }\n\n private async imageToDataUrl(\n image: string | Buffer,\n signal?: AbortSignal,\n ): Promise<string> {\n if (Buffer.isBuffer(image)) {\n return `data:image/png;base64,${image.toString('base64')}`;\n }\n if (image.startsWith('data:')) {\n return image;\n }\n\n const { bytes, mimeType } = await this.imageToBytes(image, signal);\n return `data:${mimeType};base64,${Buffer.from(bytes).toString('base64')}`;\n }\n\n private async imageToBase64(\n image: string | Buffer,\n signal?: AbortSignal,\n ): Promise<string> {\n if (Buffer.isBuffer(image)) {\n return image.toString('base64');\n }\n if (image.startsWith('data:')) {\n const match = image.match(/^data:([^;]+);base64,(.+)$/);\n if (!match) {\n throw new AIError(\n 'Invalid base64 data URL format',\n 'INVALID_INPUT',\n 'bedrock',\n );\n }\n return match[2];\n }\n\n const { bytes } = await this.imageToBytes(image, signal);\n return Buffer.from(bytes).toString('base64');\n }\n\n private async imageToBytes(\n image: string,\n signal?: AbortSignal,\n ): Promise<{ bytes: Uint8Array; mimeType: string }> {\n if (image.startsWith('data:')) {\n const match = image.match(/^data:([^;]+);base64,(.+)$/);\n if (!match) {\n throw new AIError(\n 'Invalid base64 data URL format',\n 'INVALID_INPUT',\n 'bedrock',\n );\n }\n\n return {\n bytes: Uint8Array.from(Buffer.from(match[2], 'base64')),\n mimeType: match[1],\n };\n }\n\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 'bedrock',\n );\n }\n\n const arrayBuffer = await response.arrayBuffer();\n return {\n bytes: new Uint8Array(arrayBuffer),\n mimeType: response.headers.get('content-type') || 'image/png',\n };\n }\n\n private mimeTypeToBedrockImageFormat(mimeType: string): string {\n if (mimeType.includes('png')) return 'png';\n if (mimeType.includes('jpeg') || mimeType.includes('jpg')) return 'jpeg';\n if (mimeType.includes('gif')) return 'gif';\n if (mimeType.includes('webp')) return 'webp';\n\n throw new AIError(\n `Unsupported image format for Bedrock: ${mimeType}`,\n 'INVALID_INPUT',\n 'bedrock',\n );\n }\n\n private resolveImageSize(options: ImageGenerationOptions): {\n width: number;\n height: number;\n } {\n if (options.size) {\n const [width, height] = options.size.split('x').map(Number);\n if (Number.isFinite(width) && Number.isFinite(height)) {\n return { width, height };\n }\n }\n\n const aspectRatioSizes: Record<string, { width: number; height: number }> =\n {\n '1:1': { width: 1024, height: 1024 },\n '2:3': { width: 768, height: 1152 },\n '3:2': { width: 1152, height: 768 },\n '3:5': { width: 768, height: 1280 },\n '5:3': { width: 1280, height: 768 },\n '7:9': { width: 896, height: 1152 },\n '9:7': { width: 1152, height: 896 },\n '6:11': { width: 768, height: 1408 },\n '11:6': { width: 1408, height: 768 },\n '5:11': { width: 640, height: 1408 },\n '11:5': { width: 1408, height: 640 },\n '9:5': { width: 1152, height: 640 },\n '16:9': { width: 1173, height: 640 },\n };\n\n return (\n aspectRatioSizes[options.aspectRatio || ''] || {\n width: 1024,\n height: 1024,\n }\n );\n }\n\n private mapImageQuality(quality?: string): string {\n if (!quality || quality === 'standard') {\n return 'standard';\n }\n\n if (quality === 'hd') {\n return 'premium';\n }\n\n return quality;\n }\n\n private safeJsonParse(input: string): any {\n try {\n return JSON.parse(input);\n } catch {\n return { rawArguments: input };\n }\n }\n\n private mapError(error: unknown): AIError {\n if (error instanceof AIError) {\n return error;\n }\n\n // Map common AWS error codes\n if (typeof error === 'object' && error !== null) {\n const awsError = error as { name?: string; message?: string };\n\n if (awsError.name === 'AccessDeniedException') {\n return new AuthenticationError('bedrock');\n }\n\n if (awsError.name === 'ThrottlingException') {\n return new RateLimitError('bedrock');\n }\n\n if (awsError.name === 'ResourceNotFoundException') {\n return new ModelNotFoundError(\n awsError.message || 'Model not found',\n 'bedrock',\n );\n }\n\n if (\n awsError.name === 'ValidationException' &&\n awsError.message?.includes('input is too long')\n ) {\n return new ContextLengthError('bedrock');\n }\n }\n\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown Bedrock error occurred';\n return new AIError(errorMessage, 'UNKNOWN_ERROR', 'bedrock');\n }\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"bifrost-fM9FpW_w.js","names":[],"sources":["../../src/shared/providers/bifrost.ts"],"sourcesContent":["import { ValidationError } from '@happyvertical/utils';\n\nimport {\n normalizeChatOptions,\n normalizeImageGenerationOptions,\n} from '../safety';\nimport type {\n AICapabilities,\n AIMessage,\n AIModel,\n AIResponse,\n BifrostOptions,\n ChatOptions,\n EmbeddingOptions,\n EmbeddingResponse,\n ImageDescriptionOptions,\n ImageEmbeddingOptions,\n ImageGenerationOptions,\n ImageGenerationResponse,\n} from '../types';\nimport {\n BifrostAdmin,\n normalizeGatewayBaseUrl,\n resolveGatewayAdminBaseUrl,\n} from './gateway-admin';\nimport { type OpenAICompatibleProfile, OpenAIProvider } from './openai';\n\nconst BIFROST_CAPABILITIES: AICapabilities = {\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 tts: false,\n voiceCloning: false,\n voiceDesign: false,\n maxContextLength: 128000,\n supportedOperations: [\n 'chat',\n 'completion',\n 'embedding',\n 'streaming',\n 'functions',\n 'vision',\n 'image_embedding',\n 'image_generation',\n ],\n};\n\nfunction isEmbeddingModel(modelId: string): boolean {\n return /embed/i.test(modelId);\n}\n\nfunction isImageEmbeddingModel(modelId: string): boolean {\n return /titan-embed-image|multimodalembedding|image[-_]?embed|clip/i.test(\n modelId,\n );\n}\n\nfunction isImageGenerationModel(modelId: string): boolean {\n return /gpt-image|dall-e|imagen|stable[-_ ]diffusion|sdxl|flux|titan-image|image-generator/i.test(\n modelId,\n );\n}\n\nfunction isFilteredBifrostModel(modelId: string): boolean {\n return /moderation|transcrib|whisper|speech|tts|rerank/i.test(modelId);\n}\n\nfunction inferBifrostContextLength(modelId: string): number {\n if (isEmbeddingModel(modelId)) return 8192;\n if (/gemini-1\\.5|gemini-2\\.0|gemini-2\\.5|gemini-3/i.test(modelId)) {\n return 1000000;\n }\n if (/claude/i.test(modelId)) return 200000;\n if (/gpt-4o|gpt-4\\.1|o1|o3|o4|llama|mistral|qwen|deepseek/i.test(modelId)) {\n return 128000;\n }\n return 32768;\n}\n\nfunction inferBifrostFunctions(modelId: string): boolean {\n if (isEmbeddingModel(modelId)) return false;\n return /gpt|claude|gemini|command|llama|mistral|qwen|deepseek|o1|o3|o4/i.test(\n modelId,\n );\n}\n\nfunction inferBifrostVision(modelId: string): boolean {\n return /gpt-4o|gpt-4\\.1|vision|claude-3|gemini|pixtral|llava|qwen.*vl|vl-/i.test(\n modelId,\n );\n}\n\nfunction inferBifrostCapabilities(modelId: string): string[] {\n if (isImageGenerationModel(modelId)) {\n return ['image_generation'];\n }\n\n if (isImageEmbeddingModel(modelId)) {\n return ['embeddings', 'image_embedding'];\n }\n\n if (isEmbeddingModel(modelId)) {\n return ['embeddings'];\n }\n\n const capabilities = ['text', 'chat'];\n\n if (inferBifrostFunctions(modelId)) {\n capabilities.push('functions');\n }\n\n if (inferBifrostVision(modelId)) {\n capabilities.push('vision');\n }\n\n return capabilities;\n}\n\nfunction ensureBifrostOptions(options: BifrostOptions): BifrostOptions {\n if (!options.baseUrl?.trim()) {\n throw new ValidationError('Bifrost baseUrl is required', {\n provider: 'bifrost',\n hint: 'Pass baseUrl like http://localhost:8080, http://localhost:8080/openai, or http://localhost:8080/v1 and optionally adminBaseUrl for governance endpoints',\n });\n }\n\n const baseUrl = normalizeGatewayBaseUrl(options.baseUrl);\n const inferenceBaseUrl = /\\/(?:openai|v1|pydanticai\\/v1)$/.test(baseUrl)\n ? baseUrl\n : `${baseUrl}/openai`;\n const headers = options.apiKey\n ? {\n ...options.headers,\n 'x-bf-vk': options.apiKey,\n 'x-api-key': options.apiKey,\n }\n : options.headers;\n\n return {\n ...options,\n baseUrl: inferenceBaseUrl,\n headers,\n };\n}\n\nconst BIFROST_PROFILE: OpenAICompatibleProfile = {\n providerLabel: 'Bifrost',\n providerName: 'bifrost',\n defaultModel: 'openai/gpt-4o-mini',\n capabilities: BIFROST_CAPABILITIES,\n describeModel: (modelId) => `Bifrost model: ${modelId}`,\n getContextLength: inferBifrostContextLength,\n getModelCapabilities: inferBifrostCapabilities,\n shouldIncludeModel: (modelId) => !isFilteredBifrostModel(modelId),\n supportsFunctions: inferBifrostFunctions,\n supportsVision: inferBifrostVision,\n};\n\ntype BifrostResolvedCapability =\n | 'chat'\n | 'vision'\n | 'embeddings'\n | 'image_generation';\n\nfunction supportsCapability(\n model: AIModel,\n capability: BifrostResolvedCapability,\n): boolean {\n if (capability === 'vision') {\n return (\n model.capabilities.includes('vision') || model.supportsVision === true\n );\n }\n\n if (capability === 'embeddings') {\n return model.capabilities.includes('embeddings');\n }\n\n if (capability === 'image_generation') {\n return model.capabilities.includes('image_generation');\n }\n\n return model.capabilities.includes('chat');\n}\n\n/**\n * Bifrost provider implementation.\n *\n * Bifrost exposes OpenAI-compatible inference and governance admin APIs. This\n * provider reuses the OpenAI-compatible transport for inference and exposes\n * `admin` for tenant project and virtual-key provisioning.\n */\nexport class BifrostProvider extends OpenAIProvider {\n readonly admin: BifrostAdmin;\n private readonly configuredDefaultModel?: string;\n private readonly resolvedModelCache = new Map<\n BifrostResolvedCapability,\n Promise<string>\n >();\n\n constructor(options: BifrostOptions) {\n const normalized = ensureBifrostOptions(options);\n super(normalized, BIFROST_PROFILE);\n const adminKey = normalized.adminApiKey || normalized.apiKey;\n const adminUsername = normalized.adminUser || normalized.adminUsername;\n this.admin = new BifrostAdmin({\n provider: 'bifrost',\n baseUrl: resolveGatewayAdminBaseUrl(\n normalized.baseUrl,\n normalized.adminUrl || normalized.adminBaseUrl,\n 'bifrost',\n ),\n apiKey: adminKey,\n username: adminUsername,\n password: normalized.adminPassword,\n headers:\n adminKey && !(adminUsername && normalized.adminPassword)\n ? {\n ...normalized.adminHeaders,\n 'x-bf-vk': adminKey,\n 'x-api-key': adminKey,\n }\n : normalized.adminHeaders,\n timeout: normalized.timeout,\n });\n this.configuredDefaultModel = normalized.defaultModel;\n }\n\n private async resolveModel(\n capability: BifrostResolvedCapability,\n explicitModel?: string,\n ): Promise<string> {\n if (explicitModel) {\n return explicitModel;\n }\n\n if (\n this.configuredDefaultModel &&\n (capability === 'chat' || capability === 'vision')\n ) {\n return this.configuredDefaultModel;\n }\n\n const cached = this.resolvedModelCache.get(capability);\n if (cached) {\n return cached;\n }\n\n const pending = this.selectModel(capability).catch((error) => {\n this.resolvedModelCache.delete(capability);\n throw error;\n });\n this.resolvedModelCache.set(capability, pending);\n return pending;\n }\n\n private async selectModel(\n capability: BifrostResolvedCapability,\n ): Promise<string> {\n const models = await super.getModels();\n const model = models.find((candidate) =>\n supportsCapability(candidate, capability),\n );\n\n if (!model) {\n throw new ValidationError(\n `No ${capability} model is available from the Bifrost gateway`,\n {\n provider: 'bifrost',\n capability,\n hint: 'Pass defaultModel explicitly or ensure the gateway returns a compatible model for this key',\n },\n );\n }\n\n return model.id;\n }\n\n async chat(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): Promise<AIResponse> {\n const safe = normalizeChatOptions(\n this.options,\n options,\n 'bifrost',\n options.model || this.options.defaultModel,\n );\n return super.chat(messages, {\n ...safe,\n model: await this.resolveModel('chat', safe.model),\n });\n }\n\n async *stream(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): AsyncIterable<string> {\n const safe = normalizeChatOptions(\n this.options,\n options,\n 'bifrost',\n options.model || this.options.defaultModel,\n );\n yield* super.stream(messages, {\n ...safe,\n model: await this.resolveModel('chat', safe.model),\n });\n }\n\n async describeImage(\n image: string | Buffer,\n prompt?: string,\n options: ImageDescriptionOptions = {},\n ): Promise<string> {\n const safe = normalizeChatOptions(\n this.options,\n options,\n 'bifrost',\n options.model || this.options.defaultModel,\n );\n return super.describeImage(image, prompt, {\n ...safe,\n model: await this.resolveModel('vision', safe.model),\n });\n }\n\n async embed(\n text: string | string[],\n options: EmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n return super.embed(text, {\n ...options,\n model: await this.resolveModel('embeddings', options.model),\n });\n }\n\n async embedImage(\n image: string | Buffer,\n options: ImageEmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n return super.embedImage(image, {\n ...options,\n model: await this.resolveModel('embeddings', options.model),\n });\n }\n\n async generateImage(\n prompt: string,\n options: ImageGenerationOptions = {},\n ): Promise<ImageGenerationResponse> {\n const safe = normalizeImageGenerationOptions(\n this.options,\n options,\n 'bifrost',\n options.model,\n );\n return super.generateImage(prompt, {\n ...safe,\n model: await this.resolveModel('image_generation', safe.model),\n });\n }\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"claude-cli-CnJh5KQT.js","names":[],"sources":["../../src/shared/providers/claude-cli.ts"],"sourcesContent":["/**\n * Claude CLI provider implementation\n *\n * Provides a standardized interface for interacting with Claude via the Claude Code CLI,\n * enabling users with Claude Max subscriptions to use their subscription instead of\n * paying for API usage. Supports chat completions and streaming responses.\n * Authentication is handled via existing Claude session or setup-token.\n *\n * **Authentication Priority:**\n * 1. ANTHROPIC_API_KEY environment variable (uses Anthropic SDK, no keychain prompts)\n * 2. Claude CLI with setup-token (for CI/CD, no keychain prompts)\n * 3. Claude CLI with keychain (may prompt for password on macOS)\n */\n\nimport { exec, spawn } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nimport type {\n AICapabilities,\n AIInterface,\n AIMessage,\n AIModel,\n AIResponse,\n ChatOptions,\n ClaudeCliOptions,\n CompletionOptions,\n EmbeddingOptions,\n EmbeddingResponse,\n ImageDescriptionOptions,\n ImageEmbeddingOptions,\n ImageGenerationOptions,\n ImageGenerationResponse,\n MessageOptions,\n TokenUsage,\n TTSOptions,\n TTSResponse,\n Voice,\n VoiceCloneOptions,\n VoiceDesignOptions,\n VoiceListOptions,\n} from '../types';\nimport {\n AIError,\n AuthenticationError,\n ContextLengthError,\n extractTextContent,\n RateLimitError,\n} from '../types';\nimport { emitUsage } from './usage';\n\nconst execAsync = promisify(exec);\n\n/**\n * Claude CLI provider implementation that shells out to the Claude Code CLI.\n * Supports chat completions, streaming, and leverages Claude Max subscription.\n * Does not support embeddings (use OpenAI or another provider for embeddings).\n *\n * If ANTHROPIC_API_KEY environment variable is set, automatically falls back to\n * using the Anthropic provider to avoid macOS keychain password prompts.\n */\nexport class ClaudeCliProvider implements AIInterface {\n private options: ClaudeCliOptions;\n private cliPath: string | null = null;\n private anthropicFallback: AIInterface | null = null;\n\n /**\n * Creates a new Claude CLI provider instance\n * @param options - Configuration options for the Claude CLI provider\n */\n constructor(options: ClaudeCliOptions) {\n this.options = {\n defaultModel: 'sonnet',\n ...options,\n };\n }\n\n /**\n * Checks if ANTHROPIC_API_KEY is available and initializes fallback provider if needed\n * @private\n */\n private async initializeFallback(): Promise<void> {\n if (this.anthropicFallback !== null) {\n return; // Already initialized\n }\n\n const apiKey = process.env.ANTHROPIC_API_KEY;\n if (!apiKey) {\n return; // No API key, will use CLI\n }\n\n // Lazy load Anthropic provider to avoid circular dependency\n const { AnthropicProvider } = await import('./anthropic.js');\n\n // Map claude-cli model names to Anthropic model IDs\n const modelMap: Record<string, string> = {\n sonnet: 'claude-3-5-sonnet-20241022',\n opus: 'claude-3-opus-20240229',\n haiku: 'claude-3-haiku-20240307',\n };\n\n const defaultModel =\n modelMap[this.options.defaultModel || 'sonnet'] ||\n 'claude-3-5-sonnet-20241022';\n\n this.anthropicFallback = new AnthropicProvider({\n type: 'anthropic',\n apiKey,\n defaultModel,\n onUsage: this.options.onUsage,\n usageTags: this.options.usageTags,\n });\n }\n\n /**\n * Finds the Claude CLI binary in PATH or uses custom cliPath\n * Does NOT execute the CLI during detection to avoid keychain prompts\n * @throws {AIError} When CLI cannot be found\n * @private\n */\n private async findCli(): Promise<string> {\n if (this.cliPath) {\n return this.cliPath;\n }\n\n // If custom path provided, check if it exists (don't execute it)\n if (this.options.cliPath) {\n const fs = await import('node:fs/promises');\n try {\n await fs.access(this.options.cliPath);\n this.cliPath = this.options.cliPath;\n return this.cliPath;\n } catch (_error) {\n throw new AIError(\n `Claude CLI not found at specified path: ${this.options.cliPath}. Set ANTHROPIC_API_KEY environment variable to avoid CLI dependency.`,\n 'CLI_NOT_FOUND',\n 'claude-cli',\n );\n }\n }\n\n // Try common installation locations first\n const commonPaths = [\n `${process.env.HOME}/.claude/local/claude`, // Default installation path\n '/usr/local/bin/claude',\n '/opt/homebrew/bin/claude',\n ];\n\n const fs = await import('node:fs/promises');\n for (const path of commonPaths) {\n try {\n await fs.access(path);\n this.cliPath = path;\n return this.cliPath;\n } catch (_error) {\n // Try next path\n }\n }\n\n // Try to find in PATH with which (doesn't execute the binary)\n try {\n const { stdout } = await execAsync('which claude');\n const path = stdout.trim();\n if (path) {\n this.cliPath = path;\n return this.cliPath;\n }\n } catch (_error) {\n // Not found\n }\n\n throw new AIError(\n 'Claude CLI not found. Set ANTHROPIC_API_KEY environment variable to use Anthropic SDK instead, or install Claude Code CLI. Visit https://docs.claude.com/en/docs/claude-code/ for installation instructions.',\n 'CLI_NOT_FOUND',\n 'claude-cli',\n );\n }\n\n /**\n * Normalizes model name to full model ID or short name\n * @private\n */\n private normalizeModel(model?: string): string {\n const m = model || this.options.defaultModel || 'sonnet';\n\n // Map short names to CLI-compatible values\n const modelMap: Record<string, string> = {\n sonnet: 'sonnet',\n opus: 'opus',\n haiku: 'haiku',\n };\n\n return modelMap[m] || m;\n }\n\n /**\n * Execute Claude CLI command and return parsed JSON output\n * @private\n */\n private async executeCommand(\n prompt: string,\n options: {\n model?: string;\n systemPrompt?: string;\n temperature?: number;\n maxTokens?: number;\n } = {},\n ): Promise<any> {\n const cliPath = await this.findCli();\n const model = this.normalizeModel(options.model);\n\n const args = ['--print', '--output-format', 'json', '--model', model];\n\n if (options.systemPrompt) {\n args.push('--system-prompt', options.systemPrompt);\n }\n\n args.push(prompt);\n\n return new Promise((resolve, reject) => {\n let stdout = '';\n let stderr = '';\n\n const child = spawn(cliPath, args, {\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n child.stdout.on('data', (data) => {\n stdout += data.toString();\n });\n\n child.stderr.on('data', (data) => {\n stderr += data.toString();\n });\n\n child.on('error', (error) => {\n reject(\n new AIError(\n `Failed to execute Claude CLI: ${error.message}`,\n 'EXECUTION_ERROR',\n 'claude-cli',\n ),\n );\n });\n\n child.on('close', (code) => {\n if (code !== 0) {\n reject(this.mapCliError(stderr, code || undefined));\n return;\n }\n\n try {\n // Parse JSON output\n const result = JSON.parse(stdout);\n resolve(result);\n } catch (_error) {\n reject(\n new AIError(\n 'Failed to parse CLI output as JSON',\n 'PARSE_ERROR',\n 'claude-cli',\n ),\n );\n }\n });\n });\n }\n\n /**\n * Execute Claude CLI command with streaming output\n * @private\n */\n private async *executeStreamingCommand(\n prompt: string,\n options: {\n model?: string;\n systemPrompt?: string;\n onProgress?: (chunk: string) => void;\n } = {},\n ): AsyncIterable<string> {\n const cliPath = await this.findCli();\n const model = this.normalizeModel(options.model);\n\n const args = [\n '--print',\n '--output-format',\n 'stream-json',\n '--verbose', // Required for stream-json format\n '--model',\n model,\n ];\n\n if (options.systemPrompt) {\n args.push('--system-prompt', options.systemPrompt);\n }\n\n args.push(prompt);\n\n const child = spawn(cliPath, args, {\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n let stderr = '';\n\n child.stderr.on('data', (data) => {\n stderr += data.toString();\n });\n\n // Process streaming JSON chunks\n let buffer = '';\n\n for await (const chunk of child.stdout) {\n buffer += chunk.toString();\n\n // Process complete JSON objects (one per line)\n const lines = buffer.split('\\n');\n buffer = lines.pop() || ''; // Keep incomplete line in buffer\n\n for (const line of lines) {\n if (line.trim()) {\n try {\n const parsed = JSON.parse(line);\n // Claude CLI stream-json format outputs complete messages\n // Look for assistant message with content\n if (parsed.type === 'assistant' && parsed.message?.content) {\n for (const contentBlock of parsed.message.content) {\n if (contentBlock.type === 'text' && contentBlock.text) {\n const text = contentBlock.text;\n if (options.onProgress) {\n options.onProgress(text);\n }\n yield text;\n }\n }\n }\n // Also handle result type for final output\n else if (parsed.type === 'result' && parsed.result) {\n const text = parsed.result;\n if (options.onProgress) {\n options.onProgress(text);\n }\n yield text;\n }\n } catch (_error) {\n // Skip malformed JSON lines\n }\n }\n }\n }\n\n // Wait for process to complete\n const exitCode = await new Promise<number>((resolve) => {\n child.on('close', (code) => resolve(code || 0));\n });\n\n if (exitCode !== 0) {\n throw this.mapCliError(stderr, exitCode);\n }\n }\n\n /**\n * Maps messages to a single prompt for CLI\n * @private\n */\n private mapMessagesToPrompt(messages: AIMessage[]): {\n prompt: string;\n systemPrompt?: string;\n } {\n let systemPrompt: string | undefined;\n const conversationParts: string[] = [];\n\n for (const message of messages) {\n const textContent = extractTextContent(message.content);\n if (message.role === 'system') {\n systemPrompt = systemPrompt\n ? `${systemPrompt}\\n\\n${textContent}`\n : textContent;\n } else if (message.role === 'user') {\n conversationParts.push(`User: ${textContent}`);\n } else if (message.role === 'assistant') {\n conversationParts.push(`Assistant: ${textContent}`);\n }\n }\n\n // If only one user message and no conversation, return it directly\n if (\n conversationParts.length === 1 &&\n conversationParts[0].startsWith('User: ')\n ) {\n return {\n prompt: conversationParts[0].substring(6), // Remove \"User: \" prefix\n systemPrompt,\n };\n }\n\n return {\n prompt: conversationParts.join('\\n\\n'),\n systemPrompt,\n };\n }\n\n /**\n * Maps CLI errors to standardized error types\n * @private\n */\n\n private mapCliError(stderr: string, exitCode?: number): AIError {\n const errorText = stderr.toLowerCase();\n\n // Authentication errors\n if (\n errorText.includes('not authenticated') ||\n errorText.includes('login required')\n ) {\n return new AuthenticationError('claude-cli');\n }\n\n // Rate limiting\n if (\n errorText.includes('rate limit') ||\n errorText.includes('too many requests')\n ) {\n return new RateLimitError('claude-cli');\n }\n\n // Context length\n if (\n errorText.includes('context length') ||\n errorText.includes('too long')\n ) {\n return new ContextLengthError('claude-cli');\n }\n\n return new AIError(\n `Claude CLI error (exit code ${exitCode}): ${stderr}`,\n 'CLI_ERROR',\n 'claude-cli',\n );\n }\n\n /**\n * Generate a chat completion using Claude CLI\n * @param messages - Array of conversation messages\n * @param options - Optional configuration for the chat completion\n * @returns Promise resolving to the AI response with content and metadata\n * @throws {AIError} When the CLI execution fails\n *\n * @example\n * ```typescript\n * const response = await provider.chat([\n * { role: 'system', content: 'You are a helpful assistant.' },\n * { role: 'user', content: 'Explain quantum computing' }\n * ], {\n * model: 'sonnet'\n * });\n * ```\n */\n async chat(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): Promise<AIResponse> {\n // Check if ANTHROPIC_API_KEY is available and use fallback if so\n await this.initializeFallback();\n if (this.anthropicFallback) {\n return this.anthropicFallback.chat(messages, options);\n }\n\n const startTime = Date.now();\n let { prompt, systemPrompt } = this.mapMessagesToPrompt(messages);\n\n // Add JSON format instruction if requested\n if (options.responseFormat?.type === 'json_object') {\n const jsonInstruction =\n '\\n\\nIMPORTANT: You must respond with valid JSON only. Do not include any explanatory text outside the JSON object.';\n systemPrompt = systemPrompt\n ? systemPrompt + jsonInstruction\n : jsonInstruction.trim();\n }\n\n const result = await this.executeCommand(prompt, {\n model: options.model,\n systemPrompt,\n temperature: options.temperature,\n maxTokens: options.maxTokens,\n });\n\n const model = options.model || this.options.defaultModel;\n const usage: TokenUsage | undefined = result.usage\n ? {\n promptTokens: result.usage.input_tokens || 0,\n completionTokens: result.usage.output_tokens || 0,\n totalTokens:\n (result.usage.input_tokens || 0) +\n (result.usage.output_tokens || 0),\n }\n : undefined;\n\n emitUsage(\n this.options,\n 'claude-cli',\n 'chat',\n model!,\n usage,\n startTime,\n options.usageTags,\n );\n\n // Parse Claude CLI JSON output\n return {\n content:\n result.result ||\n result.content ||\n result.text ||\n JSON.stringify(result),\n model,\n finishReason: result.is_error ? 'stop' : 'stop',\n usage,\n };\n }\n\n /**\n * Generate a text completion (delegates to chat)\n */\n async complete(\n prompt: string,\n options: CompletionOptions = {},\n ): Promise<AIResponse> {\n // Check if ANTHROPIC_API_KEY is available and use fallback if so\n await this.initializeFallback();\n if (this.anthropicFallback) {\n return this.anthropicFallback.complete(prompt, options);\n }\n\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 usageTags: options.usageTags,\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 // Check if ANTHROPIC_API_KEY is available and use fallback if so\n await this.initializeFallback();\n if (this.anthropicFallback) {\n return this.anthropicFallback.message(text, options);\n }\n\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 usageTags: options.usageTags,\n });\n\n return response.content;\n }\n\n /**\n * Embeddings are not supported by Claude CLI or Anthropic\n */\n async embed(\n _text: string | string[],\n _options: EmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n // Note: Even with fallback, Anthropic doesn't support embeddings\n throw new AIError(\n 'Claude CLI does not support embeddings. Use OpenAI or another provider for embeddings.',\n 'NOT_SUPPORTED',\n 'claude-cli',\n );\n }\n\n /**\n * Image embeddings are not supported by Claude CLI\n */\n async embedImage(\n _image: string | Buffer,\n _options: ImageEmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n throw new AIError(\n 'Claude CLI does not support image embeddings. Use OpenAI or Gemini.',\n 'NOT_SUPPORTED',\n 'claude-cli',\n );\n }\n\n /**\n * Image description is not yet implemented for Claude CLI\n * Note: Claude supports vision, but this would require significant implementation\n */\n async describeImage(\n _image: string | Buffer,\n _prompt?: string,\n _options: ImageDescriptionOptions = {},\n ): Promise<string> {\n throw new AIError(\n 'Image description is not yet implemented for Claude CLI. Use OpenAI or Gemini.',\n 'NOT_IMPLEMENTED',\n 'claude-cli',\n );\n }\n\n /**\n * Image generation is not supported by Claude\n */\n async generateImage(\n _prompt: string,\n _options: ImageGenerationOptions = {},\n ): Promise<ImageGenerationResponse> {\n throw new AIError(\n 'Claude does not support image generation. Use OpenAI or Gemini.',\n 'NOT_SUPPORTED',\n 'claude-cli',\n );\n }\n\n /**\n * Stream chat completion using Claude CLI\n */\n async *stream(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): AsyncIterable<string> {\n // Check if ANTHROPIC_API_KEY is available and use fallback if so\n await this.initializeFallback();\n if (this.anthropicFallback) {\n yield* this.anthropicFallback.stream(messages, options);\n return;\n }\n\n const startTime = Date.now();\n let { prompt, systemPrompt } = this.mapMessagesToPrompt(messages);\n\n // Add JSON format instruction if requested\n if (options.responseFormat?.type === 'json_object') {\n const jsonInstruction =\n '\\n\\nIMPORTANT: You must respond with valid JSON only. Do not include any explanatory text outside the JSON object.';\n systemPrompt = systemPrompt\n ? systemPrompt + jsonInstruction\n : jsonInstruction.trim();\n }\n\n yield* this.executeStreamingCommand(prompt, {\n model: options.model,\n systemPrompt,\n onProgress: options.onProgress,\n });\n\n const model = options.model || this.options.defaultModel;\n emitUsage(\n this.options,\n 'claude-cli',\n 'stream',\n model!,\n undefined,\n startTime,\n options.usageTags,\n );\n }\n\n /**\n * Count tokens in text (approximation)\n */\n async countTokens(text: string): Promise<number> {\n // Check if ANTHROPIC_API_KEY is available and use fallback if so\n await this.initializeFallback();\n if (this.anthropicFallback) {\n return this.anthropicFallback.countTokens(text);\n }\n\n // Claude uses a different tokenizer, approximate similar to Anthropic\n return Math.ceil(text.length / 3.5);\n }\n\n /**\n * Get available models (static list of Claude models)\n */\n async getModels(): Promise<AIModel[]> {\n // Check if ANTHROPIC_API_KEY is available and use fallback if so\n await this.initializeFallback();\n if (this.anthropicFallback) {\n return this.anthropicFallback.getModels();\n }\n\n return [\n {\n id: 'sonnet',\n name: 'Claude Sonnet',\n description: 'Balanced Claude model via CLI',\n contextLength: 200000,\n capabilities: ['text', 'chat', 'vision'],\n supportsFunctions: false,\n supportsVision: false,\n },\n {\n id: 'opus',\n name: 'Claude Opus',\n description: 'Most powerful Claude model via CLI',\n contextLength: 200000,\n capabilities: ['text', 'chat'],\n supportsFunctions: false,\n supportsVision: false,\n },\n {\n id: 'haiku',\n name: 'Claude Haiku',\n description: 'Fast Claude model via CLI',\n contextLength: 200000,\n capabilities: ['text', 'chat'],\n supportsFunctions: false,\n supportsVision: false,\n },\n ];\n }\n\n /**\n * Get provider capabilities\n */\n async getCapabilities(): Promise<AICapabilities> {\n // Check if ANTHROPIC_API_KEY is available and use fallback if so\n await this.initializeFallback();\n if (this.anthropicFallback) {\n return this.anthropicFallback.getCapabilities();\n }\n\n return {\n chat: true,\n completion: true,\n embeddings: false, // Claude CLI doesn't support embeddings\n streaming: true,\n functions: false, // Not supported via CLI\n vision: false, // Not supported in current CLI version\n fineTuning: false,\n imageEmbeddings: false,\n imageGeneration: false,\n tts: false,\n voiceCloning: false,\n voiceDesign: false,\n maxContextLength: 200000,\n supportedOperations: ['chat', 'completion', 'streaming'],\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 Claude CLI provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'claude-cli',\n );\n }\n\n streamSpeech(_text: string, _options?: TTSOptions): AsyncIterable<Buffer> {\n const error = new AIError(\n 'TTS streaming is not supported by Claude CLI provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'claude-cli',\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 Claude CLI provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'claude-cli',\n );\n }\n\n async designVoice(_options: VoiceDesignOptions): Promise<Voice> {\n throw new AIError(\n 'Voice design is not supported by Claude CLI provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'claude-cli',\n );\n }\n\n async getVoices(_options?: VoiceListOptions): Promise<Voice[]> {\n throw new AIError(\n 'Voice listing is not supported by Claude CLI provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'claude-cli',\n );\n }\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"gemini-Bu7Fke7c.js","names":[],"sources":["../../src/shared/providers/gemini.ts"],"sourcesContent":["/**\n * Google Gemini provider implementation\n */\n\nimport crypto from 'node:crypto';\nimport { extractRetryAfterSeconds } from '../rate-limit';\nimport {\n normalizeBaseAIOptions,\n normalizeChatOptions,\n normalizeImageGenerationOptions,\n type PreparedRequestControls,\n prepareRequestControls,\n} from '../safety';\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 Voice,\n VoiceCloneOptions,\n VoiceDesignOptions,\n VoiceListOptions,\n} from '../types';\nimport {\n AIError,\n AuthenticationError,\n extractTextContent,\n ModelNotFoundError,\n RateLimitError,\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\nexport class GeminiProvider implements AIInterface {\n private options: GeminiOptions;\n private client: any; // GoogleGenAI instance from @google/genai\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 }) => {\n this.client = new GoogleGenAI(this.buildClientConfig());\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 } = await import('@google/genai');\n this.client = new GoogleGenAI(this.buildClientConfig());\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 contents: this.messagesToGeminiFormat(messages),\n config: this.buildGenerateContentConfig(options, controls),\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: `call_${crypto.randomUUID()}`,\n type: 'function' as const,\n function: {\n name: part.functionCall.name,\n arguments: JSON.stringify(part.functionCall.args || {}),\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 });\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 });\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 * Convert an image to Gemini inline format\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 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 {\n inlineData: { mimeType, data: base64Data },\n };\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 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 contents: this.messagesToGeminiFormat(messages),\n config: this.buildGenerateContentConfig(options, controls),\n });\n\n let usage: TokenUsage | undefined;\n\n for await (const chunk of stream) {\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\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 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 ],\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 // Gemini doesn't provide detailed finish reasons, default to 'stop'\n return 'stop';\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 new RateLimitError('gemini', extractRetryAfterSeconds(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 +0,0 @@
1
- {"version":3,"file":"huggingface-B07_6wHW.js","names":[],"sources":["../../src/shared/providers/huggingface.ts"],"sourcesContent":["/**\n * Hugging Face provider implementation\n */\n\nimport {\n normalizeBaseAIOptions,\n normalizeChatOptions,\n type PreparedRequestControls,\n prepareRequestControls,\n} from '../safety';\nimport type {\n AICapabilities,\n AIInterface,\n AIMessage,\n AIModel,\n AIResponse,\n ChatOptions,\n CompletionOptions,\n EmbeddingOptions,\n EmbeddingResponse,\n HuggingFaceOptions,\n ImageDescriptionOptions,\n ImageEmbeddingOptions,\n ImageGenerationOptions,\n ImageGenerationResponse,\n MessageOptions,\n TokenUsage,\n TTSOptions,\n TTSResponse,\n Voice,\n VoiceCloneOptions,\n VoiceDesignOptions,\n VoiceListOptions,\n} from '../types';\nimport {\n AIError,\n AuthenticationError,\n ContextLengthError,\n extractTextContent,\n ModelNotFoundError,\n RateLimitError,\n} from '../types';\nimport { emitUsage } from './usage';\n\nexport class HuggingFaceProvider implements AIInterface {\n private options: HuggingFaceOptions;\n private baseUrl: string;\n\n constructor(options: HuggingFaceOptions) {\n this.options = normalizeBaseAIOptions({\n defaultModel: 'microsoft/DialoGPT-medium',\n useCache: true,\n waitForModel: true,\n ...options,\n });\n\n this.baseUrl =\n this.options.endpoint || 'https://api-inference.huggingface.co';\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 // Convert messages to a single prompt for text generation models\n const prompt = this.messagesToPrompt(messages);\n const model =\n options.model || this.options.model || this.options.defaultModel;\n options = normalizeChatOptions(\n this.options,\n options,\n 'huggingface',\n model,\n );\n controls = prepareRequestControls(this.options, options);\n\n const response = await this.makeRequest(\n `/models/${model}`,\n {\n inputs: prompt,\n parameters: {\n max_new_tokens: options.maxTokens,\n temperature: options.temperature ?? 1.0,\n top_p: options.topP ?? 1.0,\n do_sample:\n (options.temperature && options.temperature > 0) || false,\n stop_sequences: Array.isArray(options.stop)\n ? options.stop\n : options.stop\n ? [options.stop]\n : undefined,\n },\n options: {\n use_cache: this.options.useCache,\n wait_for_model: this.options.waitForModel,\n },\n },\n controls.signal,\n );\n\n if (Array.isArray(response) && response[0]?.generated_text) {\n const generatedText = response[0].generated_text;\n // Remove the input prompt from the response\n const content = generatedText.replace(prompt, '').trim();\n\n emitUsage(\n this.options,\n 'huggingface',\n 'chat',\n model!,\n undefined,\n startTime,\n options.usageTags,\n );\n\n return {\n content,\n model,\n finishReason: 'stop',\n };\n }\n\n throw new AIError(\n 'Invalid response format from Hugging Face',\n 'INVALID_RESPONSE',\n 'huggingface',\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 'huggingface',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'huggingface',\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 });\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 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 });\n\n return response.content;\n }\n\n async embed(\n text: string | string[],\n options: EmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n const startTime = Date.now();\n try {\n const input = Array.isArray(text) ? text : [text];\n const model = options.model || 'sentence-transformers/all-MiniLM-L6-v2';\n\n const response = await this.makeRequest(`/models/${model}`, {\n inputs: input,\n options: {\n use_cache: this.options.useCache,\n wait_for_model: this.options.waitForModel,\n },\n });\n\n // Handle different response formats from different embedding models\n let embeddings: number[][];\n if (Array.isArray(response) && Array.isArray(response[0])) {\n // Direct array of embeddings\n embeddings = Array.isArray(text) ? response : [response[0]];\n } else if (\n response &&\n typeof response === 'object' &&\n response.embeddings\n ) {\n // Response with embeddings property\n embeddings = response.embeddings;\n } else {\n throw new AIError(\n 'Invalid embedding response format',\n 'INVALID_RESPONSE',\n 'huggingface',\n );\n }\n\n emitUsage(\n this.options,\n 'huggingface',\n 'embed',\n model,\n undefined,\n startTime,\n options.usageTags,\n );\n\n return {\n embeddings,\n model,\n };\n } catch (error) {\n throw this.mapError(error);\n }\n }\n\n async embedImage(\n _image: string | Buffer,\n _options: ImageEmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n throw new AIError(\n 'Hugging Face image embeddings not implemented. Use OpenAI or Gemini.',\n 'NOT_IMPLEMENTED',\n 'huggingface',\n );\n }\n\n async describeImage(\n _image: string | Buffer,\n _prompt?: string,\n _options: ImageDescriptionOptions = {},\n ): Promise<string> {\n throw new AIError(\n 'Image description is not implemented for Hugging Face. Use OpenAI or Gemini.',\n 'NOT_IMPLEMENTED',\n 'huggingface',\n );\n }\n\n async generateImage(\n _prompt: string,\n _options: ImageGenerationOptions = {},\n ): Promise<ImageGenerationResponse> {\n // Note: Hugging Face has image generation models (Stable Diffusion), but we're keeping this as a stub\n throw new AIError(\n 'Image generation is not implemented for Hugging Face. Use OpenAI or Gemini.',\n 'NOT_IMPLEMENTED',\n 'huggingface',\n );\n }\n\n async *stream(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): AsyncIterable<string> {\n // Hugging Face Inference API doesn't support streaming for most models\n // Fall back to regular completion and yield the result\n const startTime = Date.now();\n const response = await this.chat(messages, {\n ...options,\n _skipUsage: true,\n } as any);\n\n // Simulate streaming by yielding chunks\n const content = response.content;\n const chunkSize = 10;\n\n for (let i = 0; i < content.length; i += chunkSize) {\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'huggingface',\n options.model,\n );\n }\n const chunk = content.slice(i, i + chunkSize);\n if (options.onProgress) {\n options.onProgress(chunk);\n }\n yield chunk;\n\n // Add small delay to simulate streaming\n await new Promise((resolve) => setTimeout(resolve, 50));\n }\n\n const model = options.model || this.options.defaultModel || 'gpt2';\n emitUsage(\n this.options,\n 'huggingface',\n 'stream',\n model,\n undefined,\n startTime,\n options.usageTags,\n );\n }\n\n async countTokens(text: string): Promise<number> {\n // Approximation - Hugging Face models use different tokenizers\n return Math.ceil(text.length / 4);\n }\n\n async getModels(): Promise<AIModel[]> {\n // Return some popular text generation models available on Hugging Face\n return [\n {\n id: 'microsoft/DialoGPT-medium',\n name: 'DialoGPT Medium',\n description: 'Conversational AI model by Microsoft',\n contextLength: 1024,\n capabilities: ['text', 'chat'],\n supportsFunctions: false,\n supportsVision: false,\n },\n {\n id: 'microsoft/DialoGPT-large',\n name: 'DialoGPT Large',\n description: 'Large conversational AI model by Microsoft',\n contextLength: 1024,\n capabilities: ['text', 'chat'],\n supportsFunctions: false,\n supportsVision: false,\n },\n {\n id: 'facebook/blenderbot-400M-distill',\n name: 'BlenderBot 400M',\n description: 'Conversational AI model by Meta',\n contextLength: 512,\n capabilities: ['text', 'chat'],\n supportsFunctions: false,\n supportsVision: false,\n },\n {\n id: 'gpt2',\n name: 'GPT-2',\n description: 'OpenAI GPT-2 model',\n contextLength: 1024,\n capabilities: ['text', 'completion'],\n supportsFunctions: false,\n supportsVision: false,\n },\n {\n id: 'sentence-transformers/all-MiniLM-L6-v2',\n name: 'All-MiniLM-L6-v2',\n description: 'Sentence embedding model',\n contextLength: 512,\n capabilities: ['embeddings'],\n supportsFunctions: false,\n supportsVision: false,\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: false, // Most HF models don't support function calling\n vision: false, // Limited vision model support\n fineTuning: true, // Via Hugging Face training API\n imageEmbeddings: false,\n imageGeneration: false, // Stable Diffusion exists but not implemented\n tts: false,\n voiceCloning: false,\n voiceDesign: false,\n maxContextLength: 2048,\n supportedOperations: ['chat', 'completion', 'embedding', 'streaming'],\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 HuggingFace provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'huggingface',\n );\n }\n\n streamSpeech(_text: string, _options?: TTSOptions): AsyncIterable<Buffer> {\n const error = new AIError(\n 'TTS streaming is not supported by HuggingFace provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'huggingface',\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 HuggingFace provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'huggingface',\n );\n }\n\n async designVoice(_options: VoiceDesignOptions): Promise<Voice> {\n throw new AIError(\n 'Voice design is not supported by HuggingFace provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'huggingface',\n );\n }\n\n async getVoices(_options?: VoiceListOptions): Promise<Voice[]> {\n throw new AIError(\n 'Voice listing is not supported by HuggingFace provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'huggingface',\n );\n }\n\n private messagesToPrompt(messages: AIMessage[]): string {\n // Convert chat messages to a single prompt format\n return `${messages\n .map((message) => {\n const textContent = extractTextContent(message.content);\n switch (message.role) {\n case 'system':\n return `System: ${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')}\\nAssistant:`;\n }\n\n private async makeRequest(\n endpoint: string,\n data: any,\n signal?: AbortSignal,\n ): Promise<any> {\n const url = `${this.baseUrl}${endpoint}`;\n\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${this.options.apiToken}`,\n 'Content-Type': 'application/json',\n ...this.options.headers,\n },\n body: JSON.stringify(data),\n signal,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`HTTP ${response.status}: ${errorText}`);\n }\n\n return response.json();\n }\n\n private mapError(error: unknown): AIError {\n if (error instanceof AIError) {\n return error;\n }\n\n const message = error instanceof Error ? error.message : 'Unknown error';\n\n // Map common HTTP status codes\n if (message.includes('401') || message.includes('Unauthorized')) {\n return new AuthenticationError('huggingface');\n }\n\n if (message.includes('429') || message.includes('rate limit')) {\n return new RateLimitError('huggingface');\n }\n\n if (message.includes('404') || message.includes('not found')) {\n return new ModelNotFoundError(message, 'huggingface');\n }\n\n if (message.includes('413') || message.includes('too large')) {\n return new ContextLengthError('huggingface');\n }\n\n return new AIError(message, 'UNKNOWN_ERROR', 'huggingface');\n }\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"litellm-D_Oo9OQ_.js","names":[],"sources":["../../src/shared/providers/litellm.ts"],"sourcesContent":["import { ValidationError } from '@happyvertical/utils';\n\nimport {\n normalizeChatOptions,\n normalizeImageGenerationOptions,\n} from '../safety';\nimport type {\n AICapabilities,\n AIMessage,\n AIModel,\n AIResponse,\n ChatOptions,\n EmbeddingOptions,\n EmbeddingResponse,\n ImageDescriptionOptions,\n ImageEmbeddingOptions,\n ImageGenerationOptions,\n ImageGenerationResponse,\n LiteLLMOptions,\n} from '../types';\nimport { LiteLLMAdmin, resolveGatewayAdminBaseUrl } from './gateway-admin';\nimport { type OpenAICompatibleProfile, OpenAIProvider } from './openai';\n\nconst LITELLM_CAPABILITIES: AICapabilities = {\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 tts: false,\n voiceCloning: false,\n voiceDesign: false,\n maxContextLength: 128000,\n supportedOperations: [\n 'chat',\n 'completion',\n 'embedding',\n 'streaming',\n 'functions',\n 'vision',\n 'image_embedding',\n 'image_generation',\n ],\n};\n\nfunction isEmbeddingModel(modelId: string): boolean {\n return /embed/i.test(modelId);\n}\n\nfunction isImageEmbeddingModel(modelId: string): boolean {\n return /titan-embed-image|multimodalembedding|image[-_]?embed|clip/i.test(\n modelId,\n );\n}\n\nfunction isImageGenerationModel(modelId: string): boolean {\n return /gpt-image|dall-e|imagen|stable[-_ ]diffusion|sdxl|flux|titan-image|image-generator/i.test(\n modelId,\n );\n}\n\nfunction isFilteredLiteLLMModel(modelId: string): boolean {\n return /moderation|transcrib|whisper|speech|tts|rerank/i.test(modelId);\n}\n\nfunction inferLiteLLMContextLength(modelId: string): number {\n if (isEmbeddingModel(modelId)) return 8192;\n if (/gemini-1\\.5|gemini-2\\.0|gemini-2\\.5|gemini-3/i.test(modelId)) {\n return 1000000;\n }\n if (/claude/i.test(modelId)) return 200000;\n if (/gpt-4o|gpt-4\\.1|o1|o3|o4|llama|mistral|qwen|deepseek/i.test(modelId)) {\n return 128000;\n }\n return 32768;\n}\n\nfunction inferLiteLLMFunctions(modelId: string): boolean {\n if (isEmbeddingModel(modelId)) return false;\n return /gpt|claude|gemini|command|llama|mistral|qwen|deepseek|o1|o3|o4/i.test(\n modelId,\n );\n}\n\nfunction inferLiteLLMVision(modelId: string): boolean {\n return /gpt-4o|gpt-4\\.1|vision|claude-3|gemini|pixtral|llava|qwen.*vl|vl-/i.test(\n modelId,\n );\n}\n\nfunction inferLiteLLMCapabilities(modelId: string): string[] {\n if (isImageGenerationModel(modelId)) {\n return ['image_generation'];\n }\n\n if (isImageEmbeddingModel(modelId)) {\n return ['embeddings', 'image_embedding'];\n }\n\n if (isEmbeddingModel(modelId)) {\n return ['embeddings'];\n }\n\n const capabilities = ['text', 'chat'];\n\n if (inferLiteLLMFunctions(modelId)) {\n capabilities.push('functions');\n }\n\n if (inferLiteLLMVision(modelId)) {\n capabilities.push('vision');\n }\n\n return capabilities;\n}\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n return baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;\n}\n\nfunction ensureLiteLLMOptions(options: LiteLLMOptions): LiteLLMOptions {\n if (!options.baseUrl?.trim()) {\n throw new ValidationError('LiteLLM baseUrl is required', {\n provider: 'litellm',\n hint: 'Pass baseUrl like https://llm.happyvertical.com/v1 or set HAVE_AI_BASE_URL / LITELLM_BASE_URL',\n });\n }\n\n return {\n ...options,\n baseUrl: normalizeBaseUrl(options.baseUrl.trim()),\n };\n}\n\nconst LITELLM_PROFILE: OpenAICompatibleProfile = {\n providerLabel: 'LiteLLM',\n providerName: 'litellm',\n defaultModel: 'gpt-4',\n capabilities: LITELLM_CAPABILITIES,\n describeModel: (modelId) => `LiteLLM model: ${modelId}`,\n getContextLength: inferLiteLLMContextLength,\n getModelCapabilities: inferLiteLLMCapabilities,\n shouldIncludeModel: (modelId) => !isFilteredLiteLLMModel(modelId),\n supportsFunctions: inferLiteLLMFunctions,\n supportsVision: inferLiteLLMVision,\n};\n\ntype LiteLLMResolvedCapability =\n | 'chat'\n | 'vision'\n | 'embeddings'\n | 'image_generation';\n\nfunction supportsCapability(\n model: AIModel,\n capability: LiteLLMResolvedCapability,\n): boolean {\n if (capability === 'vision') {\n return (\n model.capabilities.includes('vision') || model.supportsVision === true\n );\n }\n\n if (capability === 'embeddings') {\n return model.capabilities.includes('embeddings');\n }\n\n if (capability === 'image_generation') {\n return model.capabilities.includes('image_generation');\n }\n\n return model.capabilities.includes('chat');\n}\n\n/**\n * LiteLLM provider implementation.\n *\n * LiteLLM exposes an OpenAI-compatible API surface, so this provider reuses the\n * OpenAI transport while customizing provider identity, model discovery, and\n * capability heuristics for gateway-backed deployments.\n */\nexport class LiteLLMProvider extends OpenAIProvider {\n readonly admin: LiteLLMAdmin;\n private readonly configuredDefaultModel?: string;\n private readonly resolvedModelCache = new Map<\n LiteLLMResolvedCapability,\n Promise<string>\n >();\n\n constructor(options: LiteLLMOptions) {\n const normalized = ensureLiteLLMOptions(options);\n super(normalized, LITELLM_PROFILE);\n this.admin = new LiteLLMAdmin({\n provider: 'litellm',\n baseUrl: resolveGatewayAdminBaseUrl(\n normalized.baseUrl,\n normalized.adminUrl || normalized.adminBaseUrl,\n 'litellm',\n ),\n apiKey: normalized.adminApiKey || normalized.apiKey,\n headers: normalized.adminHeaders,\n timeout: normalized.timeout,\n });\n this.configuredDefaultModel = normalized.defaultModel;\n }\n\n private async resolveModel(\n capability: LiteLLMResolvedCapability,\n explicitModel?: string,\n ): Promise<string> {\n if (explicitModel) {\n return explicitModel;\n }\n\n if (\n this.configuredDefaultModel &&\n (capability === 'chat' || capability === 'vision')\n ) {\n return this.configuredDefaultModel;\n }\n\n const cached = this.resolvedModelCache.get(capability);\n if (cached) {\n return cached;\n }\n\n const pending = this.selectModel(capability).catch((error) => {\n this.resolvedModelCache.delete(capability);\n throw error;\n });\n this.resolvedModelCache.set(capability, pending);\n return pending;\n }\n\n private async selectModel(\n capability: LiteLLMResolvedCapability,\n ): Promise<string> {\n const models = await super.getModels();\n const model = models.find((candidate) =>\n supportsCapability(candidate, capability),\n );\n\n if (!model) {\n throw new ValidationError(\n `No ${capability} model is available from the LiteLLM gateway`,\n {\n provider: 'litellm',\n capability,\n hint: 'Pass defaultModel explicitly or ensure /models returns a compatible model for this key',\n },\n );\n }\n\n return model.id;\n }\n\n async chat(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): Promise<AIResponse> {\n const safe = normalizeChatOptions(\n this.options,\n options,\n 'litellm',\n options.model || this.options.defaultModel,\n );\n return super.chat(messages, {\n ...safe,\n model: await this.resolveModel('chat', safe.model),\n });\n }\n\n async *stream(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): AsyncIterable<string> {\n const safe = normalizeChatOptions(\n this.options,\n options,\n 'litellm',\n options.model || this.options.defaultModel,\n );\n yield* super.stream(messages, {\n ...safe,\n model: await this.resolveModel('chat', safe.model),\n });\n }\n\n async describeImage(\n image: string | Buffer,\n prompt?: string,\n options: ImageDescriptionOptions = {},\n ): Promise<string> {\n const safe = normalizeChatOptions(\n this.options,\n options,\n 'litellm',\n options.model || this.options.defaultModel,\n );\n return super.describeImage(image, prompt, {\n ...safe,\n model: await this.resolveModel('vision', safe.model),\n });\n }\n\n async embed(\n text: string | string[],\n options: EmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n return super.embed(text, {\n ...options,\n model: await this.resolveModel('embeddings', options.model),\n });\n }\n\n async embedImage(\n image: string | Buffer,\n options: ImageEmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n return super.embedImage(image, {\n ...options,\n model: await this.resolveModel('embeddings', options.model),\n });\n }\n\n async generateImage(\n prompt: string,\n options: ImageGenerationOptions = {},\n ): Promise<ImageGenerationResponse> {\n const safe = normalizeImageGenerationOptions(\n this.options,\n options,\n 'litellm',\n options.model,\n );\n return super.generateImage(prompt, {\n ...safe,\n model: await this.resolveModel('image_generation', safe.model),\n });\n }\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ollama-D4ksOTO8.js","names":[],"sources":["../../src/shared/providers/ollama.ts"],"sourcesContent":["/**\n * Ollama provider implementation.\n *\n * Uses Ollama's native `/api/*` endpoints for chat, completions, embeddings,\n * and model discovery, while bridging to the experimental OpenAI-compatible\n * image-generation endpoint when available.\n */\n\nimport { ValidationError } from '@happyvertical/utils';\n\nimport {\n normalizeBaseAIOptions,\n normalizeChatOptions,\n normalizeImageGenerationOptions,\n type PreparedRequestControls,\n prepareRequestControls,\n} from '../safety';\nimport type {\n AICapabilities,\n AIInterface,\n AIMessage,\n AIModel,\n AIResponse,\n ChatOptions,\n CompletionOptions,\n EmbeddingOptions,\n EmbeddingResponse,\n ImageDescriptionOptions,\n ImageEmbeddingOptions,\n ImageGenerationOptions,\n ImageGenerationResponse,\n MessageOptions,\n OllamaOptions,\n TokenUsage,\n TTSOptions,\n TTSResponse,\n Voice,\n VoiceCloneOptions,\n VoiceDesignOptions,\n VoiceListOptions,\n} from '../types';\nimport {\n AIError,\n AuthenticationError,\n ContentFilterError,\n ContextLengthError,\n extractTextContent,\n ModelNotFoundError,\n RateLimitError,\n} from '../types';\nimport { emitUsage } from './usage';\n\nconst DEFAULT_OLLAMA_HOST = 'http://localhost:11434';\n\nconst OLLAMA_CAPABILITIES: AICapabilities = {\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 tts: false,\n voiceCloning: false,\n voiceDesign: false,\n maxContextLength: 131072,\n supportedOperations: [\n 'chat',\n 'completion',\n 'embedding',\n 'streaming',\n 'functions',\n 'vision',\n 'image_embedding',\n 'image_generation',\n ],\n};\n\ntype ResolvedOllamaCapability =\n | 'chat'\n | 'vision'\n | 'embedding'\n | 'image_generation';\n\ninterface OllamaModelSummary {\n name?: string;\n model?: string;\n modified_at?: string;\n size?: number;\n details?: {\n family?: string;\n families?: string[];\n format?: string;\n parameter_size?: string;\n quantization_level?: string;\n };\n}\n\ninterface OllamaTagsResponse {\n models?: OllamaModelSummary[];\n}\n\ninterface OllamaShowResponse {\n capabilities?: string[];\n parameters?: string;\n modified_at?: string;\n details?: {\n parent_model?: string;\n format?: string;\n family?: string;\n families?: string[];\n parameter_size?: string;\n quantization_level?: string;\n };\n model_info?: Record<string, unknown>;\n}\n\ninterface OllamaToolCall {\n type?: 'function';\n function?: {\n index?: number;\n name?: string;\n arguments?: Record<string, unknown>;\n };\n}\n\ninterface OllamaMessage {\n role: 'system' | 'user' | 'assistant' | 'tool';\n content?: string;\n thinking?: string;\n images?: string[];\n tool_name?: string;\n tool_calls?: OllamaToolCall[];\n}\n\ninterface OllamaChatResponse {\n model?: string;\n message?: OllamaMessage;\n done?: boolean;\n done_reason?: string;\n prompt_eval_count?: number;\n eval_count?: number;\n}\n\ninterface OllamaGenerateResponse {\n model?: string;\n response?: string;\n thinking?: string;\n done?: boolean;\n done_reason?: string;\n prompt_eval_count?: number;\n eval_count?: number;\n}\n\ninterface OllamaEmbedResponse {\n model?: string;\n embeddings?: number[][];\n embedding?: number[];\n prompt_eval_count?: number;\n}\n\ninterface OllamaImageGenerationResponse {\n created?: number;\n data?: Array<{\n b64_json?: string;\n revised_prompt?: string;\n }>;\n}\n\nfunction stripTrailingSlash(value: string): string {\n return value.replace(/\\/+$/, '');\n}\n\nfunction normalizeHost(baseUrl?: string): string {\n const rawBase = baseUrl?.trim() || DEFAULT_OLLAMA_HOST;\n const withScheme = /^[a-z][a-z0-9+.-]*:\\/\\//i.test(rawBase)\n ? rawBase\n : `http://${rawBase}`;\n const base = stripTrailingSlash(withScheme);\n if (base.endsWith('/api')) return base.slice(0, -4);\n if (base.endsWith('/v1')) return base.slice(0, -3);\n return base;\n}\n\nfunction isEmbeddingModel(modelId: string): boolean {\n return /(?:^|[-_:/])(?:embed|embedding)|nomic-embed|mxbai-embed/i.test(\n modelId,\n );\n}\n\nfunction isImageGenerationModel(modelId: string): boolean {\n return /(?:^|[-_:/])(flux|sdxl|stable(?:[-_ ]?diffusion)?|z-image|image(?:[-_ ]?(?:turbo|gen|generator)))/i.test(\n modelId,\n );\n}\n\nfunction inferVisionSupport(\n modelId: string,\n capabilities: Set<string>,\n): boolean {\n if (capabilities.has('vision')) return true;\n return /vision|llava|bakllava|moondream|pixtral|qwen.*vl|vl-|gemma3/i.test(\n modelId,\n );\n}\n\nfunction inferFunctionSupport(\n modelId: string,\n capabilities: Set<string>,\n): boolean {\n if (\n capabilities.has('tools') ||\n capabilities.has('tool_calling') ||\n capabilities.has('function_calling')\n ) {\n return true;\n }\n\n if (isEmbeddingModel(modelId) || isImageGenerationModel(modelId)) {\n return false;\n }\n\n return /qwen|llama3|gpt-oss|mistral|deepseek|command-r|phi4/i.test(modelId);\n}\n\nfunction parseCapabilities(\n modelId: string,\n show?: OllamaShowResponse | null,\n): string[] {\n const capabilities = new Set(\n (show?.capabilities || []).map((capability) => capability.toLowerCase()),\n );\n\n if (isImageGenerationModel(modelId)) {\n return ['image_generation'];\n }\n\n if (\n capabilities.has('embedding') ||\n capabilities.has('embeddings') ||\n isEmbeddingModel(modelId)\n ) {\n return ['embeddings'];\n }\n\n const supported = new Set<string>(['text', 'chat']);\n\n if (inferVisionSupport(modelId, capabilities)) {\n supported.add('vision');\n }\n\n if (inferFunctionSupport(modelId, capabilities)) {\n supported.add('functions');\n }\n\n return [...supported];\n}\n\nfunction parseContextLength(\n modelId: string,\n show?: OllamaShowResponse | null,\n): number {\n const modelInfo = show?.model_info || {};\n\n for (const [key, value] of Object.entries(modelInfo)) {\n if (key.endsWith('.context_length') && typeof value === 'number') {\n return value;\n }\n }\n\n const numCtxMatch = show?.parameters?.match(/\\bnum_ctx\\s+(\\d+)/);\n if (numCtxMatch?.[1]) {\n return Number(numCtxMatch[1]);\n }\n\n if (isEmbeddingModel(modelId)) return 8192;\n if (/gemma3|qwen3|gpt-oss|llama3/i.test(modelId)) return 131072;\n return 32768;\n}\n\nfunction mapUsage(\n promptTokens?: number,\n completionTokens?: number,\n): TokenUsage | undefined {\n if (\n typeof promptTokens !== 'number' &&\n typeof completionTokens !== 'number'\n ) {\n return undefined;\n }\n\n const prompt = promptTokens || 0;\n const completion = completionTokens || 0;\n return {\n promptTokens: prompt,\n completionTokens: completion,\n totalTokens: prompt + completion,\n };\n}\n\nfunction mapFinishReason(reason?: string): AIResponse['finishReason'] {\n switch (reason) {\n case 'stop':\n return 'stop';\n case 'length':\n return 'length';\n case 'content_filter':\n return 'content_filter';\n default:\n return 'stop';\n }\n}\n\nfunction scoreModelForCapability(\n model: AIModel,\n capability: ResolvedOllamaCapability,\n): number {\n const id = model.id.toLowerCase();\n let score = 0;\n\n if (id.includes(':latest')) score += 6;\n if (id.includes('instruct') || id.includes('-it')) score += 6;\n if (id.startsWith('hf.co/')) score -= 8;\n if (/ocr|rerank|embed|image|diffusion|flux/.test(id)) score -= 12;\n\n switch (capability) {\n case 'vision':\n if (model.supportsVision) score += 25;\n if (/gemma4|gemma3/.test(id)) score += 12;\n if (/qwen.*vl|llava|moondream|vision/.test(id)) score += 8;\n if (/ocr/.test(id)) score -= 10;\n break;\n case 'embedding':\n if (model.capabilities.includes('embeddings')) score += 20;\n if (/nomic|mxbai|embed/.test(id)) score += 6;\n break;\n case 'image_generation':\n if (model.capabilities.includes('image_generation')) score += 20;\n if (/flux|sdxl|stable/.test(id)) score += 8;\n break;\n case 'chat':\n default:\n if (model.capabilities.includes('chat')) score += 12;\n if (model.supportsFunctions) score += 4;\n if (/llama|mistral|qwen|gemma|phi|command-r|deepseek-coder/.test(id)) {\n score += 8;\n }\n if (/gpt-oss/.test(id)) score -= 3;\n break;\n }\n\n return score;\n}\n\nexport class OllamaProvider implements AIInterface {\n private readonly options: OllamaOptions;\n private readonly host: string;\n private readonly configuredDefaultModel?: string;\n private modelListPromise?: Promise<AIModel[]>;\n private readonly modelShowCache = new Map<\n string,\n Promise<OllamaShowResponse | null>\n >();\n private readonly resolvedModelCache = new Map<\n ResolvedOllamaCapability,\n Promise<string>\n >();\n\n constructor(options: OllamaOptions) {\n this.host = normalizeHost(options.baseUrl);\n this.options = normalizeBaseAIOptions({\n ...options,\n baseUrl: this.host,\n });\n this.configuredDefaultModel = options.defaultModel;\n }\n\n private get nativeBaseUrl(): string {\n return `${this.host}/api`;\n }\n\n private get compatibilityBaseUrl(): string {\n return `${this.host}/v1`;\n }\n\n private buildHeaders(stream = false): Headers {\n const headers = new Headers(this.options.headers);\n headers.set('Content-Type', 'application/json');\n headers.set(\n 'Accept',\n stream ? 'application/x-ndjson, application/json' : 'application/json',\n );\n if (this.options.apiKey) {\n headers.set('Authorization', `Bearer ${this.options.apiKey}`);\n }\n return headers;\n }\n\n private async buildHttpError(response: Response): Promise<AIError> {\n const text = await response.text();\n const message =\n text && text.trim().length > 0\n ? text.trim()\n : `Ollama request failed with status ${response.status}`;\n\n switch (response.status) {\n case 401:\n case 403:\n return new AuthenticationError('ollama');\n case 404:\n return new ModelNotFoundError(message, 'ollama');\n case 413:\n return new ContextLengthError('ollama');\n case 429:\n return new RateLimitError('ollama');\n default:\n if (/content[_ -]?filter/i.test(message)) {\n return new ContentFilterError('ollama');\n }\n if (/context|too long|maximum context/i.test(message)) {\n return new ContextLengthError('ollama');\n }\n return new AIError(message, 'API_ERROR', 'ollama');\n }\n }\n\n private mapError(error: unknown): AIError {\n if (error instanceof AIError) {\n return error;\n }\n\n if (error instanceof Error && error.name === 'AbortError') {\n return new AIError('Ollama request timed out', 'TIMEOUT', 'ollama');\n }\n\n const message =\n error instanceof Error ? error.message : 'Unknown error occurred';\n return new AIError(message, 'UNKNOWN_ERROR', 'ollama');\n }\n\n private async requestJson<T>(\n path: string,\n body?: Record<string, unknown>,\n options: { compatibility?: boolean; signal?: AbortSignal } = {},\n ): Promise<T> {\n const baseUrl = options.compatibility\n ? this.compatibilityBaseUrl\n : this.nativeBaseUrl;\n const response = await fetch(`${baseUrl}${path}`, {\n method: body ? 'POST' : 'GET',\n headers: this.buildHeaders(),\n body: body ? JSON.stringify(body) : undefined,\n signal: options.signal,\n });\n\n if (!response.ok) {\n throw await this.buildHttpError(response);\n }\n\n return (await response.json()) as T;\n }\n\n private async requestStream(\n path: string,\n body: Record<string, unknown>,\n signal: AbortSignal,\n ): Promise<Response> {\n const response = await fetch(`${this.nativeBaseUrl}${path}`, {\n method: 'POST',\n headers: this.buildHeaders(true),\n body: JSON.stringify(body),\n signal,\n });\n\n if (!response.ok) {\n throw await this.buildHttpError(response);\n }\n\n return response;\n }\n\n private async *parseNdjson<T>(response: Response): AsyncIterable<T> {\n const reader = response.body?.getReader();\n if (!reader) {\n return;\n }\n\n const decoder = new TextDecoder();\n let buffer = '';\n\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n let newlineIndex = buffer.indexOf('\\n');\n while (newlineIndex !== -1) {\n const line = buffer.slice(0, newlineIndex).trim();\n buffer = buffer.slice(newlineIndex + 1);\n if (line) {\n yield JSON.parse(line) as T;\n }\n newlineIndex = buffer.indexOf('\\n');\n }\n }\n\n buffer += decoder.decode();\n const line = buffer.trim();\n if (line) {\n yield JSON.parse(line) as T;\n }\n }\n\n private async showModel(model: string): Promise<OllamaShowResponse | null> {\n const cached = this.modelShowCache.get(model);\n if (cached) {\n return cached;\n }\n\n const pending = this.requestJson<OllamaShowResponse>('/show', {\n model,\n verbose: false,\n }).catch((_error) => null);\n\n this.modelShowCache.set(model, pending);\n return pending;\n }\n\n private async resolveModel(\n capability: ResolvedOllamaCapability,\n explicitModel?: string,\n ): Promise<string> {\n if (explicitModel) {\n return explicitModel;\n }\n\n if (\n this.configuredDefaultModel &&\n (capability === 'chat' || capability === 'vision')\n ) {\n return this.configuredDefaultModel;\n }\n\n const cached = this.resolvedModelCache.get(capability);\n if (cached) {\n return cached;\n }\n\n const pending = this.selectModel(capability).catch((error) => {\n this.resolvedModelCache.delete(capability);\n throw error;\n });\n this.resolvedModelCache.set(capability, pending);\n return pending;\n }\n\n private async selectModel(\n capability: ResolvedOllamaCapability,\n ): Promise<string> {\n const models = await this.getModels();\n const candidates = models.filter((candidate) => {\n switch (capability) {\n case 'vision':\n return (\n candidate.capabilities.includes('vision') ||\n candidate.supportsVision === true\n );\n case 'embedding':\n return candidate.capabilities.includes('embeddings');\n case 'image_generation':\n return candidate.capabilities.includes('image_generation');\n case 'chat':\n default:\n return candidate.capabilities.includes('chat');\n }\n });\n\n const model = candidates.sort(\n (left, right) =>\n scoreModelForCapability(right, capability) -\n scoreModelForCapability(left, capability),\n )[0];\n\n if (!model) {\n throw new ValidationError(\n `No ${capability} model is available from the Ollama host`,\n {\n provider: 'ollama',\n capability,\n hint: 'Pass model/defaultModel explicitly or make sure the Ollama host has a compatible model installed',\n },\n );\n }\n\n return model.id;\n }\n\n private isVisionRequest(messages: AIMessage[]): boolean {\n return messages.some(\n (message) =>\n Array.isArray(message.content) &&\n message.content.some((part) => part.type === 'image_url'),\n );\n }\n\n private async imageToBase64Payload(\n image: string | Buffer,\n signal?: AbortSignal,\n ): Promise<string> {\n if (Buffer.isBuffer(image)) {\n return image.toString('base64');\n }\n\n if (image.startsWith('data:')) {\n const commaIndex = image.indexOf(',');\n return commaIndex === -1 ? image : image.slice(commaIndex + 1);\n }\n\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 'ollama',\n );\n }\n\n const arrayBuffer = await response.arrayBuffer();\n return Buffer.from(arrayBuffer).toString('base64');\n }\n\n private async imageToDataUrl(\n image: string | Buffer,\n signal?: AbortSignal,\n ): Promise<string> {\n if (Buffer.isBuffer(image)) {\n return `data:image/png;base64,${image.toString('base64')}`;\n }\n\n if (image.startsWith('data:')) {\n return image;\n }\n\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 'ollama',\n );\n }\n\n const contentType = response.headers.get('content-type') || 'image/png';\n const arrayBuffer = await response.arrayBuffer();\n return `data:${contentType};base64,${Buffer.from(arrayBuffer).toString('base64')}`;\n }\n\n private parseToolArguments(argumentsText?: string): Record<string, unknown> {\n if (!argumentsText) {\n return {};\n }\n\n try {\n const parsed = JSON.parse(argumentsText);\n return parsed && typeof parsed === 'object' ? parsed : {};\n } catch {\n return {};\n }\n }\n\n private async mapMessagesToOllama(\n messages: AIMessage[],\n signal?: AbortSignal,\n ): Promise<OllamaMessage[]> {\n const mappedMessages = await Promise.all(\n messages.map(async (message) => {\n const content = extractTextContent(message.content);\n const mapped: OllamaMessage = {\n role:\n message.role === 'function'\n ? 'tool'\n : (message.role as OllamaMessage['role']),\n content,\n };\n\n if (Array.isArray(message.content)) {\n const imageParts = message.content.filter(\n (part) => part.type === 'image_url',\n );\n if (imageParts.length > 0) {\n mapped.images = await Promise.all(\n imageParts.map((part) =>\n this.imageToBase64Payload(part.image_url.url, signal),\n ),\n );\n }\n }\n\n if (\n mapped.role === 'assistant' &&\n Array.isArray(message.tool_calls) &&\n message.tool_calls.length > 0\n ) {\n mapped.tool_calls = message.tool_calls.map((toolCall, index) => ({\n type: 'function',\n function: {\n index,\n name: toolCall.function.name,\n arguments: this.parseToolArguments(toolCall.function.arguments),\n },\n }));\n }\n\n if (mapped.role === 'tool' && message.name) {\n mapped.tool_name = message.name;\n }\n\n return mapped;\n }),\n );\n\n return mappedMessages;\n }\n\n private mapTools(\n tools: ChatOptions['tools'],\n toolChoice: ChatOptions['toolChoice'],\n ): Array<Record<string, unknown>> | undefined {\n if (!tools || tools.length === 0 || toolChoice === 'none') {\n return undefined;\n }\n\n const scopedTools =\n toolChoice && typeof toolChoice === 'object'\n ? tools.filter(\n (tool) => tool.function.name === toolChoice.function.name,\n )\n : tools;\n\n if (scopedTools.length === 0) {\n return undefined;\n }\n\n return scopedTools.map((tool) => ({\n type: 'function',\n function: {\n name: tool.function.name,\n description: tool.function.description,\n parameters: tool.function.parameters || { type: 'object' },\n },\n }));\n }\n\n private buildRuntimeOptions(options: {\n maxTokens?: number;\n temperature?: number;\n topP?: number;\n stop?: string | string[];\n seed?: number;\n }): Record<string, unknown> | undefined {\n const runtimeOptions: Record<string, unknown> = {};\n\n if (typeof options.maxTokens === 'number') {\n runtimeOptions.num_predict = options.maxTokens;\n }\n if (typeof options.temperature === 'number') {\n runtimeOptions.temperature = options.temperature;\n }\n if (typeof options.topP === 'number') {\n runtimeOptions.top_p = options.topP;\n }\n if (options.stop) {\n runtimeOptions.stop = Array.isArray(options.stop)\n ? options.stop\n : [options.stop];\n }\n if (typeof options.seed === 'number') {\n runtimeOptions.seed = options.seed;\n }\n\n return Object.keys(runtimeOptions).length > 0 ? runtimeOptions : undefined;\n }\n\n private mapThink(\n options: Pick<ChatOptions, 'thinkingLevel' | 'reasoning'>,\n ): boolean | string | undefined {\n if (options.reasoning?.maxTokens === 0) {\n return false;\n }\n if (options.reasoning?.effort) {\n return options.reasoning.effort === 'none'\n ? false\n : options.reasoning.effort;\n }\n if (!Object.hasOwn(options, 'thinkingLevel')) {\n return undefined;\n }\n\n return options.thinkingLevel;\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 options = normalizeChatOptions(\n this.options,\n options,\n 'ollama',\n options.model || this.options.defaultModel,\n );\n controls = prepareRequestControls(this.options, options);\n const model = await this.resolveModel(\n this.isVisionRequest(messages) ? 'vision' : 'chat',\n options.model,\n );\n\n const response = await this.requestJson<OllamaChatResponse>(\n '/chat',\n {\n model,\n messages: await this.mapMessagesToOllama(messages, controls.signal),\n stream: false,\n format:\n options.responseFormat?.type === 'json_object' ? 'json' : undefined,\n tools: this.mapTools(options.tools, options.toolChoice),\n think: this.mapThink(options),\n keep_alive: this.options.keepAlive,\n options: this.buildRuntimeOptions(options),\n },\n { signal: controls.signal },\n );\n\n const usage = mapUsage(response.prompt_eval_count, response.eval_count);\n\n emitUsage(\n this.options,\n 'ollama',\n 'chat',\n response.model || model,\n usage,\n startTime,\n options.usageTags,\n );\n\n const toolCalls =\n response.message?.tool_calls\n ?.filter((call) => call.function?.name)\n .map((call, index) => ({\n id: `${response.model || model}-tool-${index + 1}`,\n type: 'function' as const,\n function: {\n name: call.function?.name || '',\n arguments: JSON.stringify(call.function?.arguments || {}),\n },\n })) || undefined;\n\n return {\n content: response.message?.content || '',\n model: response.model || model,\n usage,\n finishReason:\n toolCalls && toolCalls.length > 0\n ? 'tool_calls'\n : mapFinishReason(response.done_reason),\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 'ollama',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'ollama',\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 const startTime = Date.now();\n let controls: PreparedRequestControls | undefined;\n try {\n options = normalizeChatOptions(\n this.options,\n options,\n 'ollama',\n options.model || this.options.defaultModel,\n );\n controls = prepareRequestControls(this.options, options);\n const model = await this.resolveModel('chat', options.model);\n const response = await this.requestJson<OllamaGenerateResponse>(\n '/generate',\n {\n model,\n prompt,\n stream: false,\n keep_alive: this.options.keepAlive,\n options: this.buildRuntimeOptions(options),\n },\n { signal: controls.signal },\n );\n\n const usage = mapUsage(response.prompt_eval_count, response.eval_count);\n\n emitUsage(\n this.options,\n 'ollama',\n 'complete',\n response.model || model,\n usage,\n startTime,\n options.usageTags,\n );\n\n return {\n content: response.response || '',\n model: response.model || model,\n usage,\n finishReason: mapFinishReason(response.done_reason),\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 'ollama',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'ollama',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n async message(text: string, options: MessageOptions = {}): Promise<string> {\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 });\n\n return response.content;\n }\n\n async embed(\n text: string | string[],\n options: EmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n const startTime = Date.now();\n try {\n const model = await this.resolveModel('embedding', options.model);\n const input = Array.isArray(text) ? text : [text];\n const response = await this.requestJson<OllamaEmbedResponse>('/embed', {\n model,\n input,\n keep_alive: this.options.keepAlive,\n });\n\n const embeddings =\n response.embeddings ||\n (response.embedding ? [response.embedding] : undefined);\n\n if (!embeddings || embeddings.length === 0) {\n throw new AIError(\n 'Invalid embedding response from Ollama',\n 'INVALID_RESPONSE',\n 'ollama',\n );\n }\n\n const usage = mapUsage(response.prompt_eval_count, 0);\n emitUsage(\n this.options,\n 'ollama',\n 'embed',\n response.model || model,\n usage,\n startTime,\n options.usageTags,\n );\n\n return {\n embeddings,\n usage,\n model: response.model || model,\n };\n } catch (error) {\n throw this.mapError(error);\n }\n }\n\n async embedImage(\n image: string | Buffer,\n options: ImageEmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n const description = await this.describeImage(\n image,\n 'Describe this image in detail for semantic embedding. Include objects, people, text, setting, colors, composition, and notable visual relationships.',\n );\n\n return this.embed(description, {\n model: options.model,\n dimensions: options.dimensions,\n user: options.user,\n });\n }\n\n async describeImage(\n image: string | Buffer,\n prompt?: string,\n options: ImageDescriptionOptions = {},\n ): Promise<string> {\n const defaultPrompt =\n 'Describe this image for a search index. Include objects, mood, lighting, and any visible text.';\n\n const imageUrl = await this.imageToDataUrl(image, options.signal);\n const response = await this.chat(\n [\n {\n role: 'user',\n content: [\n {\n type: 'text',\n text: prompt || defaultPrompt,\n },\n {\n type: 'image_url',\n image_url: {\n url: imageUrl,\n detail: options.detail || 'auto',\n },\n },\n ],\n },\n ],\n {\n model: options.model,\n maxTokens: options.maxTokens ?? 500,\n reasoning: options.reasoning || { effort: 'none', maxTokens: 0 },\n signal: options.signal,\n timeout: options.timeout,\n usageTags: options.usageTags,\n },\n );\n\n return response.content;\n }\n\n async generateImage(\n prompt: string,\n options: ImageGenerationOptions = {},\n ): Promise<ImageGenerationResponse> {\n let controls: PreparedRequestControls | undefined;\n try {\n options = normalizeImageGenerationOptions(\n this.options,\n options,\n 'ollama',\n options.model,\n );\n controls = prepareRequestControls(this.options, options);\n if (options.imageInput) {\n throw new AIError(\n 'Ollama image generation does not support imageInput in this adapter yet.',\n 'NOT_IMPLEMENTED',\n 'ollama',\n );\n }\n\n if (options.outputFormat === 'url') {\n throw new AIError(\n 'Ollama image generation only supports buffer or base64 outputs in this adapter.',\n 'NOT_SUPPORTED',\n 'ollama',\n );\n }\n\n const model = await this.resolveModel('image_generation', options.model);\n const response = await this.requestJson<OllamaImageGenerationResponse>(\n '/images/generations',\n {\n model,\n prompt,\n n: options.n,\n size: options.size || '1024x1024',\n response_format: 'b64_json',\n quality: options.quality,\n style: options.style,\n },\n { compatibility: true, signal: controls.signal },\n );\n\n const images = (response.data || []).map((item) => {\n const b64 = item.b64_json || '';\n return {\n data:\n options.outputFormat === 'base64'\n ? b64\n : Buffer.from(b64, 'base64'),\n mimeType: 'image/png',\n revisedPrompt: item.revised_prompt,\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 'ollama',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'ollama',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\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 options = normalizeChatOptions(\n this.options,\n options,\n 'ollama',\n options.model || this.options.defaultModel,\n );\n controls = prepareRequestControls(this.options, options);\n const model = await this.resolveModel(\n this.isVisionRequest(messages) ? 'vision' : 'chat',\n options.model,\n );\n\n const response = await this.requestStream(\n '/chat',\n {\n model,\n messages: await this.mapMessagesToOllama(messages, controls.signal),\n stream: true,\n format:\n options.responseFormat?.type === 'json_object' ? 'json' : undefined,\n tools: this.mapTools(options.tools, options.toolChoice),\n think: this.mapThink(options),\n keep_alive: this.options.keepAlive,\n options: this.buildRuntimeOptions(options),\n },\n controls.signal,\n );\n\n let finalUsage: TokenUsage | undefined;\n let finalModel = model;\n\n for await (const chunk of this.parseNdjson<OllamaChatResponse>(\n response,\n )) {\n if (chunk.model) {\n finalModel = chunk.model;\n }\n\n if (\n typeof chunk.message?.content === 'string' &&\n chunk.message.content\n ) {\n if (options.onProgress) {\n options.onProgress(chunk.message.content);\n }\n yield chunk.message.content;\n }\n\n if (chunk.done) {\n finalUsage = mapUsage(chunk.prompt_eval_count, chunk.eval_count);\n }\n }\n\n emitUsage(\n this.options,\n 'ollama',\n 'stream',\n finalModel,\n finalUsage,\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 'ollama',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'ollama',\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 return Math.ceil(text.length / 4);\n }\n\n async getModels(): Promise<AIModel[]> {\n if (this.modelListPromise) {\n return this.modelListPromise;\n }\n\n this.modelListPromise = (async () => {\n const response = await this.requestJson<OllamaTagsResponse>('/tags');\n const summaries = response.models || [];\n\n return Promise.all(\n summaries.map(async (summary) => {\n const modelId = summary.name || summary.model;\n if (!modelId) {\n throw new AIError(\n 'Ollama returned a model without an identifier',\n 'INVALID_RESPONSE',\n 'ollama',\n );\n }\n\n const show = await this.showModel(modelId);\n const capabilities = parseCapabilities(modelId, show);\n const vision = capabilities.includes('vision');\n const functions = capabilities.includes('functions');\n const parameterSize =\n show?.details?.parameter_size || summary.details?.parameter_size;\n const family = show?.details?.family || summary.details?.family;\n\n return {\n id: modelId,\n name: modelId,\n description:\n parameterSize || family\n ? `${family || 'Ollama'} ${parameterSize || ''}`.trim()\n : `Ollama model: ${modelId}`,\n contextLength: parseContextLength(modelId, show),\n capabilities,\n supportsFunctions: functions,\n supportsVision: vision,\n } satisfies AIModel;\n }),\n );\n })().catch((error) => {\n this.modelListPromise = undefined;\n throw this.mapError(error);\n });\n\n return this.modelListPromise;\n }\n\n async getCapabilities(): Promise<AICapabilities> {\n return { ...OLLAMA_CAPABILITIES };\n }\n\n async synthesizeSpeech(\n _text: string,\n _options?: TTSOptions,\n ): Promise<TTSResponse> {\n throw new AIError(\n 'TTS is not supported by the Ollama provider.',\n 'NOT_IMPLEMENTED',\n 'ollama',\n );\n }\n\n streamSpeech(_text: string, _options?: TTSOptions): AsyncIterable<Buffer> {\n const error = new AIError(\n 'TTS streaming is not supported by the Ollama provider.',\n 'NOT_IMPLEMENTED',\n 'ollama',\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 the Ollama provider.',\n 'NOT_IMPLEMENTED',\n 'ollama',\n );\n }\n\n async designVoice(_options: VoiceDesignOptions): Promise<Voice> {\n throw new AIError(\n 'Voice design is not supported by the Ollama provider.',\n 'NOT_IMPLEMENTED',\n 'ollama',\n );\n }\n\n async getVoices(_options?: VoiceListOptions): Promise<Voice[]> {\n throw new AIError(\n 'Voice listing is not supported by the Ollama provider.',\n 'NOT_IMPLEMENTED',\n 'ollama',\n );\n }\n}\n"],"mappings":"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"}