pub struct Session { /* private fields */ }Expand description
A session on a GitHub Copilot CLI server.
Created via Client::create_session or Client::resume_session.
Owns an internal event loop that dispatches events to the SessionHandler.
Protocol methods (send, get_messages, abort, etc.) automatically
inject the session ID into RPC params.
Call destroy for graceful cleanup (RPC + local). If dropped
without calling destroy, the Drop impl aborts the event loop and
unregisters from the router as a best-effort safety net.
Implementations§
Source§impl Session
impl Session
Sourcepub fn workspace_path(&self) -> Option<&Path>
pub fn workspace_path(&self) -> Option<&Path>
Workspace directory for the session (if using infinite sessions).
Sourcepub fn remote_url(&self) -> Option<&str>
pub fn remote_url(&self) -> Option<&str>
Remote session URL, if the session is running remotely.
Sourcepub fn capabilities(&self) -> SessionCapabilities
pub fn capabilities(&self) -> SessionCapabilities
Session capabilities negotiated with the CLI.
Capabilities are set during session creation and updated at runtime
via capabilities.changed events.
Sourcepub fn cancellation_token(&self) -> CancellationToken
pub fn cancellation_token(&self) -> CancellationToken
Returns a CancellationToken that fires when this session shuts
down (via Session::stop_event_loop, Session::destroy, or
Drop).
Use this to bind an external task’s lifetime to the session — when
the session shuts down, awaiting cancelled()
resolves so cooperative consumers can stop cleanly.
The returned handle is a child token: calling
cancel() on it cancels only the
caller’s child, not the session itself. To cancel the session, call
Session::stop_event_loop.
§Example
let token = session.cancellation_token();
tokio::select! {
_ = token.cancelled() => println!("session shut down"),
_ = tokio::time::sleep(std::time::Duration::from_secs(60)) => {
println!("60s elapsed, session still alive");
}
}Sourcepub fn subscribe(&self) -> EventSubscription
pub fn subscribe(&self) -> EventSubscription
Subscribe to events for this session.
Returns an EventSubscription
that yields every SessionEvent dispatched on this session’s
event loop. Drop the value to unsubscribe; there is no separate
cancel handle.
Observe-only. Subscribers receive a clone of every
SessionEvent but cannot influence permission decisions, tool
results, or anything else that requires returning a
HandlerResponse. Those remain
the responsibility of the SessionHandler passed via
SessionConfig::handler.
The returned handle implements both an inherent
recv method and
Stream, so callers can use a while let
loop or any combinator from tokio_stream::StreamExt /
futures::StreamExt.
Each subscriber maintains its own queue. If a consumer cannot keep
up, the oldest events are dropped and recv returns
RecvError::Lagged
reporting the count of skipped events. Slow consumers do not block
the session’s event loop.
§Example
let mut events = session.subscribe();
tokio::spawn(async move {
while let Ok(event) = events.recv().await {
println!("[{}] event {}", event.id, event.event_type);
}
});Sourcepub fn rpc(&self) -> SessionRpc<'_>
pub fn rpc(&self) -> SessionRpc<'_>
Typed RPC namespace for this session.
Every protocol method lives here under its schema-aligned path —
e.g. session.rpc().workspaces().list_files(). Wire method names
and request/response types are generated from the protocol schema,
so the typed namespace can’t drift from the wire contract.
The hand-authored helpers on Session delegate to this namespace
and remain the recommended entry point for everyday use; reach for
rpc() when you want a method without a hand-written wrapper.
Sourcepub async fn stop_event_loop(&self)
pub async fn stop_event_loop(&self)
Stop the internal event loop. Called automatically on destroy.
Cooperative: signals shutdown via the session’s CancellationToken
and awaits the loop’s natural exit rather than aborting the task.
Any in-flight handler (permission callback, tool call, elicitation
response) completes before the loop exits, so the CLI never sees a
half-handled request. See RFD-400 review finding #3.
Sourcepub async fn send(
&self,
opts: impl Into<MessageOptions>,
) -> Result<String, Error>
pub async fn send( &self, opts: impl Into<MessageOptions>, ) -> Result<String, Error>
Send a user message to the agent.
Accepts anything convertible to MessageOptions — pass a &str for the
trivial case, or build a MessageOptions for mode/attachments. The
wait_timeout field on MessageOptions is ignored here (use
send_and_wait if you need to wait).
Returns the assigned message ID, which can be used to correlate the
send with later SessionEvents emitted in
response (assistant messages, tool requests, etc.).
Returns an error if a send_and_wait call is
currently in flight, since the plain send would race with the waiter.
§Cancel safety
Cancel-safe. The underlying session.send RPC is dispatched
through the writer-actor (see Client::call),
so dropping this future after the actor has committed to writing
will not produce a partial frame on the wire. If the caller’s
future is dropped between “frame enqueued” and “response received”,
the message has already landed on the wire — the agent will process
it and emit events normally; the caller just won’t see the returned
message ID.
Sourcepub async fn send_and_wait(
&self,
opts: impl Into<MessageOptions>,
) -> Result<Option<SessionEvent>, Error>
pub async fn send_and_wait( &self, opts: impl Into<MessageOptions>, ) -> Result<Option<SessionEvent>, Error>
Send a user message and wait for the agent to finish processing.
Accepts anything convertible to MessageOptions — pass a &str for the
trivial case, or build a MessageOptions for mode/attachments/timeout.
Blocks until session.idle (success) or session.error (failure),
returning the last assistant.message event captured during streaming.
Times out after MessageOptions::wait_timeout (default 60 seconds).
Only one send_and_wait call may be active per session at a time.
Calling send while a send_and_wait
is in flight will also return an error.
§Cancel safety
Cancel-safe. A WaiterGuard clears the in-flight slot on every
exit path (success, internal failure, internal timeout, and
external cancellation via tokio::time::timeout / select! /
dropped JoinHandle). Subsequent send and send_and_wait calls on
this session will succeed normally — the slot is never leaked.
Sourcepub async fn get_messages(&self) -> Result<Vec<SessionEvent>, Error>
pub async fn get_messages(&self) -> Result<Vec<SessionEvent>, Error>
Retrieve the session’s message history.
Sourcepub async fn abort(&self) -> Result<(), Error>
pub async fn abort(&self) -> Result<(), Error>
Abort the current agent turn.
§Cancel safety
Cancel-safe. Single session.abort RPC; the underlying
Client::call is cancel-safe via the
writer-actor.
Sourcepub async fn set_model(
&self,
model: &str,
opts: Option<SetModelOptions>,
) -> Result<(), Error>
pub async fn set_model( &self, model: &str, opts: Option<SetModelOptions>, ) -> Result<(), Error>
Switch to a different model.
Pass None for opts if no extra configuration is needed.
Sourcepub async fn disconnect(&self) -> Result<(), Error>
pub async fn disconnect(&self) -> Result<(), Error>
Disconnect this session from the CLI.
Sends the session.destroy RPC, stops the event loop, and unregisters
the session from the client. Session state on disk (conversation
history, planning state, artifacts) is preserved, so the
conversation can be resumed later via Client::resume_session
using this session’s ID. To permanently remove all on-disk session
data, use Client::delete_session instead.
The caller should ensure the session is idle (e.g. send_and_wait
has returned) before disconnecting; in-flight tool or event handlers
may otherwise observe failures.
Sourcepub async fn destroy(&self) -> Result<(), Error>
pub async fn destroy(&self) -> Result<(), Error>
Alias for disconnect.
Named after the session.destroy wire RPC. Prefer disconnect in
new code — the wire-level “destroy” is misleading because on-disk
state is preserved.