"use strict";
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;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const agents_1 = require("../../utils/agents");
const knowledge_graph_1 = require("../../utils/knowledge-graph");
const vector_store_1 = require("../../utils/vector-store");
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
const os = __importStar(require("os"));
const path = __importStar(require("path"));
const fs = __importStar(require("fs"));
const uuid_1 = require("uuid");
describe('Agents', () => {
    let db;
    let knowledgeGraph;
    let vectorStore;
    let tempDbPath;
    let testSessionId;
    beforeEach(() => {
        tempDbPath = path.join(os.tmpdir(), `test-agents-${Date.now()}.db`);
        db = new better_sqlite3_1.default(tempDbPath);
        // Create tables
        db.exec(`
      CREATE TABLE IF NOT EXISTS sessions (
        id TEXT PRIMARY KEY,
        name TEXT,
        description TEXT,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
      );
      
      CREATE TABLE IF NOT EXISTS context_items (
        id TEXT PRIMARY KEY,
        session_id TEXT NOT NULL,
        key TEXT NOT NULL,
        value TEXT NOT NULL,
        category TEXT,
        priority TEXT DEFAULT 'normal',
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        FOREIGN KEY (session_id) REFERENCES sessions(id)
      );
      
      CREATE TABLE IF NOT EXISTS entities (
        id TEXT PRIMARY KEY,
        session_id TEXT NOT NULL,
        type TEXT NOT NULL,
        name TEXT NOT NULL,
        attributes TEXT,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        FOREIGN KEY (session_id) REFERENCES sessions(id)
      );
      
      CREATE TABLE IF NOT EXISTS relations (
        id TEXT PRIMARY KEY,
        session_id TEXT NOT NULL,
        subject_id TEXT NOT NULL,
        predicate TEXT NOT NULL,
        object_id TEXT NOT NULL,
        confidence REAL DEFAULT 1.0,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        FOREIGN KEY (session_id) REFERENCES sessions(id),
        FOREIGN KEY (subject_id) REFERENCES entities(id),
        FOREIGN KEY (object_id) REFERENCES entities(id)
      );
      
      CREATE TABLE IF NOT EXISTS embeddings (
        id TEXT PRIMARY KEY,
        content TEXT NOT NULL,
        embedding TEXT NOT NULL,
        metadata TEXT,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
      );
    `);
        knowledgeGraph = new knowledge_graph_1.KnowledgeGraphManager(db);
        vectorStore = new vector_store_1.VectorStore(db);
        // Create test session
        testSessionId = (0, uuid_1.v4)();
        db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(testSessionId, 'Test Session');
    });
    afterEach(() => {
        db.close();
        try {
            fs.unlinkSync(tempDbPath);
        }
        catch (_e) {
            // Ignore
        }
    });
    describe('AnalyzerAgent', () => {
        let analyzerAgent;
        beforeEach(() => {
            analyzerAgent = new agents_1.AnalyzerAgent(db, knowledgeGraph, vectorStore);
            // Add test data
            const items = [
                { key: 'task_1', value: 'Implement authentication', category: 'task', priority: 'high' },
                { key: 'task_2', value: 'Write unit tests', category: 'task', priority: 'normal' },
                { key: 'decision_1', value: 'Use JWT tokens', category: 'decision', priority: 'high' },
                {
                    key: 'progress_1',
                    value: 'Completed login form',
                    category: 'progress',
                    priority: 'normal',
                },
                {
                    key: 'note_1',
                    value: 'Remember to add rate limiting',
                    category: 'note',
                    priority: 'high',
                },
            ];
            for (const item of items) {
                db.prepare('INSERT INTO context_items (id, session_id, key, value, category, priority) VALUES (?, ?, ?, ?, ?, ?)').run((0, uuid_1.v4)(), testSessionId, item.key, item.value, item.category, item.priority);
            }
        });
        it('should analyze patterns in context', async () => {
            const task = {
                id: (0, uuid_1.v4)(),
                type: 'analyze',
                input: {
                    analysisType: 'patterns',
                    sessionId: testSessionId,
                },
            };
            const result = await analyzerAgent.process(task);
            expect(result.taskId).toBe(task.id);
            expect(result.agentType).toBe('analyzer');
            expect(result.confidence).toBeGreaterThan(0);
            expect(result.output.patterns).toBeDefined();
            expect(result.output.patterns.categoryDistribution).toBeDefined();
            expect(result.output.patterns.priorityDistribution).toBeDefined();
            expect(result.output.itemCount).toBe(5);
        });
        it('should analyze relationships', async () => {
            // Add some entities
            const entity1 = knowledgeGraph.createEntity(testSessionId, 'class', 'AuthService');
            const entity2 = knowledgeGraph.createEntity(testSessionId, 'class', 'TokenManager');
            knowledgeGraph.createRelation(testSessionId, entity1.id, 'uses', entity2.id);
            const task = {
                id: (0, uuid_1.v4)(),
                type: 'analyze',
                input: {
                    analysisType: 'relationships',
                    sessionId: testSessionId,
                },
            };
            const result = await analyzerAgent.process(task);
            expect(result.output.analysis).toBeDefined();
            expect(result.output.analysis.entityCount).toBeGreaterThan(0);
            expect(result.output.recommendations).toBeDefined();
        });
        it('should analyze trends', async () => {
            const task = {
                id: (0, uuid_1.v4)(),
                type: 'analyze',
                input: {
                    analysisType: 'trends',
                    sessionId: testSessionId,
                    timeframe: '-7 days',
                },
            };
            const result = await analyzerAgent.process(task);
            expect(result.output.trends).toBeDefined();
            expect(result.output.trends.activityTrend).toBeDefined();
            expect(result.output.summary).toBeDefined();
        });
        it('should perform comprehensive analysis', async () => {
            const task = {
                id: (0, uuid_1.v4)(),
                type: 'analyze',
                input: {
                    analysisType: 'comprehensive',
                    sessionId: testSessionId,
                },
            };
            const result = await analyzerAgent.process(task);
            expect(result.output.patterns).toBeDefined();
            expect(result.output.relationships).toBeDefined();
            expect(result.output.trends).toBeDefined();
            expect(result.output.overallInsights).toBeDefined();
            expect(result.confidence).toBe(0.9);
        });
        it('should handle unknown analysis type', async () => {
            const task = {
                id: (0, uuid_1.v4)(),
                type: 'analyze',
                input: {
                    analysisType: 'unknown',
                    sessionId: testSessionId,
                },
            };
            const result = await analyzerAgent.process(task);
            expect(result.output.error).toBeDefined();
            expect(result.confidence).toBe(0);
        });
        it('should filter by categories', async () => {
            const task = {
                id: (0, uuid_1.v4)(),
                type: 'analyze',
                input: {
                    analysisType: 'patterns',
                    sessionId: testSessionId,
                    categories: ['task'],
                },
            };
            const result = await analyzerAgent.process(task);
            expect(result.output.itemCount).toBe(2); // Only 2 tasks
            expect(Object.keys(result.output.patterns.categoryDistribution)).toEqual(['task']);
        });
    });
    describe('SynthesizerAgent', () => {
        let synthesizerAgent;
        beforeEach(() => {
            synthesizerAgent = new agents_1.SynthesizerAgent(db, vectorStore);
            // Add test data
            const items = [
                {
                    key: 'task_1',
                    value: 'Implement authentication with OAuth2',
                    category: 'task',
                    priority: 'high',
                },
                {
                    key: 'task_2',
                    value: 'Add rate limiting to API endpoints',
                    category: 'task',
                    priority: 'high',
                },
                {
                    key: 'decision_1',
                    value: 'Use Redis for session storage',
                    category: 'decision',
                    priority: 'high',
                },
                {
                    key: 'progress_1',
                    value: 'Completed user registration flow',
                    category: 'progress',
                    priority: 'normal',
                },
            ];
            for (const item of items) {
                db.prepare('INSERT INTO context_items (id, session_id, key, value, category, priority) VALUES (?, ?, ?, ?, ?, ?)').run((0, uuid_1.v4)(), testSessionId, item.key, item.value, item.category, item.priority);
            }
        });
        it('should create summary', async () => {
            const task = {
                id: (0, uuid_1.v4)(),
                type: 'synthesize',
                input: {
                    synthesisType: 'summary',
                    sessionId: testSessionId,
                    maxLength: 1000,
                },
            };
            const result = await synthesizerAgent.process(task);
            expect(result.output.summary).toBeDefined();
            expect(result.output.summary).toContain('Context Summary');
            expect(result.output.itemCount).toBe(4);
            expect(result.output.categories).toContain('task');
            expect(result.output.categories).toContain('decision');
        });
        it('should create summary with category filter', async () => {
            const task = {
                id: (0, uuid_1.v4)(),
                type: 'synthesize',
                input: {
                    synthesisType: 'summary',
                    sessionId: testSessionId,
                    categories: ['task'],
                },
            };
            const result = await synthesizerAgent.process(task);
            expect(result.output.summary).toContain('Current Tasks');
            expect(result.output.categories).toEqual(['task']);
        });
        it('should merge insights', async () => {
            const insights = [
                { patterns: { keywords: ['auth', 'security'] }, themes: ['authentication'] },
                { patterns: { keywords: ['api', 'rate'] }, themes: ['performance'] },
            ];
            const task = {
                id: (0, uuid_1.v4)(),
                type: 'synthesize',
                input: {
                    synthesisType: 'merge',
                    insights,
                },
            };
            const result = await synthesizerAgent.process(task);
            expect(result.output.patterns).toBeDefined();
            expect(result.output.overallThemes).toContain('authentication');
            expect(result.output.overallThemes).toContain('performance');
        });
        it('should generate recommendations', async () => {
            const analysisResults = {
                highPriorityCount: 10,
                staleTasks: true,
                contextSize: 1500,
            };
            const task = {
                id: (0, uuid_1.v4)(),
                type: 'synthesize',
                input: {
                    synthesisType: 'recommendations',
                    analysisResults,
                },
            };
            const result = await synthesizerAgent.process(task);
            expect(result.output.immediate).toBeDefined();
            expect(result.output.shortTerm).toBeDefined();
            expect(result.output.longTerm).toBeDefined();
            expect(result.output.warnings).toBeDefined();
            expect(result.output.warnings).toContain('Context size is large - consider compaction');
        });
        it('should handle unknown synthesis type', async () => {
            const task = {
                id: (0, uuid_1.v4)(),
                type: 'synthesize',
                input: {
                    synthesisType: 'unknown',
                },
            };
            const result = await synthesizerAgent.process(task);
            expect(result.output.error).toBeDefined();
            expect(result.confidence).toBe(0);
        });
    });
    describe('AgentCoordinator', () => {
        let coordinator;
        let analyzerAgent;
        let synthesizerAgent;
        beforeEach(() => {
            coordinator = new agents_1.AgentCoordinator();
            analyzerAgent = new agents_1.AnalyzerAgent(db, knowledgeGraph, vectorStore);
            synthesizerAgent = new agents_1.SynthesizerAgent(db, vectorStore);
            coordinator.registerAgent(analyzerAgent);
            coordinator.registerAgent(synthesizerAgent);
        });
        it('should delegate to appropriate agent', async () => {
            const task = {
                id: (0, uuid_1.v4)(),
                type: 'analyze',
                input: {
                    analysisType: 'patterns',
                    sessionId: testSessionId,
                },
            };
            const results = await coordinator.delegate(task);
            expect(results.length).toBe(1);
            expect(results[0].agentType).toBe('analyzer');
        });
        it('should handle no suitable agent', async () => {
            const task = {
                id: (0, uuid_1.v4)(),
                type: 'unknown',
                input: {},
            };
            const results = await coordinator.delegate(task);
            expect(results.length).toBe(1);
            expect(results[0].output.error).toBeDefined();
            expect(results[0].agentType).toBe('coordinator');
        });
        it('should process task chain', async () => {
            // Add test data
            db.prepare('INSERT INTO context_items (id, session_id, key, value, category, priority) VALUES (?, ?, ?, ?, ?, ?)').run((0, uuid_1.v4)(), testSessionId, 'test_task', 'Test task description', 'task', 'high');
            const tasks = [
                {
                    id: (0, uuid_1.v4)(),
                    type: 'analyze',
                    input: {
                        analysisType: 'patterns',
                        sessionId: testSessionId,
                    },
                },
                {
                    id: (0, uuid_1.v4)(),
                    type: 'synthesize',
                    input: {
                        synthesisType: 'recommendations',
                    },
                },
            ];
            const results = await coordinator.processChain(tasks);
            expect(results.length).toBe(2);
            expect(results[0].agentType).toBe('analyzer');
            expect(results[1].agentType).toBe('synthesizer');
            expect(results[1].output).toBeDefined(); // Should have used previous output as context
        });
        it('should get best result', async () => {
            const task = {
                id: (0, uuid_1.v4)(),
                type: 'analyze',
                input: {
                    analysisType: 'patterns',
                    sessionId: testSessionId,
                },
            };
            await coordinator.delegate(task);
            const best = coordinator.getBestResult(task.id);
            expect(best).toBeDefined();
            expect(best?.agentType).toBe('analyzer');
        });
        it('should get agent capabilities', () => {
            const capabilities = coordinator.getAgentCapabilities();
            expect(capabilities.analyzer).toBeDefined();
            expect(capabilities.synthesizer).toBeDefined();
            expect(capabilities.analyzer.length).toBeGreaterThan(0);
            expect(capabilities.synthesizer.length).toBeGreaterThan(0);
        });
    });
    describe('Agent base class', () => {
        class TestAgent extends agents_1.Agent {
            async process(task) {
                return {
                    taskId: task.id,
                    agentType: this.name,
                    output: { test: true },
                    confidence: 1.0,
                    processingTime: 0,
                };
            }
        }
        it('should check if agent can handle task', () => {
            const agent = new TestAgent('test', [
                {
                    name: 'test_capability',
                    description: 'Test capability',
                    inputTypes: ['test'],
                    outputTypes: ['result'],
                },
            ]);
            expect(agent.canHandle({ id: '1', type: 'test', input: {} })).toBe(true);
            expect(agent.canHandle({ id: '2', type: 'other', input: {} })).toBe(false);
        });
        it('should return agent name', () => {
            const agent = new TestAgent('test-agent', []);
            expect(agent.getName()).toBe('test-agent');
        });
    });
});
