"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;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.registerHumanQueueTools = registerHumanQueueTools;
const crypto = __importStar(require("crypto"));
const zod_1 = require("zod");
const escalationService = __importStar(require("../escalation"));
// ── Schemas (extracted to break TS2589 deep-instantiation in registerTool generics) ──
const escalateSchema = zod_1.z.object({
    role: zod_1.z.string().describe('Target role for the escalation (e.g., "reviewer")'),
    message: zod_1.z.string().describe('Description of what needs human review'),
    data: zod_1.z.record(zod_1.z.any()).optional().describe('Contextual data for the reviewer'),
    type: zod_1.z.string().optional().default('mcp').describe('Escalation type classification'),
    subtype: zod_1.z.string().optional().default('tool_call').describe('Escalation subtype'),
    priority: zod_1.z.number().min(1).max(4).optional().default(2)
        .describe('Priority: 1 (highest) to 4 (lowest)'),
});
const checkResolutionSchema = zod_1.z.object({
    escalation_id: zod_1.z.string().describe('The escalation ID to check'),
});
const getAvailableWorkSchema = zod_1.z.object({
    role: zod_1.z.string().describe('Role to filter by'),
    limit: zod_1.z.number().optional().default(10).describe('Max results to return'),
});
const claimAndResolveSchema = zod_1.z.object({
    escalation_id: zod_1.z.string().describe('The escalation ID to claim and resolve'),
    resolver_id: zod_1.z.string().describe('Identifier for who/what is resolving'),
    payload: zod_1.z.record(zod_1.z.any()).describe('Resolution payload data'),
});
const resolveEscalationSchema = zod_1.z.object({
    escalation_id: zod_1.z.string().describe('The escalation ID to resolve'),
    payload: zod_1.z.record(zod_1.z.any()).describe('Resolution payload data'),
});
const escalateAndWaitSchema = zod_1.z.object({
    role: zod_1.z.string().describe('Target role for the escalation (e.g., "reviewer")'),
    message: zod_1.z.string().describe('Description of what input is needed from the human'),
    form_schema: zod_1.z.record(zod_1.z.any()).optional()
        .describe('JSON Schema for the resolver form. Use format:"password" for sensitive fields.'),
    data: zod_1.z.record(zod_1.z.any()).optional().describe('Contextual data for the reviewer'),
    assigned_to: zod_1.z.string().optional().describe('Auto-assign to a specific user'),
    type: zod_1.z.string().optional().default('mcp').describe('Escalation type classification'),
    subtype: zod_1.z.string().optional().default('wait_for_human').describe('Escalation subtype'),
    priority: zod_1.z.number().min(1).max(4).optional().default(1)
        .describe('Priority: 1 (highest) to 4 (lowest)'),
}).passthrough();
/**
 * Register all human queue tools on the given MCP server.
 *
 * Tools registered:
 * - escalate_to_human -- create a new escalation (fire-and-forget)
 * - check_resolution -- check escalation status
 * - get_available_work -- list available escalations by role
 * - claim_and_resolve -- claim + resolve in one step
 * - resolve_escalation -- resolve an already-claimed escalation
 * - escalate_and_wait -- create escalation and return signal for durable wait
 */
function registerHumanQueueTools(server) {
    // ── escalate_to_human ───────────────────────────────────────────────
    server.registerTool('escalate_to_human', {
        title: 'Escalate to Human',
        description: 'Create a new escalation for human review. Returns the escalation ID.',
        inputSchema: escalateSchema,
    }, async (args) => {
        const escalation = await escalationService.createEscalation({
            type: args.type || 'mcp',
            subtype: args.subtype || 'tool_call',
            description: args.message,
            priority: args.priority,
            role: args.role,
            envelope: JSON.stringify(args.data || {}),
            metadata: { source: 'mcp_server' },
        });
        return {
            content: [{
                    type: 'text',
                    text: JSON.stringify({
                        escalation_id: escalation.id,
                        status: escalation.status,
                        role: escalation.role,
                        created_at: escalation.created_at,
                    }),
                }],
        };
    });
    // ── check_resolution ────────────────────────────────────────────────
    server.registerTool('check_resolution', {
        title: 'Check Escalation Resolution',
        description: 'Check the status of an escalation. Returns status and resolver payload if resolved.',
        inputSchema: checkResolutionSchema,
    }, async (args) => {
        const escalation = await escalationService.getEscalation(args.escalation_id);
        if (!escalation) {
            return {
                content: [{
                        type: 'text',
                        text: JSON.stringify({ error: 'Escalation not found' }),
                    }],
                isError: true,
            };
        }
        const result = {
            escalation_id: escalation.id,
            status: escalation.status,
        };
        if (escalation.status === 'resolved' && escalation.resolver_payload) {
            try {
                result.resolver_payload = JSON.parse(escalation.resolver_payload);
            }
            catch {
                result.resolver_payload = escalation.resolver_payload;
            }
            result.resolved_at = escalation.resolved_at;
        }
        return {
            content: [{ type: 'text', text: JSON.stringify(result) }],
        };
    });
    // ── get_available_work ──────────────────────────────────────────────
    server.registerTool('get_available_work', {
        title: 'Get Available Work',
        description: 'List available escalations for a role. Returns pending, unassigned escalations.',
        inputSchema: getAvailableWorkSchema,
    }, async (args) => {
        const { escalations } = await escalationService.listAvailableEscalations({
            role: args.role,
            limit: args.limit,
        });
        const items = escalations.map((e) => ({
            escalation_id: e.id,
            type: e.type,
            subtype: e.subtype,
            description: e.description,
            priority: e.priority,
            role: e.role,
            created_at: e.created_at,
        }));
        return {
            content: [{
                    type: 'text',
                    text: JSON.stringify({ count: items.length, escalations: items }),
                }],
        };
    });
    // ── claim_and_resolve ───────────────────────────────────────────────
    server.registerTool('claim_and_resolve', {
        title: 'Claim and Resolve',
        description: 'Claim an escalation and immediately resolve it with a payload. Atomic operation.',
        inputSchema: claimAndResolveSchema,
    }, async (args) => {
        const claimed = await escalationService.claimEscalation(args.escalation_id, args.resolver_id, 5);
        if (!claimed) {
            return {
                content: [{
                        type: 'text',
                        text: JSON.stringify({ error: 'Escalation not available for claim' }),
                    }],
                isError: true,
            };
        }
        const resolved = await escalationService.resolveEscalation(args.escalation_id, args.payload);
        if (!resolved) {
            return {
                content: [{
                        type: 'text',
                        text: JSON.stringify({ error: 'Failed to resolve escalation' }),
                    }],
                isError: true,
            };
        }
        return {
            content: [{
                    type: 'text',
                    text: JSON.stringify({
                        escalation_id: resolved.id,
                        status: resolved.status,
                        resolved_at: resolved.resolved_at,
                    }),
                }],
        };
    });
    // ── resolve_escalation ──────────────────────────────────────────────
    server.registerTool('resolve_escalation', {
        title: 'Resolve Escalation',
        description: 'Resolve an already-claimed escalation with a payload. Use when the claim happened externally (e.g. via API).',
        inputSchema: resolveEscalationSchema,
    }, async (args) => {
        const resolved = await escalationService.resolveEscalation(args.escalation_id, args.payload);
        if (!resolved) {
            return {
                content: [{
                        type: 'text',
                        text: JSON.stringify({ error: 'Failed to resolve escalation' }),
                    }],
                isError: true,
            };
        }
        return {
            content: [{
                    type: 'text',
                    text: JSON.stringify({
                        escalation_id: resolved.id,
                        status: resolved.status,
                        resolved_at: resolved.resolved_at,
                    }),
                }],
        };
    });
    // ── escalate_and_wait ──────────────────────────────────────────────
    server.registerTool('escalate_and_wait', {
        title: 'Escalate and Wait',
        description: 'Create an escalation and pause the workflow until a human responds. ' +
            'Returns a signal ID that the workflow uses to wait. ' +
            'Preferred over escalate_to_human + check_resolution polling.',
        inputSchema: escalateAndWaitSchema,
    }, async (args) => {
        const signalId = `wait-for-human-${crypto.randomUUID()}`;
        // YAML workflows inject _yaml_signal_routing to override Durable's signalId-based routing
        const yamlRouting = args._yaml_signal_routing;
        const signalRouting = yamlRouting
            ? { ...yamlRouting, signalId }
            : { signalId };
        const metadata = {
            source: 'mcp_server',
            signal_routing: signalRouting,
        };
        if (args.form_schema) {
            metadata.form_schema = args.form_schema;
        }
        const escalation = await escalationService.createEscalation({
            type: args.type || 'mcp',
            subtype: args.subtype || 'wait_for_human',
            description: args.message,
            priority: args.priority,
            role: args.role,
            envelope: JSON.stringify(args.data || {}),
            metadata,
            workflow_type: yamlRouting?.workflowType,
            workflow_id: yamlRouting?.workflowId,
            task_queue: yamlRouting?.taskQueue,
        });
        if (args.assigned_to) {
            await escalationService.claimEscalation(escalation.id, args.assigned_to, 240);
        }
        return {
            content: [{
                    type: 'text',
                    text: JSON.stringify({
                        type: 'waitFor',
                        signalId,
                        escalationId: escalation.id,
                    }),
                }],
        };
    });
}
