@happyvertical/ai 0.74.8

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 (77) hide show
  1. package/AGENT.md +33 -0
  2. package/LICENSE +7 -0
  3. package/README.md +384 -0
  4. package/dist/chunks/anthropic-BRwbhwIl.js +463 -0
  5. package/dist/chunks/anthropic-BRwbhwIl.js.map +1 -0
  6. package/dist/chunks/bedrock-Cf1xUerN.js +808 -0
  7. package/dist/chunks/bedrock-Cf1xUerN.js.map +1 -0
  8. package/dist/chunks/bifrost-3mXtQsTj.js +233 -0
  9. package/dist/chunks/bifrost-3mXtQsTj.js.map +1 -0
  10. package/dist/chunks/claude-cli-BrHRfkry.js +603 -0
  11. package/dist/chunks/claude-cli-BrHRfkry.js.map +1 -0
  12. package/dist/chunks/gateway-admin-C4GFPbZF.js +359 -0
  13. package/dist/chunks/gateway-admin-C4GFPbZF.js.map +1 -0
  14. package/dist/chunks/gemini-BfpHXDIQ.js +662 -0
  15. package/dist/chunks/gemini-BfpHXDIQ.js.map +1 -0
  16. package/dist/chunks/huggingface-280qv9iv.js +366 -0
  17. package/dist/chunks/huggingface-280qv9iv.js.map +1 -0
  18. package/dist/chunks/index-BT4thAvS.js +934 -0
  19. package/dist/chunks/index-BT4thAvS.js.map +1 -0
  20. package/dist/chunks/litellm-DhPKa_Jz.js +220 -0
  21. package/dist/chunks/litellm-DhPKa_Jz.js.map +1 -0
  22. package/dist/chunks/ollama-Di1ldur0.js +851 -0
  23. package/dist/chunks/ollama-Di1ldur0.js.map +1 -0
  24. package/dist/chunks/openai-5snI2diE.js +749 -0
  25. package/dist/chunks/openai-5snI2diE.js.map +1 -0
  26. package/dist/chunks/qwen-tts-DgPgdXxG.js +365 -0
  27. package/dist/chunks/qwen-tts-DgPgdXxG.js.map +1 -0
  28. package/dist/chunks/usage-DMWiJ2oB.js +21 -0
  29. package/dist/chunks/usage-DMWiJ2oB.js.map +1 -0
  30. package/dist/cli/claude-context.d.ts +3 -0
  31. package/dist/cli/claude-context.d.ts.map +1 -0
  32. package/dist/cli/claude-context.js +21 -0
  33. package/dist/cli/claude-context.js.map +1 -0
  34. package/dist/index.d.ts +20 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +21 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/node/factory.d.ts +27 -0
  39. package/dist/node/factory.d.ts.map +1 -0
  40. package/dist/shared/client.d.ts +410 -0
  41. package/dist/shared/client.d.ts.map +1 -0
  42. package/dist/shared/factory.d.ts +83 -0
  43. package/dist/shared/factory.d.ts.map +1 -0
  44. package/dist/shared/message.d.ts +71 -0
  45. package/dist/shared/message.d.ts.map +1 -0
  46. package/dist/shared/providers/anthropic.d.ts +82 -0
  47. package/dist/shared/providers/anthropic.d.ts.map +1 -0
  48. package/dist/shared/providers/bedrock.d.ts +49 -0
  49. package/dist/shared/providers/bedrock.d.ts.map +1 -0
  50. package/dist/shared/providers/bifrost.d.ts +25 -0
  51. package/dist/shared/providers/bifrost.d.ts.map +1 -0
  52. package/dist/shared/providers/claude-cli.d.ts +139 -0
  53. package/dist/shared/providers/claude-cli.d.ts.map +1 -0
  54. package/dist/shared/providers/gateway-admin.d.ts +35 -0
  55. package/dist/shared/providers/gateway-admin.d.ts.map +1 -0
  56. package/dist/shared/providers/gemini.d.ts +116 -0
  57. package/dist/shared/providers/gemini.d.ts.map +1 -0
  58. package/dist/shared/providers/huggingface.d.ts +33 -0
  59. package/dist/shared/providers/huggingface.d.ts.map +1 -0
  60. package/dist/shared/providers/litellm.d.ts +25 -0
  61. package/dist/shared/providers/litellm.d.ts.map +1 -0
  62. package/dist/shared/providers/ollama.d.ts +47 -0
  63. package/dist/shared/providers/ollama.d.ts.map +1 -0
  64. package/dist/shared/providers/openai.d.ts +272 -0
  65. package/dist/shared/providers/openai.d.ts.map +1 -0
  66. package/dist/shared/providers/qwen-tts.d.ts +85 -0
  67. package/dist/shared/providers/qwen-tts.d.ts.map +1 -0
  68. package/dist/shared/providers/usage.d.ts +14 -0
  69. package/dist/shared/providers/usage.d.ts.map +1 -0
  70. package/dist/shared/rate-limit.d.ts +13 -0
  71. package/dist/shared/rate-limit.d.ts.map +1 -0
  72. package/dist/shared/thread.d.ts +104 -0
  73. package/dist/shared/thread.d.ts.map +1 -0
  74. package/dist/shared/types.d.ts +1779 -0
  75. package/dist/shared/types.d.ts.map +1 -0
  76. package/metadata.json +35 -0
  77. package/package.json +62 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini-BfpHXDIQ.js","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 type {\n AICapabilities,\n AIInterface,\n AIMessage,\n AIModel,\n AIResponse,\n ChatOptions,\n CompletionOptions,\n EmbeddingOptions,\n EmbeddingResponse,\n GeminiOptions,\n GeminiThinkingLevel,\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 = {\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 };\n }\n\n // Default to Google AI Studio mode with API key\n return {\n apiKey: this.options.apiKey,\n };\n }\n\n async chat(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): Promise<AIResponse> {\n const startTime = Date.now();\n try {\n await this.ensureClient();\n\n const model = options.model || this.options.defaultModel;\n const requestConfig: Record<string, any> = {\n model,\n contents: this.messagesToGeminiFormat(messages),\n config: this.buildGenerateContentConfig(options),\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 throw this.mapError(error);\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 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 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 ): 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);\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 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 imageData = await this.imageToGeminiFormat(image);\n\n const response = await this.client.models.generateContent({\n model: options.model || this.options.defaultModel || 'gemini-2.5-flash',\n contents: [{ text: prompt || defaultPrompt }, imageData],\n config: {\n maxOutputTokens: options.maxTokens || 500,\n },\n });\n\n return response.text || '';\n } catch (error) {\n throw this.mapError(error);\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 try {\n await this.ensureClient();\n\n const model = options.model || 'imagen-3.0-generate-002';\n\n const config: Record<string, any> = {\n numberOfImages: options.n || 1,\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 throw this.mapError(error);\n }\n }\n\n async *stream(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): AsyncIterable<string> {\n const startTime = Date.now();\n try {\n await this.ensureClient();\n\n const model = options.model || this.options.defaultModel;\n const stream = await this.client.models.generateContentStream({\n model,\n contents: this.messagesToGeminiFormat(messages),\n config: this.buildGenerateContentConfig(options),\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 throw this.mapError(error);\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 /**\n * Map thinking level from our type to SDK's expected format\n * The SDK expects uppercase values: MINIMAL, LOW, MEDIUM, HIGH\n */\n private mapThinkingLevel(level: GeminiThinkingLevel): string {\n return level.toUpperCase();\n }\n\n private buildGenerateContentConfig(\n options: ChatOptions,\n ): Record<string, any> {\n const config: Record<string, any> = {\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 thinkingLevel = options.thinkingLevel || this.options.thinkingLevel;\n if (thinkingLevel || options.includeThoughts !== undefined) {\n config.thinkingConfig = {\n ...(thinkingLevel && {\n thinkingLevel: this.mapThinkingLevel(thinkingLevel),\n }),\n ...(options.includeThoughts !== undefined && {\n includeThoughts: options.includeThoughts,\n }),\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"],"names":[],"mappings":"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"}
@@ -0,0 +1,366 @@
1
+ import { A as AIError, c as extractTextContent, b as AuthenticationError, R as RateLimitError, M as ModelNotFoundError, a as ContextLengthError } from "./index-BT4thAvS.js";
2
+ import { e as emitUsage } from "./usage-DMWiJ2oB.js";
3
+ class HuggingFaceProvider {
4
+ options;
5
+ baseUrl;
6
+ constructor(options) {
7
+ this.options = {
8
+ defaultModel: "microsoft/DialoGPT-medium",
9
+ useCache: true,
10
+ waitForModel: true,
11
+ ...options
12
+ };
13
+ this.baseUrl = this.options.endpoint || "https://api-inference.huggingface.co";
14
+ }
15
+ async chat(messages, options = {}) {
16
+ const startTime = Date.now();
17
+ try {
18
+ const prompt = this.messagesToPrompt(messages);
19
+ const model = options.model || this.options.model || this.options.defaultModel;
20
+ const response = await this.makeRequest(`/models/${model}`, {
21
+ inputs: prompt,
22
+ parameters: {
23
+ max_new_tokens: options.maxTokens || 512,
24
+ temperature: options.temperature || 1,
25
+ top_p: options.topP || 1,
26
+ do_sample: options.temperature && options.temperature > 0 || false,
27
+ stop_sequences: Array.isArray(options.stop) ? options.stop : options.stop ? [options.stop] : void 0
28
+ },
29
+ options: {
30
+ use_cache: this.options.useCache,
31
+ wait_for_model: this.options.waitForModel
32
+ }
33
+ });
34
+ if (Array.isArray(response) && response[0]?.generated_text) {
35
+ const generatedText = response[0].generated_text;
36
+ const content = generatedText.replace(prompt, "").trim();
37
+ emitUsage(
38
+ this.options,
39
+ "huggingface",
40
+ "chat",
41
+ model,
42
+ void 0,
43
+ startTime,
44
+ options.usageTags
45
+ );
46
+ return {
47
+ content,
48
+ model,
49
+ finishReason: "stop"
50
+ };
51
+ }
52
+ throw new AIError(
53
+ "Invalid response format from Hugging Face",
54
+ "INVALID_RESPONSE",
55
+ "huggingface"
56
+ );
57
+ } catch (error) {
58
+ throw this.mapError(error);
59
+ }
60
+ }
61
+ async complete(prompt, options = {}) {
62
+ return this.chat([{ role: "user", content: prompt }], {
63
+ model: options.model,
64
+ maxTokens: options.maxTokens,
65
+ temperature: options.temperature,
66
+ topP: options.topP,
67
+ n: options.n,
68
+ stop: options.stop,
69
+ stream: options.stream,
70
+ onProgress: options.onProgress,
71
+ usageTags: options.usageTags
72
+ });
73
+ }
74
+ /**
75
+ * Simple message interface for single-turn interactions with optional history
76
+ *
77
+ * @param text - The message text to send
78
+ * @param options - Configuration options including history, model, etc.
79
+ * @returns Promise resolving to the response content string
80
+ */
81
+ async message(text, options = {}) {
82
+ const messages = [
83
+ ...options.history || [],
84
+ { role: options.role || "user", content: text }
85
+ ];
86
+ const response = await this.chat(messages, {
87
+ model: options.model,
88
+ maxTokens: options.maxTokens,
89
+ temperature: options.temperature,
90
+ topP: options.topP,
91
+ stop: options.stop,
92
+ stream: options.stream,
93
+ frequencyPenalty: options.frequencyPenalty,
94
+ presencePenalty: options.presencePenalty,
95
+ responseFormat: options.responseFormat,
96
+ seed: options.seed,
97
+ tools: options.tools,
98
+ toolChoice: options.toolChoice,
99
+ onProgress: options.onProgress,
100
+ usageTags: options.usageTags
101
+ });
102
+ return response.content;
103
+ }
104
+ async embed(text, options = {}) {
105
+ const startTime = Date.now();
106
+ try {
107
+ const input = Array.isArray(text) ? text : [text];
108
+ const model = options.model || "sentence-transformers/all-MiniLM-L6-v2";
109
+ const response = await this.makeRequest(`/models/${model}`, {
110
+ inputs: input,
111
+ options: {
112
+ use_cache: this.options.useCache,
113
+ wait_for_model: this.options.waitForModel
114
+ }
115
+ });
116
+ let embeddings;
117
+ if (Array.isArray(response) && Array.isArray(response[0])) {
118
+ embeddings = Array.isArray(text) ? response : [response[0]];
119
+ } else if (response && typeof response === "object" && response.embeddings) {
120
+ embeddings = response.embeddings;
121
+ } else {
122
+ throw new AIError(
123
+ "Invalid embedding response format",
124
+ "INVALID_RESPONSE",
125
+ "huggingface"
126
+ );
127
+ }
128
+ emitUsage(
129
+ this.options,
130
+ "huggingface",
131
+ "embed",
132
+ model,
133
+ void 0,
134
+ startTime,
135
+ options.usageTags
136
+ );
137
+ return {
138
+ embeddings,
139
+ model
140
+ };
141
+ } catch (error) {
142
+ throw this.mapError(error);
143
+ }
144
+ }
145
+ async embedImage(_image, _options = {}) {
146
+ throw new AIError(
147
+ "Hugging Face image embeddings not implemented. Use OpenAI or Gemini.",
148
+ "NOT_IMPLEMENTED",
149
+ "huggingface"
150
+ );
151
+ }
152
+ async describeImage(_image, _prompt, _options = {}) {
153
+ throw new AIError(
154
+ "Image description is not implemented for Hugging Face. Use OpenAI or Gemini.",
155
+ "NOT_IMPLEMENTED",
156
+ "huggingface"
157
+ );
158
+ }
159
+ async generateImage(_prompt, _options = {}) {
160
+ throw new AIError(
161
+ "Image generation is not implemented for Hugging Face. Use OpenAI or Gemini.",
162
+ "NOT_IMPLEMENTED",
163
+ "huggingface"
164
+ );
165
+ }
166
+ async *stream(messages, options = {}) {
167
+ const startTime = Date.now();
168
+ const response = await this.chat(messages, {
169
+ ...options,
170
+ _skipUsage: true
171
+ });
172
+ const content = response.content;
173
+ const chunkSize = 10;
174
+ for (let i = 0; i < content.length; i += chunkSize) {
175
+ const chunk = content.slice(i, i + chunkSize);
176
+ if (options.onProgress) {
177
+ options.onProgress(chunk);
178
+ }
179
+ yield chunk;
180
+ await new Promise((resolve) => setTimeout(resolve, 50));
181
+ }
182
+ const model = options.model || this.options.defaultModel || "gpt2";
183
+ emitUsage(
184
+ this.options,
185
+ "huggingface",
186
+ "stream",
187
+ model,
188
+ void 0,
189
+ startTime,
190
+ options.usageTags
191
+ );
192
+ }
193
+ async countTokens(text) {
194
+ return Math.ceil(text.length / 4);
195
+ }
196
+ async getModels() {
197
+ return [
198
+ {
199
+ id: "microsoft/DialoGPT-medium",
200
+ name: "DialoGPT Medium",
201
+ description: "Conversational AI model by Microsoft",
202
+ contextLength: 1024,
203
+ capabilities: ["text", "chat"],
204
+ supportsFunctions: false,
205
+ supportsVision: false
206
+ },
207
+ {
208
+ id: "microsoft/DialoGPT-large",
209
+ name: "DialoGPT Large",
210
+ description: "Large conversational AI model by Microsoft",
211
+ contextLength: 1024,
212
+ capabilities: ["text", "chat"],
213
+ supportsFunctions: false,
214
+ supportsVision: false
215
+ },
216
+ {
217
+ id: "facebook/blenderbot-400M-distill",
218
+ name: "BlenderBot 400M",
219
+ description: "Conversational AI model by Meta",
220
+ contextLength: 512,
221
+ capabilities: ["text", "chat"],
222
+ supportsFunctions: false,
223
+ supportsVision: false
224
+ },
225
+ {
226
+ id: "gpt2",
227
+ name: "GPT-2",
228
+ description: "OpenAI GPT-2 model",
229
+ contextLength: 1024,
230
+ capabilities: ["text", "completion"],
231
+ supportsFunctions: false,
232
+ supportsVision: false
233
+ },
234
+ {
235
+ id: "sentence-transformers/all-MiniLM-L6-v2",
236
+ name: "All-MiniLM-L6-v2",
237
+ description: "Sentence embedding model",
238
+ contextLength: 512,
239
+ capabilities: ["embeddings"],
240
+ supportsFunctions: false,
241
+ supportsVision: false
242
+ }
243
+ ];
244
+ }
245
+ async getCapabilities() {
246
+ return {
247
+ chat: true,
248
+ completion: true,
249
+ embeddings: true,
250
+ streaming: true,
251
+ functions: false,
252
+ // Most HF models don't support function calling
253
+ vision: false,
254
+ // Limited vision model support
255
+ fineTuning: true,
256
+ // Via Hugging Face training API
257
+ imageEmbeddings: false,
258
+ imageGeneration: false,
259
+ // Stable Diffusion exists but not implemented
260
+ tts: false,
261
+ voiceCloning: false,
262
+ voiceDesign: false,
263
+ maxContextLength: 2048,
264
+ supportedOperations: ["chat", "completion", "embedding", "streaming"]
265
+ };
266
+ }
267
+ // ============================================================================
268
+ // TTS Methods (Not supported - use Qwen3-TTS provider)
269
+ // ============================================================================
270
+ async synthesizeSpeech(_text, _options) {
271
+ throw new AIError(
272
+ "TTS is not supported by HuggingFace provider. Use Qwen3-TTS provider.",
273
+ "NOT_IMPLEMENTED",
274
+ "huggingface"
275
+ );
276
+ }
277
+ streamSpeech(_text, _options) {
278
+ const error = new AIError(
279
+ "TTS streaming is not supported by HuggingFace provider. Use Qwen3-TTS provider.",
280
+ "NOT_IMPLEMENTED",
281
+ "huggingface"
282
+ );
283
+ return {
284
+ [Symbol.asyncIterator]: () => ({
285
+ next: () => Promise.reject(error)
286
+ })
287
+ };
288
+ }
289
+ async cloneVoice(_options) {
290
+ throw new AIError(
291
+ "Voice cloning is not supported by HuggingFace provider. Use Qwen3-TTS provider.",
292
+ "NOT_IMPLEMENTED",
293
+ "huggingface"
294
+ );
295
+ }
296
+ async designVoice(_options) {
297
+ throw new AIError(
298
+ "Voice design is not supported by HuggingFace provider. Use Qwen3-TTS provider.",
299
+ "NOT_IMPLEMENTED",
300
+ "huggingface"
301
+ );
302
+ }
303
+ async getVoices(_options) {
304
+ throw new AIError(
305
+ "Voice listing is not supported by HuggingFace provider. Use Qwen3-TTS provider.",
306
+ "NOT_IMPLEMENTED",
307
+ "huggingface"
308
+ );
309
+ }
310
+ messagesToPrompt(messages) {
311
+ return `${messages.map((message) => {
312
+ const textContent = extractTextContent(message.content);
313
+ switch (message.role) {
314
+ case "system":
315
+ return `System: ${textContent}`;
316
+ case "user":
317
+ return `Human: ${textContent}`;
318
+ case "assistant":
319
+ return `Assistant: ${textContent}`;
320
+ default:
321
+ return textContent;
322
+ }
323
+ }).join("\n")}
324
+ Assistant:`;
325
+ }
326
+ async makeRequest(endpoint, data) {
327
+ const url = `${this.baseUrl}${endpoint}`;
328
+ const response = await fetch(url, {
329
+ method: "POST",
330
+ headers: {
331
+ Authorization: `Bearer ${this.options.apiToken}`,
332
+ "Content-Type": "application/json",
333
+ ...this.options.headers
334
+ },
335
+ body: JSON.stringify(data)
336
+ });
337
+ if (!response.ok) {
338
+ const errorText = await response.text();
339
+ throw new Error(`HTTP ${response.status}: ${errorText}`);
340
+ }
341
+ return response.json();
342
+ }
343
+ mapError(error) {
344
+ if (error instanceof AIError) {
345
+ return error;
346
+ }
347
+ const message = error instanceof Error ? error.message : "Unknown error";
348
+ if (message.includes("401") || message.includes("Unauthorized")) {
349
+ return new AuthenticationError("huggingface");
350
+ }
351
+ if (message.includes("429") || message.includes("rate limit")) {
352
+ return new RateLimitError("huggingface");
353
+ }
354
+ if (message.includes("404") || message.includes("not found")) {
355
+ return new ModelNotFoundError(message, "huggingface");
356
+ }
357
+ if (message.includes("413") || message.includes("too large")) {
358
+ return new ContextLengthError("huggingface");
359
+ }
360
+ return new AIError(message, "UNKNOWN_ERROR", "huggingface");
361
+ }
362
+ }
363
+ export {
364
+ HuggingFaceProvider
365
+ };
366
+ //# sourceMappingURL=huggingface-280qv9iv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"huggingface-280qv9iv.js","sources":["../../src/shared/providers/huggingface.ts"],"sourcesContent":["/**\n * Hugging Face provider implementation\n */\n\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 = {\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 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\n const response = await this.makeRequest(`/models/${model}`, {\n inputs: prompt,\n parameters: {\n max_new_tokens: options.maxTokens || 512,\n temperature: options.temperature || 1.0,\n top_p: options.topP || 1.0,\n do_sample: (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\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 throw this.mapError(error);\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 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 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 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(endpoint: string, data: any): 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 });\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"],"names":[],"mappings":";;AAsCO,MAAM,oBAA2C;AAAA,EAC9C;AAAA,EACA;AAAA,EAER,YAAY,SAA6B;AACvC,SAAK,UAAU;AAAA,MACb,cAAc;AAAA,MACd,UAAU;AAAA,MACV,cAAc;AAAA,MACd,GAAG;AAAA,IAAA;AAGL,SAAK,UACH,KAAK,QAAQ,YAAY;AAAA,EAC7B;AAAA,EAEA,MAAM,KACJ,UACA,UAAuB,IACF;AACrB,UAAM,YAAY,KAAK,IAAA;AACvB,QAAI;AAEF,YAAM,SAAS,KAAK,iBAAiB,QAAQ;AAC7C,YAAM,QACJ,QAAQ,SAAS,KAAK,QAAQ,SAAS,KAAK,QAAQ;AAEtD,YAAM,WAAW,MAAM,KAAK,YAAY,WAAW,KAAK,IAAI;AAAA,QAC1D,QAAQ;AAAA,QACR,YAAY;AAAA,UACV,gBAAgB,QAAQ,aAAa;AAAA,UACrC,aAAa,QAAQ,eAAe;AAAA,UACpC,OAAO,QAAQ,QAAQ;AAAA,UACvB,WAAY,QAAQ,eAAe,QAAQ,cAAc,KAAM;AAAA,UAC/D,gBAAgB,MAAM,QAAQ,QAAQ,IAAI,IACtC,QAAQ,OACR,QAAQ,OACN,CAAC,QAAQ,IAAI,IACb;AAAA,QAAA;AAAA,QAER,SAAS;AAAA,UACP,WAAW,KAAK,QAAQ;AAAA,UACxB,gBAAgB,KAAK,QAAQ;AAAA,QAAA;AAAA,MAC/B,CACD;AAED,UAAI,MAAM,QAAQ,QAAQ,KAAK,SAAS,CAAC,GAAG,gBAAgB;AAC1D,cAAM,gBAAgB,SAAS,CAAC,EAAE;AAElC,cAAM,UAAU,cAAc,QAAQ,QAAQ,EAAE,EAAE,KAAA;AAElD;AAAA,UACE,KAAK;AAAA,UACL;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,QAAQ;AAAA,QAAA;AAGV,eAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA,cAAc;AAAA,QAAA;AAAA,MAElB;AAEA,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,IAEJ,SAAS,OAAO;AACd,YAAM,KAAK,SAAS,KAAK;AAAA,IAC3B;AAAA,EACF;AAAA,EAEA,MAAM,SACJ,QACA,UAA6B,IACR;AACrB,WAAO,KAAK,KAAK,CAAC,EAAE,MAAM,QAAQ,SAAS,OAAA,CAAQ,GAAG;AAAA,MACpD,OAAO,QAAQ;AAAA,MACf,WAAW,QAAQ;AAAA,MACnB,aAAa,QAAQ;AAAA,MACrB,MAAM,QAAQ;AAAA,MACd,GAAG,QAAQ;AAAA,MACX,MAAM,QAAQ;AAAA,MACd,QAAQ,QAAQ;AAAA,MAChB,YAAY,QAAQ;AAAA,MACpB,WAAW,QAAQ;AAAA,IAAA,CACpB;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAQ,MAAc,UAA0B,IAAqB;AAEzE,UAAM,WAAwB;AAAA,MAC5B,GAAI,QAAQ,WAAW,CAAA;AAAA,MACvB,EAAE,MAAM,QAAQ,QAAQ,QAAQ,SAAS,KAAA;AAAA,IAAK;AAGhD,UAAM,WAAW,MAAM,KAAK,KAAK,UAAU;AAAA,MACzC,OAAO,QAAQ;AAAA,MACf,WAAW,QAAQ;AAAA,MACnB,aAAa,QAAQ;AAAA,MACrB,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ;AAAA,MACd,QAAQ,QAAQ;AAAA,MAChB,kBAAkB,QAAQ;AAAA,MAC1B,iBAAiB,QAAQ;AAAA,MACzB,gBAAgB,QAAQ;AAAA,MACxB,MAAM,QAAQ;AAAA,MACd,OAAO,QAAQ;AAAA,MACf,YAAY,QAAQ;AAAA,MACpB,YAAY,QAAQ;AAAA,MACpB,WAAW,QAAQ;AAAA,IAAA,CACpB;AAED,WAAO,SAAS;AAAA,EAClB;AAAA,EAEA,MAAM,MACJ,MACA,UAA4B,IACA;AAC5B,UAAM,YAAY,KAAK,IAAA;AACvB,QAAI;AACF,YAAM,QAAQ,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,IAAI;AAChD,YAAM,QAAQ,QAAQ,SAAS;AAE/B,YAAM,WAAW,MAAM,KAAK,YAAY,WAAW,KAAK,IAAI;AAAA,QAC1D,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,WAAW,KAAK,QAAQ;AAAA,UACxB,gBAAgB,KAAK,QAAQ;AAAA,QAAA;AAAA,MAC/B,CACD;AAGD,UAAI;AACJ,UAAI,MAAM,QAAQ,QAAQ,KAAK,MAAM,QAAQ,SAAS,CAAC,CAAC,GAAG;AAEzD,qBAAa,MAAM,QAAQ,IAAI,IAAI,WAAW,CAAC,SAAS,CAAC,CAAC;AAAA,MAC5D,WACE,YACA,OAAO,aAAa,YACpB,SAAS,YACT;AAEA,qBAAa,SAAS;AAAA,MACxB,OAAO;AACL,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAAA,MAEJ;AAEA;AAAA,QACE,KAAK;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,MAAA;AAGV,aAAO;AAAA,QACL;AAAA,QACA;AAAA,MAAA;AAAA,IAEJ,SAAS,OAAO;AACd,YAAM,KAAK,SAAS,KAAK;AAAA,IAC3B;AAAA,EACF;AAAA,EAEA,MAAM,WACJ,QACA,WAAkC,IACN;AAC5B,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEA,MAAM,cACJ,QACA,SACA,WAAoC,CAAA,GACnB;AACjB,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEA,MAAM,cACJ,SACA,WAAmC,IACD;AAElC,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEA,OAAO,OACL,UACA,UAAuB,IACA;AAGvB,UAAM,YAAY,KAAK,IAAA;AACvB,UAAM,WAAW,MAAM,KAAK,KAAK,UAAU;AAAA,MACzC,GAAG;AAAA,MACH,YAAY;AAAA,IAAA,CACN;AAGR,UAAM,UAAU,SAAS;AACzB,UAAM,YAAY;AAElB,aAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK,WAAW;AAClD,YAAM,QAAQ,QAAQ,MAAM,GAAG,IAAI,SAAS;AAC5C,UAAI,QAAQ,YAAY;AACtB,gBAAQ,WAAW,KAAK;AAAA,MAC1B;AACA,YAAM;AAGN,YAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AAAA,IACxD;AAEA,UAAM,QAAQ,QAAQ,SAAS,KAAK,QAAQ,gBAAgB;AAC5D;AAAA,MACE,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,IAAA;AAAA,EAEZ;AAAA,EAEA,MAAM,YAAY,MAA+B;AAE/C,WAAO,KAAK,KAAK,KAAK,SAAS,CAAC;AAAA,EAClC;AAAA,EAEA,MAAM,YAAgC;AAEpC,WAAO;AAAA,MACL;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,aAAa;AAAA,QACb,eAAe;AAAA,QACf,cAAc,CAAC,QAAQ,MAAM;AAAA,QAC7B,mBAAmB;AAAA,QACnB,gBAAgB;AAAA,MAAA;AAAA,MAElB;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,aAAa;AAAA,QACb,eAAe;AAAA,QACf,cAAc,CAAC,QAAQ,MAAM;AAAA,QAC7B,mBAAmB;AAAA,QACnB,gBAAgB;AAAA,MAAA;AAAA,MAElB;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,aAAa;AAAA,QACb,eAAe;AAAA,QACf,cAAc,CAAC,QAAQ,MAAM;AAAA,QAC7B,mBAAmB;AAAA,QACnB,gBAAgB;AAAA,MAAA;AAAA,MAElB;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,aAAa;AAAA,QACb,eAAe;AAAA,QACf,cAAc,CAAC,QAAQ,YAAY;AAAA,QACnC,mBAAmB;AAAA,QACnB,gBAAgB;AAAA,MAAA;AAAA,MAElB;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,aAAa;AAAA,QACb,eAAe;AAAA,QACf,cAAc,CAAC,YAAY;AAAA,QAC3B,mBAAmB;AAAA,QACnB,gBAAgB;AAAA,MAAA;AAAA,IAClB;AAAA,EAEJ;AAAA,EAEA,MAAM,kBAA2C;AAC/C,WAAO;AAAA,MACL,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,WAAW;AAAA;AAAA,MACX,QAAQ;AAAA;AAAA,MACR,YAAY;AAAA;AAAA,MACZ,iBAAiB;AAAA,MACjB,iBAAiB;AAAA;AAAA,MACjB,KAAK;AAAA,MACL,cAAc;AAAA,MACd,aAAa;AAAA,MACb,kBAAkB;AAAA,MAClB,qBAAqB,CAAC,QAAQ,cAAc,aAAa,WAAW;AAAA,IAAA;AAAA,EAExE;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,iBACJ,OACA,UACsB;AACtB,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEA,aAAa,OAAe,UAA8C;AACxE,UAAM,QAAQ,IAAI;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAEF,WAAO;AAAA,MACL,CAAC,OAAO,aAAa,GAAG,OAAO;AAAA,QAC7B,MAAM,MAAM,QAAQ,OAAO,KAAK;AAAA,MAAA;AAAA,IAClC;AAAA,EAEJ;AAAA,EAEA,MAAM,WAAW,UAA6C;AAC5D,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEA,MAAM,YAAY,UAA8C;AAC9D,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEA,MAAM,UAAU,UAA+C;AAC7D,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEQ,iBAAiB,UAA+B;AAEtD,WAAO,GAAG,SACP,IAAI,CAAC,YAAY;AAChB,YAAM,cAAc,mBAAmB,QAAQ,OAAO;AACtD,cAAQ,QAAQ,MAAA;AAAA,QACd,KAAK;AACH,iBAAO,WAAW,WAAW;AAAA,QAC/B,KAAK;AACH,iBAAO,UAAU,WAAW;AAAA,QAC9B,KAAK;AACH,iBAAO,cAAc,WAAW;AAAA,QAClC;AACE,iBAAO;AAAA,MAAA;AAAA,IAEb,CAAC,EACA,KAAK,IAAI,CAAC;AAAA;AAAA,EACf;AAAA,EAEA,MAAc,YAAY,UAAkB,MAAyB;AACnE,UAAM,MAAM,GAAG,KAAK,OAAO,GAAG,QAAQ;AAEtC,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,eAAe,UAAU,KAAK,QAAQ,QAAQ;AAAA,QAC9C,gBAAgB;AAAA,QAChB,GAAG,KAAK,QAAQ;AAAA,MAAA;AAAA,MAElB,MAAM,KAAK,UAAU,IAAI;AAAA,IAAA,CAC1B;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,YAAY,MAAM,SAAS,KAAA;AACjC,YAAM,IAAI,MAAM,QAAQ,SAAS,MAAM,KAAK,SAAS,EAAE;AAAA,IACzD;AAEA,WAAO,SAAS,KAAA;AAAA,EAClB;AAAA,EAEQ,SAAS,OAAyB;AACxC,QAAI,iBAAiB,SAAS;AAC5B,aAAO;AAAA,IACT;AAEA,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AAGzD,QAAI,QAAQ,SAAS,KAAK,KAAK,QAAQ,SAAS,cAAc,GAAG;AAC/D,aAAO,IAAI,oBAAoB,aAAa;AAAA,IAC9C;AAEA,QAAI,QAAQ,SAAS,KAAK,KAAK,QAAQ,SAAS,YAAY,GAAG;AAC7D,aAAO,IAAI,eAAe,aAAa;AAAA,IACzC;AAEA,QAAI,QAAQ,SAAS,KAAK,KAAK,QAAQ,SAAS,WAAW,GAAG;AAC5D,aAAO,IAAI,mBAAmB,SAAS,aAAa;AAAA,IACtD;AAEA,QAAI,QAAQ,SAAS,KAAK,KAAK,QAAQ,SAAS,WAAW,GAAG;AAC5D,aAAO,IAAI,mBAAmB,aAAa;AAAA,IAC7C;AAEA,WAAO,IAAI,QAAQ,SAAS,iBAAiB,aAAa;AAAA,EAC5D;AACF;"}