1
0
forked from wrenn/wrenn
Files
wrenn-releases/proto/hostagent/hostagent.proto
pptx704 ab3fc4a807 Add interactive PTY terminal sessions for sandboxes
Wire envd's existing PTY process capabilities through the full stack:
hostagent proto (4 new RPCs: PtyAttach, PtySendInput, PtyResize, PtyKill),
envdclient, sandbox manager, and a new WebSocket endpoint at
GET /v1/sandboxes/{id}/pty with bidirectional JSON message protocol.

Sessions use tag-based identity for disconnect/reconnect support,
base64-encoded PTY data for binary safety, and a 120s inactivity timeout.
2026-04-11 02:42:59 +06:00

467 lines
13 KiB
Protocol Buffer

syntax = "proto3";
package hostagent.v1;
// HostAgentService manages sandbox VMs on a single physical host.
// The control plane calls these RPCs to orchestrate sandbox lifecycle.
service HostAgentService {
// CreateSandbox boots a new microVM with the given configuration.
rpc CreateSandbox(CreateSandboxRequest) returns (CreateSandboxResponse);
// DestroySandbox stops and cleans up a sandbox (VM, network, rootfs).
rpc DestroySandbox(DestroySandboxRequest) returns (DestroySandboxResponse);
// PauseSandbox pauses a running sandbox's VM.
rpc PauseSandbox(PauseSandboxRequest) returns (PauseSandboxResponse);
// ResumeSandbox resumes a paused sandbox's VM.
rpc ResumeSandbox(ResumeSandboxRequest) returns (ResumeSandboxResponse);
// Exec runs a command inside a sandbox and returns the collected output.
rpc Exec(ExecRequest) returns (ExecResponse);
// ListSandboxes returns all sandboxes managed by this host agent.
rpc ListSandboxes(ListSandboxesRequest) returns (ListSandboxesResponse);
// WriteFile writes content to a file inside a sandbox.
rpc WriteFile(WriteFileRequest) returns (WriteFileResponse);
// ReadFile reads a file from inside a sandbox.
rpc ReadFile(ReadFileRequest) returns (ReadFileResponse);
// ListDir lists directory contents inside a sandbox.
rpc ListDir(ListDirRequest) returns (ListDirResponse);
// MakeDir creates a directory inside a sandbox.
rpc MakeDir(MakeDirRequest) returns (MakeDirResponse);
// RemovePath removes a file or directory inside a sandbox.
rpc RemovePath(RemovePathRequest) returns (RemovePathResponse);
// CreateSnapshot pauses a sandbox, takes a snapshot, stores it as a reusable
// template, and destroys the sandbox.
rpc CreateSnapshot(CreateSnapshotRequest) returns (CreateSnapshotResponse);
// DeleteSnapshot removes a snapshot template from disk.
rpc DeleteSnapshot(DeleteSnapshotRequest) returns (DeleteSnapshotResponse);
// ExecStream runs a command inside a sandbox and streams output events as they arrive.
rpc ExecStream(ExecStreamRequest) returns (stream ExecStreamResponse);
// WriteFileStream writes a file to a sandbox using chunked streaming.
// First message must contain metadata (sandbox_id, path). Subsequent messages contain data chunks.
rpc WriteFileStream(stream WriteFileStreamRequest) returns (WriteFileStreamResponse);
// ReadFileStream reads a file from a sandbox and streams it back in chunks.
rpc ReadFileStream(ReadFileStreamRequest) returns (stream ReadFileStreamResponse);
// PingSandbox resets the inactivity timer for a running sandbox.
rpc PingSandbox(PingSandboxRequest) returns (PingSandboxResponse);
// Terminate instructs the host agent to destroy all sandboxes and exit.
// Called by the control plane immediately when a host is deleted so the
// agent shuts down without waiting for the next heartbeat cycle.
rpc Terminate(TerminateRequest) returns (TerminateResponse);
// GetSandboxMetrics returns ring buffer metrics for a running sandbox.
rpc GetSandboxMetrics(GetSandboxMetricsRequest) returns (GetSandboxMetricsResponse);
// FlushSandboxMetrics returns all ring buffer tiers and clears them.
// Called by the control plane before pause/destroy to persist metrics to DB.
rpc FlushSandboxMetrics(FlushSandboxMetricsRequest) returns (FlushSandboxMetricsResponse);
// FlattenRootfs stops the sandbox VM, flattens the device-mapper CoW
// snapshot into a standalone rootfs.ext4 in the images directory, then
// cleans up all sandbox resources. Used by the template build system to
// produce image-only templates (no memory/CPU state).
rpc FlattenRootfs(FlattenRootfsRequest) returns (FlattenRootfsResponse);
// PtyAttach starts a new PTY process or reconnects to an existing one.
// If cmd is non-empty, starts a new process with the given PTY dimensions.
// If tag is set and cmd is empty, reconnects to the existing process with that tag.
// Returns a stream of output events (started, output data, exit).
rpc PtyAttach(PtyAttachRequest) returns (stream PtyAttachResponse);
// PtySendInput sends raw bytes to a PTY process identified by tag.
rpc PtySendInput(PtySendInputRequest) returns (PtySendInputResponse);
// PtyResize updates the terminal dimensions for a PTY process.
rpc PtyResize(PtyResizeRequest) returns (PtyResizeResponse);
// PtyKill sends a signal to a PTY process.
rpc PtyKill(PtyKillRequest) returns (PtyKillResponse);
}
message CreateSandboxRequest {
// Sandbox ID assigned by the control plane. If empty, the host agent generates one.
string sandbox_id = 5;
// Deprecated: use team_id + template_id instead.
string template = 1;
// Number of virtual CPUs (default: 1).
int32 vcpus = 2;
// Memory in MB (default: 512).
int32 memory_mb = 3;
// TTL in seconds. Sandbox is auto-paused after this duration of
// inactivity. 0 means no auto-pause.
int32 timeout_sec = 4;
// Disk size in MB for the rootfs. Base images are expanded to this size
// at host agent startup. Default: 5120 (5 GB).
int32 disk_size_mb = 6;
// Team UUID that owns the template (hex string). All-zeros = platform.
string team_id = 7;
// Template UUID (hex string). Both zeros + team zeros = "minimal" sentinel.
string template_id = 8;
}
message CreateSandboxResponse {
string sandbox_id = 1;
string status = 2;
string host_ip = 3;
}
message DestroySandboxRequest {
string sandbox_id = 1;
}
message DestroySandboxResponse {}
message PauseSandboxRequest {
string sandbox_id = 1;
}
message PauseSandboxResponse {}
message ResumeSandboxRequest {
string sandbox_id = 1;
// TTL in seconds restored from the DB so the reaper can auto-pause
// the sandbox again after inactivity. 0 means no auto-pause.
int32 timeout_sec = 2;
}
message ResumeSandboxResponse {
string sandbox_id = 1;
string status = 2;
string host_ip = 3;
}
message CreateSnapshotRequest {
string sandbox_id = 1;
// Deprecated: use team_id + template_id instead.
string name = 2;
// Team UUID that will own the new template.
string team_id = 3;
// Template UUID for the new snapshot template.
string template_id = 4;
}
message CreateSnapshotResponse {
string name = 1;
int64 size_bytes = 2;
}
message DeleteSnapshotRequest {
// Deprecated: use team_id + template_id instead.
string name = 1;
// Team UUID that owns the template.
string team_id = 2;
// Template UUID to delete.
string template_id = 3;
}
message DeleteSnapshotResponse {}
message ExecRequest {
string sandbox_id = 1;
string cmd = 2;
repeated string args = 3;
// Timeout for the command in seconds (default: 30).
int32 timeout_sec = 4;
}
message ExecResponse {
bytes stdout = 1;
bytes stderr = 2;
int32 exit_code = 3;
}
message ListSandboxesRequest {}
message ListSandboxesResponse {
repeated SandboxInfo sandboxes = 1;
// IDs of sandboxes that were automatically paused by the TTL reaper
// since the last call. Drained on read.
repeated string auto_paused_sandbox_ids = 2;
}
message SandboxInfo {
string sandbox_id = 1;
string status = 2;
// Deprecated: use team_id + template_id instead.
string template = 3;
int32 vcpus = 4;
int32 memory_mb = 5;
string host_ip = 6;
int64 created_at_unix = 7;
int64 last_active_at_unix = 8;
int32 timeout_sec = 9;
string team_id = 10;
string template_id = 11;
}
message WriteFileRequest {
string sandbox_id = 1;
string path = 2;
bytes content = 3;
}
message WriteFileResponse {}
message ReadFileRequest {
string sandbox_id = 1;
string path = 2;
}
message ReadFileResponse {
bytes content = 1;
}
// ── Streaming Exec ──────────────────────────────────────────────────
message ExecStreamRequest {
string sandbox_id = 1;
string cmd = 2;
repeated string args = 3;
int32 timeout_sec = 4;
}
message ExecStreamResponse {
oneof event {
ExecStreamStart start = 1;
ExecStreamData data = 2;
ExecStreamEnd end = 3;
}
}
message ExecStreamStart {
uint32 pid = 1;
}
message ExecStreamData {
oneof output {
bytes stdout = 1;
bytes stderr = 2;
}
}
message ExecStreamEnd {
int32 exit_code = 1;
string error = 2;
}
// ── Streaming File Transfer ─────────────────────────────────────────
message WriteFileStreamRequest {
oneof content {
WriteFileStreamMeta meta = 1;
bytes chunk = 2;
}
}
message WriteFileStreamMeta {
string sandbox_id = 1;
string path = 2;
}
message WriteFileStreamResponse {}
message ReadFileStreamRequest {
string sandbox_id = 1;
string path = 2;
}
message ReadFileStreamResponse {
bytes chunk = 1;
}
// ── Filesystem Operations ──────────────────────────────────────────
message ListDirRequest {
string sandbox_id = 1;
string path = 2;
uint32 depth = 3;
}
message ListDirResponse {
repeated FileEntry entries = 1;
}
message FileEntry {
string name = 1;
string path = 2;
// "file", "directory", or "symlink".
string type = 3;
int64 size = 4;
uint32 mode = 5;
// Human-readable permissions string, e.g. "-rwxr-xr-x".
string permissions = 6;
string owner = 7;
string group = 8;
// Last modification time as Unix timestamp (seconds).
int64 modified_at = 9;
optional string symlink_target = 10;
}
message MakeDirRequest {
string sandbox_id = 1;
string path = 2;
}
message MakeDirResponse {
FileEntry entry = 1;
}
message RemovePathRequest {
string sandbox_id = 1;
string path = 2;
}
message RemovePathResponse {}
// ── Ping ────────────────────────────────────────────────────────────
message PingSandboxRequest {
string sandbox_id = 1;
}
message PingSandboxResponse {}
// ── Terminate ────────────────────────────────────────────────────────
message TerminateRequest {}
message TerminateResponse {}
// ── Metrics ──────────────────────────────────────────────────────────
message MetricPoint {
int64 timestamp_unix = 1;
double cpu_pct = 2;
int64 mem_bytes = 3;
int64 disk_bytes = 4;
}
message GetSandboxMetricsRequest {
string sandbox_id = 1;
// Range tier: "10m", "2h", or "24h".
string range = 2;
}
message GetSandboxMetricsResponse {
repeated MetricPoint points = 1;
}
message FlushSandboxMetricsRequest {
string sandbox_id = 1;
}
message FlushSandboxMetricsResponse {
repeated MetricPoint points_10m = 1;
repeated MetricPoint points_2h = 2;
repeated MetricPoint points_24h = 3;
}
// ── FlattenRootfs ────────────────────────────────────────────────────
message FlattenRootfsRequest {
string sandbox_id = 1;
// Deprecated: use team_id + template_id instead.
string name = 2;
// Team UUID that will own the resulting template.
string team_id = 3;
// Template UUID for the output.
string template_id = 4;
}
message FlattenRootfsResponse {
int64 size_bytes = 1;
}
// ── PTY ─────────────────────────────────────────────────────────────
message PtyAttachRequest {
string sandbox_id = 1;
// Tag is the stable identifier for this PTY session (e.g. "pty-abc123de").
// Chosen by the caller and used to reconnect later.
string tag = 2;
// If cmd is non-empty, a new process is started. If empty, reconnects to
// the existing process identified by tag.
string cmd = 3;
repeated string args = 4;
uint32 cols = 5;
uint32 rows = 6;
// Environment variables for the process.
map<string, string> envs = 7;
// Working directory. Empty means default.
string cwd = 8;
// User to run as. Empty means default (root).
string user = 9;
}
message PtyAttachResponse {
oneof event {
PtyStarted started = 1;
PtyOutput output = 2;
PtyExited exited = 3;
}
}
message PtyStarted {
uint32 pid = 1;
string tag = 2;
}
message PtyOutput {
bytes data = 1;
}
message PtyExited {
int32 exit_code = 1;
string error = 2;
}
message PtySendInputRequest {
string sandbox_id = 1;
string tag = 2;
bytes data = 3;
}
message PtySendInputResponse {}
message PtyResizeRequest {
string sandbox_id = 1;
string tag = 2;
uint32 cols = 3;
uint32 rows = 4;
}
message PtyResizeResponse {}
message PtyKillRequest {
string sandbox_id = 1;
string tag = 2;
}
message PtyKillResponse {}