/**
 * Session budget tracking logic.
 *
 * Tracks one explicit cumulative budget for a prompt run. The contract is:
 * - budget activation is explicit
 * - cumulative spent tokens are tracked across the run
 * - runtime annotations are appended onto real tool results
 * - the budget does not drive continuation or stopping behavior
 *
 * Separate hard execution limits are only used for CLI/sub-agent bounds.
 */
function formatTokenCount(value) {
    return Math.max(0, Math.floor(value)).toLocaleString('en-US');
}
function buildBudgetAnnotation(spentTokens, allottedTokens) {
    const remainingTokens = allottedTokens - spentTokens;
    const overBudget = remainingTokens < 0;
    return {
        text: `${formatTokenCount(spentTokens)} spent / ${formatTokenCount(allottedTokens)} allotted.`,
        details: {
            spentTokens,
            allottedTokens,
            remainingTokens,
            overBudget
        }
    };
}
// ============================================================================
// Budget Tracking State
// ============================================================================
export class SessionBudgetContinuation {
    _listener = undefined;
    _activeBudgetTokens = 0;
    _cumulativeTurns = 0;
    _cumulativeToolUses = 0;
    _cumulativeTokens = 0;
    _hardLimitReached = false;
    _hardLimitReason = undefined;
    get activeBudgetTokens() {
        return this._activeBudgetTokens;
    }
    get hasActiveBudget() {
        return this._activeBudgetTokens > 0;
    }
    get cumulativeTurns() {
        return this._cumulativeTurns;
    }
    get cumulativeToolUses() {
        return this._cumulativeToolUses;
    }
    get cumulativeTokens() {
        return this._cumulativeTokens;
    }
    get hardLimitReached() {
        return this._hardLimitReached;
    }
    get hardLimitReason() {
        return this._hardLimitReason;
    }
    onEvent(listener) {
        this._listener = listener;
    }
    _emit(event) {
        this._listener?.(event);
    }
    beginPromptRun(budgetTokens) {
        this._activeBudgetTokens = budgetTokens ?? 0;
        this._cumulativeTurns = 0;
        this._cumulativeToolUses = 0;
        this._cumulativeTokens = 0;
        this._hardLimitReached = false;
        this._hardLimitReason = undefined;
    }
    reset() {
        this.beginPromptRun();
    }
    resetAll() {
        this.beginPromptRun();
    }
    accumulateTokens(totalTokens) {
        if (totalTokens <= 0)
            return;
        this._cumulativeTokens += totalTokens;
    }
    accumulateTurn() {
        this._cumulativeTurns++;
    }
    accumulateToolUse() {
        this._cumulativeToolUses++;
    }
    deductExternalTokens(count) {
        if (count <= 0)
            return;
        this._cumulativeTokens += count;
    }
    buildTurnAnnotation() {
        if (!this.hasActiveBudget || this._hardLimitReached) {
            return null;
        }
        return buildBudgetAnnotation(this._cumulativeTokens, this._activeBudgetTokens);
    }
    /**
     * Check whether any explicit hard execution limit has been reached.
     *
     * These are only for bounded execution contexts such as sub-agents.
     * They are intentionally disabled while an explicit budget-tracking run is active.
     */
    checkHardLimits(limits) {
        if (this._hardLimitReached || this.hasActiveBudget)
            return this._hardLimitReached;
        if (limits.maxTokens > 0 && this._cumulativeTokens >= limits.maxTokens) {
            this._hardLimitReached = true;
            this._hardLimitReason = `Token limit reached (${this._cumulativeTokens}/${limits.maxTokens})`;
            this._emit({ type: 'hard_limit_reached', reason: this._hardLimitReason });
            return true;
        }
        if (limits.maxToolUses > 0 && this._cumulativeToolUses >= limits.maxToolUses) {
            this._hardLimitReached = true;
            this._hardLimitReason = `Tool use limit reached (${this._cumulativeToolUses}/${limits.maxToolUses})`;
            this._emit({ type: 'hard_limit_reached', reason: this._hardLimitReason });
            return true;
        }
        if (limits.maxTurns > 0 && this._cumulativeTurns >= limits.maxTurns) {
            this._hardLimitReached = true;
            this._hardLimitReason = `Turn limit reached (${this._cumulativeTurns}/${limits.maxTurns})`;
            this._emit({ type: 'hard_limit_reached', reason: this._hardLimitReason });
            return true;
        }
        return false;
    }
}
//# sourceMappingURL=session-budget-continuation.js.map