Skip to main content

bursar.engine module

Core engine that loads config and calculates credit costs.

The PricingEngine class is the main entry point for the bursar package. It loads a validated PricingConfig from a dict or DB, then calculates credit costs from UsageMetrics.

Money safety (REFACTOR_CONTRACT §1): every cost is computed in decimal.Decimal. Components and the total are quantized to 4 dp ROUND_HALF_UP at this boundary; the total is the single source of truth and is clamped to >= 0 exactly once. There is no integer truncation of costs anywhere – a 0.4-credit operation costs 0.4, not 0.

class bursar.engine.PricingEngine(config: PricingConfig)

Bases: object

Credit calculation engine.

Usage:

engine = PricingEngine.from_dict({
"models": {"_default": "input_tokens * 0.001 + output_tokens * 0.003"},
})
result = engine.calculate(UsageMetrics(
model="claude-opus-4",
input_tokens=1000,
output_tokens=2000,
))
print(result.total) # Decimal('5.0000')

calculate(metrics: UsageMetrics) → CostBreakdown

Calculate credit cost for a single usage event.

Args: : metrics: Usage metrics including model, tokens, tool calls.

Returns: : CostBreakdown with per-dimension and total costs, all Decimal quantized to 4 dp. total is clamped to >= 0.

Raises: : ValueError: If the model is not found and no _default : exists in the config.
ExpressionError: If an expression evaluates unsafely (div/mod by : zero, non-finite, overflow).

calculate_batch(metrics_list: list[UsageMetrics]) → list[CostBreakdown]

Calculate credit costs for multiple usage events.

Args: : metrics_list: List of usage metrics to calculate.

Returns: : List of CostBreakdown objects, one per input.

classmethod from_dict(data: dict[str, Any]) → PricingEngine

Load engine from a config dictionary.

Args: : data: Dictionary representation of a pricing config.

Returns: : A new PricingEngine instance.

Raises: : ConfigError: If the config structure or expressions are invalid.

get_fixed_cost(job_name: str) → Decimal | None

Get the fixed credit cost for a named batch job.

Returns None for an unknown / unconfigured job so callers (the manager) can reject it rather than silently charging 0 (L1). Values are already Decimal (fractional fixed costs are charged exactly).

has_model(model_name: str) → bool

Check if a model name exists in the pricing config (exact match).

property min_balance : Decimal

Minimum balance users must keep (prevents spending last N credits).

pricing_schema() → PricingConfigData

Return the pricing config as a typed model.

Returns: : PricingConfigData with all pricing sections and expressions.

resolve_model(model_version: str) → str | None

Resolve a model version string to a pricing config key.

Tries exact match first, then prefix match (e.g. "claude-sonnet-4-20250514" -> "claude-sonnet-4"). Returns None when no match exists.