/**
 * Generic pre-execution approval gate for tools.
 *
 * Wraps a ToolDefinition with a user-approval prompt before executing.
 */
import { getApprovalSurface, resolveApprovalExecutionDecision } from '../permissions/approval-surface.js';
import { APPROVAL } from './types.js';
/** Map an ApprovalChoice to a default summary message prepended to the tool result. */
function defaultApprovalSummary(choice) {
    switch (choice) {
        case APPROVAL.ACCEPT:
            return 'User approved this.';
        case APPROVAL.ACCEPT_ALL:
            return 'User enabled session auto-approve.';
        case APPROVAL.RUN_FOREGROUND:
            return 'User approved running this task in the foreground.';
        case APPROVAL.RUN_BACKGROUND:
            return 'User approved running this task in the background.';
        case APPROVAL.ALLOW_ONCE:
            return 'User allowed this once.';
        case APPROVAL.ALLOW_FILE:
            return 'User always allowed this file.';
        case APPROVAL.ALLOW_FOLDER:
            return 'User always allowed this folder.';
        case APPROVAL.REJECT:
            return 'Tool execution rejected by user.';
    }
}
/** Prepend an approval summary text block to a tool result. */
function prependApprovalSummary(result, summary) {
    return {
        ...result,
        content: [{ type: 'text', text: summary }, ...result.content]
    };
}
/** Wrap a tool with a pre-execution approval gate that prompts when policy requires it. */
export function withPreApproval(tool, approval, buildRequest, options = {}) {
    const { alwaysPrompt, isContentSafe, onRequested, onAccepted, onRejected, isApprovedChoiceAllowed, describeApprovedChoice, applyApprovalContext } = options;
    return {
        name: tool.name,
        label: tool.label,
        description: tool.description,
        parameters: tool.parameters,
        isReadOnly: tool.isReadOnly,
        promptGuidelines: tool.promptGuidelines,
        async execute(toolCallId, params, signal, onUpdate, ctx) {
            const safe = alwaysPrompt
                ? false
                : ((await isContentSafe?.(params, ctx)) ?? false);
            const extCtx = ctx;
            const request = await buildRequest(params, ctx);
            const decision = resolveApprovalExecutionDecision({
                surface: getApprovalSurface(extCtx),
                isSafe: safe,
                isAutoApproved: approval.isAutoApproved(),
                alwaysRequireExplicitApproval: request.alwaysRequireExplicitApproval === true,
                allowHeadlessApproval: ctx?.permissionPolicy?.approvals.allowHeadlessApproval ?? false
            });
            if (decision === 'deny') {
                return {
                    content: [{ type: 'text', text: 'Tool execution rejected by user.' }],
                    details: undefined
                };
            }
            if (decision === 'prompt') {
                if (!extCtx) {
                    onRejected?.(request);
                    return {
                        content: [{ type: 'text', text: 'Tool execution rejected by user.' }],
                        details: undefined
                    };
                }
                onRequested?.(request);
                const choice = await approval.requestApproval(request, extCtx);
                if (choice === APPROVAL.REJECT || choice === undefined) {
                    onRejected?.(request);
                    return {
                        content: [{ type: 'text', text: 'Tool execution rejected by user.' }],
                        details: undefined
                    };
                }
                const allowedChoice = (await isApprovedChoiceAllowed?.(request, choice)) ?? true;
                if (!allowedChoice) {
                    onRejected?.(request);
                    return {
                        content: [{ type: 'text', text: 'Tool execution rejected by user.' }],
                        details: undefined
                    };
                }
                onAccepted?.(request, choice);
                if (choice === APPROVAL.ACCEPT_ALL) {
                    approval.onAcceptAll();
                }
                const nextCtx = (await applyApprovalContext?.(ctx, params, request, choice)) ??
                    ctx;
                const result = await tool.execute(toolCallId, params, signal, onUpdate, nextCtx);
                return prependApprovalSummary(result, describeApprovedChoice?.(request, choice) ?? defaultApprovalSummary(choice));
            }
            return tool.execute(toolCallId, params, signal, onUpdate, ctx);
        }
    };
}
//# sourceMappingURL=tool-approval.js.map