Skip to main content

AgentOs

Struct AgentOs 

Source
pub struct AgentOs { /* private fields */ }
Expand description

The high-level client. Cheaply cloneable via Arc.

Implementations§

Source§

impl AgentOs

Source

pub async fn create(options: AgentOsConfig) -> Result<AgentOs, ClientError>

The sole public VM entry point. Processes software, spawns/authenticates the sidecar, creates the VM, waits for ready (10s), configures it, takes a lease, and constructs the cron manager (default crate::config::TimerScheduleDriver).

Dispose the VM (= TS dispose). Teardown order:

  1. cron dispose
  2. close all sessions (swallow errors)
  3. kill all shells + snapshot pending exits
  4. kill all ACP terminals
  5. drain tracked shell-exit tasks (two-phase, bounded by crate::SHELL_DISPOSE_TIMEOUT_MS)
  6. unregister the sidecar event listener
  7. release the lease (or tear down the transport)

Idempotent (guarded by disposed). Dynamically link a software package into the RUNNING VM (parity with the TS client’s linkSoftware). Forwarded to the sidecar, which owns the /opt/agentos projection and appends the package to its live staging dir, so the package’s commands appear under /opt/agentos/bin (on $PATH) immediately with no reboot. Errors if a command name is already linked.

Source

pub async fn provided_commands( &self, ) -> Result<BTreeMap<String, Vec<String>>, ClientError>

Source

pub async fn shutdown(&self) -> Result<(), ClientError>

Source

pub fn sidecar(&self) -> Arc<AgentOsSidecar>

The (possibly shared) sidecar handle backing this VM. Public for parity with TS AgentOs.sidecar (e.g. describe() reports active_vm_count across VMs sharing a pool).

Source

pub fn projected_agents(&self) -> Vec<ProjectedAgent>

Source§

impl AgentOs

Source

pub fn schedule_cron( &self, options: CronJobOptions, ) -> Result<CronJobHandle, ClientError>

Schedule a cron job. SYNC. Validates the schedule (errors InvalidSchedule / PastSchedule). id defaults to a UUID; overlap defaults to allow.

Mirrors TS AgentOs.scheduleCron / CronManager.schedule: validation happens up front, the driver is asked to arm the timer (this.driver.schedule({ id, schedule, callback })), and the job is registered. The driver owns all timing: it parses the schedule, fires the callback, reschedules cron after each fire, and is cancelled on CronJobHandle::cancel / CronManager::dispose. The returned CronJobHandle cancels the job.

Source

pub fn list_cron_jobs(&self) -> Vec<CronJobInfo>

Snapshot all cron jobs. Mirrors TS CronManager.list.

Source

pub fn cancel_cron_job(&self, id: &str)

Cancel a cron job. No-op if unknown; never errors. Mirrors TS CronManager.cancel.

Source

pub fn cron_events(&self) -> Receiver<CronEvent>

Subscribe to cron events. The TS API returns no unsubscribe; dropping the receiver is the equivalent. Each run emits Fire then Complete|Error. Mirrors TS AgentOs.onCronEvent.

Source§

impl AgentOs

Source

pub async fn read_file(&self, path: &str) -> Result<Vec<u8>>

Read a file’s raw bytes (no decode).

Source

pub async fn write_file( &self, path: &str, content: impl Into<FileContent>, ) -> Result<()>

Write a file. Writable-path guard; does NOT auto-create parents; Text -> UTF-8.

Source

pub async fn write_files( &self, entries: Vec<BatchWriteEntry>, ) -> Vec<BatchWriteResult>

Batch write. Sequential; never rejects (per-entry error); auto-creates parent dirs.

Source

pub async fn read_files(&self, paths: Vec<String>) -> Vec<BatchReadResult>

Batch read. Sequential; never rejects; content None on failure.

Source

pub async fn mkdir(&self, path: &str, options: MkdirOptions) -> Result<()>

Make a directory. Recursive -> writable guard + mkdirp; non-recursive -> safe guard + single level. The guard asymmetry is load-bearing.

Source

pub async fn readdir(&self, path: &str) -> Result<Vec<String>>

List basenames (may include ./..).

Source

pub async fn read_dir_with_types( &self, path: &str, ) -> Result<Vec<VirtualDirEntry>>

Typed directory listing: each child reported with its resolved type. secure-exec’s native READ_DIR returns basenames only (entries: list<str>), so the type of each entry is derived with a per-child lstat (a symlink is reported as such, lstat-style, not followed). Goes through the kernel, so mounts are listed correctly. ./.. are filtered.

Source

pub async fn readdir_recursive( &self, path: &str, options: ReaddirRecursiveOptions, ) -> Result<Vec<DirEntry>>

Recursive BFS listing; symlinks recorded but NOT descended; a stat failure aborts the call.

Source

pub async fn stat(&self, path: &str) -> Result<VirtualStat>

Stat (follows symlinks).

Source

pub async fn exists(&self, path: &str) -> Result<bool>

Existence check. Safe-path guard still errors; missing path -> false.

Source

pub async fn snapshot_root_filesystem(&self) -> Result<RootSnapshotExport>

Export the root filesystem snapshot. Octal-string mode + utf8/base64 content verbatim.

Source

pub fn mount_fs( &self, path: &str, driver: Arc<dyn VirtualFileSystem>, options: MountFsOptions, ) -> Result<(), ClientError>

Mount an in-process VirtualFileSystem driver. SYNC. Safe-path guard. The driver is a live trait object and cannot cross an RPC boundary, so it is registered (together with the read_only flag, mirroring TS kernel.mountFs({ readOnly })) in the in-process mount table keyed by its normalized guest path.

Source

pub fn unmount_fs(&self, path: &str) -> Result<(), ClientError>

Unmount a previously mounted path. SYNC.

Source

pub async fn move_path(&self, from: &str, to: &str) -> Result<()>

Move a path through the sidecar primitive. The kernel attempts rename first, then falls back to recursive copy+remove on EXDEV.

Source

pub async fn delete(&self, path: &str, options: DeleteOptions) -> Result<()>

Delete a path through the sidecar primitive. Non-recursive directory deletes preserve ENOTEMPTY semantics.

Source§

impl AgentOs

Source

pub async fn fetch( &self, port: u16, request: Request<Bytes>, ) -> Result<Response<Bytes>>

Fetch from a guest server listening on port inside the VM.

path is derived from the request URI’s pathname+search; the host is ignored. The body is only sent for methods other than GET/HEAD. The response body is base64-decoded.

Source§

impl AgentOs

Source

pub async fn exec( &self, command: &str, options: ExecOptions, ) -> Result<ExecResult>

Run a command to completion. The wire Execute request starts the process and returns a process id immediately; stdout/stderr are accumulated and the call resolves once the matching ProcessExited event arrives. This mirrors the TS pass-through to kernel.exec semantically: the result is the full captured stdout/stderr plus exit code.

Source

pub async fn exec_argv( &self, command: &str, args: &[String], options: ExecOptions, ) -> Result<ExecResult>

Run a command to completion from an already-structured (command, args) argv, bypassing the exec command-line parser. Each args element is sent verbatim as a distinct argv element — no whitespace re-splitting, no shell metacharacter detection, and no routing through sh -c. Callers that already hold a structured argv (for example the cron Exec action) must use this so the structured-argv contract is preserved end to end.

Source

pub fn spawn( &self, command: &str, args: Vec<String>, options: SpawnOptions, ) -> Result<SpawnHandle>

Spawn a process. SYNC; returns { pid } only. Installs stdout/stderr fan-out over broadcast channels and wires exit via a background event-pump task. The user-facing pid is the SDK-allocated map key (the wire process_id is held inside the [ProcessEntry]).

Source

pub fn write_process_stdin( &self, pid: u32, data: StdinInput, ) -> Result<(), ClientError>

Write to a spawned process’s stdin. SYNC. Errors with ProcessNotFound.

Source

pub fn close_process_stdin(&self, pid: u32) -> Result<(), ClientError>

Close a spawned process’s stdin. SYNC. Errors with ProcessNotFound.

Source

pub fn on_process_stdout(&self, pid: u32) -> Result<ByteStream, ClientError>

Subscribe to a spawned process’s stdout. No replay; multi-subscriber. Errors if unknown.

Source

pub fn on_process_stderr(&self, pid: u32) -> Result<ByteStream, ClientError>

Subscribe to a spawned process’s stderr. No replay; multi-subscriber. Errors if unknown.

Source

pub fn on_process_exit( &self, pid: u32, handler: impl FnOnce(i32) + Send + 'static, ) -> Result<Subscription, ClientError>

Register a once-only exit handler. If the process has already exited, the handler fires immediately and synchronously and a no-op unsubscribe is returned (the watch already holds Some(code)). Otherwise the handler fires once when the exit code lands. The exit code is i32, never null.

Source

pub async fn wait_process(&self, pid: u32) -> Result<i32, ClientError>

Await a spawned process’s exit code. Unknown-pid lookup errors (synchronously in TS; here the lookup error is returned before any awaiting begins).

Source

pub fn list_processes(&self) -> Vec<SpawnedProcessInfo>

List SDK-spawned processes only. running = exit_code.is_none().

Source

pub async fn all_processes(&self) -> Result<Vec<ProcessInfo>>

List ALL kernel processes (native sidecar process snapshot).

The kernel snapshot keys processes by their raw kernel pid. SDK-spawned root processes carry a synthetic display pid (the spawn return value); this remaps each snapshot entry’s pid/ppid/pgid/sid back to that display pid via the per-process kernel_pid watch, so a caller can correlate spawn() with all_processes()/process_tree(). Results are sorted ascending by display pid (TS snapshotProcesses .sort((l,r) => l.pid - r.pid)).

Source

pub async fn process_tree(&self) -> Result<Vec<ProcessTreeNode>>

Build the process forest from all_processes, linked by ppid.

Source

pub fn get_process(&self, pid: u32) -> Result<SpawnedProcessInfo, ClientError>

Get a single SDK-spawned process’s info. Errors (not None) when not found.

Source

pub fn stop_process(&self, pid: u32) -> Result<(), ClientError>

SIGTERM a spawned process. No-op if already exited; errors if unknown.

Source

pub fn kill_process(&self, pid: u32) -> Result<(), ClientError>

SIGKILL a spawned process. No-op if already exited; errors if unknown.

Source§

impl AgentOs

Source

pub fn list_sessions(&self) -> Vec<SessionInfo>

List in-memory sessions.

Source

pub async fn list_agents(&self) -> Result<Vec<AgentRegistryEntry>>

List available agents. A thin forwarder: sends AcpListAgentsRequest and maps the sidecar’s response. The sidecar enumerates the projected /opt/agentos packages (client parses no manifests). Every such agent is a package materialized into the VM at boot, so installed is always true.

Source

pub async fn create_session( &self, agent_type: &str, options: CreateSessionOptions, ) -> Result<SessionId>

Create an ACP session. Resolves the agent config, merges env (user wins), creates the session via the sidecar (runtime: java_script, protocol v1, default client caps), and hydrates state. Agent OS owns dynamic tool-reference instructions and forwards them as additional instructions; the sidecar owns final base-prompt assembly and agent-specific injection. On hydration failure the session is removed and the error rethrown. Returns the session id only.

Source

pub async fn resume_session( &self, session_id: &str, agent_type: &str, options: ResumeSessionOptions, ) -> Result<ResumeSessionResult>

Resume a session that exists in durable storage but is not live in this VM (e.g. after a Rivet actor slept and woke with a fresh VM). Thin forwarder: resolves the agent config + adapter entrypoint exactly as create_session does, then forwards a single AcpResumeSessionRequest to the sidecar, which owns the resume state machine (native session/load when supported, else session/new + transcript-continuation preamble). The returned session_id is the live id in this VM (equal to session_id for native loads, freshly assigned for the fallback); the caller remaps external -> live. The new live session is registered + hydrated locally so subsequent prompts route to it.

Resume depends on a durable root; on a non-durable (default in-memory) root there is no surviving store and the fallback tier always runs.

Source

pub async fn destroy_session(&self, session_id: &str) -> Result<()>

Destroy a session. Best-effort cancel_session then internal close.

Source

pub async fn prompt(&self, session_id: &str, text: &str) -> Result<PromptResult>

Prompt a session. Subscribes to live session/update events, accumulates agent_message_chunk text, sends session/prompt, and unsubscribes by dropping the receiver. The response may itself be an error.

Source

pub async fn cancel_session(&self, session_id: &str) -> Result<JsonRpcResponse>

Cancel a session. If prompt requests are pending, resolves locally + background session/cancel and returns a synthetic { via: "prompt-fallback" }; else real session/cancel.

Source

pub fn close_session(&self, session_id: &str) -> Result<(), ClientError>

Close a session. SYNC fire-and-forget. Errors only if unknown across sessions / closed-ids / in-flight closes. Aborts pending, rejects pending permissions, records the closed id (bounded 2048). Mirrors closeSession, whose known-check spans _sessions, _closedSessionIds, and _sessionClosePromises.

Source

pub async fn respond_permission( &self, session_id: &str, permission_id: &str, reply: PermissionReply, ) -> Result<JsonRpcResponse>

Respond to a permission request. If a pending reply slot exists, resolves it and returns a synthetic { via: "sidecar-request" }; else the legacy request/permission RPC. Mirrors respondPermission.

Source

pub async fn set_session_mode( &self, session_id: &str, mode_id: &str, ) -> Result<JsonRpcResponse>

Set the session mode (session/set_mode). Updates cached current_mode_id on success.

Source

pub fn get_session_modes(&self, session_id: &str) -> Option<SessionModeState>

Get cached session mode state.

Source

pub async fn set_session_model( &self, session_id: &str, model: &str, ) -> Result<JsonRpcResponse>

Set the session model. Uses set_config_option with category model; readonly -> error response.

Source

pub async fn set_session_thought_level( &self, session_id: &str, level: &str, ) -> Result<JsonRpcResponse>

Set the session thought level. Same as model with category thought_level.

Source

pub fn get_session_config_options( &self, session_id: &str, ) -> Vec<SessionConfigOption>

Get cached config options (shallow copy).

Source

pub fn get_session_capabilities( &self, session_id: &str, ) -> Option<AgentCapabilities>

Get cached capabilities. Mirrors getSessionCapabilities: returns null (None) when the stored capabilities object has no keys (Object.keys(caps).length === 0).

Source

pub fn get_session_agent_info(&self, session_id: &str) -> Option<AgentInfo>

Get cached agent info.

Source

pub async fn raw_session_send( &self, session_id: &str, method: &str, params: Option<Value>, ) -> Result<JsonRpcResponse>

Raw passthrough to send_session_request (which already re-hydrates + applies set_mode / set_config_option cache updates). Mirrors rawSessionSend.

Source

pub async fn raw_send( &self, session_id: &str, method: &str, params: Option<Value>, ) -> Result<JsonRpcResponse>

Thin alias for raw_session_send.

Source

pub fn on_session_event( &self, session_id: &str, ) -> Result<SessionEventSubscription, ClientError>

Subscribe to live session/update events. Only events emitted after subscription are delivered.

Source

pub fn on_permission_request( &self, session_id: &str, ) -> Result<PermissionRequestSubscription, ClientError>

Subscribe to permission requests raised by the session’s guest agent. Requests originate from the sidecar permission_request callback (the sidecar normalizes both the legacy request/permission and ACP session/request_permission method names before invoking the host). With no subscribers a request auto-rejects; subscribers reply via the carried PermissionResponder or AgentOs::respond_permission, bounded by the crate::PERMISSION_TIMEOUT_MS timeout.

Source

pub fn on_agent_exit( &self, session_id: &str, ) -> Result<AgentExitSubscription, ClientError>

Subscribe to unexpected adapter process exits (crashes) for a session, including the sidecar’s bounded auto-restart outcome. Only events emitted after subscription are delivered; only restart == "restarted" leaves the session usable. Mirrors the TS onAgentExit option.

Source§

impl AgentOs

Source

pub async fn create_sidecar( sidecar_id: Option<String>, ) -> Result<Arc<AgentOsSidecar>, ClientError>

Create an explicit sidecar handle. sidecar_id defaults to agentos-sidecar-<uuid>.

Parity with TypeScript createAgentOsSidecarInternal: the explicit handle carries an Explicit placement whose sidecar_id echoes the resolved id and has no shared pool.

Source

pub async fn get_shared_sidecar( pool: Option<String>, sidecar_binary_path: Option<String>, ) -> Result<Arc<AgentOsSidecar>, ClientError>

Get (or create) a pooled shared sidecar. Pool defaults to "default". Uses the process-global cache.

Parity with TypeScript getSharedAgentOsSidecarInternal: return the cached sidecar for the pool when it exists and is not disposed; otherwise build a fresh handle (agentos-shared-sidecar:<pool>, Shared placement) and cache it. Because the cache is a process-global concurrent map rather than a synchronously-checked Map, the insert is done atomically with entry/insert so two racing callers converge on a single live handle.

Source§

impl AgentOs

Source

pub fn open_shell(&self, options: OpenShellOptions) -> Result<ShellHandle>

Open a PTY-backed shell. SYNC. Returns a synthetic shell-N id (NOT a pid).

The shell id and its registry entry are allocated synchronously (matching the TS sync contract); the actual guest-process spawn, output fan-out, and exit-task registration happen on a background task because the wire spawn is async. The exit task is tracked in the pending-shell-exit set so dispose can drain it (two-phase teardown).

Stdout is fanned into the shell’s data broadcast (on_shell_data); stderr is fanned into a SEPARATE stderr broadcast (on_shell_stderr + the OpenShellOptions::on_stderr callback), matching the TS real-process routing where stderr never reaches the data stream.

Source

pub async fn connect_terminal( &self, options: ConnectTerminalOptions, ) -> Result<u32>

Connect a terminal bound to host stdio. Returns a PID. NOT tracked in the shells map; cannot be addressed by other shell methods. Killed during dispose via the ACP-terminal registry.

Mirrors the TS connectTerminal, which routes its onData/onStderr callbacks through openShell. The Rust port opens a shell, wires the caller’s on_data to the shell’s data stream and on_stderr to the shell’s stderr stream, then returns the shell’s pid. Host stdin binding, terminal raw-mode, and SIGWINCH/resize forwarding are host-process concerns that have no native wire op and are intentionally not bound here.

Source

pub fn write_shell( &self, shell_id: &str, data: StdinInput, ) -> Result<(), ClientError>

Write to a shell. SYNC fire-and-forget. Errors with ClientError::ShellNotFound.

Source

pub async fn write_shell_awaited( &self, shell_id: &str, data: StdinInput, ) -> Result<(), ClientError>

Write to a shell and AWAIT the wire write. Same routing as Self::write_shell, but the caller observes wire failures instead of a fire-and-forget warn — used by the actor plugin’s writeShell action so a failed write rejects the action.

Source

pub fn on_shell_data(&self, shell_id: &str) -> Result<ByteStream, ClientError>

Subscribe to a shell’s stdout data. SYNC register; multi-handler; dropping the returned stream is the unsubscribe. Carries stdout ONLY (stderr is on on_shell_stderr). Errors with ClientError::ShellNotFound.

Source

pub fn on_shell_stderr(&self, shell_id: &str) -> Result<ByteStream, ClientError>

Subscribe to a shell’s stderr. SYNC register; multi-handler; dropping the returned stream is the unsubscribe. This is the dedicated stderr channel backing the TS onStderr option; stderr is never fanned into on_shell_data. Errors with ClientError::ShellNotFound.

Source

pub fn resize_shell( &self, shell_id: &str, cols: u16, rows: u16, ) -> Result<(), ClientError>

Resize a shell’s PTY winsize. SYNC fire-and-forget, mirroring the TS ShellHandle.resize (which dispatches resizePty in the background after the spawn lands). Errors with ClientError::ShellNotFound.

Source

pub async fn wait_shell(&self, shell_id: &str) -> Result<i32, ClientError>

Wait for a shell to exit and return its process exit code (TS waitShell). Resolves immediately for a shell that already exited within the bounded retention window. Errors with ClientError::ShellNotFound for an unknown id.

Source

pub fn close_shell(&self, shell_id: &str) -> Result<(), ClientError>

Close a shell. SYNC. kill() + immediate map delete; the exit task is still drained by dispose. Errors with ClientError::ShellNotFound.

Trait Implementations§

Source§

impl Clone for AgentOs

Source§

fn clone(&self) -> AgentOs

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. 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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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