@contentgrowth/llm-service 0.8.2 → 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1527 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +529 -0
- package/dist/index.d.ts +529 -0
- package/dist/index.js +1478 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +3 -0
- package/dist/ui/react/components/index.cjs +1386 -0
- package/dist/ui/react/components/index.cjs.map +1 -0
- package/dist/ui/react/components/index.d.cts +291 -0
- package/dist/ui/react/components/index.d.ts +291 -0
- package/dist/ui/react/components/index.js +1344 -0
- package/dist/ui/react/components/index.js.map +1 -0
- package/package.json +46 -10
- package/src/index.js +0 -9
- package/src/llm/config-manager.js +0 -45
- package/src/llm/config-provider.js +0 -140
- package/src/llm/json-utils.js +0 -147
- package/src/llm/providers/base-provider.js +0 -134
- package/src/llm/providers/gemini-provider.js +0 -607
- package/src/llm/providers/openai-provider.js +0 -203
- package/src/llm-service.js +0 -281
- package/src/utils/error-handler.js +0 -117
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.js","../src/llm/config-provider.js","../src/llm/config-manager.js","../src/llm/providers/openai-provider.js","../src/llm/providers/base-provider.js","../src/llm/json-utils.js","../src/llm/providers/gemini-provider.js","../src/llm-service.js","../src/utils/error-handler.js","../src/transcription-service.js","../src/handlers/speech-handler.js"],"sourcesContent":["export { LLMService, LLMServiceException } from './llm-service.js';\nexport { ConfigManager } from './llm/config-manager.js';\nexport { BaseConfigProvider, DefaultConfigProvider } from './llm/config-provider.js';\nexport { MODEL_CONFIGS } from './llm/config-manager.js';\nexport { OpenAIProvider } from './llm/providers/openai-provider.js';\nexport { GeminiProvider } from './llm/providers/gemini-provider.js';\nexport { extractJsonFromResponse, extractTextAndJson } from './llm/json-utils.js';\nexport { FINISH_REASONS } from './llm/providers/base-provider.js';\nexport { handleApiError, sanitizeError } from './utils/error-handler.js';\n\n// Export Transcription Service\nexport { TranscriptionService, TranscriptionServiceException } from './transcription-service.js';\nexport { createSpeechHandler } from './handlers/speech-handler.js';\n","import { MODEL_CONFIGS } from './config-manager.js';\n\n/**\n * Abstract base class for Config Providers.\n */\nexport class BaseConfigProvider {\n /**\n * Retrieve configuration for a specific tenant.\n * @param {string} tenantId \n * @param {Object} env \n * @returns {Promise<Object>} Configuration object\n */\n async getConfig(tenantId, env) {\n throw new Error('Method not implemented');\n }\n}\n\n/**\n * Default implementation using Cloudflare KV and Durable Objects.\n */\nexport class DefaultConfigProvider extends BaseConfigProvider {\n async getConfig(tenantId, env) {\n if (!tenantId) {\n return this._getSystemConfig(env);\n }\n\n // Layer 1: Try KV cache first (1hr TTL)\n const cacheKey = `tenant:${tenantId}:llm_config`;\n const cached = await env.TENANT_LLM_CONFIG?.get(cacheKey);\n\n if (cached !== null && cached !== undefined) {\n // Negative cache: empty object means \"no BYOK\"\n if (cached === '{}') {\n // console.log(`[ConfigManager] KV negative cache hit for tenant ${tenantId}`);\n return this._getSystemConfig(env);\n }\n\n const config = JSON.parse(cached);\n // console.log(`[ConfigManager] KV cache hit for tenant ${tenantId}`);\n return this._buildTenantConfig(config, env);\n }\n\n // Layer 2: KV miss - load from TenantDO (which loads from D1 if needed)\n // console.log(`[ConfigManager] KV miss, loading from TenantDO for tenant ${tenantId}`);\n const tenantConfig = await this._loadFromTenantDO(tenantId, env);\n\n if (tenantConfig && tenantConfig.enabled && tenantConfig.api_key) {\n // Cache the config with 1hr TTL\n if (env.TENANT_LLM_CONFIG) {\n await env.TENANT_LLM_CONFIG.put(\n cacheKey,\n JSON.stringify(tenantConfig),\n { expirationTtl: 3600 } // 1 hour\n );\n }\n // console.log(`[ConfigManager] Using BYOK for tenant ${tenantId} (${tenantConfig.provider})`);\n return this._buildTenantConfig(tenantConfig, env);\n } else {\n // Negative cache: user doesn't have BYOK\n if (env.TENANT_LLM_CONFIG) {\n await env.TENANT_LLM_CONFIG.put(\n cacheKey,\n '{}',\n { expirationTtl: 3600 } // 1 hour\n );\n }\n // console.log(`[ConfigManager] No BYOK for tenant ${tenantId}, using system config`);\n return this._getSystemConfig(env);\n }\n }\n\n async _loadFromTenantDO(tenantId, env) {\n try {\n if (!env.TENANT_DO) return null;\n\n const doId = env.TENANT_DO.idFromName(tenantId);\n const stub = env.TENANT_DO.get(doId);\n const response = await stub.fetch(new Request(`http://do/llm-config/${tenantId}`));\n\n if (response.ok) {\n const config = await response.json();\n return config; // May be null if no config\n }\n return null;\n } catch (error) {\n console.error(`[ConfigManager] Failed to load from TenantDO for tenant ${tenantId}:`, error);\n return null;\n }\n }\n\n _buildTenantConfig(tenantConfig, env) {\n return {\n provider: tenantConfig.provider,\n apiKey: tenantConfig.api_key,\n models: MODEL_CONFIGS[tenantConfig.provider],\n temperature: parseFloat(env.DEFAULT_TEMPERATURE || '0.7'),\n maxTokens: parseInt(env.DEFAULT_MAX_TOKENS || '16384'),\n capabilities: tenantConfig.capabilities || { chat: true, image: false, video: false },\n isTenantOwned: true\n };\n }\n\n _getSystemConfig(env) {\n const provider = env.LLM_PROVIDER?.toLowerCase() || 'openai';\n const providerDefaults = MODEL_CONFIGS[provider] || MODEL_CONFIGS['openai'];\n\n let apiKey;\n let models = { ...providerDefaults };\n\n if (provider === 'openai') {\n apiKey = env.OPENAI_API_KEY;\n models = {\n default: env.OPENAI_MODEL || providerDefaults.default,\n edge: env.OPENAI_MODEL_EDGE || providerDefaults.edge,\n fast: env.OPENAI_MODEL_FAST || providerDefaults.fast,\n cost: env.OPENAI_MODEL_COST || providerDefaults.cost,\n free: env.OPENAI_MODEL_FREE || providerDefaults.free,\n };\n } else if (provider === 'gemini') {\n apiKey = env.GEMINI_API_KEY;\n models = {\n default: env.GEMINI_MODEL || providerDefaults.default,\n edge: env.GEMINI_MODEL_EDGE || providerDefaults.edge,\n fast: env.GEMINI_MODEL_FAST || providerDefaults.fast,\n cost: env.GEMINI_MODEL_COST || providerDefaults.cost,\n free: env.GEMINI_MODEL_FREE || providerDefaults.free,\n image: env.GEMINI_IMAGE_MODEL || providerDefaults.image,\n video: env.GEMINI_VIDEO_MODEL || providerDefaults.video,\n };\n }\n\n return {\n provider,\n apiKey,\n models,\n temperature: parseFloat(env.DEFAULT_TEMPERATURE || '0.7'),\n maxTokens: parseInt(env.DEFAULT_MAX_TOKENS || '16384'),\n };\n }\n}\n","/**\n * Manages LLM configuration resolution.\n * Prioritizes Tenant KV config over System Environment config.\n */\n\n\n\nimport { DefaultConfigProvider } from './config-provider.js';\n\nexport const MODEL_CONFIGS = {\n openai: {\n default: 'gpt-4o',\n edge: 'gpt-4o',\n fast: 'gpt-4o-mini',\n cost: 'gpt-4o-mini',\n free: 'gpt-4o-mini',\n },\n gemini: {\n default: 'gemini-3-flash-preview', // 'gemini-2.5-flash',\n edge: 'gemini-3-pro-preview', // 'gemini-2.5-pro',\n fast: 'gemini-3-flash-preview', // 'gemini-2.5-flash-lite',\n cost: 'gemini-3-flash-preview', // 'gemini-2.5-flash-lite',\n free: 'gemini-3-flash-preview', // 'gemini-2.0-flash-lite',\n video: 'veo',\n image: 'gemini-3-pro-image-preview', // Default image generation model\n },\n};\n\n\nexport class ConfigManager {\n static _provider = new DefaultConfigProvider();\n\n /**\n * Set a custom configuration provider.\n * @param {BaseConfigProvider} provider \n */\n static setConfigProvider(provider) {\n this._provider = provider;\n }\n\n static async getConfig(tenantId, env) {\n return this._provider.getConfig(tenantId, env);\n }\n}\n\n","import OpenAI from 'openai';\nimport { BaseLLMProvider } from './base-provider.js';\nimport { extractJsonFromResponse } from '../json-utils.js';\nimport { LLMServiceException } from '../../llm-service.js';\n\nexport class OpenAIProvider extends BaseLLMProvider {\n constructor(config) {\n super(config);\n this.client = new OpenAI({ apiKey: config.apiKey });\n this.models = config.models;\n this.defaultModel = config.models.default;\n }\n\n async chat(userMessage, systemPrompt = '', options = {}) {\n const messages = [{ role: 'user', content: userMessage }];\n const tier = options.tier || 'default';\n const effectiveModel = this._getModelForTier(tier);\n const effectiveMaxTokens = options.maxTokens || this.config.maxTokens;\n const effectiveTemperature = options.temperature !== undefined ? options.temperature : this.config.temperature;\n\n const response = await this._chatCompletionWithModel(\n messages,\n systemPrompt,\n null,\n effectiveModel,\n effectiveMaxTokens,\n effectiveTemperature\n );\n return { text: response.content };\n }\n\n async chatCompletion(messages, systemPrompt, tools = null, options = {}) {\n return this._chatCompletionWithModel(\n messages,\n systemPrompt,\n tools,\n this.defaultModel,\n this.config.maxTokens,\n this.config.temperature,\n options\n );\n }\n\n async _chatCompletionWithModel(messages, systemPrompt, tools, modelName, maxTokens, temperature, options = {}) {\n const requestPayload = {\n model: modelName,\n temperature: options.temperature ?? temperature,\n max_tokens: options.maxTokens ?? maxTokens,\n messages: [{ role: 'system', content: systemPrompt }, ...messages],\n tools: tools,\n tool_choice: tools ? 'auto' : undefined,\n };\n\n // Add JSON mode support if requested\n if (options.responseFormat) {\n requestPayload.response_format = this._buildResponseFormat(options);\n }\n\n let response;\n try {\n response = await this.client.chat.completions.create(requestPayload);\n } catch (error) {\n console.error(`[OpenAIProvider] chat completion failed (API Key: ${this._getMaskedApiKey()}):`, error);\n throw error;\n }\n const message = response.choices[0].message;\n\n // Validate that we have EITHER content OR tool calls\n if (!message.content && (!message.tool_calls || message.tool_calls.length === 0)) {\n console.error('[OpenAIProvider] Model returned empty response (no text, no tool calls)');\n throw new LLMServiceException(\n 'Model returned empty response. This usually means the prompt or schema is confusing the model.',\n 500\n );\n }\n\n // Normalize the finish reason to standard value for consistent handling\n const rawFinishReason = response.choices[0].finish_reason;\n const normalizedFinishReason = this.normalizeFinishReason(rawFinishReason);\n\n // Return with parsed JSON if applicable\n return {\n content: message.content,\n tool_calls: message.tool_calls,\n finishReason: normalizedFinishReason, // Standardized: 'completed', 'truncated', etc.\n _rawFinishReason: rawFinishReason, // Keep original for debugging\n // Add metadata about response format\n _responseFormat: options.responseFormat,\n // Auto-parse JSON if requested\n ...(options.responseFormat && this._shouldAutoParse(options) ? {\n parsedContent: this._safeJsonParse(message.content)\n } : {})\n };\n }\n\n _buildResponseFormat(options) {\n if (!options.responseFormat) {\n return undefined;\n }\n\n // Handle responseFormat as either string or object { type, schema }\n const formatType = typeof options.responseFormat === 'string'\n ? options.responseFormat\n : options.responseFormat.type;\n\n const schema = typeof options.responseFormat === 'object'\n ? options.responseFormat.schema\n : options.responseSchema || null;\n\n switch (formatType) {\n case 'json':\n // If schema is provided, use strict mode; otherwise use legacy json_object\n if (schema) {\n console.log('[OpenAIProvider] Using Strict JSON mode with schema');\n return {\n type: 'json_schema',\n json_schema: {\n name: options.schemaName || 'response_schema',\n strict: options.strictSchema ?? true,\n schema: schema\n }\n };\n } else {\n console.warn('[OpenAIProvider] Using legacy json_object mode without schema - may produce markdown wrappers');\n return { type: 'json_object' };\n }\n\n case 'json_schema':\n if (!schema) {\n throw new Error('responseSchema required when using json_schema format');\n }\n console.log('[OpenAIProvider] Using Strict JSON mode with schema');\n return {\n type: 'json_schema',\n json_schema: {\n name: options.schemaName || 'response_schema',\n strict: options.strictSchema ?? true,\n schema: schema\n }\n };\n\n default:\n return undefined;\n }\n }\n\n _shouldAutoParse(options) {\n return options.autoParse !== false; // Default true\n }\n\n _safeJsonParse(content) {\n if (!content) return null;\n\n // Use the robust JSON extractor that handles:\n // - Markdown code blocks (```json ... ```)\n // - Plain JSON objects\n // - Over-escaped content (\\\\\\\\n instead of \\\\n)\n // - Brace extraction as fallback\n const parsed = extractJsonFromResponse(content);\n\n if (parsed) {\n console.log('[OpenAIProvider] Successfully parsed JSON from response');\n } else {\n console.error('[OpenAIProvider] Failed to extract valid JSON from response');\n console.error('[OpenAIProvider] Content preview:', content.substring(0, 200));\n }\n\n return parsed;\n }\n\n async executeTools(tool_calls, messages, tenantId, toolImplementations, env) {\n const toolResults = await Promise.all(\n tool_calls.map(async (toolCall) => {\n const toolName = toolCall.function.name;\n const tool = toolImplementations[toolName];\n\n console.log(`[Tool Call] ${toolName} with arguments:`, toolCall.function.arguments);\n\n if (!tool) {\n console.error(`[Tool Error] Tool '${toolName}' not found`);\n return { tool_call_id: toolCall.id, output: JSON.stringify({ error: `Tool '${toolName}' not found.` }) };\n }\n try {\n const output = await tool(toolCall.function.arguments, { env, tenantId });\n console.log(`[Tool Result] ${toolName} returned:`, output.substring(0, 200) + (output.length > 200 ? '...' : ''));\n return { tool_call_id: toolCall.id, output };\n } catch (error) {\n console.error(`[Tool Error] ${toolName} failed:`, error.message);\n return { tool_call_id: toolCall.id, output: JSON.stringify({ error: `Error executing tool '${toolName}': ${error.message}` }) };\n }\n })\n );\n toolResults.forEach(result => messages.push({ role: 'tool', tool_call_id: result.tool_call_id, content: result.output }));\n }\n\n _getModelForTier(tier) {\n return this.models[tier] || this.models.default;\n }\n\n async videoGeneration(prompt, images, modelName, systemPrompt, options = {}) {\n throw new Error('Video generation is not supported by OpenAI provider yet.');\n }\n\n async startDeepResearch(prompt, options = {}) {\n throw new Error('Deep Research is not supported by OpenAI provider.');\n }\n\n async getDeepResearchStatus(operationId) {\n throw new Error('Deep Research is not supported by OpenAI provider.');\n }\n}\n","/**\n * Standardized finish reasons across all LLM providers.\n * Providers map their native values to these standard constants.\n */\nexport const FINISH_REASONS = {\n COMPLETED: 'completed', // Normal completion (OpenAI: stop, Gemini: STOP, Anthropic: end_turn)\n TRUNCATED: 'truncated', // Hit max tokens (OpenAI: length, Gemini: MAX_TOKENS, Anthropic: max_tokens)\n CONTENT_FILTER: 'content_filter', // Content was filtered\n TOOL_CALL: 'tool_call', // Stopped for tool call\n UNKNOWN: 'unknown', // Unknown/unmapped reason\n};\n\n/**\n * Abstract base class for LLM Providers.\n * Defines the standard interface that all providers must implement.\n */\nexport class BaseLLMProvider {\n constructor(config) {\n this.config = config;\n }\n\n /**\n * Normalize provider-specific finish reason to standard value.\n * Override in subclass if provider uses different values.\n * @param {string} providerReason - The provider's native finish reason\n * @returns {string} Standardized finish reason from FINISH_REASONS\n */\n normalizeFinishReason(providerReason) {\n // Default mappings - providers can override\n const upperReason = (providerReason || '').toUpperCase();\n\n // Completed mappings\n if (['STOP', 'END_TURN'].includes(upperReason)) {\n return FINISH_REASONS.COMPLETED;\n }\n\n // Truncated mappings\n if (['LENGTH', 'MAX_TOKENS'].includes(upperReason)) {\n return FINISH_REASONS.TRUNCATED;\n }\n\n // Content filter mappings\n if (['CONTENT_FILTER', 'SAFETY'].includes(upperReason)) {\n return FINISH_REASONS.CONTENT_FILTER;\n }\n\n // Tool call mappings\n if (['TOOL_CALLS', 'TOOL_USE', 'FUNCTION_CALL'].includes(upperReason)) {\n return FINISH_REASONS.TOOL_CALL;\n }\n\n return FINISH_REASONS.UNKNOWN;\n }\n\n /**\n * Simple chat interface for single-turn conversations\n * @param {string} userMessage \n * @param {string} systemPrompt \n * @param {Object} options \n */\n async chat(userMessage, systemPrompt, options) {\n throw new Error('Method not implemented');\n }\n\n /**\n * Advanced chat completion with tool support\n * @param {Array} messages \n * @param {string} systemPrompt \n * @param {Array} tools \n * @param {Object} options - Generation options (responseFormat, temperature, etc.)\n */\n async chatCompletion(messages, systemPrompt, tools, options = {}) {\n throw new Error('Method not implemented');\n }\n\n /**\n * Execute tools requested by the LLM\n * @param {Array} toolCalls \n * @param {Array} messages \n * @param {string} tenantId \n * @param {Object} toolImplementations \n * @param {Object} env \n */\n async executeTools(toolCalls, messages, tenantId, toolImplementations, env) {\n throw new Error('Method not implemented');\n }\n\n /**\n * Generate image\n * Subclasses should override this method.\n * Model can be overridden via options.model, otherwise uses config.models.image\n * @param {string} prompt - Text description of the image\n * @param {string} systemPrompt - System instructions for generation\n * @param {Object} options - Generation options (aspectRatio, images, model, etc.)\n * @returns {Promise<{imageData: string, mimeType: string}>}\n */\n async imageGeneration(prompt, systemPrompt, options = {}) {\n throw new Error('Image generation not supported by this provider');\n }\n\n\n /**\n * Start video generation (returns operation name for polling)\n * @param {string} prompt\n * @param {Array} images\n * @param {string} modelName\n * @param {string} systemPrompt\n * @param {Object} options\n * @returns {Promise<{operationName: string}>}\n */\n async startVideoGeneration(prompt, images, modelName, systemPrompt, options) {\n throw new Error('Video generation not supported by this provider');\n }\n\n /**\n * Get video generation status (poll operation)\n * @param {string} operationName\n * @returns {Promise<{done: boolean, progress: number, state: string, videoUri?: string, error?: object}>}\n */\n async getVideoGenerationStatus(operationName) {\n throw new Error('Video generation not supported by this provider');\n }\n\n /**\n * Helper to get the last 6 digits of the API key for logging.\n * @returns {string} \"...\" + last 6 chars, or \"not_set\"\n */\n _getMaskedApiKey() {\n const key = this.config.apiKey;\n if (!key) return 'not_set';\n if (key.length <= 6) return '...';\n return '...' + key.slice(-6);\n }\n}\n","/**\n * Extracts and parses JSON from a text response (e.g., from an LLM).\n * Handles JSON in markdown code blocks or plain JSON objects.\n * \n * TODO: improveme for better performance\n * \n * @param {string} text - The text containing JSON\n * @returns {object|null} - The parsed JSON object, or null if no valid JSON found\n */\nexport function extractJsonFromResponse(text) {\n if (!text || typeof text !== 'string') {\n return null;\n }\n\n // Helper to sanitize JSON strings with unescaped control characters\n function sanitizeJsonString(str) {\n // Find all JSON strings: \"...\"\n // Handle escaped quotes \\\" and backslashes \\\\\n return str.replace(/\"(?:[^\"\\\\]|\\\\.)*\"/g, (match) => {\n // Replace unescaped control characters inside the string\n return match\n .replace(/\\n/g, \"\\\\n\")\n .replace(/\\r/g, \"\\\\r\")\n .replace(/\\t/g, \"\\\\t\");\n });\n }\n\n // Helper function to attempt JSON parsing with escape sequence normalization\n function tryParseJson(jsonStr) {\n // First, try to parse as-is\n try {\n return JSON.parse(jsonStr);\n } catch (e) {\n // If that fails, check if the LLM over-escaped the content\n // This is a common issue where LLMs return \\\\\\\\n instead of \\\\n\n\n // Only attempt normalization if we detect the problematic pattern\n if (jsonStr.includes('\\\\\\\\\\\\\\\\')) {\n // Log the first parse attempt failure for debugging\n console.warn('Initial JSON parse failed, attempting normalization:', e.message);\n\n try {\n // Strategy: The LLM sometimes escapes strings that are already escaped\n // For example: \"content\": \"text\\\\\\\\nmore\" should be \"content\": \"text\\\\nmore\"\n // Replace quadruple backslashes with double (handles over-escaping)\n let normalized = jsonStr.replace(/\\\\\\\\\\\\\\\\/g, '\\\\\\\\');\n\n return JSON.parse(normalized);\n } catch (e2) {\n // Log this failure too\n console.warn('Normalized JSON parse also failed:', e2.message);\n // Fall through to sanitization\n }\n }\n\n // Try sanitizing unescaped control characters (common LLM error)\n try {\n const sanitized = sanitizeJsonString(jsonStr);\n return JSON.parse(sanitized);\n } catch (e3) {\n // If all attempts fail, throw the original error\n throw e;\n }\n }\n }\n\n // Regular expression to find a JSON object within markdown code fences.\n // It's flexible with or without the 'json' language specifier.\n const jsonRegex = /```(?:json)?\\s*({[\\s\\S]*?})\\s*```/;\n const match = text.match(jsonRegex);\n\n // If a fenced JSON block is found, try to parse it.\n if (match && match[1]) {\n try {\n return tryParseJson(match[1]);\n } catch (e) {\n // If parsing fails, log the error and fall through to the next method.\n console.warn('Could not parse the content of a matched JSON block.', e.message);\n }\n }\n\n // Fallback for cases where the AI might not use markdown fences correctly.\n // Find the first opening brace and the last closing brace.\n const firstBrace = text.indexOf('{');\n const lastBrace = text.lastIndexOf('}');\n\n if (firstBrace !== -1 && lastBrace > firstBrace) {\n const potentialJson = text.substring(firstBrace, lastBrace + 1);\n try {\n return tryParseJson(potentialJson);\n } catch (e) {\n // This substring is not valid JSON.\n console.error('Error parsing JSON extracted in { and }', e);\n }\n }\n\n // If no valid JSON could be extracted by any method, return null.\n return null;\n}\n\n/**\n * Generic helper to separate conversational text from a structured JSON payload.\n * Supports both \"Text + JSON\" and \"JSON + Text\" patterns.\n * \n * @param {string} input - The full response string\n * @returns {{text: string, json: object|null}} \n */\nexport function extractTextAndJson(input) {\n if (!input) return { text: '', json: null };\n\n // 1. Try to extract JSON using the existing robust extractor\n const json = extractJsonFromResponse(input);\n\n // 2. If no JSON found, return full input as text\n if (!json) {\n return { text: input, json: null };\n }\n\n // 3. If JSON found, we need to remove the JSON block to get the clean text\n let text = input;\n\n // Try fenced block first (most reliable) - same regex as extractJsonFromResponse\n const fencedRegex = /```(?:json)?\\s*({[\\s\\S]*?})\\s*```/;\n const fencedMatch = input.match(fencedRegex);\n\n if (fencedMatch) {\n // Replace the entire fenced block with empty string to leave just the text\n // This handles both \"Text + JSON\" and \"JSON + Text\" patterns\n text = input.replace(fencedMatch[0], '').trim();\n return { text, json };\n }\n\n // Try brace extraction as fallback - same logic as extractJsonFromResponse\n const firstBrace = input.indexOf('{');\n const lastBrace = input.lastIndexOf('}');\n\n if (firstBrace !== -1 && lastBrace > firstBrace) {\n // Remove the brace block, keeping text before and after\n const pre = input.substring(0, firstBrace);\n const post = input.substring(lastBrace + 1);\n text = (pre + post).trim();\n return { text, json };\n }\n\n // Fallback: Return original text if we couldn't cleanly separate it\n return { text: input, json };\n}\n","import { GoogleGenAI } from '@google/genai';\nimport { BaseLLMProvider } from './base-provider.js';\nimport { LLMServiceException } from '../../llm-service.js';\nimport { extractJsonFromResponse } from '../json-utils.js';\n\nexport class GeminiProvider extends BaseLLMProvider {\n constructor(config) {\n super(config);\n\n // Unified client for all operations (text, image, video)\n // Supports both AI Studio (apiKey) and Vertex AI (project, location)\n\n const clientConfig = {};\n\n if (config.project || config.location) {\n console.log(`[GeminiProvider] Initializing with Vertex AI (Project: ${config.project}, Location: ${config.location || 'us-central1'})`);\n clientConfig.vertexAI = {\n project: config.project,\n location: config.location || 'us-central1'\n };\n // When using Vertex AI, standard Google Auth (ADC) is used automatically by the SDK\n // if no explicitly credentials are provided, but we can pass them if needed.\n } else {\n // Fallback to AI Studio\n clientConfig.apiKey = config.apiKey;\n }\n\n this.client = new GoogleGenAI(clientConfig);\n\n this.models = config.models;\n this.defaultModel = config.models.default;\n\n // Store pending operations for polling\n this._pendingOperations = new Map();\n }\n\n\n async chat(userMessage, systemPrompt = '', options = {}) {\n const messages = [{ role: 'user', content: userMessage }];\n const tier = options.tier || 'default';\n const effectiveModel = this._getModelForTier(tier);\n const effectiveMaxTokens = options.maxTokens || this.config.maxTokens;\n const effectiveTemperature = options.temperature !== undefined ? options.temperature : this.config.temperature;\n\n const response = await this._chatCompletionWithModel(\n messages,\n systemPrompt,\n null,\n effectiveModel,\n effectiveMaxTokens,\n effectiveTemperature\n );\n return { text: response.content };\n }\n\n async chatCompletion(messages, systemPrompt, tools = null, options = {}) {\n return this._chatCompletionWithModel(\n messages,\n systemPrompt,\n tools,\n this.defaultModel,\n this.config.maxTokens,\n this.config.temperature,\n options\n );\n }\n\n async _chatCompletionWithModel(messages, systemPrompt, tools, modelName, maxTokens, temperature, options = {}) {\n // Build generation config\n const generationConfig = {\n temperature: options.temperature ?? temperature,\n maxOutputTokens: options.maxTokens ?? maxTokens,\n };\n\n // Add JSON mode support\n if (options.responseFormat) {\n const formatConfig = this._buildGenerationConfig(options, maxTokens, temperature);\n Object.assign(generationConfig, formatConfig);\n }\n\n // Pre-process messages to handle the 'system' role for Gemini\n const geminiMessages = [];\n let systemContentBuffer = [];\n\n for (const msg of messages) {\n if (msg.role === 'system') {\n systemContentBuffer.push(msg.content);\n } else {\n if (msg.role === 'user' && systemContentBuffer.length > 0) {\n const fullContent = `${systemContentBuffer.join('\\n')}\\n\\n${msg.content}`;\n geminiMessages.push({ ...msg, content: fullContent });\n systemContentBuffer = [];\n } else {\n geminiMessages.push(msg);\n }\n }\n }\n\n const contents = geminiMessages.map((msg, index) => {\n let role = '';\n let parts;\n\n switch (msg.role) {\n case 'user':\n role = 'user';\n parts = [{ text: msg.content }];\n\n // Enhancement: If this is the LAST message (current turn), append the reminder.\n // This helps the model respect the system prompt (especially format) even with long context history.\n if (index === geminiMessages.length - 1) {\n let reminder = \"\";\n if (options.responseFormat === 'json' || options.responseFormat?.type === 'json_schema' || options.responseSchema) {\n reminder = \"\\n\\n[SYSTEM NOTE: The output MUST be valid JSON as per the schema. Do not include markdown formatting or explanations.]\";\n } else {\n reminder = \"\\n\\n[SYSTEM NOTE: Please ensure your response adheres strictly to the constraints defined in the System Prompt.]\";\n }\n\n // Append to the existing text part (Safest method)\n const lastPart = parts.find(p => p.text);\n if (lastPart) {\n lastPart.text += reminder;\n } else {\n // Fallback if message was image-only\n parts.push({ text: reminder });\n }\n }\n break;\n case 'assistant':\n role = 'model';\n\n // Find if this is the LAST assistant message in the conversation\n // Text messages: only the last one should carry thought_signature (cumulative state)\n // Tool calls: ALL must carry their signatures (model requirement for function calls)\n const isLastAssistantMessage = index === geminiMessages.map((m, i) => m.role === 'assistant' ? i : -1).filter(i => i >= 0).pop();\n\n if (msg.tool_calls) {\n parts = msg.tool_calls.map(tc => {\n const part = {\n functionCall: { name: tc.function.name, args: tc.function.arguments || tc.function.args }\n };\n // IMPORTANT: Always attach signatures for ALL tool calls in history\n // The model requires thought_signature on every functionCall part\n if (tc.thought_signature) {\n console.log(`[GeminiProvider] Sending thought_signature in tool_call (${tc.thought_signature.length} chars)`);\n part.thoughtSignature = tc.thought_signature; // camelCase for SDK\n }\n return part;\n });\n } else {\n // Handle text content with optional thought signature\n const part = { text: msg.content || '' };\n // Only attach signature for the last assistant message (text messages only)\n if (isLastAssistantMessage && msg.thought_signature) {\n console.log(`[GeminiProvider] Sending thought_signature in text message (${msg.thought_signature.length} chars)`);\n part.thoughtSignature = msg.thought_signature;\n }\n parts = [part];\n }\n break;\n case 'tool':\n role = 'user';\n const preceding_message = messages[index - 1];\n const tool_call = preceding_message?.tool_calls?.find(tc => tc.id === msg.tool_call_id);\n parts = [{\n functionResponse: {\n name: tool_call?.function?.name || 'unknown_tool',\n response: { content: msg.content },\n }\n }];\n\n // Fix for JSON mode: If JSON is requested, remind the model to output JSON after tool execution\n // This is necessary because strict JSON mode is disabled when tools are present.\n if (options.responseFormat === 'json' || options.responseFormat?.type === 'json_schema' || options.responseSchema) {\n parts.push({ text: \"\\n\\n[SYSTEM NOTE: The output MUST be valid JSON as per the schema. Do not include markdown formatting or explanations.]\" });\n } else {\n // Generic reminder to help model stay on track with system prompt instructions (e.g. formatting)\n // even if no specific JSON mode is configured.\n parts.push({ text: \"\\n\\n[SYSTEM NOTE: Please ensure your response adheres strictly to the constraints defined in the System Prompt.]\" });\n }\n break;\n default:\n return null;\n }\n return { role, parts };\n }).filter(Boolean);\n\n while (contents.length > 0 && contents[0].role !== 'user') {\n contents.shift();\n }\n\n if (contents.length === 0) {\n throw new LLMServiceException('Cannot process a conversation with no user messages.', 400);\n }\n\n // Use the new @google/genai API\n // Use the new @google/genai API\n const requestOptions = {\n model: modelName,\n contents: contents,\n config: generationConfig,\n };\n\n if (systemPrompt) {\n requestOptions.config.systemInstruction = { parts: [{ text: systemPrompt }] };\n }\n\n if (tools && tools.length > 0) {\n requestOptions.config.tools = [{ functionDeclarations: tools.map(t => t.function) }];\n // CRITICAL: Cannot enforce JSON mode (responseMimeType/responseSchema) when tools are present\n // because the model needs to be able to return tool calls (which are not JSON text).\n // We must rely on the system prompt for JSON formatting in this case.\n if (requestOptions.config.responseMimeType === 'application/json') {\n console.warn('[GeminiProvider] Disabling strict JSON mode because tools are present. Relying on system prompt.');\n delete requestOptions.config.responseMimeType;\n delete requestOptions.config.responseSchema;\n }\n }\n\n // console.log('[GeminiProvider] generateContent request:', JSON.stringify(requestOptions, null, 2));\n\n let response;\n try {\n response = await this.client.models.generateContent(requestOptions);\n } catch (error) {\n console.error(`[GeminiProvider] generateContent failed (API Key: ${this._getMaskedApiKey()}):`, error);\n throw error;\n }\n\n // In @google/genai, the response is returned directly (no .response property)\n // And helper methods like .text() or .functionCalls() might not exist on the raw object\n // So we extract manually from candidates\n\n const candidate = response.candidates?.[0];\n if (!candidate) {\n throw new LLMServiceException('No candidates returned from model', 500);\n }\n\n const parts = candidate.content?.parts || [];\n\n // Extract text, function calls, and thought signatures\n let textContent = '';\n let toolCalls = null;\n let responseThoughtSignature = null;\n\n for (const part of parts) {\n if (part.text) {\n textContent += part.text;\n // Capture thought signature attached to text part if present\n if (part.thought_signature || part.thoughtSignature) {\n responseThoughtSignature = part.thought_signature || part.thoughtSignature;\n }\n }\n if (part.functionCall) {\n if (!toolCalls) toolCalls = [];\n // Preserve thought_signature if present (Gemini 3 requirement)\n // Check both snake_case (API) and camelCase (SDK convention)\n const sig = part.thought_signature || part.thoughtSignature;\n if (sig) {\n part.functionCall.thought_signature = sig;\n // Also capture as top-level if not already set (though tool calls might have their own)\n if (!responseThoughtSignature) responseThoughtSignature = sig;\n }\n toolCalls.push(part.functionCall);\n }\n // Fallback for standalone thought signature parts if they exist (hypothetical)\n if (!part.text && !part.functionCall && (part.thought_signature || part.thoughtSignature)) {\n responseThoughtSignature = part.thought_signature || part.thoughtSignature;\n }\n }\n\n // Validate that we have EITHER content OR tool calls\n if (!textContent && (!toolCalls || toolCalls.length === 0)) {\n console.error('[GeminiProvider] Model returned empty response (no text, no tool calls)');\n console.error('[GeminiProvider] Finish Reason:', candidate.finishReason);\n console.error('[GeminiProvider] Safety Ratings:', JSON.stringify(candidate.safetyRatings, null, 2));\n console.error('[GeminiProvider] Full Candidate:', JSON.stringify(candidate, null, 2));\n\n throw new LLMServiceException(\n `Model returned empty response. Finish Reason: ${candidate.finishReason}.`,\n 500\n );\n }\n\n // Detailed logging as requested\n // console.log('[GeminiProvider] generateContent response candidate:', JSON.stringify(candidate, null, 2));\n\n // console.log('Gemini returns:', textContent);\n // Return with parsed JSON if applicable\n // Normalize the finish reason to standard value for consistent handling\n const normalizedFinishReason = this.normalizeFinishReason(candidate.finishReason);\n\n return {\n content: textContent,\n thought_signature: responseThoughtSignature, // Return signature to caller\n tool_calls: toolCalls ? (Array.isArray(toolCalls) ? toolCalls : [toolCalls]).map(fc => ({\n type: 'function',\n function: fc,\n thought_signature: fc.thought_signature\n })) : null,\n finishReason: normalizedFinishReason, // Standardized: 'completed', 'truncated', etc.\n _rawFinishReason: candidate.finishReason, // Keep original for debugging\n _responseFormat: options.responseFormat,\n ...(options.responseFormat && this._shouldAutoParse(options) ? {\n parsedContent: this._safeJsonParse(textContent)\n } : {})\n };\n }\n\n\n _buildGenerationConfig(options, maxTokens, temperature) {\n const config = {\n temperature: options.temperature ?? temperature,\n maxOutputTokens: options.maxTokens ?? maxTokens,\n };\n\n // Handle responseFormat as an object with type and schema properties\n if (options.responseFormat) {\n const formatType = typeof options.responseFormat === 'string'\n ? options.responseFormat\n : options.responseFormat.type;\n\n const schema = typeof options.responseFormat === 'object'\n ? options.responseFormat.schema\n : options.responseSchema || null;\n\n if (formatType === 'json' || formatType === 'json_schema') {\n config.responseMimeType = 'application/json';\n\n // CRITICAL: Must provide schema for \"Strict Mode\" to avoid markdown wrappers\n if (schema) {\n // Use responseSchema for strict structured output\n // Must convert to Gemini Schema format (Uppercase types)\n config.responseSchema = this._convertToGeminiSchema(schema);\n // console.log('[GeminiProvider] Using Strict JSON mode with schema (responseSchema)');\n } else {\n console.warn('[GeminiProvider] Using legacy JSON mode without schema - may produce markdown wrappers');\n }\n }\n }\n\n return config;\n }\n\n _convertToGeminiSchema(jsonSchema) {\n const convertType = (type) => {\n switch (type) {\n case 'string': return 'STRING';\n case 'number': return 'NUMBER';\n case 'integer': return 'INTEGER';\n case 'boolean': return 'BOOLEAN';\n case 'array': return 'ARRAY';\n case 'object': return 'OBJECT';\n default: return 'STRING';\n }\n };\n\n const convert = (schema) => {\n const result = {\n type: convertType(schema.type),\n };\n\n if (schema.properties) {\n result.properties = {};\n for (const [key, value] of Object.entries(schema.properties)) {\n result.properties[key] = convert(value);\n }\n }\n\n if (schema.items) {\n result.items = convert(schema.items);\n }\n\n if (schema.required) {\n result.required = schema.required;\n }\n\n if (schema.nullable) {\n result.nullable = schema.nullable;\n }\n\n if (schema.description) {\n result.description = schema.description;\n }\n\n return result;\n };\n\n return convert(jsonSchema);\n }\n\n _shouldAutoParse(options) {\n return options.autoParse !== false; // Default true\n }\n\n _safeJsonParse(content) {\n if (!content) return null;\n\n // Use the robust JSON extractor that handles:\n // - Markdown code blocks (```json ... ```)\n // - Plain JSON objects\n // - Over-escaped content (\\\\\\\\n instead of \\\\n)\n // - Brace extraction as fallback\n const parsed = extractJsonFromResponse(content);\n\n if (!parsed) {\n console.error('[GeminiProvider] Failed to extract valid JSON from response');\n console.error('[GeminiProvider] Content preview:', content.substring(0, 200));\n }\n\n return parsed;\n }\n\n async executeTools(tool_calls, messages, tenantId, toolImplementations, env) {\n const toolResults = await Promise.all(\n tool_calls.map(async (toolCall, index) => {\n const toolName = toolCall.function.name;\n const tool = toolImplementations[toolName];\n const tool_call_id = `gemini-tool-call-${index}`;\n toolCall.id = tool_call_id;\n\n // console.log(`[Tool Call] ${toolName} with arguments:`, toolCall.function.args);\n\n if (!tool) {\n console.error(`[Tool Error] Tool '${toolName}' not found`);\n return { tool_call_id, output: JSON.stringify({ error: `Tool '${toolName}' not found.` }) };\n }\n try {\n const output = await tool(toolCall.function.args, { env, tenantId });\n // console.log(`[Tool Result] ${toolName} returned:`, output.substring(0, 200) + (output.length > 200 ? '...' : ''));\n return { tool_call_id, output };\n } catch (error) {\n console.error(`[Tool Error] ${toolName} failed:`, error.message);\n return { tool_call_id, output: JSON.stringify({ error: `Error executing tool '${toolName}': ${error.message}` }) };\n }\n })\n );\n toolResults.forEach(result => messages.push({ role: 'tool', tool_call_id: result.tool_call_id, content: result.output }));\n }\n\n async imageGeneration(prompt, systemPrompt, options = {}) {\n // Allow model override via options.model, otherwise use default from config\n const modelName = options.model || this.models.image || 'gemini-3-pro-image-preview';\n console.log(`[GeminiProvider] Generating image with model: ${modelName}`);\n\n const generationConfig = {\n responseModalities: [\"IMAGE\"],\n };\n\n if (options.aspectRatio) {\n generationConfig.imageConfig = {\n aspectRatio: options.aspectRatio\n };\n }\n\n const parts = [{ text: prompt }];\n\n if (options.images && options.images.length > 0) {\n options.images.forEach(img => {\n parts.push({\n inlineData: {\n data: img.data,\n mimeType: img.mimeType\n }\n });\n });\n }\n\n // Use the new @google/genai API\n const requestOptions = {\n model: modelName,\n contents: [{\n role: \"user\",\n parts: parts\n }],\n config: generationConfig\n };\n\n if (systemPrompt) {\n requestOptions.config.systemInstruction = { parts: [{ text: systemPrompt }] };\n }\n\n // console.log('[GeminiProvider] imageGeneration request:', JSON.stringify(requestOptions, null, 2));\n\n const response = await this.client.models.generateContent(requestOptions);\n\n const imagePart = response.candidates?.[0]?.content?.parts?.find(\n part => part.inlineData && part.inlineData.mimeType?.startsWith('image/')\n );\n\n if (!imagePart || !imagePart.inlineData) {\n // Fallback: Check if it returned a URI or other format, or just text\n const textPart = response.candidates?.[0]?.content?.parts?.find(p => p.text);\n const candidate = response.candidates?.[0];\n\n console.error('[GeminiProvider] Image generation failed (no image data)');\n if (candidate) {\n console.error('[GeminiProvider] Finish Reason:', candidate.finishReason);\n console.error('[GeminiProvider] Safety Ratings:', JSON.stringify(candidate.safetyRatings, null, 2));\n console.error('[GeminiProvider] Full Candidate:', JSON.stringify(candidate, null, 2));\n }\n\n if (textPart) {\n console.warn('[GeminiProvider] Model returned text instead of image:', textPart.text);\n }\n throw new Error(`No image data in response. Finish Reason: ${candidate?.finishReason}`);\n }\n\n // Check for thought signature in the image part or any other part\n let thoughtSignature = null;\n if (imagePart.thought_signature || imagePart.thoughtSignature) {\n thoughtSignature = imagePart.thought_signature || imagePart.thoughtSignature;\n } else {\n // Check other parts for standalone thought signature\n const signaturePart = response.candidates?.[0]?.content?.parts?.find(p => p.thought_signature || p.thoughtSignature);\n if (signaturePart) {\n thoughtSignature = signaturePart.thought_signature || signaturePart.thoughtSignature;\n }\n }\n\n // Safety: If thought signature is abnormally large (>50KB), replace with bypass token\n // to prevent massive context usage (User reported 1.5MB signatures in some cases).\n if (thoughtSignature && thoughtSignature.length > 50000) {\n console.warn(`[GeminiProvider] ⚠️ Thought signature is abnormally large (${thoughtSignature.length} chars). Replacing with bypass token to save context.`);\n thoughtSignature = \"skip_thought_signature_validator\";\n }\n\n return {\n imageData: imagePart.inlineData.data,\n mimeType: imagePart.inlineData.mimeType,\n thought_signature: thoughtSignature\n };\n }\n\n _getModelForTier(tier) {\n return this.models[tier] || this.models.default;\n }\n\n async startVideoGeneration(prompt, images, modelName, systemPrompt, options = {}) {\n // Use unified client for video generation\n // Prepend system prompt to user prompt if provided, as video models often expect instructions in the prompt\n const effectivePrompt = systemPrompt ? `${systemPrompt}\\n\\n${prompt}` : prompt;\n\n const requestConfig = {\n model: modelName,\n prompt: effectivePrompt,\n config: {\n durationSeconds: options.durationSeconds || 6,\n aspectRatio: options.aspectRatio || '16:9',\n numberOfVideos: 1,\n // Pass reference images if provided\n ...(images && images.length > 0 ? { referenceImages: images } : {}),\n }\n };\n\n // Create a loggable copy of the config\n const logConfig = JSON.parse(JSON.stringify(requestConfig));\n if (logConfig.config && logConfig.config.referenceImages) {\n logConfig.config.referenceImages = logConfig.config.referenceImages.map(img => ({\n ...img,\n data: `... (${img.data ? img.data.length : 0} bytes)` // Summarize data\n }));\n }\n\n console.log('[GeminiProvider] startVideoGeneration request:', JSON.stringify(logConfig, null, 2));\n\n try {\n const operation = await this.client.models.generateVideos(requestConfig);\n\n // Store operation for later polling\n this._pendingOperations.set(operation.name, operation);\n\n return { operationName: operation.name };\n } catch (error) {\n console.error(`[GeminiProvider] startVideoGeneration failed (API Key: ${this._getMaskedApiKey()}):`, error);\n throw error;\n }\n }\n\n async getVideoGenerationStatus(operationName) {\n console.log(`[GeminiProvider] Checking status for operation: ${operationName}`);\n\n // Get the operation from cache or fetch it\n let operation = this._pendingOperations.get(operationName);\n\n if (!operation) {\n // If not in cache, we need to fetch it by name\n operation = await this.client.models.getOperation(operationName);\n }\n\n // Refresh status\n operation = await operation.get();\n\n // Update cache\n this._pendingOperations.set(operationName, operation);\n\n const result = {\n done: operation.done,\n progress: operation.metadata?.progressPercent || 0,\n state: operation.metadata?.state || (operation.done ? 'COMPLETED' : 'PROCESSING'),\n };\n\n console.log(`[GeminiProvider] Operation status: ${result.state}, Progress: ${result.progress}%`);\n\n if (operation.done) {\n // Clean up from cache\n this._pendingOperations.delete(operationName);\n\n if (operation.error) {\n console.error('[GeminiProvider] Video generation failed:', JSON.stringify(operation.error, null, 2));\n result.error = operation.error;\n } else {\n const videoResult = operation.response;\n // Extract video URI from response\n result.videoUri = videoResult.videos?.[0]?.gcsUri ||\n videoResult.uri ||\n (videoResult.generatedAssets?.[0]?.uri);\n result.content = \"Video generation completed.\";\n }\n }\n\n return result;\n }\n\n async startDeepResearch(prompt, options = {}) {\n const agent = options.agent || 'deep-research-pro-preview-12-2025'; // Default to preview agent if not specified\n\n console.log(`[GeminiProvider] Starting Deep Research with agent: ${agent}`);\n\n try {\n // Note: Assuming sdk supports interactions.create based on documentation\n // If sdk version is old, this might need raw fetch or update\n const interaction = await this.client.interactions.create({\n agent: agent,\n input: prompt,\n background: true, // Required for long running\n store: true // Required for polling\n });\n\n console.log(`[GeminiProvider] Deep Research started. Interaction ID: ${interaction.id}`);\n return { operationId: interaction.id };\n\n } catch (error) {\n console.error(`[GeminiProvider] startDeepResearch failed:`, error);\n throw error;\n }\n }\n\n async getDeepResearchStatus(operationId) {\n try {\n const result = await this.client.interactions.get(operationId);\n\n // Normalized status\n // API might return: 'in_progress', 'completed', 'failed'\n const state = result.state;\n\n const response = {\n state: state,\n done: state === 'completed' || state === 'failed',\n error: state === 'failed' ? result.error : null\n };\n\n if (state === 'completed') {\n response.content = result.output;\n response.citations = result.grounding_metadata; // or result.groundingMetadata\n }\n\n return response;\n } catch (error) {\n console.error(`[GeminiProvider] getDeepResearchStatus failed for ${operationId}:`, error);\n throw error;\n }\n }\n}\n","import { ConfigManager } from './llm/config-manager.js';\nimport { OpenAIProvider } from './llm/providers/openai-provider.js';\nimport { GeminiProvider } from './llm/providers/gemini-provider.js';\n\n/**\n * LLM Service Module\n * \n * This module provides a unified interface for interacting with different LLM providers.\n * It now supports BYOK (Bring Your Own Key) via Tenant Configuration.\n */\nexport class LLMService {\n constructor(env, toolImplementations = {}) {\n this.env = env;\n this.toolImplementations = toolImplementations;\n // Cache for provider instances to avoid recreation within the same request if possible\n this.providerCache = new Map();\n }\n\n async _getProvider(tenantId) {\n // Check cache first\n const cacheKey = tenantId || 'system';\n if (this.providerCache.has(cacheKey)) {\n return this.providerCache.get(cacheKey);\n }\n\n const config = await ConfigManager.getConfig(tenantId, this.env);\n\n if (!config.apiKey) {\n throw new LLMServiceException(`LLM service is not configured for ${config.provider}. Missing API Key.`, 500);\n }\n\n let provider;\n if (config.provider === 'openai') {\n provider = new OpenAIProvider(config);\n } else if (config.provider === 'gemini') {\n provider = new GeminiProvider(config);\n } else {\n throw new LLMServiceException(`Unsupported LLM provider: ${config.provider}`, 500);\n }\n\n this.providerCache.set(cacheKey, provider);\n return provider;\n }\n\n /**\n * Check if LLM service is configured for a tenant (or system default)\n */\n async isConfigured(tenantId) {\n const config = await ConfigManager.getConfig(tenantId, this.env);\n return !!config.apiKey;\n }\n\n /**\n * Simple chat interface for single-turn conversations\n */\n async chat(userMessage, tenantId, systemPrompt = '', options = {}) {\n const provider = await this._getProvider(tenantId);\n return provider.chat(userMessage, systemPrompt, options);\n }\n\n /**\n * Interact with LLM for generation\n * \n * Intelligent signature detection supports:\n * - chatCompletion(messages, tenantId, systemPrompt)\n * - chatCompletion(messages, tenantId, systemPrompt, tools)\n * - chatCompletion(messages, tenantId, systemPrompt, options)\n * - chatCompletion(messages, tenantId, systemPrompt, tools, options)\n * \n * @param {Array} messages - Conversation messages\n * @param {string} tenantId - Tenant identifier\n * @param {string} systemPrompt - System instructions\n * @param {Array|Object} toolsOrOptions - Tools array or options object\n * @param {Object} optionsParam - Options object (if tools provided)\n * @returns {Object} Response with content, tool_calls, and optionally parsedContent\n */\n async chatCompletion(messages, tenantId, systemPrompt, toolsOrOptions = null, optionsParam = {}) {\n const provider = await this._getProvider(tenantId);\n\n if (!systemPrompt?.trim()) {\n throw new LLMServiceException('No prompt set for bot', 503);\n }\n\n // Intelligent parameter detection\n const { tools, options } = this._parseToolsAndOptions(toolsOrOptions, optionsParam);\n\n return provider.chatCompletion(messages, systemPrompt, tools, options);\n }\n\n /**\n * Helper to intelligently detect tools vs options parameters\n * @private\n */\n _parseToolsAndOptions(param1, param2) {\n // If param1 is null/undefined, use defaults\n if (param1 === null || param1 === undefined) {\n return { tools: null, options: param2 || {} };\n }\n\n // If param1 is an array, it's tools\n if (Array.isArray(param1)) {\n return { tools: param1, options: param2 || {} };\n }\n\n // If param1 is an object, check if it looks like options or tools\n if (typeof param1 === 'object') {\n // Check for known options keys\n const optionsKeys = ['responseFormat', 'responseSchema', 'temperature', 'maxTokens', 'tier', 'autoParse', 'strictSchema', 'schemaName'];\n const hasOptionsKeys = optionsKeys.some(key => key in param1);\n\n if (hasOptionsKeys) {\n // param1 is options\n return { tools: null, options: param1 };\n }\n\n // Could be tools in object format (legacy support)\n // Treat as tools if it doesn't have options keys\n return { tools: param1, options: param2 || {} };\n }\n\n // Default: treat as tools\n return { tools: param1, options: param2 || {} };\n }\n\n /**\n * Convenience method for JSON-only responses\n * Automatically enables JSON mode and returns parsed object\n * \n * @param {Array} messages - Conversation messages\n * @param {string} tenantId - Tenant identifier\n * @param {string} systemPrompt - System instructions\n * @param {Object} schema - Optional JSON schema for validation\n * @param {Array} tools - Optional tools array\n * @returns {Object} Parsed JSON object\n * @throws {LLMServiceException} If JSON parsing fails\n */\n async chatCompletionJson(messages, tenantId, systemPrompt, schema = null, tools = null) {\n const options = {\n responseFormat: schema ? { type: 'json_schema', schema } : 'json',\n autoParse: true\n };\n\n const response = await this.chatCompletion(messages, tenantId, systemPrompt, tools, options);\n\n // Return parsed content directly or throw if parsing failed\n if (response.parsedContent !== null && response.parsedContent !== undefined) {\n return response.parsedContent;\n }\n\n // Fallback: try to parse the raw content\n try {\n return JSON.parse(response.content);\n } catch (e) {\n throw new LLMServiceException(\n 'LLM returned invalid JSON despite JSON mode being enabled',\n 500,\n { rawContent: response.content, parseError: e.message }\n );\n }\n }\n\n async chatWithTools(messages, tenantId, systemPrompt, tools = [], options = {}) {\n const provider = await this._getProvider(tenantId);\n\n let currentMessages = [...messages];\n const MAX_ITERATIONS = 10; // Prevent infinite loops\n let iteration = 0;\n\n // Initial call\n const initialResponse = await provider.chatCompletion(\n currentMessages,\n systemPrompt,\n tools,\n options\n );\n\n let { content, tool_calls, parsedContent, finishReason, _rawFinishReason } = initialResponse;\n\n // Tool execution loop with safety limit\n while (tool_calls && iteration < MAX_ITERATIONS) {\n iteration++;\n console.log(`[Tool Call] Iteration ${iteration}/${MAX_ITERATIONS} with finish reason ${finishReason}: Assistant wants to use tools:`, tool_calls);\n currentMessages.push({ role: 'assistant', content: content || '', tool_calls });\n\n // Execute tools using the provider's helper (which formats results for that provider)\n await provider.executeTools(tool_calls, currentMessages, tenantId, this.toolImplementations, this.env);\n\n // Next call\n const nextResponse = await provider.chatCompletion(\n currentMessages,\n systemPrompt,\n tools,\n options\n );\n\n content = nextResponse.content;\n tool_calls = nextResponse.tool_calls;\n parsedContent = nextResponse.parsedContent; // Preserve parsedContent from final response\n finishReason = nextResponse.finishReason; // Preserve finishReason from final response\n _rawFinishReason = nextResponse._rawFinishReason; // Preserve raw finish reason for debugging\n }\n\n if (iteration >= MAX_ITERATIONS) {\n console.warn(`[Tool Call] Reached maximum iterations (${MAX_ITERATIONS}). Forcing completion.`);\n }\n\n // Return both content and parsedContent (if available)\n return { content, parsedContent, toolCalls: tool_calls, finishReason, _rawFinishReason };\n }\n\n /**\n * Generate a video (async wrapper with polling - backward compatibility)\n */\n async videoGeneration(prompt, images, tenantId, modelName, systemPrompt, options = {}) {\n const { operationName } = await this.startVideoGeneration(prompt, images, tenantId, modelName, systemPrompt, options);\n\n let status = await this.getVideoGenerationStatus(operationName, tenantId);\n\n while (!status.done) {\n console.log(`Waiting for video generation... Progress: ${status.progress}%`);\n await new Promise(resolve => setTimeout(resolve, 10000)); // Wait 10 seconds\n status = await this.getVideoGenerationStatus(operationName, tenantId);\n }\n\n if (status.error) {\n throw new Error(`Video generation failed: ${status.error.message || JSON.stringify(status.error)}`);\n }\n\n return {\n content: status.content || \"Video generation completed.\",\n videoUri: status.videoUri\n };\n }\n\n /**\n * Start video generation (returns operation name for polling)\n */\n async startVideoGeneration(prompt, images, tenantId, modelName, systemPrompt, options = {}) {\n const provider = await this._getProvider(tenantId);\n return provider.startVideoGeneration(prompt, images, modelName, systemPrompt, options);\n }\n\n /**\n * Get video generation status\n */\n async getVideoGenerationStatus(operationName, tenantId) {\n const provider = await this._getProvider(tenantId);\n return provider.getVideoGenerationStatus(operationName);\n }\n\n /**\n * Generate an image\n * Falls back to system keys if tenant doesn't have image capability enabled\n * @param {string} prompt - Text description of the image\n * @param {string} tenantId - Tenant identifier\n * @param {string} systemPrompt - System instructions for generation\n * @param {Object} options - Generation options (aspectRatio, images, etc.)\n */\n async imageGeneration(prompt, tenantId, systemPrompt, options = {}) {\n // Check if tenant has image capability enabled\n if (tenantId) {\n const config = await ConfigManager.getConfig(tenantId, this.env);\n if (config.isTenantOwned && !config.capabilities?.image) {\n console.log(`[LLMService] Tenant ${tenantId} BYOK doesn't have image capability. Using system keys.`);\n tenantId = null; // Fall back to system\n }\n }\n\n const provider = await this._getProvider(tenantId);\n return provider.imageGeneration(prompt, systemPrompt, options);\n }\n\n /**\n * Start a Deep Research task\n * @param {string} prompt - Research prompt/query\n * @param {string} tenantId - Tenant identifier\n * @param {Object} options - Options (agentId, etc.)\n * @returns {Promise<{operationId: string}>}\n */\n async startDeepResearch(prompt, tenantId, options = {}) {\n const provider = await this._getProvider(tenantId);\n return provider.startDeepResearch(prompt, options);\n }\n\n /**\n * Get status of a Deep Research task\n * @param {string} operationId - ID returned from startDeepResearch\n * @param {string} tenantId - Tenant identifier\n * @returns {Promise<{state: string, content?: string, citations?: any[]}>}\n */\n async getDeepResearchStatus(operationId, tenantId) {\n const provider = await this._getProvider(tenantId);\n return provider.getDeepResearchStatus(operationId);\n }\n}\n\nexport class LLMServiceException extends Error {\n constructor(message, statusCode = 500, details = null) {\n super(message);\n this.name = 'LLMServiceException';\n this.statusCode = statusCode;\n this.details = details || {};\n }\n}\n","/**\n * Error Handling Utility for LLM Service\n * Provides centralized error parsing and user-friendly message generation.\n * Returns plain objects - framework-specific response handling is done by consumers.\n */\n\n/**\n * Parse an error and return a standardized error response object.\n * Detects specific error types like service overload, rate limits, and input issues.\n * \n * @param {Error} error - The caught error\n * @param {string} operation - The operation being performed (e.g., 'generate image', 'edit article')\n * @param {string} context - Context for logging (e.g., 'image_generation', 'ai_edit')\n * @returns {{ message: string, error: string, retryable: boolean, statusCode: number }}\n */\nexport function handleApiError(error, operation = 'complete this operation', context = 'api') {\n console.error(`[${context}] Error:`, error);\n\n const errorMessage = error.message?.toLowerCase() || '';\n const errorString = JSON.stringify(error).toLowerCase();\n\n // Check for model overload (503)\n if (errorMessage.includes('overloaded') || errorMessage.includes('503') ||\n errorString.includes('unavailable') || errorString.includes('overloaded')) {\n return {\n message: 'AI service is busy. Please try again.',\n error: 'service_overloaded',\n retryable: true,\n statusCode: 503\n };\n }\n\n // Check for rate limiting (429)\n if (errorMessage.includes('quota') || errorMessage.includes('429') ||\n errorMessage.includes('too many requests') || errorMessage.includes('rate limit') ||\n errorString.includes('resource_exhausted')) {\n return {\n message: 'Too many requests. Please try again later.',\n error: 'rate_limited',\n retryable: true,\n statusCode: 429\n };\n }\n\n // Check for context length / input too long\n if (errorMessage.includes('context length') || errorMessage.includes('too long') ||\n errorString.includes('invalid_argument')) {\n return {\n message: 'Content too big. Try making focused edits.',\n error: 'input_too_long',\n retryable: false,\n statusCode: 422\n };\n }\n\n // Check for user quota exceeded (from our own quota system)\n if (errorMessage.includes('quotaerror') || errorMessage.includes('quota_exceeded')) {\n return {\n message: 'You have reached your usage limit for this month. Please upgrade your plan to continue.',\n error: 'user_quota_exceeded',\n retryable: false,\n statusCode: 402\n };\n }\n\n // Check for trial limitation errors\n if (errorMessage.includes('trial')) {\n return {\n message: 'This feature is not available during the free trial. Please upgrade to use this feature.',\n error: 'trial_limitation',\n retryable: false,\n statusCode: 402\n };\n }\n\n // Check for authentication/configuration errors\n if (errorMessage.includes('api key') || errorMessage.includes('authentication') || errorMessage.includes('unauthorized')) {\n return {\n message: 'Service is not available at this time. Please contact support.',\n error: 'not_configured',\n retryable: false,\n statusCode: 503\n };\n }\n\n // Check for invalid input errors\n if (errorMessage.includes('invalid') || errorMessage.includes('bad request')) {\n return {\n message: 'Invalid request. Please check your input and try again.',\n error: 'invalid_input',\n retryable: false,\n statusCode: 400\n };\n }\n\n // Default error\n return {\n message: `An error occurred while trying to ${operation}. Please try again.`,\n error: 'operation_failed',\n retryable: true,\n statusCode: 500\n };\n}\n\n/**\n * Sanitize error messages to prevent leaking technical details.\n * Returns an Error with a clean error code that can be handled by the API layer.\n * Use this when you want to throw an error rather than return a JSON response.\n * \n * @param {Error} error - The original error\n * @param {string} context - Context of where error occurred (e.g., 'image_generation', 'ai_edit')\n * @returns {Error} - Sanitized error with clean message code\n */\nexport function sanitizeError(error, context = 'general') {\n const result = handleApiError(error, 'complete this operation', context);\n return new Error(result.error);\n}\n","import OpenAI from 'openai';\n\n/**\n * Transcription Service - Separate from LLM Service\n * Handles audio-to-text transcription using various providers.\n * \n * Supported providers:\n * - 'openai': OpenAI Whisper API\n * - 'generic': Any Whisper-compatible endpoint (Grok, self-hosted, etc.)\n */\nexport class TranscriptionService {\n /**\n * @param {Object} config\n * @param {string} config.provider - 'openai' | 'generic'\n * @param {string} config.apiKey - API key for the provider\n * @param {string} [config.endpoint] - Custom endpoint URL (required for 'generic')\n * @param {string} [config.model] - Model to use (default: 'whisper-1')\n */\n constructor(config) {\n this.provider = config.provider || 'openai';\n this.apiKey = config.apiKey;\n this.endpoint = config.endpoint;\n this.model = config.model || 'whisper-1';\n\n if (this.provider === 'openai') {\n this.client = new OpenAI({ apiKey: this.apiKey });\n }\n }\n\n /**\n * Transcribe audio to text\n * @param {File|Blob} audioFile - Audio file to transcribe\n * @param {Object} options - Transcription options\n * @param {string} [options.language] - Language hint (ISO-639-1 code)\n * @param {string} [options.model] - Override default model\n * @returns {Promise<{text: string}>}\n */\n async transcribe(audioFile, options = {}) {\n const model = options.model || this.model;\n const language = options.language;\n\n if (this.provider === 'openai') {\n return this._transcribeOpenAI(audioFile, model, language);\n } else if (this.provider === 'generic') {\n return this._transcribeGeneric(audioFile, model, language);\n } else {\n throw new TranscriptionServiceException(\n `Unsupported transcription provider: ${this.provider}`,\n 400\n );\n }\n }\n\n async _transcribeOpenAI(audioFile, model, language) {\n try {\n const response = await this.client.audio.transcriptions.create({\n file: audioFile,\n model: model,\n language: language,\n });\n return { text: response.text };\n } catch (error) {\n console.error('[TranscriptionService] OpenAI transcription failed:', error);\n throw new TranscriptionServiceException(\n `Transcription failed: ${error.message}`,\n 500\n );\n }\n }\n\n async _transcribeGeneric(audioFile, model, language) {\n if (!this.endpoint) {\n throw new TranscriptionServiceException(\n 'Endpoint is required for generic transcription provider',\n 400\n );\n }\n\n try {\n const formData = new FormData();\n formData.append('file', audioFile);\n formData.append('model', model);\n if (language) {\n formData.append('language', language);\n }\n\n const response = await fetch(this.endpoint, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`,\n },\n body: formData,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`HTTP ${response.status}: ${errorText}`);\n }\n\n const result = await response.json();\n return { text: result.text };\n } catch (error) {\n console.error('[TranscriptionService] Generic transcription failed:', error);\n throw new TranscriptionServiceException(\n `Transcription failed: ${error.message}`,\n 500\n );\n }\n }\n}\n\nexport class TranscriptionServiceException extends Error {\n constructor(message, statusCode = 500) {\n super(message);\n this.name = 'TranscriptionServiceException';\n this.statusCode = statusCode;\n }\n}\n","import { TranscriptionService } from '../transcription-service.js';\n\n/**\n * Create a Hono handler for speech transcription.\n *\n * @param {Hono} app - Hono app or router instance to attach the endpoint to\n * @param {Function} getConfig - Async function that returns transcription config from context\n * Should return: { provider: 'openai'|'generic', apiKey: string, endpoint?: string, model?: string }\n *\n * @example\n * // Mount in your Hono app:\n * import { Hono } from 'hono';\n * import { createSpeechHandler } from '@contentgrowth/llm-service';\n *\n * const speechHandler = new Hono();\n * createSpeechHandler(speechHandler, async (c) => ({\n * provider: 'openai',\n * apiKey: c.env.OPENAI_API_KEY,\n * }));\n *\n * app.route('/api/speech', speechHandler);\n */\nexport function createSpeechHandler(app, getConfig) {\n app.post('/transcribe', async (c) => {\n try {\n const config = await getConfig(c);\n\n if (!config || !config.apiKey) {\n return c.json({ error: 'Transcription service not configured' }, 503);\n }\n\n const formData = await c.req.formData();\n const audioFile = formData.get('audio');\n\n if (!audioFile) {\n return c.json({ error: 'No audio file provided' }, 400);\n }\n\n const language = formData.get('language') || undefined;\n\n const service = new TranscriptionService(config);\n const result = await service.transcribe(audioFile, { language });\n\n return c.json(result);\n } catch (error) {\n console.error('[SpeechHandler] Transcription error:', error);\n const statusCode = error.statusCode || 500;\n return c.json({ error: error.message }, statusCode);\n }\n });\n\n return app;\n}\n"],"mappings":"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","names":["match","OpenAI","_a","_b","_c","_d","parts","import_openai","OpenAI"]}
|