Skip to main content

Session

Struct Session 

Source
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

Source

pub fn id(&self) -> &SessionId

Session ID assigned by the CLI.

Source

pub fn cwd(&self) -> &PathBuf

Working directory of the CLI process.

Source

pub fn workspace_path(&self) -> Option<&Path>

Workspace directory for the session (if using infinite sessions).

Source

pub fn remote_url(&self) -> Option<&str>

Remote session URL, if the session is running remotely.

Source

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.

Source

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");
    }
}
Source

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);
    }
});
Source

pub fn client(&self) -> &Client

The underlying Client (for advanced use cases).

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub async fn get_messages(&self) -> Result<Vec<SessionEvent>, Error>

Retrieve the session’s message history.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub async fn log( &self, message: &str, opts: Option<LogOptions>, ) -> Result<(), Error>

Write a log message to the session.

Pass None for opts to use defaults (info level, persisted).

Source

pub fn ui(&self) -> SessionUi<'_>

Returns the UI sub-API for elicitation, confirmation, selection, and free-form input.

All UI methods route through session.ui.* RPCs and require host support — check session.capabilities().ui.elicitation before use.

Trait Implementations§

Source§

impl Drop for Session

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more