"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildQuestionHandoffState = buildQuestionHandoffState;
exports.handleWorkerAttemptFailure = handleWorkerAttemptFailure;
exports.buildNestedWorkflowPlanningState = buildNestedWorkflowPlanningState;
exports.appendWorkerStartSection = appendWorkerStartSection;
exports.buildDeferredWorkerState = buildDeferredWorkerState;
exports.appendWorkerDecisionSections = appendWorkerDecisionSections;
exports.buildWorkerExecutionState = buildWorkerExecutionState;
const catalog_1 = require("../../i18n/catalog");
const constants_1 = require("../../worker/constants");
const errors_1 = require("../../worker/errors");
const types_1 = require("../../worker/types");
const state_1 = require("../../workflows/state");
const issue_logger_1 = require("../issue-logger");
const log_text_1 = require("../log-text");
const freshness_1 = require("./freshness");
const presentation_1 = require("./presentation");
const shared_1 = require("./shared");
const ai_run_accounting_1 = require("./ai-run-accounting");
const types_2 = require("./types");
function buildQuestionHandoffState(input) {
    const workflowState = (0, ai_run_accounting_1.applyAiRunAccountingToWorkflowState)({
        workflowState: input.workflowState,
        ...(input.consecutiveAiRuns !== undefined
            ? { consecutiveAiRuns: input.consecutiveAiRuns }
            : {}),
        ...(input.totalAiRunHours !== undefined
            ? { totalAiRunHours: input.totalAiRunHours }
            : {}),
    });
    return {
        kind: "handoff",
        handoff: {
            issue: input.issue,
            responseLanguage: input.responseLanguage,
            summary: input.summary,
            branchName: input.branchName,
            workflowTemplateName: input.workflowTemplateName,
            workflowState,
            ...(input.consecutiveAiRuns !== undefined
                ? { consecutiveAiRuns: input.consecutiveAiRuns }
                : {}),
            ...(input.totalAiRunHours !== undefined
                ? { totalAiRunHours: input.totalAiRunHours }
                : {}),
            needsHumanReason: types_2.WORKER_NEEDS_HUMAN_REASONS.question,
        },
    };
}
function handleWorkerAttemptFailure(input) {
    const nestedPlanningSummary = buildNestedWorkflowPlanningFailureSummary(input.nestedPlanningPass, input.error, input.responseLanguage);
    if (nestedPlanningSummary !== null) {
        const accounting = resolveFailedWorkerAiRunAccounting({
            currentConsecutiveAiRuns: input.preparation.currentConsecutiveAiRuns,
            currentTotalAiRunHours: input.preparation.currentTotalAiRunHours,
            error: input.error,
        });
        return buildQuestionHandoffState({
            issue: input.preparation.latestIssue,
            responseLanguage: input.responseLanguage,
            summary: nestedPlanningSummary,
            branchName: input.workspace.branchName,
            workflowTemplateName: input.preparation.workflowTemplateName,
            workflowState: input.preparation.workflowState,
            consecutiveAiRuns: accounting.consecutiveAiRuns,
            totalAiRunHours: accounting.totalAiRunHours,
        });
    }
    const accounting = resolveFailedWorkerAiRunAccounting({
        currentConsecutiveAiRuns: input.preparation.currentConsecutiveAiRuns,
        currentTotalAiRunHours: input.preparation.currentTotalAiRunHours,
        error: input.error,
    });
    throw new shared_1.WorkerCycleError({
        issue: input.preparation.latestIssue,
        branchName: input.workspace.branchName,
        pullRequestUrl: null,
        consecutiveAiRuns: accounting.consecutiveAiRuns,
        totalAiRunHours: accounting.totalAiRunHours,
        runMode: input.preparation.workflow.mode,
        workflowTemplateName: input.preparation.workflowTemplateName,
        workflowState: (0, ai_run_accounting_1.applyAiRunAccountingToWorkflowState)({
            workflowState: input.preparation.workflowState,
            consecutiveAiRuns: accounting.consecutiveAiRuns,
            totalAiRunHours: accounting.totalAiRunHours,
        }),
        needsHumanReason: input.preparation.needsHumanReason,
    }, input.error);
}
function resolveFailedWorkerAiRunAccounting(input) {
    return (0, ai_run_accounting_1.resolveAttemptedAiRunAccounting)({
        currentConsecutiveAiRuns: input.currentConsecutiveAiRuns,
        currentTotalAiRunHours: input.currentTotalAiRunHours,
        attemptedWorkerExecution: (0, errors_1.hasAttemptedWorkerExecution)(input.error),
        workerDurationMs: (0, errors_1.readWorkerFailureDurationMs)(input.error),
    });
}
function buildNestedWorkflowPlanningFailureSummary(nestedPlanningPass, error, locale) {
    if (nestedPlanningPass?.kind !== "continue") {
        return null;
    }
    if (!(error instanceof errors_1.WorkerDecisionParseError) &&
        !(0, state_1.isWorkflowDecisionValidationError)(error)) {
        return null;
    }
    const detail = error.message.trim().length > 0
        ? error.message
        : (0, catalog_1.translate)(locale, "workflow.runContext.childPlanning.invalidResult");
    return buildNestedWorkflowChildHandoffSummary(nestedPlanningPass.parentStepTitle, nestedPlanningPass.targetTemplateName, detail, locale);
}
function buildNestedWorkflowPlanningState(preparation, nestedPlanningPass, responseLanguage, workspace, workspaceHeadCommitOidBeforeRun, workerResult, scannedInputCursor) {
    const resolvedChildWorkflow = (0, state_1.resolveWorkerExecutionWorkflow)({
        workflow: nestedPlanningPass.workflowForWorker,
        workflowTemplateName: nestedPlanningPass.workflowTemplateNameForWorker,
        workflowState: nestedPlanningPass.workflowStateForWorker,
    }, workerResult.launchResult.decision, responseLanguage);
    const childPlan = resolvedChildWorkflow.workflowState?.plan ?? null;
    if (workerResult.launchResult.decision.outcome !== constants_1.WORKER_OUTCOMES.proceed ||
        childPlan === null ||
        childPlan.steps.length === 0) {
        return buildQuestionHandoffState({
            issue: preparation.latestIssue,
            responseLanguage,
            summary: buildNestedWorkflowChildHandoffSummary(nestedPlanningPass.parentStepTitle, nestedPlanningPass.targetTemplateName, workerResult.launchResult.decision.result.resultSummary, responseLanguage),
            branchName: workspace.branchName,
            workflowTemplateName: preparation.workflowTemplateName,
            workflowState: preparation.workflowState,
        });
    }
    const expandedWorkflowState = (0, state_1.replaceWorkflowRefStepWithExpandedSteps)(nestedPlanningPass.parentWorkflowState, {
        stepIndex: nestedPlanningPass.stepIndex,
        sourceTemplateName: nestedPlanningPass.sourceTemplateName,
        sourceTemplateDigest: nestedPlanningPass.sourceTemplateDigest,
        expansionGroupId: nestedPlanningPass.expansionGroupId,
        originSubtreeKey: nestedPlanningPass.originSubtreeKey,
        originWorkflowRef: nestedPlanningPass.originWorkflowRef,
        childPlan,
    });
    return {
        kind: "completed",
        workerExecution: buildWorkerExecutionState(preparation.latestIssue, {
            workerId: workerResult.workerId,
            workerName: workerResult.workerName,
            ...(workerResult.authProfileId === undefined
                ? {}
                : { authProfileId: workerResult.authProfileId }),
            ...(workerResult.authProfileKind === undefined
                ? {}
                : { authProfileKind: workerResult.authProfileKind }),
            workerDurationMs: workerResult.workerDurationMs ?? 0,
            workspaceHeadCommitOidBeforeRun,
            decision: workerResult.launchResult.decision,
        }, preparation.currentConsecutiveAiRuns, responseLanguage, {
            facts: shared_1.EMPTY_FACTS,
            pullRequestUrl: null,
            pullRequestThreadId: null,
        }, scannedInputCursor, workspace.branchName, preparation.workflow.mode, preparation.workflowTemplateName, expandedWorkflowState, preparation.planningIntent, {
            incrementsConsecutiveAiRuns: false,
            recordsRunOutcome: false,
            startedWithPlanningIntent: preparation.workflowState?.pendingPlanningIntent ?? null,
            startedWithWorkflowStartApprovalIntent: preparation.workflowState?.pendingWorkflowStartApprovalIntent ?? null,
        }),
    };
}
function buildNestedWorkflowChildHandoffSummary(parentStepTitle, childTemplateName, detail, locale) {
    const prefix = (0, catalog_1.translate)(locale, "workflow.runContext.childWorkflowHandoffPrefix", {
        parentStepTitle,
        childTemplateName,
    });
    return `${prefix}\n${detail}`;
}
async function appendWorkerStartSection(logger, workspace, preparation, runMode) {
    await logger.appendSection((0, log_text_1.issueLogSection)("workerStart"), [
        (0, log_text_1.issueLogField)("mode", runMode),
        (0, log_text_1.issueLogField)("template", (0, issue_logger_1.formatNullable)(preparation.workflowTemplateName)),
        (0, log_text_1.issueLogField)("workspace", workspace.path),
        (0, log_text_1.issueLogField)("branch", workspace.branchName),
        (0, log_text_1.issueLogField)("commentCount", preparation.comments.length),
        (0, log_text_1.issueLogField)("consecutiveAiRunsBeforeWorker", preparation.currentConsecutiveAiRuns),
    ].join("\n"));
}
function buildDeferredWorkerState(preparation, responseLanguage, workspace, workerResult) {
    return {
        kind: "deferred",
        deferred: {
            issue: preparation.latestIssue,
            responseLanguage,
            branchName: workspace.branchName,
            workflowState: preparation.workflowState,
            triedProfiles: workerResult.triedProfiles.map((profile) => (0, freshness_1.renderWorkerAttemptLabel)(profile.workerName)),
            deferredReason: workerResult.reason,
            cooldowns: workerResult.cooldowns,
            cooldownUntil: workerResult.cooldownUntil,
            attemptedWorkerExecution: workerResult.attemptedWorkerExecution,
            ...(0, ai_run_accounting_1.resolveAttemptedAiRunAccounting)({
                currentConsecutiveAiRuns: preparation.currentConsecutiveAiRuns,
                currentTotalAiRunHours: preparation.currentTotalAiRunHours,
                attemptedWorkerExecution: workerResult.attemptedWorkerExecution,
                workerDurationMs: workerResult.workerDurationMs,
            }),
        },
    };
}
async function appendWorkerDecisionSections(logger, workerResult) {
    await logger.appendSection((0, log_text_1.issueLogSection)("resolvedSignIn"), [
        (0, log_text_1.issueLogField)("worker", workerResult.workerName),
        (0, log_text_1.issueLogField)("signIn", formatWorkerAuthLabel(workerResult.authProfileKind ?? "custom-worker")),
    ].join("\n"));
    const decision = workerResult.launchResult.decision;
    const stepResults = decision.stepResults;
    const parsedDecisionLines = [
        (0, log_text_1.issueLogField)("outcome", decision.outcome),
        (0, log_text_1.issueLogField)("summary", decision.result.resultSummary),
        (0, log_text_1.issueLogField)("comment", (0, issue_logger_1.formatNullable)(decision.result.humanComment)),
        (0, log_text_1.issueLogField)("workflow", (0, log_text_1.formatLogWorkflowPresence)(Boolean(decision.workflow))),
    ];
    if (stepResults !== undefined) {
        parsedDecisionLines.push((0, log_text_1.issueLogField)("stepIds", (0, log_text_1.formatLogList)(stepResults.map((stepResult) => stepResult.stepId))), (0, log_text_1.issueLogField)("stepResults", JSON.stringify(stepResults, null, 2)));
    }
    await logger.appendSection((0, log_text_1.issueLogSection)("parsedDecision"), parsedDecisionLines.join("\n"));
    await appendWorkerRepairTraceSection(logger, workerResult);
}
async function appendWorkerRepairTraceSection(logger, workerResult) {
    const repairTrace = workerResult.launchResult.repairTrace;
    if (repairTrace === undefined || repairTrace === null) {
        return;
    }
    const lines = [];
    if (typeof repairTrace === "object" && !Array.isArray(repairTrace)) {
        const record = repairTrace;
        if (typeof record.attemptCount === "number") {
            lines.push((0, log_text_1.issueLogField)("repairAttemptCount", record.attemptCount));
        }
        if (typeof record.repaired === "boolean") {
            lines.push((0, log_text_1.issueLogField)("repaired", (0, log_text_1.formatLogBoolean)(record.repaired)));
        }
        if (typeof record.kind === "string") {
            lines.push((0, log_text_1.issueLogField)("repairKind", record.kind));
        }
        if (typeof record.result === "string") {
            lines.push((0, log_text_1.issueLogField)("repairResult", record.result));
        }
    }
    lines.push(`${log_text_1.ISSUE_LOG_TEXT.field.repairTrace}:`);
    lines.push(JSON.stringify(repairTrace, null, 2));
    await logger.appendSection((0, log_text_1.issueLogSection)("workerRepairRetry"), lines.join("\n"));
}
function formatWorkerAuthLabel(authProfileKind) {
    if (authProfileKind === "custom-worker") {
        return "Custom worker";
    }
    return (0, presentation_1.renderSavedAuthLabel)({
        kind: authProfileKind,
    }, catalog_1.DEFAULT_APP_LOCALE);
}
function buildWorkerExecutionState(issue, input, consecutiveAiRuns, responseLanguage, routing, scannedInputCursor, branchName, runMode, workflowTemplateName, workflowState, planningIntent, options = {}) {
    const normalizedCommitMessage = input.decision.commitMessage?.trim() || null;
    const continuation = normalizeWorkerDecisionContinuation(input.decision.continuation);
    return {
        issue,
        workerId: input.workerId,
        workerName: input.workerName,
        authProfileId: input.authProfileId ?? input.workerName,
        authProfileKind: input.authProfileKind ?? "custom-worker",
        workerDurationMs: input.workerDurationMs,
        workspaceHeadCommitOidBeforeRun: input.workspaceHeadCommitOidBeforeRun,
        workerOutcome: input.decision.outcome,
        result: input.decision.result,
        commitMessage: normalizedCommitMessage,
        consecutiveAiRuns,
        responseLanguage,
        facts: routing.facts,
        branchName,
        pullRequestUrl: routing.pullRequestUrl,
        scannedInputCursor,
        runMode,
        workflowTemplateName,
        workflowState,
        plannedIssueTitle: options.plannedIssueTitle ?? null,
        mergeContext: options.mergeContext ?? null,
        planningIntent,
        workflowStartApproval: input.decision.workflowStartApproval ?? null,
        startedWithPlanningIntent: options.startedWithPlanningIntent ?? null,
        startedWithWorkflowStartApprovalIntent: options.startedWithWorkflowStartApprovalIntent ?? null,
        continuation,
        ...(input.decision.followupRecommendation !== undefined
            ? { followupRecommendation: input.decision.followupRecommendation }
            : {}),
        needsHumanReason: (0, shared_1.readWorkerNeedsHumanReason)(input.decision),
        incrementsConsecutiveAiRuns: options.incrementsConsecutiveAiRuns ?? true,
        recordsRunOutcome: options.recordsRunOutcome ?? runMode === types_1.WORKER_RUN_MODES.workflowExecute,
    };
}
function normalizeWorkerDecisionContinuation(continuation) {
    if (continuation === undefined) {
        return null;
    }
    if (continuation.strategy === "spawn_child_issue") {
        return {
            strategy: continuation.strategy,
            title: continuation.title.trim(),
            reason: continuation.reason.trim(),
        };
    }
    return {
        strategy: continuation.strategy,
        reason: continuation.reason.trim(),
    };
}
