import { decisionLeakToolNames, } from "../../provider/model-provider.js";
import { deriveControlsForActionPolicy } from "../../provider/provider-action-controls.js";
import { resolveProviderTurnActionPolicy } from "./tool-constraint.js";
import { buildProviderToolLoopContext } from "./provider-tool-loop-context.js";
import { finalizeProviderToolBudgetExhausted } from "./provider-tool-budget-finalizer.js";
import { classifyRuntimeFailure } from "../failure-classification.js";
import { appendRuntimeObservation } from "./runtime-observation.js";
export async function runProviderToolFollowUp(input) {
    const { context, runtime, turn } = input;
    const providerTurnBudget = input.invokeContext.budget;
    const providerTurnBudgeted = providerTurnBudget.enabled;
    const maxProviderTurns = providerTurnBudget.max;
    let followUpMessages = input.followUpMessages;
    let followUpDecisionSystemPrompt = input.followUpDecisionSystemPrompt;
    if (providerTurnBudget.used >= maxProviderTurns &&
        providerTurnBudgeted &&
        !context.allowPlanUpdate &&
        !context.allowPhaseResult) {
        return {
            kind: "response",
            responseText: await finalizeProviderToolBudgetExhausted({
                advancedPhaseEscalationLevel: input.advancedPhaseEscalationLevel,
                consumedToolStepCount: input.consumedToolStepCount,
                context,
                followUpDecisionSystemPrompt,
                followUpMessages,
                followUpRouteConfig: input.followUpRouteConfig,
                invokeContext: input.invokeContext,
                runtime,
                turn,
                unresolvedRequiredToolConstraint: input.unresolvedRequiredToolConstraint,
            }),
        };
    }
    const followUpActionPolicy = resolveProviderTurnActionPolicy({
        allowPhaseResult: context.allowPhaseResult ?? false,
        allowPlanUpdate: context.allowPlanUpdate ?? false,
        requestKind: "decide",
        requiredToolConstraint: input.unresolvedRequiredToolConstraint,
        visibleTools: input.followUpVisibleTools,
    });
    const followUpControls = deriveControlsForActionPolicy({
        allowPhaseResult: context.allowPhaseResult ?? false,
        allowPlanUpdate: context.allowPlanUpdate ?? false,
        phaseResultPhaseName: context.phaseResultPhaseName,
    }, followUpActionPolicy);
    const followUpVisibleTools = followUpActionPolicy.allowedActions.includes("tool")
        ? input.followUpVisibleTools
        : [];
    let followUpDecision;
    let resolvePreviewToolCallId;
    for (let attempt = 0; attempt < 2; attempt += 1) {
        const followUpPreview = runtime.provider.createDecisionStreamPreview(turn, false, decisionLeakToolNames(followUpVisibleTools, followUpControls.allowPlanUpdate, followUpControls.allowPhaseResult), providerTurnBudgeted ? runtime.provider.decisionNoActionTimeoutMs() : undefined);
        try {
            followUpDecision = await runtime.provider.decide(turn.threadId, turn.id, {
                actionPolicy: followUpActionPolicy,
                allowPhaseResult: followUpControls.allowPhaseResult,
                allowPlanUpdate: followUpControls.allowPlanUpdate,
                cacheControl: context.cacheControl,
                messages: followUpMessages,
                ...(followUpControls.phaseResultPhaseName
                    ? { phaseResultPhaseName: followUpControls.phaseResultPhaseName }
                    : {}),
                stream: followUpPreview.callbacks,
                systemPrompt: followUpDecisionSystemPrompt,
                tools: followUpVisibleTools,
            }, "tool-followup", buildProviderToolLoopContext(input.invokeContext, {
                escalationLevel: input.advancedPhaseEscalationLevel,
                requiredToolConstraint: input.unresolvedRequiredToolConstraint,
                routeConfigOverride: input.followUpRouteConfig,
                toolStepCount: input.consumedToolStepCount,
            }));
            resolvePreviewToolCallId = followUpPreview.resolveToolCallId;
            break;
        }
        catch (error) {
            const failure = classifyRuntimeFailure(error);
            if (failure.errorCode !== "PROVIDER_NO_ACTION" || attempt > 0) {
                throw error;
            }
            followUpMessages = appendRuntimeObservation(followUpMessages, providerNoActionObservation(error));
        }
        finally {
            await followUpPreview.finalize();
        }
    }
    if (!followUpDecision || !resolvePreviewToolCallId) {
        throw new Error("Provider follow-up did not produce a decision.");
    }
    return {
        decision: followUpDecision,
        followUpDecisionSystemPrompt,
        followUpMessages,
        invokeContext: buildProviderToolLoopContext(input.invokeContext, {
            escalationLevel: input.advancedPhaseEscalationLevel,
            requiredToolConstraint: input.unresolvedRequiredToolConstraint,
            routeConfigOverride: input.followUpRouteConfig,
            toolStepCount: input.consumedToolStepCount,
        }),
        kind: "decision",
        resolvePreviewToolCallId,
    };
}
function providerNoActionObservation(error) {
    const message = error instanceof Error ? error.message : String(error);
    return {
        code: "PROVIDER_NO_ACTION",
        message: `Provider returned no runtime action for this tool follow-up. Reason: ${message}`,
        severity: "error",
    };
}
//# sourceMappingURL=provider-tool-follow-up-runner.js.map