"use strict";
/**
 * GoalCompiler — decomposes a high-level goal (from /goal) into concrete,
 * executable mission drafts.
 *
 * Phase 2 (Goal→Mission Bridge) of the autonomous-agent milestone.
 *
 * The daemon's QueueScheduler executes missions, but missions have to come
 * from somewhere. This compiler is the bridge: it reads the user's stated
 * goal (optionally framed by their longer-term dream) and asks the Brain to
 * break it into 1–N missions, each with explicit acceptance criteria and a
 * bounded step budget.
 *
 * Cost note: uses Brain.thinkFast() (the cheap tier) rather than a dedicated
 * auxiliary credential. OpenLife's Brain is stateless per call — there is no
 * conversation cache to pollute (unlike Hermes), so the only thing that
 * matters is using a cheap model, which thinkFast already does. A separate
 * ModelManager.getAuxiliary() is deferred until a real need appears.
 *
 * Safety: every draft is validated before it can become a mission. A draft
 * without acceptance criteria would produce a mission with no stopping
 * condition, so such drafts are dropped, not enqueued.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.GoalCompiler = void 0;
const Brain_1 = require("./Brain");
const SquadCreator_1 = require("./SquadCreator");
class GoalCompiler {
    brain;
    maxDrafts;
    maxStepsCap;
    constructor(opts = {}) {
        this.brain = opts.brain || new Brain_1.Brain();
        this.maxDrafts = opts.maxDrafts ?? 5;
        this.maxStepsCap = opts.maxStepsCap ?? 12;
    }
    async compile(goal, dream) {
        const trimmed = (goal || '').trim();
        if (!trimmed) {
            return { ok: false, drafts: [], source: 'error', error: 'empty_goal' };
        }
        // No provider configured → deterministic heuristic so the bridge still
        // produces *something* runnable instead of silently stalling.
        if (!this.brain.isAnyProviderAvailable()) {
            return { ok: true, drafts: [this.heuristicDraft(trimmed)], source: 'heuristic' };
        }
        let raw;
        try {
            raw = await this.brain.thinkFast(this.systemPrompt(), this.userPrompt(trimmed, dream));
        }
        catch (err) {
            // Fall back to heuristic rather than leaving the goal uncompiled.
            return {
                ok: true,
                drafts: [this.heuristicDraft(trimmed)],
                source: 'heuristic',
                error: `llm_failed: ${err instanceof Error ? err.message : String(err)}`,
            };
        }
        const parsed = (0, SquadCreator_1.extractFirstJson)(raw);
        const rawMissions = parsed && Array.isArray(parsed.missions) ? parsed.missions : [];
        const drafts = this.validateDrafts(rawMissions);
        if (drafts.length === 0) {
            // LLM responded but produced nothing usable — heuristic keeps the
            // bridge moving instead of dropping the goal on the floor.
            return { ok: true, drafts: [this.heuristicDraft(trimmed)], source: 'heuristic', error: 'no_valid_drafts' };
        }
        return { ok: true, drafts, source: 'llm' };
    }
    /** Validate + sanitize raw LLM mission objects into MissionDrafts. */
    validateDrafts(rawMissions) {
        const out = [];
        for (const m of rawMissions) {
            if (out.length >= this.maxDrafts)
                break;
            if (!m || typeof m !== 'object')
                continue;
            const obj = m;
            const goal = typeof obj.goal === 'string' ? obj.goal.trim() : '';
            if (!goal)
                continue;
            const acRaw = Array.isArray(obj.acceptanceCriteria) ? obj.acceptanceCriteria : [];
            const acceptanceCriteria = acRaw
                .filter((a) => typeof a === 'string' && a.trim().length > 0)
                .map((a) => a.trim());
            // A mission with no acceptance criteria has no stopping condition — drop it.
            if (acceptanceCriteria.length === 0)
                continue;
            const rawSteps = typeof obj.maxSteps === 'number' ? obj.maxSteps : 5;
            const maxSteps = Math.max(1, Math.min(this.maxStepsCap, Math.floor(rawSteps)));
            const rationale = typeof obj.rationale === 'string' ? obj.rationale.trim() : undefined;
            out.push({ goal, acceptanceCriteria, maxSteps, rationale });
        }
        return out;
    }
    heuristicDraft(goal) {
        return {
            goal,
            acceptanceCriteria: [`The goal "${goal.slice(0, 120)}" is satisfied and verified.`],
            maxSteps: Math.min(this.maxStepsCap, 8),
            rationale: 'heuristic: no LLM available or no valid drafts — goal passed through verbatim',
        };
    }
    systemPrompt() {
        return [
            'You are a planning compiler for an autonomous agent.',
            'Break the user GOAL into 1 to ' + this.maxDrafts + ' concrete, independently-runnable missions.',
            'Each mission MUST have testable acceptance criteria and a small step budget.',
            'Do NOT invent missions unrelated to the goal. Prefer fewer, well-scoped missions.',
            'Respond with ONLY a JSON object of this exact shape (no prose, no markdown fences):',
            '{"missions":[{"goal":"<concrete mission>","acceptanceCriteria":["<criterion>"],"maxSteps":<int 1-' + this.maxStepsCap + '>,"rationale":"<why>"}]}',
        ].join('\n');
    }
    userPrompt(goal, dream) {
        const lines = [`GOAL: ${goal}`];
        if (dream && dream.trim())
            lines.push(`DREAM (longer-term vision for context): ${dream.trim()}`);
        lines.push('', 'Produce the missions JSON now.');
        return lines.join('\n');
    }
}
exports.GoalCompiler = GoalCompiler;
