"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.callGeminiChat = callGeminiChat;
exports.streamGeminiChat = streamGeminiChat;
const genai_1 = require("@google/genai");
const GEMINI_API_KEY = process.env.GOOGLE_API_KEY || "";
const GEMINI_MODEL = process.env.VIBN_CHAT_MODEL || "gemini-3.1-pro-preview";
// Add a clear visual log so we always know exactly which model is active in the terminal
console.log(`[GeminiChat Runner] Initialized — Model: ${GEMINI_MODEL}`);
if (!GEMINI_API_KEY) {
    console.warn(`[GeminiChat] WARNING: GOOGLE_API_KEY is not set. Chat stream will fail with 403 Forbidden.`);
}
const ai = new genai_1.GoogleGenAI({ apiKey: GEMINI_API_KEY });
function toGeminiContents(messages) {
    const contents = [];
    for (const msg of messages) {
        if (msg.role === "user") {
            contents.push({ role: "user", parts: [{ text: msg.content }] });
        }
        else if (msg.role === "assistant") {
            const parts = [];
            if (msg.content)
                parts.push({ text: msg.content });
            if (msg.toolCalls?.length) {
                for (const tc of msg.toolCalls) {
                    const part = {
                        functionCall: { name: tc.name, args: tc.args },
                    };
                    if (tc.thoughtSignature) {
                        part.thoughtSignature = tc.thoughtSignature;
                    }
                    parts.push(part);
                }
            }
            if (parts.length)
                contents.push({ role: "model", parts });
        }
        else if (msg.role === "tool") {
            const part = {
                functionResponse: {
                    name: msg.toolName || "unknown",
                    response: { name: msg.toolName || "unknown", content: msg.content },
                },
            };
            const last = contents[contents.length - 1];
            if (last?.role === "user") {
                last.parts.push(part);
            }
            else {
                contents.push({ role: "user", parts: [part] });
            }
        }
    }
    return contents;
}
function toGeminiFunctions(tools) {
    if (!tools.length)
        return undefined;
    return [
        {
            functionDeclarations: tools.map((t) => ({
                name: t.name,
                description: t.description,
                parameters: t.parameters,
            })),
        },
    ];
}
async function callGeminiChat(opts) {
    try {
        const config = {
            temperature: opts.temperature ?? 0.7,
            maxOutputTokens: 8192,
        };
        if (opts.systemPrompt) {
            config.systemInstruction = opts.systemPrompt;
        }
        const fns = toGeminiFunctions(opts.tools ?? []);
        if (fns)
            config.tools = fns;
        console.log("\n========================================================");
        console.log("➡️ [GEMINI API REQUEST]");
        console.log("========================================================");
        console.log(`System Prompt: ${config.systemInstruction ? config.systemInstruction.slice(0, 1000) + "..." : "None"}`);
        console.log("Contents Payload:", JSON.stringify(toGeminiContents(opts.messages), null, 2));
        console.log("========================================================\n");
        const response = await ai.models.generateContent({
            model: GEMINI_MODEL,
            contents: toGeminiContents(opts.messages),
            config,
        });
        console.log("\n========================================================");
        console.log("⬅️ [GEMINI API RESPONSE]");
        console.log("========================================================");
        console.log("Raw Candidates:", JSON.stringify(response.candidates, null, 2));
        console.log("========================================================\n");
        let text = "";
        let thoughts = "";
        const toolCalls = [];
        const parts = response.candidates?.[0]?.content?.parts ?? [];
        for (const part of parts) {
            if (part.text) {
                if (part.thought)
                    thoughts += part.text;
                else
                    text += part.text;
            }
            if (part.functionCall) {
                toolCalls.push({
                    id: `tc-${Date.now()}-${Math.random().toString(36).slice(2)}`,
                    name: part.functionCall.name || "",
                    args: part.functionCall.args ?? {},
                    thoughtSignature: part.thoughtSignature,
                });
            }
        }
        return {
            text,
            thoughts,
            toolCalls,
            finishReason: response.candidates?.[0]?.finishReason,
        };
    }
    catch (error) {
        return {
            text: "",
            thoughts: "",
            toolCalls: [],
            error: `GoogleGenAI error: ${error instanceof Error ? error.message : String(error)}`,
        };
    }
}
async function* streamGeminiChat(opts) {
    try {
        const config = {
            temperature: opts.temperature ?? 0.7,
            maxOutputTokens: 8192,
        };
        if (opts.systemPrompt) {
            config.systemInstruction = opts.systemPrompt;
        }
        const fns = toGeminiFunctions(opts.tools ?? []);
        if (fns)
            config.tools = fns;
        console.log("\n========================================================");
        console.log("➡️ [GEMINI STREAM REQUEST]");
        console.log("========================================================");
        console.log(`System Prompt: ${config.systemInstruction ? config.systemInstruction.slice(0, 1000) + "..." : "None"}`);
        console.log("Contents Payload:", JSON.stringify(toGeminiContents(opts.messages), null, 2));
        console.log("========================================================\n");
        const streamResult = await ai.models.generateContentStream({
            model: GEMINI_MODEL,
            contents: toGeminiContents(opts.messages),
            config,
        });
        for await (const chunk of streamResult) {
            const parts = chunk.candidates?.[0]?.content?.parts ?? [];
            for (const part of parts) {
                if (part.text) {
                    yield part.thought
                        ? { type: "thinking", text: part.text }
                        : { type: "text", text: part.text };
                }
            }
        }
        yield { type: "done" };
    }
    catch (error) {
        yield {
            type: "error",
            error: `GoogleGenAI error: ${error instanceof Error ? error.message : String(error)}`,
        };
    }
}
