"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OllamaAdapter = void 0;
const DEFAULT_OLLAMA_CONFIG = {
    baseUrl: "http://localhost:11434",
    model: "llama3.1:8b",
};
/**
 * Ollama Adapter — Local LLM inference via Ollama HTTP API.
 * Zero dependencies, zero cost, zero latency to network.
 * Falls back gracefully if Ollama isn't running.
 */
class OllamaAdapter {
    provider = "ollama";
    config;
    get name() {
        return `Ollama (${this.config.model})`;
    }
    constructor(config) {
        this.config = { ...DEFAULT_OLLAMA_CONFIG, ...config };
    }
    async available() {
        try {
            const controller = new AbortController();
            const timeout = setTimeout(() => controller.abort(), 2000);
            const res = await fetch(`${this.config.baseUrl}/api/tags`, {
                signal: controller.signal,
            });
            clearTimeout(timeout);
            if (!res.ok)
                return false;
            const data = (await res.json());
            const models = data.models ?? [];
            // Check if requested model is pulled
            const modelBase = this.config.model.split(":")[0];
            return models.some((m) => m.name === this.config.model || m.name.startsWith(modelBase));
        }
        catch {
            return false;
        }
    }
    async chat(messages, options) {
        const startMs = Date.now();
        const ollamaMessages = messages.map((m) => ({
            role: m.role === "tool" ? "assistant" : m.role,
            content: m.content,
        }));
        const body = {
            model: this.config.model,
            messages: ollamaMessages,
            stream: false,
            options: {
                temperature: options?.temperature ?? 0.1,
                num_predict: options?.maxTokens ?? 4096,
            },
        };
        if (options?.responseFormat === "json") {
            body.format = "json";
        }
        const res = await fetch(`${this.config.baseUrl}/api/chat`, {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify(body),
        });
        if (!res.ok) {
            const text = await res.text();
            throw new Error(`Ollama error (${res.status}): ${text}`);
        }
        const data = (await res.json());
        const content = data.message?.content ?? "";
        const toolCalls = this.parseToolCalls(content);
        return {
            content,
            toolCalls: toolCalls.length > 0 ? toolCalls : undefined,
            usage: {
                promptTokens: data.prompt_eval_count ?? 0,
                completionTokens: data.eval_count ?? 0,
                totalTokens: (data.prompt_eval_count ?? 0) + (data.eval_count ?? 0),
            },
            finishReason: toolCalls.length > 0 ? "tool_calls" : "stop",
            model: this.config.model,
            latencyMs: Date.now() - startMs,
        };
    }
    /**
     * Ollama doesn't natively support function calling for all models.
     * We parse structured JSON action blocks from the response text.
     * Format expected:
     * ```json
     * {"action": "tool_name", "params": {...}}
     * ```
     */
    parseToolCalls(content) {
        const calls = [];
        // Match JSON blocks with action field
        const jsonPattern = /\{[\s\S]*?"action"\s*:\s*"([^"]+)"[\s\S]*?\}/g;
        let match;
        while ((match = jsonPattern.exec(content)) !== null) {
            try {
                const parsed = JSON.parse(match[0]);
                if (parsed.action) {
                    calls.push({
                        id: `call_${Date.now()}_${calls.length}`,
                        name: parsed.action,
                        arguments: parsed.params ?? {},
                    });
                }
            }
            catch {
                // Not valid JSON, skip
            }
        }
        return calls;
    }
}
exports.OllamaAdapter = OllamaAdapter;
//# sourceMappingURL=ollama-adapter.js.map