pub struct Session { /* private fields */ }Expand description
One driven agent session. Owns the conversation history across runs: a
second Session::run on the same session continues the same conversation
(ADR-0016) — the exact call shape an interactive frontend needs for
follow-up turns.
Construct with Session::new, then call Session::run (or
Session::run_text) to drive one run to a terminal state. run is
infallible — every terminal condition (including provider and Fatal tool
errors) is captured in the returned Report’s status/error, so a caller
gets a structured result every time (locode-exec maps status → exit code).
Each Report is per-run: turns/usage/tool_calls count the current
run only (a cumulative view is derivable from the event stream). Continuing
after a failed run is allowed unconditionally — for ModelError the history
simply didn’t advance, and for Error the transcript was fully paired before
the break; the pre-send pairing repair heals any residue on the next sample.
Implementations§
Source§impl Session
impl Session
Sourcepub fn new(
provider: Arc<dyn Provider>,
registry: Registry,
preamble: Vec<Message>,
config: EngineConfig,
sink: Box<dyn EventSink>,
) -> Session
pub fn new( provider: Arc<dyn Provider>, registry: Registry, preamble: Vec<Message>, config: EngineConfig, sink: Box<dyn EventSink>, ) -> Session
Assemble a session from its parts.
preamble is the base System + Developer messages (the pack supplies
these); provider/sink are trait objects so the binary can select them at
runtime.
Sourcepub fn with_approver(self, approver: Arc<dyn Approver>) -> Session
pub fn with_approver(self, approver: Arc<dyn Approver>) -> Session
Install an Approver consulted before every tool call (ADR-0017).
Builder-style so Session::new’s signature stays intact. The default
is AllowAll — headless consumers are unchanged without this call.
Sourcepub fn set_model(&mut self, provider: Arc<dyn Provider>, model: &str) -> Message
pub fn set_model(&mut self, provider: Arc<dyn Provider>, model: &str) -> Message
Switch the model this session samples with, mid-conversation.
The caller rebuilds the provider (the registry’s factory already takes a model override) and hands it in; this swaps it and updates the config so the trace’s later records name the model actually in use.
The preamble is not rewritten. A pack’s system prompt may name the model —
Claude Code’s env block does, and so does our port — and after a switch that line
is stale. Rewriting the System message would desync the transcript from the
trace, whose Init record already captured the original preamble: a resumed
session would replay one preamble while the live session had another. So the
change is announced instead, as an appended <system-reminder> — the same
never-mutate-history discipline project instructions and skills already follow.
Returns the announcement, which the caller appends and emits like any other message. (Doing it here would bypass the sink the caller owns.)
Sourcepub fn add_root(&mut self, root: PathBuf)
pub fn add_root(&mut self, root: PathBuf)
Register another discovery root, so the next turn’s instruction and skill
rescans see that directory’s AGENTS.md and .agents/skills.
Only the config changes here — widening the tool jail is the host’s
job (Host::add_root), and the caller does both. Both discoveries
already re-run per turn (ADR-0023 whole-body diff, ADR-0025 post-run
rescan), so nothing needs re-injecting by hand: the added root simply
appears in the next scan.
Sourcepub fn input_queue(&self) -> InputQueue
pub fn input_queue(&self) -> InputQueue
A clonable handle to this session’s mid-run input queue (ADR-0028).
Clone it before calling Session::run — run takes &mut self,
so nothing on the session is reachable while a turn is in flight. Same
shape as Session::cancel_handle and for the same reason.
Sourcepub fn set_effort(&mut self, effort: Option<ReasoningEffort>)
pub fn set_effort(&mut self, effort: Option<ReasoningEffort>)
Set the reasoning effort subsequent turns sample with.
Unlike Session::set_model this announces nothing: effort changes how
hard the model thinks, not who it is, so there is no stale statement in
the transcript to correct — and injecting a reminder would cost a cache
breakpoint for no gain.
Sourcepub fn announce(&mut self, message: Message)
pub fn announce(&mut self, message: Message)
Append a message to the conversation and emit it, exactly as a turn would.
Sourcepub fn history(&self) -> &[Message]
pub fn history(&self) -> &[Message]
The conversation so far: the preamble plus every appended turn across all runs on this session (ADR-0016). Lets a frontend render the transcript after a run without replaying the event stream.
Sourcepub fn cancel_handle(&self) -> CancellationToken
pub fn cancel_handle(&self) -> CancellationToken
The cancellation handle for the current run (ADR-0018).
Clone it before calling Session::run (mandatory — run takes
&mut self, so nothing is callable mid-run) and move it into an Esc
handler, signal handler, or timeout. Firing it stops the run at the
next observation point — mid-sample (the in-flight request is
aborted), between batch calls (the rest of the batch is paired
synthetically), or at the loop top — and the run returns a report with
Status::Cancelled. Partial work is
preserved: with session continuity, the next run() continues the
same conversation.
The token is per-run, replaced when run returns: a cancel landing
after the run ended hits the retired token — a harmless no-op — so the
Esc-lands-late race is resolved by construction. Re-fetch the handle
each turn. cancel() is idempotent; there is no reset.