Package com.tnsai.quality.cost
Class CostBudgetEnforcer
java.lang.Object
com.tnsai.quality.cost.CostBudgetEnforcer
- All Implemented Interfaces:
com.tnsai.hooks.spi.Hook<com.tnsai.hooks.events.PreAction>
public final class CostBudgetEnforcer
extends Object
implements com.tnsai.hooks.spi.Hook<com.tnsai.hooks.events.PreAction>
Hook that enforces a CostBudget on every pre-LLM
action (issue #82). Sits in the PreAction chain, matches
only on ActionType.LLM, and either:
allowsthe call when the budget is not exceeded;blocksit onBudgetPolicy.HARD_STOPwhen the spend so far + the pre-call estimate would exceed the cap;- logs a warning and allows on
BudgetPolicy.SOFT_WARN; - blocks (the only sensible action — the framework owns no queue
to defer into) on
BudgetPolicy.DEFER, with a clear message so the consumer can implement the deferral externally.
Pluggable concerns
- Budget resolution: the
FunctionbudgetResolvermaps aPreActionto the most-specificCostBudgetthat applies. ReturningOptional.empty()means "no budget configured for this scope, allow without enforcement". Implementations typically read a config map or a database. - Pre-call cost estimate: the
Functionestimatorreturns the predicted USD spend for a single call. The framework doesn't ship per-provider pricing today (seeLLMPricingRegistryfollow-up); a sensible default returnsBigDecimal.ZERO, in which case the enforcer only blocks after the cap is already hit, never before a borderline call.
Why a hook
Same SPI surface as every other intercept point; consumers wire it via the standardHookDispatcher alongside
security and audit hooks. No new framework primitive needed.- Since:
- 0.10.0 (issue #82 closeout)
-
Constructor Summary
ConstructorsConstructorDescriptionCostBudgetEnforcer(CostBudgetStore store, Function<com.tnsai.hooks.events.PreAction, Optional<CostBudget>> budgetResolver) Convenience for the common "don't pre-estimate" case — every call's cost is treated as 0, so the enforcer only fires after the cap is already crossed by recorded spend.CostBudgetEnforcer(CostBudgetStore store, Function<com.tnsai.hooks.events.PreAction, Optional<CostBudget>> budgetResolver, Function<com.tnsai.hooks.events.PreAction, BigDecimal> estimator) -
Method Summary
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface com.tnsai.hooks.spi.Hook
id
-
Constructor Details
-
CostBudgetEnforcer
public CostBudgetEnforcer(CostBudgetStore store, Function<com.tnsai.hooks.events.PreAction, Optional<CostBudget>> budgetResolver, Function<com.tnsai.hooks.events.PreAction, BigDecimal> estimator) -
CostBudgetEnforcer
public CostBudgetEnforcer(CostBudgetStore store, Function<com.tnsai.hooks.events.PreAction, Optional<CostBudget>> budgetResolver) Convenience for the common "don't pre-estimate" case — every call's cost is treated as 0, so the enforcer only fires after the cap is already crossed by recorded spend. Operators who want pre-estimate-driven blocking pass a real estimator.
-
-
Method Details
-
eventType
- Specified by:
eventTypein interfacecom.tnsai.hooks.spi.Hook<com.tnsai.hooks.events.PreAction>
-
matcher
public com.tnsai.hooks.HookMatcher<com.tnsai.hooks.events.PreAction> matcher()- Specified by:
matcherin interfacecom.tnsai.hooks.spi.Hook<com.tnsai.hooks.events.PreAction>
-
priority
public int priority()- Specified by:
priorityin interfacecom.tnsai.hooks.spi.Hook<com.tnsai.hooks.events.PreAction>
-
apply
public com.tnsai.hooks.HookResult<com.tnsai.hooks.events.PreAction> apply(com.tnsai.hooks.events.PreAction event) - Specified by:
applyin interfacecom.tnsai.hooks.spi.Hook<com.tnsai.hooks.events.PreAction>
-