// engine/compact/compact-middleware.ts — SPEC-922: Apply compact mode to tool responses
/** Approximate chars per token for English text. */
const CHARS_PER_TOKEN = 4;
/** Truncate a single text block to a token budget. */
function truncateBlock(text, tokenBudget) {
    const maxChars = tokenBudget * CHARS_PER_TOKEN;
    if (text.length <= maxChars) {
        return text;
    }
    const kept = text.slice(0, maxChars);
    const omittedTokens = Math.ceil((text.length - maxChars) / CHARS_PER_TOKEN);
    return `${kept}\n\n... (${omittedTokens} tokens omitted — verbose:true for full output)`;
}
/**
 * Apply compact mode formatting to a ToolResult.
 * - Truncates text content blocks to tokenBudget
 * - Preserves structuredContent (essential data: status, scores, blockers)
 * - Adds _meta.compactMode and _meta.contextUsed
 */
export function applyCompactMode(result, decision) {
    if (decision.mode !== 'compact') {
        // Still add _meta even in verbose mode if contextUsed was provided
        if (decision.contextUsed !== undefined) {
            return {
                ...result,
                _meta: {
                    ...(typeof result._meta === 'object' && result._meta !== null ? result._meta : {}),
                    compactMode: false,
                    contextUsed: decision.contextUsed,
                },
            };
        }
        return result;
    }
    const truncatedContent = result.content.map((block) => ({
        ...block,
        text: truncateBlock(block.text, decision.tokenBudget),
    }));
    return {
        ...result,
        content: truncatedContent,
        _meta: {
            ...(typeof result._meta === 'object' && result._meta !== null ? result._meta : {}),
            compactMode: true,
            contextUsed: decision.contextUsed,
            tokenBudget: decision.tokenBudget,
        },
    };
}
//# sourceMappingURL=compact-middleware.js.map