import { z } from 'zod';
import { formatNumber } from '../utils.js';
export const NarrowingOptionSchema = z.object({
    description: z.string().min(1),
    argv: z.array(z.string()).min(1),
    projectedTokens: z.number().int().positive(),
});
export const TokenBudgetRefusalSchema = z.object({
    refused: z.literal(true),
    reason: z.literal('token-budget-exceeded'),
    required: z.number().int().positive(),
    budget: z.number().int().positive(),
    options: z.array(NarrowingOptionSchema).min(1),
});
/**
 * Build the one shared refusal arm for output envelopes that cannot fit their
 * own fixed chrome. Producers calculate projections from data they already
 * hold; this builder validates and freezes the vocabulary carried over wire.
 */
export function buildTokenBudgetRefusal(required, budget, options) {
    return TokenBudgetRefusalSchema.parse({
        refused: true,
        reason: 'token-budget-exceeded',
        required,
        budget,
        options,
    });
}
export function isTokenBudgetRefusal(value) {
    return TokenBudgetRefusalSchema.safeParse(value).success;
}
export function describeProjectedFit(action, projectedTokens) {
    return `${action}: projection fits in ~${formatNumber(projectedTokens)} tokens.`;
}
export class TokenBudgetRefusalError extends Error {
    refusal;
    name = 'TokenBudgetRefusalError';
    constructor(refusal, envelope = 'output') {
        super(`The empty ${envelope} envelope requires ${refusal.required} tokens, exceeding the ${refusal.budget}-token budget.`);
        this.refusal = refusal;
    }
}
/** Human-readable refusal output. Projected costs are explicitly non-evidence. */
export function renderTokenBudgetRefusal(refusal) {
    const lines = [
        `Token-budget refusal: the empty envelope requires ${formatNumber(refusal.required)} tokens; budget ${formatNumber(refusal.budget)}.`,
        'Narrowing options (projected token counts are projections, not measured usage):',
    ];
    for (const option of refusal.options) {
        lines.push(`- ${option.description}`, `  argv: ${JSON.stringify(option.argv)}`);
    }
    return `${lines.join('\n')}\n`;
}
//# sourceMappingURL=narrowing.js.map