- usage_pricing: _snap() builder for official-docs pricing entries (table values identical, verified by dump), shared source/version dicts, drop dead DEFAULT_PRICING - models_dev: _registry_models/_iter_model_entries/_extract_limit helpers replace repeated registry walking; drop dead ModelInfo.format_cost - billing_view/subscription_view: OrgRoleCapability mixin replaces duplicated is_admin/can_change_plan; shared fetch_portal_state/parse_org_fields - reasoning_effort/timeouts/summaries, thinking_timeout_guidance, portal_tags: dispatch tables and compacted comment essays; drop dead CODEX_RESPONSES_EFFORTS alias and _match_any
51 lines
1.5 KiB
Python
51 lines
1.5 KiB
Python
"""Per-agent iteration budget — thread-safe consume/refund counter.
|
|
|
|
Each ``AIAgent`` (parent or subagent) holds its own :class:`IterationBudget`:
|
|
the parent's cap is ``max_iterations`` (default 500), each subagent's is
|
|
``delegation.max_iterations`` (default 50), so total iterations across parent
|
|
+ subagents can exceed the parent's cap. ``run_agent`` re-exports the class so
|
|
``from run_agent import IterationBudget`` keeps working.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import threading
|
|
|
|
|
|
class IterationBudget:
|
|
"""Thread-safe iteration counter. ``execute_code`` (programmatic tool
|
|
calling) iterations are refunded via :meth:`refund` so they don't eat
|
|
into the budget."""
|
|
|
|
def __init__(self, max_total: int):
|
|
self.max_total = max_total
|
|
self._used = 0
|
|
self._lock = threading.Lock()
|
|
|
|
def consume(self) -> bool:
|
|
"""Try to consume one iteration. Returns True if allowed."""
|
|
with self._lock:
|
|
if self._used >= self.max_total:
|
|
return False
|
|
self._used += 1
|
|
return True
|
|
|
|
def refund(self) -> None:
|
|
"""Give back one iteration (e.g. for execute_code turns)."""
|
|
with self._lock:
|
|
if self._used > 0:
|
|
self._used -= 1
|
|
|
|
@property
|
|
def used(self) -> int:
|
|
with self._lock:
|
|
return self._used
|
|
|
|
@property
|
|
def remaining(self) -> int:
|
|
with self._lock:
|
|
return max(0, self.max_total - self._used)
|
|
|
|
|
|
__all__ = ["IterationBudget"]
|