import axios from "axios"; import { PostProcessingProvider } from "./SettingsManager"; export interface ChatCompletionOptions { apiKey: string; model: string; endpoint?: string; provider?: "anthropic" | "openai" | "openrouter" | "groq" | "custom"; temperature?: number; maxTokens?: number; } /** * Unified AI service for all NibbleAI modules. * Supports OpenAI-compatible chat completions and Anthropic native API. */ export class AIService { /** * Call a chat completion API (OpenAI-compatible or Anthropic). * @param userMessage - The user's input text * @param systemPrompt - System-level instructions * @param options - API configuration * @returns The model's response text */ static async callChatCompletion( userMessage: string, systemPrompt: string, options: ChatCompletionOptions ): Promise { const provider = options.provider || "openai"; const endpoint = options.endpoint || "https://openrouter.ai/api/v1/chat/completions"; if (provider === "anthropic") { return AIService.callAnthropic(userMessage, systemPrompt, options); } return AIService.callOpenAI(userMessage, systemPrompt, { ...options, endpoint, }); } private static async callOpenAI( userMessage: string, systemPrompt: string, options: ChatCompletionOptions ): Promise { const response = await axios.post( options.endpoint || "https://openrouter.ai/api/v1/chat/completions", { model: options.model, messages: [ { role: "system", content: systemPrompt }, { role: "user", content: userMessage }, ], temperature: options.temperature ?? 0.3, max_tokens: options.maxTokens ?? 2000, }, { headers: { Authorization: `Bearer ${options.apiKey}`, "Content-Type": "application/json", ...(options.endpoint?.includes("openrouter.ai") ? { "HTTP-Referer": "https://obsidian.md", "X-Title": "Obsidian NibbleAI", } : {}), }, } ); return response.data.choices[0].message.content.trim(); } private static async callAnthropic( userMessage: string, systemPrompt: string, options: ChatCompletionOptions ): Promise { const response = await axios.post( options.endpoint || "https://api.anthropic.com/v1/messages", { model: options.model, max_tokens: options.maxTokens ?? 8192, system: systemPrompt, messages: [{ role: "user", content: userMessage }], }, { headers: { "x-api-key": options.apiKey, "anthropic-version": "2023-06-01", "anthropic-dangerous-direct-browser-access": "true", "Content-Type": "application/json", }, } ); return response.data.content[0].text; } }