"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.runAgent = runAgent;
const genai_1 = require("@google/genai");
const tools_1 = require("./tools");
const job_store_1 = require("./job-store");
const MAX_TURNS = 40; // safety cap — prevents infinite loops
/**
 * Core Gemini agent loop.
 *
 * Sends the task to Gemini with the agent's system prompt and tools,
 * then loops: execute tool calls → send results back → repeat until
 * the model stops calling tools or MAX_TURNS is reached.
 */
async function runAgent(job, config, task, ctx) {
    const apiKey = process.env.GOOGLE_API_KEY;
    if (!apiKey) {
        throw new Error('GOOGLE_API_KEY environment variable is not set');
    }
    const genai = new genai_1.GoogleGenAI({ apiKey });
    // Build Gemini function declarations from our tool definitions
    const functionDeclarations = config.tools.map(tool => ({
        name: tool.name,
        description: tool.description,
        parameters: tool.parameters
    }));
    const tools = functionDeclarations.length > 0
        ? [{ functionDeclarations }]
        : [];
    const model = genai.models;
    // Build conversation history
    const history = [];
    // Initial user message
    let currentMessage = {
        role: 'user',
        parts: [{ text: task }]
    };
    let toolCallCount = 0;
    let turn = 0;
    let finalText = '';
    (0, job_store_1.updateJob)(job.id, { status: 'running', progress: `Starting ${config.name} agent...` });
    while (turn < MAX_TURNS) {
        turn++;
        // Add current message to history
        history.push(currentMessage);
        // Call Gemini
        const response = await model.generateContent({
            model: config.model || 'gemini-2.0-flash',
            contents: history,
            config: {
                systemInstruction: config.systemPrompt,
                tools: tools.length > 0 ? tools : undefined,
                temperature: 0.2,
                maxOutputTokens: 8192
            }
        });
        const candidate = response.candidates?.[0];
        if (!candidate) {
            throw new Error('No response from Gemini');
        }
        // Add model response to history
        const modelContent = {
            role: 'model',
            parts: candidate.content?.parts || []
        };
        history.push(modelContent);
        // Extract function calls from the response
        const functionCalls = candidate.content?.parts?.filter(p => p.functionCall) ?? [];
        if (functionCalls.length === 0) {
            // No tool calls — the agent is done
            finalText = candidate.content?.parts
                ?.filter(p => p.text)
                .map(p => p.text)
                .join('') ?? '';
            break;
        }
        // Execute all tool calls
        const toolResultParts = [];
        for (const part of functionCalls) {
            const call = part.functionCall;
            const callName = call.name ?? 'unknown';
            const callArgs = (call.args ?? {});
            toolCallCount++;
            (0, job_store_1.updateJob)(job.id, {
                progress: `Turn ${turn}: calling ${callName}...`,
                toolCalls: [...(job.toolCalls || []), {
                        turn,
                        tool: callName,
                        args: callArgs,
                        timestamp: new Date().toISOString()
                    }]
            });
            let result;
            try {
                result = await (0, tools_1.executeTool)(callName, callArgs, ctx);
            }
            catch (err) {
                result = { error: err instanceof Error ? err.message : String(err) };
            }
            toolResultParts.push({
                functionResponse: {
                    name: callName,
                    response: { result }
                }
            });
        }
        // Next turn: send tool results back to the model
        currentMessage = {
            role: 'user',
            parts: toolResultParts
        };
    }
    if (turn >= MAX_TURNS && !finalText) {
        finalText = `Agent reached the ${MAX_TURNS}-turn safety limit. Last tool call count: ${toolCallCount}.`;
    }
    return { finalText, toolCallCount, turns: turn };
}
