pub struct RunSpec {
pub prompt: String,
pub session_name: String,
pub effort: Option<Effort>,
pub deadline: Option<Duration>,
pub tool_budget: Option<usize>,
pub token_budget: Option<u64>,
pub budget: Option<BudgetPool>,
}Expand description
One run’s worth of intent, to be minted against a Workspace.
Built the way every other config in basis is built — new plus with_*
methods that return new values — so a caller can keep one spec as a template
and derive each run’s from it without the derivations interfering.
A bare prompt converts, because that is the common case:
let run = workspace.prepare("what does this repo do?")?;Fields§
§prompt: StringWhat to ask. May be empty: a conversation opened before anything is
typed is a real state, and the check happens where a prompt is actually
sent — see Workspace::prepare.
session_name: String§effort: Option<Effort>How hard the model should think. None leaves the provider’s default;
unsupported provider/model levels fail instead of being downgraded.
deadline: Option<Duration>Gives up on the run after this long.
Unset by default, and unset for an unattended caller too. An attended run has a person watching, who can tell “thinking hard” from “stuck” in a way no timer can; a caller nobody is watching has to write the bound down in advance, and with no scheduler shipped there is no period for basis to guess one from (ADR-0014).
tool_budget: Option<usize>Caps how many tool calls the run may make.
token_budget: Option<u64>Caps the tokens the run may report using, input plus output.
Soft by construction: usage is only known once a round has streamed in full, so the round that crosses the line always finishes. This is the bound that maps to money.
budget: Option<BudgetPool>An allowance this run shares with the others drawing on it.
Where token_budget is this run’s own ceiling, a
BudgetPool is the job’s — the one figure a fan-out spends from
together. A spec carrying both stops at whichever binds first.
The one field here that is shared rather than copied: deriving a second
spec from this one gives it a handle on the same pool, which is the
point. See BudgetPool for why that exception exists and what it
costs.
Implementations§
Source§impl RunSpec
impl RunSpec
pub fn new(prompt: impl Into<String>) -> Self
pub fn with_prompt(self, prompt: impl Into<String>) -> Self
pub fn with_session_name(self, session_name: impl Into<String>) -> Self
Sourcepub fn with_effort(self, effort: Effort) -> Self
pub fn with_effort(self, effort: Effort) -> Self
Asks the model to think harder, where the provider supports it.
Sourcepub fn with_deadline(self, deadline: Duration) -> Self
pub fn with_deadline(self, deadline: Duration) -> Self
Gives up on the run after deadline.
Every bound here is a graceful end rather than a discarded run: the event stream closes the way it always does, and whatever the model committed before the bound tripped is kept. That is what makes bounding an unattended run safe to do — the alternative, throwing the work away for being one round too long, would make callers reluctant to set one.
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 the run may make.
Sourcepub fn with_token_budget(self, token_budget: u64) -> Self
pub fn with_token_budget(self, token_budget: u64) -> Self
Caps the tokens the run may report using, input plus output.
Soft: the round that crosses the line is allowed to finish, because usage is only known once a round has streamed in full.
Sourcepub fn with_budget(self, budget: BudgetPool) -> Self
pub fn with_budget(self, budget: BudgetPool) -> Self
Draws this run’s tokens from an allowance shared with other runs.
The line a fan-out is written on — BudgetPool::spec is this call with
the prompt folded in:
let pool = BudgetPool::new(500_000);
let run = workspace.prepare(RunSpec::new("review the tests").with_budget(pool.clone()))?;Every turn the minted run performs draws here, not just the first, so a conversation and a one-shot are bounded the same way.
Sourcepub fn turn_options(&self) -> TurnOptions
pub fn turn_options(&self) -> TurnOptions
The bounds this spec puts on every turn the run performs.
Limits only. Cancellation and the graceful stop signal are per-call
things a caller holds a token for, not configuration, so they stay at
their defaults here and arrive through
send_with_options.
Trait Implementations§
Source§impl Default for RunSpec
A run with nothing said yet — what a protocol server opens on session/new.
impl Default for RunSpec
A run with nothing said yet — what a protocol server opens on session/new.
impl Eq for RunSpec
impl StructuralPartialEq for RunSpec
Auto Trait Implementations§
impl Freeze for RunSpec
impl RefUnwindSafe for RunSpec
impl Send for RunSpec
impl Sync for RunSpec
impl Unpin for RunSpec
impl UnsafeUnpin for RunSpec
impl UnwindSafe for RunSpec
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.