import { getDeletedContentBlocks, getDeletedEntryIds } from "./context-deletion-targets.js";
export function formatErrorMessage(error) {
    return error instanceof Error ? error.message : String(error);
}
export function createContextDeletionToolResult(text, details) {
    return { content: [{ type: "text", text }], details, terminate: false };
}
export function roundPercent(value) {
    return Math.round(value * 10) / 10;
}
export function percentOf(part, total) {
    return total > 0 ? roundPercent((part / total) * 100) : 0;
}
export function finitePositiveNumber(value) {
    return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : undefined;
}
export function contextCompactionTargetReductionPercent(parameters) {
    return roundPercent((1 - parameters.compression_ratio) * 100);
}
export function contextCompactionTargetLabel(parameters) {
    return `${contextCompactionTargetReductionPercent(parameters)}%`;
}
export function createContextCompactionBudgetDetails(stats, callCount, contextWindow, parameters, remainingImageTokens, imageBlockCount) {
    const targetTokensAfter = Math.max(0, Math.floor(stats.tokensBefore * parameters.compression_ratio));
    const targetReductionPercent = contextCompactionTargetReductionPercent(parameters);
    const details = {
        ...(contextWindow !== undefined ? { contextWindow } : {}),
        compression_ratio: parameters.compression_ratio,
        tokensBefore: stats.tokensBefore,
        currentTokensAfter: stats.tokensAfter,
        deletedTokens: Math.max(0, stats.tokensBefore - stats.tokensAfter),
        currentReductionPercent: stats.percentReduction,
        targetReductionPercent,
        targetTokensAfter,
        tokensToDeleteForTarget: Math.max(0, stats.tokensAfter - targetTokensAfter),
        ...(contextWindow !== undefined
            ? {
                contextWindowBeforePercent: percentOf(stats.tokensBefore, contextWindow),
                contextWindowAfterPercent: percentOf(stats.tokensAfter, contextWindow),
            }
            : {}),
        remainingImageTokens,
        imageBlockCount,
        imageTokenPercent: percentOf(remainingImageTokens, stats.tokensAfter),
        callCount,
    };
    return details;
}
export function contextCompactionTargetMet(result, parameters) {
    return (result !== undefined &&
        result.deletedTargets.length > 0 &&
        result.stats.percentReduction >= contextCompactionTargetReductionPercent(parameters));
}
export function contextCompactionProgressKey(result) {
    if (!result)
        return "none:0";
    return `${result.deletedTargets.length}:${result.stats.percentReduction}:${result.stats.tokensAfter}`;
}
export function contextCompactionProgressPercent(result) {
    return result?.stats.percentReduction ?? 0;
}
/**
 * Sum the token estimates of image content blocks that remain after applying the
 * current deletion targets. Deleted entries and individually-deleted image blocks
 * are excluded so the budget tool always reflects the live working set.
 */
export function sumRemainingImageTokens(transcript, targets) {
    const deletedEntryIds = getDeletedEntryIds(targets);
    const deletedContentBlocks = getDeletedContentBlocks(targets);
    let imageTokens = 0;
    for (const entry of transcript.entries) {
        if (deletedEntryIds.has(entry.entryId))
            continue;
        const deletedBlocks = deletedContentBlocks.get(entry.entryId);
        for (const block of entry.contentBlocks) {
            if (block.type !== "image")
                continue;
            if (deletedBlocks?.has(block.blockIndex))
                continue;
            imageTokens += block.tokenEstimate;
        }
    }
    return imageTokens;
}
/**
 * Count the image content blocks that remain after applying the current deletion
 * targets. Deleted entries and individually-deleted image blocks are excluded.
 */
export function countRemainingImageBlocks(transcript, targets) {
    const deletedEntryIds = getDeletedEntryIds(targets);
    const deletedContentBlocks = getDeletedContentBlocks(targets);
    let count = 0;
    for (const entry of transcript.entries) {
        if (deletedEntryIds.has(entry.entryId))
            continue;
        const deletedBlocks = deletedContentBlocks.get(entry.entryId);
        for (const block of entry.contentBlocks) {
            if (block.type !== "image")
                continue;
            if (deletedBlocks?.has(block.blockIndex))
                continue;
            count += 1;
        }
    }
    return count;
}
//# sourceMappingURL=context-compaction-metrics.js.map