pub struct AssistantSessions { /* private fields */ }Expand description
Every assistant session this server knows about.
Implementations§
Source§impl AssistantSessions
impl AssistantSessions
Sourcepub async fn create(
&self,
subject: &str,
harness: Option<&str>,
account: Option<&str>,
title: Option<String>,
) -> Result<AssistantSessionSummary, AssistantSessionError>
pub async fn create( &self, subject: &str, harness: Option<&str>, account: Option<&str>, title: Option<String>, ) -> Result<AssistantSessionSummary, AssistantSessionError>
Open a session on a catalogue harness.
Records the session; the harness starts on the first turn. The returned
summary therefore reports dormant — no process, and continuable — which
is the truthful answer for a conversation nobody has said anything in
yet.
The pick is REMEMBERED, caller-scoped, so the next new-conversation form opens on the harness this operator last used. It is written from what they actually opened rather than from a preference they set, and it is written only after the session record exists — a remembered pick for a session that was refused would be a choice nobody made.
§Errors
[AssistantSessionError::NotCommissioned] when the store is unusable,
[AssistantSessionError::UnknownHarness] / UnknownAccount when the
caller names one that does not exist,
[AssistantSessionError::HarnessUnavailable] when the chosen harness’s
launch program is not on this server’s PATH — refused HERE rather than
accepted and failed at the first message — or whatever the store reports.
Sourcepub async fn current(
&self,
subject: &str,
) -> Result<Option<AssistantSessionSummary>, AssistantSessionError>
pub async fn current( &self, subject: &str, ) -> Result<Option<AssistantSessionSummary>, AssistantSessionError>
The caller’s CURRENT session: the newest one that is not ended.
One thread is the shape an operator actually holds — the dock panel and the inline editor bar are two views of ONE conversation, not two conversations — so “which session am I in” is a first-class read rather than something each surface derives from a list and could derive differently.
Ok(None) when the caller has no continuable session. That is an
absence, not a refusal: a caller with no session is the ordinary state
of somebody who has not started one.
§Errors
Whatever the store reports.
Sourcepub async fn read(
&self,
subject: &str,
session_id: AssistantSessionId,
) -> Result<(AssistantSessionSummary, Vec<AssistantSessionFrame>), AssistantSessionError>
pub async fn read( &self, subject: &str, session_id: AssistantSessionId, ) -> Result<(AssistantSessionSummary, Vec<AssistantSessionFrame>), AssistantSessionError>
A session’s summary and its whole transcript.
§Errors
Not found (including another subject’s session), or whatever the store reports.
Sourcepub async fn watch(
&self,
subject: &str,
session_id: AssistantSessionId,
after: Option<u64>,
) -> Result<(Vec<AssistantSessionFrame>, Receiver<AssistantSessionFrame>), AssistantSessionError>
pub async fn watch( &self, subject: &str, session_id: AssistantSessionId, after: Option<u64>, ) -> Result<(Vec<AssistantSessionFrame>, Receiver<AssistantSessionFrame>), AssistantSessionError>
The transcript so far, then every frame as it arrives.
The replay is read BEFORE the subscription is taken so nothing can land between the two: a frame committed after the read and before the subscribe would be in neither, and a client would have a hole it could not see. Taking the receiver first means the worst case is a DUPLICATE frame, which a client can drop by index.
§Errors
Not found, or whatever the store reports.
Sourcepub async fn push_context(
&self,
subject: &str,
session_id: AssistantSessionId,
context: AssistantTurnContext,
) -> Result<(), AssistantSessionError>
pub async fn push_context( &self, subject: &str, session_id: AssistantSessionId, context: AssistantTurnContext, ) -> Result<(), AssistantSessionError>
Share the operator’s on-screen context without asking anything.
Appended to the transcript, which IS the shared context: the harness’s
assistant_context tool reads the latest one, and both console surfaces
read the same record. There is no second store to keep in step.
§Errors
Not found, or whatever the store reports.
Sourcepub async fn turn(
&self,
subject: &str,
session_id: AssistantSessionId,
text: String,
context: Option<AssistantTurnContext>,
command: Option<AssistantCommandInvocation>,
) -> Result<String, AssistantSessionError>
pub async fn turn( &self, subject: &str, session_id: AssistantSessionId, text: String, context: Option<AssistantTurnContext>, command: Option<AssistantCommandInvocation>, ) -> Result<String, AssistantSessionError>
Ask the agent something.
Starts the harness when none is running — freshly for a session that has
never opened, or with session/load for a dormant one whose agent can
reload its own conversation.
§Errors
Not found; [AssistantSessionError::Busy] when a turn is already open;
[AssistantSessionError::Ended] when the session cannot be continued;
[AssistantSessionError::HarnessFailed] when the harness will not start.
Sourcepub async fn cancel(
&self,
subject: &str,
session_id: AssistantSessionId,
) -> Result<(), AssistantSessionError>
pub async fn cancel( &self, subject: &str, session_id: AssistantSessionId, ) -> Result<(), AssistantSessionError>
Stop the open turn.
§Errors
Not found, or [AssistantSessionError::Ended] when no process is
running to cancel.
Sourcepub async fn set_config_option(
&self,
subject: &str,
session_id: AssistantSessionId,
option_id: &str,
value: &Value,
) -> Result<Vec<AssistantConfigOption>, AssistantSessionError>
pub async fn set_config_option( &self, subject: &str, session_id: AssistantSessionId, option_id: &str, value: &Value, ) -> Result<Vec<AssistantConfigOption>, AssistantSessionError>
Set one advertised configuration option on a live session — the model picker’s write side.
Refused BY NAME when the harness has not advertised the option, or (for
a select) the value: a client offers what the session’s
config_options say, and anything else is a control that should never
have been on the screen — the exact rule turns follow for commands. The
agent’s answer, the full option set as it now stands, is recorded on
the transcript exactly as an advertisement is (which also refreshes the
record’s cache), and returned.
§Errors
Not found / not yours; [AssistantSessionError::UnknownConfigOption]
for an unadvertised option or value, or a value of the wrong shape;
[AssistantSessionError::Ended] when no process is running;
[AssistantSessionError::HarnessFailed] when the agent refuses, the
transport fails, or the answer cannot be read as an option set.
Sourcepub async fn resume(
&self,
subject: &str,
session_id: AssistantSessionId,
) -> Result<AssistantSessionSummary, AssistantSessionError>
pub async fn resume( &self, subject: &str, session_id: AssistantSessionId, ) -> Result<AssistantSessionSummary, AssistantSessionError>
Say whether a session can be continued, settling it when it cannot.
There is no promptless spawn to perform here — ACP opens a conversation
by asking something — so this does not start a process. What it does is
make the resume decision READABLE before an operator types: a session
whose agent never advertised loadSession is settled ended by an
appended record naming the capability, so the panel can say so instead of
offering a box that would refuse.
§Errors
Not found, or whatever the store reports.
Sourcepub async fn delete(
&self,
subject: &str,
session_id: AssistantSessionId,
) -> Result<(), AssistantSessionError>
pub async fn delete( &self, subject: &str, session_id: AssistantSessionId, ) -> Result<(), AssistantSessionError>
Put a session away: shut its harness down and settle it.
The transcript is KEPT. Deleting a session deletes a process, not a record — an operator reading back what an agent did a week ago is exactly who this surface exists for.
What it settles to follows the same fact every resume decision follows:
whether the agent can reload the conversation. A session whose agent
advertised loadSession and left a handle settles
AssistantSessionState::Closed — out of the operator’s way, never
current, but reopened by the next turn taken on it from history. One
whose agent cannot reload settles AssistantSessionState::Ended, and
the transcript is all that is left of it.
§Errors
Not found, or whatever the store reports.
Sourcepub async fn sweep_orphans(&self) -> Result<usize, AssistantSessionError>
pub async fn sweep_orphans(&self) -> Result<usize, AssistantSessionError>
Settle every session whose process is gone, at boot.
WRITTEN BACK, not merely displayed: the settlement is an appended record with its cause, so the next reader projects it rather than recomputing the same decision — and so the decision itself is auditable.
Returns how many sessions were settled.
§Errors
Whatever the store reports.
Source§impl AssistantSessions
impl AssistantSessions
Sourcepub fn new(
store: Arc<dyn AssistantSessionStore>,
config: ResolvedAssistantConfig,
endpoint: Option<AssistantEndpoints>,
catalogue: &'static [CatalogueHarness],
) -> Self
pub fn new( store: Arc<dyn AssistantSessionStore>, config: ResolvedAssistantConfig, endpoint: Option<AssistantEndpoints>, catalogue: &'static [CatalogueHarness], ) -> Self
Build the registry over one durable store and the operator’s configuration.
Sourcepub fn config(&self) -> &ResolvedAssistantConfig
pub fn config(&self) -> &ResolvedAssistantConfig
The operator’s resolved [assistant] configuration.
Sourcepub fn availability(&self) -> Availability
pub fn availability(&self) -> Availability
Whether this server can open a session at all, and why not when it cannot.
A stock server can: there is no [assistant] section to write, the
harness catalogue ships with the build, and “not configured” is no longer
a reason anything may give (RULED 2026-08-29). What CAN take the surface
down is the durable store the sessions live in — a session is a record
and a transcript before it is a process — and that is a refusal the
product can name, with the store’s own error in it.
Read from the boot sweep, which is the one place this server has already exercised the store end to end. Nothing probes on the descriptor path: a full listing per description would make the panel’s own refresh the heaviest read on the box.
Whether a PARTICULAR harness can run is a different question with a
different answer per entry, and it is answered on the descriptor’s
harnesses[] (available, with the install hint) rather than folded
into one sentence here.
Sourcepub async fn last_harness_pick(
&self,
subject: &str,
) -> Result<Option<String>, AssistantSessionError>
pub async fn last_harness_pick( &self, subject: &str, ) -> Result<Option<String>, AssistantSessionError>
The harness this caller last opened a session on, or None.
Read from the store, so it survives the restart that a remembered
in-process choice would not. None is a complete answer — a caller who
has picked nothing has picked nothing — and the console preselects the
first available catalogue entry rather than the server inventing one.
§Errors
Whatever the store reports.
Sourcepub fn hands_over_assistant_tools(&self) -> bool
pub fn hands_over_assistant_tools(&self) -> bool
Whether a session’s agent is handed this server’s own assistant tool
server — the assistant_context route.
Independent of [mcp] enabled and of [assistant.tools] aion: the only
thing that can take it away is this server being unable to state an
address an agent could dial back on.
Sourcepub fn hands_over_general_mcp(&self) -> bool
pub fn hands_over_general_mcp(&self) -> bool
Whether a session’s agent is handed this server’s GENERAL MCP endpoint — the workflow tools.
One switch, [mcp] enabled, and no second one: the [assistant.tools] aion knob was retired with the rest of the section. Whether this server
publishes workflow tools at all is a question an operator answers once,
where the tools are; asking it again under the assistant would be a
second thing to keep in step, and a session whose agent silently lacked
the tools the server publishes is exactly the confusion that costs.
Sourcepub async fn record(
&self,
session_id: AssistantSessionId,
) -> Result<Option<AssistantSessionRecord>, AssistantSessionError>
pub async fn record( &self, session_id: AssistantSessionId, ) -> Result<Option<AssistantSessionRecord>, AssistantSessionError>
One session’s record, with NO caller narrowing.
The narrowed read (Self::owned_record) is for a human caller, whose
authority is a subject. The assistant MCP route’s caller is a SESSION —
it holds that session’s own minted bearer and no subject at all — so it
reads the record it is about to prove it is, and the proof is the digest
comparison rather than a subject match.
§Errors
Whatever the store reports.
Sourcepub async fn state_of_session(
&self,
session_id: AssistantSessionId,
) -> Result<(AssistantSessionState, Option<String>), AssistantSessionError>
pub async fn state_of_session( &self, session_id: AssistantSessionId, ) -> Result<(AssistantSessionState, Option<String>), AssistantSessionError>
A session’s projected state and cause.
The public read of Self::state_of, for the assistant MCP route: a
bearer is honoured only while the session it names is not ended, and
that decision has to read the same projection every other surface reads.
§Errors
Whatever the store reports.
Sourcepub async fn list(
&self,
subject: &str,
) -> Result<Vec<AssistantSessionSummary>, AssistantSessionError>
pub async fn list( &self, subject: &str, ) -> Result<Vec<AssistantSessionSummary>, AssistantSessionError>
Every session this caller owns, newest first.
CALLER-scoped, not namespace-scoped: a session is one operator’s conversation with an agent and lives in no namespace. The store enumerates what it holds and the narrowing happens here, where the caller identity is.
§Errors
Whatever the store reports.
Sourcepub async fn latest_context(
&self,
session_id: AssistantSessionId,
) -> Result<Option<AssistantTurnContext>, AssistantSessionError>
pub async fn latest_context( &self, session_id: AssistantSessionId, ) -> Result<Option<AssistantTurnContext>, AssistantSessionError>
The most recently shared on-screen context for a session.
What the assistant_context MCP tool answers with, read off the
transcript: the transcript IS the shared context, so there is no second
store to keep in step and a restart loses nothing.
§Errors
Whatever Self::projection reports.
Trait Implementations§
Source§impl Clone for AssistantSessions
impl Clone for AssistantSessions
Source§fn clone(&self) -> AssistantSessions
fn clone(&self) -> AssistantSessions
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl !RefUnwindSafe for AssistantSessions
impl !UnwindSafe for AssistantSessions
impl Freeze for AssistantSessions
impl Send for AssistantSessions
impl Sync for AssistantSessions
impl Unpin for AssistantSessions
impl UnsafeUnpin for AssistantSessions
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<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoMaybeUndefined<T> for T
impl<T> IntoMaybeUndefined<T> for T
Source§fn into_maybe_undefined(self) -> MaybeUndefined<T>
fn into_maybe_undefined(self) -> MaybeUndefined<T>
Source§impl<T> IntoOption<T> for T
impl<T> IntoOption<T> for T
Source§fn into_option(self) -> Option<T>
fn into_option(self) -> Option<T>
Source§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request