"use strict";
// =============================================================================
// Pure Agent - Delegate Task Tool
// Ported from Hermes tools/delegate_tool.py
// =============================================================================
Object.defineProperty(exports, "__esModule", { value: true });
exports.listActiveSubagents = listActiveSubagents;
exports.interruptSubagent = interruptSubagent;
exports.cleanupDelegateTool = cleanupDelegateTool;
const tool_registry_1 = require("./tool-registry");
const result_types_1 = require("./result-types");
const pure_agent_1 = require("./pure-agent");
const logger_1 = require("./logger");
const utils_1 = require("./utils");
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
const BLOCKED_TOOLS = new Set(['delegate_task', 'memory', 'execute_code']);
const DEFAULT_MAX_CONCURRENT = 3;
const DEFAULT_CHILD_TIMEOUT = 600_000; // 10 minutes
const DEFAULT_MAX_ITERATIONS = 50;
// ---------------------------------------------------------------------------
// Active sub-agents tracking
// ---------------------------------------------------------------------------
const _activeSubagents = new Map();
// ---------------------------------------------------------------------------
// Delegate task handler
// ---------------------------------------------------------------------------
async function delegateTaskHandler(args, context) {
    const { goal, context: taskContext, tasks, toolsets, max_iterations = DEFAULT_MAX_ITERATIONS, role = 'leaf', } = args;
    // Single task mode
    if (goal && !tasks) {
        return runSingleTask(goal, taskContext, toolsets, max_iterations, role, context);
    }
    // Batch mode (multiple tasks)
    if (tasks && Array.isArray(tasks)) {
        return runBatchTasks(tasks, toolsets, max_iterations, role, context);
    }
    return (0, result_types_1.toolError)('Provide either "goal" (single task) or "tasks" (batch)');
}
// ---------------------------------------------------------------------------
// Single task execution
// ---------------------------------------------------------------------------
async function runSingleTask(goal, taskContext, toolsets, maxIterations, role, parentContext) {
    const subagentId = `sub_${(0, utils_1.generateId)()}`;
    const startTime = Date.now();
    (0, logger_1.getLogger)().info(`Delegate: starting sub-agent ${subagentId} for "${goal.slice(0, 80)}"`);
    try {
        // Build child agent config (inherit from parent's context)
        const child = new pure_agent_1.PureAgent({
            baseUrl: '', // Will be set by the parent agent's config
            apiKey: '',
            model: 'default',
            maxIterations,
            workingDir: parentContext.workingDir,
            systemMessage: buildChildSystemPrompt(goal, taskContext, role),
            sessionId: subagentId,
        });
        _activeSubagents.set(subagentId, {
            agent: child,
            goal,
            startedAt: startTime,
            status: 'running',
        });
        // Run with timeout
        const result = await runWithTimeout(child, goal, DEFAULT_CHILD_TIMEOUT);
        _activeSubagents.get(subagentId).status = 'completed';
        return (0, result_types_1.toolResult)({
            task_index: 0,
            status: 'completed',
            summary: result.finalResponse,
            api_calls: result.apiCalls,
            duration_seconds: Math.round((Date.now() - startTime) / 1000),
        });
    }
    catch (err) {
        const status = _activeSubagents.get(subagentId);
        if (status)
            status.status = 'failed';
        return (0, result_types_1.toolResult)({
            task_index: 0,
            status: 'failed',
            error: (0, utils_1.sanitizeError)(err),
            duration_seconds: Math.round((Date.now() - startTime) / 1000),
        });
    }
    finally {
        const agent = _activeSubagents.get(subagentId)?.agent;
        if (agent)
            agent.close();
        _activeSubagents.delete(subagentId);
    }
}
// ---------------------------------------------------------------------------
// Batch task execution
// ---------------------------------------------------------------------------
async function runBatchTasks(tasks, defaultToolsets, maxIterations, defaultRole, parentContext) {
    const startTime = Date.now();
    const maxConcurrent = Math.min(tasks.length, DEFAULT_MAX_CONCURRENT);
    const results = [];
    (0, logger_1.getLogger)().info(`Delegate batch: ${tasks.length} tasks, max ${maxConcurrent} concurrent`);
    // Execute in batches
    for (let i = 0; i < tasks.length; i += maxConcurrent) {
        const batch = tasks.slice(i, i + maxConcurrent);
        const batchPromises = batch.map((task, batchIdx) => {
            const taskIdx = i + batchIdx;
            return runSingleTask(task.goal, task.context, task.toolsets || defaultToolsets, maxIterations, task.role || defaultRole, parentContext).then(resultStr => {
                try {
                    const parsed = JSON.parse(resultStr);
                    return { ...parsed, task_index: taskIdx };
                }
                catch {
                    return { task_index: taskIdx, status: 'error', error: resultStr };
                }
            });
        });
        const batchResults = await Promise.all(batchPromises);
        results.push(...batchResults);
    }
    const duration = Math.round((Date.now() - startTime) / 1000);
    return (0, result_types_1.toolResult)({ results, total_duration_seconds: duration });
}
// ---------------------------------------------------------------------------
// Run agent with timeout
// ---------------------------------------------------------------------------
async function runWithTimeout(agent, message, timeoutMs) {
    return new Promise(async (resolve, reject) => {
        const timer = setTimeout(() => {
            agent.interrupt();
            reject(new Error(`Sub-agent timed out after ${timeoutMs / 1000}s`));
        }, timeoutMs);
        try {
            let finalResponse = '';
            let apiCalls = 0;
            for await (const event of agent.runConversation(message)) {
                if (event.event === 'content' && event.data.delta) {
                    finalResponse += event.data.delta;
                }
                if (event.event === 'progress') {
                    apiCalls++;
                }
                if (event.event === 'done' || event.event === 'error')
                    break;
            }
            clearTimeout(timer);
            resolve({ finalResponse, apiCalls });
        }
        catch (err) {
            clearTimeout(timer);
            reject(err);
        }
    });
}
// ---------------------------------------------------------------------------
// Child system prompt
// ---------------------------------------------------------------------------
function buildChildSystemPrompt(goal, context, role) {
    const parts = [
        'You are a focused sub-agent working on a delegated task. Complete it fully and report results.',
        '',
        `## Task`,
        goal,
    ];
    if (context) {
        parts.push('', `## Context`, context);
    }
    if (role === 'orchestrator') {
        parts.push('', '## Role: Orchestrator', 'You may further delegate sub-tasks using delegate_task if needed.', 'Break complex tasks into independent sub-tasks and run them in parallel.');
    }
    parts.push('', '## Instructions', '- Use tools to accomplish the task', '- Be thorough but focused', '- Report concrete results, not plans', '- If blocked, report the blocker clearly');
    return parts.join('\n');
}
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
function listActiveSubagents() {
    const now = Date.now();
    return Array.from(_activeSubagents.entries()).map(([id, info]) => ({
        id,
        goal: info.goal.slice(0, 80),
        status: info.status,
        elapsed: Math.round((now - info.startedAt) / 1000),
    }));
}
function interruptSubagent(id) {
    const entry = _activeSubagents.get(id);
    if (!entry)
        return false;
    entry.agent.interrupt();
    entry.status = 'interrupted';
    return true;
}
function cleanupDelegateTool() {
    for (const [, entry] of _activeSubagents) {
        entry.agent.interrupt();
        entry.agent.close();
    }
    _activeSubagents.clear();
}
// ---------------------------------------------------------------------------
// Registration
// ---------------------------------------------------------------------------
tool_registry_1.registry.register({
    name: 'delegate_task',
    toolset: 'delegation',
    schema: {
        description: `Delegate a task to a sub-agent. The sub-agent runs independently with its own tool access and returns results. Use for parallelizing independent work or isolating complex sub-tasks.`,
        parameters: {
            type: 'object',
            properties: {
                goal: {
                    type: 'string',
                    description: 'The task goal / instruction for the sub-agent',
                },
                context: {
                    type: 'string',
                    description: 'Additional context the sub-agent needs',
                },
                tasks: {
                    type: 'array',
                    description: 'Batch mode: array of tasks to run in parallel',
                    items: {
                        type: 'object',
                        properties: {
                            goal: { type: 'string' },
                            context: { type: 'string' },
                            toolsets: { type: 'array', items: { type: 'string' } },
                            role: { type: 'string', enum: ['leaf', 'orchestrator'] },
                        },
                        required: ['goal'],
                    },
                },
                toolsets: {
                    type: 'array',
                    items: { type: 'string' },
                    description: 'Toolsets the sub-agent can use (default: terminal, file, web)',
                },
                max_iterations: {
                    type: 'number',
                    description: 'Max iterations for the sub-agent (default: 50)',
                },
                role: {
                    type: 'string',
                    enum: ['leaf', 'orchestrator'],
                    description: 'Sub-agent role. "leaf" cannot delegate further. "orchestrator" can.',
                },
            },
            required: [],
        },
    },
    handler: delegateTaskHandler,
    isAsync: true,
    description: 'Delegate task to sub-agent',
    emoji: '🔀',
});
//# sourceMappingURL=delegate-tool.js.map