Skip to main content

agentkernel_sdk/
types.rs

1use serde::{Deserialize, Serialize};
2
3/// Security profile for sandbox execution.
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5#[serde(rename_all = "lowercase")]
6pub enum SecurityProfile {
7    Permissive,
8    Moderate,
9    Restrictive,
10}
11
12/// Options for running a command.
13#[derive(Debug, Default, Serialize)]
14pub struct RunOptions {
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub image: Option<String>,
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub profile: Option<SecurityProfile>,
19    #[serde(skip_serializing_if = "Option::is_none")]
20    pub fast: Option<bool>,
21}
22
23/// Output from a command execution.
24#[derive(Debug, Deserialize)]
25pub struct RunOutput {
26    pub output: String,
27}
28
29/// Information about a sandbox.
30#[derive(Debug, Deserialize)]
31pub struct SandboxInfo {
32    pub name: String,
33    #[serde(default)]
34    pub uuid: Option<String>,
35    pub status: String,
36    pub backend: String,
37    pub image: Option<String>,
38    pub vcpus: Option<u32>,
39    pub memory_mb: Option<u64>,
40    pub created_at: Option<String>,
41}
42
43/// Backend capabilities reported by the server.
44#[derive(Debug, Deserialize)]
45pub struct BackendCapabilities {
46    pub mount_cwd: bool,
47    pub mount_home: bool,
48    pub attach: bool,
49    pub host_volumes: bool,
50    pub ssh: bool,
51    pub proxy_secret_bindings: bool,
52    pub secret_files: bool,
53    pub snapshots: bool,
54    pub resume: bool,
55    pub full_state_pause_resume: bool,
56    pub full_state_fork: bool,
57    pub endpoints: bool,
58}
59
60/// Server-side backend readiness information.
61#[derive(Debug, Deserialize)]
62pub struct BackendDescriptor {
63    pub backend: String,
64    pub configured: bool,
65    pub usable: bool,
66    pub readiness_reason: String,
67    pub capabilities: BackendCapabilities,
68}
69
70/// Result of backend discovery.
71#[derive(Debug, Deserialize)]
72pub struct BackendDiscovery {
73    pub default_backend: Option<String>,
74    pub backends: Vec<BackendDescriptor>,
75}
76
77/// SSE stream event.
78#[derive(Debug)]
79pub struct StreamEvent {
80    pub event_type: String,
81    pub data: serde_json::Value,
82}
83
84/// Opaque orchestration payload.
85pub type Orchestration = serde_json::Value;
86pub type OrchestrationCreateRequest = serde_json::Value;
87pub type OrchestrationDefinition = serde_json::Value;
88
89/// Opaque durable object payload.
90pub type DurableObject = serde_json::Value;
91pub type DurableObjectCreateRequest = serde_json::Value;
92
93/// Opaque schedule payload.
94pub type Schedule = serde_json::Value;
95pub type ScheduleCreateRequest = serde_json::Value;
96
97/// Opaque durable store payload.
98pub type DurableStore = serde_json::Value;
99pub type DurableStoreCreateRequest = serde_json::Value;
100pub type DurableStoreQueryResult = serde_json::Value;
101pub type DurableStoreExecuteResult = serde_json::Value;
102pub type DurableStoreCommandResult = serde_json::Value;
103
104/// API response wrapper (internal).
105#[derive(Debug, Deserialize)]
106pub(crate) struct ApiResponse<T> {
107    pub success: bool,
108    pub data: Option<T>,
109    pub error: Option<String>,
110}
111
112/// Run request body (internal).
113#[derive(Serialize)]
114pub(crate) struct RunRequest {
115    pub command: Vec<String>,
116    #[serde(skip_serializing_if = "Option::is_none")]
117    pub image: Option<String>,
118    #[serde(skip_serializing_if = "Option::is_none")]
119    pub profile: Option<SecurityProfile>,
120    pub fast: bool,
121}
122
123/// Options for creating a sandbox with a git source.
124#[derive(Debug, Default, Serialize)]
125pub struct CreateSandboxOptions {
126    /// Backend identifier; omit or use `automatic` for server selection.
127    #[serde(skip_serializing_if = "Option::is_none")]
128    pub backend: Option<String>,
129    /// Docker image to use.
130    #[serde(skip_serializing_if = "Option::is_none")]
131    pub image: Option<String>,
132    #[serde(skip_serializing_if = "Option::is_none")]
133    pub vcpus: Option<u32>,
134    #[serde(skip_serializing_if = "Option::is_none")]
135    pub memory_mb: Option<u64>,
136    #[serde(skip_serializing_if = "Option::is_none")]
137    pub profile: Option<SecurityProfile>,
138    /// Git repository URL to clone into the sandbox.
139    #[serde(skip_serializing_if = "Option::is_none")]
140    pub source_url: Option<String>,
141    /// Git ref to checkout after cloning.
142    #[serde(skip_serializing_if = "Option::is_none")]
143    pub source_ref: Option<String>,
144    /// Volume mounts (slug:/path or slug:/path:ro). Create volumes via CLI first.
145    #[serde(skip_serializing_if = "Vec::is_empty")]
146    #[serde(default)]
147    pub volumes: Vec<String>,
148    /// Secret bindings for proxy-based injection (Gondolin pattern).
149    /// Secrets are injected as HTTP headers by the host proxy — they never enter the VM.
150    /// Formats: `"KEY=value:host"`, `"KEY:host"`, `"KEY:host:header"`.
151    #[serde(skip_serializing_if = "Vec::is_empty")]
152    #[serde(default)]
153    pub secrets: Vec<String>,
154    /// Secret keys to inject as files at `/run/agentkernel/secrets/KEY`.
155    /// Values are resolved from the secret vault.
156    #[serde(skip_serializing_if = "Vec::is_empty")]
157    #[serde(default)]
158    pub secret_files: Vec<String>,
159}
160
161/// Create sandbox request body (internal).
162#[derive(Serialize)]
163pub(crate) struct CreateRequest {
164    pub name: String,
165    #[serde(skip_serializing_if = "Option::is_none")]
166    pub backend: Option<String>,
167    #[serde(skip_serializing_if = "Option::is_none")]
168    pub image: Option<String>,
169    #[serde(skip_serializing_if = "Option::is_none")]
170    pub vcpus: Option<u32>,
171    #[serde(skip_serializing_if = "Option::is_none")]
172    pub memory_mb: Option<u64>,
173    #[serde(skip_serializing_if = "Option::is_none")]
174    pub profile: Option<SecurityProfile>,
175    #[serde(skip_serializing_if = "Option::is_none")]
176    pub source_url: Option<String>,
177    #[serde(skip_serializing_if = "Option::is_none")]
178    pub source_ref: Option<String>,
179    #[serde(skip_serializing_if = "Vec::is_empty")]
180    #[serde(default)]
181    pub volumes: Vec<String>,
182    #[serde(skip_serializing_if = "Vec::is_empty")]
183    #[serde(default)]
184    pub secrets: Vec<String>,
185    #[serde(skip_serializing_if = "Vec::is_empty")]
186    #[serde(default)]
187    pub secret_files: Vec<String>,
188}
189
190/// Options for executing a command in a sandbox.
191#[derive(Debug, Default, Serialize)]
192pub struct ExecOptions {
193    /// Environment variables (`KEY=VALUE`).
194    #[serde(skip_serializing_if = "Vec::is_empty")]
195    pub env: Vec<String>,
196    /// Working directory inside the container.
197    #[serde(skip_serializing_if = "Option::is_none")]
198    pub workdir: Option<String>,
199    /// Run as root (maps to `--sudo` on CLI).
200    #[serde(skip_serializing_if = "Option::is_none")]
201    pub sudo: Option<bool>,
202}
203
204/// Exec request body (internal).
205#[derive(Serialize)]
206pub(crate) struct ExecRequest {
207    pub command: Vec<String>,
208    #[serde(skip_serializing_if = "Vec::is_empty")]
209    pub env: Vec<String>,
210    #[serde(skip_serializing_if = "Option::is_none")]
211    pub workdir: Option<String>,
212    #[serde(skip_serializing_if = "Option::is_none")]
213    pub sudo: Option<bool>,
214}
215
216/// File write request body (internal).
217#[derive(Serialize)]
218pub(crate) struct FileWriteRequest {
219    pub content: String,
220    #[serde(skip_serializing_if = "Option::is_none")]
221    pub encoding: Option<String>,
222}
223
224/// Response from reading a file.
225#[derive(Debug, Deserialize)]
226pub struct FileReadResponse {
227    pub content: String,
228    pub encoding: String,
229    pub size: usize,
230}
231
232/// Batch run request body (internal).
233#[derive(Serialize)]
234pub(crate) struct BatchRunRequest {
235    pub commands: Vec<BatchCommand>,
236}
237
238/// A command for batch execution.
239#[derive(Debug, Serialize)]
240pub struct BatchCommand {
241    pub command: Vec<String>,
242}
243
244/// Result of a single batch command.
245#[derive(Debug, Deserialize)]
246pub struct BatchResult {
247    pub output: Option<String>,
248    pub error: Option<String>,
249}
250
251/// Response from batch execution.
252#[derive(Debug, Deserialize)]
253pub struct BatchRunResponse {
254    pub results: Vec<BatchResult>,
255}
256
257/// Batch file write request body (internal).
258#[derive(Serialize)]
259pub(crate) struct BatchFileWriteRequest {
260    pub files: std::collections::HashMap<String, String>,
261}
262
263/// Result of a batch file write.
264#[derive(Debug, Deserialize)]
265pub struct BatchFileWriteResponse {
266    pub written: usize,
267}
268
269/// Response from extending a sandbox's TTL.
270#[derive(Debug, Deserialize)]
271pub struct ExtendTtlResponse {
272    pub expires_at: Option<String>,
273}
274
275/// Request body for extending TTL (internal).
276#[derive(Serialize)]
277pub(crate) struct ExtendTtlRequest {
278    pub by: String,
279}
280
281/// Metadata for a sandbox snapshot.
282#[derive(Debug, Deserialize)]
283pub struct SnapshotMeta {
284    pub name: String,
285    pub sandbox: String,
286    pub image_tag: String,
287    pub backend: String,
288    pub base_image: Option<String>,
289    pub vcpus: Option<u32>,
290    pub memory_mb: Option<u64>,
291    pub created_at: String,
292}
293
294/// Options for taking a snapshot.
295#[derive(Debug, Default, Serialize)]
296pub struct TakeSnapshotOptions {
297    pub sandbox: String,
298    #[serde(skip_serializing_if = "Option::is_none")]
299    pub name: Option<String>,
300}
301
302/// Status of a detached command.
303#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
304#[serde(rename_all = "lowercase")]
305pub enum DetachedStatus {
306    Running,
307    Completed,
308    Failed,
309}
310
311/// A detached (background) command running in a sandbox.
312#[derive(Debug, Deserialize)]
313pub struct DetachedCommand {
314    pub id: String,
315    pub sandbox: String,
316    pub command: Vec<String>,
317    pub pid: u32,
318    pub status: DetachedStatus,
319    pub exit_code: Option<i32>,
320    pub started_at: String,
321}
322
323/// Response from detached command logs.
324#[derive(Debug, Deserialize)]
325pub struct DetachedLogsResponse {
326    pub stdout: Option<String>,
327    pub stderr: Option<String>,
328}
329
330// -- Browser types --
331
332/// A link extracted from a page.
333#[derive(Debug, Clone, Serialize, Deserialize)]
334pub struct PageLink {
335    pub text: String,
336    pub href: String,
337}
338
339/// Result of navigating to a page.
340#[derive(Debug, Clone, Serialize, Deserialize)]
341pub struct PageResult {
342    pub title: String,
343    pub url: String,
344    pub text: String,
345    pub links: Vec<PageLink>,
346}
347
348/// ARIA accessibility tree snapshot of a web page (v2).
349#[derive(Debug, Clone, Serialize, Deserialize)]
350pub struct AriaSnapshot {
351    /// ARIA tree as YAML.
352    pub snapshot: String,
353    /// Current page URL.
354    pub url: String,
355    /// Page title.
356    pub title: String,
357    /// Available ref IDs (e.g. `["e1", "e2"]`).
358    #[serde(default)]
359    pub refs: Vec<String>,
360}
361
362/// A browser interaction event for debugging and context recovery.
363#[derive(Debug, Clone, Serialize, Deserialize)]
364pub struct BrowserEvent {
365    /// Monotonic sequence number.
366    pub seq: u64,
367    /// Event type (e.g. "page.navigated", "page.clicked").
368    #[serde(rename = "type")]
369    pub event_type: String,
370    /// Page name.
371    pub page: String,
372    /// ISO 8601 timestamp.
373    pub ts: String,
374}