"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveReplyTargetAgentId = resolveReplyTargetAgentId;
exports.hasSameReplyDirective = hasSameReplyDirective;
exports.resolvePromptReplyGuidance = resolvePromptReplyGuidance;
exports.buildReplyObligationSuppressionGuide = buildReplyObligationSuppressionGuide;
const dialog_1 = require("../../dialog");
const dialog_instance_registry_1 = require("../../dialog-instance-registry");
const persistence_1 = require("../../persistence");
const interjection_pause_stop_1 = require("../../runtime/interjection-pause-stop");
const reply_prompt_copy_1 = require("../../runtime/reply-prompt-copy");
const work_language_1 = require("../../runtime/work-language");
const tellask_special_1 = require("./tellask-special");
async function resolveReplyTargetAgentId(args) {
    const mainDialog = args.dlg instanceof dialog_1.MainDialog
        ? args.dlg
        : args.dlg instanceof dialog_1.SideDialog
            ? args.dlg.mainDialog
            : undefined;
    if (!mainDialog) {
        return undefined;
    }
    const targetDialogId = new dialog_1.DialogID(args.directive.targetDialogId, mainDialog.id.rootId);
    const targetDialog = mainDialog.lookupDialog(targetDialogId.selfId) ??
        (await (0, dialog_instance_registry_1.ensureDialogLoaded)(mainDialog, targetDialogId, mainDialog.status));
    return targetDialog?.agentId;
}
function buildPromptContentWithExactReplyToolName(args) {
    const isFbrSideDialog = args.dlg instanceof dialog_1.SideDialog &&
        args.dlg.assignmentFromAsker.callName === 'freshBootsReasoning';
    const noActivePrefix = args.language === 'zh' ? reply_prompt_copy_1.NO_ACTIVE_REPLY_PREFIX_ZH : reply_prompt_copy_1.NO_ACTIVE_REPLY_PREFIX_EN;
    const activePrefix = args.language === 'zh' ? reply_prompt_copy_1.ACTIVE_REPLY_TOOL_PREFIX_ZH : reply_prompt_copy_1.ACTIVE_REPLY_TOOL_PREFIX_EN;
    const reminderPrefixes = [
        reply_prompt_copy_1.REPLY_TOOL_REMINDER_PREFIX_EN,
        reply_prompt_copy_1.REPLY_TOOL_REMINDER_PREFIX_ZH,
        reply_prompt_copy_1.ANSWERING_REPLY_REMINDER_PREFIX_EN,
        reply_prompt_copy_1.ANSWERING_REPLY_REMINDER_PREFIX_ZH,
    ];
    const directive = args.activeReplyDirective;
    if (!directive) {
        // Business scenario: a user can come back to a Side Dialog after its final reply has already
        // been delivered to the requester. At that point the business obligation is complete and the
        // visible user is simply asking a follow-up in this dialog. Old assignment text and reply tool
        // names remain in transcript history, so the model may otherwise "finish" the old request
        // again. Dominds has already checked durable reply state here; the prompt says the current
        // business expectation directly: answer/continue this conversation normally.
        if (isFbrSideDialog) {
            return args.prompt.content;
        }
        if (!(args.dlg instanceof dialog_1.SideDialog)) {
            return args.prompt.content;
        }
        if (args.prompt.content.startsWith(noActivePrefix)) {
            return args.prompt.content;
        }
        const note = args.language === 'zh'
            ? [
                noActivePrefix,
                'Dominds 已经判断好：当前没有别的对话在等你发送最终回贴。',
                '本轮按当前对话正常交流即可；如果用户提出了问题，就直接回答这个问题。',
            ].join('\n')
            : [
                noActivePrefix,
                'Dominds has already decided that no other dialog is waiting for your final reply right now.',
                'Handle this as a normal turn in the current conversation; if the user asked a question, answer that question directly.',
            ].join('\n');
        return `${note}\n\n${args.prompt.content}`;
    }
    if (args.prompt.content.startsWith(activePrefix)) {
        return args.prompt.content;
    }
    if (reminderPrefixes.some((prefix) => args.prompt.content.startsWith(prefix))) {
        return args.prompt.content;
    }
    const note = (0, reply_prompt_copy_1.buildActiveReplyToolNote)({
        language: args.language,
        toolName: directive.expectedReplyCallName,
    });
    return `${note}\n\n${args.prompt.content}`;
}
function hasSameReplyDirective(left, right) {
    if (!left || !right) {
        return left === right;
    }
    if (left.expectedReplyCallName !== right.expectedReplyCallName) {
        return false;
    }
    if (left.targetDialogId !== right.targetDialogId ||
        left.targetCallId !== right.targetCallId ||
        left.tellaskContent !== right.tellaskContent) {
        return false;
    }
    return true;
}
async function resolveFreshCurrentSideDialogAssignmentPromptMeta(args) {
    if (!(args.dlg instanceof dialog_1.SideDialog)) {
        return undefined;
    }
    const currentAssignmentPromptMeta = (0, dialog_1.buildSideDialogAssignmentPromptMeta)(args.dlg);
    if (args.prompt?.origin === 'runtime') {
        const promptDirective = args.prompt.tellaskReplyDirective;
        if (!promptDirective) {
            return undefined;
        }
        if (!hasSameReplyDirective(promptDirective, currentAssignmentPromptMeta.tellaskReplyDirective)) {
            return undefined;
        }
    }
    else if (args.prompt?.origin !== 'user') {
        return undefined;
    }
    const latest = await persistence_1.DialogPersistence.loadDialogLatest(args.dlg.id, args.dlg.status);
    if (!latest) {
        return undefined;
    }
    const targetCallId = currentAssignmentPromptMeta.tellaskReplyDirective.targetCallId.trim();
    if (latest.sideDialogFinalResponse?.callId === targetCallId) {
        return undefined;
    }
    if (latest.tellaskResults.results.some((entry) => entry.callId.trim() === targetCallId)) {
        return undefined;
    }
    return currentAssignmentPromptMeta;
}
async function resolveFreshPendingAskBackReplyDirective(args) {
    const prompt = args.prompt;
    if (prompt?.origin !== 'runtime' ||
        prompt.tellaskReplyDirective?.expectedReplyCallName !== 'replyTellaskBack') {
        return undefined;
    }
    const promptLatest = await persistence_1.DialogPersistence.loadDialogLatest(args.dlg.id, args.dlg.status);
    if (promptLatest?.pendingRuntimePrompt?.msgId !== prompt.msgId) {
        return undefined;
    }
    const mainDialog = args.dlg instanceof dialog_1.MainDialog
        ? args.dlg
        : args.dlg instanceof dialog_1.SideDialog
            ? args.dlg.mainDialog
            : undefined;
    if (!mainDialog) {
        return undefined;
    }
    const askBackAskerDialogId = new dialog_1.DialogID(prompt.tellaskReplyDirective.targetDialogId, mainDialog.id.rootId);
    const latest = await persistence_1.DialogPersistence.loadDialogLatest(askBackAskerDialogId, mainDialog.status);
    if (!latest) {
        return undefined;
    }
    const targetCallId = prompt.tellaskReplyDirective.targetCallId.trim();
    if (latest.tellaskResults.results.some((entry) => entry.callId.trim() === targetCallId)) {
        return undefined;
    }
    const activeObligation = await persistence_1.DialogPersistence.loadActiveTellaskReplyObligation(args.dlg.id, args.dlg.status);
    return activeObligation !== undefined &&
        activeObligation.expectedReplyCallName === 'replyTellaskBack' &&
        activeObligation.targetDialogId === prompt.tellaskReplyDirective.targetDialogId &&
        activeObligation.targetCallId === targetCallId &&
        activeObligation.tellaskContent === prompt.tellaskReplyDirective.tellaskContent
        ? prompt.tellaskReplyDirective
        : undefined;
}
function resolveFreshReplyDirective(args) {
    const promptDirective = args.promptDirective;
    const persistedDirective = args.persistedDirective;
    if (!promptDirective) {
        return persistedDirective;
    }
    if (!persistedDirective) {
        return undefined;
    }
    return hasSameReplyDirective(promptDirective, persistedDirective)
        ? promptDirective
        : persistedDirective;
}
function resolvePromptPersistedReplyDirective(args) {
    const promptDirective = args.promptDirective;
    const persistedDirective = args.persistedDirective;
    if (!promptDirective || !persistedDirective) {
        return undefined;
    }
    return hasSameReplyDirective(promptDirective, persistedDirective) ? promptDirective : undefined;
}
async function shouldSuppressInterDialogReplyGuidanceForUserInterjection(args) {
    // WARNING:
    // This suppression decision is not a cosmetic prompt tweak. A real user interjection should be
    // answered locally before old reply obligations or pending callee work pull the model back into
    // earlier handoff closure.
    //
    // Do not "simplify" this into a pure display-state check or a pure active-callee check.
    // Proceeding dialogs with a still-active reply obligation are part of the same rule: a fresh
    // user interjection should still suppress the live reply obligation and answer locally first.
    // A stale paused execution marker still means a repeated interjection should behave as local
    // side conversation, but it is not durable drive work and must not force a manual Continue after
    // the answer is visible.
    const prompt = args.prompt;
    if (!prompt) {
        return false;
    }
    if (prompt.origin !== 'user') {
        return false;
    }
    if (prompt.tellaskReplyDirective !== undefined) {
        return false;
    }
    const latest = await persistence_1.DialogPersistence.loadDialogLatest(args.dlg.id, args.dlg.status);
    if (latest?.executionMarker?.kind === 'interrupted' &&
        (0, interjection_pause_stop_1.isUserInterjectionPauseStopReason)(latest.executionMarker.reason)) {
        return true;
    }
    const activeReplyDirective = await (0, tellask_special_1.loadActiveTellaskReplyDirective)(args.dlg);
    if (activeReplyDirective) {
        return true;
    }
    // Use strict persistence reads here. This branch changes business behavior, so a read failure
    // must loud-fail the round instead of being silently treated as "pending callees exist".
    const activeCallees = await persistence_1.DialogPersistence.loadActiveCallees(args.dlg.id, args.dlg.status);
    return activeCallees.batches.some((batch) => batch.callees.some((callee) => callee.status === 'pending'));
}
async function resolvePromptReplyGuidance(args) {
    const prompt = args.prompt;
    const isQ4HAnswerPrompt = typeof prompt?.q4hAnswerCallId === 'string' && prompt.q4hAnswerCallId.trim() !== '';
    const latest = await persistence_1.DialogPersistence.loadDialogLatest(args.dlg.id, args.dlg.status);
    const persistedCurrentSideDialogAssignmentPromptMeta = await resolveFreshCurrentSideDialogAssignmentPromptMeta({
        dlg: args.dlg,
        prompt,
    });
    const persistedPendingAskBackReplyDirective = await resolveFreshPendingAskBackReplyDirective({
        dlg: args.dlg,
        prompt,
    });
    const persistedPendingRuntimePromptDirective = prompt !== undefined &&
        latest?.pendingRuntimePrompt?.msgId === prompt.msgId &&
        latest.pendingRuntimePrompt.origin === 'runtime'
        ? latest.pendingRuntimePrompt.tellaskReplyDirective
        : undefined;
    const persistedActiveReplyObligation = await (0, tellask_special_1.loadActiveTellaskReplyDirective)(args.dlg);
    const persistedActiveReplyDirective = persistedCurrentSideDialogAssignmentPromptMeta?.tellaskReplyDirective ??
        persistedPendingAskBackReplyDirective ??
        persistedPendingRuntimePromptDirective ??
        persistedActiveReplyObligation;
    const suppressInterDialogReplyGuidance = isQ4HAnswerPrompt
        ? false
        : await shouldSuppressInterDialogReplyGuidanceForUserInterjection({
            dlg: args.dlg,
            prompt,
        });
    const availableReplyDirective = resolveFreshReplyDirective({
        promptDirective: prompt?.tellaskReplyDirective,
        persistedDirective: persistedActiveReplyDirective,
    });
    const activeReplyDirective = suppressInterDialogReplyGuidance
        ? undefined
        : availableReplyDirective;
    const promptContent = prompt === undefined
        ? undefined
        : suppressInterDialogReplyGuidance
            ? prompt.content
            : buildPromptContentWithExactReplyToolName({
                dlg: args.dlg,
                prompt,
                activeReplyDirective,
                language: args.language ?? (0, work_language_1.getWorkLanguage)(),
            });
    return {
        activeReplyDirective,
        isQ4HAnswerPrompt,
        promptContent,
        persistedTellaskReplyDirective: resolvePromptPersistedReplyDirective({
            promptDirective: prompt?.tellaskReplyDirective,
            persistedDirective: persistedActiveReplyDirective,
        }),
        suppressedCalleeDialogReplyTarget: suppressInterDialogReplyGuidance
            ? persistedCurrentSideDialogAssignmentPromptMeta?.calleeDialogReplyTarget
            : undefined,
        suppressedTellaskReplyDirective: suppressInterDialogReplyGuidance
            ? persistedActiveReplyDirective
            : undefined,
        suppressInterDialogReplyGuidance,
        transientGuideContent: suppressInterDialogReplyGuidance && prompt !== undefined
            ? buildReplyObligationSuppressionGuide({
                language: args.language ?? (0, work_language_1.getWorkLanguage)(),
            })
            : undefined,
    };
}
function buildReplyObligationSuppressionGuide(args) {
    return (0, reply_prompt_copy_1.buildReplyObligationSuppressionGuideText)(args.language);
}
