pub struct TurnOptions {
pub cancel: Option<CancellationToken>,
pub stop: Option<CancellationToken>,
pub bounds: Bounds,
pub absolute_deadline: Option<SystemTime>,
pub model_budget: Option<usize>,
pub provider_retry: Option<ProviderRetry>,
pub retry_budget: Option<usize>,
pub budget: Option<BudgetPool>,
pub round_strategy: Option<Arc<dyn RoundStrategy>>,
}Expand description
Limits and stop signals for a single turn.
basis’s own type rather than a re-export of mentra’s RunOptions: the same
reasoning as Event — basis owns its surface so mentra’s
internals can move without breaking basis’s callers. Only the knobs a harness
actually needs are exposed; the rest stay at mentra’s defaults.
Fields§
§cancel: Option<CancellationToken>Trips to abandon the turn. The turn fails and is rolled back — what a client’s stop button means.
stop: Option<CancellationToken>Trips to end the turn gracefully at the next round boundary, keeping what the model has already committed.
One caveat, upstream and honest: mentra ends the turn but still owes its
caller a final assistant message, so a stop that lands after a tool
round — where the last committed message is the tool’s result — comes
back as a failed turn even though nothing was rolled back. The work is
kept either way; the report is what disagrees. basis’s
tests/cancellation.rs pins that behavior so a change to it is noticed.
A stopped turn reports no Bound, unlike a spent
Bounds::token_budget. A bound is an allowance the
run outgrew, and a script is right to retry one with a bigger number; a
stop is an instruction whoever holds this token issued, and retrying it
would undo their decision.
bounds: BoundsWhat this one call may spend — deadline, tool budget, token budget.
One caveat here beyond what Bounds itself says, and it matters: a
token budget ends the turn gracefully, and the caveat on
stop about how a graceful end is reported applies — a
turn stopped after a tool round comes back failed for want of a final
message, and without the named bound that failure is indistinguishable
from a provider’s. basis’s tests/token_budget.rs drives exactly
that shape.
absolute_deadline: Option<SystemTime>An exact wall-clock deadline for this turn.
The absolute sibling of Bounds::deadline. Builder calls treat the
two as one last-writer-wins dimension; if a direct struct literal sets
both, the absolute value wins when the Mentra options are built.
model_budget: Option<usize>Maximum main-model requests this turn may issue, including retries.
Some(0) is meaningful: refuse before the first provider request.
provider_retry: Option<ProviderRetry>Per-turn override for the runtime’s provider retry schedule.
retry_budget: Option<usize>Per-turn override for the runtime’s retry count after the initial call.
Some(0) disables retries. The schedule and count override
independently so changing one retains the runtime fallback for the
other.
budget: Option<BudgetPool>An allowance this turn shares with every other run drawing on it.
The other kind of token bound, and the two compose rather than compete:
Bounds::token_budget says what this turn may spend, a
pool says what the whole job may, and a turn carrying both stops at
whichever comes first. See BudgetPool for how that is arranged, and
for the overshoot a shared soft bound implies.
A turn drawing on a pool with nothing left is refused before its prompt
is sent, with RunError::BudgetExhausted.
round_strategy: Option<Arc<dyn RoundStrategy>>A policy consulted at each round boundary of this one call — after a committed tool round, and after a committed tool-free assistant message before the turn returns it.
The steering surface: at either boundary the strategy may proceed,
inject a corrective user turn and run another round, switch the model
or reasoning for the rounds that follow
(RoundAdjustment), or end the turn
gracefully. None — the default — reproduces the round loop exactly as
it runs without one; a strategy that always proceeds is inert.
Per call, like the two tokens above and unlike
bounds: mentra binds a strategy to exactly one run so
its state cannot leak into another, and a configured fallback here
would quietly share one strategy’s state across every turn of a
conversation. A caller that wants the same policy each turn attaches it
each turn.
Every decision still passes the run’s bounds: an injected round is a
normal round, refused like any other once a budget is spent or a
deadline passed. A strategy’s stop is the reverse — an instruction,
not an allowance — so a turn it ends reports no
Bound, exactly as stop does, and the
caveat there about a stop that lands after a tool round applies to a
strategy’s stop unchanged. basis’s tests/round_strategy.rs pins
both facts.
Arc because that is how mentra carries it — the strategy is shared
with the runner, not copied — and a host usually holds its half to read
what the strategy observed after the turn.
Implementations§
Source§impl TurnOptions
impl TurnOptions
Sourcepub fn cancellable() -> (Self, CancellationToken)
pub fn cancellable() -> (Self, CancellationToken)
A turn that can be abandoned through the returned token.
What a client’s stop button trips: the turn fails with
RunOutcome::Error and mentra rolls it back, so the session is left
as it was before the prompt. For “stop when you have enough, and keep
it”, see stoppable.
Sourcepub fn stoppable() -> (Self, CancellationToken)
pub fn stoppable() -> (Self, CancellationToken)
A turn that can be ended gracefully through the returned token.
The other half of the pair, and the difference is what happens to the
work: this one lets the round in flight finish and keeps everything the
model committed, where cancellable throws the
turn away. A caller watching the stream and deciding it has read enough
wants this one; a caller whose user pressed stop wants the other. Mind
the caveat on stop about how the kept work is reported.
Sourcepub fn with_cancel(self, cancel: CancellationToken) -> Self
pub fn with_cancel(self, cancel: CancellationToken) -> Self
Attaches a token that abandons the turn — for a caller that already holds one, because it arms the token before it knows which turn it will stop.
Sourcepub fn with_stop(self, stop: CancellationToken) -> Self
pub fn with_stop(self, stop: CancellationToken) -> Self
Attaches a token that ends the turn gracefully at the next round boundary.
Sourcepub fn with_deadline(self, deadline: Duration) -> Self
pub fn with_deadline(self, deadline: Duration) -> Self
Gives up on the turn after deadline. Sugar into
bounds.
Sourcepub fn with_absolute_deadline(self, deadline: SystemTime) -> Self
pub fn with_absolute_deadline(self, deadline: SystemTime) -> Self
Gives up at the exact wall-clock deadline.
Clears a relative deadline already present; a later
with_deadline clears this in turn.
Sourcepub fn with_model_budget(self, model_budget: usize) -> Self
pub fn with_model_budget(self, model_budget: usize) -> Self
Caps how many main-model requests this turn may issue.
Sourcepub fn with_provider_retry(self, provider_retry: ProviderRetry) -> Self
pub fn with_provider_retry(self, provider_retry: ProviderRetry) -> Self
Overrides the runtime’s provider retry schedule for this turn.
Sourcepub fn with_retry_budget(self, retry_budget: usize) -> Self
pub fn with_retry_budget(self, retry_budget: usize) -> Self
Overrides how many retries this turn gets after its initial call.
Sourcepub fn with_tool_budget(self, tool_budget: usize) -> Self
pub fn with_tool_budget(self, tool_budget: usize) -> Self
Caps how many tool calls this turn may make. Sugar into
bounds.
Sourcepub fn with_token_budget(self, token_budget: u64) -> Self
pub fn with_token_budget(self, token_budget: u64) -> Self
Caps the tokens this turn may report using. Sugar into
bounds.
Sourcepub fn with_budget(self, budget: BudgetPool) -> Self
pub fn with_budget(self, budget: BudgetPool) -> Self
Draws this turn’s tokens from an allowance shared with other runs.
Immutable like the rest — a new value, the same pool. That is the whole
shape of the exception BudgetPool makes: options are copied, the
allowance is shared.
Sourcepub fn with_round_strategy(self, strategy: Arc<dyn RoundStrategy>) -> Self
pub fn with_round_strategy(self, strategy: Arc<dyn RoundStrategy>) -> Self
Steers this one call through strategy, consulted at each round
boundary. See round_strategy for what a
strategy may decide and what it can never override.
Trait Implementations§
Source§impl Clone for TurnOptions
impl Clone for TurnOptions
Source§impl Debug for TurnOptions
By hand because a strategy is opaque: presence is the only honest thing a
debug line can say about a dyn policy, and deriving would instead forbid
Debug on every struct that embeds these options.
impl Debug for TurnOptions
By hand because a strategy is opaque: presence is the only honest thing a
debug line can say about a dyn policy, and deriving would instead forbid
Debug on every struct that embeds these options.