import { convertToLlm, createBranchSummaryMessage, createCustomMessage, messageIsLlmVisible, messageStartsLlmUserTurn } from "../messages.js";
import { normalizeDerivedSessionEntries } from "../session-entry-normalization.js";
import { buildSessionContext } from "../session-manager-history.js";
import { estimateContextTokens, estimateTokens } from "./compaction.js";
import { normalizeCompactionParameters, normalizeCompactionQuery, COMPACTION_AUTO_QUERY } from "./compaction-parameters.js";
import { MIN_COMPACTABLE_REGION_LINES, VERBATIM_COMPACTION_STRATEGY, } from "./compaction-types.js";
import { createNumberedRegion, serializeConversationForCompaction } from "./transcript-serialization.js";
const keptTailTokensByPreparation = new WeakMap();
/** Return the independently estimated cost of the protected tail. */
export function getKeptTailTokenEstimate(preparation) {
    return keptTailTokensByPreparation.get(preparation)
        ?? Math.max(0, preparation.tokensBefore - preparation.region.tokenEstimate);
}
function messageFromEntry(entry) {
    if (entry.type === "message")
        return entry.message;
    if (entry.type === "custom_message") {
        return createCustomMessage(entry.customType, entry.content, entry.display, entry.details, entry.timestamp, entry.excludeFromContext);
    }
    if (entry.type === "branch_summary" && typeof entry.summary === "string") {
        return createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp);
    }
    return undefined;
}
function activeBoundary(entry) {
    if (entry.type !== "compaction")
        return false;
    const details = entry.details;
    return details?.strategy === VERBATIM_COMPACTION_STRATEGY;
}
function visibleEntries(entries, start = 0) {
    const visible = [];
    for (let index = start; index < entries.length; index++) {
        const entry = entries[index];
        const message = messageFromEntry(entry);
        if (message && messageIsLlmVisible(message))
            visible.push({ entry, index, message });
    }
    return visible;
}
function messageText(message) {
    const converted = convertToLlm([message]);
    if (converted.length === 0)
        return "";
    return converted
        .flatMap((item) => typeof item.content === "string" ? [item.content] : item.content.filter((block) => block.type === "text").map((block) => block.text))
        .join("\n");
}
export function autoDetectCompactionQuery(entries) {
    const normalized = normalizeDerivedSessionEntries(entries);
    for (let index = normalized.length - 1; index >= 0; index--) {
        const message = messageFromEntry(normalized[index]);
        if (!message || !messageStartsLlmUserTurn(message))
            continue;
        const text = messageText(message).trim();
        if (text)
            return normalizeCompactionQuery(text, COMPACTION_AUTO_QUERY);
    }
    return COMPACTION_AUTO_QUERY;
}
function latestActiveBoundary(entries) {
    for (let index = entries.length - 1; index >= 0; index--) {
        const entry = entries[index];
        if (activeBoundary(entry))
            return { entry, index };
    }
    return undefined;
}
/** Prepare the complete compactable transcript and its exact context-visible message tail. */
export function prepareCompactionBoundary(pathEntries, settings, options = {}) {
    const entries = normalizeDerivedSessionEntries(pathEntries);
    const previous = latestActiveBoundary(entries);
    let regionStart = 0;
    if (previous) {
        const keptIndex = previous.entry.firstKeptEntryId === null
            ? -1
            : entries.findIndex((entry) => entry.id === previous.entry.firstKeptEntryId);
        regionStart = keptIndex >= 0 ? keptIndex : previous.index + 1;
    }
    const visible = visibleEntries(entries, regionStart);
    const parameters = normalizeCompactionParameters({ ...settings, ...options }, autoDetectCompactionQuery(entries));
    const tailStart = Math.max(0, visible.length - parameters.preserve_recent);
    const regionMessages = visible.slice(0, tailStart);
    const tailMessages = visible.slice(tailStart);
    const serialized = serializeConversationForCompaction(convertToLlm(regionMessages.map((item) => item.message)));
    const regionText = [previous?.entry.summary, serialized].filter((text) => typeof text === "string" && text.length > 0).join("\n");
    const region = createNumberedRegion(regionText);
    if (region.lines.length < MIN_COMPACTABLE_REGION_LINES)
        return undefined;
    const preparation = {
        firstKeptEntryId: tailMessages[0]?.entry.id ?? null,
        region,
        regionEntryIds: regionMessages.map((item) => item.entry.id),
        keptTailMessageCount: tailMessages.length,
        tokensBefore: estimateContextTokens(buildSessionContext(entries).messages).tokens,
        parameters,
        settings,
    };
    keptTailTokensByPreparation.set(preparation, tailMessages.reduce((sum, item) => sum + estimateTokens(item.message), 0));
    return preparation;
}
//# sourceMappingURL=compaction-boundary.js.map