"use strict";
// src/test_catalog_agent_executor.ts
// Validates CatalogAgentExecutor: loads real persona bodies, guards traversal,
// builds a persona system prompt, and routes the task through an injected Brain.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const CatalogAgentExecutor_1 = require("./orchestrator/CatalogAgentExecutor");
let passed = 0;
let failed = 0;
function check(label, ok, detail) {
    if (ok) {
        console.log(`  ✓ ${label}`);
        passed++;
    }
    else {
        console.error(`  ✗ ${label}${detail ? ` — ${detail}` : ''}`);
        failed++;
    }
}
/** Mock Brain — captures the prompts it was called with, returns a canned reply. */
class MockBrain {
    lastSystem = '';
    lastUser = '';
    calls = 0;
    async think(systemPrompt, userMessage) {
        this.calls++;
        this.lastSystem = systemPrompt;
        this.lastUser = userMessage;
        return `MOCK_REPLY for: ${userMessage.slice(0, 40)}`;
    }
}
/** Pick a real catalog agent id that exists on disk, for the happy path. */
function firstRealAgentId() {
    const root = path.join(process.cwd(), '.catalog', 'agents');
    if (!fs.existsSync(root))
        return null;
    for (const entry of fs.readdirSync(root)) {
        if (entry.startsWith('.') || entry.startsWith('test-'))
            continue;
        if (fs.existsSync(path.join(root, entry, 'AGENT.md')))
            return entry;
    }
    return null;
}
async function main() {
    console.log('test_catalog_agent_executor: starting\n');
    const brain = new MockBrain();
    const exec = new CatalogAgentExecutor_1.CatalogAgentExecutor(brain);
    const realId = firstRealAgentId();
    console.log('[1] loadDefinition — real agent');
    check('a real catalog agent id was found', realId !== null, 'no .catalog/agents/*/AGENT.md on disk');
    if (realId) {
        const def = exec.loadDefinition(realId);
        check('loadDefinition returns non-null', def !== null);
        if (def) {
            check('definition has id', def.id === realId);
            check('definition has non-empty name', !!def.name);
            check('definition has non-empty role', !!def.role);
            check('definition has non-empty body', def.body.length > 0, `body len ${def.body.length}`);
            check('sourcePath ends with AGENT.md', def.sourcePath.endsWith('AGENT.md'));
        }
    }
    console.log('\n[2] loadDefinition — unknown id returns null');
    check('unknown id → null', exec.loadDefinition('__does_not_exist__') === null);
    console.log('\n[3] path traversal is rejected');
    check('../ traversal → null', exec.loadDefinition('../../etc/passwd') === null);
    check('absolute-ish id → null', exec.loadDefinition('/etc') === null);
    check('empty id → null', exec.loadDefinition('') === null);
    console.log('\n[4] buildSystemPrompt includes persona');
    if (realId) {
        const def = exec.loadDefinition(realId);
        const sys = exec.buildSystemPrompt(def);
        check('system prompt contains name', sys.includes(def.name));
        check('system prompt contains role', sys.includes(def.role));
        check('system prompt contains body', sys.includes(def.body.slice(0, 30)));
        check('system prompt has AGENT DEFINITION marker', sys.includes('AGENT DEFINITION'));
    }
    console.log('\n[5] execute — happy path routes through Brain');
    if (realId) {
        const res = await exec.execute(realId, 'summarize your role in one line');
        check('execute ok', res.ok === true, res.error);
        check('execute returns output', !!res.output && res.output.includes('MOCK_REPLY'));
        check('brain was called once', brain.calls === 1, `calls=${brain.calls}`);
        check('brain received persona system prompt', brain.lastSystem.includes('OpenLife catalog agent'));
    }
    console.log('\n[6] execute — error contracts');
    const notFound = await exec.execute('__nope__', 'do something');
    check('unknown agent → ok:false, error:agent_not_found', notFound.ok === false && notFound.error === 'agent_not_found');
    if (realId) {
        const emptyTask = await exec.execute(realId, '   ');
        check('empty task → ok:false, error:task_required', emptyTask.ok === false && emptyTask.error === 'task_required');
    }
    console.log('\n[7] Phase 4 — memory injection (when memory is wired)');
    if (realId) {
        class MockMemory {
            reply;
            lastQuery = '';
            constructor(reply) {
                this.reply = reply;
            }
            async search(q) { this.lastQuery = q; return this.reply; }
        }
        const mem = new MockMemory('- [local] user prefers concise answers');
        const brain2 = new MockBrain();
        const execWithMem = new CatalogAgentExecutor_1.CatalogAgentExecutor(brain2, mem);
        const res = await execWithMem.execute(realId, 'summarize your role');
        check('execute ok with memory', res.ok === true, res.error);
        check('memory was queried with the task', mem.lastQuery === 'summarize your role');
        check('brain user message includes RELEVANT MEMORY block', brain2.lastUser.includes('RELEVANT MEMORY'));
        check('brain user message includes the memory content', brain2.lastUser.includes('concise answers'));
        check('brain user message still includes the task', brain2.lastUser.includes('summarize your role'));
        // Empty memory → task passes through unchanged
        const emptyMem = new MockMemory('');
        const brain3 = new MockBrain();
        const execEmpty = new CatalogAgentExecutor_1.CatalogAgentExecutor(brain3, emptyMem);
        await execEmpty.execute(realId, 'do the thing');
        check('empty memory leaves task unchanged', brain3.lastUser === 'do the thing');
        // Memory that throws → fails open, task still runs
        class ThrowingMemory {
            async search() { throw new Error('memory down'); }
        }
        const brain4 = new MockBrain();
        const execThrow = new CatalogAgentExecutor_1.CatalogAgentExecutor(brain4, new ThrowingMemory());
        const resThrow = await execThrow.execute(realId, 'resilient task');
        check('memory failure does not block execution', resThrow.ok === true);
        check('task survives memory failure', brain4.lastUser === 'resilient task');
    }
    console.log('');
    console.log(`Results: ${passed} passed, ${failed} failed`);
    if (failed > 0) {
        console.error('TEST_CATALOG_AGENT_EXECUTOR_FAIL');
        process.exit(1);
    }
    console.log('✅ test_catalog_agent_executor: all checks passed');
}
main().catch(err => { console.error(err); process.exit(1); });
