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    pub status: String,
34    pub backend: String,
35    pub image: Option<String>,
36    pub vcpus: Option<u32>,
37    pub memory_mb: Option<u64>,
38    pub created_at: Option<String>,
39}
40
41/// SSE stream event.
42#[derive(Debug)]
43pub struct StreamEvent {
44    pub event_type: String,
45    pub data: serde_json::Value,
46}
47
48/// API response wrapper (internal).
49#[derive(Debug, Deserialize)]
50pub(crate) struct ApiResponse<T> {
51    pub success: bool,
52    pub data: Option<T>,
53    pub error: Option<String>,
54}
55
56/// Run request body (internal).
57#[derive(Serialize)]
58pub(crate) struct RunRequest {
59    pub command: Vec<String>,
60    #[serde(skip_serializing_if = "Option::is_none")]
61    pub image: Option<String>,
62    #[serde(skip_serializing_if = "Option::is_none")]
63    pub profile: Option<SecurityProfile>,
64    pub fast: bool,
65}
66
67/// Options for creating a sandbox with a git source.
68#[derive(Debug, Default, Serialize)]
69pub struct CreateSandboxOptions {
70    /// Docker image to use.
71    #[serde(skip_serializing_if = "Option::is_none")]
72    pub image: Option<String>,
73    #[serde(skip_serializing_if = "Option::is_none")]
74    pub vcpus: Option<u32>,
75    #[serde(skip_serializing_if = "Option::is_none")]
76    pub memory_mb: Option<u64>,
77    #[serde(skip_serializing_if = "Option::is_none")]
78    pub profile: Option<SecurityProfile>,
79    /// Git repository URL to clone into the sandbox.
80    #[serde(skip_serializing_if = "Option::is_none")]
81    pub source_url: Option<String>,
82    /// Git ref to checkout after cloning.
83    #[serde(skip_serializing_if = "Option::is_none")]
84    pub source_ref: Option<String>,
85    /// Volume mounts (slug:/path or slug:/path:ro). Create volumes via CLI first.
86    #[serde(skip_serializing_if = "Vec::is_empty")]
87    #[serde(default)]
88    pub volumes: Vec<String>,
89    /// Secret bindings for proxy-based injection (Gondolin pattern).
90    /// Secrets are injected as HTTP headers by the host proxy — they never enter the VM.
91    /// Formats: `"KEY=value:host"`, `"KEY:host"`, `"KEY:host:header"`.
92    #[serde(skip_serializing_if = "Vec::is_empty")]
93    #[serde(default)]
94    pub secrets: Vec<String>,
95    /// Secret keys to inject as files at `/run/agentkernel/secrets/KEY`.
96    /// Values are resolved from the secret vault.
97    #[serde(skip_serializing_if = "Vec::is_empty")]
98    #[serde(default)]
99    pub secret_files: Vec<String>,
100}
101
102/// Create sandbox request body (internal).
103#[derive(Serialize)]
104pub(crate) struct CreateRequest {
105    pub name: String,
106    #[serde(skip_serializing_if = "Option::is_none")]
107    pub image: Option<String>,
108    #[serde(skip_serializing_if = "Option::is_none")]
109    pub vcpus: Option<u32>,
110    #[serde(skip_serializing_if = "Option::is_none")]
111    pub memory_mb: Option<u64>,
112    #[serde(skip_serializing_if = "Option::is_none")]
113    pub profile: Option<SecurityProfile>,
114    #[serde(skip_serializing_if = "Option::is_none")]
115    pub source_url: Option<String>,
116    #[serde(skip_serializing_if = "Option::is_none")]
117    pub source_ref: Option<String>,
118    #[serde(skip_serializing_if = "Vec::is_empty")]
119    #[serde(default)]
120    pub volumes: Vec<String>,
121    #[serde(skip_serializing_if = "Vec::is_empty")]
122    #[serde(default)]
123    pub secrets: Vec<String>,
124    #[serde(skip_serializing_if = "Vec::is_empty")]
125    #[serde(default)]
126    pub secret_files: Vec<String>,
127}
128
129/// Options for executing a command in a sandbox.
130#[derive(Debug, Default, Serialize)]
131pub struct ExecOptions {
132    /// Environment variables (`KEY=VALUE`).
133    #[serde(skip_serializing_if = "Vec::is_empty")]
134    pub env: Vec<String>,
135    /// Working directory inside the container.
136    #[serde(skip_serializing_if = "Option::is_none")]
137    pub workdir: Option<String>,
138    /// Run as root (maps to `--sudo` on CLI).
139    #[serde(skip_serializing_if = "Option::is_none")]
140    pub sudo: Option<bool>,
141}
142
143/// Exec request body (internal).
144#[derive(Serialize)]
145pub(crate) struct ExecRequest {
146    pub command: Vec<String>,
147    #[serde(skip_serializing_if = "Vec::is_empty")]
148    pub env: Vec<String>,
149    #[serde(skip_serializing_if = "Option::is_none")]
150    pub workdir: Option<String>,
151    #[serde(skip_serializing_if = "Option::is_none")]
152    pub sudo: Option<bool>,
153}
154
155/// File write request body (internal).
156#[derive(Serialize)]
157pub(crate) struct FileWriteRequest {
158    pub content: String,
159    #[serde(skip_serializing_if = "Option::is_none")]
160    pub encoding: Option<String>,
161}
162
163/// Response from reading a file.
164#[derive(Debug, Deserialize)]
165pub struct FileReadResponse {
166    pub content: String,
167    pub encoding: String,
168    pub size: usize,
169}
170
171/// Batch run request body (internal).
172#[derive(Serialize)]
173pub(crate) struct BatchRunRequest {
174    pub commands: Vec<BatchCommand>,
175}
176
177/// A command for batch execution.
178#[derive(Debug, Serialize)]
179pub struct BatchCommand {
180    pub command: Vec<String>,
181}
182
183/// Result of a single batch command.
184#[derive(Debug, Deserialize)]
185pub struct BatchResult {
186    pub output: Option<String>,
187    pub error: Option<String>,
188}
189
190/// Response from batch execution.
191#[derive(Debug, Deserialize)]
192pub struct BatchRunResponse {
193    pub results: Vec<BatchResult>,
194}
195
196/// Batch file write request body (internal).
197#[derive(Serialize)]
198pub(crate) struct BatchFileWriteRequest {
199    pub files: std::collections::HashMap<String, String>,
200}
201
202/// Result of a batch file write.
203#[derive(Debug, Deserialize)]
204pub struct BatchFileWriteResponse {
205    pub written: usize,
206}
207
208/// Response from extending a sandbox's TTL.
209#[derive(Debug, Deserialize)]
210pub struct ExtendTtlResponse {
211    pub expires_at: Option<String>,
212}
213
214/// Request body for extending TTL (internal).
215#[derive(Serialize)]
216pub(crate) struct ExtendTtlRequest {
217    pub by: String,
218}
219
220/// Metadata for a sandbox snapshot.
221#[derive(Debug, Deserialize)]
222pub struct SnapshotMeta {
223    pub name: String,
224    pub sandbox: String,
225    pub image_tag: String,
226    pub backend: String,
227    pub base_image: Option<String>,
228    pub vcpus: Option<u32>,
229    pub memory_mb: Option<u64>,
230    pub created_at: String,
231}
232
233/// Options for taking a snapshot.
234#[derive(Debug, Default, Serialize)]
235pub struct TakeSnapshotOptions {
236    pub sandbox: String,
237    #[serde(skip_serializing_if = "Option::is_none")]
238    pub name: Option<String>,
239}
240
241/// Status of a detached command.
242#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
243#[serde(rename_all = "lowercase")]
244pub enum DetachedStatus {
245    Running,
246    Completed,
247    Failed,
248}
249
250/// A detached (background) command running in a sandbox.
251#[derive(Debug, Deserialize)]
252pub struct DetachedCommand {
253    pub id: String,
254    pub sandbox: String,
255    pub command: Vec<String>,
256    pub pid: u32,
257    pub status: DetachedStatus,
258    pub exit_code: Option<i32>,
259    pub started_at: String,
260}
261
262/// Response from detached command logs.
263#[derive(Debug, Deserialize)]
264pub struct DetachedLogsResponse {
265    pub stdout: Option<String>,
266    pub stderr: Option<String>,
267}
268
269// -- Browser types --
270
271/// A link extracted from a page.
272#[derive(Debug, Clone, Serialize, Deserialize)]
273pub struct PageLink {
274    pub text: String,
275    pub href: String,
276}
277
278/// Result of navigating to a page.
279#[derive(Debug, Clone, Serialize, Deserialize)]
280pub struct PageResult {
281    pub title: String,
282    pub url: String,
283    pub text: String,
284    pub links: Vec<PageLink>,
285}
286
287/// ARIA accessibility tree snapshot of a web page (v2).
288#[derive(Debug, Clone, Serialize, Deserialize)]
289pub struct AriaSnapshot {
290    /// ARIA tree as YAML.
291    pub snapshot: String,
292    /// Current page URL.
293    pub url: String,
294    /// Page title.
295    pub title: String,
296    /// Available ref IDs (e.g. `["e1", "e2"]`).
297    #[serde(default)]
298    pub refs: Vec<String>,
299}
300
301/// A browser interaction event for debugging and context recovery.
302#[derive(Debug, Clone, Serialize, Deserialize)]
303pub struct BrowserEvent {
304    /// Monotonic sequence number.
305    pub seq: u64,
306    /// Event type (e.g. "page.navigated", "page.clicked").
307    #[serde(rename = "type")]
308    pub event_type: String,
309    /// Page name.
310    pub page: String,
311    /// ISO 8601 timestamp.
312    pub ts: String,
313}