pub struct AgentOs { /* private fields */ }Expand description
The high-level client. Cheaply cloneable via Arc.
Implementations§
Source§impl AgentOs
impl AgentOs
Sourcepub async fn create(options: AgentOsConfig) -> Result<AgentOs, ClientError>
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).
Sourcepub async fn link_software(
&self,
descriptor: PackageDescriptor,
) -> Result<(), ClientError>
pub async fn link_software( &self, descriptor: PackageDescriptor, ) -> Result<(), ClientError>
Dispose the VM (= TS dispose). Teardown order:
- cron dispose
- kill all shells + snapshot pending exits
- kill all ACP terminals
- drain tracked shell-exit tasks (two-phase, bounded by
crate::SHELL_DISPOSE_TIMEOUT_MS) - unregister the sidecar event listener
- 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.
pub async fn list_software(&self) -> Result<Vec<SoftwareInfo>, ClientError>
pub async fn shutdown(&self) -> Result<(), ClientError>
Sourcepub fn sidecar(&self) -> Arc<AgentOsSidecar> ⓘ
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).
pub fn projected_agents(&self) -> Vec<ProjectedAgent>
Source§impl AgentOs
impl AgentOs
Sourcepub fn schedule_cron(
&self,
options: CronJobOptions,
) -> Result<CronJobHandle, ClientError>
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.
Sourcepub fn list_cron_jobs(&self) -> Vec<CronJobInfo>
pub fn list_cron_jobs(&self) -> Vec<CronJobInfo>
Snapshot all cron jobs. Mirrors TS CronManager.list.
Sourcepub fn cancel_cron_job(&self, id: &str)
pub fn cancel_cron_job(&self, id: &str)
Cancel a cron job. No-op if unknown; never errors. Mirrors TS CronManager.cancel.
Sourcepub fn cron_events(&self) -> Receiver<CronEvent>
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
impl AgentOs
Sourcepub async fn read_file(&self, path: &str) -> Result<Vec<u8>>
pub async fn read_file(&self, path: &str) -> Result<Vec<u8>>
Read a file’s raw bytes (no decode).
Sourcepub async fn write_file(
&self,
path: &str,
content: impl Into<FileContent>,
) -> Result<()>
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.
Sourcepub async fn write_files(
&self,
entries: Vec<BatchWriteEntry>,
) -> Vec<BatchWriteResult>
pub async fn write_files( &self, entries: Vec<BatchWriteEntry>, ) -> Vec<BatchWriteResult>
Batch write. Sequential; never rejects (per-entry error); auto-creates parent dirs.
Sourcepub async fn read_files(&self, paths: Vec<String>) -> Vec<BatchReadResult>
pub async fn read_files(&self, paths: Vec<String>) -> Vec<BatchReadResult>
Batch read. Sequential; never rejects; content None on failure.
Sourcepub async fn mkdir(&self, path: &str, options: MkdirOptions) -> Result<()>
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.
Sourcepub async fn readdir(&self, path: &str) -> Result<Vec<String>>
pub async fn readdir(&self, path: &str) -> Result<Vec<String>>
List basenames (may include ./..).
Sourcepub async fn read_dir_with_types(
&self,
path: &str,
) -> Result<Vec<VirtualDirEntry>>
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.
Sourcepub async fn readdir_recursive(
&self,
path: &str,
options: ReaddirRecursiveOptions,
) -> Result<Vec<DirEntry>>
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.
Sourcepub async fn readdir_entries(&self, path: &str) -> Result<Vec<VirtualDirEntry>>
pub async fn readdir_entries(&self, path: &str) -> Result<Vec<VirtualDirEntry>>
Return typed immediate children using one sidecar filesystem operation.
Sourcepub async fn stat(&self, path: &str) -> Result<VirtualStat>
pub async fn stat(&self, path: &str) -> Result<VirtualStat>
Stat (follows symlinks).
Sourcepub async fn exists(&self, path: &str) -> Result<bool>
pub async fn exists(&self, path: &str) -> Result<bool>
Existence check. Safe-path guard still errors; missing path -> false.
Sourcepub async fn export_root_filesystem(
&self,
max_bytes: usize,
) -> Result<RootSnapshotExport>
pub async fn export_root_filesystem( &self, max_bytes: usize, ) -> Result<RootSnapshotExport>
Export the root filesystem snapshot. Octal-string mode + utf8/base64 content verbatim.
Sourcepub async fn mount_fs(&self, descriptor: DynamicMountDescriptor) -> Result<()>
pub async fn mount_fs(&self, descriptor: DynamicMountDescriptor) -> Result<()>
Mount a portable sidecar-owned filesystem descriptor.
pub async fn unmount_fs(&self, path: &str) -> Result<()>
pub async fn list_mounts(&self) -> Result<Vec<MountInfo>>
Source§impl AgentOs
impl AgentOs
Sourcepub async fn http_request(&self, request: HttpRequest) -> Result<HttpResponse>
pub async fn http_request(&self, request: HttpRequest) -> Result<HttpResponse>
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
impl AgentOs
Sourcepub async fn exec(
&self,
command: &str,
options: ExecOptions,
) -> Result<ExecResult>
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.
Sourcepub async fn exec_argv(
&self,
command: &str,
args: &[String],
options: ExecOptions,
) -> Result<ExecResult>
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.
Sourcepub fn spawn(
&self,
command: &str,
args: Vec<String>,
options: SpawnOptions,
) -> Result<SpawnHandle>
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]).
Sourcepub fn write_process_stdin(
&self,
pid: u32,
data: StdinInput,
) -> Result<(), ClientError>
pub fn write_process_stdin( &self, pid: u32, data: StdinInput, ) -> Result<(), ClientError>
Write to a spawned process’s stdin. SYNC. Errors with ProcessNotFound.
Sourcepub fn close_process_stdin(&self, pid: u32) -> Result<(), ClientError>
pub fn close_process_stdin(&self, pid: u32) -> Result<(), ClientError>
Close a spawned process’s stdin. SYNC. Errors with ProcessNotFound.
Sourcepub fn on_process_output(
&self,
pid: u32,
handler: impl FnMut(ProcessOutput) + Send + 'static,
) -> Result<Subscription, ClientError>
pub fn on_process_output( &self, pid: u32, handler: impl FnMut(ProcessOutput) + Send + 'static, ) -> Result<Subscription, ClientError>
Subscribe to the unified stdout/stderr event stream for a process.
Sourcepub fn on_process_exit(
&self,
pid: u32,
handler: impl FnOnce(ProcessExit) + Send + 'static,
) -> Result<Subscription, ClientError>
pub fn on_process_exit( &self, pid: u32, handler: impl FnOnce(ProcessExit) + 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.
Sourcepub async fn wait_process(&self, pid: u32) -> Result<i32, ClientError>
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).
Sourcepub fn list_processes(&self) -> Vec<SpawnedProcessInfo>
pub fn list_processes(&self) -> Vec<SpawnedProcessInfo>
List SDK-spawned processes only. running = exit_code.is_none().
Sourcepub async fn all_processes(&self) -> Result<Vec<ProcessInfo>>
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)).
Sourcepub async fn process_tree(&self) -> Result<Vec<ProcessTreeNode>>
pub async fn process_tree(&self) -> Result<Vec<ProcessTreeNode>>
Build the process forest from all_processes, linked by ppid.
Sourcepub fn get_process(&self, pid: u32) -> Result<SpawnedProcessInfo, ClientError>
pub fn get_process(&self, pid: u32) -> Result<SpawnedProcessInfo, ClientError>
Get a single SDK-spawned process’s info. Errors (not None) when not found.
Sourcepub fn stop_process(&self, pid: u32) -> Result<(), ClientError>
pub fn stop_process(&self, pid: u32) -> Result<(), ClientError>
SIGTERM a spawned process. No-op if already exited; errors if unknown.
Sourcepub fn kill_process(&self, pid: u32) -> Result<(), ClientError>
pub fn kill_process(&self, pid: u32) -> Result<(), ClientError>
SIGKILL a spawned process. No-op if already exited; errors if unknown.
Source§impl AgentOs
impl AgentOs
Sourcepub async fn list_agents(&self) -> Result<Vec<AgentRegistryEntry>>
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.
Sourcepub async fn open_session(&self, input: OpenSessionInput) -> Result<()>
pub async fn open_session(&self, input: OpenSessionInput) -> Result<()>
Open or restore a durable session. The sidecar owns defaults,
negotiation, and ACP restore selection; an omitted ID targets main.
This is an idempotent command and returns no metadata. Call
AgentOs::get_session when the stored session record is needed.
Sourcepub async fn get_session(&self, session_id: Option<&str>) -> Result<SessionInfo>
pub async fn get_session(&self, session_id: Option<&str>) -> Result<SessionInfo>
Read durable metadata without starting or restoring an ACP adapter.
Sourcepub async fn list_sessions(
&self,
input: ListSessionsInput,
) -> Result<SessionPage>
pub async fn list_sessions( &self, input: ListSessionsInput, ) -> Result<SessionPage>
Traverse durable sessions by the sidecar-issued keyset cursor. This is a SQLite-only operation and never starts an adapter.
Sourcepub async fn delete_session(&self, session_id: Option<&str>) -> Result<()>
pub async fn delete_session(&self, session_id: Option<&str>) -> Result<()>
Permanently delete durable metadata and history. None targets main.
Sourcepub async fn unload_session(&self, session_id: Option<&str>) -> Result<()>
pub async fn unload_session(&self, session_id: Option<&str>) -> Result<()>
Release the live adapter while preserving the durable session.
Sourcepub async fn prompt(&self, input: PromptInput) -> Result<PromptResult>
pub async fn prompt(&self, input: PromptInput) -> Result<PromptResult>
Durably accept a complete ACP prompt before dispatch. A missing session is an error; the sidecar never creates one here or retries uncertain work.
pub async fn cancel_prompt( &self, session_id: Option<&str>, ) -> Result<CancelPromptStatus>
pub async fn respond_permission( &self, session_id: &str, request_id: &str, option_id: &str, ) -> Result<PermissionResponseStatus>
Sourcepub async fn read_history(&self, input: ReadHistoryInput) -> Result<HistoryPage>
pub async fn read_history(&self, input: ReadHistoryInput) -> Result<HistoryPage>
Read the authoritative SQLite history. ACP message updates deserialize through the official protocol-v1 schema crate.
pub async fn get_session_config( &self, session_id: Option<&str>, ) -> Result<SessionConfig>
pub async fn set_session_config_option( &self, session_id: Option<&str>, config_id: &str, value: SessionConfigValue, ) -> Result<SessionConfig>
pub async fn get_session_capabilities( &self, session_id: Option<&str>, ) -> Result<Option<SessionCapabilities>>
pub async fn get_session_agent_info( &self, session_id: Option<&str>, ) -> Result<Option<Implementation>>
Sourcepub fn on_session_event(
&self,
session_id: Option<&str>,
) -> DurableSessionEventSubscription
pub fn on_session_event( &self, session_id: Option<&str>, ) -> DurableSessionEventSubscription
Subscribe to durable and ephemeral ACP updates for one public session.
Omitted session IDs target main. Durable entries are emitted only
after their SQLite transaction commits; ephemeral entries are deltas and
have no durable sequence of their own.
Sourcepub fn on_agent_exit(&self, session_id: Option<&str>) -> AgentExitSubscription
pub fn on_agent_exit(&self, session_id: Option<&str>) -> AgentExitSubscription
Subscribe to unexpected ACP adapter exits. Pass a session ID to filter
to one durable session, or None to observe all adapter exits for this
VM. Subscribing never starts or restores an adapter.
Source§impl AgentOs
impl AgentOs
Sourcepub async fn create_sidecar(
sidecar_id: Option<String>,
) -> Result<Arc<AgentOsSidecar>, ClientError>
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.
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
impl AgentOs
Sourcepub fn open_shell(&self, options: OpenShellOptions) -> Result<ShellHandle>
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 and stderr are fanned into the shell’s ordered data broadcast (on_shell_data).
Stderr is also fanned into a dedicated diagnostic broadcast (on_shell_stderr and the
[OpenShellOptions::on_stderr] callback); terminal renderers should consume only data.
Sourcepub async fn connect_terminal(
&self,
options: ConnectTerminalOptions,
) -> Result<u32>
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 ordered terminal data
and on_stderr to the optional diagnostic tap, 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.
Sourcepub fn write_shell(
&self,
shell_id: &str,
data: StdinInput,
) -> Result<(), ClientError>
pub fn write_shell( &self, shell_id: &str, data: StdinInput, ) -> Result<(), ClientError>
Write to a shell. SYNC fire-and-forget. Errors with ClientError::ShellNotFound.
Sourcepub async fn write_shell_awaited(
&self,
shell_id: &str,
data: StdinInput,
) -> Result<(), ClientError>
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.
Sourcepub fn on_shell_data(
&self,
shell_id: &str,
handler: impl FnMut(ShellData) + Send + 'static,
) -> Result<Subscription, ClientError>
pub fn on_shell_data( &self, shell_id: &str, handler: impl FnMut(ShellData) + Send + 'static, ) -> Result<Subscription, ClientError>
Subscribe to a shell’s ordered terminal data. SYNC register; multi-handler; dropping the
returned stream is the unsubscribe. Carries stdout and stderr exactly once in wire order.
Use Self::on_shell_stderr only as a channel-specific diagnostic tap, not as a second
terminal-rendering stream. Errors with ClientError::ShellNotFound.
Sourcepub fn on_shell_stderr(
&self,
shell_id: &str,
handler: impl FnMut(ShellData) + Send + 'static,
) -> Result<Subscription, ClientError>
pub fn on_shell_stderr( &self, shell_id: &str, handler: impl FnMut(ShellData) + Send + 'static, ) -> Result<Subscription, ClientError>
Subscribe to a shell’s stderr. SYNC register; multi-handler; dropping the returned stream is
the unsubscribe. This is the optional diagnostic channel backing the TS onStderr option;
stderr is also present once in ordered on_shell_data. Errors with
ClientError::ShellNotFound.
pub fn on_shell_exit( &self, shell_id: &str, handler: impl FnOnce(ShellExit) + Send + 'static, ) -> Result<Subscription, ClientError>
Sourcepub fn resize_shell(
&self,
shell_id: &str,
cols: u16,
rows: u16,
) -> Result<(), ClientError>
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.
Sourcepub async fn wait_shell(&self, shell_id: &str) -> Result<i32, ClientError>
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.
Sourcepub fn close_shell(&self, shell_id: &str) -> Result<(), ClientError>
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.