/** * Ollama AI Adapter — Local LLM provider * * Connects to a locally-running Ollama instance for private, * cost-free AI code reviews. No data leaves your infrastructure. */ import type { AIAdapter, AICompletionResult, AIConfig, AIReviewPrompt, } from "./types"; export class OllamaAdapter implements AIAdapter { async complete( prompt: AIReviewPrompt, config: AIConfig, ): Promise { const baseUrl = config.baseUrl || process.env.OLLAMA_BASE_URL || "http://localhost:11434"; const model = config.model || process.env.OLLAMA_MODEL || "codellama:13b"; const response = await fetch(`${baseUrl}/api/chat`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ model, messages: [ { role: "system", content: prompt.system }, { role: "user", content: prompt.user }, ], stream: false, options: { temperature: config.temperature ?? 0.1, num_predict: config.maxTokens ?? 4096, }, format: "json", }), }); if (!response.ok) { const errorText = await response.text(); throw new Error(`Ollama error (${response.status}): ${errorText}`); } const data = await response.json(); return { content: data.message?.content || "", usage: { inputTokens: data.prompt_eval_count || 0, outputTokens: data.eval_count || 0, totalTokens: (data.prompt_eval_count || 0) + (data.eval_count || 0), }, }; } }