{"version":3,"sources":["../providers/router.ts"],"sourcesContent":["/**\n * Router Provider - Intelligent LLM Routing via LLMRouter\n * \n * Routes requests to the most appropriate model based on:\n * - Task complexity analysis\n * - User priority preferences\n * - Cost optimization\n * - Performance requirements\n */\n\nimport type { \n  AIProvider, \n  AIResponse, \n  ForgeConfig,\n  ProviderOptions \n} from \"../types\";\n\nimport type {\n  RouterRoutingResponse,\n  RouterExecuteRequest,\n  RouterFeedbackRequest,\n  RoutedAIResponse\n} from \"../types/router\";\n\nexport class RouterProvider implements AIProvider {\n  private config: ForgeConfig;\n  private baseURL: string;\n  private headers: Record<string, string>;\n\n  constructor(config: ForgeConfig) {\n    this.config = config;\n    this.baseURL = config.baseURL || process.env.LLMROUTER_URL || \"http://localhost:8000\";\n    \n    if (!this.baseURL) {\n      throw new Error(\n        \"LLMRouter URL is required. Set LLMROUTER_URL environment variable or pass baseURL in config.\"\n      );\n    }\n\n    this.headers = {\n      \"Content-Type\": \"application/json\",\n      \"User-Agent\": \"TryAI/1.0\"\n    };\n\n    if (config.apiKey || process.env.LLMROUTER_API_KEY) {\n      this.headers.Authorization = `Bearer ${config.apiKey || process.env.LLMROUTER_API_KEY}`;\n    }\n  }\n\n  async complete(\n    message: string | any[],\n    options?: ProviderOptions\n  ): Promise<RoutedAIResponse> {\n    const prompt = typeof message === 'string' ? message : this.messagesToPrompt(message);\n    \n    // Step 1: Get routing decision\n    const routing = await this.getRouting(prompt, options);\n    \n    // Step 2: Execute with selected model\n    const startTime = Date.now();\n    const response = await this.executeWithRouting(prompt, routing, options);\n    const responseTime = Date.now() - startTime;\n\n    // Step 3: Create enhanced response with feedback method\n    const routedResponse: RoutedAIResponse = {\n      ...response,\n      metadata: {\n        ...response.metadata,\n        routingId: routing.routing_id,\n        selectedModel: routing.selected_model,\n        routingReason: routing.routing_reason,\n        dimensionalScores: routing.dimensional_scores,\n        priorityMode: routing.priority_mode,\n        estimatedCost: routing.estimated_cost,\n        cached: routing.cached,\n        responseTime\n      },\n      submitFeedback: async (feedback) => {\n        await this.submitFeedback({\n          routing_id: routing.routing_id,\n          response_time: responseTime,\n          ...feedback\n        });\n      }\n    };\n\n    return routedResponse;\n  }\n\n  async stream(\n    message: string | any[],\n    options?: ProviderOptions\n  ): Promise<AsyncIterable<any>> {\n    const prompt = typeof message === 'string' ? message : this.messagesToPrompt(message);\n    \n    // Get routing decision\n    const routing = await this.getRouting(prompt, options);\n    \n    // Execute with streaming\n    const response = await fetch(`${this.baseURL}/execute`, {\n      method: \"POST\",\n      headers: this.headers,\n      body: JSON.stringify({\n        routing_id: routing.routing_id,\n        prompt,\n        model: routing.selected_model,\n        priority_mode: options?.priority || this.config.defaultPriority || \"balanced\",\n        stream: true,\n        temperature: options?.temperature,\n        max_tokens: options?.maxTokens\n      })\n    });\n\n    if (!response.ok) {\n      throw new Error(`Router execution failed: ${response.statusText}`);\n    }\n\n    // Return async generator for streaming\n    return this.parseSSEStream(response.body!);\n  }\n\n  private async getRouting(\n    prompt: string,\n    options?: ProviderOptions\n  ): Promise<RouterRoutingResponse> {\n    const response = await fetch(`${this.baseURL}/route`, {\n      method: \"POST\",\n      headers: this.headers,\n      body: JSON.stringify({\n        prompt,\n        priority_mode: options?.priority || this.config.defaultPriority || \"balanced\",\n        max_tokens: options?.maxTokens,\n        temperature: options?.temperature,\n        tools: options?.tools,\n        response_format: options?.responseFormat\n      })\n    });\n\n    if (!response.ok) {\n      const error = await response.text();\n      throw new Error(`Routing failed: ${error}`);\n    }\n\n    return response.json();\n  }\n\n  private async executeWithRouting(\n    prompt: string,\n    routing: RouterRoutingResponse,\n    options?: ProviderOptions\n  ): Promise<AIResponse> {\n    const response = await fetch(`${this.baseURL}/execute`, {\n      method: \"POST\",\n      headers: this.headers,\n      body: JSON.stringify({\n        routing_id: routing.routing_id,\n        prompt,\n        model: routing.selected_model,\n        priority_mode: options?.priority || routing.priority_mode,\n        stream: false,\n        temperature: options?.temperature,\n        max_tokens: options?.maxTokens,\n        tools: options?.tools,\n        response_format: options?.responseFormat\n      } as RouterExecuteRequest)\n    });\n\n    if (!response.ok) {\n      const error = await response.text();\n      throw new Error(`Execution failed: ${error}`);\n    }\n\n    const data = await response.json();\n\n    return {\n      text: data.content || data.text || \"\",\n      usage: data.usage,\n      model: data.model || routing.selected_model,\n      metadata: {\n        cost: data.cost,\n        finishReason: data.finish_reason\n      }\n    };\n  }\n\n  private async submitFeedback(feedback: RouterFeedbackRequest): Promise<void> {\n    try {\n      const response = await fetch(`${this.baseURL}/feedback`, {\n        method: \"POST\",\n        headers: this.headers,\n        body: JSON.stringify(feedback)\n      });\n\n      if (!response.ok) {\n        console.error(\"Failed to submit feedback:\", await response.text());\n      }\n    } catch (error) {\n      console.error(\"Error submitting feedback:\", error);\n      // Don't throw - feedback is best effort\n    }\n  }\n\n  private messagesToPrompt(messages: any[]): string {\n    return messages\n      .map(msg => {\n        if (typeof msg === 'string') return msg;\n        if (msg.content) return msg.content;\n        if (msg.text) return msg.text;\n        return JSON.stringify(msg);\n      })\n      .join('\\n\\n');\n  }\n\n  private async *parseSSEStream(stream: ReadableStream): AsyncIterable<any> {\n    const reader = stream.getReader();\n    const decoder = new TextDecoder();\n    let buffer = '';\n\n    try {\n      while (true) {\n        const { done, value } = await reader.read();\n        if (done) break;\n\n        buffer += decoder.decode(value, { stream: true });\n        const lines = buffer.split('\\n');\n        buffer = lines.pop() || '';\n\n        for (const line of lines) {\n          if (line.startsWith('data: ')) {\n            const data = line.slice(6);\n            if (data === '[DONE]') return;\n            \n            try {\n              const chunk = JSON.parse(data);\n              yield chunk;\n            } catch (e) {\n              console.error('Failed to parse SSE chunk:', e);\n            }\n          }\n        }\n      }\n    } finally {\n      reader.releaseLock();\n    }\n  }\n\n  // AIProvider interface methods\n  async listModels(): Promise<string[]> {\n    // Router handles model selection internally\n    return [\"auto\"];\n  }\n\n  async embeddings(input: string | string[]): Promise<any> {\n    throw new Error(\"Embeddings not supported by Router provider. Use a specific provider.\");\n  }\n\n  async moderate(input: string): Promise<any> {\n    throw new Error(\"Moderation not supported by Router provider. Use a specific provider.\");\n  }\n}"],"mappings":"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","names":["RouterProvider","config","message","options","prompt","routing","startTime","response","responseTime","feedback","error","data","messages","msg","stream","reader","decoder","buffer","done","value","lines","line","e","input"]}