/**
 * Session statistics and context usage computation.
 *
 * Pure functions extracted from AgentSession to keep the orchestration file focused.
 */
import { calculateContextTokens, estimateContextTokens } from '../../core/session/compaction/index.js';
import { findLatestCompactionEntry } from '../../core/session/session-compaction.js';
/**
 * Compute session statistics from agent state.
 */
export function computeSessionStats(state, sessionFile, sessionId) {
    const userMessages = state.messages.filter((m) => m.role === 'user').length;
    const assistantMessages = state.messages.filter((m) => m.role === 'assistant').length;
    const toolResults = state.messages.filter((m) => m.role === 'toolResult').length;
    let toolCalls = 0;
    let totalInput = 0;
    let totalOutput = 0;
    let totalCacheRead = 0;
    let totalCacheWrite = 0;
    let totalCost = 0;
    for (const message of state.messages) {
        if (message.role === 'assistant') {
            const assistantMsg = message;
            toolCalls += assistantMsg.content.filter((c) => c.type === 'toolCall').length;
            totalInput += assistantMsg.usage.input;
            totalOutput += assistantMsg.usage.output;
            totalCacheRead += assistantMsg.usage.cacheRead;
            totalCacheWrite += assistantMsg.usage.cacheWrite;
            totalCost += assistantMsg.usage.cost.total;
        }
    }
    return {
        sessionFile,
        sessionId,
        userMessages,
        assistantMessages,
        toolCalls,
        toolResults,
        totalMessages: state.messages.length,
        tokens: {
            input: totalInput,
            output: totalOutput,
            cacheRead: totalCacheRead,
            cacheWrite: totalCacheWrite,
            // usage.input already includes uncached + cache tokens, so adding cache
            // buckets again would double count them in the displayed total.
            total: totalInput + totalOutput
        },
        cost: totalCost
    };
}
/**
 * Compute context window usage from agent state.
 */
export function computeContextUsage(model, messages, sessionManager) {
    if (!model)
        return undefined;
    const contextWindow = model.contextWindow ?? 0;
    if (contextWindow <= 0)
        return undefined;
    // After compaction, the last assistant usage reflects pre-compaction context size.
    // We can only trust usage from an assistant that responded after the latest compaction.
    // If no such assistant exists, context token count is unknown until the next LLM response.
    const branchEntries = sessionManager.getBranch();
    const latestCompaction = findLatestCompactionEntry(branchEntries);
    if (latestCompaction) {
        // Check if there's a valid assistant usage after the compaction boundary
        const compactionIndex = branchEntries.lastIndexOf(latestCompaction);
        let hasPostCompactionUsage = false;
        for (let i = branchEntries.length - 1; i > compactionIndex; i--) {
            const entry = branchEntries[i];
            if (entry.type === 'message' && entry.message.role === 'assistant') {
                const assistant = entry.message;
                if (assistant.stopReason !== 'aborted' && assistant.stopReason !== 'error') {
                    const contextTokens = calculateContextTokens(assistant.usage);
                    if (contextTokens > 0) {
                        hasPostCompactionUsage = true;
                    }
                    break;
                }
            }
        }
        if (!hasPostCompactionUsage) {
            return { tokens: null, contextWindow, percent: null };
        }
    }
    const estimate = estimateContextTokens(messages);
    const percent = (estimate.tokens / contextWindow) * 100;
    return {
        tokens: estimate.tokens,
        contextWindow,
        percent
    };
}
//# sourceMappingURL=session-stats.js.map