Skip to main content

RunUsage

Struct RunUsage 

Source
pub struct RunUsage {
    pub input_tokens: u64,
    pub output_tokens: u64,
    pub cache_read_tokens: u64,
    pub cache_creation_tokens: u64,
    pub reasoning_tokens: u64,
    pub thoughts_tokens: u64,
    pub model_responses: u32,
}
Expand description

What a run reported spending, summed over the rounds it took.

mentra emits one usage report per completed model response, carrying that round’s numbers rather than a running total — its own soft token budget is a sum of them, and so is this. A turn that took four rounds reports four times and lands here as one figure.

Four things to know before treating this as a bill.

It is reported, not measured. A provider that says nothing leaves this at zero. Basis records the reports through the run’s synchronous observer, so a lagging presentation stream cannot make the in-process tally undercount.

It counts every model call the run reported, summarizing passes included. A compaction that happens inside a run — automatic, context-overflow recovery, or the model’s own compact intrinsic — is a provider request like any other, and since mentra 0.26 it reports like one: one UsageReport per provider sample, emitted after the compaction’s own events, folded in here through the same observer, and added to mentra’s own token_budget counter — and so to any BudgetPool — at the same point. That is real spend truthfully accounted, not inflation: the summarizing request was always billed, it just used to be invisible here (the pre-0.26 engine dropped the response’s usage on the floor). The one summarizing pass this figure never carries is the standalone PreparedRun::compact, which is not a run and returns no report — its samples reach the caller as Event::Usage lines on the sink the pass borrows, and the stream is the account for that verb.

It counts the rounds of the run’s own agent and of the work that agent delegates. A delegating tool — basis’s spawn, or mentra’s own task intrinsic — drives its subagent on the parent run’s RunOptions::child and relays the child’s usage reports onto the parent’s bus, so a delegated round arrives here like any other. Indistinguishable from the parent’s own, which is consistent with the accounting being aggregate: mentra’s usage report carries no agent id for anyone to attribute by. Summing the stream and reading this figure therefore give one answer, and it is the same answer TurnOptions::token_budget and BudgetPool are enforced against, because the child shares the parent’s accounting handle rather than getting one of its own.

Both halves had to be built for that to hold. The shared counter came first, and until mentra made its event relay public the two disagreed for basis’s own delegations: the bound saw a delegated round and the tally did not, so a run could stop on a total it reported a fraction of.

One edge survives, and it fails loudly rather than leaking: a delegation issued once the shared budget is already crossed inherits an allowance with nothing left in it, does zero rounds, and comes back as a failed tool call instead of an empty success. That is the round-boundary softness TurnOptions::token_budget already describes, seen from the delegating side, and mentra pins it (delegating_with_the_budget_already_spent_fails_the_delegation).

And cache tokens are counted but never mixed in — see total_tokens.

It is serializable because the same four numbers are what Event::RunFinished puts on the wire and what basis’s CLI records beside a finished task: one shape, so a host reading the stream and a host holding the report cannot disagree about what a run cost.

Fields§

§input_tokens: u64§output_tokens: u64§cache_read_tokens: u64§cache_creation_tokens: u64§reasoning_tokens: u64

Reasoning the model did inside output_tokens — the Responses wire counts it there, so adding it to the total would count it twice.

§thoughts_tokens: u64

Thinking the model did outside output_tokens — Gemini counts its thoughts beside the candidates, not in them. Two fields rather than one sum because a sum would be wrong for one of the two wires, and a reader who wants “how much did it think” adds them; one who wants “what was I billed for output” must not. Absent from a record written before the split, both read as zero.

§model_responses: u32

Completed model responses that reported usage. This distinguishes a provider-reported all-zero response from a provider that reported no usage at all.

Implementations§

Source§

impl RunUsage

Source

pub const fn total_tokens(&self) -> u64

Input plus output — what RunSpec::with_token_budget counts.

Cache reads and cache writes are left out for the same reason mentra leaves them out of the budget it enforces: they are priced differently everywhere, and a total that mixed them would answer no question exactly.

Source

pub const fn plus(self, other: Self) -> Self

This total plus other’s — how a caller adds up several runs.

The shape a shared budget wants: a fan-out folds its reports into one figure without any of the runs knowing about the others.

Trait Implementations§

Source§

impl Clone for RunUsage

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for RunUsage

Source§

impl Debug for RunUsage

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for RunUsage

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for RunUsage

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Eq for RunUsage

Source§

impl PartialEq for RunUsage

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for RunUsage

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for RunUsage

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more