"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AgentBrain = void 0;
const prompts_1 = require("./prompts");
const state_1 = require("./state");
/**
 * Agent Brain — The ReAct (Reason + Act) reasoning engine.
 *
 * This is the core loop:
 *   1. Build context (system prompt + history)
 *   2. Send to LLM
 *   3. Parse the THOUGHT + ACTION from the response
 *   4. Execute the tool
 *   5. Append the observation to history
 *   6. Loop until TASK_COMPLETE, TASK_FAILED, or max iterations
 */
class AgentBrain {
    llm;
    tools;
    constructor(llm, tools) {
        this.llm = llm;
        this.tools = tools;
    }
    /**
     * Run one reasoning step: LLM produces a thought + action.
     */
    async think(state) {
        const messages = this.buildMessages(state);
        const options = {
            temperature: 0.1,
            maxTokens: 2048,
        };
        // Removed native tool calling logic because GitHub Models' gpt-4o-mini often omits tool calls.
        // We will rely entirely on the text-based THOUGHT/ACTION JSON format.
        let response;
        try {
            response = await this.llm.chat(messages, options);
        }
        catch (err) {
            const errorMsg = err instanceof Error ? err.message : String(err);
            const newState = (0, state_1.appendError)(state, {
                message: `LLM call failed: ${errorMsg}`,
                category: "LLM_ERROR",
            });
            return {
                action: {
                    type: "task_failed",
                    thought: `LLM call failed: ${errorMsg}`,
                    reason: errorMsg,
                },
                state: newState,
            };
        }
        // Parse text-based THOUGHT + ACTION format (for Ollama and fallback)
        const action = this.parseTextResponse(response.content);
        const newState = (0, state_1.appendHistory)(state, {
            role: "thought",
            content: action.thought,
        });
        return { action, state: newState };
    }
    /**
     * Execute a tool call and return the observation.
     */
    async act(action, state) {
        if (!action.toolName) {
            return {
                observation: "No tool specified.",
                success: false,
                state,
            };
        }
        if (action.toolName === "INVALID_ACTION") {
            const observation = (0, prompts_1.buildObservationMessage)("INVALID_ACTION", false, "You did not provide a valid JSON action block or native tool call. You MUST provide exactly ONE action.");
            const newState = (0, state_1.appendHistory)(state, {
                role: "observation",
                content: observation,
                toolName: "INVALID_ACTION",
            });
            return {
                observation,
                success: false,
                state: (0, state_1.appendError)(newState, {
                    message: "Invalid action format",
                    stepId: "parse",
                }),
            };
        }
        const result = await this.tools.execute(action.toolName, action.toolParams ?? {}, state);
        const observation = (0, prompts_1.buildObservationMessage)(action.toolName, result.success, result.output || result.error || "No output");
        const newState = (0, state_1.appendHistory)(state, {
            role: "observation",
            content: observation,
            toolName: action.toolName,
            toolParams: action.toolParams,
        });
        return {
            observation,
            success: result.success,
            state: result.success
                ? newState
                : (0, state_1.appendError)(newState, {
                    message: result.error ?? `Tool ${action.toolName} failed`,
                    stepId: action.toolName,
                }),
        };
    }
    /**
     * Build the full message array for the LLM.
     */
    buildMessages(state) {
        const messages = [];
        // System prompt
        messages.push({
            role: "system",
            content: (0, prompts_1.buildSystemPrompt)(this.tools, state.environment.os, state.environment.route, false),
        });
        // User's goal
        messages.push({
            role: "user",
            content: (0, prompts_1.buildPlanningPrompt)(state.userGoal),
        });
        // History (thoughts, actions, observations)
        for (const entry of state.history) {
            if (entry.role === "thought") {
                messages.push({
                    role: "assistant",
                    content: entry.content,
                });
            }
            else if (entry.role === "observation") {
                messages.push({
                    role: "user",
                    content: entry.content,
                });
            }
            else if (entry.role === "error") {
                messages.push({
                    role: "user",
                    content: (0, prompts_1.buildReflectionPrompt)(entry.toolName ?? "unknown", entry.content, state.iterationCount),
                });
            }
            else if (entry.role === "system") {
                messages.push({
                    role: "user",
                    content: `[System] ${entry.content}`,
                });
            }
        }
        return messages;
    }
    /**
     * Parse the THOUGHT + ACTION text format from Ollama responses.
     */
    parseTextResponse(text) {
        const thoughtMatch = text.match(/THOUGHT:\s*([\s\S]*?)(?=ACTION:|$)/i);
        const actionMatch = text.match(/ACTION:\s*(\{[\s\S]*?\})\s*$/im);
        const thought = thoughtMatch
            ? thoughtMatch[1].trim()
            : text.split("\n")[0] || "Thinking...";
        if (!actionMatch) {
            // Try to find any JSON block in the response
            const jsonMatch = text.match(/\{[\s\S]*?"action"\s*:[\s\S]*?\}/);
            if (jsonMatch) {
                try {
                    const parsed = JSON.parse(jsonMatch[0]);
                    return this.classifyAction(thought, parsed);
                }
                catch {
                    // Fall through
                }
            }
            // No parseable action — treat as thinking aloud
            return {
                type: "tool_call",
                thought,
                toolName: "INVALID_ACTION",
                toolParams: {},
            };
        }
        try {
            const parsed = JSON.parse(actionMatch[1]);
            return this.classifyAction(thought, parsed);
        }
        catch {
            return {
                type: "tool_call",
                thought,
                toolName: "INVALID_ACTION",
                toolParams: { error: `Invalid JSON in ACTION block: ${actionMatch[1]}` },
            };
        }
    }
    classifyAction(thought, parsed) {
        if (parsed.action === "TASK_COMPLETE") {
            return {
                type: "task_complete",
                thought,
                summary: String(parsed.params?.summary ?? "") || thought,
            };
        }
        if (parsed.action === "TASK_FAILED") {
            return {
                type: "task_failed",
                thought,
                reason: String(parsed.params?.reason ?? "") || thought,
            };
        }
        return {
            type: "tool_call",
            thought,
            toolName: parsed.action,
            toolParams: parsed.params ?? {},
        };
    }
}
exports.AgentBrain = AgentBrain;
//# sourceMappingURL=brain.js.map