"use strict";
/**
 * Insight service — business logic for MCP query invocation and
 * workflow description generation.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.startMcpQuery = startMcpQuery;
exports.startWorkflowBuilder = startWorkflowBuilder;
exports.startWorkflowPlanner = startWorkflowPlanner;
exports.describeWorkflow = describeWorkflow;
const hotmesh_1 = require("@hotmeshio/hotmesh");
const db_1 = require("../../lib/db");
const defaults_1 = require("../../modules/defaults");
const utils_1 = require("../../modules/utils");
const llm_1 = require("../llm");
const principal_1 = require("../iam/principal");
const prompts_1 = require("./prompts");
// ── MCP query invocation ─────────────────────────────────────────────────────
async function startMcpQuery(input) {
    const { prompt, tags, wait = true, direct = false, context, userId } = input;
    const startTime = Date.now();
    const client = new hotmesh_1.Durable.Client({ connection: (0, db_1.getConnection)() });
    const wfName = direct ? 'mcpQuery' : 'mcpQueryRouter';
    const entity = direct ? 'mcpQuery' : 'mcpQueryRouter';
    const prefix = direct ? 'mcp-query-direct' : 'mcp-query';
    const workflowId = `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
    // Resolve the full principal so ToolContext carries identity to tool calls
    const principal = userId ? await (0, principal_1.resolvePrincipal)(userId) : undefined;
    const handle = await client.workflow.start({
        args: [{
                data: { prompt, tags, context },
                metadata: { source: 'dashboard', certified: true },
                lt: { userId, principal, scopes: ['workflow:invoke', 'mcp:tool:call'] },
            }],
        taskQueue: 'long-tail-system',
        workflowName: wfName,
        workflowId,
        expire: defaults_1.JOB_EXPIRE_SECS,
        entity,
        signalIn: false,
    });
    if (wait === false) {
        return { workflow_id: workflowId, status: 'started', prompt };
    }
    const result = await handle.result({ state: true });
    const data = result?.data || result;
    return {
        ...data,
        prompt,
        workflow_id: workflowId,
        duration_ms: Date.now() - startTime,
    };
}
async function startWorkflowBuilder(input) {
    const { prompt, tags, wait = true, feedback, prior_yaml, answers, prior_questions, userId } = input;
    const startTime = Date.now();
    const client = new hotmesh_1.Durable.Client({ connection: (0, db_1.getConnection)() });
    const workflowId = `wf-builder-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
    const principal = userId ? await (0, principal_1.resolvePrincipal)(userId) : undefined;
    const handle = await client.workflow.start({
        args: [{
                data: { prompt, tags, feedback, prior_yaml, answers, prior_questions },
                metadata: { source: 'dashboard', certified: true },
                lt: { userId, principal, scopes: ['workflow:invoke', 'mcp:tool:call'] },
            }],
        taskQueue: 'long-tail-system',
        workflowName: 'mcpWorkflowBuilder',
        workflowId,
        expire: defaults_1.JOB_EXPIRE_SECS,
        entity: 'mcpWorkflowBuilder',
        signalIn: false,
    });
    if (wait === false) {
        return { workflow_id: workflowId, status: 'started', prompt };
    }
    const result = await handle.result({ state: true });
    const data = result?.data || result;
    return {
        ...data,
        prompt,
        workflow_id: workflowId,
        duration_ms: Date.now() - startTime,
    };
}
async function startWorkflowPlanner(input) {
    const { specification, setId, wait = true, userId, existingPlan, existingSchemas } = input;
    const startTime = Date.now();
    const client = new hotmesh_1.Durable.Client({ connection: (0, db_1.getConnection)() });
    const workflowId = `wf-planner-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
    const principal = userId ? await (0, principal_1.resolvePrincipal)(userId) : undefined;
    const handle = await client.workflow.start({
        args: [{
                data: { specification, setId, existingPlan, existingSchemas },
                metadata: { source: 'dashboard', certified: true },
                lt: { userId, principal, scopes: ['workflow:invoke', 'mcp:tool:call'] },
            }],
        taskQueue: 'long-tail-system',
        workflowName: 'mcpWorkflowPlanner',
        workflowId,
        expire: defaults_1.JOB_EXPIRE_SECS,
        entity: 'mcpWorkflowPlanner',
        signalIn: false,
    });
    if (wait === false) {
        return { workflow_id: workflowId, status: 'started', prompt: specification.slice(0, 200) };
    }
    const result = await handle.result({ state: true });
    const data = result?.data || result;
    return {
        ...data,
        prompt: specification.slice(0, 200),
        workflow_id: workflowId,
        duration_ms: Date.now() - startTime,
    };
}
// ── Workflow description generation ──────────────────────────────────────────
async function describeWorkflow(input) {
    const { prompt, result_title, result_summary } = input;
    if (!(0, llm_1.hasLLMApiKey)(defaults_1.LLM_MODEL_SECONDARY)) {
        return { description: prompt, tags: [] };
    }
    const userContent = [
        `Original query: "${prompt}"`,
        result_title ? `Result: ${result_title}` : '',
        result_summary ? `Summary: ${result_summary.slice(0, 500)}` : '',
    ].filter(Boolean).join('\n');
    const response = await (0, llm_1.callLLM)({
        model: defaults_1.LLM_MODEL_SECONDARY,
        max_tokens: 300,
        messages: [
            { role: 'system', content: prompts_1.DESCRIBE_WORKFLOW_SYSTEM_PROMPT },
            { role: 'user', content: userContent },
        ],
    });
    const raw = response.content || '{}';
    const cleaned = raw.replace(/^```(?:json)?\s*/m, '').replace(/\s*```$/m, '').trim();
    const parsed = JSON.parse(cleaned);
    const toolName = (0, utils_1.sanitizeToolName)(parsed.tool_name || '').slice(0, 60);
    return {
        tool_name: toolName || undefined,
        description: parsed.description || prompt,
        tags: Array.isArray(parsed.tags) ? parsed.tags : [],
    };
}
