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.