Source code for ralph.recovery.failure_budget

"""Per-agent failure budget wrapper."""

from __future__ import annotations

from dataclasses import dataclass
from typing import TYPE_CHECKING

from .budget_state import BudgetState

if TYPE_CHECKING:
    from .classifier import ClassifiedFailure


[docs] @dataclass(frozen=True) class FailureBudget: """Per-agent failure budget wrapper.""" state: BudgetState
[docs] def debit(self, failure: ClassifiedFailure) -> FailureBudget: """Return a new budget with the failure counted (only if it counts).""" if not failure.counts_against_budget: return self new_state = BudgetState( max_retries=self.state.max_retries, consumed=self.state.consumed + 1, failures=(*self.state.failures, failure), ) return FailureBudget(state=new_state)
[docs] def reset(self) -> FailureBudget: """Return a fresh budget with the same max_retries.""" return FailureBudget(state=BudgetState(max_retries=self.state.max_retries))
@property def exhausted(self) -> bool: return self.state.exhausted @property def remaining(self) -> int: return self.state.remaining