91e75e620b
CI: cua-driver distro-compat matrix / debian:12 (glibc 2.36) (push) Has been cancelled
CI: SPDX Headers / Check SPDX headers (warn-only) (push) Has been cancelled
CD: Docs MCP Server / build (linux/amd64) (push) Has been cancelled
CD: Docs MCP Server / build (linux/arm64) (push) Has been cancelled
CD: Docs MCP Server / merge (push) Has been cancelled
CI: cua-driver distro-compat matrix / Resolve release version (push) Has been cancelled
CI: cua-driver distro-compat matrix / fedora:41 (glibc 2.40) (push) Has been cancelled
CI: cua-driver distro-compat matrix / rockylinux:9 (glibc 2.34) (push) Has been cancelled
CI: cua-driver distro-compat matrix / ubuntu:22.04 (glibc 2.35) (push) Has been cancelled
CI: cua-driver distro-compat matrix / ubuntu:24.04 (glibc 2.39) (push) Has been cancelled
CI: cua-driver distro-compat matrix / Distro compat summary (push) Has been cancelled
CI: Rust Linux unit / Rust Linux unit and compile (push) Has been cancelled
CI: Rust Windows unit / Rust Windows unit and compile (push) Has been cancelled
CI: Nix Linux Rust source / Nix / compositor build (push) Has been cancelled
CI: Nix Linux Rust source / Nix / driver package (push) Has been cancelled
CI: Nix Linux Rust source / Nix / Rust unit tests (push) Has been cancelled
57 lines
1.9 KiB
Python
57 lines
1.9 KiB
Python
from typing import Any, Dict, List
|
|
|
|
from .base import AsyncCallbackHandler
|
|
|
|
|
|
class BudgetExceededError(Exception):
|
|
"""Exception raised when budget is exceeded."""
|
|
|
|
pass
|
|
|
|
|
|
class BudgetManagerCallback(AsyncCallbackHandler):
|
|
"""Budget manager callback that tracks usage costs and can stop execution when budget is exceeded."""
|
|
|
|
def __init__(
|
|
self, max_budget: float, reset_after_each_run: bool = True, raise_error: bool = False
|
|
):
|
|
"""
|
|
Initialize BudgetManagerCallback.
|
|
|
|
Args:
|
|
max_budget: Maximum budget allowed
|
|
reset_after_each_run: Whether to reset budget after each run
|
|
raise_error: Whether to raise an error when budget is exceeded
|
|
"""
|
|
self.max_budget = max_budget
|
|
self.reset_after_each_run = reset_after_each_run
|
|
self.raise_error = raise_error
|
|
self.total_cost = 0.0
|
|
|
|
async def on_run_start(self, kwargs: Dict[str, Any], old_items: List[Dict[str, Any]]) -> None:
|
|
"""Reset budget if configured to do so."""
|
|
if self.reset_after_each_run:
|
|
self.total_cost = 0.0
|
|
|
|
async def on_usage(self, usage: Dict[str, Any]) -> None:
|
|
"""Track usage costs."""
|
|
if "response_cost" in usage:
|
|
self.total_cost += usage["response_cost"]
|
|
|
|
async def on_run_continue(
|
|
self,
|
|
kwargs: Dict[str, Any],
|
|
old_items: List[Dict[str, Any]],
|
|
new_items: List[Dict[str, Any]],
|
|
) -> bool:
|
|
"""Check if budget allows continuation."""
|
|
if self.total_cost >= self.max_budget:
|
|
if self.raise_error:
|
|
raise BudgetExceededError(
|
|
f"Budget exceeded: ${self.total_cost} >= ${self.max_budget}"
|
|
)
|
|
else:
|
|
print(f"Budget exceeded: ${self.total_cost} >= ${self.max_budget}")
|
|
return False
|
|
return True
|