pub struct Budget {
pub limit_tokens: u64,
pub used_tokens: u64,
pub required_tokens: u64,
pub remaining_tokens: u64,
pub over_budget: bool,
pub bytes_per_token: u64,
pub tiers: Vec<TierSpend>,
}Expand description
The budget, and what became of it.
over_budget is the field to read and the one most likely to be misread. It does not
mean the compiler overspent by accident: every entry the budget has a say over is refused
the moment it would not fit, so the only way past the ceiling is through the entries that
may not be dropped — the seeds, the policy, the scope, a blocking rule. So
over_budget means the things this context cannot do without already cost more than you
allowed, and required_tokens is the explanation of it. The honest answer to that is to
say so, not to return a context missing the thing it was compiled about.
remaining_tokens is floored at zero rather than going negative, so it is safe to
display; the overspend is read from used_tokens against limit_tokens, which is why
both are carried.
use majordomus_cli::devcontext::{Budget, Tier, BYTES_PER_TOKEN};
use serde_json::json;
let tier = |name: &str, tokens: u64, required: usize| json!({
"tier": name, "meaning": "as this tier is for", "selected": 1,
"excluded": 0, "tokens": tokens, "required": required,
});
// the undroppable entries alone cost more than the caller allowed
let b: Budget = serde_json::from_value(json!({
"limit_tokens": 1_000,
"used_tokens": 2_500,
"required_tokens": 2_500,
"remaining_tokens": 0,
"over_budget": true,
"bytes_per_token": BYTES_PER_TOKEN,
"tiers": [tier("task", 2_000, 1), tier("governance", 500, 1)],
})).unwrap();
assert!(b.over_budget);
assert!(b.used_tokens > b.limit_tokens, "the overspend is read from these two");
assert_eq!(b.required_tokens, b.used_tokens, "all of it was undroppable");
assert_eq!(b.remaining_tokens, 0, "floored, so it is safe to display");
// the divisor is carried so a caller measuring tokens differently can convert
// rather than guess what the estimate meant
assert_eq!(b.bytes_per_token, BYTES_PER_TOKEN);
// and the tiers are reported in the order the budget spends in
let order: Vec<Tier> = b.tiers.iter().map(|t| t.tier).collect();
assert_eq!(order, [Tier::Task, Tier::Governance]);
assert!(order.windows(2).all(|w| w[0] < w[1]));Fields§
§limit_tokens: u64The ceiling this answer was compiled under, in estimated tokens.
used_tokens: u64What the survivors cost.
required_tokens: u64What the entries that cannot be dropped cost. Above the limit, the answer is over-budget and says so rather than dropping what it must keep.
remaining_tokens: u64limit - used, floored at zero.
over_budget: boolTrue when the required entries alone exceed the limit.
bytes_per_token: u64Bytes per token, the divisor the estimate uses.
tiers: Vec<TierSpend>Per tier, in the order the budget spends in.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for Budget
impl<'de> Deserialize<'de> for Budget
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl JsonSchema for Budget
impl JsonSchema for Budget
Source§fn schema_id() -> Cow<'static, str>
fn schema_id() -> Cow<'static, str>
Source§fn json_schema(generator: &mut SchemaGenerator) -> Schema
fn json_schema(generator: &mut SchemaGenerator) -> Schema
Source§fn inline_schema() -> bool
fn inline_schema() -> bool
$ref keyword. Read more