chat-agent-toolkit 1.2.11 → 1.2.13
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/research-agent.cjs.js +1 -1
- package/dist/research-agent.cjs.js.map +1 -1
- package/dist/research-agent.es.js +1 -1
- package/dist/research-agent.es.js.map +1 -1
- package/dist/tools/search/doc-utils.d.ts +15 -0
- package/dist/tools/search/index.d.ts +2 -1
- package/package.json +1 -1
- package/src/tools/search/doc-utils.ts +38 -2
- package/src/tools/search/index.ts +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"research-agent.cjs.js","names":[],"sources":["../src/memory/types.ts","../src/memory/storage/in-memory-storage.ts","../src/memory/agent-memory-manager.ts","../src/memory/storage/drizzle-storage.ts","../src/memory/mastra-integration.ts","../src/tools/qwksearch-api-tools.ts","../src/utils/outputParser.ts","../src/utils/chat-helpers.ts","../src/tools/search/doc-utils.ts","../src/tools/search/link-summarizer.ts","../src/tools/search/metaSearchAgent.ts","../src/tools/search/search-handlers.ts","../src/tools/search/suggestionGeneratorAgent.ts","../src/tools/search/document.ts","../src/config/provider-ui-config.ts","../src/config/environment-variables.ts","../src/config/language-models-database.ts","../src/config/config-manager.ts","../src/config/model-registry.ts","../src/utils/provider-image-cropper.ts"],"sourcesContent":["/**\n * Memory System Types and Constants\n *\n * Defines interfaces and configuration for the memory management system\n */\n\n/**\n * Memory types for categorization\n */\nexport const MEMORY_TYPES = {\n FACT: \"fact\",\n CONVERSATION: \"conversation\",\n PREFERENCE: \"preference\",\n PERSONAL: \"personal\",\n WORK: \"work\",\n MANUAL: \"manual\",\n} as const;\n\nexport type MemoryType = (typeof MEMORY_TYPES)[keyof typeof MEMORY_TYPES];\n\n/**\n * Configuration constants for memory management\n */\nexport const MEMORY_CONFIG = {\n DEFAULT_MAX_MEMORIES: 100,\n DEFAULT_SUMMARY_THRESHOLD: 10,\n DEFAULT_CACHE_EXPIRY: 5 * 60 * 1000, // 5 minutes\n DEFAULT_BATCH_SIZE: 5,\n DEFAULT_RELEVANCE_THRESHOLD: 0.3,\n DEFAULT_IMPORTANCE_RANGE: { min: 0, max: 10 },\n DEFAULT_RATE_LIMIT: { requests: 10, windowMs: 60000 },\n DEFAULT_TIMEOUT: 30000, // 30 seconds\n VECTOR_SEARCH_ENABLED: true,\n AUTO_SUMMARIZATION_ENABLED: true,\n} as const;\n\n/**\n * Memory record structure\n */\nexport interface MemoryRecord {\n id: string;\n user_id: string;\n memory_type: MemoryType;\n content: string;\n importance: number;\n access_count: number;\n metadata?: Record<string, any>;\n created_at: Date;\n updated_at: Date;\n relevance_score?: number;\n}\n\n/**\n * Message structure for conversation tracking\n */\nexport interface Message {\n role: \"user\" | \"assistant\";\n content: string;\n timestamp: number;\n metadata?: Record<string, any>;\n}\n\n/**\n * Memory search options\n */\nexport interface MemorySearchOptions {\n minImportance?: number;\n memoryType?: MemoryType;\n includeMetadata?: boolean;\n}\n\n/**\n * Memory update payload\n */\nexport interface MemoryUpdate {\n importance?: number;\n access_count?: number | { increment: number };\n updated_at?: Date;\n metadata?: Record<string, any>;\n}\n\n/**\n * Memory context options\n */\nexport interface MemoryContextOptions {\n maxMemories?: number;\n minImportance?: number;\n}\n\n/**\n * Performance metrics\n */\nexport interface MemoryMetrics {\n cacheHits: number;\n cacheMisses: number;\n vectorSearches: number;\n summarizations: number;\n errors: number;\n cacheSize: number;\n recentMessagesCount: number;\n isProcessing: boolean;\n}\n\n/**\n * Memory initialization options\n */\nexport interface MemoryOptions {\n maxMemories?: number;\n summaryThreshold?: number;\n cacheExpiry?: number;\n batchSize?: number;\n relevanceThreshold?: number;\n enableVectorSearch?: boolean;\n enableAutoSummarization?: boolean;\n}\n\n/**\n * Extracted fact structure\n */\nexport interface ExtractedFact {\n content: string;\n importance?: number;\n category?: MemoryType;\n metadata?: Record<string, any>;\n}\n","// @ts-nocheck\n/**\n * Simple Memory Class\n *\n * Core memory management functionality with:\n * - Message deduplication\n * - Automatic summarization\n * - Vector-based relevance search\n * - Caching with TTL\n * - Batch processing\n * - Conflict resolution\n */\n\nimport { writeLanguageResponse } from \"write-language\";\nimport type { IMemoryStorage } from \"./storage-interface\";\nimport type {\n MemoryRecord,\n Message,\n MemorySearchOptions,\n MemoryMetrics,\n MemoryOptions,\n MemoryContextOptions,\n ExtractedFact,\n MemoryType,\n} from \"../types\";\nimport { MEMORY_CONFIG, MEMORY_TYPES } from \"../types\";\n\nexport class SimpleMemory {\n private userId: string;\n private storage: IMemoryStorage;\n private maxMemories: number;\n private summaryThreshold: number;\n private cacheExpiry: number;\n private batchSize: number;\n private relevanceThreshold: number;\n private enableVectorSearch: boolean;\n private enableAutoSummarization: boolean;\n private recentMessages: Message[];\n private memoryCache: Map<string, { data: any; timestamp: number }>;\n private isProcessing: boolean;\n private processingQueue: any[];\n private summarizeTimeout?: NodeJS.Timeout;\n private metrics: {\n cacheHits: number;\n cacheMisses: number;\n vectorSearches: number;\n summarizations: number;\n errors: number;\n };\n\n /**\n * Initialize memory system for a user\n */\n constructor(\n userId: string,\n storage: IMemoryStorage,\n options: MemoryOptions = {},\n ) {\n if (!userId || !storage) {\n throw new Error(\"userId and storage are required parameters\");\n }\n\n this.userId = userId;\n this.storage = storage;\n this.maxMemories =\n options.maxMemories || MEMORY_CONFIG.DEFAULT_MAX_MEMORIES;\n this.summaryThreshold =\n options.summaryThreshold || MEMORY_CONFIG.DEFAULT_SUMMARY_THRESHOLD;\n this.cacheExpiry =\n options.cacheExpiry || MEMORY_CONFIG.DEFAULT_CACHE_EXPIRY;\n this.batchSize = options.batchSize || MEMORY_CONFIG.DEFAULT_BATCH_SIZE;\n this.relevanceThreshold =\n options.relevanceThreshold || MEMORY_CONFIG.DEFAULT_RELEVANCE_THRESHOLD;\n\n // Feature flags\n this.enableVectorSearch =\n options.enableVectorSearch !== false &&\n MEMORY_CONFIG.VECTOR_SEARCH_ENABLED;\n this.enableAutoSummarization =\n options.enableAutoSummarization !== false &&\n MEMORY_CONFIG.AUTO_SUMMARIZATION_ENABLED;\n\n // State management\n this.recentMessages = [];\n this.memoryCache = new Map();\n this.isProcessing = false;\n this.processingQueue = [];\n\n // Performance metrics\n this.metrics = {\n cacheHits: 0,\n cacheMisses: 0,\n vectorSearches: 0,\n summarizations: 0,\n errors: 0,\n };\n }\n\n /**\n * Add a message to current session with intelligent deduplication\n */\n addMessage(\n role: \"user\" | \"assistant\",\n content: string,\n metadata: Record<string, any> = {},\n ): boolean {\n if (!role || !content || typeof content !== \"string\") {\n console.warn(\"Invalid message parameters:\", { role, content });\n return false;\n }\n\n // Intelligent deduplication - check last few messages\n const lastMessages = this.recentMessages.slice(-3);\n const isDuplicate = lastMessages.some(\n (msg) =>\n msg.role === role &&\n msg.content === content &&\n Date.now() - msg.timestamp < 60000, // Within 1 minute\n );\n\n if (isDuplicate) {\n console.log(\"Duplicate message detected, skipping\");\n return false;\n }\n\n // Add message with metadata\n const message: Message = {\n role,\n content: content.trim(),\n timestamp: metadata.timestamp || Date.now(),\n metadata: { ...metadata },\n };\n\n this.recentMessages.push(message);\n\n // Auto-summarization with debouncing\n if (\n this.enableAutoSummarization &&\n this.recentMessages.length >= this.summaryThreshold &&\n !this.isProcessing\n ) {\n this.debouncedSummarize();\n }\n\n return true;\n }\n\n /**\n * Debounced summarization to prevent excessive processing\n */\n private debouncedSummarize(): void {\n if (this.summarizeTimeout) {\n clearTimeout(this.summarizeTimeout);\n }\n\n this.summarizeTimeout = setTimeout(() => {\n this.summarizeAndStore().catch((error) => {\n console.error(\"Auto-summarization failed:\", error);\n this.metrics.errors++;\n });\n }, 1000); // 1 second debounce\n }\n\n /**\n * Store important facts with validation and conflict resolution\n */\n async storeFact(\n content: string,\n importance: number = 1,\n category: MemoryType = MEMORY_TYPES.FACT,\n metadata: Record<string, any> = {},\n ): Promise<string> {\n // Input validation\n if (\n !content ||\n typeof content !== \"string\" ||\n content.trim().length === 0\n ) {\n throw new Error(\"Content cannot be empty\");\n }\n\n if (\n importance < MEMORY_CONFIG.DEFAULT_IMPORTANCE_RANGE.min ||\n importance > MEMORY_CONFIG.DEFAULT_IMPORTANCE_RANGE.max\n ) {\n throw new Error(\n `Importance must be between ${MEMORY_CONFIG.DEFAULT_IMPORTANCE_RANGE.min} and ${MEMORY_CONFIG.DEFAULT_IMPORTANCE_RANGE.max}`,\n );\n }\n\n const normalizedContent = content.trim();\n const normalizedCategory = Object.values(MEMORY_TYPES).includes(category)\n ? category\n : MEMORY_TYPES.FACT;\n\n try {\n // Check for existing similar facts using fuzzy matching\n const existingFacts = await this.findSimilarFacts(normalizedContent);\n\n if (existingFacts.length > 0) {\n // Update existing fact if importance is higher\n const bestMatch = existingFacts[0];\n if (importance > bestMatch.importance) {\n await this.storage.updateMemory(bestMatch.id, {\n importance,\n updated_at: new Date(),\n access_count: { increment: 1 },\n metadata: { ...bestMatch.metadata, ...metadata },\n });\n }\n return bestMatch.id;\n }\n\n // Insert new fact\n const id = await this.storage.insertMemory(\n this.userId,\n normalizedCategory,\n normalizedContent,\n Math.max(0, Math.min(10, importance)),\n metadata,\n );\n\n // Clear cache after new insertion\n this.clearCache();\n\n return id;\n } catch (error) {\n console.error(\"Error storing fact:\", error);\n this.metrics.errors++;\n throw error;\n }\n }\n\n /**\n * Find similar facts using content similarity\n */\n private async findSimilarFacts(content: string): Promise<MemoryRecord[]> {\n try {\n return await this.storage.findSimilarMemories(this.userId, content, 5);\n } catch (error) {\n console.error(\"Error finding similar facts:\", error);\n return [];\n }\n }\n\n /**\n * Enhanced memory recall with caching and vector search\n */\n async recallRelevantMemories(\n query: string = \"\",\n limit: number = 10,\n options: MemorySearchOptions = {},\n ): Promise<MemoryRecord[]> {\n const cacheKey = `${query}-${limit}-${JSON.stringify(options)}`;\n\n // Check cache first\n if (this.memoryCache.has(cacheKey)) {\n const cached = this.memoryCache.get(cacheKey)!;\n if (Date.now() - cached.timestamp < this.cacheExpiry) {\n this.metrics.cacheHits++;\n return cached.data;\n }\n this.memoryCache.delete(cacheKey);\n }\n\n this.metrics.cacheMisses++;\n\n try {\n let memories = await this.storage.findMemories(\n this.userId,\n query,\n limit,\n options,\n );\n\n if (memories.length === 0) {\n return [];\n }\n\n // Apply vector search if enabled and query provided\n if (this.enableVectorSearch && query.trim() && memories.length > 0) {\n memories = await this.applyVectorSearch(query, memories, options);\n }\n\n // Apply relevance filtering\n if (options.minImportance) {\n memories = memories.filter(\n (m) => m.importance >= options.minImportance!,\n );\n }\n\n // Format results\n const result = memories.map((m) => ({\n ...m,\n relevance_score: m.relevance_score || 0,\n metadata: options.includeMetadata ? m.metadata : undefined,\n }));\n\n // Cache the result\n this.memoryCache.set(cacheKey, {\n data: result,\n timestamp: Date.now(),\n });\n\n return result;\n } catch (error) {\n console.error(\"Error retrieving memories:\", error);\n this.metrics.errors++;\n return [];\n }\n }\n\n /**\n * Apply vector search to memories\n */\n private async applyVectorSearch(\n query: string,\n memories: MemoryRecord[],\n options: MemorySearchOptions,\n ): Promise<MemoryRecord[]> {\n // Placeholder for vector search implementation\n // In production, integrate with your vector similarity API\n // try {\n // this.metrics.vectorSearches++;\n // const sentencesByRelevance = await weighRelevanceConceptVectorAPI(\n // query,\n // memories.map(m => m.content)\n // );\n // await this.updateRelevanceScores(memories, sentencesByRelevance);\n // return memories\n // .map(memory => {\n // const relevanceData = sentencesByRelevance.find(s => s.sentence === memory.content);\n // return {\n // ...memory,\n // relevance_score: relevanceData?.relevance || 0\n // };\n // })\n // .sort((a, b) => b.relevance_score - a.relevance_score);\n // } catch (vectorError) {\n // console.warn('Vector search failed, falling back to basic search:', vectorError);\n // return memories;\n // }\n return memories;\n }\n\n /**\n * Update relevance scores for memories\n */\n private async updateRelevanceScores(\n memories: MemoryRecord[],\n sentencesByRelevance: Array<{ sentence: string; relevance: number }>,\n ): Promise<void> {\n const updates = sentencesByRelevance\n .filter((m) => m.relevance > this.relevanceThreshold)\n .map((m) => {\n const memory = memories.find((mem) => mem.content === m.sentence);\n if (memory) {\n return {\n id: memory.id,\n updates: {\n importance: Math.min(10, memory.importance + m.relevance * 0.5),\n access_count: { increment: 1 },\n updated_at: new Date(),\n },\n };\n }\n return null;\n })\n .filter(Boolean) as Array<{ id: string; updates: any }>;\n\n if (updates.length > 0) {\n await this.storage.batchUpdateMemories(updates);\n }\n }\n\n /**\n * Improved summarization with error handling and batch processing\n */\n async summarizeAndStore(): Promise<boolean> {\n if (this.recentMessages.length === 0 || this.isProcessing) {\n return false;\n }\n\n this.isProcessing = true;\n this.metrics.summarizations++;\n\n try {\n // Create conversation summary\n const conversationText = this.recentMessages\n .map((msg) => `${msg.role}: ${msg.content}`)\n .join(\"\\n\");\n\n // Extract facts using LLM\n const factsResponse =\n await this.extractFactsFromConversation(conversationText);\n\n if (!Array.isArray(factsResponse) || factsResponse.length === 0) {\n console.warn(\"No facts extracted from conversation\");\n return false;\n }\n\n // Process facts in batches\n await this.processFactsInBatches(factsResponse);\n\n // Clear processed messages\n this.recentMessages = [];\n\n return true;\n } catch (error) {\n console.error(\"Error in summarizeAndStore:\", error);\n this.metrics.errors++;\n return false;\n } finally {\n this.isProcessing = false;\n }\n }\n\n /**\n * Extract facts from conversation using LLM\n */\n private async extractFactsFromConversation(\n conversationText: string,\n ): Promise<ExtractedFact[]> {\n try {\n const { extract: factsResponse } = await writeLanguageResponse({\n agent: \"remember-facts\",\n chat_history: conversationText,\n provider: \"groq\",\n model: \"mixtral-8x7b-32768\",\n timeout: MEMORY_CONFIG.DEFAULT_TIMEOUT,\n });\n\n return Array.isArray(factsResponse) ? factsResponse : [];\n } catch (error) {\n console.error(\"Error extracting facts:\", error);\n return [];\n }\n }\n\n /**\n * Process facts in batches to avoid overwhelming the database\n */\n private async processFactsInBatches(\n factsResponse: ExtractedFact[],\n ): Promise<void> {\n for (let i = 0; i < factsResponse.length; i += this.batchSize) {\n const batch = factsResponse.slice(i, i + this.batchSize);\n\n const storePromises = batch.map(async (fact) => {\n try {\n if (fact && typeof fact === \"object\" && fact.content) {\n return await this.storeFact(\n fact.content,\n fact.importance || 1,\n fact.category || MEMORY_TYPES.CONVERSATION,\n fact.metadata || {},\n );\n } else if (typeof fact === \"string\" && fact.trim()) {\n return await this.storeFact(\n fact.trim(),\n 1,\n MEMORY_TYPES.CONVERSATION,\n );\n }\n } catch (error) {\n console.error(\"Error storing individual fact:\", error);\n return null;\n }\n });\n\n await Promise.allSettled(storePromises);\n\n // Small delay between batches\n if (i + this.batchSize < factsResponse.length) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n }\n }\n\n /**\n * Clear cache utility\n */\n clearCache(): void {\n this.memoryCache.clear();\n }\n\n /**\n * Get memory context with better formatting and relevance\n */\n async getMemoryContext(\n query: string = \"\",\n includeRecent: boolean = true,\n options: MemoryContextOptions = {},\n ): Promise<string> {\n const memories = await this.recallRelevantMemories(\n query,\n options.maxMemories || 8,\n { minImportance: options.minImportance || 0.5 },\n );\n\n if (memories.length === 0 && this.recentMessages.length === 0) {\n return \"\";\n }\n\n let context = \"\";\n\n // Add relevant memories\n if (memories.length > 0) {\n context += \"What I remember about you:\\n\";\n memories\n .filter((memory) => memory.importance > (options.minImportance || 0.5))\n .forEach((memory) => {\n const importanceIndicator =\n memory.importance >= 8\n ? \"\\u2b50\"\n : memory.importance >= 5\n ? \"\\u2022\"\n : \"-\";\n context += `${importanceIndicator} ${memory.content}\\n`;\n });\n }\n\n // Add recent conversation if requested\n if (includeRecent && this.recentMessages.length > 0) {\n context += context\n ? \"\\nRecent conversation:\\n\"\n : \"Recent conversation:\\n\";\n this.recentMessages.slice(-3).forEach((msg) => {\n const truncatedContent =\n msg.content.length > 100\n ? msg.content.substring(0, 100) + \"...\"\n : msg.content;\n context += `${msg.role}: ${truncatedContent}\\n`;\n });\n }\n\n return context;\n }\n\n /**\n * Get performance metrics\n */\n getMetrics(): MemoryMetrics {\n return {\n ...this.metrics,\n cacheSize: this.memoryCache.size,\n recentMessagesCount: this.recentMessages.length,\n isProcessing: this.isProcessing,\n };\n }\n}\n","// @ts-nocheck\n/**\n * Memory Agent\n *\n * Enhanced Memory Agent with:\n * - Rate limiting\n * - Multiple LLM provider support\n * - Health monitoring\n * - Conversation management\n * - Memory analytics\n */\n\nimport { SimpleMemory } from \"./storage/in-memory-storage\";\nimport type { IMemoryStorage } from \"./storage/storage-interface\";\nimport type { MemoryType, MemorySearchOptions } from \"./types\";\nimport { MEMORY_CONFIG, MEMORY_TYPES } from \"./types\";\n\n/**\n * LLM provider interface\n */\ninterface LLMProvider {\n invoke: (prompt: string) => Promise<{ content: string; tokensUsed: number }>;\n}\n\n/**\n * Chat options\n */\ninterface ChatOptions {\n provider?: string;\n apiKey?: string;\n model?: string;\n temperature?: number;\n systemPrompt?: string;\n includeHistory?: boolean;\n maxMemories?: number;\n minImportance?: number;\n}\n\n/**\n * Chat response\n */\ninterface ChatResponse {\n content?: string;\n memoryContext?: string;\n success: boolean;\n tokensUsed?: number;\n responseTime?: number;\n sessionId?: string;\n timestamp: string;\n error?: string;\n}\n\n/**\n * Agent analytics\n */\ninterface AgentAnalytics {\n totalMessages: number;\n totalTokens: number;\n averageResponseTime: number;\n errorCount: number;\n sessionStartTime: number;\n}\n\n/**\n * Rate limit configuration\n */\ninterface RateLimitConfig {\n requests: number;\n windowMs: number;\n}\n\n/**\n * Agent options\n */\nexport interface MemoryAgentOptions {\n memoryOptions?: any;\n defaultProvider?: string;\n defaultApiKey?: string;\n defaultModel?: string;\n rateLimit?: RateLimitConfig;\n providers?: Record<string, (apiKey: string, model: string, temperature: number) => LLMProvider>;\n}\n\nexport class MemoryAgent {\n private memory: SimpleMemory;\n private defaultProvider: string;\n private defaultApiKey?: string;\n private defaultModel?: string;\n private rateLimiter: Map<string, number[]>;\n private rateLimitConfig: RateLimitConfig;\n private providers: Record<string, (apiKey: string, model: string, temperature: number) => LLMProvider>;\n private sessionId: string;\n private conversationHistory: Array<{ role: string; content: string }>;\n private analytics: AgentAnalytics;\n private userId: string;\n\n /**\n * Initialize memory agent\n */\n constructor(userId: string, storage: IMemoryStorage, options: MemoryAgentOptions = {}) {\n if (!userId || !storage) {\n throw new Error(\"userId and storage are required parameters\");\n }\n\n this.userId = userId;\n this.memory = new SimpleMemory(userId, storage, options.memoryOptions || {});\n this.defaultProvider = options.defaultProvider || \"groq\";\n this.defaultApiKey = options.defaultApiKey;\n this.defaultModel = options.defaultModel;\n\n // Rate limiting\n this.rateLimiter = new Map();\n this.rateLimitConfig = {\n ...MEMORY_CONFIG.DEFAULT_RATE_LIMIT,\n ...options.rateLimit,\n };\n\n // LLM providers\n this.providers = options.providers || this.getDefaultProviders();\n\n // Session management\n this.sessionId = this.generateSessionId();\n this.conversationHistory = [];\n\n // Analytics\n this.analytics = {\n totalMessages: 0,\n totalTokens: 0,\n averageResponseTime: 0,\n errorCount: 0,\n sessionStartTime: Date.now(),\n };\n }\n\n /**\n * Get default LLM providers\n */\n private getDefaultProviders(): Record<string, (apiKey: string, model: string, temperature: number) => LLMProvider> {\n return {\n groq: (apiKey, model, temperature) => ({\n invoke: async (prompt) => {\n // Implementation would go here\n return { content: \"Default response\", tokensUsed: 0 };\n },\n }),\n openai: (apiKey, model, temperature) => ({\n invoke: async (prompt) => {\n // Implementation would go here\n return { content: \"Default response\", tokensUsed: 0 };\n },\n }),\n };\n }\n\n /**\n * Generate unique session ID\n */\n private generateSessionId(): string {\n return `${this.userId}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n\n /**\n * Rate limiting check with sliding window\n */\n private checkRateLimit(key: string, maxRequests?: number, windowMs?: number): boolean {\n const config = {\n maxRequests: maxRequests || this.rateLimitConfig.requests,\n windowMs: windowMs || this.rateLimitConfig.windowMs,\n };\n\n const now = Date.now();\n const requests = this.rateLimiter.get(key) || [];\n\n // Remove old requests outside the window\n const validRequests = requests.filter(\n (time) => now - time < config.windowMs,\n );\n\n if (validRequests.length >= config.maxRequests) {\n return false;\n }\n\n validRequests.push(now);\n this.rateLimiter.set(key, validRequests);\n return true;\n }\n\n /**\n * Main chat method with comprehensive error handling\n */\n async chat(message: string, options: ChatOptions = {}): Promise<ChatResponse> {\n const startTime = Date.now();\n\n // Input validation\n if (!message || typeof message !== \"string\" || message.trim().length === 0) {\n return {\n error: \"Message cannot be empty\",\n success: false,\n timestamp: new Date().toISOString(),\n };\n }\n\n // Rate limiting\n const rateLimitKey = `chat-${this.userId}`;\n if (!this.checkRateLimit(rateLimitKey)) {\n return {\n error: \"Rate limit exceeded. Please try again later.\",\n success: false,\n timestamp: new Date().toISOString(),\n };\n }\n\n try {\n // Add user message to memory\n this.memory.addMessage(\"user\", message, {\n sessionId: this.sessionId,\n timestamp: Date.now(),\n });\n\n // Get memory context\n const memoryContext = await this.memory.getMemoryContext(message, true, {\n maxMemories: options.maxMemories || 8,\n minImportance: options.minImportance || 0.5,\n });\n\n // Build enhanced prompt\n const prompt = this.buildPrompt(message, memoryContext, options);\n\n // Generate response\n const response = await this.generateResponse(prompt, options);\n\n if (!response || !response.content) {\n throw new Error(\"Invalid response from LLM\");\n }\n\n // Add response to memory\n this.memory.addMessage(\"assistant\", response.content, {\n sessionId: this.sessionId,\n tokensUsed: response.tokensUsed,\n timestamp: Date.now(),\n });\n\n // Update analytics\n this.updateAnalytics(response.tokensUsed, Date.now() - startTime);\n\n return {\n content: response.content,\n memoryContext: memoryContext,\n success: true,\n tokensUsed: response.tokensUsed || 0,\n responseTime: Date.now() - startTime,\n sessionId: this.sessionId,\n timestamp: new Date().toISOString(),\n };\n } catch (error) {\n console.error(\"Chat error:\", error);\n this.analytics.errorCount++;\n\n return {\n error: error.message || \"An unexpected error occurred\",\n success: false,\n timestamp: new Date().toISOString(),\n };\n }\n }\n\n /**\n * Generate LLM response with timeout and error handling\n */\n private async generateResponse(prompt: string, options: ChatOptions): Promise<{ content: string; tokensUsed: number }> {\n const provider = options.provider || this.defaultProvider;\n const apiKey = options.apiKey || this.defaultApiKey;\n const model = options.model || this.defaultModel;\n const temperature = options.temperature || 0.7;\n\n if (!this.providers || !this.providers[provider]) {\n throw new Error(`Provider ${provider} not available`);\n }\n\n const llm = this.providers[provider](apiKey || \"\", model || \"\", temperature);\n\n // Add timeout to LLM call\n const timeoutPromise = new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(\"LLM request timeout\")),\n MEMORY_CONFIG.DEFAULT_TIMEOUT,\n ),\n );\n\n return await Promise.race([llm.invoke(prompt), timeoutPromise]);\n }\n\n /**\n * Build enhanced prompt with context\n */\n private buildPrompt(message: string, memoryContext: string, options: ChatOptions): string {\n let prompt = \"\";\n\n // Add system context if provided\n if (options.systemPrompt) {\n prompt += `${options.systemPrompt}\\n\\n`;\n }\n\n // Add memory context\n if (memoryContext) {\n prompt += `${memoryContext}\\n\\n`;\n }\n\n // Add conversation history if requested\n if (options.includeHistory && this.conversationHistory.length > 0) {\n prompt += \"Recent conversation history:\\n\";\n this.conversationHistory.slice(-5).forEach((msg) => {\n prompt += `${msg.role}: ${msg.content}\\n`;\n });\n prompt += \"\\n\";\n }\n\n prompt += `User: ${message}\\n\\nAssistant:`;\n\n return prompt;\n }\n\n /**\n * Update analytics\n */\n private updateAnalytics(tokensUsed: number, responseTime: number): void {\n this.analytics.totalMessages++;\n this.analytics.totalTokens += tokensUsed || 0;\n this.analytics.averageResponseTime =\n (this.analytics.averageResponseTime * (this.analytics.totalMessages - 1) +\n responseTime) /\n this.analytics.totalMessages;\n }\n\n /**\n * Remember a fact manually\n */\n async remember(\n fact: string,\n importance: number = 1,\n category: MemoryType = MEMORY_TYPES.MANUAL,\n metadata: Record<string, any> = {},\n ): Promise<string> {\n try {\n return await this.memory.storeFact(fact, importance, category, {\n ...metadata,\n source: \"manual\",\n timestamp: Date.now(),\n });\n } catch (error) {\n console.error(\"Error remembering fact:\", error);\n throw error;\n }\n }\n\n /**\n * Get memories with filtering\n */\n async getMemories(query: string = \"\", limit: number = 10, options: MemorySearchOptions = {}): Promise<any[]> {\n return await this.memory.recallRelevantMemories(query, limit, options);\n }\n\n /**\n * Force store summary of current conversation\n */\n async forceStoreSummary(): Promise<boolean> {\n return await this.memory.summarizeAndStore();\n }\n\n /**\n * Health check for the agent\n */\n async healthCheck(): Promise<any> {\n try {\n const memoryMetrics = this.memory.getMetrics();\n const rateLimitStatus = this.checkRateLimit(\"health-check\", 1, 1000);\n\n return {\n status: \"healthy\",\n memory: memoryMetrics,\n rateLimit: rateLimitStatus,\n analytics: this.analytics,\n sessionId: this.sessionId,\n uptime: Date.now() - this.analytics.sessionStartTime,\n timestamp: new Date().toISOString(),\n };\n } catch (error) {\n return {\n status: \"unhealthy\",\n error: error.message,\n timestamp: new Date().toISOString(),\n };\n }\n }\n\n /**\n * Get analytics and performance metrics\n */\n getAnalytics(): any {\n return {\n ...this.analytics,\n memory: this.memory.getMetrics(),\n sessionId: this.sessionId,\n uptime: Date.now() - this.analytics.sessionStartTime,\n };\n }\n\n /**\n * Reset session and clear conversation history\n */\n resetSession(): void {\n this.sessionId = this.generateSessionId();\n this.conversationHistory = [];\n this.analytics.sessionStartTime = Date.now();\n }\n}\n","/**\n * Drizzle Storage Adapter\n *\n * Implementation of IMemoryStorage using Drizzle ORM\n */\n\nimport { sql, eq, and, desc, or, like } from \"drizzle-orm\";\nimport type { IMemoryStorage } from \"./storage-interface\";\nimport type {\n MemoryRecord,\n MemoryType,\n MemorySearchOptions,\n MemoryUpdate,\n} from \"../types\";\n\n/**\n * The Drizzle table passed to {@link DrizzleMemoryStorage} must expose these\n * columns (see {@link createMemorySchema} for the expected shape).\n */\nexport interface MemoryTable {\n id: any;\n user_id: any;\n memory_type: any;\n content: any;\n importance: any;\n access_count: any;\n metadata: any;\n created_at: any;\n updated_at: any;\n}\n\n/**\n * Drizzle-based storage adapter.\n *\n * Pass the Drizzle database instance and the memory table object defined in\n * your schema (not a table-name string) so queries reference real columns:\n *\n * ```ts\n * import { sqliteTable, text, integer, real } from \"drizzle-orm/sqlite-core\";\n * const userMemories = sqliteTable(\"user_memories\", { ... });\n * const storage = new DrizzleMemoryStorage(db, userMemories);\n * ```\n */\nexport class DrizzleMemoryStorage implements IMemoryStorage {\n private db: any;\n private table: MemoryTable & Record<string, any>;\n\n constructor(db: any, table: MemoryTable & Record<string, any>) {\n this.db = db;\n this.table = table;\n }\n\n /**\n * Insert a new memory record\n */\n async insertMemory(\n userId: string,\n memoryType: MemoryType,\n content: string,\n importance: number,\n metadata?: Record<string, any>,\n ): Promise<string> {\n const result = await this.db\n .insert(this.table)\n .values({\n user_id: userId,\n memory_type: memoryType,\n content: content,\n importance: importance,\n access_count: 0,\n metadata: metadata || {},\n created_at: new Date(),\n updated_at: new Date(),\n })\n .returning({ id: this.table.id });\n\n return result[0]?.id;\n }\n\n /**\n * Find memories by user ID and optional filters\n */\n async findMemories(\n userId: string,\n query?: string,\n limit: number = 10,\n options: MemorySearchOptions = {},\n ): Promise<MemoryRecord[]> {\n const conditions = [eq(this.table.user_id, userId)];\n\n if (query && query.trim()) {\n conditions.push(like(this.table.content, `%${query}%`));\n }\n\n if (options.memoryType) {\n conditions.push(eq(this.table.memory_type, options.memoryType));\n }\n\n const results = await this.db\n .select({\n id: this.table.id,\n user_id: this.table.user_id,\n memory_type: this.table.memory_type,\n content: this.table.content,\n importance: this.table.importance,\n access_count: this.table.access_count,\n metadata: this.table.metadata,\n created_at: this.table.created_at,\n updated_at: this.table.updated_at,\n })\n .from(this.table)\n .where(and(...conditions))\n .orderBy(\n desc(this.table.importance),\n desc(this.table.access_count),\n desc(this.table.updated_at),\n )\n .limit(Math.min(limit, 50)); // Cap at 50 for performance\n\n return results as MemoryRecord[];\n }\n\n /**\n * Find similar memories based on content\n */\n async findSimilarMemories(\n userId: string,\n content: string,\n limit: number = 5,\n ): Promise<MemoryRecord[]> {\n // Simple similarity check using keywords\n const words = content\n .toLowerCase()\n .split(/\\s+/)\n .filter((w) => w.length > 2);\n const searchTerms = words.slice(0, 3); // Use first 3 words\n\n if (searchTerms.length === 0) {\n return [];\n }\n\n const conditions = searchTerms.map((term) =>\n like(this.table.content, `%${term}%`),\n );\n\n const results = await this.db\n .select()\n .from(this.table)\n .where(and(eq(this.table.user_id, userId), or(...conditions)))\n .orderBy(desc(this.table.importance), desc(this.table.updated_at))\n .limit(limit);\n\n return results as MemoryRecord[];\n }\n\n /**\n * Update a memory record\n */\n async updateMemory(id: string, updates: MemoryUpdate): Promise<void> {\n const updateData: any = {};\n\n if (updates.importance !== undefined) {\n updateData.importance = updates.importance;\n }\n\n if (updates.access_count !== undefined) {\n if (typeof updates.access_count === \"object\" && updates.access_count.increment) {\n updateData.access_count = sql`${this.table.access_count} + ${updates.access_count.increment}`;\n } else {\n updateData.access_count = updates.access_count;\n }\n }\n\n if (updates.updated_at !== undefined) {\n updateData.updated_at = updates.updated_at;\n }\n\n if (updates.metadata !== undefined) {\n updateData.metadata = updates.metadata;\n }\n\n await this.db.update(this.table).set(updateData).where(eq(this.table.id, id));\n }\n\n /**\n * Delete a memory record\n */\n async deleteMemory(id: string): Promise<void> {\n await this.db.delete(this.table).where(eq(this.table.id, id));\n }\n\n /**\n * Get memory by ID\n */\n async getMemoryById(id: string): Promise<MemoryRecord | null> {\n const results = await this.db\n .select()\n .from(this.table)\n .where(eq(this.table.id, id))\n .limit(1);\n\n return (results[0] as MemoryRecord) || null;\n }\n\n /**\n * Batch update memories\n */\n async batchUpdateMemories(\n updates: Array<{ id: string; updates: MemoryUpdate }>,\n ): Promise<void> {\n const promises = updates.map(({ id, updates: updateData }) =>\n this.updateMemory(id, updateData),\n );\n await Promise.allSettled(promises);\n }\n}\n\n/**\n * Database schema for memory system\n * This is kept here for reference but should be managed by your migration system\n */\nexport function createMemorySchema(db: any) {\n return {\n user_memories: {\n id: \"uuid\",\n user_id: \"string\",\n memory_type: \"string\",\n content: \"text\",\n importance: \"number\",\n access_count: \"number\",\n metadata: \"jsonb\",\n created_at: \"timestamp\",\n updated_at: \"timestamp\",\n },\n };\n}\n","/**\n * @fileoverview Mastra Memory Integration for Cloudflare Workers\n *\n * Integrates Mastra's memory system with Cloudflare Workers environment.\n * Provides persistent conversation memory using D1, KV, or Durable Objects.\n *\n * Features:\n * - Multi-storage backend support (D1, KV, Durable Objects)\n * - Thread-based conversation management\n * - Resource scoping for multi-user scenarios\n * - Cloudflare Workers optimized (edge-ready)\n * - Compatible with existing MemoryAgent architecture\n *\n * @see https://docs.mastra.ai/core/memory\n */\n\nimport { Mastra } from '@mastra/core';\nimport { Agent } from '@mastra/core/agent';\nimport type { D1Database, KVNamespace } from '@cloudflare/workers-types';\nimport type { IMemoryStorage } from './storage/storage-interface';\nimport type { MemoryRecord, MemoryType, MemorySearchOptions, MemoryUpdate } from './types';\n\n/**\n * Cloudflare Workers environment bindings\n */\nexport interface CloudflareEnv {\n DB?: D1Database;\n KV?: KVNamespace;\n OPENAI_API_KEY?: string;\n ANTHROPIC_API_KEY?: string;\n GROQ_API_KEY?: string;\n}\n\n/**\n * Storage backend types for Mastra memory\n */\nexport type MastraStorageBackend = 'memory' | 'd1' | 'kv';\n\n/**\n * Configuration for Mastra memory integration\n */\nexport interface MastraMemoryConfig {\n /** Storage backend (memory, d1, or kv) */\n storage: MastraStorageBackend;\n /** Cloudflare environment bindings */\n env?: CloudflareEnv;\n /** D1 table name (for d1 storage) */\n tableName?: string;\n /** KV key prefix (for kv storage) */\n kvPrefix?: string;\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * D1-based storage adapter for Mastra Memory\n * Implements IMemoryStorage using Cloudflare D1\n */\nexport class MastraD1MemoryStorage implements IMemoryStorage {\n private db: D1Database;\n private tableName: string;\n\n constructor(db: D1Database, tableName: string = 'mastra_memories') {\n this.db = db;\n this.tableName = tableName;\n }\n\n /**\n * Initialize D1 schema for Mastra memory\n */\n async initSchema(): Promise<void> {\n await this.db.exec(`\n CREATE TABLE IF NOT EXISTS ${this.tableName} (\n id TEXT PRIMARY KEY,\n user_id TEXT NOT NULL,\n thread_id TEXT NOT NULL,\n resource_id TEXT,\n memory_type TEXT NOT NULL,\n content TEXT NOT NULL,\n importance REAL DEFAULT 1.0,\n access_count INTEGER DEFAULT 0,\n metadata TEXT,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL\n );\n\n CREATE INDEX IF NOT EXISTS idx_user_thread ON ${this.tableName}(user_id, thread_id);\n CREATE INDEX IF NOT EXISTS idx_resource ON ${this.tableName}(resource_id);\n CREATE INDEX IF NOT EXISTS idx_importance ON ${this.tableName}(importance DESC);\n `);\n }\n\n async insertMemory(\n userId: string,\n memoryType: MemoryType,\n content: string,\n importance: number,\n metadata?: Record<string, any>\n ): Promise<string> {\n const id = crypto.randomUUID();\n const now = Date.now();\n\n await this.db\n .prepare(\n `INSERT INTO ${this.tableName}\n (id, user_id, thread_id, resource_id, memory_type, content, importance, metadata, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`\n )\n .bind(\n id,\n userId,\n metadata?.thread_id || 'default',\n metadata?.resource_id || null,\n memoryType,\n content,\n importance,\n JSON.stringify(metadata || {}),\n now,\n now\n )\n .run();\n\n return id;\n }\n\n async findMemories(\n userId: string,\n query?: string,\n limit: number = 10,\n options: MemorySearchOptions = {}\n ): Promise<MemoryRecord[]> {\n let sql = `SELECT * FROM ${this.tableName} WHERE user_id = ?`;\n const params: any[] = [userId];\n\n if (options.memoryType) {\n sql += ' AND memory_type = ?';\n params.push(options.memoryType);\n }\n\n if (query) {\n sql += ' AND content LIKE ?';\n params.push(`%${query}%`);\n }\n\n if (options.minImportance !== undefined) {\n sql += ' AND importance >= ?';\n params.push(options.minImportance);\n }\n\n sql += ' ORDER BY importance DESC, updated_at DESC LIMIT ?';\n params.push(limit);\n\n const result = await this.db.prepare(sql).bind(...params).all();\n\n return (result.results || []).map((row: any) => ({\n id: row.id,\n user_id: row.user_id,\n memory_type: row.memory_type,\n content: row.content,\n importance: row.importance,\n access_count: row.access_count,\n metadata: JSON.parse(row.metadata || '{}'),\n created_at: new Date(row.created_at),\n updated_at: new Date(row.updated_at),\n }));\n }\n\n async findSimilarMemories(\n userId: string,\n content: string,\n limit: number = 5\n ): Promise<MemoryRecord[]> {\n // Simple keyword-based similarity for D1 (no vector search)\n const words = content.toLowerCase().split(/\\s+/).filter(w => w.length > 2);\n const searchTerms = words.slice(0, 3);\n\n if (searchTerms.length === 0) return [];\n\n const likeConditions = searchTerms.map(() => 'content LIKE ?').join(' OR ');\n const params = [userId, ...searchTerms.map(term => `%${term}%`), limit];\n\n const result = await this.db\n .prepare(\n `SELECT * FROM ${this.tableName}\n WHERE user_id = ? AND (${likeConditions})\n ORDER BY importance DESC, updated_at DESC\n LIMIT ?`\n )\n .bind(...params)\n .all();\n\n return (result.results || []).map((row: any) => ({\n id: row.id,\n user_id: row.user_id,\n memory_type: row.memory_type,\n content: row.content,\n importance: row.importance,\n access_count: row.access_count,\n metadata: JSON.parse(row.metadata || '{}'),\n created_at: new Date(row.created_at),\n updated_at: new Date(row.updated_at),\n }));\n }\n\n async updateMemory(id: string, updates: MemoryUpdate): Promise<void> {\n const fields: string[] = [];\n const params: any[] = [];\n\n if (updates.importance !== undefined) {\n fields.push('importance = ?');\n params.push(updates.importance);\n }\n\n if (updates.access_count !== undefined) {\n if (typeof updates.access_count === 'object' && updates.access_count.increment) {\n fields.push('access_count = access_count + ?');\n params.push(updates.access_count.increment);\n } else {\n fields.push('access_count = ?');\n params.push(updates.access_count);\n }\n }\n\n if (updates.metadata !== undefined) {\n fields.push('metadata = ?');\n params.push(JSON.stringify(updates.metadata));\n }\n\n fields.push('updated_at = ?');\n params.push(Date.now());\n params.push(id);\n\n if (fields.length > 0) {\n await this.db\n .prepare(`UPDATE ${this.tableName} SET ${fields.join(', ')} WHERE id = ?`)\n .bind(...params)\n .run();\n }\n }\n\n async deleteMemory(id: string): Promise<void> {\n await this.db.prepare(`DELETE FROM ${this.tableName} WHERE id = ?`).bind(id).run();\n }\n\n async getMemoryById(id: string): Promise<MemoryRecord | null> {\n const result = await this.db\n .prepare(`SELECT * FROM ${this.tableName} WHERE id = ?`)\n .bind(id)\n .first();\n\n if (!result) return null;\n\n return {\n id: result.id as string,\n user_id: result.user_id as string,\n memory_type: result.memory_type as MemoryType,\n content: result.content as string,\n importance: result.importance as number,\n access_count: result.access_count as number,\n metadata: JSON.parse((result.metadata as string) || '{}'),\n created_at: new Date(result.created_at as number),\n updated_at: new Date(result.updated_at as number),\n };\n }\n\n async batchUpdateMemories(updates: Array<{ id: string; updates: MemoryUpdate }>): Promise<void> {\n for (const { id, updates: updateData } of updates) {\n await this.updateMemory(id, updateData);\n }\n }\n}\n\n/**\n * KV-based storage adapter for Mastra Memory\n * Uses Cloudflare KV for simple key-value storage\n */\nexport class MastraKVMemoryStorage implements IMemoryStorage {\n private kv: KVNamespace;\n private prefix: string;\n\n constructor(kv: KVNamespace, prefix: string = 'mastra:memory:') {\n this.kv = kv;\n this.prefix = prefix;\n }\n\n private getUserKey(userId: string): string {\n return `${this.prefix}user:${userId}`;\n }\n\n private getMemoryKey(id: string): string {\n return `${this.prefix}memory:${id}`;\n }\n\n async insertMemory(\n userId: string,\n memoryType: MemoryType,\n content: string,\n importance: number,\n metadata?: Record<string, any>\n ): Promise<string> {\n const id = crypto.randomUUID();\n const now = Date.now();\n\n const memory: MemoryRecord = {\n id,\n user_id: userId,\n memory_type: memoryType,\n content,\n importance,\n access_count: 0,\n metadata: metadata || {},\n created_at: new Date(now),\n updated_at: new Date(now),\n };\n\n // Store memory\n await this.kv.put(this.getMemoryKey(id), JSON.stringify(memory));\n\n // Update user's memory list\n const userKey = this.getUserKey(userId);\n const userMemories = await this.kv.get(userKey, 'json') as string[] || [];\n userMemories.push(id);\n await this.kv.put(userKey, JSON.stringify(userMemories));\n\n return id;\n }\n\n async findMemories(\n userId: string,\n query?: string,\n limit: number = 10,\n options: MemorySearchOptions = {}\n ): Promise<MemoryRecord[]> {\n const userKey = this.getUserKey(userId);\n const memoryIds = await this.kv.get(userKey, 'json') as string[] || [];\n\n const memories = await Promise.all(\n memoryIds.map(id => this.getMemoryById(id))\n );\n\n let filtered = memories.filter((m): m is MemoryRecord => m !== null);\n\n if (query) {\n filtered = filtered.filter(m =>\n m.content.toLowerCase().includes(query.toLowerCase())\n );\n }\n\n if (options.memoryType) {\n filtered = filtered.filter(m => m.memory_type === options.memoryType);\n }\n\n if (options.minImportance !== undefined) {\n filtered = filtered.filter(m => m.importance >= options.minImportance!);\n }\n\n return filtered\n .sort((a, b) => b.importance - a.importance || b.updated_at.getTime() - a.updated_at.getTime())\n .slice(0, limit);\n }\n\n async findSimilarMemories(\n userId: string,\n content: string,\n limit: number = 5\n ): Promise<MemoryRecord[]> {\n const words = content.toLowerCase().split(/\\s+/).filter(w => w.length > 2);\n const searchTerms = words.slice(0, 3);\n\n if (searchTerms.length === 0) return [];\n\n const memories = await this.findMemories(userId, '', 50);\n\n return memories\n .filter(m =>\n searchTerms.some(term => m.content.toLowerCase().includes(term))\n )\n .slice(0, limit);\n }\n\n async updateMemory(id: string, updates: MemoryUpdate): Promise<void> {\n const memory = await this.getMemoryById(id);\n if (!memory) return;\n\n if (updates.importance !== undefined) {\n memory.importance = updates.importance;\n }\n\n if (updates.access_count !== undefined) {\n if (typeof updates.access_count === 'object') {\n memory.access_count += updates.access_count.increment ?? 0;\n } else {\n memory.access_count = updates.access_count;\n }\n }\n\n if (updates.metadata !== undefined) {\n memory.metadata = { ...memory.metadata, ...updates.metadata };\n }\n\n memory.updated_at = new Date();\n\n await this.kv.put(this.getMemoryKey(id), JSON.stringify(memory));\n }\n\n async deleteMemory(id: string): Promise<void> {\n const memory = await this.getMemoryById(id);\n if (!memory) return;\n\n await this.kv.delete(this.getMemoryKey(id));\n\n // Remove from user's list\n const userKey = this.getUserKey(memory.user_id);\n const userMemories = await this.kv.get(userKey, 'json') as string[] || [];\n const filtered = userMemories.filter(mId => mId !== id);\n await this.kv.put(userKey, JSON.stringify(filtered));\n }\n\n async getMemoryById(id: string): Promise<MemoryRecord | null> {\n const data = await this.kv.get(this.getMemoryKey(id), 'json') as any;\n if (!data) return null;\n\n return {\n ...data,\n created_at: new Date(data.created_at),\n updated_at: new Date(data.updated_at),\n };\n }\n\n async batchUpdateMemories(updates: Array<{ id: string; updates: MemoryUpdate }>): Promise<void> {\n await Promise.all(\n updates.map(({ id, updates: updateData }) => this.updateMemory(id, updateData))\n );\n }\n}\n\n/**\n * Mastra Memory Manager for Cloudflare Workers\n * Wraps Mastra's memory system with Cloudflare-compatible storage\n */\nexport class MastraMemoryManager {\n private mastra: Mastra | null = null;\n private storage: IMemoryStorage;\n private config: MastraMemoryConfig;\n\n constructor(config: MastraMemoryConfig) {\n this.config = config;\n\n // Initialize storage backend\n if (config.storage === 'd1' && config.env?.DB) {\n this.storage = new MastraD1MemoryStorage(config.env.DB, config.tableName);\n } else if (config.storage === 'kv' && config.env?.KV) {\n this.storage = new MastraKVMemoryStorage(config.env.KV, config.kvPrefix);\n } else {\n throw new Error(`Invalid storage configuration: ${config.storage}`);\n }\n }\n\n /**\n * Initialize Mastra instance with memory\n */\n async initialize(): Promise<Mastra> {\n if (this.mastra) return this.mastra;\n\n // Memory persistence is handled by this manager's own D1/KV storage\n // adapters rather than a Mastra memory backend.\n this.mastra = new Mastra({});\n\n // Initialize D1 schema if needed\n if (this.config.storage === 'd1' && this.storage instanceof MastraD1MemoryStorage) {\n await this.storage.initSchema();\n }\n\n return this.mastra;\n }\n\n /**\n * Get storage instance (for direct access)\n */\n getStorage(): IMemoryStorage {\n return this.storage;\n }\n\n /**\n * Create an agent with memory\n */\n async createAgent(config: {\n id: string;\n name: string;\n instructions: string;\n model: any;\n tools?: Record<string, any>;\n userId: string;\n threadId?: string;\n resourceId?: string;\n }): Promise<Agent> {\n const mastra = await this.initialize();\n\n // Get or create agent with memory\n const agent = new Agent({\n id: config.id,\n name: config.name,\n instructions: config.instructions,\n model: config.model,\n tools: config.tools || {},\n });\n\n // Attach memory context\n (agent as any).memoryContext = {\n userId: config.userId,\n threadId: config.threadId || 'default',\n resourceId: config.resourceId,\n };\n\n return agent;\n }\n\n /**\n * Store a message in memory\n */\n async storeMessage(\n userId: string,\n threadId: string,\n role: 'user' | 'assistant',\n content: string,\n metadata?: Record<string, any>\n ): Promise<string> {\n return await this.storage.insertMemory(\n userId,\n 'conversation',\n content,\n 1.0,\n {\n thread_id: threadId,\n role,\n ...metadata,\n }\n );\n }\n\n /**\n * Recall conversation history\n */\n async recallConversation(\n userId: string,\n threadId: string,\n limit: number = 20\n ): Promise<Array<{ role: 'user' | 'assistant'; content: string; timestamp: Date }>> {\n const memories = await this.storage.findMemories(\n userId,\n undefined,\n limit,\n { memoryType: 'conversation' }\n );\n\n return memories\n .filter(m => m.metadata?.thread_id === threadId)\n .map(m => ({\n role: m.metadata?.role || 'user',\n content: m.content,\n timestamp: m.created_at,\n }))\n .sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());\n }\n\n /**\n * Get relevant context for a query\n */\n async getRelevantContext(\n userId: string,\n query: string,\n limit: number = 5\n ): Promise<string> {\n const memories = await this.storage.findSimilarMemories(userId, query, limit);\n\n if (memories.length === 0) return '';\n\n return memories.map(m => m.content).join('\\n\\n');\n }\n}\n\n/**\n * Quick helper to create Mastra memory manager for Cloudflare Workers\n *\n * @example\n * ```ts\n * const memoryManager = createMastraMemory({\n * storage: 'd1',\n * env: env, // Cloudflare env bindings\n * });\n *\n * const agent = await memoryManager.createAgent({\n * id: 'assistant',\n * name: 'AI Assistant',\n * instructions: 'Help users with their questions',\n * model: openai('gpt-4o'),\n * userId: 'user-123',\n * threadId: 'conversation-1',\n * });\n * ```\n */\nexport function createMastraMemory(config: MastraMemoryConfig): MastraMemoryManager {\n return new MastraMemoryManager(config);\n}\n","/**\n * @fileoverview Specialized tools for AI agents to interact with the QwkSearch API.\n * Provides web search, content extraction, and AI response generation.\n */\n\n// @ts-nocheck\nimport { z } from \"zod\";\nimport * as QwkSearch from 'qwksearch-api-client'; // Update this path to match your QwkSearch module location\n\n// Configuration for QwkSearch API\nconst QWKSEARCH_CONFIG = {\n baseURL: typeof process !== \"undefined\" && process?.env.QWKSEARCH_URL || 'https://app.qwksearch.com/api',\n apiKey: typeof process !== \"undefined\" && process?.env.QWKSEARCH_API_KEY || null,\n};\n\n/**\n * List of tools available for agent usage, including their schemas and implementation.\n */\nexport const AGENT_TOOLS = [\n\n {\n name: \"web_search\",\n description:\n \"Search the web for information on any topic using QwkSearch API. Input: search query string and optional category. Returns relevant search results with titles, descriptions, and URLs from 100+ sources via SearXNG metasearch engine.\",\n schema: z.object({\n query: z.string(),\n category: z.enum([\"general\", \"news\", \"videos\", \"images\", \"science\", \"files\", \"it\"]).optional().default(\"general\"),\n recency: z.enum([\"none\", \"day\", \"week\", \"month\", \"year\"]).optional().default(\"none\"),\n page: z.number().optional().default(1),\n language: z.string().optional().default(\"en-US\"),\n public: z.boolean().optional().default(false),\n timeout: z.number().optional().default(10),\n baseURL: z.string().optional(),\n apiKey: z.string().optional()\n }),\n func: async ({ query, category = \"general\", recency = \"none\", page = 1, language = \"en-US\", public: isPublic = false, timeout = 10, baseURL, apiKey }) => {\n try {\n // Use provided config or fall back to environment/defaults\n const baseUrl = baseURL || QWKSEARCH_CONFIG.baseURL;\n const headers = apiKey || QWKSEARCH_CONFIG.apiKey ? { 'x-api-key': apiKey || QWKSEARCH_CONFIG.apiKey } : undefined;\n\n const result = await QwkSearch.searchWeb({\n query: {\n q: query,\n cat: category,\n recency: recency,\n page: page,\n lang: language,\n public: isPublic,\n timeout: timeout\n },\n baseUrl: baseUrl,\n ...(headers && { headers })\n });\n\n if (!result.data || !result.data.results || result.data.results.length === 0) {\n return `No search results found for \"${query}\". Please try a different search term.`;\n }\n\n let resultText = `Web search results for \"${query}\" (${category} category):\\n\\n`;\n\n result.data.results.forEach((searchResult, index) => {\n resultText += `${index + 1}. ${searchResult.title}\\n`;\n resultText += ` URL: ${searchResult.url}\\n`;\n if (searchResult.domain) {\n resultText += ` Domain: ${searchResult.domain}\\n`;\n }\n if (searchResult.snippet) {\n resultText += ` Description: ${searchResult.snippet}\\n`;\n }\n if (searchResult.engines && searchResult.engines.length > 0) {\n resultText += ` Sources: ${searchResult.engines.join(\", \")}\\n`;\n }\n resultText += `\\n`;\n });\n\n resultText += `Found ${result.data.results.length} results from multiple search engines. This is the complete search information.`;\n\n return resultText;\n } catch (error) {\n return `Unable to perform web search for \"${query}\". Error: ${error.message}`;\n }\n },\n },\n {\n name: \"extract_page\",\n description:\n \"Extract and summarize content from a web page using QwkSearch API. Supports articles, PDFs, and YouTube videos. Uses Mozilla Readability and Postlight Mercury algorithms with 100+ custom adapters for major sites. Input: URL of the page to extract. Returns structured content with citation information.\",\n schema: z.object({\n url: z.string().url(),\n images: z.boolean().optional().default(true),\n links: z.boolean().optional().default(true),\n formatting: z.boolean().optional().default(true),\n absoluteURLs: z.boolean().optional().default(true),\n timeout: z.number().min(1).max(30).optional().default(10),\n baseURL: z.string().optional(),\n apiKey: z.string().optional()\n }),\n func: async ({ url, images = true, links = true, formatting = true, absoluteURLs = true, timeout = 10, baseURL, apiKey }) => {\n try {\n // Use provided config or fall back to environment/defaults\n const baseUrl = baseURL || QWKSEARCH_CONFIG.baseURL;\n const headers = apiKey || QWKSEARCH_CONFIG.apiKey ? { 'x-api-key': apiKey || QWKSEARCH_CONFIG.apiKey } : undefined;\n\n const result = await QwkSearch.extractContent({\n query: {\n url: url,\n images: images,\n links: links,\n formatting: formatting,\n absoluteURLs: absoluteURLs,\n timeout: timeout\n },\n baseUrl: baseUrl,\n ...(headers && { headers })\n });\n\n if (!result.data) {\n return `No content could be extracted from \"${url}\". Please check the URL and try again.`;\n }\n\n const data = result.data;\n\n let resultText = `Content extracted from: ${data.url || url}\\n\\n`;\n\n if (data.title) {\n resultText += `Title: ${data.title}\\n\\n`;\n }\n\n if (data.author) {\n resultText += `Author: ${data.author}\\n`;\n if (data.author_cite) {\n resultText += `Author (Citation Format): ${data.author_cite}\\n`;\n }\n if (data.author_type) {\n resultText += `Author Type: ${data.author_type}\\n`;\n }\n }\n\n if (data.date) {\n resultText += `Publication Date: ${data.date}\\n`;\n }\n\n if (data.source) {\n resultText += `Source: ${data.source}\\n`;\n }\n\n if (data.word_count) {\n resultText += `Word Count: ${data.word_count}\\n`;\n }\n\n if (data.cite) {\n resultText += `\\nCitation (APA Format): ${data.cite}\\n`;\n }\n\n if (data.html) {\n resultText += `\\nContent:\\n${data.html}\\n\\n`;\n }\n\n resultText += `This is the complete page extraction information.`;\n\n return resultText;\n } catch (error) {\n return `Unable to extract content from \"${url}\". Error: ${error.message}`;\n }\n },\n },\n {\n name: \"generate_ai_response\",\n description:\n \"Generate AI language model responses using QwkSearch API with various agent templates. Supports multiple providers (Groq, OpenAI, Anthropic, etc.) and agent types for different tasks like summarization, question answering, and content generation.\",\n schema: z.object({\n provider: z.enum([\"groq\", \"openai\", \"anthropic\", \"together\", \"xai\", \"google\", \"perplexity\", \"cloudflare\"]),\n key: z.string().optional(),\n agent: z.enum([\n \"question\",\n \"summarize-bullets\",\n \"summarize\",\n \"suggest-followups\",\n \"answer-cite-sources\",\n \"query-resolution\",\n \"knowledge-graph-nodes\",\n \"summary-longtext\"\n ]).optional().default(\"question\"),\n model: z.string().optional().default(\"meta-llama/llama-4-maverick-17b-128e-instruct\"),\n temperature: z.number().min(0).max(2).optional().default(0.7),\n html: z.boolean().optional().default(true),\n query: z.string().optional(),\n chat_history: z.string().optional(),\n article: z.string().optional(),\n baseURL: z.string().optional(),\n apiKey: z.string().optional()\n }),\n func: async ({ provider, key, agent = \"question\", model = \"meta-llama/llama-4-maverick-17b-128e-instruct\", temperature = 0.7, html = true, query, chat_history, article, baseURL, apiKey }) => {\n try {\n // Use provided config or fall back to environment/defaults\n const baseUrl = baseURL || QWKSEARCH_CONFIG.baseURL;\n const headers = apiKey || QWKSEARCH_CONFIG.apiKey ? { 'x-api-key': apiKey || QWKSEARCH_CONFIG.apiKey } : undefined;\n\n const requestBody = {\n agent,\n provider,\n model,\n html,\n temperature\n };\n\n if (key) {\n requestBody.key = key;\n }\n\n if (query) {\n requestBody.query = query;\n }\n\n if (chat_history) {\n requestBody.chat_history = chat_history;\n }\n\n if (article) {\n requestBody.article = article;\n }\n\n const result = await QwkSearch.writeLanguage({\n body: requestBody,\n baseUrl: baseUrl,\n ...(headers && { headers })\n });\n\n if (!result.data) {\n return `No response generated. Please check your input parameters and try again.`;\n }\n\n let resultText = `AI Response (${agent} agent, ${provider} provider):\\n\\n`;\n\n if (result.data.content) {\n resultText += result.data.content;\n }\n\n if (result.data.extract) {\n resultText += `\\n\\nStructured Extract:\\n${JSON.stringify(result.data.extract, null, 2)}`;\n }\n\n resultText += `\\n\\nThis is the complete AI-generated response.`;\n\n return resultText;\n } catch (error) {\n return `Unable to generate AI response. Error: ${error.message}`;\n }\n },\n },\n {\n name: \"render_page_with_javascript\",\n description:\n \"Render a web page with JavaScript execution using Cloudflare Browser Rendering. Use this for JavaScript-heavy sites (SPAs, React apps), pages behind bot protection (Cloudflare, reCAPTCHA), or when extract_page fails. Returns fully rendered HTML with JavaScript executed. Slower but more complete than extract_page.\",\n schema: z.object({\n url: z.string().url(),\n blockImages: z.boolean().optional().default(true),\n wait: z.number().min(0).max(10000).optional().default(0),\n timeout: z.number().min(1000).max(60000).optional().default(30000),\n waitUntil: z.enum([\"domcontentloaded\", \"load\", \"networkidle0\", \"networkidle2\"]).optional().default(\"networkidle2\"),\n bypassCaptcha: z.boolean().optional().default(true),\n sessionId: z.string().optional().default(\"default\"),\n format: z.enum([\"html\", \"json\"]).optional().default(\"html\"),\n scraperUrl: z.string().optional(),\n scraperApiKey: z.string().optional()\n }),\n func: async ({ url, blockImages = true, wait = 0, timeout = 30000, waitUntil = \"networkidle2\", bypassCaptcha = true, sessionId = \"default\", format = \"html\", scraperUrl, scraperApiKey }) => {\n try {\n const scraperEndpoint = scraperUrl || (typeof process !== \"undefined\" && process?.env?.SCRAPER_URL) || 'https://scraper.qwksearch.workers.dev';\n const apiKey = scraperApiKey || (typeof process !== \"undefined\" && process?.env?.SCRAPER_API_KEY);\n\n const requestUrl = new URL('/api/render', scraperEndpoint);\n\n const body = {\n url,\n blockImages,\n wait,\n timeout,\n waitUntil,\n bypassCaptcha,\n sessionId,\n format\n };\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n if (apiKey) {\n headers['Authorization'] = `Bearer ${apiKey}`;\n }\n\n const response = await fetch(requestUrl.toString(), {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n return `Failed to render page: ${errorText}`;\n }\n\n if (format === 'json') {\n const data = await response.json();\n let resultText = `Page rendered successfully: ${data.url}\\n\\n`;\n if (data.title) {\n resultText += `Title: ${data.title}\\n`;\n }\n resultText += `Load Time: ${data.loadTime}ms\\n`;\n if (data.challengeBypassed) {\n resultText += `Challenge Bypassed: Yes (${data.retryCount} retries)\\n`;\n }\n resultText += `\\nRendered HTML Content:\\n${data.html}\\n\\n`;\n resultText += `This is the complete rendered page content.`;\n return resultText;\n }\n\n const html = await response.text();\n return `Page rendered successfully.\\n\\nHTML Content:\\n${html}`;\n } catch (error) {\n return `Unable to render page \"${url}\". Error: ${error.message}`;\n }\n },\n },\n];","/**\n * @module agent-toolkit/utils/outputParser\n * @description Parsers that extract values from XML-tagged sections of LLM\n * output (e.g. `<links>...</links>`, `<question>...</question>`).\n */\n\nconst LIST_MARKER_REGEX = /^(\\s*(-|\\*|\\d+\\.\\s|\\d+\\)\\s|•)\\s*)+/;\n\ninterface LineListOutputParserArgs {\n key?: string;\n}\n\nexport class LineListOutputParser {\n private key = \"questions\";\n\n constructor(args?: LineListOutputParserArgs) {\n this.key = args?.key ?? this.key;\n }\n\n async parse(text: string): Promise<string[]> {\n text = text.trim() || \"\";\n\n const startKeyIndex = text.indexOf(`<${this.key}>`);\n const endKeyIndex = text.indexOf(`</${this.key}>`);\n\n if (startKeyIndex === -1 || endKeyIndex === -1) {\n return [];\n }\n\n const questionsStartIndex = startKeyIndex + `<${this.key}>`.length;\n const lines = text\n .slice(questionsStartIndex, endKeyIndex)\n .trim()\n .split(\"\\n\")\n .filter((line) => line.trim() !== \"\")\n .map((line) => line.replace(LIST_MARKER_REGEX, \"\"));\n\n return lines;\n }\n}\n\ninterface LineOutputParserArgs {\n key?: string;\n}\n\nexport class LineOutputParser {\n private key = \"questions\";\n\n constructor(args?: LineOutputParserArgs) {\n this.key = args?.key ?? this.key;\n }\n\n async parse(text: string): Promise<string | undefined> {\n text = text.trim() || \"\";\n\n const startKeyIndex = text.indexOf(`<${this.key}>`);\n const endKeyIndex = text.indexOf(`</${this.key}>`);\n\n if (startKeyIndex === -1 || endKeyIndex === -1) {\n return undefined;\n }\n\n const questionsStartIndex = startKeyIndex + `<${this.key}>`.length;\n const line = text\n .slice(questionsStartIndex, endKeyIndex)\n .trim()\n .replace(LIST_MARKER_REGEX, \"\");\n\n return line;\n }\n}\n\nexport default LineOutputParser;\n","/**\n * Chat history formatting utilities\n */\n\ntype ChatHistoryMessage = {\n content?: unknown;\n role?: string;\n type?: string;\n};\n\nexport const formatChatHistoryAsString = (history: ChatHistoryMessage[]) => {\n return history\n .map(\n (message) =>\n `${message.role === 'assistant' || message.type === 'ai' ? 'AI' : 'User'}: ${String(message.content ?? '')}`,\n )\n .join('\\n');\n};\n","/**\n * @module research/search/doc-utils\n * @description Document utilities: fallback docs, reranking, and formatting.\n */\nimport type { Document } from \"./document\";\n\nexport interface R2CredentialsInput {\n accountId: string;\n accessKeyId: string;\n secretAccessKey: string;\n bucket: string;\n}\n\nexport function buildFallbackDocs(query: string): Document[] {\n const trimmedQuery = (query || \"\").trim();\n const searchQuery = trimmedQuery.length > 0 ? trimmedQuery : \"web search\";\n const fallbackUrl = `https://www.google.com/search?q=${encodeURIComponent(searchQuery)}`;\n\n return [\n {\n pageContent:\n \"No indexed sources were returned by the configured search providers for this query.\",\n metadata: {\n title: `Search results for: ${searchQuery}`,\n url: fallbackUrl,\n source: \"Google Search\",\n },\n },\n ];\n}\n\nexport function normalizeSourcesOutput(output: unknown, query: string): Document[] {\n if (Array.isArray(output) && output.length > 0) {\n return output as Document[];\n }\n return buildFallbackDocs(query);\n}\n\nasync function downloadExtractedContent(fileId: string, r2Credentials: R2CredentialsInput): Promise<{ title: string; content: string } | null> {\n try {\n const { manageStorage } = await import(\"manage-storage\");\n const config = {\n provider: \"cloudflare\" as const,\n BUCKET_NAME: r2Credentials.bucket,\n ACCESS_KEY_ID: r2Credentials.accessKeyId,\n SECRET_ACCESS_KEY: r2Credentials.secretAccessKey,\n BUCKET_URL: `https://${r2Credentials.accountId}.r2.cloudflarestorage.com`,\n };\n const extractedKey = `${fileId}-extracted.json`;\n const data = await manageStorage(\"download\", { ...config, key: extractedKey });\n const parsed = JSON.parse(data);\n return { title: parsed.title || \"Uploaded Document\", content: parsed.content || \"\" };\n } catch (error) {\n console.error(`[rerankDocs] Failed to download extracted content for fileId ${fileId}:`, error);\n return null;\n }\n}\n\nexport async function rerankDocs(\n query: string,\n docs: Document[],\n fileIds: string[],\n optimizationMode: \"speed\" | \"balanced\" | \"quality\",\n r2Credentials?: R2CredentialsInput,\n): Promise<Document[]> {\n if (docs.length === 0 && fileIds.length === 0) {\n return docs;\n }\n\n let filesData: { title: string; content: string }[] = [];\n\n if (fileIds.length > 0 && r2Credentials) {\n const results = await Promise.all(\n fileIds.map((fileId) => downloadExtractedContent(fileId, r2Credentials))\n );\n filesData = results.filter((r) => r !== null);\n }\n\n if (query.toLocaleLowerCase() === \"summarize\") {\n return docs.slice(0, 15);\n }\n\n const docsWithContent = docs.filter(\n (doc) => doc.pageContent && doc.pageContent.length > 0,\n );\n\n const fileDocs: Document[] = filesData.map((fileData) => ({\n pageContent: fileData.content,\n metadata: { title: fileData.title, url: \"File\" },\n }));\n\n // Combine file docs with web results, cap at 15\n return [...fileDocs, ...docsWithContent].slice(0, 15);\n}\n\nexport function processDocs(docs: Document[]): string {\n return docs\n .map(\n (_, index) =>\n `${index + 1}. ${docs[index].metadata.title} ${docs[index].pageContent}`,\n )\n .join(\"\\n\");\n}\n","/**\n * @module research/search/link-summarizer\n * @description Groups link documents by URL then summarizes each group with an LLM.\n */\nimport { generateText, type LanguageModel } from \"ai\";\nimport type { Document } from \"./document\";\nimport { buildFallbackDocs } from \"./doc-utils\";\n\nconst SUMMARIZER_PROMPT = `You are a web search summarizer, tasked with summarizing a piece of text retrieved from a web search. Your job is to summarize the\ntext into a detailed, 2-4 paragraph explanation that captures the main ideas and provides a comprehensive answer to the query.\nIf the query is \"summarize\", you should provide a detailed summary of the text. If the query is a specific question, you should answer it in the summary.\n\n- **Journalistic tone**: The summary should sound professional and journalistic, not too casual or vague.\n- **Thorough and detailed**: Ensure that every key point from the text is captured and that the summary directly answers the query.\n- **Not too lengthy, but detailed**: The summary should be informative but not excessively long. Focus on providing detailed information in a concise format.\n\nThe text will be shared inside the \\`text\\` XML tag, and the query inside the \\`query\\` XML tag.\n\n<example>\n1. \\`<text>\nDocker is a set of platform-as-a-service products that use OS-level virtualization to deliver software in packages called containers.\nIt was first released in 2013 and is developed by Docker, Inc. Docker is designed to make it easier to create, deploy, and run applications\nby using containers.\n</text>\n\n<query>\nWhat is Docker and how does it work?\n</query>\n\nResponse:\nDocker is a revolutionary platform-as-a-service product developed by Docker, Inc., that uses container technology to make application\ndeployment more efficient. It allows developers to package their software with all necessary dependencies, making it easier to run in\nany environment. Released in 2013, Docker has transformed the way applications are built, deployed, and managed.\n\\`\n2. \\`<text>\nThe theory of relativity, or simply relativity, encompasses two interrelated theories of Albert Einstein: special relativity and general\nrelativity. However, the word \"relativity\" is sometimes used in reference to Galilean invariance. The term \"theory of relativity\" was based\non the expression \"relative theory\" used by Max Planck in 1906. The theory of relativity usually encompasses two interrelated theories by\nAlbert Einstein: special relativity and general relativity. Special relativity applies to all physical phenomena in the absence of gravity.\nGeneral relativity explains the law of gravitation and its relation to other forces of nature. It applies to the cosmological and astrophysical\nrealm, including astronomy.\n</text>\n\n<query>\nsummarize\n</query>\n\nResponse:\nThe theory of relativity, developed by Albert Einstein, encompasses two main theories: special relativity and general relativity. Special\nrelativity applies to all physical phenomena in the absence of gravity, while general relativity explains the law of gravitation and its\nrelation to other forces of nature. The theory of relativity is based on the concept of \"relative theory,\" as introduced by Max Planck in\n1906. It is a fundamental theory in physics that has revolutionized our understanding of the universe.\n\\`\n</example>\n\nEverything below is the actual data you will be working with. Good luck!\n\n<query>\n{question}\n</query>\n\n<text>\n{content}\n</text>\n\nMake sure to answer the query in the summary.`;\n\n/**\n * Groups fetched link documents by URL (max 10 chunks per URL), then\n * summarizes each group with the LLM in parallel.\n */\nexport async function groupAndSummarizeDocs(\n llm: LanguageModel,\n linkDocs: Document[],\n question: string,\n): Promise<Document[]> {\n // Group chunks by URL, capping at 10 chunks each\n const docGroups: Document[] = [];\n\n for (const doc of linkDocs) {\n const existing = docGroups.find(\n (d) => d.metadata.url === doc.metadata.url && d.metadata.totalDocs < 10,\n );\n\n if (!existing) {\n docGroups.push({ ...doc, metadata: { ...doc.metadata, totalDocs: 1 } });\n } else {\n existing.pageContent += `\\n\\n${doc.pageContent}`;\n existing.metadata.totalDocs += 1;\n }\n }\n\n // Summarize each group in parallel\n const docs: Document[] = [];\n\n await Promise.all(\n docGroups.map(async (doc) => {\n const prompt = SUMMARIZER_PROMPT.replace(\"{question}\", question).replace(\n \"{content}\",\n doc.pageContent,\n );\n const { text } = await generateText({ model: llm, prompt });\n\n docs.push({\n pageContent: text,\n metadata: { title: doc.metadata.title, url: doc.metadata.url },\n });\n }),\n );\n\n return docs.length > 0 ? docs : buildFallbackDocs(question);\n}\n","/**\n * @fileoverview Orchestrator for complex research queries.\n * Manages query expansion, web search execution, and result synthesis using\n * LLMs through the Vercel AI SDK (generateText/streamText).\n */\nimport { generateText, streamText, type LanguageModel } from \"ai\";\nimport { LineOutputParser, LineListOutputParser } from \"../../utils/outputParser\";\nimport type { Document } from \"./document\";\n\n/** Strip HTML tags and decode entities — works in Cloudflare edge runtime */\nfunction htmlToText(html: string): string {\n return html\n .replace(/<(script|style)[^>]*>[\\s\\S]*?<\\/(script|style)>/gi, ' ')\n .replace(/<[^>]+>/g, ' ')\n .replace(/ /g, ' ')\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/&[a-z#][a-z0-9]+;/gi, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\nimport { formatChatHistoryAsString } from \"../../utils\";\nimport EventEmitter from \"events\";\nimport type {\n Config,\n ChatTurnMessage,\n MetaSearchAgentType,\n SearchingEvent,\n} from \"./meta-search-types\";\nimport {\n buildFallbackDocs,\n rerankDocs,\n processDocs,\n normalizeSourcesOutput,\n type R2CredentialsInput,\n} from \"./doc-utils\";\nimport { groupAndSummarizeDocs } from \"./link-summarizer\";\n\nexport type { MetaSearchAgentType, Config } from \"./meta-search-types\";\n\nconst waitWithTimeout = async <T>(\n promise: Promise<T>,\n timeoutMs: number,\n): Promise<T | undefined> => {\n return Promise.race([\n promise,\n new Promise<undefined>((resolve) => {\n setTimeout(() => resolve(undefined), timeoutMs);\n }),\n ]);\n};\n\n/**\n * Substitutes `{key}` placeholders in a prompt template with the provided\n * values, leaving unknown placeholders untouched.\n */\nconst interpolatePrompt = (\n template: string,\n vars: Record<string, string>,\n): string => {\n return Object.entries(vars).reduce(\n (result, [key, value]) => result.split(`{${key}}`).join(value),\n template,\n );\n};\n\nclass MetaSearchAgent implements MetaSearchAgentType {\n private config: Config;\n\n constructor(config: Config) {\n this.config = config;\n }\n\n /**\n * Rephrases the user's query into a standalone search question (and any\n * URLs to summarize), runs the web search, and returns the documents to\n * use as answer context.\n */\n private async retrieveSearchDocs(\n llm: LanguageModel,\n chatHistory: string,\n query: string,\n category: string = \"general\",\n sourceExtractionEnabled = false,\n thinkingTimeLimit = 0,\n emitter?: EventEmitter,\n ): Promise<{ query: string; docs: Document[] }> {\n const { text: retrieverOutput } = await generateText({\n model: llm,\n temperature: 0,\n system: this.config.queryGeneratorPrompt,\n messages: [\n ...this.config.queryGeneratorFewShots.map(([role, content]) => ({\n role,\n content,\n })),\n {\n role: \"user\",\n content: `\n <conversation>\n ${chatHistory}\n </conversation>\n\n <query>\n ${query}\n </query>\n `,\n },\n ],\n });\n\n const linksOutputParser = new LineListOutputParser({ key: \"links\" });\n const questionOutputParser = new LineOutputParser({ key: \"question\" });\n\n const links = await linksOutputParser.parse(retrieverOutput);\n let question =\n (await questionOutputParser.parse(retrieverOutput)) ?? retrieverOutput;\n\n if (question === \"not_needed\") {\n question = \"latest information\";\n }\n\n if (links.length > 0 && this.config.getDocumentsFromLinks) {\n if (question.length === 0) question = \"summarize\";\n\n const linkDocs = await this.config.getDocumentsFromLinks({ links });\n const docs = await groupAndSummarizeDocs(llm, linkDocs, question);\n\n return { query: question, docs };\n }\n\n question = question.replace(/<think>.*?<\\/think>/g, \"\");\n if (!question || question.trim().length === 0) {\n question = \"latest information\";\n }\n\n // Validate and sanitize the query before sending to search APIs\n // If the LLM returned a long response instead of a concise query, extract the first sentence\n // or use the original user query as fallback\n question = question.trim();\n if (question.length > 500 || question.split(/[.!?]\\s+/).length > 5) {\n // Query is too long or contains too many sentences - likely the LLM returned a full response\n console.warn(`[MetaSearchAgent] Query is too long (${question.length} chars), truncating or using fallback`);\n\n // Try to extract first sentence as the query\n const firstSentence = question.split(/[.!?]\\s+/)[0].trim();\n if (firstSentence.length > 0 && firstSentence.length < 200) {\n question = firstSentence;\n } else {\n // Fallback to original user query\n question = query.slice(0, 200);\n }\n }\n\n // Emit \"searching\" progress event so the client can show live status\n const categoryLabel = this.config.activeEngines.length > 0\n ? this.config.activeEngines.slice(0, 2).join(\", \")\n : \"Web\";\n const emitSearching = (status: SearchingEvent[\"status\"], query: string, cat?: string) => {\n emitter?.emit(\"data\", JSON.stringify({\n type: \"searching\",\n data: { query, category: cat ?? categoryLabel, status } satisfies SearchingEvent,\n }));\n };\n\n emitSearching(\"running\", question);\n\n let res: { results: any[]; suggestions: string[] } = { results: [], suggestions: [] };\n\n // If no search functions provided, return empty results\n if (!this.config.searchSearxng && !this.config.searchTavily) {\n res = { results: [], suggestions: [] };\n } else {\n const runSearxng = async () => {\n try {\n const result = await this.config.searchSearxng!(question, {\n language: \"en\",\n engines: this.config.activeEngines,\n categories: [category],\n });\n // Ensure result has the expected structure\n return result && typeof result === 'object' && 'results' in result\n ? result\n : { results: [], suggestions: [] };\n } catch (error) {\n console.error(\"[MetaSearchAgent] SearXNG search failed:\", error);\n return { results: [], suggestions: [] };\n }\n };\n\n const isTavilyConfigured = this.config.isTavilyConfigured?.() ?? false;\n\n if (\n isTavilyConfigured &&\n this.config.activeEngines.length === 0 &&\n category === \"general\"\n ) {\n try {\n const tavilyResult = await this.config.searchTavily!(question, { searchDepth: \"basic\", maxResults: 10 });\n res = tavilyResult && typeof tavilyResult === 'object' && 'results' in tavilyResult\n ? tavilyResult\n : { results: [], suggestions: [] };\n } catch (error) {\n console.error(\"Tavily search failed, falling back to SearXNG:\", error);\n res = this.config.searchSearxng ? await runSearxng() : { results: [], suggestions: [] };\n }\n } else {\n if (isTavilyConfigured && this.config.searchTavily) {\n try {\n res = await Promise.race([\n runSearxng(),\n new Promise<{ results: any[]; suggestions: string[] }>((_, reject) =>\n setTimeout(() => reject(new Error(\"Timeout\")), 10000)\n )\n ]);\n } catch (err: any) {\n if (err.message === \"Timeout\") {\n console.warn(\"[MetaSearchAgent] SearXNG search did not respond in 10 seconds, falling back to Tavily.\");\n try {\n const tavilyResult = await this.config.searchTavily(question, { searchDepth: \"basic\", maxResults: 10 });\n res = tavilyResult && typeof tavilyResult === 'object' && 'results' in tavilyResult\n ? tavilyResult\n : { results: [], suggestions: [] };\n } catch (tavilyErr) {\n console.error(\"[MetaSearchAgent] Tavily fallback also failed, awaiting SearXNG directly:\", tavilyErr);\n res = this.config.searchSearxng ? await runSearxng() : { results: [], suggestions: [] };\n }\n } else {\n console.error(\"[MetaSearchAgent] SearXNG search failed, falling back to Tavily:\", err);\n try {\n const tavilyResult = await this.config.searchTavily(question, { searchDepth: \"basic\", maxResults: 10 });\n res = tavilyResult && typeof tavilyResult === 'object' && 'results' in tavilyResult\n ? tavilyResult\n : { results: [], suggestions: [] };\n } catch (tavilyErr) {\n console.error(\"[MetaSearchAgent] Tavily fallback also failed:\", tavilyErr);\n res = { results: [], suggestions: [] };\n }\n }\n }\n } else {\n res = this.config.searchSearxng ? await runSearxng() : { results: [], suggestions: [] };\n }\n }\n }\n\n let documents: Document[] = (res?.results ?? []).map((result) => ({\n pageContent:\n result.content ||\n (this.config.activeEngines.includes(\"youtube\") ? result.title : \"\"),\n metadata: {\n title: result.title,\n url: result.url,\n source: result.source,\n ...(result.img_src && { img_src: result.img_src }),\n },\n }));\n\n if (documents.length === 0) {\n documents = buildFallbackDocs(question);\n }\n\n emitSearching(\"done\", question);\n\n // Determine extraction budget from thinkingTimeLimit (seconds).\n // thinkingTimeLimit === 0 means unlimited; use server config.\n let scrapeCount: number;\n let perSourceTimeout: number;\n\n if (thinkingTimeLimit > 0) {\n // Spread the time budget across 3 sources\n scrapeCount = 3;\n perSourceTimeout = Math.max(2, Math.floor(thinkingTimeLimit / scrapeCount));\n } else if (sourceExtractionEnabled) {\n scrapeCount = 3;\n // Default to 5 seconds if no config function available\n perSourceTimeout = 5;\n } else {\n scrapeCount = 0;\n perSourceTimeout = 0;\n }\n\n if (scrapeCount > 0) {\n const docsToScrape = documents.slice(0, scrapeCount);\n emitSearching(\"running\", `Extracting top ${docsToScrape.length} sources`, \"extract\");\n\n const extractionTasks = this.config.scrapeURL ? docsToScrape.map(async (doc, idx) => {\n const url = doc.metadata?.url;\n if (!url || !this.config.scrapeURL) return;\n try {\n const result = await waitWithTimeout(\n this.config.scrapeURL(url, { timeout: perSourceTimeout }),\n perSourceTimeout * 1000 + 1500,\n );\n if (typeof result === \"string\" && result.length > 100) {\n const text = htmlToText(result)\n .replace(/(\\r\\n|\\n|\\r)/gm, \" \")\n .replace(/\\s+/g, \" \")\n .trim()\n .slice(0, 5000);\n if (text.length > 100) {\n documents[idx].pageContent = text;\n }\n }\n } catch {\n // Keep original snippet on scraping failure or timeout\n }\n }) : [];\n\n await Promise.allSettled(extractionTasks);\n emitSearching(\"done\", `Extracting top ${docsToScrape.length} sources`, \"extract\");\n }\n\n return { query: question, docs: documents };\n }\n\n /**\n * Runs the full search-and-answer pipeline, emitting \"sources\",\n * \"response\", \"searching\", \"end\", and \"error\" events on the emitter.\n */\n private async runPipeline(\n emitter: EventEmitter,\n message: string,\n history: ChatTurnMessage[],\n llm: LanguageModel,\n optimizationMode: \"speed\" | \"balanced\" | \"quality\",\n fileIds: string[],\n systemInstructions: string,\n category: string,\n sourceExtractionEnabled: boolean,\n thinkingTimeLimit: number,\n ): Promise<void> {\n try {\n let docs: Document[] | null = null;\n let query = message;\n\n if (this.config.searchWeb) {\n const result = await this.retrieveSearchDocs(\n llm,\n formatChatHistoryAsString(history),\n message,\n category,\n sourceExtractionEnabled,\n thinkingTimeLimit,\n emitter,\n );\n query = result.query;\n docs = result.docs;\n }\n\n const r2Credentials: R2CredentialsInput | undefined = process.env.R2_ACCOUNT_ID\n ? {\n accountId: process.env.R2_ACCOUNT_ID,\n accessKeyId: process.env.R2_ACCESS_KEY_ID || \"\",\n secretAccessKey: process.env.R2_SECRET_ACCESS_KEY || \"\",\n bucket: process.env.R2_UPLOADS_BUCKET || \"qwksearch-uploads\",\n }\n : undefined;\n\n const sortedDocs = await rerankDocs(\n query,\n docs ?? [],\n fileIds,\n optimizationMode,\n r2Credentials,\n );\n\n const sources = normalizeSourcesOutput(sortedDocs, message);\n console.log(\"[MetaSearchAgent] emitting sources:\", sources.length);\n emitter.emit(\"data\", JSON.stringify({ type: \"sources\", data: sources }));\n\n const systemPrompt = interpolatePrompt(this.config.responsePrompt, {\n systemInstructions,\n context: processDocs(sortedDocs),\n date: new Date().toISOString(),\n });\n\n const result = streamText({\n model: llm,\n temperature: 0.7,\n system: systemPrompt,\n messages: [...history, { role: \"user\", content: message }],\n });\n\n let responseChunkCount = 0;\n for await (const chunk of result.textStream) {\n responseChunkCount += 1;\n emitter.emit(\"data\", JSON.stringify({ type: \"response\", data: chunk }));\n }\n console.log(\"[MetaSearchAgent] response stream ended, chunks:\", responseChunkCount);\n\n if (responseChunkCount === 0) {\n const fallbackUrls = sources\n .map((doc) => doc.metadata?.url)\n .filter((url): url is string => typeof url === \"string\")\n .slice(0, 5);\n\n const fallbackMessage = [\n \"I couldn't generate a full answer, but I ran a web search and found these source URLs:\",\n ...fallbackUrls.map((url) => `- ${url}`),\n ].join(\"\\n\");\n\n emitter.emit(\"data\", JSON.stringify({ type: \"response\", data: fallbackMessage }));\n }\n\n emitter.emit(\"end\");\n } catch (err) {\n const errMessage = err instanceof Error ? err.message : String(err);\n console.error(\"[MetaSearchAgent] caught error from AI SDK stream:\", errMessage, err);\n let userMessage = errMessage;\n if (errMessage.includes(\"404\") || errMessage.toLowerCase().includes(\"not found\")) {\n userMessage =\n \"The selected AI model was not found at the provider. Please go to Settings → Model Providers and select a different model.\";\n } else if (errMessage.includes(\"410\")) {\n userMessage =\n \"The selected AI model is no longer available (deprecated by the provider). Please go to Settings → Model Providers and select a different model.\";\n } else if (errMessage.includes(\"401\") || errMessage.includes(\"authentication\")) {\n userMessage =\n \"Authentication failed with the AI provider. Please check your API key in Settings.\";\n } else if (errMessage.includes(\"429\") || errMessage.includes(\"rate limit\")) {\n userMessage =\n \"Rate limit reached for the AI provider. Please wait a moment and try again.\";\n }\n emitter.emit(\"error\", JSON.stringify({ data: userMessage }));\n }\n }\n\n async searchAndAnswer(\n message: string,\n history: ChatTurnMessage[],\n llm: LanguageModel,\n optimizationMode: \"speed\" | \"balanced\" | \"quality\",\n fileIds: string[],\n systemInstructions: string,\n category: string = \"general\",\n sourceExtractionEnabled = false,\n thinkingTimeLimit = 0,\n ) {\n const emitter = new EventEmitter();\n\n // Start on the next macrotask so callers can attach their event\n // listeners before the first \"sources\"/\"response\" event can fire.\n setTimeout(() => {\n this.runPipeline(\n emitter,\n message,\n history,\n llm,\n optimizationMode,\n fileIds,\n systemInstructions,\n category,\n sourceExtractionEnabled,\n thinkingTimeLimit,\n );\n }, 0);\n\n return emitter;\n }\n}\n\nexport default MetaSearchAgent;\n","/**\n * @module research/search/index\n * @description Research library module.\n *\n * Note: To use these search handlers, you need to provide search functions\n * (searchSearxng, searchTavily, etc.) from extract-webpage package.\n * See extract-webpage/src/search/index.ts for an example.\n */\nimport MetaSearchAgent from \"./metaSearchAgent\";\nimport {\n webSearchRetrieverPrompt,\n webSearchResponsePrompt,\n webSearchRetrieverFewShots,\n writingAssistantPrompt,\n} from \"write-language\";\nimport type { Config } from \"./meta-search-types\";\n\nconst prompts = {\n webSearchRetrieverPrompt,\n webSearchResponsePrompt,\n webSearchRetrieverFewShots,\n writingAssistantPrompt,\n};\n\n/**\n * Creates search handler instances with provided search functions.\n * Pass in search functions from extract-webpage to enable web search.\n */\nexport const createSearchHandlers = (searchFunctions?: Partial<Config>) => ({\n webSearch: new MetaSearchAgent({\n activeEngines: [],\n queryGeneratorPrompt: prompts.webSearchRetrieverPrompt,\n responsePrompt: prompts.webSearchResponsePrompt,\n queryGeneratorFewShots: prompts.webSearchRetrieverFewShots,\n rerank: true,\n rerankThreshold: 0.3,\n searchWeb: true,\n ...searchFunctions,\n }),\n academicSearch: new MetaSearchAgent({\n activeEngines: [\"arxiv\", \"google scholar\", \"pubmed\"],\n queryGeneratorPrompt: prompts.webSearchRetrieverPrompt,\n responsePrompt: prompts.webSearchResponsePrompt,\n queryGeneratorFewShots: prompts.webSearchRetrieverFewShots,\n rerank: true,\n rerankThreshold: 0,\n searchWeb: true,\n ...searchFunctions,\n }),\n writingAssistant: new MetaSearchAgent({\n activeEngines: [],\n queryGeneratorPrompt: \"\",\n queryGeneratorFewShots: [],\n responsePrompt: prompts.writingAssistantPrompt,\n rerank: true,\n rerankThreshold: 0,\n searchWeb: true,\n ...searchFunctions,\n }),\n wolframAlphaSearch: new MetaSearchAgent({\n activeEngines: [\"wolframalpha\"],\n queryGeneratorPrompt: prompts.webSearchRetrieverPrompt,\n responsePrompt: prompts.webSearchResponsePrompt,\n queryGeneratorFewShots: prompts.webSearchRetrieverFewShots,\n rerank: false,\n rerankThreshold: 0,\n searchWeb: true,\n ...searchFunctions,\n }),\n youtubeSearch: new MetaSearchAgent({\n activeEngines: [\"youtube\"],\n queryGeneratorPrompt: prompts.webSearchRetrieverPrompt,\n responsePrompt: prompts.webSearchResponsePrompt,\n queryGeneratorFewShots: prompts.webSearchRetrieverFewShots,\n rerank: true,\n rerankThreshold: 0.3,\n searchWeb: true,\n ...searchFunctions,\n }),\n redditSearch: new MetaSearchAgent({\n activeEngines: [\"reddit\"],\n queryGeneratorPrompt: prompts.webSearchRetrieverPrompt,\n responsePrompt: prompts.webSearchResponsePrompt,\n queryGeneratorFewShots: prompts.webSearchRetrieverFewShots,\n rerank: true,\n rerankThreshold: 0.3,\n searchWeb: true,\n ...searchFunctions,\n }),\n});\n\n/**\n * Default search handlers without search functions.\n * These will not perform actual web searches unless search functions are added to the Config.\n * @deprecated Use createSearchHandlers() with search functions instead\n */\nexport const searchHandlers = createSearchHandlers();\n","/**\n * @module research/chains/suggestionGeneratorAgent\n * @description Generates follow-up question suggestions from a conversation\n * using the Vercel AI SDK.\n */\nimport { generateText, type LanguageModel } from \"ai\";\nimport { LineListOutputParser } from \"../../utils/outputParser\";\nimport { formatChatHistoryAsString } from \"../../utils\";\nimport type { ChatTurnMessage } from \"./meta-search-types\";\n\nconst createSuggestionGeneratorPrompt = (maxQuestions: number = 4) => `\nYou are an AI suggestion generator for an AI powered search engine. You will be given a conversation below. You need to generate ${maxQuestions} suggestions based on the conversation. The suggestion should be relevant to the conversation that can be used by the user to ask the chat model for more information.\nYou need to make sure the suggestions are relevant to the conversation and are helpful to the user. Keep a note that the user might use these suggestions to ask a chat model for more information.\nMake sure the suggestions are medium in length and are informative and relevant to the conversation.\n\nProvide these suggestions separated by newlines between the XML tags <suggestions> and </suggestions>. For example:\n\n<suggestions>\nTell me more about SpaceX and their recent projects\nWhat is the latest news on SpaceX?\nWho is the CEO of SpaceX?\n</suggestions>\n\nConversation:\n{chat_history}\n`;\n\ntype SuggestionGeneratorInput = {\n chat_history: ChatTurnMessage[];\n maxQuestions?: number;\n};\n\nconst outputParser = new LineListOutputParser({\n key: \"suggestions\",\n});\n\nconst generateSuggestions = async (\n input: SuggestionGeneratorInput,\n llm: LanguageModel,\n): Promise<string[]> => {\n const maxQuestions = input.maxQuestions ?? 4;\n const prompt = createSuggestionGeneratorPrompt(maxQuestions).replace(\n \"{chat_history}\",\n formatChatHistoryAsString(input.chat_history),\n );\n\n const { text } = await generateText({\n model: llm,\n temperature: 0,\n prompt,\n });\n\n return outputParser.parse(text);\n};\n\nexport default generateSuggestions;\n","/**\n * @module research/search/document\n * @description Minimal document shape shared across the search pipeline.\n * A document is a chunk of page content plus citation metadata (title, url, source, etc.).\n */\n\nexport interface Document<\n Metadata extends Record<string, any> = Record<string, any>,\n> {\n pageContent: string;\n metadata: Metadata;\n}\n\n/**\n * Splits text into overlapping chunks on whitespace boundaries.\n * Default chunkSize 1000, chunkOverlap 200.\n */\nexport function splitTextIntoChunks(\n text: string,\n chunkSize = 1000,\n chunkOverlap = 200,\n): string[] {\n const trimmed = (text || \"\").trim();\n if (trimmed.length <= chunkSize) {\n return trimmed.length > 0 ? [trimmed] : [];\n }\n\n const chunks: string[] = [];\n let start = 0;\n\n while (start < trimmed.length) {\n let end = Math.min(start + chunkSize, trimmed.length);\n\n // Break on the last whitespace inside the window so words stay intact\n if (end < trimmed.length) {\n const lastSpace = trimmed.lastIndexOf(\" \", end);\n if (lastSpace > start) end = lastSpace;\n }\n\n chunks.push(trimmed.slice(start, end).trim());\n\n if (end >= trimmed.length) break;\n start = Math.max(end - chunkOverlap, start + 1);\n }\n\n return chunks.filter((chunk) => chunk.length > 0);\n}\n","/**\n * @module research/models/providers/index\n * @description Research library module.\n *\n * This file provides metadata about providers without importing them directly,\n * to avoid circular dependency issues with the config system.\n */\nimport { ModelProviderUISection } from \"../types\";\n\n/**\n * Gets provider UI configuration without triggering circular dependencies.\n * This function uses static metadata instead of importing provider classes.\n */\nexport const getModelProvidersUIConfigSection =\n (): ModelProviderUISection[] => {\n // Import statically defined metadata instead of loading the providers\n // This breaks the circular dependency\n return [\n {\n key: \"openai\",\n name: \"OpenAI\",\n fields: getOpenAIConfigFields(),\n },\n {\n key: \"anthropic\",\n name: \"Anthropic\",\n fields: getAnthropicConfigFields(),\n },\n {\n key: \"gemini\",\n name: \"Google Gemini\",\n fields: getGeminiConfigFields(),\n },\n {\n key: \"groq\",\n name: \"Groq\",\n fields: getGroqConfigFields(),\n },\n {\n key: \"deepseek\",\n name: \"DeepSeek\",\n fields: getDeepSeekConfigFields(),\n },\n {\n key: \"nvidia\",\n name: \"NVIDIA\",\n fields: getNvidiaConfigFields(),\n },\n {\n key: \"openrouter\",\n name: \"OpenRouter\",\n fields: getOpenRouterConfigFields(),\n },\n ];\n };\n\n// Static config field definitions to avoid loading provider classes\n// These match the providerConfigFields in each provider file\nfunction getOpenAIConfigFields() {\n return [\n {\n type: \"password\" as const,\n name: \"API Key\",\n key: \"apiKey\",\n description: \"Your OpenAI API key\",\n required: true,\n placeholder: \"OpenAI API Key\",\n env: \"OPENAI_API_KEY\",\n scope: \"server\" as const,\n },\n {\n type: \"string\" as const,\n name: \"Base URL\",\n key: \"baseURL\",\n description: \"The base URL for the OpenAI API\",\n required: true,\n placeholder: \"OpenAI Base URL\",\n default: \"https://api.openai.com/v1\",\n env: \"OPENAI_BASE_URL\",\n scope: \"server\" as const,\n },\n ];\n}\n\n\nfunction getAnthropicConfigFields() {\n return [\n {\n type: \"password\" as const,\n name: \"API Key\",\n key: \"apiKey\",\n description: \"Your Anthropic API key\",\n required: true,\n placeholder: \"Anthropic API Key\",\n env: \"ANTHROPIC_API_KEY\",\n scope: \"server\" as const,\n },\n ];\n}\n\nfunction getGeminiConfigFields() {\n return [\n {\n type: \"password\" as const,\n name: \"API Key\",\n key: \"apiKey\",\n description: \"Your Google Gemini API key\",\n required: true,\n placeholder: \"Google Gemini API Key\",\n env: \"GEMINI_API_KEY\",\n scope: \"server\" as const,\n },\n ];\n}\n\nfunction getGroqConfigFields() {\n return [\n {\n type: \"password\" as const,\n name: \"API Key\",\n key: \"apiKey\",\n description: \"Your Groq API key. Free tier includes fast inference on Llama and Mixtral models - get yours at console.groq.com\",\n required: true,\n placeholder: \"gsk_...\",\n env: \"GROQ_API_KEY\",\n scope: \"server\" as const,\n },\n ];\n}\n\nfunction getDeepSeekConfigFields() {\n return [\n {\n type: \"password\" as const,\n name: \"API Key\",\n key: \"apiKey\",\n description: \"Your DeepSeek API key\",\n required: true,\n placeholder: \"DeepSeek API Key\",\n env: \"DEEPSEEK_API_KEY\",\n scope: \"server\" as const,\n },\n ];\n}\n\nfunction getNvidiaConfigFields() {\n return [\n {\n type: \"password\" as const,\n name: \"API Key\",\n key: \"apiKey\",\n description: \"Your NVIDIA API key. Free tier includes access to Nemotron, Llama, and other models - get yours at build.nvidia.com\",\n required: true,\n placeholder: \"nvapi-...\",\n env: \"NVIDIA_API_KEY\",\n scope: \"server\" as const,\n },\n {\n type: \"string\" as const,\n name: \"Base URL\",\n key: \"baseURL\",\n description: \"The base URL for NVIDIA's OpenAI-compatible API\",\n required: true,\n placeholder: \"https://integrate.api.nvidia.com/v1\",\n default: \"https://integrate.api.nvidia.com/v1\",\n env: \"NVIDIA_BASE_URL\",\n scope: \"server\" as const,\n },\n ];\n}\n\nfunction getOpenRouterConfigFields() {\n return [\n {\n type: \"password\" as const,\n name: \"API Key\",\n key: \"apiKey\",\n description: \"Your OpenRouter API key. Get one free at openrouter.ai - includes free access to Llama 3.3 70B, Nemotron, and other models.\",\n required: true,\n placeholder: \"sk-or-v1-...\",\n env: \"OPENROUTER_API_KEY\",\n scope: \"server\" as const,\n },\n {\n type: \"string\" as const,\n name: \"Base URL\",\n key: \"baseURL\",\n description: \"The base URL for OpenRouter's OpenAI-compatible API\",\n required: true,\n placeholder: \"https://openrouter.ai/api/v1\",\n default: \"https://openrouter.ai/api/v1\",\n env: \"OPENROUTER_BASE_URL\",\n scope: \"server\" as const,\n },\n ];\n}\n","/**\n * Runtime env-var accessor.\n * Supports both local development (process.env) and Cloudflare Workers\n * (cloudflare:workers virtual module) via dynamic import.\n */\nexport function getEnv(key: string): string | undefined {\n // Try Cloudflare Workers context first (production)\n try {\n // @ts-ignore - cloudflare:workers is a virtual module provided by @cloudflare/vite-plugin\n const cfWorkers = require(\"cloudflare:workers\");\n return cfWorkers.env?.[key];\n } catch {\n // Fallback to process.env for local development\n return process.env[key];\n }\n}\n","/**\n * List of default models for the chat providers and a list of models\n * @property {string} provider - The provider name\n * @property {string} docs - The documentation URL for the model\n * @property {string} api_key - The API key url for the model\n * @property {string} default - The default model for the chat provider\n * @property {Object[]} models - The list of models available for the chat provider\n * @category Generate\n */\nexport const LANGUAGE_MODELS = [\n {\n \"provider\": \"NVIDIA\",\n \"docs\": \"https://docs.api.nvidia.com/nim/reference/llm-apis\",\n \"api_key\": \"https://build.nvidia.com/settings/api-keys\",\n \"default\": \"nvidia/llama-3.1-nemotron-70b-instruct\",\n \"models\": [\n {\n \"name\": \"Llama 3.1 Nemotron 70B Instruct\",\n \"id\": \"nvidia/llama-3.1-nemotron-70b-instruct\",\n \"contextLength\": 131_072,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Nemotron 3 Super 120B\",\n \"id\": \"nvidia/nemotron-3-super-120b-a12b\",\n \"contextLength\": 1_000_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Nemotron-4 340B\",\n \"id\": \"nvidia/nemotron-4-340b\",\n \"contextLength\": 131_072,\n \"free\": false,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Llama 3.3 70B Instruct\",\n \"id\": \"meta/llama-3.3-70b-instruct\",\n \"contextLength\": 131_072,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Llama 3.1 405B Instruct\",\n \"id\": \"meta/llama-3.1-405b-instruct\",\n \"contextLength\": 131_072,\n \"free\": false,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Llama 3.1 8B Instruct\",\n \"id\": \"meta/llama-3.1-8b-instruct\",\n \"contextLength\": 131_072,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Gemma 4 31B IT\",\n \"id\": \"google/gemma-4-31b-it\",\n \"contextLength\": 131_072,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Mistral Large 2\",\n \"id\": \"mistralai/mistral-large-2\",\n \"contextLength\": 131_072,\n \"free\": false,\n \"type\": \"text-generation\"\n }\n ]\n},\n {\n provider: \"Cloudflare\",\n docs: \"https://developers.cloudflare.com/workers-ai/\",\n api_key: \"https://dash.cloudflare.com/profile/api-tokens\",\n default: \"llama-4-scout-17b-16e-instruct\",\n models: [\n {\n name: \"Llama 4 Scout 17B 16E Instruct\",\n id: \"llama-4-scout-17b-16e-instruct\",\n contextLength: 128000,\n },\n {\n name: \"Llama 3.3 70B Instruct FP8 Fast\",\n id: \"llama-3.3-70b-instruct-fp8-fast\",\n contextLength: 128000,\n },\n {\n name: \"Llama 3.1 8B Instruct Fast\",\n id: \"llama-3.1-8b-instruct-fast\",\n contextLength: 128000,\n },\n {\n name: \"Gemma 3 12B IT\",\n id: \"gemma-3-12b-it\",\n contextLength: 128000,\n },\n {\n name: \"Mistral Small 3.1 24B Instruct\",\n id: \"mistral-small-3.1-24b-instruct\",\n contextLength: 128000,\n },\n {\n name: \"QwQ 32B\",\n id: \"qwq-32b\",\n contextLength: 32768,\n },\n {\n name: \"Qwen2.5 Coder 32B Instruct\",\n id: \"qwen2.5-coder-32b-instruct\",\n contextLength: 32768,\n },\n {\n name: \"Llama Guard 3 8B\",\n id: \"llama-guard-3-8b\",\n contextLength: 8192,\n },\n {\n name: \"DeepSeek R1 Distill Qwen 32B\",\n id: \"deepseek-r1-distill-qwen-32b\",\n contextLength: 32768,\n },\n {\n name: \"Llama 3.2 1B Instruct\",\n id: \"llama-3.2-1b-instruct\",\n contextLength: 131072,\n },\n {\n name: \"Llama 3.2 3B Instruct\",\n id: \"llama-3.2-3b-instruct\",\n contextLength: 131072,\n },\n {\n name: \"Llama 3.2 11B Vision Instruct\",\n id: \"llama-3.2-11b-vision-instruct\",\n contextLength: 131072,\n },\n {\n name: \"Llama 3.1 8B Instruct AWQ\",\n id: \"llama-3.1-8b-instruct-awq\",\n contextLength: 128000,\n },\n {\n name: \"Llama 3.1 8B Instruct FP8\",\n id: \"llama-3.1-8b-instruct-fp8\",\n contextLength: 128000,\n },\n {\n name: \"MeloTTS\",\n id: \"melotts\",\n contextLength: 1024,\n },\n {\n name: \"Llama 3.1 8B Instruct\",\n id: \"llama-3.1-8b-instruct\",\n contextLength: 128000,\n },\n {\n name: \"Meta Llama 3 8B Instruct\",\n id: \"meta-llama-3-8b-instruct\",\n contextLength: 8192,\n },\n {\n name: \"Whisper Large V3 Turbo\",\n id: \"whisper-large-v3-turbo\",\n contextLength: 448000,\n },\n {\n name: \"Llama 3 8B Instruct AWQ\",\n id: \"llama-3-8b-instruct-awq\",\n contextLength: 8192,\n },\n {\n name: \"LLaVA 1.5 7B HF\",\n id: \"llava-1.5-7b-hf\",\n contextLength: 4096,\n },\n {\n name: \"Una Cybertron 7B V2 BF16\",\n id: \"una-cybertron-7b-v2-bf16\",\n contextLength: 32768,\n },\n {\n name: \"Whisper Tiny EN\",\n id: \"whisper-tiny-en\",\n contextLength: 448000,\n },\n {\n name: \"Llama 3 8B Instruct\",\n id: \"llama-3-8b-instruct\",\n contextLength: 8192,\n },\n {\n name: \"Mistral 7B Instruct v0.2\",\n id: \"mistral-7b-instruct-v0.2\",\n contextLength: 32768,\n },\n {\n name: \"Gemma 7B IT LoRA\",\n id: \"gemma-7b-it-lora\",\n contextLength: 8192,\n },\n {\n name: \"Gemma 2B IT LoRA\",\n id: \"gemma-2b-it-lora\",\n contextLength: 8192,\n },\n {\n name: \"Llama 2 7B Chat HF LoRA\",\n id: \"llama-2-7b-chat-hf-lora\",\n contextLength: 4096,\n },\n {\n name: \"Gemma 7B IT\",\n id: \"gemma-7b-it\",\n contextLength: 8192,\n },\n {\n name: \"Starling LM 7B Beta\",\n id: \"starling-lm-7b-beta\",\n contextLength: 8192,\n },\n {\n name: \"Hermes 2 Pro Mistral 7B\",\n id: \"hermes-2-pro-mistral-7b\",\n contextLength: 32768,\n },\n {\n name: \"Mistral 7B Instruct v0.2 LoRA\",\n id: \"mistral-7b-instruct-v0.2-lora\",\n contextLength: 32768,\n },\n {\n name: \"Qwen1.5 1.8B Chat\",\n id: \"qwen1.5-1.8b-chat\",\n contextLength: 32768,\n },\n {\n name: \"UForm Gen2 Qwen 500M\",\n id: \"uform-gen2-qwen-500m\",\n contextLength: 2048,\n },\n {\n name: \"BART Large CNN\",\n id: \"bart-large-cnn\",\n contextLength: 1024,\n },\n {\n name: \"Phi-2\",\n id: \"phi-2\",\n contextLength: 2048,\n },\n {\n name: \"TinyLlama 1.1B Chat v1.0\",\n id: \"tinyllama-1.1b-chat-v1.0\",\n contextLength: 2048,\n },\n {\n name: \"Qwen1.5 14B Chat AWQ\",\n id: \"qwen1.5-14b-chat-awq\",\n contextLength: 32768,\n },\n {\n name: \"Qwen1.5 7B Chat AWQ\",\n id: \"qwen1.5-7b-chat-awq\",\n contextLength: 32768,\n },\n {\n name: \"Qwen1.5 0.5B Chat\",\n id: \"qwen1.5-0.5b-chat\",\n contextLength: 32768,\n },\n {\n name: \"DiscoLM German 7B v1 AWQ\",\n id: \"discolm-german-7b-v1-awq\",\n contextLength: 32768,\n },\n {\n name: \"Falcon 7B Instruct\",\n id: \"falcon-7b-instruct\",\n contextLength: 2048,\n },\n {\n name: \"OpenChat 3.5 0106\",\n id: \"openchat-3.5-0106\",\n contextLength: 8192,\n },\n {\n name: \"SQLCoder 7B 2\",\n id: \"sqlcoder-7b-2\",\n contextLength: 16384,\n },\n {\n name: \"DeepSeek Math 7B Instruct\",\n id: \"deepseek-math-7b-instruct\",\n contextLength: 4096,\n },\n {\n name: \"DETR ResNet-50\",\n id: \"detr-resnet-50\",\n contextLength: 1024,\n },\n {\n name: \"Stable Diffusion XL Lightning\",\n id: \"stable-diffusion-xl-lightning\",\n contextLength: 77,\n },\n {\n name: \"DreamShaper 8 LCM\",\n id: \"dreamshaper-8-lcm\",\n contextLength: 77,\n },\n {\n name: \"Stable Diffusion v1.5 Img2Img\",\n id: \"stable-diffusion-v1-5-img2img\",\n contextLength: 77,\n },\n {\n name: \"Stable Diffusion v1.5 Inpainting\",\n id: \"stable-diffusion-v1-5-inpainting\",\n contextLength: 77,\n },\n {\n name: \"DeepSeek Coder 6.7B Instruct AWQ\",\n id: \"deepseek-coder-6.7b-instruct-awq\",\n contextLength: 16384,\n },\n {\n name: \"DeepSeek Coder 6.7B Base AWQ\",\n id: \"deepseek-coder-6.7b-base-awq\",\n contextLength: 16384,\n },\n {\n name: \"LlamaGuard 7B AWQ\",\n id: \"llamaguard-7b-awq\",\n contextLength: 4096,\n },\n {\n name: \"Neural Chat 7B v3.1 AWQ\",\n id: \"neural-chat-7b-v3-1-awq\",\n contextLength: 8192,\n },\n {\n name: \"OpenHermes 2.5 Mistral 7B AWQ\",\n id: \"openhermes-2.5-mistral-7b-awq\",\n contextLength: 8192,\n },\n {\n name: \"Llama 2 13B Chat AWQ\",\n id: \"llama-2-13b-chat-awq\",\n contextLength: 4096,\n },\n {\n name: \"Mistral 7B Instruct v0.1 AWQ\",\n id: \"mistral-7b-instruct-v0.1-awq\",\n contextLength: 8192,\n },\n {\n name: \"Zephyr 7B Beta AWQ\",\n id: \"zephyr-7b-beta-awq\",\n contextLength: 8192,\n },\n {\n name: \"Stable Diffusion XL Base 1.0\",\n id: \"stable-diffusion-xl-base-1.0\",\n contextLength: 77,\n },\n {\n name: \"BGE Large EN v1.5\",\n id: \"bge-large-en-v1.5\",\n contextLength: 512,\n },\n {\n name: \"BGE Small EN v1.5\",\n id: \"bge-small-en-v1.5\",\n contextLength: 512,\n },\n {\n name: \"Llama 2 7B Chat FP16\",\n id: \"llama-2-7b-chat-fp16\",\n contextLength: 4096,\n },\n {\n name: \"Mistral 7B Instruct v0.1\",\n id: \"mistral-7b-instruct-v0.1\",\n contextLength: 8192,\n },\n {\n name: \"BGE Base EN v1.5\",\n id: \"bge-base-en-v1.5\",\n contextLength: 512,\n },\n {\n name: \"DistilBERT SST-2 Int8\",\n id: \"distilbert-sst-2-int8\",\n contextLength: 512,\n },\n {\n name: \"Llama 2 7B Chat Int8\",\n id: \"llama-2-7b-chat-int8\",\n contextLength: 4096,\n },\n {\n name: \"M2M100 1.2B\",\n id: \"m2m100-1.2b\",\n contextLength: 1024,\n },\n {\n name: \"ResNet-50\",\n id: \"resnet-50\",\n contextLength: 224,\n },\n {\n name: \"Whisper\",\n id: \"whisper\",\n contextLength: 448000,\n },\n {\n name: \"Llama 3.1 70B Instruct\",\n id: \"llama-3.1-70b-instruct\",\n contextLength: 128000,\n },\n ],\n },\n {\n provider: \"Perplexity\",\n docs: \"https://docs.perplexity.ai/models/model-cards\",\n api_key: \"https://www.perplexity.ai/account/api/keys\",\n default: \"sonar\",\n models: [\n {\n name: \"Sonar Pro\",\n id: \"sonar-pro\",\n contextLength: 200000,\n },\n {\n name: \"Sonar\",\n id: \"sonar\",\n contextLength: 128000,\n },\n {\n name: \"Sonar Reasoning Pro\",\n id: \"sonar-reasoning-pro\",\n contextLength: 128000,\n },\n {\n name: \"Sonar Reasoning\",\n id: \"sonar-reasoning\",\n contextLength: 128000,\n },\n {\n name: \"Sonar Deep Research\",\n id: \"sonar-deep-research\",\n contextLength: 128000,\n },\n {\n name: \"Llama 3.1 Sonar Small 128k Online\",\n id: \"llama-3.1-sonar-small-128k-online\",\n contextLength: 127072,\n },\n {\n name: \"Llama 3.1 Sonar Large 128k Online\",\n id: \"llama-3.1-sonar-large-128k-online\",\n contextLength: 127072,\n },\n {\n name: \"Llama 3.1 Sonar Huge 128k Online\",\n id: \"llama-3.1-sonar-huge-128k-online\",\n contextLength: 127072,\n },\n ],\n },\n {\n provider: \"Groq\",\n docs: \"https://console.groq.com/docs/overview\",\n api_key: \"https://console.groq.com/keys\",\n default: \"llama-3.3-70b-versatile\",\n models: [\n {\n name: \"Llama 3.3 70B Versatile (Free)\",\n id: \"llama-3.3-70b-versatile\",\n contextLength: 131072,\n free: true,\n type: \"text-generation\",\n rateLimit: \"300K TPM / 1K RPM = ~432M tokens/day\",\n },\n {\n name: \"Llama 3.1 8B Instant (Free)\",\n id: \"llama-3.1-8b-instant\",\n contextLength: 8192,\n free: true,\n type: \"text-generation\",\n rateLimit: \"250K TPM / 1K RPM = ~360M tokens/day\",\n },\n {\n name: \"Llama 4 Scout 17B (Free)\",\n id: \"meta-llama/llama-4-scout-17b-16e-instruct\",\n contextLength: 131072,\n free: true,\n type: \"text-generation\",\n rateLimit: \"300K TPM / 1K RPM = ~432M tokens/day\",\n },\n {\n name: \"Qwen 3 32B (Free)\",\n id: \"qwen/qwen3-32b\",\n contextLength: 128000,\n free: true,\n type: \"text-generation\",\n rateLimit: \"300K TPM / 1K RPM = ~432M tokens/day\",\n },\n {\n name: \"GPT-OSS 120B (Free)\",\n id: \"openai/gpt-oss-120b\",\n contextLength: 32768,\n free: true,\n type: \"text-generation\",\n rateLimit: \"250K TPM / 1K RPM = ~360M tokens/day\",\n },\n {\n name: \"GPT-OSS 20B (Free)\",\n id: \"openai/gpt-oss-20b\",\n contextLength: 32768,\n free: true,\n type: \"text-generation\",\n rateLimit: \"250K TPM / 1K RPM = ~360M tokens/day\",\n },\n {\n name: \"Groq Compound (Free)\",\n id: \"groq/compound\",\n contextLength: 32768,\n free: true,\n type: \"text-generation\",\n rateLimit: \"200K TPM / 200 RPM = ~288M tokens/day\",\n },\n {\n name: \"Groq Compound Mini (Free)\",\n id: \"groq/compound-mini\",\n contextLength: 32768,\n free: true,\n type: \"text-generation\",\n rateLimit: \"200K TPM / 200 RPM = ~288M tokens/day\",\n },\n {\n name: \"GPT-OSS Safeguard 20B (Free)\",\n id: \"openai/gpt-oss-safeguard-20b\",\n contextLength: 32768,\n free: true,\n type: \"text-generation\",\n rateLimit: \"150K TPM / 1K RPM = ~216M tokens/day\",\n },\n ],\n },\n {\n provider: \"OpenAI\",\n docs: \"https://platform.openai.com/docs/overview\",\n api_key: \"https://platform.openai.com/api-keys\",\n default: \"gpt-4o\",\n models: [\n {\n name: \"GPT-4 Omni\",\n id: \"gpt-4o\",\n contextLength: 128000,\n },\n {\n name: \"GPT-4 Omni Mini\",\n id: \"gpt-4o-mini\",\n contextLength: 128000,\n },\n {\n name: \"GPT-4 Turbo\",\n id: \"gpt-4-turbo\",\n contextLength: 128000,\n },\n {\n name: \"GPT-4\",\n id: \"gpt-4\",\n contextLength: 8192,\n },\n {\n name: \"GPT-3.5 Turbo\",\n id: \"gpt-3.5-turbo\",\n contextLength: 16385,\n },\n ],\n },\n {\n provider: \"Anthropic\",\n docs: \"https://docs.anthropic.com/en/docs/welcome\",\n api_key: \"https://console.anthropic.com/settings/keys\",\n default: \"claude-3-7-sonnet-20250219\",\n models: [\n {\n name: \"Claude 3.7 Sonnet\",\n id: \"claude-3-7-sonnet-20250219\",\n contextLength: 200000,\n },\n {\n name: \"Claude 3.5 Sonnet\",\n id: \"claude-3-5-sonnet-20241022\",\n contextLength: 200000,\n },\n {\n name: \"Claude 3 Opus\",\n id: \"claude-3-opus-20240229\",\n contextLength: 200000,\n },\n {\n name: \"Claude 3 Sonnet\",\n id: \"claude-3-sonnet-20240229\",\n contextLength: 200000,\n },\n {\n name: \"Claude 3 Haiku\",\n id: \"claude-3-haiku-20240307\",\n contextLength: 200000,\n },\n ],\n },\n {\n provider: \"TogetherAI\",\n docs: \"https://docs.together.ai/docs/quickstart\",\n api_key: \"https://api.together.xyz/settings/api-keys\",\n default: \"meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo\",\n models: [\n {\n name: \"Llama 3.1 8B Instruct Turbo\",\n id: \"meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo\",\n contextLength: 131072,\n },\n {\n name: \"Llama 3.1 70B Instruct Turbo\",\n id: \"meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo\",\n contextLength: 131072,\n },\n {\n name: \"Llama 3.1 405B Instruct Turbo\",\n id: \"meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo\",\n contextLength: 130815,\n },\n {\n name: \"Llama 3 8B Instruct Turbo\",\n id: \"meta-llama/Meta-Llama-3-8B-Instruct-Turbo\",\n contextLength: 8192,\n },\n {\n name: \"Llama 3 70B Instruct Turbo\",\n id: \"meta-llama/Meta-Llama-3-70B-Instruct-Turbo\",\n contextLength: 8192,\n },\n {\n name: \"Llama 3.2 3B Instruct Turbo\",\n id: \"meta-llama/Llama-3.2-3B-Instruct-Turbo\",\n contextLength: 131072,\n },\n {\n name: \"Llama 3 8B Instruct Lite\",\n id: \"meta-llama/Meta-Llama-3-8B-Instruct-Lite\",\n contextLength: 8192,\n },\n {\n name: \"Llama 3 70B Instruct Lite\",\n id: \"meta-llama/Meta-Llama-3-70B-Instruct-Lite\",\n contextLength: 8192,\n },\n {\n name: \"Llama 3 8B Instruct Reference\",\n id: \"meta-llama/Llama-3-8b-chat-hf\",\n contextLength: 8192,\n },\n {\n name: \"Llama 3 70B Instruct Reference\",\n id: \"meta-llama/Llama-3-70b-chat-hf\",\n contextLength: 8192,\n },\n {\n name: \"Llama 3.1 Nemotron 70B\",\n id: \"nvidia/Llama-3.1-Nemotron-70B-Instruct-HF\",\n contextLength: 32768,\n },\n {\n name: \"Qwen 2.5 Coder 32B Instruct\",\n id: \"Qwen/Qwen2.5-Coder-32B-Instruct\",\n contextLength: 32769,\n },\n {\n name: \"WizardLM-2 8x22B\",\n id: \"microsoft/WizardLM-2-8x22B\",\n contextLength: 65536,\n },\n {\n name: \"Gemma 2 27B\",\n id: \"google/gemma-2-27b-it\",\n contextLength: 8192,\n },\n {\n name: \"Gemma 2 9B\",\n id: \"google/gemma-2-9b-it\",\n contextLength: 8192,\n },\n {\n name: \"DBRX Instruct\",\n id: \"databricks/dbrx-instruct\",\n contextLength: 32768,\n },\n {\n name: \"DeepSeek LLM Chat (67B)\",\n id: \"deepseek-ai/deepseek-llm-67b-chat\",\n contextLength: 4096,\n },\n {\n name: \"Gemma Instruct (2B)\",\n id: \"google/gemma-2b-it\",\n contextLength: 8192,\n },\n {\n name: \"MythoMax-L2 (13B)\",\n id: \"Gryphe/MythoMax-L2-13b\",\n contextLength: 4096,\n },\n {\n name: \"LLaMA-2 Chat (13B)\",\n id: \"meta-llama/Llama-2-13b-chat-hf\",\n contextLength: 4096,\n },\n {\n name: \"Mistral (7B) Instruct\",\n id: \"mistralai/Mistral-7B-Instruct-v0.1\",\n contextLength: 8192,\n },\n {\n name: \"Mistral (7B) Instruct v0.2\",\n id: \"mistralai/Mistral-7B-Instruct-v0.2\",\n contextLength: 32768,\n },\n {\n name: \"Mistral (7B) Instruct v0.3\",\n id: \"mistralai/Mistral-7B-Instruct-v0.3\",\n contextLength: 32768,\n },\n {\n name: \"Mixtral-8x7B Instruct (46.7B)\",\n id: \"mistralai/Mixtral-8x7B-Instruct-v0.1\",\n contextLength: 32768,\n },\n {\n name: \"Mixtral-8x22B Instruct (141B)\",\n id: \"mistralai/Mixtral-8x22B-Instruct-v0.1\",\n contextLength: 65536,\n },\n {\n name: \"Nous Hermes 2 - Mixtral 8x7B-DPO (46.7B)\",\n id: \"NousResearch/Nous-Hermes-2-Mixtral-8x7B-DPO\",\n contextLength: 32768,\n },\n {\n name: \"Qwen 2.5 7B Instruct Turbo\",\n id: \"Qwen/Qwen2.5-7B-Instruct-Turbo\",\n contextLength: 32768,\n },\n {\n name: \"Qwen 2.5 72B Instruct Turbo\",\n id: \"Qwen/Qwen2.5-72B-Instruct-Turbo\",\n contextLength: 32768,\n },\n {\n name: \"Qwen 2 Instruct (72B)\",\n id: \"Qwen/Qwen2-72B-Instruct\",\n contextLength: 32768,\n },\n {\n name: \"StripedHyena Nous (7B)\",\n id: \"togethercomputer/StripedHyena-Nous-7B\",\n contextLength: 32768,\n },\n {\n name: \"Upstage SOLAR Instruct v1 (11B)\",\n id: \"upstage/SOLAR-10.7B-Instruct-v1.0\",\n contextLength: 4096,\n },\n {\n name: \"Llama 3.2 11B Vision Instruct Turbo (Free)\",\n id: \"meta-llama/Llama-Vision-Free\",\n contextLength: 131072,\n },\n {\n name: \"Llama 3.2 11B Vision Instruct Turbo\",\n id: \"meta-llama/Llama-3.2-11B-Vision-Instruct-Turbo\",\n contextLength: 131072,\n },\n {\n name: \"Llama 3.2 90B Vision Instruct Turbo\",\n id: \"meta-llama/Llama-3.2-90B-Vision-Instruct-Turbo\",\n contextLength: 131072,\n },\n ],\n },\n {\n provider: \"XAI\",\n docs: \"https://docs.x.ai/docs#models\",\n api_key: \"https://console.x.ai/\",\n default: \"grok-beta\",\n models: [\n {\n name: \"Grok\",\n id: \"grok-beta\",\n contextLength: 131072,\n },\n {\n name: \"Grok Vision\",\n id: \"grok-vision-beta\",\n contextLength: 8192,\n },\n ],\n },\n {\n provider: \"Google\",\n docs: \"https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models\",\n api_key:\n \"https://cloud.google.com/vertex-ai/generative-ai/docs/start/express-mode/overview#api-keys\",\n models: [\n {\n name: \"Gemini 2.5 Pro Preview\",\n id: \"gemini-2.5-pro-preview-05-06\",\n contextLength: 1048576,\n },\n {\n name: \"Gemini 2.5 Flash Preview\",\n id: \"gemini-2.5-flash-preview-04-17\",\n contextLength: 1048576,\n },\n {\n name: \"Gemini 2.0 Flash\",\n id: \"gemini-2.0-flash-001\",\n contextLength: 1048576,\n },\n {\n name: \"Gemini 2.0 Flash-Lite\",\n id: \"gemini-2.0-flash-lite-001\",\n contextLength: 1048576,\n },\n {\n name: \"Gemini 2.0 Flash-Live\",\n id: \"gemini-2.0-flash-live-preview-04-09\",\n contextLength: 32768,\n },\n {\n name: \"Imagen 3\",\n id: \"imagen-3.0-generate-002\",\n contextLength: 480,\n },\n {\n name: \"Imagen 3 Fast\",\n id: \"imagen-3.0-fast-generate-001\",\n contextLength: 480,\n },\n {\n name: \"Llama 3.2 90B Vision Instruct Turbo\",\n id: \"meta-llama/Llama-3.2-90B-Vision-Instruct-Turbo\",\n contextLength: 131072,\n },\n {\n name: \"Llama 3.3 70B\",\n id: \"meta-llama/Llama-3.3-70B\",\n contextLength: 131072,\n },\n {\n name: \"Gemma 3\",\n id: \"gemma-3\",\n contextLength: 131072,\n },\n {\n name: \"Gemma 2\",\n id: \"gemma-2\",\n contextLength: 131072,\n },\n {\n name: \"Gemma\",\n id: \"gemma\",\n contextLength: 131072,\n },\n ],\n },\n {\n provider: \"Amazon\",\n docs: \"https://docs.aws.amazon.com/bedrock/\",\n api_key: \"https://console.aws.amazon.com/iam/home#/security_credentials\",\n default: \"anthropic.claude-3-5-sonnet-20241022-v2:0\",\n models: [\n {\n name: \"AI21 Jamba 1.5 Mini\",\n id: \"ai21.jamba-1-5-mini-v1:0\",\n contextLength: 256000,\n provider: \"AI21 Labs\",\n },\n {\n name: \"AI21 Jamba 1.5 Large\",\n id: \"ai21.jamba-1-5-large-v1:0\",\n contextLength: 256000,\n provider: \"AI21 Labs\",\n },\n {\n name: \"Amazon Nova Canvas\",\n id: \"amazon.nova-canvas-v1:0\",\n contextLength: 77,\n provider: \"Amazon\",\n type: \"image\",\n },\n {\n name: \"Amazon Nova Lite\",\n id: \"amazon.nova-lite-v1:0\",\n contextLength: 300000,\n provider: \"Amazon\",\n },\n {\n name: \"Amazon Nova Micro\",\n id: \"amazon.nova-micro-v1:0\",\n contextLength: 128000,\n provider: \"Amazon\",\n },\n {\n name: \"Amazon Nova Pro\",\n id: \"amazon.nova-pro-v1:0\",\n contextLength: 300000,\n provider: \"Amazon\",\n },\n {\n name: \"Amazon Nova Reel\",\n id: \"amazon.nova-reel-v1:0\",\n contextLength: 10000,\n provider: \"Amazon\",\n type: \"video\",\n },\n {\n name: \"Amazon Nova Reel V2 Lite\",\n id: \"amazon.nova-reel-v2-lite-v1:0\",\n contextLength: 10000,\n provider: \"Amazon\",\n type: \"video\",\n },\n {\n name: \"Amazon Nova Reel V2 Standard\",\n id: \"amazon.nova-reel-v2-standard-v1:0\",\n contextLength: 10000,\n provider: \"Amazon\",\n type: \"video\",\n },\n {\n name: \"Amazon Rerank\",\n id: \"amazon.rerank-v1:0\",\n contextLength: 8192,\n provider: \"Amazon\",\n type: \"reranker\",\n },\n {\n name: \"Amazon Titan Embeddings G1 - Text\",\n id: \"amazon.titan-embed-text-v1\",\n contextLength: 8192,\n provider: \"Amazon\",\n type: \"embedding\",\n },\n {\n name: \"Amazon Titan Embeddings G1 - Text v2\",\n id: \"amazon.titan-embed-text-v2:0\",\n contextLength: 8192,\n provider: \"Amazon\",\n type: \"embedding\",\n },\n {\n name: \"Amazon Titan Image Generator G1\",\n id: \"amazon.titan-image-generator-v1\",\n contextLength: 128,\n provider: \"Amazon\",\n type: \"image\",\n },\n {\n name: \"Amazon Titan Image Generator G2\",\n id: \"amazon.titan-image-generator-v2:0\",\n contextLength: 128,\n provider: \"Amazon\",\n type: \"image\",\n },\n {\n name: \"Amazon Titan Multimodal Embeddings G1\",\n id: \"amazon.titan-embed-image-v1\",\n contextLength: 8192,\n provider: \"Amazon\",\n type: \"embedding\",\n },\n {\n name: \"Amazon Titan Text G1 - Express\",\n id: \"amazon.titan-text-express-v1\",\n contextLength: 8192,\n provider: \"Amazon\",\n },\n {\n name: \"Amazon Titan Text G1 - Lite\",\n id: \"amazon.titan-text-lite-v1\",\n contextLength: 4096,\n provider: \"Amazon\",\n },\n {\n name: \"Amazon Titan Text G1 - Premier\",\n id: \"amazon.titan-text-premier-v1:0\",\n contextLength: 32000,\n provider: \"Amazon\",\n },\n {\n name: \"Claude 3.5 Sonnet v2\",\n id: \"anthropic.claude-3-5-sonnet-20241022-v2:0\",\n contextLength: 200000,\n provider: \"Anthropic\",\n },\n {\n name: \"Claude 3.5 Sonnet v1\",\n id: \"anthropic.claude-3-5-sonnet-20240620-v1:0\",\n contextLength: 200000,\n provider: \"Anthropic\",\n },\n {\n name: \"Claude 3.5 Haiku\",\n id: \"anthropic.claude-3-5-haiku-20241022-v1:0\",\n contextLength: 200000,\n provider: \"Anthropic\",\n },\n {\n name: \"Claude 3 Opus\",\n id: \"anthropic.claude-3-opus-20240229-v1:0\",\n contextLength: 200000,\n provider: \"Anthropic\",\n },\n {\n name: \"Claude 3 Sonnet\",\n id: \"anthropic.claude-3-sonnet-20240229-v1:0\",\n contextLength: 200000,\n provider: \"Anthropic\",\n },\n {\n name: \"Claude 3 Haiku\",\n id: \"anthropic.claude-3-haiku-20240307-v1:0\",\n contextLength: 200000,\n provider: \"Anthropic\",\n },\n {\n name: \"Claude Instant\",\n id: \"anthropic.claude-instant-v1\",\n contextLength: 100000,\n provider: \"Anthropic\",\n },\n {\n name: \"Cohere Command\",\n id: \"cohere.command-text-v14\",\n contextLength: 4096,\n provider: \"Cohere\",\n },\n {\n name: \"Cohere Command Light\",\n id: \"cohere.command-light-text-v14\",\n contextLength: 4096,\n provider: \"Cohere\",\n },\n {\n name: \"Cohere Command R\",\n id: \"cohere.command-r-v1:0\",\n contextLength: 128000,\n provider: \"Cohere\",\n },\n {\n name: \"Cohere Command R+\",\n id: \"cohere.command-r-plus-v1:0\",\n contextLength: 128000,\n provider: \"Cohere\",\n },\n {\n name: \"Cohere Embed English\",\n id: \"cohere.embed-english-v3\",\n contextLength: 512,\n provider: \"Cohere\",\n type: \"embedding\",\n },\n {\n name: \"Cohere Embed Multilingual\",\n id: \"cohere.embed-multilingual-v3\",\n contextLength: 512,\n provider: \"Cohere\",\n type: \"embedding\",\n },\n {\n name: \"Cohere Rerank English\",\n id: \"cohere.rerank-english-v3:0\",\n contextLength: 4096,\n provider: \"Cohere\",\n type: \"reranker\",\n },\n {\n name: \"Cohere Rerank Multilingual\",\n id: \"cohere.rerank-multilingual-v3:0\",\n contextLength: 4096,\n provider: \"Cohere\",\n type: \"reranker\",\n },\n {\n name: \"DeepSeek R1\",\n id: \"deepseek.deepseek-r1-distill-qwen-32b-v1:0\",\n contextLength: 32768,\n provider: \"DeepSeek\",\n },\n {\n name: \"Luma Dream Machine\",\n id: \"luma.dream-machine-v1:0\",\n contextLength: 512,\n provider: \"Luma AI\",\n type: \"video\",\n },\n\n {\n name: \"Llama 3.2 11B Vision Instruct\",\n id: \"meta.llama3-2-11b-instruct-v1:0\",\n contextLength: 128000,\n provider: \"Meta\",\n },\n {\n name: \"Llama 3.2 90B Vision Instruct\",\n id: \"meta.llama3-2-90b-instruct-v1:0\",\n contextLength: 128000,\n provider: \"Meta\",\n },\n {\n name: \"Mistral 7B Instruct\",\n id: \"mistral.mistral-7b-instruct-v0:2\",\n contextLength: 32768,\n provider: \"Mistral AI\",\n },\n {\n name: \"Mixtral 8x7B Instruct\",\n id: \"mistral.mixtral-8x7b-instruct-v0:1\",\n contextLength: 32768,\n provider: \"Mistral AI\",\n },\n {\n name: \"Mistral Small\",\n id: \"mistral.mistral-small-2402-v1:0\",\n contextLength: 32768,\n provider: \"Mistral AI\",\n },\n {\n name: \"Mistral Large\",\n id: \"mistral.mistral-large-2402-v1:0\",\n contextLength: 32768,\n provider: \"Mistral AI\",\n },\n {\n name: \"Mistral Large 2\",\n id: \"mistral.mistral-large-2407-v1:0\",\n contextLength: 128000,\n provider: \"Mistral AI\",\n },\n {\n name: \"Mistral Large 2411\",\n id: \"mistral.mistral-large-2411-v1:0\",\n contextLength: 128000,\n provider: \"Mistral AI\",\n },\n {\n name: \"Stable Diffusion XL\",\n id: \"stability.stable-diffusion-xl-v1\",\n contextLength: 77,\n provider: \"Stability AI\",\n type: \"image\",\n },\n {\n name: \"SDXL 1.0\",\n id: \"stability.stable-diffusion-xl-v0\",\n contextLength: 77,\n provider: \"Stability AI\",\n type: \"image\",\n },\n {\n name: \"Stable Image Ultra\",\n id: \"stability.stable-image-ultra-v1:0\",\n contextLength: 77,\n provider: \"Stability AI\",\n type: \"image\",\n },\n {\n name: \"Stable Image Core\",\n id: \"stability.stable-image-core-v1:0\",\n contextLength: 77,\n provider: \"Stability AI\",\n type: \"image\",\n },\n ],\n },\n {\n \"provider\": \"OpenRouter\",\n \"docs\": \"https://openrouter.ai/docs\",\n \"api_key\": \"https://openrouter.ai/settings/keys\",\n \"default\": \"openrouter/free\",\n \"models\": [\n {\n \"name\": \"OpenRouter Free (rotating)\",\n \"id\": \"openrouter/free\",\n \"contextLength\": 200_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Nemotron 3 Super 120B\",\n \"id\": \"nvidia/nemotron-3-super-120b-a12b:free\",\n \"contextLength\": 1_000_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Nemotron 3 Ultra 550B\",\n \"id\": \"nvidia/nemotron-3-ultra-550b-a55b:free\",\n \"contextLength\": 1_000_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Nemotron 3 Nano 30B A3B\",\n \"id\": \"nvidia/nemotron-3-nano-30b-a3b:free\",\n \"contextLength\": 256_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Nemotron 3 Nano Omni 30B A3B Reasoning\",\n \"id\": \"nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free\",\n \"contextLength\": 256_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Nemotron Nano 12B v2 VL\",\n \"id\": \"nvidia/nemotron-nano-12b-v2-vl:free\",\n \"contextLength\": 128_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Nemotron Nano 9B v2\",\n \"id\": \"nvidia/nemotron-nano-9b-v2:free\",\n \"contextLength\": 128_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Nemotron 3.5 Content Safety\",\n \"id\": \"nvidia/nemotron-3.5-content-safety:free\",\n \"contextLength\": 128_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Gemma 4 31B IT\",\n \"id\": \"google/gemma-4-31b-it:free\",\n \"contextLength\": 262_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Gemma 4 26B A4B IT\",\n \"id\": \"google/gemma-4-26b-a4b-it:free\",\n \"contextLength\": 262_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"GPT-OSS 120B\",\n \"id\": \"openai/gpt-oss-120b:free\",\n \"contextLength\": 131_072,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"GPT-OSS 20B\",\n \"id\": \"openai/gpt-oss-20b:free\",\n \"contextLength\": 131_072,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Qwen3 Coder\",\n \"id\": \"qwen/qwen3-coder:free\",\n \"contextLength\": 1_000_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Qwen3 Next 80B A3B Instruct\",\n \"id\": \"qwen/qwen3-next-80b-a3b-instruct:free\",\n \"contextLength\": 262_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Llama 3.3 70B Instruct\",\n \"id\": \"meta-llama/llama-3.3-70b-instruct:free\",\n \"contextLength\": 131_072,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Llama 3.2 3B Instruct\",\n \"id\": \"meta-llama/llama-3.2-3b-instruct:free\",\n \"contextLength\": 131_072,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Hermes 3 Llama 3.1 405B\",\n \"id\": \"nousresearch/hermes-3-llama-3.1-405b:free\",\n \"contextLength\": 131_072,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Laguna XS 2.1\",\n \"id\": \"poolside/laguna-xs-2.1:free\",\n \"contextLength\": 262_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Laguna XS 2\",\n \"id\": \"poolside/laguna-xs.2:free\",\n \"contextLength\": 262_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Laguna M 1\",\n \"id\": \"poolside/laguna-m.1:free\",\n \"contextLength\": 262_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"North Mini Code\",\n \"id\": \"cohere/north-mini-code:free\",\n \"contextLength\": 256_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Dolphin Mistral 24B Venice Edition\",\n \"id\": \"cognitivecomputations/dolphin-mistral-24b-venice-edition:free\",\n \"contextLength\": 33_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"LFM 2.5 1.2B Thinking\",\n \"id\": \"liquid/lfm-2.5-1.2b-thinking:free\",\n \"contextLength\": 33_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"LFM 2.5 1.2B Instruct\",\n \"id\": \"liquid/lfm-2.5-1.2b-instruct:free\",\n \"contextLength\": 33_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"OpenRouter Free (rotating)\",\n \"id\": \"openrouter/free\",\n \"contextLength\": 200_000,\n \"free\": true,\n \"type\": \"text-generation\"\n }\n ]\n}\n];\n\n/** List of available LLM provider services */\nexport const LANGUAGE_PROVIDERS = LANGUAGE_MODELS.map((p) =>\n p.provider.toLocaleLowerCase(),\n);\n\n/**\n * Guest-safe models that are known to work reliably.\n * Based on test results: only models with HTTP 200 status.\n */\nexport const GUEST_SAFE_MODELS = {\n openrouter: [\n \"openrouter/free\",\n \"nvidia/nemotron-3-super-120b-a12b:free\",\n \"nvidia/nemotron-3-ultra-550b-a55b:free\",\n \"nvidia/nemotron-3-nano-30b-a3b:free\",\n \"nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free\",\n \"nvidia/nemotron-nano-9b-v2:free\",\n \"nvidia/nemotron-3.5-content-safety:free\",\n \"google/gemma-4-31b-it:free\",\n \"google/gemma-4-26b-a4b-it:free\",\n \"openai/gpt-oss-20b:free\",\n \"poolside/laguna-xs-2.1:free\",\n \"poolside/laguna-m.1:free\",\n \"cohere/north-mini-code:free\",\n ],\n nvidia: [\n \"nvidia/nemotron-3-super-120b-a12b\",\n \"meta/llama-3.1-8b-instruct\",\n ],\n};\n\n/**\n * Filter models to only those in the guest-safe list.\n * Returns models with `free: true` property.\n */\nexport function filterModelsForGuests(models: any[]): any[] {\n return models.filter((m) => m.free === true);\n}\n\n/**\n * Get guest-safe provider list (only tested working models).\n * Uses GUEST_SAFE_MODELS whitelist to ensure reliability.\n */\nexport function getGuestSafeProviders(): typeof LANGUAGE_MODELS {\n return LANGUAGE_MODELS.map((provider) => ({\n ...provider,\n models: provider.models.filter(\n (model: any) =>\n GUEST_SAFE_MODELS[provider.provider.toLowerCase() as keyof typeof GUEST_SAFE_MODELS]?.includes(\n model.id,\n ) || false,\n ),\n })).filter((p) => p.models.length > 0);\n}\n","/**\n * @fileoverview Configuration Manager\n *\n * Manages model providers, MCP servers, and search configuration in memory.\n * Handles environment variable loading, provider hashing, and config updates.\n */\nimport type { ConfigModelProvider, MCPServerConfig, Config, UIConfigSections, Model } from \"./config-types\";\nimport { getModelProvidersUIConfigSection } from \"./provider-ui-config\";\nimport { getEnv } from \"./environment-variables\";\nimport { LANGUAGE_MODELS } from \"./language-models-database\";\n\n// Maps a provider UI key (from provider-ui-config) to the matching\n// `provider` name in the LANGUAGE_MODELS database. Names differ in a few\n// cases (e.g. the \"gemini\" UI key corresponds to the \"Google\" model list).\nconst PROVIDER_KEY_TO_DB_NAME: Record<string, string> = {\n openai: \"openai\",\n anthropic: \"anthropic\",\n gemini: \"google\",\n groq: \"groq\",\n deepseek: \"deepseek\",\n nvidia: \"nvidia\",\n openrouter: \"openrouter\",\n};\n\n/**\n * Returns the default chat models for a provider from the LANGUAGE_MODELS\n * database so that env-based providers expose a usable model list instead of\n * an empty one. Returns [] when no matching provider list exists.\n */\nconst getDefaultChatModels = (providerKey: string): Model[] => {\n const dbName = PROVIDER_KEY_TO_DB_NAME[providerKey] ?? providerKey;\n const entry = LANGUAGE_MODELS.find(\n (p) => p.provider.toLowerCase() === dbName.toLowerCase(),\n );\n if (!entry?.models) return [];\n\n return entry.models.map((m: any) => ({\n name: m.name,\n key: m.id,\n }));\n};\n\nconst hashObj = (obj: { [key: string]: any }) => {\n const str = JSON.stringify(obj, Object.keys(obj).sort());\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n hash = (hash << 5) - hash + str.charCodeAt(i);\n hash |= 0;\n }\n return String(Math.abs(hash).toString(36));\n};\n\nclass ConfigManager {\n configVersion = 1;\n currentConfig: Config = {\n version: this.configVersion,\n setupComplete: getEnv(\"SETUP_COMPLETE\") === \"true\" || false,\n preferences: {},\n personalization: {},\n modelProviders: [],\n mcpServers: [],\n search: {\n searxngURL: \"\",\n tavilyApiKey: \"\",\n sourceScrapeCount: 3,\n sourceScrapeTimeout: 5,\n },\n };\n uiConfigSections: UIConfigSections = {\n preferences: [],\n personalization: [],\n modelProviders: [],\n mcpServers: [],\n search: [\n {\n name: \"SearXNG URL\",\n key: \"searxngURL\",\n type: \"string\",\n required: false,\n description: \"The URL of your SearXNG instance\",\n placeholder: \"http://localhost:4000\",\n default: \"\",\n scope: \"server\",\n env: \"SEARXNG_API_URL\",\n },\n {\n name: \"Tavily API Key\",\n key: \"tavilyApiKey\",\n type: \"string\",\n required: false,\n description: \"Your Tavily API key for enhanced search capabilities.\",\n placeholder: \"tvly-...\",\n default: \"\",\n scope: \"server\",\n env: \"TAVILY_API_KEY\",\n },\n {\n name: \"Source pages to scrape\",\n key: \"sourceScrapeCount\",\n type: \"select\",\n options: [\n { name: \"Disabled (snippet only)\", value: \"0\" },\n { name: \"1 page\", value: \"1\" },\n { name: \"2 pages\", value: \"2\" },\n { name: \"3 pages (default)\", value: \"3\" },\n { name: \"5 pages\", value: \"5\" },\n ],\n required: false,\n description: \"Number of top search result URLs to fully scrape.\",\n default: \"3\",\n scope: \"server\",\n },\n {\n name: \"Scrape timeout (seconds)\",\n key: \"sourceScrapeTimeout\",\n type: \"select\",\n options: [\n { name: \"3 seconds\", value: \"3\" },\n { name: \"5 seconds (default)\", value: \"5\" },\n { name: \"10 seconds\", value: \"10\" },\n { name: \"15 seconds\", value: \"15\" },\n { name: \"20 seconds\", value: \"20\" },\n ],\n required: false,\n description: \"Maximum time to wait when scraping each source URL.\",\n default: \"5\",\n scope: \"server\",\n },\n ],\n };\n\n private initialized = false;\n\n constructor() {\n // Don't initialize in constructor to avoid circular dependency\n // Initialize lazily when config is first accessed\n }\n\n private ensureInitialized() {\n if (this.initialized) return;\n this.initialize();\n this.initialized = true;\n }\n\n private initialize() {\n const providerConfigSections = getModelProvidersUIConfigSection();\n this.uiConfigSections.modelProviders = providerConfigSections;\n\n const newProviders: ConfigModelProvider[] = [];\n\n providerConfigSections.forEach((provider) => {\n\n const tempConfig: Record<string, any> = {};\n const required: string[] = [];\n\n provider.fields.forEach((field) => {\n tempConfig[field.key] =\n getEnv(field.env!) || field.default || \"\";\n if (field.required) required.push(field.key);\n });\n\n let configured = true;\n required.forEach((r) => {\n if (!tempConfig[r]) configured = false;\n });\n\n if (configured) {\n const hash = hashObj(tempConfig);\n const exists = this.currentConfig.modelProviders.find(\n (p) => p.hash === hash,\n );\n\n if (!exists) {\n newProviders.push({\n id: hash,\n name: `${provider.name}`,\n type: provider.key,\n chatModels: getDefaultChatModels(provider.key),\n config: tempConfig,\n hash: hash,\n isEnvBased: true,\n });\n }\n }\n });\n\n if (newProviders.length > 0) {\n this.currentConfig.modelProviders.push(...newProviders);\n }\n\n // Search config from env\n this.uiConfigSections.search.forEach((f) => {\n if (f.env && !this.currentConfig.search[f.key]) {\n this.currentConfig.search[f.key] =\n getEnv(f.env) ?? f.default ?? \"\";\n }\n });\n }\n\n public getConfig(key: string, defaultValue?: any): any {\n this.ensureInitialized();\n const nested = key.split(\".\");\n let obj: any = this.currentConfig;\n\n for (let i = 0; i < nested.length; i++) {\n const part = nested[i];\n if (obj == null) return defaultValue;\n obj = obj[part];\n }\n\n return obj === undefined ? defaultValue : obj;\n }\n\n public updateConfig(key: string, val: any) {\n const parts = key.split(\".\");\n if (parts.length === 0) return;\n\n let target: any = this.currentConfig;\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n if (target[part] === null || typeof target[part] !== \"object\") {\n target[part] = {};\n }\n target = target[part];\n }\n\n const finalKey = parts[parts.length - 1];\n target[finalKey] = val;\n }\n\n public addModelProvider(type: string, name: string, config: any) {\n this.ensureInitialized();\n const hash = hashObj(config);\n\n const newModelProvider: ConfigModelProvider = {\n id: hash,\n name,\n type,\n config,\n chatModels: [],\n hash: hash,\n };\n\n this.currentConfig.modelProviders.push(newModelProvider);\n return newModelProvider;\n }\n\n public removeModelProvider(id: string) {\n this.currentConfig.modelProviders =\n this.currentConfig.modelProviders.filter((p) => p.id !== id);\n }\n\n public async updateModelProvider(id: string, name: string, config: any) {\n const provider = this.currentConfig.modelProviders.find(\n (p) => p.id === id,\n );\n if (!provider) throw new Error(\"Provider not found\");\n\n provider.name = name;\n provider.config = config;\n return provider;\n }\n\n public addProviderModel(providerId: string, type: \"chat\", model: any) {\n const provider = this.currentConfig.modelProviders.find(\n (p) => p.id === providerId,\n );\n if (!provider) throw new Error(\"Invalid provider id\");\n\n delete model.type;\n provider.chatModels.push(model);\n return model;\n }\n\n public removeProviderModel(\n providerId: string,\n type: \"chat\",\n modelKey: string,\n ) {\n const provider = this.currentConfig.modelProviders.find(\n (p) => p.id === providerId,\n );\n if (!provider) throw new Error(\"Invalid provider id\");\n\n provider.chatModels = provider.chatModels.filter((m) => m.key !== modelKey);\n }\n\n public isSetupComplete() {\n return this.currentConfig.setupComplete;\n }\n\n public markSetupComplete() {\n if (!this.currentConfig.setupComplete) {\n this.currentConfig.setupComplete = true;\n }\n }\n\n public getUIConfigSections(): UIConfigSections {\n this.ensureInitialized();\n return this.uiConfigSections;\n }\n\n public getCurrentConfig(): Config {\n this.ensureInitialized();\n return JSON.parse(JSON.stringify(this.currentConfig));\n }\n}\n\nconst configManager = new ConfigManager();\n\nexport default configManager;\n","/**\n * @fileoverview Registry for managing and loading Vercel AI SDK model providers.\n *\n * Exposes the full API expected by the app's API routes and chat handler:\n * - `activeProviders` (sync getter) / `getActiveProviders()`\n * - `isProviderEnvBased(providerId)`\n * - `loadChatModel(providerId, modelKey)` — returns an AI SDK `LanguageModel`\n * - provider/model CRUD passthroughs to {@link configManager}\n */\nimport configManager from \"./config-manager\";\nimport { LANGUAGE_MODELS, getGuestSafeProviders } from \"./language-models-database\";\nimport { getModelProvidersUIConfigSection } from \"./provider-ui-config\";\nimport type { ConfigModelProvider, Model } from \"./config-types\";\n\n// Maps a provider UI key to the matching `provider` name in the\n// LANGUAGE_MODELS database (e.g. the \"gemini\" UI key ↔ \"Google\" model list).\nconst PROVIDER_KEY_TO_DB_NAME: Record<string, string> = {\n openai: \"openai\",\n anthropic: \"anthropic\",\n gemini: \"google\",\n groq: \"groq\",\n deepseek: \"deepseek\",\n nvidia: \"nvidia\",\n openrouter: \"openrouter\",\n};\n\n/** Default chat models for a provider type from the LANGUAGE_MODELS database. */\nconst getDefaultChatModels = (providerType: string): Model[] => {\n const dbName = PROVIDER_KEY_TO_DB_NAME[providerType] ?? providerType;\n const entry = LANGUAGE_MODELS.find(\n (p) => p.provider.toLowerCase() === dbName.toLowerCase(),\n );\n if (!entry?.models) return [];\n return entry.models.map((m: any) => ({ name: m.name, key: m.id }));\n};\n\n/** Merges default and user-added models, deduplicated by model key. */\nconst mergeChatModels = (provider: ConfigModelProvider): Model[] => {\n const merged = new Map<string, Model>();\n for (const m of getDefaultChatModels(provider.type)) {\n merged.set(m.key, m);\n }\n for (const m of provider.chatModels || []) {\n merged.set(m.key, { key: m.key, name: m.name });\n }\n return [...merged.values()];\n};\n\nexport default class ModelRegistry {\n /**\n * Currently configured providers (env-based + user-added).\n * Sync getter used by the chat handler for logging and lookups.\n */\n get activeProviders(): ConfigModelProvider[] {\n return configManager.getCurrentConfig().modelProviders;\n }\n\n /**\n * Providers with their full chat model lists (defaults merged with\n * user-added models), shaped for the settings/providers UI.\n */\n async getActiveProviders(guestMode: boolean = false) {\n const providers = this.activeProviders;\n const dbModels = guestMode ? getGuestSafeProviders() : LANGUAGE_MODELS;\n\n return providers.map((p) => ({\n id: p.id,\n name: p.name,\n type: p.type,\n chatModels: guestMode ? this.getGuestChatModels(p, dbModels) : mergeChatModels(p),\n })).filter((p) => p.chatModels.length > 0);\n }\n\n /**\n * Get guest-safe chat models for a provider (only tested working models).\n */\n private getGuestChatModels(provider: ConfigModelProvider, guestProviders: typeof LANGUAGE_MODELS): Model[] {\n const dbName = PROVIDER_KEY_TO_DB_NAME[provider.type.toLowerCase()];\n const dbEntry = guestProviders.find(\n (p) => p.provider.toLowerCase() === (dbName?.toLowerCase() || provider.type.toLowerCase()),\n );\n if (!dbEntry?.models) return [];\n return dbEntry.models.map((m: any) => ({ name: m.name, key: m.id }));\n }\n\n /**\n * Finds a provider by id, falling back to free providers in order:\n * OpenRouter (no daily limits, best for guests), Groq (fastest, daily limits),\n * then NVIDIA, then the first configured provider.\n * Client-side provider ids are config hashes that go stale whenever\n * server env config changes, so a graceful fallback keeps existing\n * chat sessions working after a redeploy.\n */\n private findProvider(providerId?: string): ConfigModelProvider | undefined {\n const providers = this.activeProviders;\n let provider = providers.find((p) => p.id === providerId);\n\n if (!provider && providers.length > 0) {\n // Prioritize OpenRouter (no daily limits) over Groq (has daily limits)\n provider =\n providers.find((p) => p.name.toLowerCase().includes(\"openrouter\")) ??\n providers.find((p) => p.name.toLowerCase().includes(\"groq\")) ??\n providers.find((p) => p.name.toLowerCase().includes(\"nvidia\")) ??\n providers[0];\n }\n\n return provider;\n }\n\n /** Whether the resolved provider was configured from environment variables. */\n isProviderEnvBased(providerId?: string): boolean {\n return this.findProvider(providerId)?.isEnvBased === true;\n }\n\n /**\n * Instantiates a Vercel AI SDK language model for the given provider and\n * model key. Falls back to the provider's first/default model when no key\n * is given. Temperature is a per-call setting in the AI SDK, so callers\n * pass it to generateText/streamText rather than the model instance.\n */\n async loadChatModel(providerId?: string, modelKey?: string): Promise<any> {\n const provider = this.findProvider(providerId);\n\n if (!provider) {\n throw new Error(\n \"No model providers configured. Please add a provider in settings.\",\n );\n }\n\n const type = provider.type.toLowerCase();\n const config = provider.config || {};\n const apiKey = config.apiKey || \"\";\n const availableModels = mergeChatModels(provider);\n const modelName =\n modelKey || availableModels[0]?.key || \"\";\n\n console.log(\n `[ModelRegistry] loadChatModel: providerId=${providerId} provider=${provider.name} type=${type} requestedModel=${modelKey ?? \"(default)\"} resolvedModel=${modelName}`,\n );\n\n if (!modelName) {\n throw new Error(`No chat models available for provider \"${provider.name}\"`);\n }\n\n // Validate that the requested model exists in the provider's model list\n if (modelKey && !availableModels.some((m) => m.key === modelKey)) {\n console.warn(\n `[ModelRegistry] Requested model \"${modelKey}\" not found in provider \"${provider.name}\". Available models: ${availableModels.map((m) => m.key).join(\", \")}`,\n );\n throw new Error(\n `Model \"${modelKey}\" is not available for provider \"${provider.name}\". Please select a different model in Settings.`,\n );\n }\n\n // Validate API key is present\n if (!apiKey) {\n throw new Error(\n `No API key configured for provider \"${provider.name}\". Please add your API key in Settings → Model Providers.`,\n );\n }\n\n // OpenAI-compatible providers differ only by base URL.\n const openAICompatibleBaseURLs: Record<string, string> = {\n openai: \"https://api.openai.com/v1\",\n togetherai: \"https://api.together.xyz/v1\",\n perplexity: \"https://api.perplexity.ai\",\n nvidia: \"https://integrate.api.nvidia.com/v1\",\n openrouter: \"https://openrouter.ai/api/v1\",\n deepseek: \"https://api.deepseek.com\",\n xai: \"https://api.x.ai/v1\",\n };\n\n if (type in openAICompatibleBaseURLs) {\n const { createOpenAI } = await import(\"@ai-sdk/openai\");\n return createOpenAI({\n apiKey,\n baseURL: config.baseURL || openAICompatibleBaseURLs[type],\n }).chat(modelName);\n }\n\n switch (type) {\n case \"cloudflare\": {\n const { createOpenAI } = await import(\"@ai-sdk/openai\");\n const [cfApiToken, accountId] = apiKey.split(\":\");\n return createOpenAI({\n apiKey: cfApiToken,\n baseURL: `https://api.cloudflare.com/client/v4/accounts/${accountId}/ai/v1`,\n }).chat(modelName);\n }\n case \"groq\": {\n const { createGroq } = await import(\"@ai-sdk/groq\");\n return createGroq({ apiKey })(modelName);\n }\n case \"anthropic\": {\n const { createAnthropic } = await import(\"@ai-sdk/anthropic\");\n return createAnthropic({ apiKey })(modelName);\n }\n case \"gemini\":\n case \"google\": {\n const { createGoogleGenerativeAI } = await import(\"@ai-sdk/google\");\n return createGoogleGenerativeAI({ apiKey })(modelName);\n }\n default:\n throw new Error(`Unsupported provider type: ${type}`);\n }\n }\n\n /**\n * Registers a new provider. Accepts both `(type, config)` — used by the\n * providers API route — and `(type, name, config)`.\n */\n async addProvider(type: string, nameOrConfig: any, config?: Record<string, any>) {\n let name: string;\n let finalConfig: Record<string, any>;\n if (typeof nameOrConfig === \"object\" && nameOrConfig !== null && !config) {\n finalConfig = nameOrConfig;\n const section = getModelProvidersUIConfigSection().find(\n (s) => s.key === type,\n );\n name = section?.name || type.toUpperCase();\n } else {\n name = String(nameOrConfig);\n finalConfig = config || {};\n }\n\n const newProvider = configManager.addModelProvider(type, name, finalConfig);\n return {\n ...newProvider,\n chatModels: getDefaultChatModels(type),\n };\n }\n\n async removeProvider(providerId: string) {\n configManager.removeModelProvider(providerId);\n }\n\n /**\n * Updates a provider's config. Accepts both `(id, config)` — used by the\n * providers API route — and `(id, name, config)`.\n */\n async updateProvider(providerId: string, nameOrConfig: any, config?: Record<string, any>) {\n let name: string;\n let finalConfig: Record<string, any>;\n if (typeof nameOrConfig === \"object\" && nameOrConfig !== null && !config) {\n finalConfig = nameOrConfig;\n const existing = this.activeProviders.find((p) => p.id === providerId);\n name = existing?.name || providerId;\n } else {\n name = String(nameOrConfig);\n finalConfig = config || {};\n }\n\n const updated = await configManager.updateModelProvider(\n providerId,\n name,\n finalConfig,\n );\n return {\n ...updated,\n chatModels: mergeChatModels(updated),\n };\n }\n\n async addProviderModel(providerId: string, type: \"chat\", model: any) {\n return configManager.addProviderModel(providerId, type, model);\n }\n\n async removeProviderModel(providerId: string, type: \"chat\", modelKey: string) {\n configManager.removeProviderModel(providerId, type, modelKey);\n }\n}\n","const PROVIDERS = {\n openrouter: { row: 0, col: 0 },\n tongyi: { row: 0, col: 1 },\n ollama: { row: 0, col: 2 },\n huggingface: { row: 0, col: 3 },\n localai: { row: 0, col: 4 },\n openllm: { row: 0, col: 5 },\n zhipu: { row: 1, col: 0 },\n replicate: { row: 1, col: 1 },\n azure: { row: 1, col: 2 },\n anthropic: { row: 1, col: 3 },\n groq: { row: 1, col: 4 },\n sagemaker: { row: 1, col: 5 },\n \"01ai\": { row: 2, col: 0 },\n bedrock: { row: 2, col: 1 },\n openai: { row: 2, col: 2 },\n cohere: { row: 2, col: 3 },\n together: { row: 2, col: 4 },\n xorbits: { row: 2, col: 5 },\n wenxin: { row: 3, col: 0 },\n moonshot: { row: 3, col: 1 },\n gemini: { row: 3, col: 2 },\n mistral: { row: 3, col: 3 },\n jina: { row: 3, col: 4 },\n chatglm: { row: 3, col: 5 },\n} as const;\n\nexport type Provider = keyof typeof PROVIDERS;\n\nconst COLS = 6;\nconst ROWS = 4;\n\n/**\n * Returns a cropped canvas containing just the provider box.\n */\nexport async function cropProvider(\n image: HTMLImageElement | ImageBitmap,\n provider: Provider\n): Promise<HTMLCanvasElement> {\n if (!(provider in PROVIDERS)) {\n throw new Error(`Unknown provider: ${provider}`);\n }\n\n const { row, col } = PROVIDERS[provider];\n\n const tileWidth = image.width / COLS;\n const tileHeight = image.height / ROWS;\n\n const canvas = document.createElement(\"canvas\");\n canvas.width = tileWidth;\n canvas.height = tileHeight;\n\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n throw new Error(\"Failed to get 2D context\");\n }\n\n ctx.drawImage(\n image,\n col * tileWidth,\n row * tileHeight,\n tileWidth,\n tileHeight,\n 0,\n 0,\n tileWidth,\n tileHeight\n );\n\n return canvas;\n}\n\n/**\n * Returns the provider image as a Blob.\n */\nexport async function cropProviderAsBlob(\n image: HTMLImageElement | ImageBitmap,\n provider: Provider,\n type: \"image/png\" | \"image/jpeg\" | \"image/webp\" = \"image/png\",\n quality?: number\n): Promise<Blob> {\n const canvas = await cropProvider(image, provider);\n\n return new Promise<Blob>((resolve, reject) => {\n canvas.toBlob(\n (blob) => {\n if (blob) {\n resolve(blob);\n } else {\n reject(new Error(\"Failed to create blob\"));\n }\n },\n type,\n quality\n );\n });\n}\n\n/**\n * Returns the provider image as a data URL.\n */\nexport async function cropProviderAsDataURL(\n image: HTMLImageElement | ImageBitmap,\n provider: Provider,\n type: \"image/png\" | \"image/jpeg\" | \"image/webp\" = \"image/png\",\n quality?: number\n): Promise<string> {\n const canvas = await cropProvider(image, provider);\n return canvas.toDataURL(type, quality);\n}\n\n/**\n * Helper to load and crop in one call.\n */\nexport async function getProviderImage(\n spriteSheetUrl: string,\n provider: Provider\n): Promise<HTMLCanvasElement> {\n const img = new Image();\n img.src = spriteSheetUrl;\n await img.decode();\n return cropProvider(img, provider);\n}\n\n/**\n * Get all available provider names.\n */\nexport function getProviderNames(): Provider[] {\n return Object.keys(PROVIDERS) as Provider[];\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"research-agent.cjs.js","names":[],"sources":["../src/memory/types.ts","../src/memory/storage/in-memory-storage.ts","../src/memory/agent-memory-manager.ts","../src/memory/storage/drizzle-storage.ts","../src/memory/mastra-integration.ts","../src/tools/qwksearch-api-tools.ts","../src/utils/outputParser.ts","../src/utils/chat-helpers.ts","../src/tools/search/doc-utils.ts","../src/tools/search/link-summarizer.ts","../src/tools/search/metaSearchAgent.ts","../src/tools/search/search-handlers.ts","../src/tools/search/suggestionGeneratorAgent.ts","../src/tools/search/document.ts","../src/config/provider-ui-config.ts","../src/config/environment-variables.ts","../src/config/language-models-database.ts","../src/config/config-manager.ts","../src/config/model-registry.ts","../src/utils/provider-image-cropper.ts"],"sourcesContent":["/**\n * Memory System Types and Constants\n *\n * Defines interfaces and configuration for the memory management system\n */\n\n/**\n * Memory types for categorization\n */\nexport const MEMORY_TYPES = {\n FACT: \"fact\",\n CONVERSATION: \"conversation\",\n PREFERENCE: \"preference\",\n PERSONAL: \"personal\",\n WORK: \"work\",\n MANUAL: \"manual\",\n} as const;\n\nexport type MemoryType = (typeof MEMORY_TYPES)[keyof typeof MEMORY_TYPES];\n\n/**\n * Configuration constants for memory management\n */\nexport const MEMORY_CONFIG = {\n DEFAULT_MAX_MEMORIES: 100,\n DEFAULT_SUMMARY_THRESHOLD: 10,\n DEFAULT_CACHE_EXPIRY: 5 * 60 * 1000, // 5 minutes\n DEFAULT_BATCH_SIZE: 5,\n DEFAULT_RELEVANCE_THRESHOLD: 0.3,\n DEFAULT_IMPORTANCE_RANGE: { min: 0, max: 10 },\n DEFAULT_RATE_LIMIT: { requests: 10, windowMs: 60000 },\n DEFAULT_TIMEOUT: 30000, // 30 seconds\n VECTOR_SEARCH_ENABLED: true,\n AUTO_SUMMARIZATION_ENABLED: true,\n} as const;\n\n/**\n * Memory record structure\n */\nexport interface MemoryRecord {\n id: string;\n user_id: string;\n memory_type: MemoryType;\n content: string;\n importance: number;\n access_count: number;\n metadata?: Record<string, any>;\n created_at: Date;\n updated_at: Date;\n relevance_score?: number;\n}\n\n/**\n * Message structure for conversation tracking\n */\nexport interface Message {\n role: \"user\" | \"assistant\";\n content: string;\n timestamp: number;\n metadata?: Record<string, any>;\n}\n\n/**\n * Memory search options\n */\nexport interface MemorySearchOptions {\n minImportance?: number;\n memoryType?: MemoryType;\n includeMetadata?: boolean;\n}\n\n/**\n * Memory update payload\n */\nexport interface MemoryUpdate {\n importance?: number;\n access_count?: number | { increment: number };\n updated_at?: Date;\n metadata?: Record<string, any>;\n}\n\n/**\n * Memory context options\n */\nexport interface MemoryContextOptions {\n maxMemories?: number;\n minImportance?: number;\n}\n\n/**\n * Performance metrics\n */\nexport interface MemoryMetrics {\n cacheHits: number;\n cacheMisses: number;\n vectorSearches: number;\n summarizations: number;\n errors: number;\n cacheSize: number;\n recentMessagesCount: number;\n isProcessing: boolean;\n}\n\n/**\n * Memory initialization options\n */\nexport interface MemoryOptions {\n maxMemories?: number;\n summaryThreshold?: number;\n cacheExpiry?: number;\n batchSize?: number;\n relevanceThreshold?: number;\n enableVectorSearch?: boolean;\n enableAutoSummarization?: boolean;\n}\n\n/**\n * Extracted fact structure\n */\nexport interface ExtractedFact {\n content: string;\n importance?: number;\n category?: MemoryType;\n metadata?: Record<string, any>;\n}\n","// @ts-nocheck\n/**\n * Simple Memory Class\n *\n * Core memory management functionality with:\n * - Message deduplication\n * - Automatic summarization\n * - Vector-based relevance search\n * - Caching with TTL\n * - Batch processing\n * - Conflict resolution\n */\n\nimport { writeLanguageResponse } from \"write-language\";\nimport type { IMemoryStorage } from \"./storage-interface\";\nimport type {\n MemoryRecord,\n Message,\n MemorySearchOptions,\n MemoryMetrics,\n MemoryOptions,\n MemoryContextOptions,\n ExtractedFact,\n MemoryType,\n} from \"../types\";\nimport { MEMORY_CONFIG, MEMORY_TYPES } from \"../types\";\n\nexport class SimpleMemory {\n private userId: string;\n private storage: IMemoryStorage;\n private maxMemories: number;\n private summaryThreshold: number;\n private cacheExpiry: number;\n private batchSize: number;\n private relevanceThreshold: number;\n private enableVectorSearch: boolean;\n private enableAutoSummarization: boolean;\n private recentMessages: Message[];\n private memoryCache: Map<string, { data: any; timestamp: number }>;\n private isProcessing: boolean;\n private processingQueue: any[];\n private summarizeTimeout?: NodeJS.Timeout;\n private metrics: {\n cacheHits: number;\n cacheMisses: number;\n vectorSearches: number;\n summarizations: number;\n errors: number;\n };\n\n /**\n * Initialize memory system for a user\n */\n constructor(\n userId: string,\n storage: IMemoryStorage,\n options: MemoryOptions = {},\n ) {\n if (!userId || !storage) {\n throw new Error(\"userId and storage are required parameters\");\n }\n\n this.userId = userId;\n this.storage = storage;\n this.maxMemories =\n options.maxMemories || MEMORY_CONFIG.DEFAULT_MAX_MEMORIES;\n this.summaryThreshold =\n options.summaryThreshold || MEMORY_CONFIG.DEFAULT_SUMMARY_THRESHOLD;\n this.cacheExpiry =\n options.cacheExpiry || MEMORY_CONFIG.DEFAULT_CACHE_EXPIRY;\n this.batchSize = options.batchSize || MEMORY_CONFIG.DEFAULT_BATCH_SIZE;\n this.relevanceThreshold =\n options.relevanceThreshold || MEMORY_CONFIG.DEFAULT_RELEVANCE_THRESHOLD;\n\n // Feature flags\n this.enableVectorSearch =\n options.enableVectorSearch !== false &&\n MEMORY_CONFIG.VECTOR_SEARCH_ENABLED;\n this.enableAutoSummarization =\n options.enableAutoSummarization !== false &&\n MEMORY_CONFIG.AUTO_SUMMARIZATION_ENABLED;\n\n // State management\n this.recentMessages = [];\n this.memoryCache = new Map();\n this.isProcessing = false;\n this.processingQueue = [];\n\n // Performance metrics\n this.metrics = {\n cacheHits: 0,\n cacheMisses: 0,\n vectorSearches: 0,\n summarizations: 0,\n errors: 0,\n };\n }\n\n /**\n * Add a message to current session with intelligent deduplication\n */\n addMessage(\n role: \"user\" | \"assistant\",\n content: string,\n metadata: Record<string, any> = {},\n ): boolean {\n if (!role || !content || typeof content !== \"string\") {\n console.warn(\"Invalid message parameters:\", { role, content });\n return false;\n }\n\n // Intelligent deduplication - check last few messages\n const lastMessages = this.recentMessages.slice(-3);\n const isDuplicate = lastMessages.some(\n (msg) =>\n msg.role === role &&\n msg.content === content &&\n Date.now() - msg.timestamp < 60000, // Within 1 minute\n );\n\n if (isDuplicate) {\n console.log(\"Duplicate message detected, skipping\");\n return false;\n }\n\n // Add message with metadata\n const message: Message = {\n role,\n content: content.trim(),\n timestamp: metadata.timestamp || Date.now(),\n metadata: { ...metadata },\n };\n\n this.recentMessages.push(message);\n\n // Auto-summarization with debouncing\n if (\n this.enableAutoSummarization &&\n this.recentMessages.length >= this.summaryThreshold &&\n !this.isProcessing\n ) {\n this.debouncedSummarize();\n }\n\n return true;\n }\n\n /**\n * Debounced summarization to prevent excessive processing\n */\n private debouncedSummarize(): void {\n if (this.summarizeTimeout) {\n clearTimeout(this.summarizeTimeout);\n }\n\n this.summarizeTimeout = setTimeout(() => {\n this.summarizeAndStore().catch((error) => {\n console.error(\"Auto-summarization failed:\", error);\n this.metrics.errors++;\n });\n }, 1000); // 1 second debounce\n }\n\n /**\n * Store important facts with validation and conflict resolution\n */\n async storeFact(\n content: string,\n importance: number = 1,\n category: MemoryType = MEMORY_TYPES.FACT,\n metadata: Record<string, any> = {},\n ): Promise<string> {\n // Input validation\n if (\n !content ||\n typeof content !== \"string\" ||\n content.trim().length === 0\n ) {\n throw new Error(\"Content cannot be empty\");\n }\n\n if (\n importance < MEMORY_CONFIG.DEFAULT_IMPORTANCE_RANGE.min ||\n importance > MEMORY_CONFIG.DEFAULT_IMPORTANCE_RANGE.max\n ) {\n throw new Error(\n `Importance must be between ${MEMORY_CONFIG.DEFAULT_IMPORTANCE_RANGE.min} and ${MEMORY_CONFIG.DEFAULT_IMPORTANCE_RANGE.max}`,\n );\n }\n\n const normalizedContent = content.trim();\n const normalizedCategory = Object.values(MEMORY_TYPES).includes(category)\n ? category\n : MEMORY_TYPES.FACT;\n\n try {\n // Check for existing similar facts using fuzzy matching\n const existingFacts = await this.findSimilarFacts(normalizedContent);\n\n if (existingFacts.length > 0) {\n // Update existing fact if importance is higher\n const bestMatch = existingFacts[0];\n if (importance > bestMatch.importance) {\n await this.storage.updateMemory(bestMatch.id, {\n importance,\n updated_at: new Date(),\n access_count: { increment: 1 },\n metadata: { ...bestMatch.metadata, ...metadata },\n });\n }\n return bestMatch.id;\n }\n\n // Insert new fact\n const id = await this.storage.insertMemory(\n this.userId,\n normalizedCategory,\n normalizedContent,\n Math.max(0, Math.min(10, importance)),\n metadata,\n );\n\n // Clear cache after new insertion\n this.clearCache();\n\n return id;\n } catch (error) {\n console.error(\"Error storing fact:\", error);\n this.metrics.errors++;\n throw error;\n }\n }\n\n /**\n * Find similar facts using content similarity\n */\n private async findSimilarFacts(content: string): Promise<MemoryRecord[]> {\n try {\n return await this.storage.findSimilarMemories(this.userId, content, 5);\n } catch (error) {\n console.error(\"Error finding similar facts:\", error);\n return [];\n }\n }\n\n /**\n * Enhanced memory recall with caching and vector search\n */\n async recallRelevantMemories(\n query: string = \"\",\n limit: number = 10,\n options: MemorySearchOptions = {},\n ): Promise<MemoryRecord[]> {\n const cacheKey = `${query}-${limit}-${JSON.stringify(options)}`;\n\n // Check cache first\n if (this.memoryCache.has(cacheKey)) {\n const cached = this.memoryCache.get(cacheKey)!;\n if (Date.now() - cached.timestamp < this.cacheExpiry) {\n this.metrics.cacheHits++;\n return cached.data;\n }\n this.memoryCache.delete(cacheKey);\n }\n\n this.metrics.cacheMisses++;\n\n try {\n let memories = await this.storage.findMemories(\n this.userId,\n query,\n limit,\n options,\n );\n\n if (memories.length === 0) {\n return [];\n }\n\n // Apply vector search if enabled and query provided\n if (this.enableVectorSearch && query.trim() && memories.length > 0) {\n memories = await this.applyVectorSearch(query, memories, options);\n }\n\n // Apply relevance filtering\n if (options.minImportance) {\n memories = memories.filter(\n (m) => m.importance >= options.minImportance!,\n );\n }\n\n // Format results\n const result = memories.map((m) => ({\n ...m,\n relevance_score: m.relevance_score || 0,\n metadata: options.includeMetadata ? m.metadata : undefined,\n }));\n\n // Cache the result\n this.memoryCache.set(cacheKey, {\n data: result,\n timestamp: Date.now(),\n });\n\n return result;\n } catch (error) {\n console.error(\"Error retrieving memories:\", error);\n this.metrics.errors++;\n return [];\n }\n }\n\n /**\n * Apply vector search to memories\n */\n private async applyVectorSearch(\n query: string,\n memories: MemoryRecord[],\n options: MemorySearchOptions,\n ): Promise<MemoryRecord[]> {\n // Placeholder for vector search implementation\n // In production, integrate with your vector similarity API\n // try {\n // this.metrics.vectorSearches++;\n // const sentencesByRelevance = await weighRelevanceConceptVectorAPI(\n // query,\n // memories.map(m => m.content)\n // );\n // await this.updateRelevanceScores(memories, sentencesByRelevance);\n // return memories\n // .map(memory => {\n // const relevanceData = sentencesByRelevance.find(s => s.sentence === memory.content);\n // return {\n // ...memory,\n // relevance_score: relevanceData?.relevance || 0\n // };\n // })\n // .sort((a, b) => b.relevance_score - a.relevance_score);\n // } catch (vectorError) {\n // console.warn('Vector search failed, falling back to basic search:', vectorError);\n // return memories;\n // }\n return memories;\n }\n\n /**\n * Update relevance scores for memories\n */\n private async updateRelevanceScores(\n memories: MemoryRecord[],\n sentencesByRelevance: Array<{ sentence: string; relevance: number }>,\n ): Promise<void> {\n const updates = sentencesByRelevance\n .filter((m) => m.relevance > this.relevanceThreshold)\n .map((m) => {\n const memory = memories.find((mem) => mem.content === m.sentence);\n if (memory) {\n return {\n id: memory.id,\n updates: {\n importance: Math.min(10, memory.importance + m.relevance * 0.5),\n access_count: { increment: 1 },\n updated_at: new Date(),\n },\n };\n }\n return null;\n })\n .filter(Boolean) as Array<{ id: string; updates: any }>;\n\n if (updates.length > 0) {\n await this.storage.batchUpdateMemories(updates);\n }\n }\n\n /**\n * Improved summarization with error handling and batch processing\n */\n async summarizeAndStore(): Promise<boolean> {\n if (this.recentMessages.length === 0 || this.isProcessing) {\n return false;\n }\n\n this.isProcessing = true;\n this.metrics.summarizations++;\n\n try {\n // Create conversation summary\n const conversationText = this.recentMessages\n .map((msg) => `${msg.role}: ${msg.content}`)\n .join(\"\\n\");\n\n // Extract facts using LLM\n const factsResponse =\n await this.extractFactsFromConversation(conversationText);\n\n if (!Array.isArray(factsResponse) || factsResponse.length === 0) {\n console.warn(\"No facts extracted from conversation\");\n return false;\n }\n\n // Process facts in batches\n await this.processFactsInBatches(factsResponse);\n\n // Clear processed messages\n this.recentMessages = [];\n\n return true;\n } catch (error) {\n console.error(\"Error in summarizeAndStore:\", error);\n this.metrics.errors++;\n return false;\n } finally {\n this.isProcessing = false;\n }\n }\n\n /**\n * Extract facts from conversation using LLM\n */\n private async extractFactsFromConversation(\n conversationText: string,\n ): Promise<ExtractedFact[]> {\n try {\n const { extract: factsResponse } = await writeLanguageResponse({\n agent: \"remember-facts\",\n chat_history: conversationText,\n provider: \"groq\",\n model: \"mixtral-8x7b-32768\",\n timeout: MEMORY_CONFIG.DEFAULT_TIMEOUT,\n });\n\n return Array.isArray(factsResponse) ? factsResponse : [];\n } catch (error) {\n console.error(\"Error extracting facts:\", error);\n return [];\n }\n }\n\n /**\n * Process facts in batches to avoid overwhelming the database\n */\n private async processFactsInBatches(\n factsResponse: ExtractedFact[],\n ): Promise<void> {\n for (let i = 0; i < factsResponse.length; i += this.batchSize) {\n const batch = factsResponse.slice(i, i + this.batchSize);\n\n const storePromises = batch.map(async (fact) => {\n try {\n if (fact && typeof fact === \"object\" && fact.content) {\n return await this.storeFact(\n fact.content,\n fact.importance || 1,\n fact.category || MEMORY_TYPES.CONVERSATION,\n fact.metadata || {},\n );\n } else if (typeof fact === \"string\" && fact.trim()) {\n return await this.storeFact(\n fact.trim(),\n 1,\n MEMORY_TYPES.CONVERSATION,\n );\n }\n } catch (error) {\n console.error(\"Error storing individual fact:\", error);\n return null;\n }\n });\n\n await Promise.allSettled(storePromises);\n\n // Small delay between batches\n if (i + this.batchSize < factsResponse.length) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n }\n }\n\n /**\n * Clear cache utility\n */\n clearCache(): void {\n this.memoryCache.clear();\n }\n\n /**\n * Get memory context with better formatting and relevance\n */\n async getMemoryContext(\n query: string = \"\",\n includeRecent: boolean = true,\n options: MemoryContextOptions = {},\n ): Promise<string> {\n const memories = await this.recallRelevantMemories(\n query,\n options.maxMemories || 8,\n { minImportance: options.minImportance || 0.5 },\n );\n\n if (memories.length === 0 && this.recentMessages.length === 0) {\n return \"\";\n }\n\n let context = \"\";\n\n // Add relevant memories\n if (memories.length > 0) {\n context += \"What I remember about you:\\n\";\n memories\n .filter((memory) => memory.importance > (options.minImportance || 0.5))\n .forEach((memory) => {\n const importanceIndicator =\n memory.importance >= 8\n ? \"\\u2b50\"\n : memory.importance >= 5\n ? \"\\u2022\"\n : \"-\";\n context += `${importanceIndicator} ${memory.content}\\n`;\n });\n }\n\n // Add recent conversation if requested\n if (includeRecent && this.recentMessages.length > 0) {\n context += context\n ? \"\\nRecent conversation:\\n\"\n : \"Recent conversation:\\n\";\n this.recentMessages.slice(-3).forEach((msg) => {\n const truncatedContent =\n msg.content.length > 100\n ? msg.content.substring(0, 100) + \"...\"\n : msg.content;\n context += `${msg.role}: ${truncatedContent}\\n`;\n });\n }\n\n return context;\n }\n\n /**\n * Get performance metrics\n */\n getMetrics(): MemoryMetrics {\n return {\n ...this.metrics,\n cacheSize: this.memoryCache.size,\n recentMessagesCount: this.recentMessages.length,\n isProcessing: this.isProcessing,\n };\n }\n}\n","// @ts-nocheck\n/**\n * Memory Agent\n *\n * Enhanced Memory Agent with:\n * - Rate limiting\n * - Multiple LLM provider support\n * - Health monitoring\n * - Conversation management\n * - Memory analytics\n */\n\nimport { SimpleMemory } from \"./storage/in-memory-storage\";\nimport type { IMemoryStorage } from \"./storage/storage-interface\";\nimport type { MemoryType, MemorySearchOptions } from \"./types\";\nimport { MEMORY_CONFIG, MEMORY_TYPES } from \"./types\";\n\n/**\n * LLM provider interface\n */\ninterface LLMProvider {\n invoke: (prompt: string) => Promise<{ content: string; tokensUsed: number }>;\n}\n\n/**\n * Chat options\n */\ninterface ChatOptions {\n provider?: string;\n apiKey?: string;\n model?: string;\n temperature?: number;\n systemPrompt?: string;\n includeHistory?: boolean;\n maxMemories?: number;\n minImportance?: number;\n}\n\n/**\n * Chat response\n */\ninterface ChatResponse {\n content?: string;\n memoryContext?: string;\n success: boolean;\n tokensUsed?: number;\n responseTime?: number;\n sessionId?: string;\n timestamp: string;\n error?: string;\n}\n\n/**\n * Agent analytics\n */\ninterface AgentAnalytics {\n totalMessages: number;\n totalTokens: number;\n averageResponseTime: number;\n errorCount: number;\n sessionStartTime: number;\n}\n\n/**\n * Rate limit configuration\n */\ninterface RateLimitConfig {\n requests: number;\n windowMs: number;\n}\n\n/**\n * Agent options\n */\nexport interface MemoryAgentOptions {\n memoryOptions?: any;\n defaultProvider?: string;\n defaultApiKey?: string;\n defaultModel?: string;\n rateLimit?: RateLimitConfig;\n providers?: Record<string, (apiKey: string, model: string, temperature: number) => LLMProvider>;\n}\n\nexport class MemoryAgent {\n private memory: SimpleMemory;\n private defaultProvider: string;\n private defaultApiKey?: string;\n private defaultModel?: string;\n private rateLimiter: Map<string, number[]>;\n private rateLimitConfig: RateLimitConfig;\n private providers: Record<string, (apiKey: string, model: string, temperature: number) => LLMProvider>;\n private sessionId: string;\n private conversationHistory: Array<{ role: string; content: string }>;\n private analytics: AgentAnalytics;\n private userId: string;\n\n /**\n * Initialize memory agent\n */\n constructor(userId: string, storage: IMemoryStorage, options: MemoryAgentOptions = {}) {\n if (!userId || !storage) {\n throw new Error(\"userId and storage are required parameters\");\n }\n\n this.userId = userId;\n this.memory = new SimpleMemory(userId, storage, options.memoryOptions || {});\n this.defaultProvider = options.defaultProvider || \"groq\";\n this.defaultApiKey = options.defaultApiKey;\n this.defaultModel = options.defaultModel;\n\n // Rate limiting\n this.rateLimiter = new Map();\n this.rateLimitConfig = {\n ...MEMORY_CONFIG.DEFAULT_RATE_LIMIT,\n ...options.rateLimit,\n };\n\n // LLM providers\n this.providers = options.providers || this.getDefaultProviders();\n\n // Session management\n this.sessionId = this.generateSessionId();\n this.conversationHistory = [];\n\n // Analytics\n this.analytics = {\n totalMessages: 0,\n totalTokens: 0,\n averageResponseTime: 0,\n errorCount: 0,\n sessionStartTime: Date.now(),\n };\n }\n\n /**\n * Get default LLM providers\n */\n private getDefaultProviders(): Record<string, (apiKey: string, model: string, temperature: number) => LLMProvider> {\n return {\n groq: (apiKey, model, temperature) => ({\n invoke: async (prompt) => {\n // Implementation would go here\n return { content: \"Default response\", tokensUsed: 0 };\n },\n }),\n openai: (apiKey, model, temperature) => ({\n invoke: async (prompt) => {\n // Implementation would go here\n return { content: \"Default response\", tokensUsed: 0 };\n },\n }),\n };\n }\n\n /**\n * Generate unique session ID\n */\n private generateSessionId(): string {\n return `${this.userId}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n\n /**\n * Rate limiting check with sliding window\n */\n private checkRateLimit(key: string, maxRequests?: number, windowMs?: number): boolean {\n const config = {\n maxRequests: maxRequests || this.rateLimitConfig.requests,\n windowMs: windowMs || this.rateLimitConfig.windowMs,\n };\n\n const now = Date.now();\n const requests = this.rateLimiter.get(key) || [];\n\n // Remove old requests outside the window\n const validRequests = requests.filter(\n (time) => now - time < config.windowMs,\n );\n\n if (validRequests.length >= config.maxRequests) {\n return false;\n }\n\n validRequests.push(now);\n this.rateLimiter.set(key, validRequests);\n return true;\n }\n\n /**\n * Main chat method with comprehensive error handling\n */\n async chat(message: string, options: ChatOptions = {}): Promise<ChatResponse> {\n const startTime = Date.now();\n\n // Input validation\n if (!message || typeof message !== \"string\" || message.trim().length === 0) {\n return {\n error: \"Message cannot be empty\",\n success: false,\n timestamp: new Date().toISOString(),\n };\n }\n\n // Rate limiting\n const rateLimitKey = `chat-${this.userId}`;\n if (!this.checkRateLimit(rateLimitKey)) {\n return {\n error: \"Rate limit exceeded. Please try again later.\",\n success: false,\n timestamp: new Date().toISOString(),\n };\n }\n\n try {\n // Add user message to memory\n this.memory.addMessage(\"user\", message, {\n sessionId: this.sessionId,\n timestamp: Date.now(),\n });\n\n // Get memory context\n const memoryContext = await this.memory.getMemoryContext(message, true, {\n maxMemories: options.maxMemories || 8,\n minImportance: options.minImportance || 0.5,\n });\n\n // Build enhanced prompt\n const prompt = this.buildPrompt(message, memoryContext, options);\n\n // Generate response\n const response = await this.generateResponse(prompt, options);\n\n if (!response || !response.content) {\n throw new Error(\"Invalid response from LLM\");\n }\n\n // Add response to memory\n this.memory.addMessage(\"assistant\", response.content, {\n sessionId: this.sessionId,\n tokensUsed: response.tokensUsed,\n timestamp: Date.now(),\n });\n\n // Update analytics\n this.updateAnalytics(response.tokensUsed, Date.now() - startTime);\n\n return {\n content: response.content,\n memoryContext: memoryContext,\n success: true,\n tokensUsed: response.tokensUsed || 0,\n responseTime: Date.now() - startTime,\n sessionId: this.sessionId,\n timestamp: new Date().toISOString(),\n };\n } catch (error) {\n console.error(\"Chat error:\", error);\n this.analytics.errorCount++;\n\n return {\n error: error.message || \"An unexpected error occurred\",\n success: false,\n timestamp: new Date().toISOString(),\n };\n }\n }\n\n /**\n * Generate LLM response with timeout and error handling\n */\n private async generateResponse(prompt: string, options: ChatOptions): Promise<{ content: string; tokensUsed: number }> {\n const provider = options.provider || this.defaultProvider;\n const apiKey = options.apiKey || this.defaultApiKey;\n const model = options.model || this.defaultModel;\n const temperature = options.temperature || 0.7;\n\n if (!this.providers || !this.providers[provider]) {\n throw new Error(`Provider ${provider} not available`);\n }\n\n const llm = this.providers[provider](apiKey || \"\", model || \"\", temperature);\n\n // Add timeout to LLM call\n const timeoutPromise = new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(\"LLM request timeout\")),\n MEMORY_CONFIG.DEFAULT_TIMEOUT,\n ),\n );\n\n return await Promise.race([llm.invoke(prompt), timeoutPromise]);\n }\n\n /**\n * Build enhanced prompt with context\n */\n private buildPrompt(message: string, memoryContext: string, options: ChatOptions): string {\n let prompt = \"\";\n\n // Add system context if provided\n if (options.systemPrompt) {\n prompt += `${options.systemPrompt}\\n\\n`;\n }\n\n // Add memory context\n if (memoryContext) {\n prompt += `${memoryContext}\\n\\n`;\n }\n\n // Add conversation history if requested\n if (options.includeHistory && this.conversationHistory.length > 0) {\n prompt += \"Recent conversation history:\\n\";\n this.conversationHistory.slice(-5).forEach((msg) => {\n prompt += `${msg.role}: ${msg.content}\\n`;\n });\n prompt += \"\\n\";\n }\n\n prompt += `User: ${message}\\n\\nAssistant:`;\n\n return prompt;\n }\n\n /**\n * Update analytics\n */\n private updateAnalytics(tokensUsed: number, responseTime: number): void {\n this.analytics.totalMessages++;\n this.analytics.totalTokens += tokensUsed || 0;\n this.analytics.averageResponseTime =\n (this.analytics.averageResponseTime * (this.analytics.totalMessages - 1) +\n responseTime) /\n this.analytics.totalMessages;\n }\n\n /**\n * Remember a fact manually\n */\n async remember(\n fact: string,\n importance: number = 1,\n category: MemoryType = MEMORY_TYPES.MANUAL,\n metadata: Record<string, any> = {},\n ): Promise<string> {\n try {\n return await this.memory.storeFact(fact, importance, category, {\n ...metadata,\n source: \"manual\",\n timestamp: Date.now(),\n });\n } catch (error) {\n console.error(\"Error remembering fact:\", error);\n throw error;\n }\n }\n\n /**\n * Get memories with filtering\n */\n async getMemories(query: string = \"\", limit: number = 10, options: MemorySearchOptions = {}): Promise<any[]> {\n return await this.memory.recallRelevantMemories(query, limit, options);\n }\n\n /**\n * Force store summary of current conversation\n */\n async forceStoreSummary(): Promise<boolean> {\n return await this.memory.summarizeAndStore();\n }\n\n /**\n * Health check for the agent\n */\n async healthCheck(): Promise<any> {\n try {\n const memoryMetrics = this.memory.getMetrics();\n const rateLimitStatus = this.checkRateLimit(\"health-check\", 1, 1000);\n\n return {\n status: \"healthy\",\n memory: memoryMetrics,\n rateLimit: rateLimitStatus,\n analytics: this.analytics,\n sessionId: this.sessionId,\n uptime: Date.now() - this.analytics.sessionStartTime,\n timestamp: new Date().toISOString(),\n };\n } catch (error) {\n return {\n status: \"unhealthy\",\n error: error.message,\n timestamp: new Date().toISOString(),\n };\n }\n }\n\n /**\n * Get analytics and performance metrics\n */\n getAnalytics(): any {\n return {\n ...this.analytics,\n memory: this.memory.getMetrics(),\n sessionId: this.sessionId,\n uptime: Date.now() - this.analytics.sessionStartTime,\n };\n }\n\n /**\n * Reset session and clear conversation history\n */\n resetSession(): void {\n this.sessionId = this.generateSessionId();\n this.conversationHistory = [];\n this.analytics.sessionStartTime = Date.now();\n }\n}\n","/**\n * Drizzle Storage Adapter\n *\n * Implementation of IMemoryStorage using Drizzle ORM\n */\n\nimport { sql, eq, and, desc, or, like } from \"drizzle-orm\";\nimport type { IMemoryStorage } from \"./storage-interface\";\nimport type {\n MemoryRecord,\n MemoryType,\n MemorySearchOptions,\n MemoryUpdate,\n} from \"../types\";\n\n/**\n * The Drizzle table passed to {@link DrizzleMemoryStorage} must expose these\n * columns (see {@link createMemorySchema} for the expected shape).\n */\nexport interface MemoryTable {\n id: any;\n user_id: any;\n memory_type: any;\n content: any;\n importance: any;\n access_count: any;\n metadata: any;\n created_at: any;\n updated_at: any;\n}\n\n/**\n * Drizzle-based storage adapter.\n *\n * Pass the Drizzle database instance and the memory table object defined in\n * your schema (not a table-name string) so queries reference real columns:\n *\n * ```ts\n * import { sqliteTable, text, integer, real } from \"drizzle-orm/sqlite-core\";\n * const userMemories = sqliteTable(\"user_memories\", { ... });\n * const storage = new DrizzleMemoryStorage(db, userMemories);\n * ```\n */\nexport class DrizzleMemoryStorage implements IMemoryStorage {\n private db: any;\n private table: MemoryTable & Record<string, any>;\n\n constructor(db: any, table: MemoryTable & Record<string, any>) {\n this.db = db;\n this.table = table;\n }\n\n /**\n * Insert a new memory record\n */\n async insertMemory(\n userId: string,\n memoryType: MemoryType,\n content: string,\n importance: number,\n metadata?: Record<string, any>,\n ): Promise<string> {\n const result = await this.db\n .insert(this.table)\n .values({\n user_id: userId,\n memory_type: memoryType,\n content: content,\n importance: importance,\n access_count: 0,\n metadata: metadata || {},\n created_at: new Date(),\n updated_at: new Date(),\n })\n .returning({ id: this.table.id });\n\n return result[0]?.id;\n }\n\n /**\n * Find memories by user ID and optional filters\n */\n async findMemories(\n userId: string,\n query?: string,\n limit: number = 10,\n options: MemorySearchOptions = {},\n ): Promise<MemoryRecord[]> {\n const conditions = [eq(this.table.user_id, userId)];\n\n if (query && query.trim()) {\n conditions.push(like(this.table.content, `%${query}%`));\n }\n\n if (options.memoryType) {\n conditions.push(eq(this.table.memory_type, options.memoryType));\n }\n\n const results = await this.db\n .select({\n id: this.table.id,\n user_id: this.table.user_id,\n memory_type: this.table.memory_type,\n content: this.table.content,\n importance: this.table.importance,\n access_count: this.table.access_count,\n metadata: this.table.metadata,\n created_at: this.table.created_at,\n updated_at: this.table.updated_at,\n })\n .from(this.table)\n .where(and(...conditions))\n .orderBy(\n desc(this.table.importance),\n desc(this.table.access_count),\n desc(this.table.updated_at),\n )\n .limit(Math.min(limit, 50)); // Cap at 50 for performance\n\n return results as MemoryRecord[];\n }\n\n /**\n * Find similar memories based on content\n */\n async findSimilarMemories(\n userId: string,\n content: string,\n limit: number = 5,\n ): Promise<MemoryRecord[]> {\n // Simple similarity check using keywords\n const words = content\n .toLowerCase()\n .split(/\\s+/)\n .filter((w) => w.length > 2);\n const searchTerms = words.slice(0, 3); // Use first 3 words\n\n if (searchTerms.length === 0) {\n return [];\n }\n\n const conditions = searchTerms.map((term) =>\n like(this.table.content, `%${term}%`),\n );\n\n const results = await this.db\n .select()\n .from(this.table)\n .where(and(eq(this.table.user_id, userId), or(...conditions)))\n .orderBy(desc(this.table.importance), desc(this.table.updated_at))\n .limit(limit);\n\n return results as MemoryRecord[];\n }\n\n /**\n * Update a memory record\n */\n async updateMemory(id: string, updates: MemoryUpdate): Promise<void> {\n const updateData: any = {};\n\n if (updates.importance !== undefined) {\n updateData.importance = updates.importance;\n }\n\n if (updates.access_count !== undefined) {\n if (typeof updates.access_count === \"object\" && updates.access_count.increment) {\n updateData.access_count = sql`${this.table.access_count} + ${updates.access_count.increment}`;\n } else {\n updateData.access_count = updates.access_count;\n }\n }\n\n if (updates.updated_at !== undefined) {\n updateData.updated_at = updates.updated_at;\n }\n\n if (updates.metadata !== undefined) {\n updateData.metadata = updates.metadata;\n }\n\n await this.db.update(this.table).set(updateData).where(eq(this.table.id, id));\n }\n\n /**\n * Delete a memory record\n */\n async deleteMemory(id: string): Promise<void> {\n await this.db.delete(this.table).where(eq(this.table.id, id));\n }\n\n /**\n * Get memory by ID\n */\n async getMemoryById(id: string): Promise<MemoryRecord | null> {\n const results = await this.db\n .select()\n .from(this.table)\n .where(eq(this.table.id, id))\n .limit(1);\n\n return (results[0] as MemoryRecord) || null;\n }\n\n /**\n * Batch update memories\n */\n async batchUpdateMemories(\n updates: Array<{ id: string; updates: MemoryUpdate }>,\n ): Promise<void> {\n const promises = updates.map(({ id, updates: updateData }) =>\n this.updateMemory(id, updateData),\n );\n await Promise.allSettled(promises);\n }\n}\n\n/**\n * Database schema for memory system\n * This is kept here for reference but should be managed by your migration system\n */\nexport function createMemorySchema(db: any) {\n return {\n user_memories: {\n id: \"uuid\",\n user_id: \"string\",\n memory_type: \"string\",\n content: \"text\",\n importance: \"number\",\n access_count: \"number\",\n metadata: \"jsonb\",\n created_at: \"timestamp\",\n updated_at: \"timestamp\",\n },\n };\n}\n","/**\n * @fileoverview Mastra Memory Integration for Cloudflare Workers\n *\n * Integrates Mastra's memory system with Cloudflare Workers environment.\n * Provides persistent conversation memory using D1, KV, or Durable Objects.\n *\n * Features:\n * - Multi-storage backend support (D1, KV, Durable Objects)\n * - Thread-based conversation management\n * - Resource scoping for multi-user scenarios\n * - Cloudflare Workers optimized (edge-ready)\n * - Compatible with existing MemoryAgent architecture\n *\n * @see https://docs.mastra.ai/core/memory\n */\n\nimport { Mastra } from '@mastra/core';\nimport { Agent } from '@mastra/core/agent';\nimport type { D1Database, KVNamespace } from '@cloudflare/workers-types';\nimport type { IMemoryStorage } from './storage/storage-interface';\nimport type { MemoryRecord, MemoryType, MemorySearchOptions, MemoryUpdate } from './types';\n\n/**\n * Cloudflare Workers environment bindings\n */\nexport interface CloudflareEnv {\n DB?: D1Database;\n KV?: KVNamespace;\n OPENAI_API_KEY?: string;\n ANTHROPIC_API_KEY?: string;\n GROQ_API_KEY?: string;\n}\n\n/**\n * Storage backend types for Mastra memory\n */\nexport type MastraStorageBackend = 'memory' | 'd1' | 'kv';\n\n/**\n * Configuration for Mastra memory integration\n */\nexport interface MastraMemoryConfig {\n /** Storage backend (memory, d1, or kv) */\n storage: MastraStorageBackend;\n /** Cloudflare environment bindings */\n env?: CloudflareEnv;\n /** D1 table name (for d1 storage) */\n tableName?: string;\n /** KV key prefix (for kv storage) */\n kvPrefix?: string;\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * D1-based storage adapter for Mastra Memory\n * Implements IMemoryStorage using Cloudflare D1\n */\nexport class MastraD1MemoryStorage implements IMemoryStorage {\n private db: D1Database;\n private tableName: string;\n\n constructor(db: D1Database, tableName: string = 'mastra_memories') {\n this.db = db;\n this.tableName = tableName;\n }\n\n /**\n * Initialize D1 schema for Mastra memory\n */\n async initSchema(): Promise<void> {\n await this.db.exec(`\n CREATE TABLE IF NOT EXISTS ${this.tableName} (\n id TEXT PRIMARY KEY,\n user_id TEXT NOT NULL,\n thread_id TEXT NOT NULL,\n resource_id TEXT,\n memory_type TEXT NOT NULL,\n content TEXT NOT NULL,\n importance REAL DEFAULT 1.0,\n access_count INTEGER DEFAULT 0,\n metadata TEXT,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL\n );\n\n CREATE INDEX IF NOT EXISTS idx_user_thread ON ${this.tableName}(user_id, thread_id);\n CREATE INDEX IF NOT EXISTS idx_resource ON ${this.tableName}(resource_id);\n CREATE INDEX IF NOT EXISTS idx_importance ON ${this.tableName}(importance DESC);\n `);\n }\n\n async insertMemory(\n userId: string,\n memoryType: MemoryType,\n content: string,\n importance: number,\n metadata?: Record<string, any>\n ): Promise<string> {\n const id = crypto.randomUUID();\n const now = Date.now();\n\n await this.db\n .prepare(\n `INSERT INTO ${this.tableName}\n (id, user_id, thread_id, resource_id, memory_type, content, importance, metadata, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`\n )\n .bind(\n id,\n userId,\n metadata?.thread_id || 'default',\n metadata?.resource_id || null,\n memoryType,\n content,\n importance,\n JSON.stringify(metadata || {}),\n now,\n now\n )\n .run();\n\n return id;\n }\n\n async findMemories(\n userId: string,\n query?: string,\n limit: number = 10,\n options: MemorySearchOptions = {}\n ): Promise<MemoryRecord[]> {\n let sql = `SELECT * FROM ${this.tableName} WHERE user_id = ?`;\n const params: any[] = [userId];\n\n if (options.memoryType) {\n sql += ' AND memory_type = ?';\n params.push(options.memoryType);\n }\n\n if (query) {\n sql += ' AND content LIKE ?';\n params.push(`%${query}%`);\n }\n\n if (options.minImportance !== undefined) {\n sql += ' AND importance >= ?';\n params.push(options.minImportance);\n }\n\n sql += ' ORDER BY importance DESC, updated_at DESC LIMIT ?';\n params.push(limit);\n\n const result = await this.db.prepare(sql).bind(...params).all();\n\n return (result.results || []).map((row: any) => ({\n id: row.id,\n user_id: row.user_id,\n memory_type: row.memory_type,\n content: row.content,\n importance: row.importance,\n access_count: row.access_count,\n metadata: JSON.parse(row.metadata || '{}'),\n created_at: new Date(row.created_at),\n updated_at: new Date(row.updated_at),\n }));\n }\n\n async findSimilarMemories(\n userId: string,\n content: string,\n limit: number = 5\n ): Promise<MemoryRecord[]> {\n // Simple keyword-based similarity for D1 (no vector search)\n const words = content.toLowerCase().split(/\\s+/).filter(w => w.length > 2);\n const searchTerms = words.slice(0, 3);\n\n if (searchTerms.length === 0) return [];\n\n const likeConditions = searchTerms.map(() => 'content LIKE ?').join(' OR ');\n const params = [userId, ...searchTerms.map(term => `%${term}%`), limit];\n\n const result = await this.db\n .prepare(\n `SELECT * FROM ${this.tableName}\n WHERE user_id = ? AND (${likeConditions})\n ORDER BY importance DESC, updated_at DESC\n LIMIT ?`\n )\n .bind(...params)\n .all();\n\n return (result.results || []).map((row: any) => ({\n id: row.id,\n user_id: row.user_id,\n memory_type: row.memory_type,\n content: row.content,\n importance: row.importance,\n access_count: row.access_count,\n metadata: JSON.parse(row.metadata || '{}'),\n created_at: new Date(row.created_at),\n updated_at: new Date(row.updated_at),\n }));\n }\n\n async updateMemory(id: string, updates: MemoryUpdate): Promise<void> {\n const fields: string[] = [];\n const params: any[] = [];\n\n if (updates.importance !== undefined) {\n fields.push('importance = ?');\n params.push(updates.importance);\n }\n\n if (updates.access_count !== undefined) {\n if (typeof updates.access_count === 'object' && updates.access_count.increment) {\n fields.push('access_count = access_count + ?');\n params.push(updates.access_count.increment);\n } else {\n fields.push('access_count = ?');\n params.push(updates.access_count);\n }\n }\n\n if (updates.metadata !== undefined) {\n fields.push('metadata = ?');\n params.push(JSON.stringify(updates.metadata));\n }\n\n fields.push('updated_at = ?');\n params.push(Date.now());\n params.push(id);\n\n if (fields.length > 0) {\n await this.db\n .prepare(`UPDATE ${this.tableName} SET ${fields.join(', ')} WHERE id = ?`)\n .bind(...params)\n .run();\n }\n }\n\n async deleteMemory(id: string): Promise<void> {\n await this.db.prepare(`DELETE FROM ${this.tableName} WHERE id = ?`).bind(id).run();\n }\n\n async getMemoryById(id: string): Promise<MemoryRecord | null> {\n const result = await this.db\n .prepare(`SELECT * FROM ${this.tableName} WHERE id = ?`)\n .bind(id)\n .first();\n\n if (!result) return null;\n\n return {\n id: result.id as string,\n user_id: result.user_id as string,\n memory_type: result.memory_type as MemoryType,\n content: result.content as string,\n importance: result.importance as number,\n access_count: result.access_count as number,\n metadata: JSON.parse((result.metadata as string) || '{}'),\n created_at: new Date(result.created_at as number),\n updated_at: new Date(result.updated_at as number),\n };\n }\n\n async batchUpdateMemories(updates: Array<{ id: string; updates: MemoryUpdate }>): Promise<void> {\n for (const { id, updates: updateData } of updates) {\n await this.updateMemory(id, updateData);\n }\n }\n}\n\n/**\n * KV-based storage adapter for Mastra Memory\n * Uses Cloudflare KV for simple key-value storage\n */\nexport class MastraKVMemoryStorage implements IMemoryStorage {\n private kv: KVNamespace;\n private prefix: string;\n\n constructor(kv: KVNamespace, prefix: string = 'mastra:memory:') {\n this.kv = kv;\n this.prefix = prefix;\n }\n\n private getUserKey(userId: string): string {\n return `${this.prefix}user:${userId}`;\n }\n\n private getMemoryKey(id: string): string {\n return `${this.prefix}memory:${id}`;\n }\n\n async insertMemory(\n userId: string,\n memoryType: MemoryType,\n content: string,\n importance: number,\n metadata?: Record<string, any>\n ): Promise<string> {\n const id = crypto.randomUUID();\n const now = Date.now();\n\n const memory: MemoryRecord = {\n id,\n user_id: userId,\n memory_type: memoryType,\n content,\n importance,\n access_count: 0,\n metadata: metadata || {},\n created_at: new Date(now),\n updated_at: new Date(now),\n };\n\n // Store memory\n await this.kv.put(this.getMemoryKey(id), JSON.stringify(memory));\n\n // Update user's memory list\n const userKey = this.getUserKey(userId);\n const userMemories = await this.kv.get(userKey, 'json') as string[] || [];\n userMemories.push(id);\n await this.kv.put(userKey, JSON.stringify(userMemories));\n\n return id;\n }\n\n async findMemories(\n userId: string,\n query?: string,\n limit: number = 10,\n options: MemorySearchOptions = {}\n ): Promise<MemoryRecord[]> {\n const userKey = this.getUserKey(userId);\n const memoryIds = await this.kv.get(userKey, 'json') as string[] || [];\n\n const memories = await Promise.all(\n memoryIds.map(id => this.getMemoryById(id))\n );\n\n let filtered = memories.filter((m): m is MemoryRecord => m !== null);\n\n if (query) {\n filtered = filtered.filter(m =>\n m.content.toLowerCase().includes(query.toLowerCase())\n );\n }\n\n if (options.memoryType) {\n filtered = filtered.filter(m => m.memory_type === options.memoryType);\n }\n\n if (options.minImportance !== undefined) {\n filtered = filtered.filter(m => m.importance >= options.minImportance!);\n }\n\n return filtered\n .sort((a, b) => b.importance - a.importance || b.updated_at.getTime() - a.updated_at.getTime())\n .slice(0, limit);\n }\n\n async findSimilarMemories(\n userId: string,\n content: string,\n limit: number = 5\n ): Promise<MemoryRecord[]> {\n const words = content.toLowerCase().split(/\\s+/).filter(w => w.length > 2);\n const searchTerms = words.slice(0, 3);\n\n if (searchTerms.length === 0) return [];\n\n const memories = await this.findMemories(userId, '', 50);\n\n return memories\n .filter(m =>\n searchTerms.some(term => m.content.toLowerCase().includes(term))\n )\n .slice(0, limit);\n }\n\n async updateMemory(id: string, updates: MemoryUpdate): Promise<void> {\n const memory = await this.getMemoryById(id);\n if (!memory) return;\n\n if (updates.importance !== undefined) {\n memory.importance = updates.importance;\n }\n\n if (updates.access_count !== undefined) {\n if (typeof updates.access_count === 'object') {\n memory.access_count += updates.access_count.increment ?? 0;\n } else {\n memory.access_count = updates.access_count;\n }\n }\n\n if (updates.metadata !== undefined) {\n memory.metadata = { ...memory.metadata, ...updates.metadata };\n }\n\n memory.updated_at = new Date();\n\n await this.kv.put(this.getMemoryKey(id), JSON.stringify(memory));\n }\n\n async deleteMemory(id: string): Promise<void> {\n const memory = await this.getMemoryById(id);\n if (!memory) return;\n\n await this.kv.delete(this.getMemoryKey(id));\n\n // Remove from user's list\n const userKey = this.getUserKey(memory.user_id);\n const userMemories = await this.kv.get(userKey, 'json') as string[] || [];\n const filtered = userMemories.filter(mId => mId !== id);\n await this.kv.put(userKey, JSON.stringify(filtered));\n }\n\n async getMemoryById(id: string): Promise<MemoryRecord | null> {\n const data = await this.kv.get(this.getMemoryKey(id), 'json') as any;\n if (!data) return null;\n\n return {\n ...data,\n created_at: new Date(data.created_at),\n updated_at: new Date(data.updated_at),\n };\n }\n\n async batchUpdateMemories(updates: Array<{ id: string; updates: MemoryUpdate }>): Promise<void> {\n await Promise.all(\n updates.map(({ id, updates: updateData }) => this.updateMemory(id, updateData))\n );\n }\n}\n\n/**\n * Mastra Memory Manager for Cloudflare Workers\n * Wraps Mastra's memory system with Cloudflare-compatible storage\n */\nexport class MastraMemoryManager {\n private mastra: Mastra | null = null;\n private storage: IMemoryStorage;\n private config: MastraMemoryConfig;\n\n constructor(config: MastraMemoryConfig) {\n this.config = config;\n\n // Initialize storage backend\n if (config.storage === 'd1' && config.env?.DB) {\n this.storage = new MastraD1MemoryStorage(config.env.DB, config.tableName);\n } else if (config.storage === 'kv' && config.env?.KV) {\n this.storage = new MastraKVMemoryStorage(config.env.KV, config.kvPrefix);\n } else {\n throw new Error(`Invalid storage configuration: ${config.storage}`);\n }\n }\n\n /**\n * Initialize Mastra instance with memory\n */\n async initialize(): Promise<Mastra> {\n if (this.mastra) return this.mastra;\n\n // Memory persistence is handled by this manager's own D1/KV storage\n // adapters rather than a Mastra memory backend.\n this.mastra = new Mastra({});\n\n // Initialize D1 schema if needed\n if (this.config.storage === 'd1' && this.storage instanceof MastraD1MemoryStorage) {\n await this.storage.initSchema();\n }\n\n return this.mastra;\n }\n\n /**\n * Get storage instance (for direct access)\n */\n getStorage(): IMemoryStorage {\n return this.storage;\n }\n\n /**\n * Create an agent with memory\n */\n async createAgent(config: {\n id: string;\n name: string;\n instructions: string;\n model: any;\n tools?: Record<string, any>;\n userId: string;\n threadId?: string;\n resourceId?: string;\n }): Promise<Agent> {\n const mastra = await this.initialize();\n\n // Get or create agent with memory\n const agent = new Agent({\n id: config.id,\n name: config.name,\n instructions: config.instructions,\n model: config.model,\n tools: config.tools || {},\n });\n\n // Attach memory context\n (agent as any).memoryContext = {\n userId: config.userId,\n threadId: config.threadId || 'default',\n resourceId: config.resourceId,\n };\n\n return agent;\n }\n\n /**\n * Store a message in memory\n */\n async storeMessage(\n userId: string,\n threadId: string,\n role: 'user' | 'assistant',\n content: string,\n metadata?: Record<string, any>\n ): Promise<string> {\n return await this.storage.insertMemory(\n userId,\n 'conversation',\n content,\n 1.0,\n {\n thread_id: threadId,\n role,\n ...metadata,\n }\n );\n }\n\n /**\n * Recall conversation history\n */\n async recallConversation(\n userId: string,\n threadId: string,\n limit: number = 20\n ): Promise<Array<{ role: 'user' | 'assistant'; content: string; timestamp: Date }>> {\n const memories = await this.storage.findMemories(\n userId,\n undefined,\n limit,\n { memoryType: 'conversation' }\n );\n\n return memories\n .filter(m => m.metadata?.thread_id === threadId)\n .map(m => ({\n role: m.metadata?.role || 'user',\n content: m.content,\n timestamp: m.created_at,\n }))\n .sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());\n }\n\n /**\n * Get relevant context for a query\n */\n async getRelevantContext(\n userId: string,\n query: string,\n limit: number = 5\n ): Promise<string> {\n const memories = await this.storage.findSimilarMemories(userId, query, limit);\n\n if (memories.length === 0) return '';\n\n return memories.map(m => m.content).join('\\n\\n');\n }\n}\n\n/**\n * Quick helper to create Mastra memory manager for Cloudflare Workers\n *\n * @example\n * ```ts\n * const memoryManager = createMastraMemory({\n * storage: 'd1',\n * env: env, // Cloudflare env bindings\n * });\n *\n * const agent = await memoryManager.createAgent({\n * id: 'assistant',\n * name: 'AI Assistant',\n * instructions: 'Help users with their questions',\n * model: openai('gpt-4o'),\n * userId: 'user-123',\n * threadId: 'conversation-1',\n * });\n * ```\n */\nexport function createMastraMemory(config: MastraMemoryConfig): MastraMemoryManager {\n return new MastraMemoryManager(config);\n}\n","/**\n * @fileoverview Specialized tools for AI agents to interact with the QwkSearch API.\n * Provides web search, content extraction, and AI response generation.\n */\n\n// @ts-nocheck\nimport { z } from \"zod\";\nimport * as QwkSearch from 'qwksearch-api-client'; // Update this path to match your QwkSearch module location\n\n// Configuration for QwkSearch API\nconst QWKSEARCH_CONFIG = {\n baseURL: typeof process !== \"undefined\" && process?.env.QWKSEARCH_URL || 'https://app.qwksearch.com/api',\n apiKey: typeof process !== \"undefined\" && process?.env.QWKSEARCH_API_KEY || null,\n};\n\n/**\n * List of tools available for agent usage, including their schemas and implementation.\n */\nexport const AGENT_TOOLS = [\n\n {\n name: \"web_search\",\n description:\n \"Search the web for information on any topic using QwkSearch API. Input: search query string and optional category. Returns relevant search results with titles, descriptions, and URLs from 100+ sources via SearXNG metasearch engine.\",\n schema: z.object({\n query: z.string(),\n category: z.enum([\"general\", \"news\", \"videos\", \"images\", \"science\", \"files\", \"it\"]).optional().default(\"general\"),\n recency: z.enum([\"none\", \"day\", \"week\", \"month\", \"year\"]).optional().default(\"none\"),\n page: z.number().optional().default(1),\n language: z.string().optional().default(\"en-US\"),\n public: z.boolean().optional().default(false),\n timeout: z.number().optional().default(10),\n baseURL: z.string().optional(),\n apiKey: z.string().optional()\n }),\n func: async ({ query, category = \"general\", recency = \"none\", page = 1, language = \"en-US\", public: isPublic = false, timeout = 10, baseURL, apiKey }) => {\n try {\n // Use provided config or fall back to environment/defaults\n const baseUrl = baseURL || QWKSEARCH_CONFIG.baseURL;\n const headers = apiKey || QWKSEARCH_CONFIG.apiKey ? { 'x-api-key': apiKey || QWKSEARCH_CONFIG.apiKey } : undefined;\n\n const result = await QwkSearch.searchWeb({\n query: {\n q: query,\n cat: category,\n recency: recency,\n page: page,\n lang: language,\n public: isPublic,\n timeout: timeout\n },\n baseUrl: baseUrl,\n ...(headers && { headers })\n });\n\n if (!result.data || !result.data.results || result.data.results.length === 0) {\n return `No search results found for \"${query}\". Please try a different search term.`;\n }\n\n let resultText = `Web search results for \"${query}\" (${category} category):\\n\\n`;\n\n result.data.results.forEach((searchResult, index) => {\n resultText += `${index + 1}. ${searchResult.title}\\n`;\n resultText += ` URL: ${searchResult.url}\\n`;\n if (searchResult.domain) {\n resultText += ` Domain: ${searchResult.domain}\\n`;\n }\n if (searchResult.snippet) {\n resultText += ` Description: ${searchResult.snippet}\\n`;\n }\n if (searchResult.engines && searchResult.engines.length > 0) {\n resultText += ` Sources: ${searchResult.engines.join(\", \")}\\n`;\n }\n resultText += `\\n`;\n });\n\n resultText += `Found ${result.data.results.length} results from multiple search engines. This is the complete search information.`;\n\n return resultText;\n } catch (error) {\n return `Unable to perform web search for \"${query}\". Error: ${error.message}`;\n }\n },\n },\n {\n name: \"extract_page\",\n description:\n \"Extract and summarize content from a web page using QwkSearch API. Supports articles, PDFs, and YouTube videos. Uses Mozilla Readability and Postlight Mercury algorithms with 100+ custom adapters for major sites. Input: URL of the page to extract. Returns structured content with citation information.\",\n schema: z.object({\n url: z.string().url(),\n images: z.boolean().optional().default(true),\n links: z.boolean().optional().default(true),\n formatting: z.boolean().optional().default(true),\n absoluteURLs: z.boolean().optional().default(true),\n timeout: z.number().min(1).max(30).optional().default(10),\n baseURL: z.string().optional(),\n apiKey: z.string().optional()\n }),\n func: async ({ url, images = true, links = true, formatting = true, absoluteURLs = true, timeout = 10, baseURL, apiKey }) => {\n try {\n // Use provided config or fall back to environment/defaults\n const baseUrl = baseURL || QWKSEARCH_CONFIG.baseURL;\n const headers = apiKey || QWKSEARCH_CONFIG.apiKey ? { 'x-api-key': apiKey || QWKSEARCH_CONFIG.apiKey } : undefined;\n\n const result = await QwkSearch.extractContent({\n query: {\n url: url,\n images: images,\n links: links,\n formatting: formatting,\n absoluteURLs: absoluteURLs,\n timeout: timeout\n },\n baseUrl: baseUrl,\n ...(headers && { headers })\n });\n\n if (!result.data) {\n return `No content could be extracted from \"${url}\". Please check the URL and try again.`;\n }\n\n const data = result.data;\n\n let resultText = `Content extracted from: ${data.url || url}\\n\\n`;\n\n if (data.title) {\n resultText += `Title: ${data.title}\\n\\n`;\n }\n\n if (data.author) {\n resultText += `Author: ${data.author}\\n`;\n if (data.author_cite) {\n resultText += `Author (Citation Format): ${data.author_cite}\\n`;\n }\n if (data.author_type) {\n resultText += `Author Type: ${data.author_type}\\n`;\n }\n }\n\n if (data.date) {\n resultText += `Publication Date: ${data.date}\\n`;\n }\n\n if (data.source) {\n resultText += `Source: ${data.source}\\n`;\n }\n\n if (data.word_count) {\n resultText += `Word Count: ${data.word_count}\\n`;\n }\n\n if (data.cite) {\n resultText += `\\nCitation (APA Format): ${data.cite}\\n`;\n }\n\n if (data.html) {\n resultText += `\\nContent:\\n${data.html}\\n\\n`;\n }\n\n resultText += `This is the complete page extraction information.`;\n\n return resultText;\n } catch (error) {\n return `Unable to extract content from \"${url}\". Error: ${error.message}`;\n }\n },\n },\n {\n name: \"generate_ai_response\",\n description:\n \"Generate AI language model responses using QwkSearch API with various agent templates. Supports multiple providers (Groq, OpenAI, Anthropic, etc.) and agent types for different tasks like summarization, question answering, and content generation.\",\n schema: z.object({\n provider: z.enum([\"groq\", \"openai\", \"anthropic\", \"together\", \"xai\", \"google\", \"perplexity\", \"cloudflare\"]),\n key: z.string().optional(),\n agent: z.enum([\n \"question\",\n \"summarize-bullets\",\n \"summarize\",\n \"suggest-followups\",\n \"answer-cite-sources\",\n \"query-resolution\",\n \"knowledge-graph-nodes\",\n \"summary-longtext\"\n ]).optional().default(\"question\"),\n model: z.string().optional().default(\"meta-llama/llama-4-maverick-17b-128e-instruct\"),\n temperature: z.number().min(0).max(2).optional().default(0.7),\n html: z.boolean().optional().default(true),\n query: z.string().optional(),\n chat_history: z.string().optional(),\n article: z.string().optional(),\n baseURL: z.string().optional(),\n apiKey: z.string().optional()\n }),\n func: async ({ provider, key, agent = \"question\", model = \"meta-llama/llama-4-maverick-17b-128e-instruct\", temperature = 0.7, html = true, query, chat_history, article, baseURL, apiKey }) => {\n try {\n // Use provided config or fall back to environment/defaults\n const baseUrl = baseURL || QWKSEARCH_CONFIG.baseURL;\n const headers = apiKey || QWKSEARCH_CONFIG.apiKey ? { 'x-api-key': apiKey || QWKSEARCH_CONFIG.apiKey } : undefined;\n\n const requestBody = {\n agent,\n provider,\n model,\n html,\n temperature\n };\n\n if (key) {\n requestBody.key = key;\n }\n\n if (query) {\n requestBody.query = query;\n }\n\n if (chat_history) {\n requestBody.chat_history = chat_history;\n }\n\n if (article) {\n requestBody.article = article;\n }\n\n const result = await QwkSearch.writeLanguage({\n body: requestBody,\n baseUrl: baseUrl,\n ...(headers && { headers })\n });\n\n if (!result.data) {\n return `No response generated. Please check your input parameters and try again.`;\n }\n\n let resultText = `AI Response (${agent} agent, ${provider} provider):\\n\\n`;\n\n if (result.data.content) {\n resultText += result.data.content;\n }\n\n if (result.data.extract) {\n resultText += `\\n\\nStructured Extract:\\n${JSON.stringify(result.data.extract, null, 2)}`;\n }\n\n resultText += `\\n\\nThis is the complete AI-generated response.`;\n\n return resultText;\n } catch (error) {\n return `Unable to generate AI response. Error: ${error.message}`;\n }\n },\n },\n {\n name: \"render_page_with_javascript\",\n description:\n \"Render a web page with JavaScript execution using Cloudflare Browser Rendering. Use this for JavaScript-heavy sites (SPAs, React apps), pages behind bot protection (Cloudflare, reCAPTCHA), or when extract_page fails. Returns fully rendered HTML with JavaScript executed. Slower but more complete than extract_page.\",\n schema: z.object({\n url: z.string().url(),\n blockImages: z.boolean().optional().default(true),\n wait: z.number().min(0).max(10000).optional().default(0),\n timeout: z.number().min(1000).max(60000).optional().default(30000),\n waitUntil: z.enum([\"domcontentloaded\", \"load\", \"networkidle0\", \"networkidle2\"]).optional().default(\"networkidle2\"),\n bypassCaptcha: z.boolean().optional().default(true),\n sessionId: z.string().optional().default(\"default\"),\n format: z.enum([\"html\", \"json\"]).optional().default(\"html\"),\n scraperUrl: z.string().optional(),\n scraperApiKey: z.string().optional()\n }),\n func: async ({ url, blockImages = true, wait = 0, timeout = 30000, waitUntil = \"networkidle2\", bypassCaptcha = true, sessionId = \"default\", format = \"html\", scraperUrl, scraperApiKey }) => {\n try {\n const scraperEndpoint = scraperUrl || (typeof process !== \"undefined\" && process?.env?.SCRAPER_URL) || 'https://scraper.qwksearch.workers.dev';\n const apiKey = scraperApiKey || (typeof process !== \"undefined\" && process?.env?.SCRAPER_API_KEY);\n\n const requestUrl = new URL('/api/render', scraperEndpoint);\n\n const body = {\n url,\n blockImages,\n wait,\n timeout,\n waitUntil,\n bypassCaptcha,\n sessionId,\n format\n };\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n if (apiKey) {\n headers['Authorization'] = `Bearer ${apiKey}`;\n }\n\n const response = await fetch(requestUrl.toString(), {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n return `Failed to render page: ${errorText}`;\n }\n\n if (format === 'json') {\n const data = await response.json();\n let resultText = `Page rendered successfully: ${data.url}\\n\\n`;\n if (data.title) {\n resultText += `Title: ${data.title}\\n`;\n }\n resultText += `Load Time: ${data.loadTime}ms\\n`;\n if (data.challengeBypassed) {\n resultText += `Challenge Bypassed: Yes (${data.retryCount} retries)\\n`;\n }\n resultText += `\\nRendered HTML Content:\\n${data.html}\\n\\n`;\n resultText += `This is the complete rendered page content.`;\n return resultText;\n }\n\n const html = await response.text();\n return `Page rendered successfully.\\n\\nHTML Content:\\n${html}`;\n } catch (error) {\n return `Unable to render page \"${url}\". Error: ${error.message}`;\n }\n },\n },\n];","/**\n * @module agent-toolkit/utils/outputParser\n * @description Parsers that extract values from XML-tagged sections of LLM\n * output (e.g. `<links>...</links>`, `<question>...</question>`).\n */\n\nconst LIST_MARKER_REGEX = /^(\\s*(-|\\*|\\d+\\.\\s|\\d+\\)\\s|•)\\s*)+/;\n\ninterface LineListOutputParserArgs {\n key?: string;\n}\n\nexport class LineListOutputParser {\n private key = \"questions\";\n\n constructor(args?: LineListOutputParserArgs) {\n this.key = args?.key ?? this.key;\n }\n\n async parse(text: string): Promise<string[]> {\n text = text.trim() || \"\";\n\n const startKeyIndex = text.indexOf(`<${this.key}>`);\n const endKeyIndex = text.indexOf(`</${this.key}>`);\n\n if (startKeyIndex === -1 || endKeyIndex === -1) {\n return [];\n }\n\n const questionsStartIndex = startKeyIndex + `<${this.key}>`.length;\n const lines = text\n .slice(questionsStartIndex, endKeyIndex)\n .trim()\n .split(\"\\n\")\n .filter((line) => line.trim() !== \"\")\n .map((line) => line.replace(LIST_MARKER_REGEX, \"\"));\n\n return lines;\n }\n}\n\ninterface LineOutputParserArgs {\n key?: string;\n}\n\nexport class LineOutputParser {\n private key = \"questions\";\n\n constructor(args?: LineOutputParserArgs) {\n this.key = args?.key ?? this.key;\n }\n\n async parse(text: string): Promise<string | undefined> {\n text = text.trim() || \"\";\n\n const startKeyIndex = text.indexOf(`<${this.key}>`);\n const endKeyIndex = text.indexOf(`</${this.key}>`);\n\n if (startKeyIndex === -1 || endKeyIndex === -1) {\n return undefined;\n }\n\n const questionsStartIndex = startKeyIndex + `<${this.key}>`.length;\n const line = text\n .slice(questionsStartIndex, endKeyIndex)\n .trim()\n .replace(LIST_MARKER_REGEX, \"\");\n\n return line;\n }\n}\n\nexport default LineOutputParser;\n","/**\n * Chat history formatting utilities\n */\n\ntype ChatHistoryMessage = {\n content?: unknown;\n role?: string;\n type?: string;\n};\n\nexport const formatChatHistoryAsString = (history: ChatHistoryMessage[]) => {\n return history\n .map(\n (message) =>\n `${message.role === 'assistant' || message.type === 'ai' ? 'AI' : 'User'}: ${String(message.content ?? '')}`,\n )\n .join('\\n');\n};\n","/**\n * @module research/search/doc-utils\n * @description Document utilities: fallback docs, reranking, and formatting.\n */\nimport type { Document } from \"./document\";\n\nexport interface R2CredentialsInput {\n accountId: string;\n accessKeyId: string;\n secretAccessKey: string;\n bucket: string;\n}\n\nexport function buildFallbackDocs(query: string): Document[] {\n const trimmedQuery = (query || \"\").trim();\n const searchQuery = trimmedQuery.length > 0 ? trimmedQuery : \"web search\";\n const fallbackUrl = `https://www.google.com/search?q=${encodeURIComponent(searchQuery)}`;\n\n return [\n {\n pageContent:\n \"No indexed sources were returned by the configured search providers for this query.\",\n metadata: {\n title: `Search results for: ${searchQuery}`,\n url: fallbackUrl,\n source: \"Google Search\",\n },\n },\n ];\n}\n\nexport function normalizeSourcesOutput(output: unknown, query: string): Document[] {\n if (Array.isArray(output) && output.length > 0) {\n return output as Document[];\n }\n return buildFallbackDocs(query);\n}\n\n/**\n * Resolves an uploaded fileId to its extracted `{ title, content }` payload.\n * Hosts register a loader (e.g. reading the native R2 binding) so the search\n * pipeline does not depend on filesystem or credential-based access.\n */\nexport type UploadFileLoader = (\n fileId: string,\n) => Promise<{ title: string; content: string } | null>;\n\nlet uploadFileLoader: UploadFileLoader | null = null;\n\n/**\n * Registers the loader used by {@link rerankDocs} to resolve uploaded\n * fileIds to extracted content. The registered loader takes precedence over\n * the S3-credentials fallback.\n */\nexport function registerUploadFileLoader(loader: UploadFileLoader): void {\n uploadFileLoader = loader;\n}\n\nasync function downloadExtractedContent(fileId: string, r2Credentials: R2CredentialsInput): Promise<{ title: string; content: string } | null> {\n try {\n const { manageStorage } = await import(\"manage-storage\");\n const config = {\n provider: \"cloudflare\" as const,\n BUCKET_NAME: r2Credentials.bucket,\n ACCESS_KEY_ID: r2Credentials.accessKeyId,\n SECRET_ACCESS_KEY: r2Credentials.secretAccessKey,\n BUCKET_URL: `https://${r2Credentials.accountId}.r2.cloudflarestorage.com`,\n };\n const extractedKey = `${fileId}-extracted.json`;\n const data = await manageStorage(\"download\", { ...config, key: extractedKey });\n const parsed = JSON.parse(data);\n return { title: parsed.title || \"Uploaded Document\", content: parsed.content || \"\" };\n } catch (error) {\n console.error(`[rerankDocs] Failed to download extracted content for fileId ${fileId}:`, error);\n return null;\n }\n}\n\nexport async function rerankDocs(\n query: string,\n docs: Document[],\n fileIds: string[],\n optimizationMode: \"speed\" | \"balanced\" | \"quality\",\n r2Credentials?: R2CredentialsInput,\n): Promise<Document[]> {\n if (docs.length === 0 && fileIds.length === 0) {\n return docs;\n }\n\n let filesData: { title: string; content: string }[] = [];\n\n if (fileIds.length > 0) {\n const results = await Promise.all(\n fileIds.map(async (fileId) => {\n if (uploadFileLoader) {\n try {\n const loaded = await uploadFileLoader(fileId);\n if (loaded) return loaded;\n } catch (error) {\n console.error(\n `[rerankDocs] Registered upload loader failed for fileId ${fileId}:`,\n error,\n );\n }\n }\n if (r2Credentials) {\n return downloadExtractedContent(fileId, r2Credentials);\n }\n return null;\n }),\n );\n filesData = results.filter((r) => r !== null);\n }\n\n if (query.toLocaleLowerCase() === \"summarize\") {\n return docs.slice(0, 15);\n }\n\n const docsWithContent = docs.filter(\n (doc) => doc.pageContent && doc.pageContent.length > 0,\n );\n\n const fileDocs: Document[] = filesData.map((fileData) => ({\n pageContent: fileData.content,\n metadata: { title: fileData.title, url: \"File\" },\n }));\n\n // Combine file docs with web results, cap at 15\n return [...fileDocs, ...docsWithContent].slice(0, 15);\n}\n\nexport function processDocs(docs: Document[]): string {\n return docs\n .map(\n (_, index) =>\n `${index + 1}. ${docs[index].metadata.title} ${docs[index].pageContent}`,\n )\n .join(\"\\n\");\n}\n","/**\n * @module research/search/link-summarizer\n * @description Groups link documents by URL then summarizes each group with an LLM.\n */\nimport { generateText, type LanguageModel } from \"ai\";\nimport type { Document } from \"./document\";\nimport { buildFallbackDocs } from \"./doc-utils\";\n\nconst SUMMARIZER_PROMPT = `You are a web search summarizer, tasked with summarizing a piece of text retrieved from a web search. Your job is to summarize the\ntext into a detailed, 2-4 paragraph explanation that captures the main ideas and provides a comprehensive answer to the query.\nIf the query is \"summarize\", you should provide a detailed summary of the text. If the query is a specific question, you should answer it in the summary.\n\n- **Journalistic tone**: The summary should sound professional and journalistic, not too casual or vague.\n- **Thorough and detailed**: Ensure that every key point from the text is captured and that the summary directly answers the query.\n- **Not too lengthy, but detailed**: The summary should be informative but not excessively long. Focus on providing detailed information in a concise format.\n\nThe text will be shared inside the \\`text\\` XML tag, and the query inside the \\`query\\` XML tag.\n\n<example>\n1. \\`<text>\nDocker is a set of platform-as-a-service products that use OS-level virtualization to deliver software in packages called containers.\nIt was first released in 2013 and is developed by Docker, Inc. Docker is designed to make it easier to create, deploy, and run applications\nby using containers.\n</text>\n\n<query>\nWhat is Docker and how does it work?\n</query>\n\nResponse:\nDocker is a revolutionary platform-as-a-service product developed by Docker, Inc., that uses container technology to make application\ndeployment more efficient. It allows developers to package their software with all necessary dependencies, making it easier to run in\nany environment. Released in 2013, Docker has transformed the way applications are built, deployed, and managed.\n\\`\n2. \\`<text>\nThe theory of relativity, or simply relativity, encompasses two interrelated theories of Albert Einstein: special relativity and general\nrelativity. However, the word \"relativity\" is sometimes used in reference to Galilean invariance. The term \"theory of relativity\" was based\non the expression \"relative theory\" used by Max Planck in 1906. The theory of relativity usually encompasses two interrelated theories by\nAlbert Einstein: special relativity and general relativity. Special relativity applies to all physical phenomena in the absence of gravity.\nGeneral relativity explains the law of gravitation and its relation to other forces of nature. It applies to the cosmological and astrophysical\nrealm, including astronomy.\n</text>\n\n<query>\nsummarize\n</query>\n\nResponse:\nThe theory of relativity, developed by Albert Einstein, encompasses two main theories: special relativity and general relativity. Special\nrelativity applies to all physical phenomena in the absence of gravity, while general relativity explains the law of gravitation and its\nrelation to other forces of nature. The theory of relativity is based on the concept of \"relative theory,\" as introduced by Max Planck in\n1906. It is a fundamental theory in physics that has revolutionized our understanding of the universe.\n\\`\n</example>\n\nEverything below is the actual data you will be working with. Good luck!\n\n<query>\n{question}\n</query>\n\n<text>\n{content}\n</text>\n\nMake sure to answer the query in the summary.`;\n\n/**\n * Groups fetched link documents by URL (max 10 chunks per URL), then\n * summarizes each group with the LLM in parallel.\n */\nexport async function groupAndSummarizeDocs(\n llm: LanguageModel,\n linkDocs: Document[],\n question: string,\n): Promise<Document[]> {\n // Group chunks by URL, capping at 10 chunks each\n const docGroups: Document[] = [];\n\n for (const doc of linkDocs) {\n const existing = docGroups.find(\n (d) => d.metadata.url === doc.metadata.url && d.metadata.totalDocs < 10,\n );\n\n if (!existing) {\n docGroups.push({ ...doc, metadata: { ...doc.metadata, totalDocs: 1 } });\n } else {\n existing.pageContent += `\\n\\n${doc.pageContent}`;\n existing.metadata.totalDocs += 1;\n }\n }\n\n // Summarize each group in parallel\n const docs: Document[] = [];\n\n await Promise.all(\n docGroups.map(async (doc) => {\n const prompt = SUMMARIZER_PROMPT.replace(\"{question}\", question).replace(\n \"{content}\",\n doc.pageContent,\n );\n const { text } = await generateText({ model: llm, prompt });\n\n docs.push({\n pageContent: text,\n metadata: { title: doc.metadata.title, url: doc.metadata.url },\n });\n }),\n );\n\n return docs.length > 0 ? docs : buildFallbackDocs(question);\n}\n","/**\n * @fileoverview Orchestrator for complex research queries.\n * Manages query expansion, web search execution, and result synthesis using\n * LLMs through the Vercel AI SDK (generateText/streamText).\n */\nimport { generateText, streamText, type LanguageModel } from \"ai\";\nimport { LineOutputParser, LineListOutputParser } from \"../../utils/outputParser\";\nimport type { Document } from \"./document\";\n\n/** Strip HTML tags and decode entities — works in Cloudflare edge runtime */\nfunction htmlToText(html: string): string {\n return html\n .replace(/<(script|style)[^>]*>[\\s\\S]*?<\\/(script|style)>/gi, ' ')\n .replace(/<[^>]+>/g, ' ')\n .replace(/ /g, ' ')\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/&[a-z#][a-z0-9]+;/gi, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\nimport { formatChatHistoryAsString } from \"../../utils\";\nimport EventEmitter from \"events\";\nimport type {\n Config,\n ChatTurnMessage,\n MetaSearchAgentType,\n SearchingEvent,\n} from \"./meta-search-types\";\nimport {\n buildFallbackDocs,\n rerankDocs,\n processDocs,\n normalizeSourcesOutput,\n type R2CredentialsInput,\n} from \"./doc-utils\";\nimport { groupAndSummarizeDocs } from \"./link-summarizer\";\n\nexport type { MetaSearchAgentType, Config } from \"./meta-search-types\";\n\nconst waitWithTimeout = async <T>(\n promise: Promise<T>,\n timeoutMs: number,\n): Promise<T | undefined> => {\n return Promise.race([\n promise,\n new Promise<undefined>((resolve) => {\n setTimeout(() => resolve(undefined), timeoutMs);\n }),\n ]);\n};\n\n/**\n * Substitutes `{key}` placeholders in a prompt template with the provided\n * values, leaving unknown placeholders untouched.\n */\nconst interpolatePrompt = (\n template: string,\n vars: Record<string, string>,\n): string => {\n return Object.entries(vars).reduce(\n (result, [key, value]) => result.split(`{${key}}`).join(value),\n template,\n );\n};\n\nclass MetaSearchAgent implements MetaSearchAgentType {\n private config: Config;\n\n constructor(config: Config) {\n this.config = config;\n }\n\n /**\n * Rephrases the user's query into a standalone search question (and any\n * URLs to summarize), runs the web search, and returns the documents to\n * use as answer context.\n */\n private async retrieveSearchDocs(\n llm: LanguageModel,\n chatHistory: string,\n query: string,\n category: string = \"general\",\n sourceExtractionEnabled = false,\n thinkingTimeLimit = 0,\n emitter?: EventEmitter,\n ): Promise<{ query: string; docs: Document[] }> {\n const { text: retrieverOutput } = await generateText({\n model: llm,\n temperature: 0,\n system: this.config.queryGeneratorPrompt,\n messages: [\n ...this.config.queryGeneratorFewShots.map(([role, content]) => ({\n role,\n content,\n })),\n {\n role: \"user\",\n content: `\n <conversation>\n ${chatHistory}\n </conversation>\n\n <query>\n ${query}\n </query>\n `,\n },\n ],\n });\n\n const linksOutputParser = new LineListOutputParser({ key: \"links\" });\n const questionOutputParser = new LineOutputParser({ key: \"question\" });\n\n const links = await linksOutputParser.parse(retrieverOutput);\n let question =\n (await questionOutputParser.parse(retrieverOutput)) ?? retrieverOutput;\n\n if (question === \"not_needed\") {\n question = \"latest information\";\n }\n\n if (links.length > 0 && this.config.getDocumentsFromLinks) {\n if (question.length === 0) question = \"summarize\";\n\n const linkDocs = await this.config.getDocumentsFromLinks({ links });\n const docs = await groupAndSummarizeDocs(llm, linkDocs, question);\n\n return { query: question, docs };\n }\n\n question = question.replace(/<think>.*?<\\/think>/g, \"\");\n if (!question || question.trim().length === 0) {\n question = \"latest information\";\n }\n\n // Validate and sanitize the query before sending to search APIs\n // If the LLM returned a long response instead of a concise query, extract the first sentence\n // or use the original user query as fallback\n question = question.trim();\n if (question.length > 500 || question.split(/[.!?]\\s+/).length > 5) {\n // Query is too long or contains too many sentences - likely the LLM returned a full response\n console.warn(`[MetaSearchAgent] Query is too long (${question.length} chars), truncating or using fallback`);\n\n // Try to extract first sentence as the query\n const firstSentence = question.split(/[.!?]\\s+/)[0].trim();\n if (firstSentence.length > 0 && firstSentence.length < 200) {\n question = firstSentence;\n } else {\n // Fallback to original user query\n question = query.slice(0, 200);\n }\n }\n\n // Emit \"searching\" progress event so the client can show live status\n const categoryLabel = this.config.activeEngines.length > 0\n ? this.config.activeEngines.slice(0, 2).join(\", \")\n : \"Web\";\n const emitSearching = (status: SearchingEvent[\"status\"], query: string, cat?: string) => {\n emitter?.emit(\"data\", JSON.stringify({\n type: \"searching\",\n data: { query, category: cat ?? categoryLabel, status } satisfies SearchingEvent,\n }));\n };\n\n emitSearching(\"running\", question);\n\n let res: { results: any[]; suggestions: string[] } = { results: [], suggestions: [] };\n\n // If no search functions provided, return empty results\n if (!this.config.searchSearxng && !this.config.searchTavily) {\n res = { results: [], suggestions: [] };\n } else {\n const runSearxng = async () => {\n try {\n const result = await this.config.searchSearxng!(question, {\n language: \"en\",\n engines: this.config.activeEngines,\n categories: [category],\n });\n // Ensure result has the expected structure\n return result && typeof result === 'object' && 'results' in result\n ? result\n : { results: [], suggestions: [] };\n } catch (error) {\n console.error(\"[MetaSearchAgent] SearXNG search failed:\", error);\n return { results: [], suggestions: [] };\n }\n };\n\n const isTavilyConfigured = this.config.isTavilyConfigured?.() ?? false;\n\n if (\n isTavilyConfigured &&\n this.config.activeEngines.length === 0 &&\n category === \"general\"\n ) {\n try {\n const tavilyResult = await this.config.searchTavily!(question, { searchDepth: \"basic\", maxResults: 10 });\n res = tavilyResult && typeof tavilyResult === 'object' && 'results' in tavilyResult\n ? tavilyResult\n : { results: [], suggestions: [] };\n } catch (error) {\n console.error(\"Tavily search failed, falling back to SearXNG:\", error);\n res = this.config.searchSearxng ? await runSearxng() : { results: [], suggestions: [] };\n }\n } else {\n if (isTavilyConfigured && this.config.searchTavily) {\n try {\n res = await Promise.race([\n runSearxng(),\n new Promise<{ results: any[]; suggestions: string[] }>((_, reject) =>\n setTimeout(() => reject(new Error(\"Timeout\")), 10000)\n )\n ]);\n } catch (err: any) {\n if (err.message === \"Timeout\") {\n console.warn(\"[MetaSearchAgent] SearXNG search did not respond in 10 seconds, falling back to Tavily.\");\n try {\n const tavilyResult = await this.config.searchTavily(question, { searchDepth: \"basic\", maxResults: 10 });\n res = tavilyResult && typeof tavilyResult === 'object' && 'results' in tavilyResult\n ? tavilyResult\n : { results: [], suggestions: [] };\n } catch (tavilyErr) {\n console.error(\"[MetaSearchAgent] Tavily fallback also failed, awaiting SearXNG directly:\", tavilyErr);\n res = this.config.searchSearxng ? await runSearxng() : { results: [], suggestions: [] };\n }\n } else {\n console.error(\"[MetaSearchAgent] SearXNG search failed, falling back to Tavily:\", err);\n try {\n const tavilyResult = await this.config.searchTavily(question, { searchDepth: \"basic\", maxResults: 10 });\n res = tavilyResult && typeof tavilyResult === 'object' && 'results' in tavilyResult\n ? tavilyResult\n : { results: [], suggestions: [] };\n } catch (tavilyErr) {\n console.error(\"[MetaSearchAgent] Tavily fallback also failed:\", tavilyErr);\n res = { results: [], suggestions: [] };\n }\n }\n }\n } else {\n res = this.config.searchSearxng ? await runSearxng() : { results: [], suggestions: [] };\n }\n }\n }\n\n let documents: Document[] = (res?.results ?? []).map((result) => ({\n pageContent:\n result.content ||\n (this.config.activeEngines.includes(\"youtube\") ? result.title : \"\"),\n metadata: {\n title: result.title,\n url: result.url,\n source: result.source,\n ...(result.img_src && { img_src: result.img_src }),\n },\n }));\n\n if (documents.length === 0) {\n documents = buildFallbackDocs(question);\n }\n\n emitSearching(\"done\", question);\n\n // Determine extraction budget from thinkingTimeLimit (seconds).\n // thinkingTimeLimit === 0 means unlimited; use server config.\n let scrapeCount: number;\n let perSourceTimeout: number;\n\n if (thinkingTimeLimit > 0) {\n // Spread the time budget across 3 sources\n scrapeCount = 3;\n perSourceTimeout = Math.max(2, Math.floor(thinkingTimeLimit / scrapeCount));\n } else if (sourceExtractionEnabled) {\n scrapeCount = 3;\n // Default to 5 seconds if no config function available\n perSourceTimeout = 5;\n } else {\n scrapeCount = 0;\n perSourceTimeout = 0;\n }\n\n if (scrapeCount > 0) {\n const docsToScrape = documents.slice(0, scrapeCount);\n emitSearching(\"running\", `Extracting top ${docsToScrape.length} sources`, \"extract\");\n\n const extractionTasks = this.config.scrapeURL ? docsToScrape.map(async (doc, idx) => {\n const url = doc.metadata?.url;\n if (!url || !this.config.scrapeURL) return;\n try {\n const result = await waitWithTimeout(\n this.config.scrapeURL(url, { timeout: perSourceTimeout }),\n perSourceTimeout * 1000 + 1500,\n );\n if (typeof result === \"string\" && result.length > 100) {\n const text = htmlToText(result)\n .replace(/(\\r\\n|\\n|\\r)/gm, \" \")\n .replace(/\\s+/g, \" \")\n .trim()\n .slice(0, 5000);\n if (text.length > 100) {\n documents[idx].pageContent = text;\n }\n }\n } catch {\n // Keep original snippet on scraping failure or timeout\n }\n }) : [];\n\n await Promise.allSettled(extractionTasks);\n emitSearching(\"done\", `Extracting top ${docsToScrape.length} sources`, \"extract\");\n }\n\n return { query: question, docs: documents };\n }\n\n /**\n * Runs the full search-and-answer pipeline, emitting \"sources\",\n * \"response\", \"searching\", \"end\", and \"error\" events on the emitter.\n */\n private async runPipeline(\n emitter: EventEmitter,\n message: string,\n history: ChatTurnMessage[],\n llm: LanguageModel,\n optimizationMode: \"speed\" | \"balanced\" | \"quality\",\n fileIds: string[],\n systemInstructions: string,\n category: string,\n sourceExtractionEnabled: boolean,\n thinkingTimeLimit: number,\n ): Promise<void> {\n try {\n let docs: Document[] | null = null;\n let query = message;\n\n if (this.config.searchWeb) {\n const result = await this.retrieveSearchDocs(\n llm,\n formatChatHistoryAsString(history),\n message,\n category,\n sourceExtractionEnabled,\n thinkingTimeLimit,\n emitter,\n );\n query = result.query;\n docs = result.docs;\n }\n\n const r2Credentials: R2CredentialsInput | undefined = process.env.R2_ACCOUNT_ID\n ? {\n accountId: process.env.R2_ACCOUNT_ID,\n accessKeyId: process.env.R2_ACCESS_KEY_ID || \"\",\n secretAccessKey: process.env.R2_SECRET_ACCESS_KEY || \"\",\n bucket: process.env.R2_UPLOADS_BUCKET || \"qwksearch-uploads\",\n }\n : undefined;\n\n const sortedDocs = await rerankDocs(\n query,\n docs ?? [],\n fileIds,\n optimizationMode,\n r2Credentials,\n );\n\n const sources = normalizeSourcesOutput(sortedDocs, message);\n console.log(\"[MetaSearchAgent] emitting sources:\", sources.length);\n emitter.emit(\"data\", JSON.stringify({ type: \"sources\", data: sources }));\n\n const systemPrompt = interpolatePrompt(this.config.responsePrompt, {\n systemInstructions,\n context: processDocs(sortedDocs),\n date: new Date().toISOString(),\n });\n\n const result = streamText({\n model: llm,\n temperature: 0.7,\n system: systemPrompt,\n messages: [...history, { role: \"user\", content: message }],\n });\n\n let responseChunkCount = 0;\n for await (const chunk of result.textStream) {\n responseChunkCount += 1;\n emitter.emit(\"data\", JSON.stringify({ type: \"response\", data: chunk }));\n }\n console.log(\"[MetaSearchAgent] response stream ended, chunks:\", responseChunkCount);\n\n if (responseChunkCount === 0) {\n const fallbackUrls = sources\n .map((doc) => doc.metadata?.url)\n .filter((url): url is string => typeof url === \"string\")\n .slice(0, 5);\n\n const fallbackMessage = [\n \"I couldn't generate a full answer, but I ran a web search and found these source URLs:\",\n ...fallbackUrls.map((url) => `- ${url}`),\n ].join(\"\\n\");\n\n emitter.emit(\"data\", JSON.stringify({ type: \"response\", data: fallbackMessage }));\n }\n\n emitter.emit(\"end\");\n } catch (err) {\n const errMessage = err instanceof Error ? err.message : String(err);\n console.error(\"[MetaSearchAgent] caught error from AI SDK stream:\", errMessage, err);\n let userMessage = errMessage;\n if (errMessage.includes(\"404\") || errMessage.toLowerCase().includes(\"not found\")) {\n userMessage =\n \"The selected AI model was not found at the provider. Please go to Settings → Model Providers and select a different model.\";\n } else if (errMessage.includes(\"410\")) {\n userMessage =\n \"The selected AI model is no longer available (deprecated by the provider). Please go to Settings → Model Providers and select a different model.\";\n } else if (errMessage.includes(\"401\") || errMessage.includes(\"authentication\")) {\n userMessage =\n \"Authentication failed with the AI provider. Please check your API key in Settings.\";\n } else if (errMessage.includes(\"429\") || errMessage.includes(\"rate limit\")) {\n userMessage =\n \"Rate limit reached for the AI provider. Please wait a moment and try again.\";\n }\n emitter.emit(\"error\", JSON.stringify({ data: userMessage }));\n }\n }\n\n async searchAndAnswer(\n message: string,\n history: ChatTurnMessage[],\n llm: LanguageModel,\n optimizationMode: \"speed\" | \"balanced\" | \"quality\",\n fileIds: string[],\n systemInstructions: string,\n category: string = \"general\",\n sourceExtractionEnabled = false,\n thinkingTimeLimit = 0,\n ) {\n const emitter = new EventEmitter();\n\n // Start on the next macrotask so callers can attach their event\n // listeners before the first \"sources\"/\"response\" event can fire.\n setTimeout(() => {\n this.runPipeline(\n emitter,\n message,\n history,\n llm,\n optimizationMode,\n fileIds,\n systemInstructions,\n category,\n sourceExtractionEnabled,\n thinkingTimeLimit,\n );\n }, 0);\n\n return emitter;\n }\n}\n\nexport default MetaSearchAgent;\n","/**\n * @module research/search/index\n * @description Research library module.\n *\n * Note: To use these search handlers, you need to provide search functions\n * (searchSearxng, searchTavily, etc.) from extract-webpage package.\n * See extract-webpage/src/search/index.ts for an example.\n */\nimport MetaSearchAgent from \"./metaSearchAgent\";\nimport {\n webSearchRetrieverPrompt,\n webSearchResponsePrompt,\n webSearchRetrieverFewShots,\n writingAssistantPrompt,\n} from \"write-language\";\nimport type { Config } from \"./meta-search-types\";\n\nconst prompts = {\n webSearchRetrieverPrompt,\n webSearchResponsePrompt,\n webSearchRetrieverFewShots,\n writingAssistantPrompt,\n};\n\n/**\n * Creates search handler instances with provided search functions.\n * Pass in search functions from extract-webpage to enable web search.\n */\nexport const createSearchHandlers = (searchFunctions?: Partial<Config>) => ({\n webSearch: new MetaSearchAgent({\n activeEngines: [],\n queryGeneratorPrompt: prompts.webSearchRetrieverPrompt,\n responsePrompt: prompts.webSearchResponsePrompt,\n queryGeneratorFewShots: prompts.webSearchRetrieverFewShots,\n rerank: true,\n rerankThreshold: 0.3,\n searchWeb: true,\n ...searchFunctions,\n }),\n academicSearch: new MetaSearchAgent({\n activeEngines: [\"arxiv\", \"google scholar\", \"pubmed\"],\n queryGeneratorPrompt: prompts.webSearchRetrieverPrompt,\n responsePrompt: prompts.webSearchResponsePrompt,\n queryGeneratorFewShots: prompts.webSearchRetrieverFewShots,\n rerank: true,\n rerankThreshold: 0,\n searchWeb: true,\n ...searchFunctions,\n }),\n writingAssistant: new MetaSearchAgent({\n activeEngines: [],\n queryGeneratorPrompt: \"\",\n queryGeneratorFewShots: [],\n responsePrompt: prompts.writingAssistantPrompt,\n rerank: true,\n rerankThreshold: 0,\n searchWeb: true,\n ...searchFunctions,\n }),\n wolframAlphaSearch: new MetaSearchAgent({\n activeEngines: [\"wolframalpha\"],\n queryGeneratorPrompt: prompts.webSearchRetrieverPrompt,\n responsePrompt: prompts.webSearchResponsePrompt,\n queryGeneratorFewShots: prompts.webSearchRetrieverFewShots,\n rerank: false,\n rerankThreshold: 0,\n searchWeb: true,\n ...searchFunctions,\n }),\n youtubeSearch: new MetaSearchAgent({\n activeEngines: [\"youtube\"],\n queryGeneratorPrompt: prompts.webSearchRetrieverPrompt,\n responsePrompt: prompts.webSearchResponsePrompt,\n queryGeneratorFewShots: prompts.webSearchRetrieverFewShots,\n rerank: true,\n rerankThreshold: 0.3,\n searchWeb: true,\n ...searchFunctions,\n }),\n redditSearch: new MetaSearchAgent({\n activeEngines: [\"reddit\"],\n queryGeneratorPrompt: prompts.webSearchRetrieverPrompt,\n responsePrompt: prompts.webSearchResponsePrompt,\n queryGeneratorFewShots: prompts.webSearchRetrieverFewShots,\n rerank: true,\n rerankThreshold: 0.3,\n searchWeb: true,\n ...searchFunctions,\n }),\n});\n\n/**\n * Default search handlers without search functions.\n * These will not perform actual web searches unless search functions are added to the Config.\n * @deprecated Use createSearchHandlers() with search functions instead\n */\nexport const searchHandlers = createSearchHandlers();\n","/**\n * @module research/chains/suggestionGeneratorAgent\n * @description Generates follow-up question suggestions from a conversation\n * using the Vercel AI SDK.\n */\nimport { generateText, type LanguageModel } from \"ai\";\nimport { LineListOutputParser } from \"../../utils/outputParser\";\nimport { formatChatHistoryAsString } from \"../../utils\";\nimport type { ChatTurnMessage } from \"./meta-search-types\";\n\nconst createSuggestionGeneratorPrompt = (maxQuestions: number = 4) => `\nYou are an AI suggestion generator for an AI powered search engine. You will be given a conversation below. You need to generate ${maxQuestions} suggestions based on the conversation. The suggestion should be relevant to the conversation that can be used by the user to ask the chat model for more information.\nYou need to make sure the suggestions are relevant to the conversation and are helpful to the user. Keep a note that the user might use these suggestions to ask a chat model for more information.\nMake sure the suggestions are medium in length and are informative and relevant to the conversation.\n\nProvide these suggestions separated by newlines between the XML tags <suggestions> and </suggestions>. For example:\n\n<suggestions>\nTell me more about SpaceX and their recent projects\nWhat is the latest news on SpaceX?\nWho is the CEO of SpaceX?\n</suggestions>\n\nConversation:\n{chat_history}\n`;\n\ntype SuggestionGeneratorInput = {\n chat_history: ChatTurnMessage[];\n maxQuestions?: number;\n};\n\nconst outputParser = new LineListOutputParser({\n key: \"suggestions\",\n});\n\nconst generateSuggestions = async (\n input: SuggestionGeneratorInput,\n llm: LanguageModel,\n): Promise<string[]> => {\n const maxQuestions = input.maxQuestions ?? 4;\n const prompt = createSuggestionGeneratorPrompt(maxQuestions).replace(\n \"{chat_history}\",\n formatChatHistoryAsString(input.chat_history),\n );\n\n const { text } = await generateText({\n model: llm,\n temperature: 0,\n prompt,\n });\n\n return outputParser.parse(text);\n};\n\nexport default generateSuggestions;\n","/**\n * @module research/search/document\n * @description Minimal document shape shared across the search pipeline.\n * A document is a chunk of page content plus citation metadata (title, url, source, etc.).\n */\n\nexport interface Document<\n Metadata extends Record<string, any> = Record<string, any>,\n> {\n pageContent: string;\n metadata: Metadata;\n}\n\n/**\n * Splits text into overlapping chunks on whitespace boundaries.\n * Default chunkSize 1000, chunkOverlap 200.\n */\nexport function splitTextIntoChunks(\n text: string,\n chunkSize = 1000,\n chunkOverlap = 200,\n): string[] {\n const trimmed = (text || \"\").trim();\n if (trimmed.length <= chunkSize) {\n return trimmed.length > 0 ? [trimmed] : [];\n }\n\n const chunks: string[] = [];\n let start = 0;\n\n while (start < trimmed.length) {\n let end = Math.min(start + chunkSize, trimmed.length);\n\n // Break on the last whitespace inside the window so words stay intact\n if (end < trimmed.length) {\n const lastSpace = trimmed.lastIndexOf(\" \", end);\n if (lastSpace > start) end = lastSpace;\n }\n\n chunks.push(trimmed.slice(start, end).trim());\n\n if (end >= trimmed.length) break;\n start = Math.max(end - chunkOverlap, start + 1);\n }\n\n return chunks.filter((chunk) => chunk.length > 0);\n}\n","/**\n * @module research/models/providers/index\n * @description Research library module.\n *\n * This file provides metadata about providers without importing them directly,\n * to avoid circular dependency issues with the config system.\n */\nimport { ModelProviderUISection } from \"../types\";\n\n/**\n * Gets provider UI configuration without triggering circular dependencies.\n * This function uses static metadata instead of importing provider classes.\n */\nexport const getModelProvidersUIConfigSection =\n (): ModelProviderUISection[] => {\n // Import statically defined metadata instead of loading the providers\n // This breaks the circular dependency\n return [\n {\n key: \"openai\",\n name: \"OpenAI\",\n fields: getOpenAIConfigFields(),\n },\n {\n key: \"anthropic\",\n name: \"Anthropic\",\n fields: getAnthropicConfigFields(),\n },\n {\n key: \"gemini\",\n name: \"Google Gemini\",\n fields: getGeminiConfigFields(),\n },\n {\n key: \"groq\",\n name: \"Groq\",\n fields: getGroqConfigFields(),\n },\n {\n key: \"deepseek\",\n name: \"DeepSeek\",\n fields: getDeepSeekConfigFields(),\n },\n {\n key: \"nvidia\",\n name: \"NVIDIA\",\n fields: getNvidiaConfigFields(),\n },\n {\n key: \"openrouter\",\n name: \"OpenRouter\",\n fields: getOpenRouterConfigFields(),\n },\n ];\n };\n\n// Static config field definitions to avoid loading provider classes\n// These match the providerConfigFields in each provider file\nfunction getOpenAIConfigFields() {\n return [\n {\n type: \"password\" as const,\n name: \"API Key\",\n key: \"apiKey\",\n description: \"Your OpenAI API key\",\n required: true,\n placeholder: \"OpenAI API Key\",\n env: \"OPENAI_API_KEY\",\n scope: \"server\" as const,\n },\n {\n type: \"string\" as const,\n name: \"Base URL\",\n key: \"baseURL\",\n description: \"The base URL for the OpenAI API\",\n required: true,\n placeholder: \"OpenAI Base URL\",\n default: \"https://api.openai.com/v1\",\n env: \"OPENAI_BASE_URL\",\n scope: \"server\" as const,\n },\n ];\n}\n\n\nfunction getAnthropicConfigFields() {\n return [\n {\n type: \"password\" as const,\n name: \"API Key\",\n key: \"apiKey\",\n description: \"Your Anthropic API key\",\n required: true,\n placeholder: \"Anthropic API Key\",\n env: \"ANTHROPIC_API_KEY\",\n scope: \"server\" as const,\n },\n ];\n}\n\nfunction getGeminiConfigFields() {\n return [\n {\n type: \"password\" as const,\n name: \"API Key\",\n key: \"apiKey\",\n description: \"Your Google Gemini API key\",\n required: true,\n placeholder: \"Google Gemini API Key\",\n env: \"GEMINI_API_KEY\",\n scope: \"server\" as const,\n },\n ];\n}\n\nfunction getGroqConfigFields() {\n return [\n {\n type: \"password\" as const,\n name: \"API Key\",\n key: \"apiKey\",\n description: \"Your Groq API key. Free tier includes fast inference on Llama and Mixtral models - get yours at console.groq.com\",\n required: true,\n placeholder: \"gsk_...\",\n env: \"GROQ_API_KEY\",\n scope: \"server\" as const,\n },\n ];\n}\n\nfunction getDeepSeekConfigFields() {\n return [\n {\n type: \"password\" as const,\n name: \"API Key\",\n key: \"apiKey\",\n description: \"Your DeepSeek API key\",\n required: true,\n placeholder: \"DeepSeek API Key\",\n env: \"DEEPSEEK_API_KEY\",\n scope: \"server\" as const,\n },\n ];\n}\n\nfunction getNvidiaConfigFields() {\n return [\n {\n type: \"password\" as const,\n name: \"API Key\",\n key: \"apiKey\",\n description: \"Your NVIDIA API key. Free tier includes access to Nemotron, Llama, and other models - get yours at build.nvidia.com\",\n required: true,\n placeholder: \"nvapi-...\",\n env: \"NVIDIA_API_KEY\",\n scope: \"server\" as const,\n },\n {\n type: \"string\" as const,\n name: \"Base URL\",\n key: \"baseURL\",\n description: \"The base URL for NVIDIA's OpenAI-compatible API\",\n required: true,\n placeholder: \"https://integrate.api.nvidia.com/v1\",\n default: \"https://integrate.api.nvidia.com/v1\",\n env: \"NVIDIA_BASE_URL\",\n scope: \"server\" as const,\n },\n ];\n}\n\nfunction getOpenRouterConfigFields() {\n return [\n {\n type: \"password\" as const,\n name: \"API Key\",\n key: \"apiKey\",\n description: \"Your OpenRouter API key. Get one free at openrouter.ai - includes free access to Llama 3.3 70B, Nemotron, and other models.\",\n required: true,\n placeholder: \"sk-or-v1-...\",\n env: \"OPENROUTER_API_KEY\",\n scope: \"server\" as const,\n },\n {\n type: \"string\" as const,\n name: \"Base URL\",\n key: \"baseURL\",\n description: \"The base URL for OpenRouter's OpenAI-compatible API\",\n required: true,\n placeholder: \"https://openrouter.ai/api/v1\",\n default: \"https://openrouter.ai/api/v1\",\n env: \"OPENROUTER_BASE_URL\",\n scope: \"server\" as const,\n },\n ];\n}\n","/**\n * Runtime env-var accessor.\n * Supports both local development (process.env) and Cloudflare Workers\n * (cloudflare:workers virtual module) via dynamic import.\n */\nexport function getEnv(key: string): string | undefined {\n // Try Cloudflare Workers context first (production)\n try {\n // @ts-ignore - cloudflare:workers is a virtual module provided by @cloudflare/vite-plugin\n const cfWorkers = require(\"cloudflare:workers\");\n return cfWorkers.env?.[key];\n } catch {\n // Fallback to process.env for local development\n return process.env[key];\n }\n}\n","/**\n * List of default models for the chat providers and a list of models\n * @property {string} provider - The provider name\n * @property {string} docs - The documentation URL for the model\n * @property {string} api_key - The API key url for the model\n * @property {string} default - The default model for the chat provider\n * @property {Object[]} models - The list of models available for the chat provider\n * @category Generate\n */\nexport const LANGUAGE_MODELS = [\n {\n \"provider\": \"NVIDIA\",\n \"docs\": \"https://docs.api.nvidia.com/nim/reference/llm-apis\",\n \"api_key\": \"https://build.nvidia.com/settings/api-keys\",\n \"default\": \"nvidia/llama-3.1-nemotron-70b-instruct\",\n \"models\": [\n {\n \"name\": \"Llama 3.1 Nemotron 70B Instruct\",\n \"id\": \"nvidia/llama-3.1-nemotron-70b-instruct\",\n \"contextLength\": 131_072,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Nemotron 3 Super 120B\",\n \"id\": \"nvidia/nemotron-3-super-120b-a12b\",\n \"contextLength\": 1_000_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Nemotron-4 340B\",\n \"id\": \"nvidia/nemotron-4-340b\",\n \"contextLength\": 131_072,\n \"free\": false,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Llama 3.3 70B Instruct\",\n \"id\": \"meta/llama-3.3-70b-instruct\",\n \"contextLength\": 131_072,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Llama 3.1 405B Instruct\",\n \"id\": \"meta/llama-3.1-405b-instruct\",\n \"contextLength\": 131_072,\n \"free\": false,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Llama 3.1 8B Instruct\",\n \"id\": \"meta/llama-3.1-8b-instruct\",\n \"contextLength\": 131_072,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Gemma 4 31B IT\",\n \"id\": \"google/gemma-4-31b-it\",\n \"contextLength\": 131_072,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Mistral Large 2\",\n \"id\": \"mistralai/mistral-large-2\",\n \"contextLength\": 131_072,\n \"free\": false,\n \"type\": \"text-generation\"\n }\n ]\n},\n {\n provider: \"Cloudflare\",\n docs: \"https://developers.cloudflare.com/workers-ai/\",\n api_key: \"https://dash.cloudflare.com/profile/api-tokens\",\n default: \"llama-4-scout-17b-16e-instruct\",\n models: [\n {\n name: \"Llama 4 Scout 17B 16E Instruct\",\n id: \"llama-4-scout-17b-16e-instruct\",\n contextLength: 128000,\n },\n {\n name: \"Llama 3.3 70B Instruct FP8 Fast\",\n id: \"llama-3.3-70b-instruct-fp8-fast\",\n contextLength: 128000,\n },\n {\n name: \"Llama 3.1 8B Instruct Fast\",\n id: \"llama-3.1-8b-instruct-fast\",\n contextLength: 128000,\n },\n {\n name: \"Gemma 3 12B IT\",\n id: \"gemma-3-12b-it\",\n contextLength: 128000,\n },\n {\n name: \"Mistral Small 3.1 24B Instruct\",\n id: \"mistral-small-3.1-24b-instruct\",\n contextLength: 128000,\n },\n {\n name: \"QwQ 32B\",\n id: \"qwq-32b\",\n contextLength: 32768,\n },\n {\n name: \"Qwen2.5 Coder 32B Instruct\",\n id: \"qwen2.5-coder-32b-instruct\",\n contextLength: 32768,\n },\n {\n name: \"Llama Guard 3 8B\",\n id: \"llama-guard-3-8b\",\n contextLength: 8192,\n },\n {\n name: \"DeepSeek R1 Distill Qwen 32B\",\n id: \"deepseek-r1-distill-qwen-32b\",\n contextLength: 32768,\n },\n {\n name: \"Llama 3.2 1B Instruct\",\n id: \"llama-3.2-1b-instruct\",\n contextLength: 131072,\n },\n {\n name: \"Llama 3.2 3B Instruct\",\n id: \"llama-3.2-3b-instruct\",\n contextLength: 131072,\n },\n {\n name: \"Llama 3.2 11B Vision Instruct\",\n id: \"llama-3.2-11b-vision-instruct\",\n contextLength: 131072,\n },\n {\n name: \"Llama 3.1 8B Instruct AWQ\",\n id: \"llama-3.1-8b-instruct-awq\",\n contextLength: 128000,\n },\n {\n name: \"Llama 3.1 8B Instruct FP8\",\n id: \"llama-3.1-8b-instruct-fp8\",\n contextLength: 128000,\n },\n {\n name: \"MeloTTS\",\n id: \"melotts\",\n contextLength: 1024,\n },\n {\n name: \"Llama 3.1 8B Instruct\",\n id: \"llama-3.1-8b-instruct\",\n contextLength: 128000,\n },\n {\n name: \"Meta Llama 3 8B Instruct\",\n id: \"meta-llama-3-8b-instruct\",\n contextLength: 8192,\n },\n {\n name: \"Whisper Large V3 Turbo\",\n id: \"whisper-large-v3-turbo\",\n contextLength: 448000,\n },\n {\n name: \"Llama 3 8B Instruct AWQ\",\n id: \"llama-3-8b-instruct-awq\",\n contextLength: 8192,\n },\n {\n name: \"LLaVA 1.5 7B HF\",\n id: \"llava-1.5-7b-hf\",\n contextLength: 4096,\n },\n {\n name: \"Una Cybertron 7B V2 BF16\",\n id: \"una-cybertron-7b-v2-bf16\",\n contextLength: 32768,\n },\n {\n name: \"Whisper Tiny EN\",\n id: \"whisper-tiny-en\",\n contextLength: 448000,\n },\n {\n name: \"Llama 3 8B Instruct\",\n id: \"llama-3-8b-instruct\",\n contextLength: 8192,\n },\n {\n name: \"Mistral 7B Instruct v0.2\",\n id: \"mistral-7b-instruct-v0.2\",\n contextLength: 32768,\n },\n {\n name: \"Gemma 7B IT LoRA\",\n id: \"gemma-7b-it-lora\",\n contextLength: 8192,\n },\n {\n name: \"Gemma 2B IT LoRA\",\n id: \"gemma-2b-it-lora\",\n contextLength: 8192,\n },\n {\n name: \"Llama 2 7B Chat HF LoRA\",\n id: \"llama-2-7b-chat-hf-lora\",\n contextLength: 4096,\n },\n {\n name: \"Gemma 7B IT\",\n id: \"gemma-7b-it\",\n contextLength: 8192,\n },\n {\n name: \"Starling LM 7B Beta\",\n id: \"starling-lm-7b-beta\",\n contextLength: 8192,\n },\n {\n name: \"Hermes 2 Pro Mistral 7B\",\n id: \"hermes-2-pro-mistral-7b\",\n contextLength: 32768,\n },\n {\n name: \"Mistral 7B Instruct v0.2 LoRA\",\n id: \"mistral-7b-instruct-v0.2-lora\",\n contextLength: 32768,\n },\n {\n name: \"Qwen1.5 1.8B Chat\",\n id: \"qwen1.5-1.8b-chat\",\n contextLength: 32768,\n },\n {\n name: \"UForm Gen2 Qwen 500M\",\n id: \"uform-gen2-qwen-500m\",\n contextLength: 2048,\n },\n {\n name: \"BART Large CNN\",\n id: \"bart-large-cnn\",\n contextLength: 1024,\n },\n {\n name: \"Phi-2\",\n id: \"phi-2\",\n contextLength: 2048,\n },\n {\n name: \"TinyLlama 1.1B Chat v1.0\",\n id: \"tinyllama-1.1b-chat-v1.0\",\n contextLength: 2048,\n },\n {\n name: \"Qwen1.5 14B Chat AWQ\",\n id: \"qwen1.5-14b-chat-awq\",\n contextLength: 32768,\n },\n {\n name: \"Qwen1.5 7B Chat AWQ\",\n id: \"qwen1.5-7b-chat-awq\",\n contextLength: 32768,\n },\n {\n name: \"Qwen1.5 0.5B Chat\",\n id: \"qwen1.5-0.5b-chat\",\n contextLength: 32768,\n },\n {\n name: \"DiscoLM German 7B v1 AWQ\",\n id: \"discolm-german-7b-v1-awq\",\n contextLength: 32768,\n },\n {\n name: \"Falcon 7B Instruct\",\n id: \"falcon-7b-instruct\",\n contextLength: 2048,\n },\n {\n name: \"OpenChat 3.5 0106\",\n id: \"openchat-3.5-0106\",\n contextLength: 8192,\n },\n {\n name: \"SQLCoder 7B 2\",\n id: \"sqlcoder-7b-2\",\n contextLength: 16384,\n },\n {\n name: \"DeepSeek Math 7B Instruct\",\n id: \"deepseek-math-7b-instruct\",\n contextLength: 4096,\n },\n {\n name: \"DETR ResNet-50\",\n id: \"detr-resnet-50\",\n contextLength: 1024,\n },\n {\n name: \"Stable Diffusion XL Lightning\",\n id: \"stable-diffusion-xl-lightning\",\n contextLength: 77,\n },\n {\n name: \"DreamShaper 8 LCM\",\n id: \"dreamshaper-8-lcm\",\n contextLength: 77,\n },\n {\n name: \"Stable Diffusion v1.5 Img2Img\",\n id: \"stable-diffusion-v1-5-img2img\",\n contextLength: 77,\n },\n {\n name: \"Stable Diffusion v1.5 Inpainting\",\n id: \"stable-diffusion-v1-5-inpainting\",\n contextLength: 77,\n },\n {\n name: \"DeepSeek Coder 6.7B Instruct AWQ\",\n id: \"deepseek-coder-6.7b-instruct-awq\",\n contextLength: 16384,\n },\n {\n name: \"DeepSeek Coder 6.7B Base AWQ\",\n id: \"deepseek-coder-6.7b-base-awq\",\n contextLength: 16384,\n },\n {\n name: \"LlamaGuard 7B AWQ\",\n id: \"llamaguard-7b-awq\",\n contextLength: 4096,\n },\n {\n name: \"Neural Chat 7B v3.1 AWQ\",\n id: \"neural-chat-7b-v3-1-awq\",\n contextLength: 8192,\n },\n {\n name: \"OpenHermes 2.5 Mistral 7B AWQ\",\n id: \"openhermes-2.5-mistral-7b-awq\",\n contextLength: 8192,\n },\n {\n name: \"Llama 2 13B Chat AWQ\",\n id: \"llama-2-13b-chat-awq\",\n contextLength: 4096,\n },\n {\n name: \"Mistral 7B Instruct v0.1 AWQ\",\n id: \"mistral-7b-instruct-v0.1-awq\",\n contextLength: 8192,\n },\n {\n name: \"Zephyr 7B Beta AWQ\",\n id: \"zephyr-7b-beta-awq\",\n contextLength: 8192,\n },\n {\n name: \"Stable Diffusion XL Base 1.0\",\n id: \"stable-diffusion-xl-base-1.0\",\n contextLength: 77,\n },\n {\n name: \"BGE Large EN v1.5\",\n id: \"bge-large-en-v1.5\",\n contextLength: 512,\n },\n {\n name: \"BGE Small EN v1.5\",\n id: \"bge-small-en-v1.5\",\n contextLength: 512,\n },\n {\n name: \"Llama 2 7B Chat FP16\",\n id: \"llama-2-7b-chat-fp16\",\n contextLength: 4096,\n },\n {\n name: \"Mistral 7B Instruct v0.1\",\n id: \"mistral-7b-instruct-v0.1\",\n contextLength: 8192,\n },\n {\n name: \"BGE Base EN v1.5\",\n id: \"bge-base-en-v1.5\",\n contextLength: 512,\n },\n {\n name: \"DistilBERT SST-2 Int8\",\n id: \"distilbert-sst-2-int8\",\n contextLength: 512,\n },\n {\n name: \"Llama 2 7B Chat Int8\",\n id: \"llama-2-7b-chat-int8\",\n contextLength: 4096,\n },\n {\n name: \"M2M100 1.2B\",\n id: \"m2m100-1.2b\",\n contextLength: 1024,\n },\n {\n name: \"ResNet-50\",\n id: \"resnet-50\",\n contextLength: 224,\n },\n {\n name: \"Whisper\",\n id: \"whisper\",\n contextLength: 448000,\n },\n {\n name: \"Llama 3.1 70B Instruct\",\n id: \"llama-3.1-70b-instruct\",\n contextLength: 128000,\n },\n ],\n },\n {\n provider: \"Perplexity\",\n docs: \"https://docs.perplexity.ai/models/model-cards\",\n api_key: \"https://www.perplexity.ai/account/api/keys\",\n default: \"sonar\",\n models: [\n {\n name: \"Sonar Pro\",\n id: \"sonar-pro\",\n contextLength: 200000,\n },\n {\n name: \"Sonar\",\n id: \"sonar\",\n contextLength: 128000,\n },\n {\n name: \"Sonar Reasoning Pro\",\n id: \"sonar-reasoning-pro\",\n contextLength: 128000,\n },\n {\n name: \"Sonar Reasoning\",\n id: \"sonar-reasoning\",\n contextLength: 128000,\n },\n {\n name: \"Sonar Deep Research\",\n id: \"sonar-deep-research\",\n contextLength: 128000,\n },\n {\n name: \"Llama 3.1 Sonar Small 128k Online\",\n id: \"llama-3.1-sonar-small-128k-online\",\n contextLength: 127072,\n },\n {\n name: \"Llama 3.1 Sonar Large 128k Online\",\n id: \"llama-3.1-sonar-large-128k-online\",\n contextLength: 127072,\n },\n {\n name: \"Llama 3.1 Sonar Huge 128k Online\",\n id: \"llama-3.1-sonar-huge-128k-online\",\n contextLength: 127072,\n },\n ],\n },\n {\n provider: \"Groq\",\n docs: \"https://console.groq.com/docs/overview\",\n api_key: \"https://console.groq.com/keys\",\n default: \"llama-3.3-70b-versatile\",\n models: [\n {\n name: \"Llama 3.3 70B Versatile (Free)\",\n id: \"llama-3.3-70b-versatile\",\n contextLength: 131072,\n free: true,\n type: \"text-generation\",\n rateLimit: \"300K TPM / 1K RPM = ~432M tokens/day\",\n },\n {\n name: \"Llama 3.1 8B Instant (Free)\",\n id: \"llama-3.1-8b-instant\",\n contextLength: 8192,\n free: true,\n type: \"text-generation\",\n rateLimit: \"250K TPM / 1K RPM = ~360M tokens/day\",\n },\n {\n name: \"Llama 4 Scout 17B (Free)\",\n id: \"meta-llama/llama-4-scout-17b-16e-instruct\",\n contextLength: 131072,\n free: true,\n type: \"text-generation\",\n rateLimit: \"300K TPM / 1K RPM = ~432M tokens/day\",\n },\n {\n name: \"Qwen 3 32B (Free)\",\n id: \"qwen/qwen3-32b\",\n contextLength: 128000,\n free: true,\n type: \"text-generation\",\n rateLimit: \"300K TPM / 1K RPM = ~432M tokens/day\",\n },\n {\n name: \"GPT-OSS 120B (Free)\",\n id: \"openai/gpt-oss-120b\",\n contextLength: 32768,\n free: true,\n type: \"text-generation\",\n rateLimit: \"250K TPM / 1K RPM = ~360M tokens/day\",\n },\n {\n name: \"GPT-OSS 20B (Free)\",\n id: \"openai/gpt-oss-20b\",\n contextLength: 32768,\n free: true,\n type: \"text-generation\",\n rateLimit: \"250K TPM / 1K RPM = ~360M tokens/day\",\n },\n {\n name: \"Groq Compound (Free)\",\n id: \"groq/compound\",\n contextLength: 32768,\n free: true,\n type: \"text-generation\",\n rateLimit: \"200K TPM / 200 RPM = ~288M tokens/day\",\n },\n {\n name: \"Groq Compound Mini (Free)\",\n id: \"groq/compound-mini\",\n contextLength: 32768,\n free: true,\n type: \"text-generation\",\n rateLimit: \"200K TPM / 200 RPM = ~288M tokens/day\",\n },\n {\n name: \"GPT-OSS Safeguard 20B (Free)\",\n id: \"openai/gpt-oss-safeguard-20b\",\n contextLength: 32768,\n free: true,\n type: \"text-generation\",\n rateLimit: \"150K TPM / 1K RPM = ~216M tokens/day\",\n },\n ],\n },\n {\n provider: \"OpenAI\",\n docs: \"https://platform.openai.com/docs/overview\",\n api_key: \"https://platform.openai.com/api-keys\",\n default: \"gpt-4o\",\n models: [\n {\n name: \"GPT-4 Omni\",\n id: \"gpt-4o\",\n contextLength: 128000,\n },\n {\n name: \"GPT-4 Omni Mini\",\n id: \"gpt-4o-mini\",\n contextLength: 128000,\n },\n {\n name: \"GPT-4 Turbo\",\n id: \"gpt-4-turbo\",\n contextLength: 128000,\n },\n {\n name: \"GPT-4\",\n id: \"gpt-4\",\n contextLength: 8192,\n },\n {\n name: \"GPT-3.5 Turbo\",\n id: \"gpt-3.5-turbo\",\n contextLength: 16385,\n },\n ],\n },\n {\n provider: \"Anthropic\",\n docs: \"https://docs.anthropic.com/en/docs/welcome\",\n api_key: \"https://console.anthropic.com/settings/keys\",\n default: \"claude-3-7-sonnet-20250219\",\n models: [\n {\n name: \"Claude 3.7 Sonnet\",\n id: \"claude-3-7-sonnet-20250219\",\n contextLength: 200000,\n },\n {\n name: \"Claude 3.5 Sonnet\",\n id: \"claude-3-5-sonnet-20241022\",\n contextLength: 200000,\n },\n {\n name: \"Claude 3 Opus\",\n id: \"claude-3-opus-20240229\",\n contextLength: 200000,\n },\n {\n name: \"Claude 3 Sonnet\",\n id: \"claude-3-sonnet-20240229\",\n contextLength: 200000,\n },\n {\n name: \"Claude 3 Haiku\",\n id: \"claude-3-haiku-20240307\",\n contextLength: 200000,\n },\n ],\n },\n {\n provider: \"TogetherAI\",\n docs: \"https://docs.together.ai/docs/quickstart\",\n api_key: \"https://api.together.xyz/settings/api-keys\",\n default: \"meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo\",\n models: [\n {\n name: \"Llama 3.1 8B Instruct Turbo\",\n id: \"meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo\",\n contextLength: 131072,\n },\n {\n name: \"Llama 3.1 70B Instruct Turbo\",\n id: \"meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo\",\n contextLength: 131072,\n },\n {\n name: \"Llama 3.1 405B Instruct Turbo\",\n id: \"meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo\",\n contextLength: 130815,\n },\n {\n name: \"Llama 3 8B Instruct Turbo\",\n id: \"meta-llama/Meta-Llama-3-8B-Instruct-Turbo\",\n contextLength: 8192,\n },\n {\n name: \"Llama 3 70B Instruct Turbo\",\n id: \"meta-llama/Meta-Llama-3-70B-Instruct-Turbo\",\n contextLength: 8192,\n },\n {\n name: \"Llama 3.2 3B Instruct Turbo\",\n id: \"meta-llama/Llama-3.2-3B-Instruct-Turbo\",\n contextLength: 131072,\n },\n {\n name: \"Llama 3 8B Instruct Lite\",\n id: \"meta-llama/Meta-Llama-3-8B-Instruct-Lite\",\n contextLength: 8192,\n },\n {\n name: \"Llama 3 70B Instruct Lite\",\n id: \"meta-llama/Meta-Llama-3-70B-Instruct-Lite\",\n contextLength: 8192,\n },\n {\n name: \"Llama 3 8B Instruct Reference\",\n id: \"meta-llama/Llama-3-8b-chat-hf\",\n contextLength: 8192,\n },\n {\n name: \"Llama 3 70B Instruct Reference\",\n id: \"meta-llama/Llama-3-70b-chat-hf\",\n contextLength: 8192,\n },\n {\n name: \"Llama 3.1 Nemotron 70B\",\n id: \"nvidia/Llama-3.1-Nemotron-70B-Instruct-HF\",\n contextLength: 32768,\n },\n {\n name: \"Qwen 2.5 Coder 32B Instruct\",\n id: \"Qwen/Qwen2.5-Coder-32B-Instruct\",\n contextLength: 32769,\n },\n {\n name: \"WizardLM-2 8x22B\",\n id: \"microsoft/WizardLM-2-8x22B\",\n contextLength: 65536,\n },\n {\n name: \"Gemma 2 27B\",\n id: \"google/gemma-2-27b-it\",\n contextLength: 8192,\n },\n {\n name: \"Gemma 2 9B\",\n id: \"google/gemma-2-9b-it\",\n contextLength: 8192,\n },\n {\n name: \"DBRX Instruct\",\n id: \"databricks/dbrx-instruct\",\n contextLength: 32768,\n },\n {\n name: \"DeepSeek LLM Chat (67B)\",\n id: \"deepseek-ai/deepseek-llm-67b-chat\",\n contextLength: 4096,\n },\n {\n name: \"Gemma Instruct (2B)\",\n id: \"google/gemma-2b-it\",\n contextLength: 8192,\n },\n {\n name: \"MythoMax-L2 (13B)\",\n id: \"Gryphe/MythoMax-L2-13b\",\n contextLength: 4096,\n },\n {\n name: \"LLaMA-2 Chat (13B)\",\n id: \"meta-llama/Llama-2-13b-chat-hf\",\n contextLength: 4096,\n },\n {\n name: \"Mistral (7B) Instruct\",\n id: \"mistralai/Mistral-7B-Instruct-v0.1\",\n contextLength: 8192,\n },\n {\n name: \"Mistral (7B) Instruct v0.2\",\n id: \"mistralai/Mistral-7B-Instruct-v0.2\",\n contextLength: 32768,\n },\n {\n name: \"Mistral (7B) Instruct v0.3\",\n id: \"mistralai/Mistral-7B-Instruct-v0.3\",\n contextLength: 32768,\n },\n {\n name: \"Mixtral-8x7B Instruct (46.7B)\",\n id: \"mistralai/Mixtral-8x7B-Instruct-v0.1\",\n contextLength: 32768,\n },\n {\n name: \"Mixtral-8x22B Instruct (141B)\",\n id: \"mistralai/Mixtral-8x22B-Instruct-v0.1\",\n contextLength: 65536,\n },\n {\n name: \"Nous Hermes 2 - Mixtral 8x7B-DPO (46.7B)\",\n id: \"NousResearch/Nous-Hermes-2-Mixtral-8x7B-DPO\",\n contextLength: 32768,\n },\n {\n name: \"Qwen 2.5 7B Instruct Turbo\",\n id: \"Qwen/Qwen2.5-7B-Instruct-Turbo\",\n contextLength: 32768,\n },\n {\n name: \"Qwen 2.5 72B Instruct Turbo\",\n id: \"Qwen/Qwen2.5-72B-Instruct-Turbo\",\n contextLength: 32768,\n },\n {\n name: \"Qwen 2 Instruct (72B)\",\n id: \"Qwen/Qwen2-72B-Instruct\",\n contextLength: 32768,\n },\n {\n name: \"StripedHyena Nous (7B)\",\n id: \"togethercomputer/StripedHyena-Nous-7B\",\n contextLength: 32768,\n },\n {\n name: \"Upstage SOLAR Instruct v1 (11B)\",\n id: \"upstage/SOLAR-10.7B-Instruct-v1.0\",\n contextLength: 4096,\n },\n {\n name: \"Llama 3.2 11B Vision Instruct Turbo (Free)\",\n id: \"meta-llama/Llama-Vision-Free\",\n contextLength: 131072,\n },\n {\n name: \"Llama 3.2 11B Vision Instruct Turbo\",\n id: \"meta-llama/Llama-3.2-11B-Vision-Instruct-Turbo\",\n contextLength: 131072,\n },\n {\n name: \"Llama 3.2 90B Vision Instruct Turbo\",\n id: \"meta-llama/Llama-3.2-90B-Vision-Instruct-Turbo\",\n contextLength: 131072,\n },\n ],\n },\n {\n provider: \"XAI\",\n docs: \"https://docs.x.ai/docs#models\",\n api_key: \"https://console.x.ai/\",\n default: \"grok-beta\",\n models: [\n {\n name: \"Grok\",\n id: \"grok-beta\",\n contextLength: 131072,\n },\n {\n name: \"Grok Vision\",\n id: \"grok-vision-beta\",\n contextLength: 8192,\n },\n ],\n },\n {\n provider: \"Google\",\n docs: \"https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models\",\n api_key:\n \"https://cloud.google.com/vertex-ai/generative-ai/docs/start/express-mode/overview#api-keys\",\n models: [\n {\n name: \"Gemini 2.5 Pro Preview\",\n id: \"gemini-2.5-pro-preview-05-06\",\n contextLength: 1048576,\n },\n {\n name: \"Gemini 2.5 Flash Preview\",\n id: \"gemini-2.5-flash-preview-04-17\",\n contextLength: 1048576,\n },\n {\n name: \"Gemini 2.0 Flash\",\n id: \"gemini-2.0-flash-001\",\n contextLength: 1048576,\n },\n {\n name: \"Gemini 2.0 Flash-Lite\",\n id: \"gemini-2.0-flash-lite-001\",\n contextLength: 1048576,\n },\n {\n name: \"Gemini 2.0 Flash-Live\",\n id: \"gemini-2.0-flash-live-preview-04-09\",\n contextLength: 32768,\n },\n {\n name: \"Imagen 3\",\n id: \"imagen-3.0-generate-002\",\n contextLength: 480,\n },\n {\n name: \"Imagen 3 Fast\",\n id: \"imagen-3.0-fast-generate-001\",\n contextLength: 480,\n },\n {\n name: \"Llama 3.2 90B Vision Instruct Turbo\",\n id: \"meta-llama/Llama-3.2-90B-Vision-Instruct-Turbo\",\n contextLength: 131072,\n },\n {\n name: \"Llama 3.3 70B\",\n id: \"meta-llama/Llama-3.3-70B\",\n contextLength: 131072,\n },\n {\n name: \"Gemma 3\",\n id: \"gemma-3\",\n contextLength: 131072,\n },\n {\n name: \"Gemma 2\",\n id: \"gemma-2\",\n contextLength: 131072,\n },\n {\n name: \"Gemma\",\n id: \"gemma\",\n contextLength: 131072,\n },\n ],\n },\n {\n provider: \"Amazon\",\n docs: \"https://docs.aws.amazon.com/bedrock/\",\n api_key: \"https://console.aws.amazon.com/iam/home#/security_credentials\",\n default: \"anthropic.claude-3-5-sonnet-20241022-v2:0\",\n models: [\n {\n name: \"AI21 Jamba 1.5 Mini\",\n id: \"ai21.jamba-1-5-mini-v1:0\",\n contextLength: 256000,\n provider: \"AI21 Labs\",\n },\n {\n name: \"AI21 Jamba 1.5 Large\",\n id: \"ai21.jamba-1-5-large-v1:0\",\n contextLength: 256000,\n provider: \"AI21 Labs\",\n },\n {\n name: \"Amazon Nova Canvas\",\n id: \"amazon.nova-canvas-v1:0\",\n contextLength: 77,\n provider: \"Amazon\",\n type: \"image\",\n },\n {\n name: \"Amazon Nova Lite\",\n id: \"amazon.nova-lite-v1:0\",\n contextLength: 300000,\n provider: \"Amazon\",\n },\n {\n name: \"Amazon Nova Micro\",\n id: \"amazon.nova-micro-v1:0\",\n contextLength: 128000,\n provider: \"Amazon\",\n },\n {\n name: \"Amazon Nova Pro\",\n id: \"amazon.nova-pro-v1:0\",\n contextLength: 300000,\n provider: \"Amazon\",\n },\n {\n name: \"Amazon Nova Reel\",\n id: \"amazon.nova-reel-v1:0\",\n contextLength: 10000,\n provider: \"Amazon\",\n type: \"video\",\n },\n {\n name: \"Amazon Nova Reel V2 Lite\",\n id: \"amazon.nova-reel-v2-lite-v1:0\",\n contextLength: 10000,\n provider: \"Amazon\",\n type: \"video\",\n },\n {\n name: \"Amazon Nova Reel V2 Standard\",\n id: \"amazon.nova-reel-v2-standard-v1:0\",\n contextLength: 10000,\n provider: \"Amazon\",\n type: \"video\",\n },\n {\n name: \"Amazon Rerank\",\n id: \"amazon.rerank-v1:0\",\n contextLength: 8192,\n provider: \"Amazon\",\n type: \"reranker\",\n },\n {\n name: \"Amazon Titan Embeddings G1 - Text\",\n id: \"amazon.titan-embed-text-v1\",\n contextLength: 8192,\n provider: \"Amazon\",\n type: \"embedding\",\n },\n {\n name: \"Amazon Titan Embeddings G1 - Text v2\",\n id: \"amazon.titan-embed-text-v2:0\",\n contextLength: 8192,\n provider: \"Amazon\",\n type: \"embedding\",\n },\n {\n name: \"Amazon Titan Image Generator G1\",\n id: \"amazon.titan-image-generator-v1\",\n contextLength: 128,\n provider: \"Amazon\",\n type: \"image\",\n },\n {\n name: \"Amazon Titan Image Generator G2\",\n id: \"amazon.titan-image-generator-v2:0\",\n contextLength: 128,\n provider: \"Amazon\",\n type: \"image\",\n },\n {\n name: \"Amazon Titan Multimodal Embeddings G1\",\n id: \"amazon.titan-embed-image-v1\",\n contextLength: 8192,\n provider: \"Amazon\",\n type: \"embedding\",\n },\n {\n name: \"Amazon Titan Text G1 - Express\",\n id: \"amazon.titan-text-express-v1\",\n contextLength: 8192,\n provider: \"Amazon\",\n },\n {\n name: \"Amazon Titan Text G1 - Lite\",\n id: \"amazon.titan-text-lite-v1\",\n contextLength: 4096,\n provider: \"Amazon\",\n },\n {\n name: \"Amazon Titan Text G1 - Premier\",\n id: \"amazon.titan-text-premier-v1:0\",\n contextLength: 32000,\n provider: \"Amazon\",\n },\n {\n name: \"Claude 3.5 Sonnet v2\",\n id: \"anthropic.claude-3-5-sonnet-20241022-v2:0\",\n contextLength: 200000,\n provider: \"Anthropic\",\n },\n {\n name: \"Claude 3.5 Sonnet v1\",\n id: \"anthropic.claude-3-5-sonnet-20240620-v1:0\",\n contextLength: 200000,\n provider: \"Anthropic\",\n },\n {\n name: \"Claude 3.5 Haiku\",\n id: \"anthropic.claude-3-5-haiku-20241022-v1:0\",\n contextLength: 200000,\n provider: \"Anthropic\",\n },\n {\n name: \"Claude 3 Opus\",\n id: \"anthropic.claude-3-opus-20240229-v1:0\",\n contextLength: 200000,\n provider: \"Anthropic\",\n },\n {\n name: \"Claude 3 Sonnet\",\n id: \"anthropic.claude-3-sonnet-20240229-v1:0\",\n contextLength: 200000,\n provider: \"Anthropic\",\n },\n {\n name: \"Claude 3 Haiku\",\n id: \"anthropic.claude-3-haiku-20240307-v1:0\",\n contextLength: 200000,\n provider: \"Anthropic\",\n },\n {\n name: \"Claude Instant\",\n id: \"anthropic.claude-instant-v1\",\n contextLength: 100000,\n provider: \"Anthropic\",\n },\n {\n name: \"Cohere Command\",\n id: \"cohere.command-text-v14\",\n contextLength: 4096,\n provider: \"Cohere\",\n },\n {\n name: \"Cohere Command Light\",\n id: \"cohere.command-light-text-v14\",\n contextLength: 4096,\n provider: \"Cohere\",\n },\n {\n name: \"Cohere Command R\",\n id: \"cohere.command-r-v1:0\",\n contextLength: 128000,\n provider: \"Cohere\",\n },\n {\n name: \"Cohere Command R+\",\n id: \"cohere.command-r-plus-v1:0\",\n contextLength: 128000,\n provider: \"Cohere\",\n },\n {\n name: \"Cohere Embed English\",\n id: \"cohere.embed-english-v3\",\n contextLength: 512,\n provider: \"Cohere\",\n type: \"embedding\",\n },\n {\n name: \"Cohere Embed Multilingual\",\n id: \"cohere.embed-multilingual-v3\",\n contextLength: 512,\n provider: \"Cohere\",\n type: \"embedding\",\n },\n {\n name: \"Cohere Rerank English\",\n id: \"cohere.rerank-english-v3:0\",\n contextLength: 4096,\n provider: \"Cohere\",\n type: \"reranker\",\n },\n {\n name: \"Cohere Rerank Multilingual\",\n id: \"cohere.rerank-multilingual-v3:0\",\n contextLength: 4096,\n provider: \"Cohere\",\n type: \"reranker\",\n },\n {\n name: \"DeepSeek R1\",\n id: \"deepseek.deepseek-r1-distill-qwen-32b-v1:0\",\n contextLength: 32768,\n provider: \"DeepSeek\",\n },\n {\n name: \"Luma Dream Machine\",\n id: \"luma.dream-machine-v1:0\",\n contextLength: 512,\n provider: \"Luma AI\",\n type: \"video\",\n },\n\n {\n name: \"Llama 3.2 11B Vision Instruct\",\n id: \"meta.llama3-2-11b-instruct-v1:0\",\n contextLength: 128000,\n provider: \"Meta\",\n },\n {\n name: \"Llama 3.2 90B Vision Instruct\",\n id: \"meta.llama3-2-90b-instruct-v1:0\",\n contextLength: 128000,\n provider: \"Meta\",\n },\n {\n name: \"Mistral 7B Instruct\",\n id: \"mistral.mistral-7b-instruct-v0:2\",\n contextLength: 32768,\n provider: \"Mistral AI\",\n },\n {\n name: \"Mixtral 8x7B Instruct\",\n id: \"mistral.mixtral-8x7b-instruct-v0:1\",\n contextLength: 32768,\n provider: \"Mistral AI\",\n },\n {\n name: \"Mistral Small\",\n id: \"mistral.mistral-small-2402-v1:0\",\n contextLength: 32768,\n provider: \"Mistral AI\",\n },\n {\n name: \"Mistral Large\",\n id: \"mistral.mistral-large-2402-v1:0\",\n contextLength: 32768,\n provider: \"Mistral AI\",\n },\n {\n name: \"Mistral Large 2\",\n id: \"mistral.mistral-large-2407-v1:0\",\n contextLength: 128000,\n provider: \"Mistral AI\",\n },\n {\n name: \"Mistral Large 2411\",\n id: \"mistral.mistral-large-2411-v1:0\",\n contextLength: 128000,\n provider: \"Mistral AI\",\n },\n {\n name: \"Stable Diffusion XL\",\n id: \"stability.stable-diffusion-xl-v1\",\n contextLength: 77,\n provider: \"Stability AI\",\n type: \"image\",\n },\n {\n name: \"SDXL 1.0\",\n id: \"stability.stable-diffusion-xl-v0\",\n contextLength: 77,\n provider: \"Stability AI\",\n type: \"image\",\n },\n {\n name: \"Stable Image Ultra\",\n id: \"stability.stable-image-ultra-v1:0\",\n contextLength: 77,\n provider: \"Stability AI\",\n type: \"image\",\n },\n {\n name: \"Stable Image Core\",\n id: \"stability.stable-image-core-v1:0\",\n contextLength: 77,\n provider: \"Stability AI\",\n type: \"image\",\n },\n ],\n },\n {\n \"provider\": \"OpenRouter\",\n \"docs\": \"https://openrouter.ai/docs\",\n \"api_key\": \"https://openrouter.ai/settings/keys\",\n \"default\": \"openrouter/free\",\n \"models\": [\n {\n \"name\": \"OpenRouter Free (rotating)\",\n \"id\": \"openrouter/free\",\n \"contextLength\": 200_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Nemotron 3 Super 120B\",\n \"id\": \"nvidia/nemotron-3-super-120b-a12b:free\",\n \"contextLength\": 1_000_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Nemotron 3 Ultra 550B\",\n \"id\": \"nvidia/nemotron-3-ultra-550b-a55b:free\",\n \"contextLength\": 1_000_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Nemotron 3 Nano 30B A3B\",\n \"id\": \"nvidia/nemotron-3-nano-30b-a3b:free\",\n \"contextLength\": 256_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Nemotron 3 Nano Omni 30B A3B Reasoning\",\n \"id\": \"nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free\",\n \"contextLength\": 256_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Nemotron Nano 12B v2 VL\",\n \"id\": \"nvidia/nemotron-nano-12b-v2-vl:free\",\n \"contextLength\": 128_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Nemotron Nano 9B v2\",\n \"id\": \"nvidia/nemotron-nano-9b-v2:free\",\n \"contextLength\": 128_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Nemotron 3.5 Content Safety\",\n \"id\": \"nvidia/nemotron-3.5-content-safety:free\",\n \"contextLength\": 128_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Gemma 4 31B IT\",\n \"id\": \"google/gemma-4-31b-it:free\",\n \"contextLength\": 262_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Gemma 4 26B A4B IT\",\n \"id\": \"google/gemma-4-26b-a4b-it:free\",\n \"contextLength\": 262_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"GPT-OSS 120B\",\n \"id\": \"openai/gpt-oss-120b:free\",\n \"contextLength\": 131_072,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"GPT-OSS 20B\",\n \"id\": \"openai/gpt-oss-20b:free\",\n \"contextLength\": 131_072,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Qwen3 Coder\",\n \"id\": \"qwen/qwen3-coder:free\",\n \"contextLength\": 1_000_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Qwen3 Next 80B A3B Instruct\",\n \"id\": \"qwen/qwen3-next-80b-a3b-instruct:free\",\n \"contextLength\": 262_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Llama 3.3 70B Instruct\",\n \"id\": \"meta-llama/llama-3.3-70b-instruct:free\",\n \"contextLength\": 131_072,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Llama 3.2 3B Instruct\",\n \"id\": \"meta-llama/llama-3.2-3b-instruct:free\",\n \"contextLength\": 131_072,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Hermes 3 Llama 3.1 405B\",\n \"id\": \"nousresearch/hermes-3-llama-3.1-405b:free\",\n \"contextLength\": 131_072,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Laguna XS 2.1\",\n \"id\": \"poolside/laguna-xs-2.1:free\",\n \"contextLength\": 262_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Laguna XS 2\",\n \"id\": \"poolside/laguna-xs.2:free\",\n \"contextLength\": 262_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Laguna M 1\",\n \"id\": \"poolside/laguna-m.1:free\",\n \"contextLength\": 262_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"North Mini Code\",\n \"id\": \"cohere/north-mini-code:free\",\n \"contextLength\": 256_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"Dolphin Mistral 24B Venice Edition\",\n \"id\": \"cognitivecomputations/dolphin-mistral-24b-venice-edition:free\",\n \"contextLength\": 33_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"LFM 2.5 1.2B Thinking\",\n \"id\": \"liquid/lfm-2.5-1.2b-thinking:free\",\n \"contextLength\": 33_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"LFM 2.5 1.2B Instruct\",\n \"id\": \"liquid/lfm-2.5-1.2b-instruct:free\",\n \"contextLength\": 33_000,\n \"free\": true,\n \"type\": \"text-generation\"\n },\n {\n \"name\": \"OpenRouter Free (rotating)\",\n \"id\": \"openrouter/free\",\n \"contextLength\": 200_000,\n \"free\": true,\n \"type\": \"text-generation\"\n }\n ]\n}\n];\n\n/** List of available LLM provider services */\nexport const LANGUAGE_PROVIDERS = LANGUAGE_MODELS.map((p) =>\n p.provider.toLocaleLowerCase(),\n);\n\n/**\n * Guest-safe models that are known to work reliably.\n * Based on test results: only models with HTTP 200 status.\n */\nexport const GUEST_SAFE_MODELS = {\n openrouter: [\n \"openrouter/free\",\n \"nvidia/nemotron-3-super-120b-a12b:free\",\n \"nvidia/nemotron-3-ultra-550b-a55b:free\",\n \"nvidia/nemotron-3-nano-30b-a3b:free\",\n \"nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free\",\n \"nvidia/nemotron-nano-9b-v2:free\",\n \"nvidia/nemotron-3.5-content-safety:free\",\n \"google/gemma-4-31b-it:free\",\n \"google/gemma-4-26b-a4b-it:free\",\n \"openai/gpt-oss-20b:free\",\n \"poolside/laguna-xs-2.1:free\",\n \"poolside/laguna-m.1:free\",\n \"cohere/north-mini-code:free\",\n ],\n nvidia: [\n \"nvidia/nemotron-3-super-120b-a12b\",\n \"meta/llama-3.1-8b-instruct\",\n ],\n};\n\n/**\n * Filter models to only those in the guest-safe list.\n * Returns models with `free: true` property.\n */\nexport function filterModelsForGuests(models: any[]): any[] {\n return models.filter((m) => m.free === true);\n}\n\n/**\n * Get guest-safe provider list (only tested working models).\n * Uses GUEST_SAFE_MODELS whitelist to ensure reliability.\n */\nexport function getGuestSafeProviders(): typeof LANGUAGE_MODELS {\n return LANGUAGE_MODELS.map((provider) => ({\n ...provider,\n models: provider.models.filter(\n (model: any) =>\n GUEST_SAFE_MODELS[provider.provider.toLowerCase() as keyof typeof GUEST_SAFE_MODELS]?.includes(\n model.id,\n ) || false,\n ),\n })).filter((p) => p.models.length > 0);\n}\n","/**\n * @fileoverview Configuration Manager\n *\n * Manages model providers, MCP servers, and search configuration in memory.\n * Handles environment variable loading, provider hashing, and config updates.\n */\nimport type { ConfigModelProvider, MCPServerConfig, Config, UIConfigSections, Model } from \"./config-types\";\nimport { getModelProvidersUIConfigSection } from \"./provider-ui-config\";\nimport { getEnv } from \"./environment-variables\";\nimport { LANGUAGE_MODELS } from \"./language-models-database\";\n\n// Maps a provider UI key (from provider-ui-config) to the matching\n// `provider` name in the LANGUAGE_MODELS database. Names differ in a few\n// cases (e.g. the \"gemini\" UI key corresponds to the \"Google\" model list).\nconst PROVIDER_KEY_TO_DB_NAME: Record<string, string> = {\n openai: \"openai\",\n anthropic: \"anthropic\",\n gemini: \"google\",\n groq: \"groq\",\n deepseek: \"deepseek\",\n nvidia: \"nvidia\",\n openrouter: \"openrouter\",\n};\n\n/**\n * Returns the default chat models for a provider from the LANGUAGE_MODELS\n * database so that env-based providers expose a usable model list instead of\n * an empty one. Returns [] when no matching provider list exists.\n */\nconst getDefaultChatModels = (providerKey: string): Model[] => {\n const dbName = PROVIDER_KEY_TO_DB_NAME[providerKey] ?? providerKey;\n const entry = LANGUAGE_MODELS.find(\n (p) => p.provider.toLowerCase() === dbName.toLowerCase(),\n );\n if (!entry?.models) return [];\n\n return entry.models.map((m: any) => ({\n name: m.name,\n key: m.id,\n }));\n};\n\nconst hashObj = (obj: { [key: string]: any }) => {\n const str = JSON.stringify(obj, Object.keys(obj).sort());\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n hash = (hash << 5) - hash + str.charCodeAt(i);\n hash |= 0;\n }\n return String(Math.abs(hash).toString(36));\n};\n\nclass ConfigManager {\n configVersion = 1;\n currentConfig: Config = {\n version: this.configVersion,\n setupComplete: getEnv(\"SETUP_COMPLETE\") === \"true\" || false,\n preferences: {},\n personalization: {},\n modelProviders: [],\n mcpServers: [],\n search: {\n searxngURL: \"\",\n tavilyApiKey: \"\",\n sourceScrapeCount: 3,\n sourceScrapeTimeout: 5,\n },\n };\n uiConfigSections: UIConfigSections = {\n preferences: [],\n personalization: [],\n modelProviders: [],\n mcpServers: [],\n search: [\n {\n name: \"SearXNG URL\",\n key: \"searxngURL\",\n type: \"string\",\n required: false,\n description: \"The URL of your SearXNG instance\",\n placeholder: \"http://localhost:4000\",\n default: \"\",\n scope: \"server\",\n env: \"SEARXNG_API_URL\",\n },\n {\n name: \"Tavily API Key\",\n key: \"tavilyApiKey\",\n type: \"string\",\n required: false,\n description: \"Your Tavily API key for enhanced search capabilities.\",\n placeholder: \"tvly-...\",\n default: \"\",\n scope: \"server\",\n env: \"TAVILY_API_KEY\",\n },\n {\n name: \"Source pages to scrape\",\n key: \"sourceScrapeCount\",\n type: \"select\",\n options: [\n { name: \"Disabled (snippet only)\", value: \"0\" },\n { name: \"1 page\", value: \"1\" },\n { name: \"2 pages\", value: \"2\" },\n { name: \"3 pages (default)\", value: \"3\" },\n { name: \"5 pages\", value: \"5\" },\n ],\n required: false,\n description: \"Number of top search result URLs to fully scrape.\",\n default: \"3\",\n scope: \"server\",\n },\n {\n name: \"Scrape timeout (seconds)\",\n key: \"sourceScrapeTimeout\",\n type: \"select\",\n options: [\n { name: \"3 seconds\", value: \"3\" },\n { name: \"5 seconds (default)\", value: \"5\" },\n { name: \"10 seconds\", value: \"10\" },\n { name: \"15 seconds\", value: \"15\" },\n { name: \"20 seconds\", value: \"20\" },\n ],\n required: false,\n description: \"Maximum time to wait when scraping each source URL.\",\n default: \"5\",\n scope: \"server\",\n },\n ],\n };\n\n private initialized = false;\n\n constructor() {\n // Don't initialize in constructor to avoid circular dependency\n // Initialize lazily when config is first accessed\n }\n\n private ensureInitialized() {\n if (this.initialized) return;\n this.initialize();\n this.initialized = true;\n }\n\n private initialize() {\n const providerConfigSections = getModelProvidersUIConfigSection();\n this.uiConfigSections.modelProviders = providerConfigSections;\n\n const newProviders: ConfigModelProvider[] = [];\n\n providerConfigSections.forEach((provider) => {\n\n const tempConfig: Record<string, any> = {};\n const required: string[] = [];\n\n provider.fields.forEach((field) => {\n tempConfig[field.key] =\n getEnv(field.env!) || field.default || \"\";\n if (field.required) required.push(field.key);\n });\n\n let configured = true;\n required.forEach((r) => {\n if (!tempConfig[r]) configured = false;\n });\n\n if (configured) {\n const hash = hashObj(tempConfig);\n const exists = this.currentConfig.modelProviders.find(\n (p) => p.hash === hash,\n );\n\n if (!exists) {\n newProviders.push({\n id: hash,\n name: `${provider.name}`,\n type: provider.key,\n chatModels: getDefaultChatModels(provider.key),\n config: tempConfig,\n hash: hash,\n isEnvBased: true,\n });\n }\n }\n });\n\n if (newProviders.length > 0) {\n this.currentConfig.modelProviders.push(...newProviders);\n }\n\n // Search config from env\n this.uiConfigSections.search.forEach((f) => {\n if (f.env && !this.currentConfig.search[f.key]) {\n this.currentConfig.search[f.key] =\n getEnv(f.env) ?? f.default ?? \"\";\n }\n });\n }\n\n public getConfig(key: string, defaultValue?: any): any {\n this.ensureInitialized();\n const nested = key.split(\".\");\n let obj: any = this.currentConfig;\n\n for (let i = 0; i < nested.length; i++) {\n const part = nested[i];\n if (obj == null) return defaultValue;\n obj = obj[part];\n }\n\n return obj === undefined ? defaultValue : obj;\n }\n\n public updateConfig(key: string, val: any) {\n const parts = key.split(\".\");\n if (parts.length === 0) return;\n\n let target: any = this.currentConfig;\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n if (target[part] === null || typeof target[part] !== \"object\") {\n target[part] = {};\n }\n target = target[part];\n }\n\n const finalKey = parts[parts.length - 1];\n target[finalKey] = val;\n }\n\n public addModelProvider(type: string, name: string, config: any) {\n this.ensureInitialized();\n const hash = hashObj(config);\n\n const newModelProvider: ConfigModelProvider = {\n id: hash,\n name,\n type,\n config,\n chatModels: [],\n hash: hash,\n };\n\n this.currentConfig.modelProviders.push(newModelProvider);\n return newModelProvider;\n }\n\n public removeModelProvider(id: string) {\n this.currentConfig.modelProviders =\n this.currentConfig.modelProviders.filter((p) => p.id !== id);\n }\n\n public async updateModelProvider(id: string, name: string, config: any) {\n const provider = this.currentConfig.modelProviders.find(\n (p) => p.id === id,\n );\n if (!provider) throw new Error(\"Provider not found\");\n\n provider.name = name;\n provider.config = config;\n return provider;\n }\n\n public addProviderModel(providerId: string, type: \"chat\", model: any) {\n const provider = this.currentConfig.modelProviders.find(\n (p) => p.id === providerId,\n );\n if (!provider) throw new Error(\"Invalid provider id\");\n\n delete model.type;\n provider.chatModels.push(model);\n return model;\n }\n\n public removeProviderModel(\n providerId: string,\n type: \"chat\",\n modelKey: string,\n ) {\n const provider = this.currentConfig.modelProviders.find(\n (p) => p.id === providerId,\n );\n if (!provider) throw new Error(\"Invalid provider id\");\n\n provider.chatModels = provider.chatModels.filter((m) => m.key !== modelKey);\n }\n\n public isSetupComplete() {\n return this.currentConfig.setupComplete;\n }\n\n public markSetupComplete() {\n if (!this.currentConfig.setupComplete) {\n this.currentConfig.setupComplete = true;\n }\n }\n\n public getUIConfigSections(): UIConfigSections {\n this.ensureInitialized();\n return this.uiConfigSections;\n }\n\n public getCurrentConfig(): Config {\n this.ensureInitialized();\n return JSON.parse(JSON.stringify(this.currentConfig));\n }\n}\n\nconst configManager = new ConfigManager();\n\nexport default configManager;\n","/**\n * @fileoverview Registry for managing and loading Vercel AI SDK model providers.\n *\n * Exposes the full API expected by the app's API routes and chat handler:\n * - `activeProviders` (sync getter) / `getActiveProviders()`\n * - `isProviderEnvBased(providerId)`\n * - `loadChatModel(providerId, modelKey)` — returns an AI SDK `LanguageModel`\n * - provider/model CRUD passthroughs to {@link configManager}\n */\nimport configManager from \"./config-manager\";\nimport { LANGUAGE_MODELS, getGuestSafeProviders } from \"./language-models-database\";\nimport { getModelProvidersUIConfigSection } from \"./provider-ui-config\";\nimport type { ConfigModelProvider, Model } from \"./config-types\";\n\n// Maps a provider UI key to the matching `provider` name in the\n// LANGUAGE_MODELS database (e.g. the \"gemini\" UI key ↔ \"Google\" model list).\nconst PROVIDER_KEY_TO_DB_NAME: Record<string, string> = {\n openai: \"openai\",\n anthropic: \"anthropic\",\n gemini: \"google\",\n groq: \"groq\",\n deepseek: \"deepseek\",\n nvidia: \"nvidia\",\n openrouter: \"openrouter\",\n};\n\n/** Default chat models for a provider type from the LANGUAGE_MODELS database. */\nconst getDefaultChatModels = (providerType: string): Model[] => {\n const dbName = PROVIDER_KEY_TO_DB_NAME[providerType] ?? providerType;\n const entry = LANGUAGE_MODELS.find(\n (p) => p.provider.toLowerCase() === dbName.toLowerCase(),\n );\n if (!entry?.models) return [];\n return entry.models.map((m: any) => ({ name: m.name, key: m.id }));\n};\n\n/** Merges default and user-added models, deduplicated by model key. */\nconst mergeChatModels = (provider: ConfigModelProvider): Model[] => {\n const merged = new Map<string, Model>();\n for (const m of getDefaultChatModels(provider.type)) {\n merged.set(m.key, m);\n }\n for (const m of provider.chatModels || []) {\n merged.set(m.key, { key: m.key, name: m.name });\n }\n return [...merged.values()];\n};\n\nexport default class ModelRegistry {\n /**\n * Currently configured providers (env-based + user-added).\n * Sync getter used by the chat handler for logging and lookups.\n */\n get activeProviders(): ConfigModelProvider[] {\n return configManager.getCurrentConfig().modelProviders;\n }\n\n /**\n * Providers with their full chat model lists (defaults merged with\n * user-added models), shaped for the settings/providers UI.\n */\n async getActiveProviders(guestMode: boolean = false) {\n const providers = this.activeProviders;\n const dbModels = guestMode ? getGuestSafeProviders() : LANGUAGE_MODELS;\n\n return providers.map((p) => ({\n id: p.id,\n name: p.name,\n type: p.type,\n chatModels: guestMode ? this.getGuestChatModels(p, dbModels) : mergeChatModels(p),\n })).filter((p) => p.chatModels.length > 0);\n }\n\n /**\n * Get guest-safe chat models for a provider (only tested working models).\n */\n private getGuestChatModels(provider: ConfigModelProvider, guestProviders: typeof LANGUAGE_MODELS): Model[] {\n const dbName = PROVIDER_KEY_TO_DB_NAME[provider.type.toLowerCase()];\n const dbEntry = guestProviders.find(\n (p) => p.provider.toLowerCase() === (dbName?.toLowerCase() || provider.type.toLowerCase()),\n );\n if (!dbEntry?.models) return [];\n return dbEntry.models.map((m: any) => ({ name: m.name, key: m.id }));\n }\n\n /**\n * Finds a provider by id, falling back to free providers in order:\n * OpenRouter (no daily limits, best for guests), Groq (fastest, daily limits),\n * then NVIDIA, then the first configured provider.\n * Client-side provider ids are config hashes that go stale whenever\n * server env config changes, so a graceful fallback keeps existing\n * chat sessions working after a redeploy.\n */\n private findProvider(providerId?: string): ConfigModelProvider | undefined {\n const providers = this.activeProviders;\n let provider = providers.find((p) => p.id === providerId);\n\n if (!provider && providers.length > 0) {\n // Prioritize OpenRouter (no daily limits) over Groq (has daily limits)\n provider =\n providers.find((p) => p.name.toLowerCase().includes(\"openrouter\")) ??\n providers.find((p) => p.name.toLowerCase().includes(\"groq\")) ??\n providers.find((p) => p.name.toLowerCase().includes(\"nvidia\")) ??\n providers[0];\n }\n\n return provider;\n }\n\n /** Whether the resolved provider was configured from environment variables. */\n isProviderEnvBased(providerId?: string): boolean {\n return this.findProvider(providerId)?.isEnvBased === true;\n }\n\n /**\n * Instantiates a Vercel AI SDK language model for the given provider and\n * model key. Falls back to the provider's first/default model when no key\n * is given. Temperature is a per-call setting in the AI SDK, so callers\n * pass it to generateText/streamText rather than the model instance.\n */\n async loadChatModel(providerId?: string, modelKey?: string): Promise<any> {\n const provider = this.findProvider(providerId);\n\n if (!provider) {\n throw new Error(\n \"No model providers configured. Please add a provider in settings.\",\n );\n }\n\n const type = provider.type.toLowerCase();\n const config = provider.config || {};\n const apiKey = config.apiKey || \"\";\n const availableModels = mergeChatModels(provider);\n const modelName =\n modelKey || availableModels[0]?.key || \"\";\n\n console.log(\n `[ModelRegistry] loadChatModel: providerId=${providerId} provider=${provider.name} type=${type} requestedModel=${modelKey ?? \"(default)\"} resolvedModel=${modelName}`,\n );\n\n if (!modelName) {\n throw new Error(`No chat models available for provider \"${provider.name}\"`);\n }\n\n // Validate that the requested model exists in the provider's model list\n if (modelKey && !availableModels.some((m) => m.key === modelKey)) {\n console.warn(\n `[ModelRegistry] Requested model \"${modelKey}\" not found in provider \"${provider.name}\". Available models: ${availableModels.map((m) => m.key).join(\", \")}`,\n );\n throw new Error(\n `Model \"${modelKey}\" is not available for provider \"${provider.name}\". Please select a different model in Settings.`,\n );\n }\n\n // Validate API key is present\n if (!apiKey) {\n throw new Error(\n `No API key configured for provider \"${provider.name}\". Please add your API key in Settings → Model Providers.`,\n );\n }\n\n // OpenAI-compatible providers differ only by base URL.\n const openAICompatibleBaseURLs: Record<string, string> = {\n openai: \"https://api.openai.com/v1\",\n togetherai: \"https://api.together.xyz/v1\",\n perplexity: \"https://api.perplexity.ai\",\n nvidia: \"https://integrate.api.nvidia.com/v1\",\n openrouter: \"https://openrouter.ai/api/v1\",\n deepseek: \"https://api.deepseek.com\",\n xai: \"https://api.x.ai/v1\",\n };\n\n if (type in openAICompatibleBaseURLs) {\n const { createOpenAI } = await import(\"@ai-sdk/openai\");\n return createOpenAI({\n apiKey,\n baseURL: config.baseURL || openAICompatibleBaseURLs[type],\n }).chat(modelName);\n }\n\n switch (type) {\n case \"cloudflare\": {\n const { createOpenAI } = await import(\"@ai-sdk/openai\");\n const [cfApiToken, accountId] = apiKey.split(\":\");\n return createOpenAI({\n apiKey: cfApiToken,\n baseURL: `https://api.cloudflare.com/client/v4/accounts/${accountId}/ai/v1`,\n }).chat(modelName);\n }\n case \"groq\": {\n const { createGroq } = await import(\"@ai-sdk/groq\");\n return createGroq({ apiKey })(modelName);\n }\n case \"anthropic\": {\n const { createAnthropic } = await import(\"@ai-sdk/anthropic\");\n return createAnthropic({ apiKey })(modelName);\n }\n case \"gemini\":\n case \"google\": {\n const { createGoogleGenerativeAI } = await import(\"@ai-sdk/google\");\n return createGoogleGenerativeAI({ apiKey })(modelName);\n }\n default:\n throw new Error(`Unsupported provider type: ${type}`);\n }\n }\n\n /**\n * Registers a new provider. Accepts both `(type, config)` — used by the\n * providers API route — and `(type, name, config)`.\n */\n async addProvider(type: string, nameOrConfig: any, config?: Record<string, any>) {\n let name: string;\n let finalConfig: Record<string, any>;\n if (typeof nameOrConfig === \"object\" && nameOrConfig !== null && !config) {\n finalConfig = nameOrConfig;\n const section = getModelProvidersUIConfigSection().find(\n (s) => s.key === type,\n );\n name = section?.name || type.toUpperCase();\n } else {\n name = String(nameOrConfig);\n finalConfig = config || {};\n }\n\n const newProvider = configManager.addModelProvider(type, name, finalConfig);\n return {\n ...newProvider,\n chatModels: getDefaultChatModels(type),\n };\n }\n\n async removeProvider(providerId: string) {\n configManager.removeModelProvider(providerId);\n }\n\n /**\n * Updates a provider's config. Accepts both `(id, config)` — used by the\n * providers API route — and `(id, name, config)`.\n */\n async updateProvider(providerId: string, nameOrConfig: any, config?: Record<string, any>) {\n let name: string;\n let finalConfig: Record<string, any>;\n if (typeof nameOrConfig === \"object\" && nameOrConfig !== null && !config) {\n finalConfig = nameOrConfig;\n const existing = this.activeProviders.find((p) => p.id === providerId);\n name = existing?.name || providerId;\n } else {\n name = String(nameOrConfig);\n finalConfig = config || {};\n }\n\n const updated = await configManager.updateModelProvider(\n providerId,\n name,\n finalConfig,\n );\n return {\n ...updated,\n chatModels: mergeChatModels(updated),\n };\n }\n\n async addProviderModel(providerId: string, type: \"chat\", model: any) {\n return configManager.addProviderModel(providerId, type, model);\n }\n\n async removeProviderModel(providerId: string, type: \"chat\", modelKey: string) {\n configManager.removeProviderModel(providerId, type, modelKey);\n }\n}\n","const PROVIDERS = {\n openrouter: { row: 0, col: 0 },\n tongyi: { row: 0, col: 1 },\n ollama: { row: 0, col: 2 },\n huggingface: { row: 0, col: 3 },\n localai: { row: 0, col: 4 },\n openllm: { row: 0, col: 5 },\n zhipu: { row: 1, col: 0 },\n replicate: { row: 1, col: 1 },\n azure: { row: 1, col: 2 },\n anthropic: { row: 1, col: 3 },\n groq: { row: 1, col: 4 },\n sagemaker: { row: 1, col: 5 },\n \"01ai\": { row: 2, col: 0 },\n bedrock: { row: 2, col: 1 },\n openai: { row: 2, col: 2 },\n cohere: { row: 2, col: 3 },\n together: { row: 2, col: 4 },\n xorbits: { row: 2, col: 5 },\n wenxin: { row: 3, col: 0 },\n moonshot: { row: 3, col: 1 },\n gemini: { row: 3, col: 2 },\n mistral: { row: 3, col: 3 },\n jina: { row: 3, col: 4 },\n chatglm: { row: 3, col: 5 },\n} as const;\n\nexport type Provider = keyof typeof PROVIDERS;\n\nconst COLS = 6;\nconst ROWS = 4;\n\n/**\n * Returns a cropped canvas containing just the provider box.\n */\nexport async function cropProvider(\n image: HTMLImageElement | ImageBitmap,\n provider: Provider\n): Promise<HTMLCanvasElement> {\n if (!(provider in PROVIDERS)) {\n throw new Error(`Unknown provider: ${provider}`);\n }\n\n const { row, col } = PROVIDERS[provider];\n\n const tileWidth = image.width / COLS;\n const tileHeight = image.height / ROWS;\n\n const canvas = document.createElement(\"canvas\");\n canvas.width = tileWidth;\n canvas.height = tileHeight;\n\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n throw new Error(\"Failed to get 2D context\");\n }\n\n ctx.drawImage(\n image,\n col * tileWidth,\n row * tileHeight,\n tileWidth,\n tileHeight,\n 0,\n 0,\n tileWidth,\n tileHeight\n );\n\n return canvas;\n}\n\n/**\n * Returns the provider image as a Blob.\n */\nexport async function cropProviderAsBlob(\n image: HTMLImageElement | ImageBitmap,\n provider: Provider,\n type: \"image/png\" | \"image/jpeg\" | \"image/webp\" = \"image/png\",\n quality?: number\n): Promise<Blob> {\n const canvas = await cropProvider(image, provider);\n\n return new Promise<Blob>((resolve, reject) => {\n canvas.toBlob(\n (blob) => {\n if (blob) {\n resolve(blob);\n } else {\n reject(new Error(\"Failed to create blob\"));\n }\n },\n type,\n quality\n );\n });\n}\n\n/**\n * Returns the provider image as a data URL.\n */\nexport async function cropProviderAsDataURL(\n image: HTMLImageElement | ImageBitmap,\n provider: Provider,\n type: \"image/png\" | \"image/jpeg\" | \"image/webp\" = \"image/png\",\n quality?: number\n): Promise<string> {\n const canvas = await cropProvider(image, provider);\n return canvas.toDataURL(type, quality);\n}\n\n/**\n * Helper to load and crop in one call.\n */\nexport async function getProviderImage(\n spriteSheetUrl: string,\n provider: Provider\n): Promise<HTMLCanvasElement> {\n const img = new Image();\n img.src = spriteSheetUrl;\n await img.decode();\n return cropProvider(img, provider);\n}\n\n/**\n * Get all available provider names.\n */\nexport function getProviderNames(): Provider[] {\n return Object.keys(PROVIDERS) as Provider[];\n}\n"],"mappings":"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CAEA,UAAA,GACE,MAAM,EHhIC,CACL,CACE,IAAK,SACL,KAAM,SACN,OAsCC,CACL,CACE,KAAM,WACN,KAAM,UACN,IAAK,SACL,YAAa,sBACb,UAAU,EACV,YAAa,iBACb,IAAK,iBACL,MAAO,UAET,CACE,KAAM,SACN,KAAM,WACN,IAAK,UACL,YAAa,kCACb,UAAU,EACV,YAAa,kBACb,QAAS,4BACT,IAAK,kBACL,MAAO,YAxDP,CACE,IAAK,YACL,KAAM,YACN,OA4DC,CACL,CACE,KAAM,WACN,KAAM,UACN,IAAK,SACL,YAAa,yBACb,UAAU,EACV,YAAa,oBACb,IAAK,oBACL,MAAO,YAnEP,CACE,IAAK,SACL,KAAM,gBACN,OAsEC,CACL,CACE,KAAM,WACN,KAAM,UACN,IAAK,SACL,YAAa,6BACb,UAAU,EACV,YAAa,wBACb,IAAK,iBACL,MAAO,YA7EP,CACE,IAAK,OACL,KAAM,OACN,OAgFC,CACL,CACE,KAAM,WACN,KAAM,UACN,IAAK,SACL,YAAa,mHACb,UAAU,EACV,YAAa,UACb,IAAK,eACL,MAAO,YAvFP,CACE,IAAK,WACL,KAAM,WACN,OA0FC,CACL,CACE,KAAM,WACN,KAAM,UACN,IAAK,SACL,YAAa,wBACb,UAAU,EACV,YAAa,mBACb,IAAK,mBACL,MAAO,YAjGP,CACE,IAAK,SACL,KAAM,SACN,OAoGC,CACL,CACE,KAAM,WACN,KAAM,UACN,IAAK,SACL,YAAa,sHACb,UAAU,EACV,YAAa,YACb,IAAK,iBACL,MAAO,UAET,CACE,KAAM,SACN,KAAM,WACN,IAAK,UACL,YAAa,kDACb,UAAU,EACV,YAAa,sCACb,QAAS,sCACT,IAAK,kBACL,MAAO,YAtHP,CACE,IAAK,aACL,KAAM,aACN,OAyHC,CACL,CACE,KAAM,WACN,KAAM,UACN,IAAK,SACL,YAAa,8HACb,UAAU,EACV,YAAa,eACb,IAAK,qBACL,MAAO,UAET,CACE,KAAM,SACN,KAAM,WACN,IAAK,UACL,YAAa,sDACb,UAAU,EACV,YAAa,+BACb,QAAS,+BACT,IAAK,sBACL,MAAO,aG9CT,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C,KAAE,SAAS,EAAA,EAAA,cAAmB,CAClC,MAAO,EACP,YAAa,EACb,OARa,EAAgC,GAAc,QAC3D,iBACA,EAA0B,EAAM,iBASlC,OAAO,EAAa,MAAM,8DEvCf,IAIF,CACL,CACE,IAAK,SACL,KAAM,SACN,OAsCC,CACL,CACE,KAAM,WACN,KAAM,UACN,IAAK,SACL,YAAa,sBACb,UAAU,EACV,YAAa,iBACb,IAAK,iBACL,MAAO,UAET,CACE,KAAM,SACN,KAAM,WACN,IAAK,UACL,YAAa,kCACb,UAAU,EACV,YAAa,kBACb,QAAS,4BACT,IAAK,kBACL,MAAO,YAxDP,CACE,IAAK,YACL,KAAM,YACN,OA4DC,CACL,CACE,KAAM,WACN,KAAM,UACN,IAAK,SACL,YAAa,yBACb,UAAU,EACV,YAAa,oBACb,IAAK,oBACL,MAAO,YAnEP,CACE,IAAK,SACL,KAAM,gBACN,OAsEC,CACL,CACE,KAAM,WACN,KAAM,UACN,IAAK,SACL,YAAa,6BACb,UAAU,EACV,YAAa,wBACb,IAAK,iBACL,MAAO,YA7EP,CACE,IAAK,OACL,KAAM,OACN,OAgFC,CACL,CACE,KAAM,WACN,KAAM,UACN,IAAK,SACL,YAAa,mHACb,UAAU,EACV,YAAa,UACb,IAAK,eACL,MAAO,YAvFP,CACE,IAAK,WACL,KAAM,WACN,OA0FC,CACL,CACE,KAAM,WACN,KAAM,UACN,IAAK,SACL,YAAa,wBACb,UAAU,EACV,YAAa,mBACb,IAAK,mBACL,MAAO,YAjGP,CACE,IAAK,SACL,KAAM,SACN,OAoGC,CACL,CACE,KAAM,WACN,KAAM,UACN,IAAK,SACL,YAAa,sHACb,UAAU,EACV,YAAa,YACb,IAAK,iBACL,MAAO,UAET,CACE,KAAM,SACN,KAAM,WACN,IAAK,UACL,YAAa,kDACb,UAAU,EACV,YAAa,sCACb,QAAS,sCACT,IAAK,kBACL,MAAO,YAtHP,CACE,IAAK,aACL,KAAM,aACN,OAyHC,CACL,CACE,KAAM,WACN,KAAM,UACN,IAAK,SACL,YAAa,8HACb,UAAU,EACV,YAAa,eACb,IAAK,qBACL,MAAO,UAET,CACE,KAAM,SACN,KAAM,WACN,IAAK,UACL,YAAa,sDACb,UAAU,EACV,YAAa,+BACb,QAAS,+BACT,IAAK,sBACL,MAAO,sCK9Eb,eACE,EACA,GAEA,MAAM,EAAM,IAAI,MAGhB,OAFA,EAAI,IAAM,QACJ,EAAI,SACH,EAAa,EAAK,EAC3B,2BAKA,WACE,OAAO,OAAO,KAAK,EACrB,0HX3EA,SAAyC,GACvC,EAAmB,CACrB,4EKvCA,SACE,EACA,EAAY,IACZ,EAAe,KAEf,MAAM,GAAW,GAAQ,IAAI,OAC7B,GAAI,EAAQ,QAAU,EACpB,OAAO,EAAQ,OAAS,EAAI,CAAC,GAAW,GAG1C,MAAM,EAAmB,GACzB,IAAI,EAAQ,EAEZ,KAAO,EAAQ,EAAQ,QAAQ,CAC7B,IAAI,EAAM,KAAK,IAAI,EAAQ,EAAW,EAAQ,QAG9C,GAAI,EAAM,EAAQ,OAAQ,CACxB,MAAM,EAAY,EAAQ,YAAY,IAAK,GACvC,EAAY,IAAO,EAAM,EAC/B,CAIA,GAFA,EAAO,KAAK,EAAQ,MAAM,EAAO,GAAK,QAElC,GAAO,EAAQ,OAAQ,MAC3B,EAAQ,KAAK,IAAI,EAAM,EAAc,EAAQ,EAC/C,CAEA,OAAO,EAAO,OAAQ,GAAU,EAAM,OAAS,EACjD"}
|