/**
 * Heal broken prompt patterns in the waitlist extraction workflow.
 *
 * Idempotent: reads the LLM step's prompt, replaces known broken patterns
 * with the correct versions, and writes back only if something changed.
 * Safe to call on every heartbeat cycle — a no-op when the prompt is healthy.
 *
 * Heal patterns:
 *   1. {{conversations._raw}} → {{conversations}} (pre-structured-JSON)
 *   2. Missing conversationDate field instruction (pre-Task-231)
 */
import { getSession } from "../lib/neo4j.js";
// ---------------------------------------------------------------------------
// Constants — broken patterns and their replacements
// ---------------------------------------------------------------------------
export const WORKFLOW_NAME = "Waitlist lead extraction";
const BROKEN_PROMPT_PATTERN = "{{conversations._raw}}";
const FIXED_PROMPT_FRAGMENT = "{{conversations}}";
/**
 * Broken prompt instructions described delimiter-separated text;
 * fixed version describes the JSON format waitlist-scan actually returns.
 */
const BROKEN_INSTRUCTION = "Below are transcripts from public agent conversations. Each conversation is delimited by " +
    '"--- CONVERSATION <id> ---".';
const FIXED_INSTRUCTION = "Below is a JSON object containing public agent conversations. It has a `conversations` array " +
    "where each element has a `conversationId`, a `createdAt` timestamp, and a `messages` array of user message strings.";
const BROKEN_ID_REF = "the conversation ID from the delimiter";
const FIXED_ID_REF = "the conversation ID from the input data";
/**
 * Heal pattern: prompt missing the conversationDate field instruction.
 * Deployed workflows created before this field was added won't tell the
 * LLM to pass through the conversation timestamp. The heal inserts the
 * field instruction after the conversationId line and updates the data
 * description to mention the createdAt timestamp.
 */
const CONVERSATION_DATE_FIELD = '"conversationDate": the createdAt timestamp of the conversation from the input data';
const OLD_DATA_DESCRIPTION = "where each element has a `conversationId` and a `messages` array of user message strings.";
const NEW_DATA_DESCRIPTION = "where each element has a `conversationId`, a `createdAt` timestamp, and a `messages` array of user message strings.";
// ---------------------------------------------------------------------------
// Core heal logic — also used by waitlist-setup on its idempotency path
// ---------------------------------------------------------------------------
/**
 * Surgically repair a known-broken prompt pattern in a workflow's LLM step.
 * Only updates if the broken pattern is present; preserves any user
 * customisations made via workflow-update.
 */
export async function healBrokenPrompt(session, workflowId) {
    const result = await session.run(`MATCH (w:Workflow {workflowId: $workflowId})-[:HAS_STEP]->(s:WorkflowStep {type: 'llm'})
     WHERE s.prompt CONTAINS $pattern
     RETURN s.stepId AS stepId, s.prompt AS prompt
     LIMIT 1`, { workflowId, pattern: BROKEN_PROMPT_PATTERN });
    if (result.records.length === 0)
        return false;
    const stepId = result.records[0].get("stepId");
    const prompt = result.records[0].get("prompt");
    const healed = prompt
        .replace(BROKEN_PROMPT_PATTERN, FIXED_PROMPT_FRAGMENT)
        .replace(BROKEN_INSTRUCTION, FIXED_INSTRUCTION)
        .replace(BROKEN_ID_REF, FIXED_ID_REF);
    if (healed === prompt)
        return false; // Nothing changed — defensive guard
    await session.run(`MATCH (s:WorkflowStep {stepId: $stepId})
     SET s.prompt = $prompt`, { stepId, prompt: healed });
    return true;
}
/**
 * Patch the LLM step prompt to include the conversationDate field.
 * Only updates if the field is missing; preserves user customisations.
 */
export async function healMissingConversationDate(session, workflowId) {
    const result = await session.run(`MATCH (w:Workflow {workflowId: $workflowId})-[:HAS_STEP]->(s:WorkflowStep {type: 'llm'})
     WHERE s.prompt IS NOT NULL
       AND NOT s.prompt CONTAINS $marker
     RETURN s.stepId AS stepId, s.prompt AS prompt
     LIMIT 1`, { workflowId, marker: "conversationDate" });
    if (result.records.length === 0)
        return false;
    const stepId = result.records[0].get("stepId");
    let prompt = result.records[0].get("prompt");
    // Insert the conversationDate field instruction after the conversationId line
    const convIdLine = '"conversationId": the conversation ID from the input data';
    if (prompt.includes(convIdLine)) {
        prompt = prompt.replace(convIdLine, convIdLine + "\n" + "- " + CONVERSATION_DATE_FIELD);
    }
    // Update the data description to mention createdAt
    prompt = prompt.replace(OLD_DATA_DESCRIPTION, NEW_DATA_DESCRIPTION);
    await session.run(`MATCH (s:WorkflowStep {stepId: $stepId})
     SET s.prompt = $prompt`, { stepId, prompt });
    console.error(`[waitlist-heal] patched conversationDate field into prompt for workflow ${workflowId}`);
    return true;
}
// ---------------------------------------------------------------------------
// Standalone tool entry point
// ---------------------------------------------------------------------------
export async function waitlistHeal(params) {
    const { accountId } = params;
    const session = getSession();
    try {
        // Look up the workflow by name
        const workflowResult = await session.run(`MATCH (w:Workflow {accountId: $accountId, name: $name})
       WHERE w.status IN ['active', 'draft']
       RETURN w.workflowId AS workflowId
       LIMIT 1`, { accountId, name: WORKFLOW_NAME });
        if (workflowResult.records.length === 0) {
            console.error("[waitlist-heal] no workflow found — nothing to heal");
            return { healed: false, workflowId: null };
        }
        const workflowId = workflowResult.records[0].get("workflowId");
        const healedBroken = await healBrokenPrompt(session, workflowId);
        const healedDate = await healMissingConversationDate(session, workflowId);
        const healed = healedBroken || healedDate;
        if (healed) {
            console.error(`[waitlist-heal] prompt healed for workflow ${workflowId}`);
        }
        else {
            console.error("[waitlist-heal] no healing needed");
        }
        return { healed, workflowId };
    }
    finally {
        await session.close();
    }
}
//# sourceMappingURL=waitlist-heal.js.map