Skip to main content

agentos_sidecar_protocol/
protocol.rs

1use crate::generated_protocol::v1 as generated_protocol;
2use serde::de::{self, SeqAccess, Visitor};
3use serde::ser::SerializeTuple;
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5use serde_json::Value;
6use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
7use std::error::Error;
8use std::fmt;
9
10pub use crate::wire::{OwnershipRequirement, ProtocolCodecError, RequestDirection};
11
12pub const PROTOCOL_NAME: &str = crate::wire::PROTOCOL_NAME;
13pub const PROTOCOL_VERSION: u16 = crate::wire::PROTOCOL_VERSION;
14pub const DEFAULT_MAX_FRAME_BYTES: usize = crate::wire::DEFAULT_MAX_FRAME_BYTES;
15pub const DEFAULT_COMPLETED_RESPONSE_CAP: usize = 10_000;
16pub type RequestId = crate::wire::RequestId;
17pub type ExtEnvelope = crate::wire::ExtEnvelope;
18
19fn serialize_bare_newtype_tag<S, T>(serializer: S, tag: u64, payload: &T) -> Result<S::Ok, S::Error>
20where
21    S: Serializer,
22    T: Serialize,
23{
24    let mut tuple = serializer.serialize_tuple(2)?;
25    tuple.serialize_element(&serde_bare::Uint(tag))?;
26    tuple.serialize_element(payload)?;
27    tuple.end()
28}
29
30/// Convert the compatibility protocol frame into the generated wire frame.
31pub fn to_generated_protocol_frame(
32    frame: &ProtocolFrame,
33) -> Result<generated_protocol::ProtocolFrame, ProtocolCodecError> {
34    Ok(match frame {
35        ProtocolFrame::Request(frame) => {
36            generated_protocol::ProtocolFrame::RequestFrame(generated_protocol::RequestFrame {
37                schema: to_generated_protocol_schema(&frame.schema),
38                request_id: frame.request_id,
39                ownership: to_generated_ownership_scope(&frame.ownership),
40                payload: to_generated_request_payload(&frame.payload)?,
41            })
42        }
43        ProtocolFrame::Response(frame) => {
44            generated_protocol::ProtocolFrame::ResponseFrame(generated_protocol::ResponseFrame {
45                schema: to_generated_protocol_schema(&frame.schema),
46                request_id: frame.request_id,
47                ownership: to_generated_ownership_scope(&frame.ownership),
48                payload: to_generated_response_payload(&frame.payload)?,
49            })
50        }
51        ProtocolFrame::Event(frame) => {
52            generated_protocol::ProtocolFrame::EventFrame(generated_protocol::EventFrame {
53                schema: to_generated_protocol_schema(&frame.schema),
54                ownership: to_generated_ownership_scope(&frame.ownership),
55                payload: to_generated_event_payload(&frame.payload),
56            })
57        }
58        ProtocolFrame::SidecarRequest(frame) => {
59            generated_protocol::ProtocolFrame::SidecarRequestFrame(
60                generated_protocol::SidecarRequestFrame {
61                    schema: to_generated_protocol_schema(&frame.schema),
62                    request_id: frame.request_id,
63                    ownership: to_generated_ownership_scope(&frame.ownership),
64                    payload: to_generated_sidecar_request_payload(&frame.payload)?,
65                },
66            )
67        }
68        ProtocolFrame::SidecarResponse(frame) => {
69            generated_protocol::ProtocolFrame::SidecarResponseFrame(
70                generated_protocol::SidecarResponseFrame {
71                    schema: to_generated_protocol_schema(&frame.schema),
72                    request_id: frame.request_id,
73                    ownership: to_generated_ownership_scope(&frame.ownership),
74                    payload: to_generated_sidecar_response_payload(&frame.payload)?,
75                },
76            )
77        }
78        ProtocolFrame::Control(frame) => {
79            generated_protocol::ProtocolFrame::ControlFrame(frame.clone())
80        }
81    })
82}
83
84/// Convert the generated wire frame into the compatibility protocol frame.
85pub fn from_generated_protocol_frame(
86    frame: generated_protocol::ProtocolFrame,
87) -> Result<ProtocolFrame, ProtocolCodecError> {
88    Ok(match frame {
89        generated_protocol::ProtocolFrame::RequestFrame(frame) => {
90            ProtocolFrame::Request(RequestFrame {
91                schema: from_generated_protocol_schema(frame.schema),
92                request_id: frame.request_id,
93                ownership: from_generated_ownership_scope(frame.ownership),
94                payload: from_generated_request_payload(frame.payload)?,
95            })
96        }
97        generated_protocol::ProtocolFrame::ResponseFrame(frame) => {
98            ProtocolFrame::Response(ResponseFrame {
99                schema: from_generated_protocol_schema(frame.schema),
100                request_id: frame.request_id,
101                ownership: from_generated_ownership_scope(frame.ownership),
102                payload: from_generated_response_payload(frame.payload)?,
103            })
104        }
105        generated_protocol::ProtocolFrame::EventFrame(frame) => ProtocolFrame::Event(EventFrame {
106            schema: from_generated_protocol_schema(frame.schema),
107            ownership: from_generated_ownership_scope(frame.ownership),
108            payload: from_generated_event_payload(frame.payload),
109        }),
110        generated_protocol::ProtocolFrame::SidecarRequestFrame(frame) => {
111            ProtocolFrame::SidecarRequest(SidecarRequestFrame {
112                schema: from_generated_protocol_schema(frame.schema),
113                request_id: frame.request_id,
114                ownership: from_generated_ownership_scope(frame.ownership),
115                payload: from_generated_sidecar_request_payload(frame.payload)?,
116            })
117        }
118        generated_protocol::ProtocolFrame::SidecarResponseFrame(frame) => {
119            ProtocolFrame::SidecarResponse(SidecarResponseFrame {
120                schema: from_generated_protocol_schema(frame.schema),
121                request_id: frame.request_id,
122                ownership: from_generated_ownership_scope(frame.ownership),
123                payload: from_generated_sidecar_response_payload(frame.payload)?,
124            })
125        }
126        generated_protocol::ProtocolFrame::ControlFrame(frame) => ProtocolFrame::Control(frame),
127    })
128}
129
130fn to_generated_protocol_schema(schema: &ProtocolSchema) -> generated_protocol::ProtocolSchema {
131    schema.clone()
132}
133
134fn from_generated_protocol_schema(schema: generated_protocol::ProtocolSchema) -> ProtocolSchema {
135    schema
136}
137
138// `OwnershipScope` is now an alias for the generated `crate::wire::OwnershipScope`, so the
139// compat<->generated converters are identity functions. They are retained so the JSON-carrying
140// frame-conversion chain (still hand-written, out of scope for this pass) keeps compiling
141// without site-by-site rewiring.
142pub(crate) fn to_generated_ownership_scope(
143    ownership: &OwnershipScope,
144) -> generated_protocol::OwnershipScope {
145    ownership.clone()
146}
147
148pub(crate) fn from_generated_ownership_scope(
149    ownership: generated_protocol::OwnershipScope,
150) -> OwnershipScope {
151    ownership
152}
153
154fn to_generated_dispose_reason(reason: &DisposeReason) -> generated_protocol::DisposeReason {
155    match reason {
156        DisposeReason::Requested => generated_protocol::DisposeReason::Requested,
157        DisposeReason::ConnectionClosed => generated_protocol::DisposeReason::ConnectionClosed,
158        DisposeReason::HostShutdown => generated_protocol::DisposeReason::HostShutdown,
159    }
160}
161
162fn from_generated_dispose_reason(reason: generated_protocol::DisposeReason) -> DisposeReason {
163    match reason {
164        generated_protocol::DisposeReason::Requested => DisposeReason::Requested,
165        generated_protocol::DisposeReason::ConnectionClosed => DisposeReason::ConnectionClosed,
166        generated_protocol::DisposeReason::HostShutdown => DisposeReason::HostShutdown,
167    }
168}
169
170fn to_generated_filesystem_operation(
171    operation: &FilesystemOperation,
172) -> generated_protocol::FilesystemOperation {
173    match operation {
174        FilesystemOperation::Read => generated_protocol::FilesystemOperation::Read,
175        FilesystemOperation::Write => generated_protocol::FilesystemOperation::Write,
176        FilesystemOperation::Stat => generated_protocol::FilesystemOperation::Stat,
177        FilesystemOperation::ReadDir => generated_protocol::FilesystemOperation::ReadDir,
178        FilesystemOperation::Mkdir => generated_protocol::FilesystemOperation::Mkdir,
179        FilesystemOperation::Remove => generated_protocol::FilesystemOperation::Remove,
180        FilesystemOperation::Rename => generated_protocol::FilesystemOperation::Rename,
181    }
182}
183
184fn from_generated_filesystem_operation(
185    operation: generated_protocol::FilesystemOperation,
186) -> FilesystemOperation {
187    match operation {
188        generated_protocol::FilesystemOperation::Read => FilesystemOperation::Read,
189        generated_protocol::FilesystemOperation::Write => FilesystemOperation::Write,
190        generated_protocol::FilesystemOperation::Stat => FilesystemOperation::Stat,
191        generated_protocol::FilesystemOperation::ReadDir => FilesystemOperation::ReadDir,
192        generated_protocol::FilesystemOperation::Mkdir => FilesystemOperation::Mkdir,
193        generated_protocol::FilesystemOperation::Remove => FilesystemOperation::Remove,
194        generated_protocol::FilesystemOperation::Rename => FilesystemOperation::Rename,
195    }
196}
197
198fn to_generated_guest_filesystem_operation(
199    operation: &GuestFilesystemOperation,
200) -> generated_protocol::GuestFilesystemOperation {
201    match operation {
202        GuestFilesystemOperation::ReadFile => {
203            generated_protocol::GuestFilesystemOperation::ReadFile
204        }
205        GuestFilesystemOperation::WriteFile => {
206            generated_protocol::GuestFilesystemOperation::WriteFile
207        }
208        GuestFilesystemOperation::CreateDir => {
209            generated_protocol::GuestFilesystemOperation::CreateDir
210        }
211        GuestFilesystemOperation::Mkdir => generated_protocol::GuestFilesystemOperation::Mkdir,
212        GuestFilesystemOperation::Exists => generated_protocol::GuestFilesystemOperation::Exists,
213        GuestFilesystemOperation::Stat => generated_protocol::GuestFilesystemOperation::Stat,
214        GuestFilesystemOperation::Lstat => generated_protocol::GuestFilesystemOperation::Lstat,
215        GuestFilesystemOperation::ReadDir => generated_protocol::GuestFilesystemOperation::ReadDir,
216        GuestFilesystemOperation::ReadDirRecursive => {
217            generated_protocol::GuestFilesystemOperation::ReadDirRecursive
218        }
219        GuestFilesystemOperation::RemoveFile => {
220            generated_protocol::GuestFilesystemOperation::RemoveFile
221        }
222        GuestFilesystemOperation::RemoveDir => {
223            generated_protocol::GuestFilesystemOperation::RemoveDir
224        }
225        GuestFilesystemOperation::Remove => generated_protocol::GuestFilesystemOperation::Remove,
226        GuestFilesystemOperation::Copy => generated_protocol::GuestFilesystemOperation::Copy,
227        GuestFilesystemOperation::Move => generated_protocol::GuestFilesystemOperation::Move,
228        GuestFilesystemOperation::Rename => generated_protocol::GuestFilesystemOperation::Rename,
229        GuestFilesystemOperation::Realpath => {
230            generated_protocol::GuestFilesystemOperation::Realpath
231        }
232        GuestFilesystemOperation::Symlink => generated_protocol::GuestFilesystemOperation::Symlink,
233        GuestFilesystemOperation::ReadLink => {
234            generated_protocol::GuestFilesystemOperation::ReadLink
235        }
236        GuestFilesystemOperation::Link => generated_protocol::GuestFilesystemOperation::Link,
237        GuestFilesystemOperation::Chmod => generated_protocol::GuestFilesystemOperation::Chmod,
238        GuestFilesystemOperation::Chown => generated_protocol::GuestFilesystemOperation::Chown,
239        GuestFilesystemOperation::Utimes => generated_protocol::GuestFilesystemOperation::Utimes,
240        GuestFilesystemOperation::Truncate => {
241            generated_protocol::GuestFilesystemOperation::Truncate
242        }
243        GuestFilesystemOperation::Pread => generated_protocol::GuestFilesystemOperation::Pread,
244        GuestFilesystemOperation::Pwrite => generated_protocol::GuestFilesystemOperation::Pwrite,
245    }
246}
247
248fn from_generated_guest_filesystem_operation(
249    operation: generated_protocol::GuestFilesystemOperation,
250) -> GuestFilesystemOperation {
251    match operation {
252        generated_protocol::GuestFilesystemOperation::ReadFile => {
253            GuestFilesystemOperation::ReadFile
254        }
255        generated_protocol::GuestFilesystemOperation::WriteFile => {
256            GuestFilesystemOperation::WriteFile
257        }
258        generated_protocol::GuestFilesystemOperation::CreateDir => {
259            GuestFilesystemOperation::CreateDir
260        }
261        generated_protocol::GuestFilesystemOperation::Mkdir => GuestFilesystemOperation::Mkdir,
262        generated_protocol::GuestFilesystemOperation::Exists => GuestFilesystemOperation::Exists,
263        generated_protocol::GuestFilesystemOperation::Stat => GuestFilesystemOperation::Stat,
264        generated_protocol::GuestFilesystemOperation::Lstat => GuestFilesystemOperation::Lstat,
265        generated_protocol::GuestFilesystemOperation::ReadDir => GuestFilesystemOperation::ReadDir,
266        generated_protocol::GuestFilesystemOperation::ReadDirRecursive => {
267            GuestFilesystemOperation::ReadDirRecursive
268        }
269        generated_protocol::GuestFilesystemOperation::RemoveFile => {
270            GuestFilesystemOperation::RemoveFile
271        }
272        generated_protocol::GuestFilesystemOperation::RemoveDir => {
273            GuestFilesystemOperation::RemoveDir
274        }
275        generated_protocol::GuestFilesystemOperation::Remove => GuestFilesystemOperation::Remove,
276        generated_protocol::GuestFilesystemOperation::Copy => GuestFilesystemOperation::Copy,
277        generated_protocol::GuestFilesystemOperation::Move => GuestFilesystemOperation::Move,
278        generated_protocol::GuestFilesystemOperation::Rename => GuestFilesystemOperation::Rename,
279        generated_protocol::GuestFilesystemOperation::Realpath => {
280            GuestFilesystemOperation::Realpath
281        }
282        generated_protocol::GuestFilesystemOperation::Symlink => GuestFilesystemOperation::Symlink,
283        generated_protocol::GuestFilesystemOperation::ReadLink => {
284            GuestFilesystemOperation::ReadLink
285        }
286        generated_protocol::GuestFilesystemOperation::Link => GuestFilesystemOperation::Link,
287        generated_protocol::GuestFilesystemOperation::Chmod => GuestFilesystemOperation::Chmod,
288        generated_protocol::GuestFilesystemOperation::Chown => GuestFilesystemOperation::Chown,
289        generated_protocol::GuestFilesystemOperation::Utimes => GuestFilesystemOperation::Utimes,
290        generated_protocol::GuestFilesystemOperation::Truncate => {
291            GuestFilesystemOperation::Truncate
292        }
293        generated_protocol::GuestFilesystemOperation::Pread => GuestFilesystemOperation::Pread,
294        generated_protocol::GuestFilesystemOperation::Pwrite => GuestFilesystemOperation::Pwrite,
295    }
296}
297
298fn to_generated_permission_mode(mode: &PermissionMode) -> generated_protocol::PermissionMode {
299    mode.clone()
300}
301
302fn from_generated_permission_mode(mode: generated_protocol::PermissionMode) -> PermissionMode {
303    mode
304}
305
306fn to_generated_root_filesystem_entry_encoding(
307    encoding: &RootFilesystemEntryEncoding,
308) -> generated_protocol::RootFilesystemEntryEncoding {
309    match encoding {
310        RootFilesystemEntryEncoding::Utf8 => generated_protocol::RootFilesystemEntryEncoding::Utf8,
311        RootFilesystemEntryEncoding::Base64 => {
312            generated_protocol::RootFilesystemEntryEncoding::Base64
313        }
314    }
315}
316
317fn from_generated_root_filesystem_entry_encoding(
318    encoding: generated_protocol::RootFilesystemEntryEncoding,
319) -> RootFilesystemEntryEncoding {
320    match encoding {
321        generated_protocol::RootFilesystemEntryEncoding::Utf8 => RootFilesystemEntryEncoding::Utf8,
322        generated_protocol::RootFilesystemEntryEncoding::Base64 => {
323            RootFilesystemEntryEncoding::Base64
324        }
325    }
326}
327
328fn to_generated_stream_channel(channel: &StreamChannel) -> generated_protocol::StreamChannel {
329    match channel {
330        StreamChannel::Stdout => generated_protocol::StreamChannel::Stdout,
331        StreamChannel::Stderr => generated_protocol::StreamChannel::Stderr,
332    }
333}
334
335fn from_generated_stream_channel(channel: generated_protocol::StreamChannel) -> StreamChannel {
336    match channel {
337        generated_protocol::StreamChannel::Stdout => StreamChannel::Stdout,
338        generated_protocol::StreamChannel::Stderr => StreamChannel::Stderr,
339    }
340}
341
342fn to_generated_vm_lifecycle_state(
343    state: &VmLifecycleState,
344) -> generated_protocol::VmLifecycleState {
345    match state {
346        VmLifecycleState::Creating => generated_protocol::VmLifecycleState::Creating,
347        VmLifecycleState::Ready => generated_protocol::VmLifecycleState::Ready,
348        VmLifecycleState::Disposing => generated_protocol::VmLifecycleState::Disposing,
349        VmLifecycleState::Disposed => generated_protocol::VmLifecycleState::Disposed,
350        VmLifecycleState::Failed => generated_protocol::VmLifecycleState::Failed,
351    }
352}
353
354fn from_generated_vm_lifecycle_state(
355    state: generated_protocol::VmLifecycleState,
356) -> VmLifecycleState {
357    match state {
358        generated_protocol::VmLifecycleState::Creating => VmLifecycleState::Creating,
359        generated_protocol::VmLifecycleState::Ready => VmLifecycleState::Ready,
360        generated_protocol::VmLifecycleState::Disposing => VmLifecycleState::Disposing,
361        generated_protocol::VmLifecycleState::Disposed => VmLifecycleState::Disposed,
362        generated_protocol::VmLifecycleState::Failed => VmLifecycleState::Failed,
363    }
364}
365
366fn to_generated_guest_filesystem_stat(
367    stat: &GuestFilesystemStat,
368) -> generated_protocol::GuestFilesystemStat {
369    stat.clone()
370}
371
372fn from_generated_guest_filesystem_stat(
373    stat: generated_protocol::GuestFilesystemStat,
374) -> GuestFilesystemStat {
375    stat
376}
377
378fn to_generated_process_snapshot_entry(
379    entry: &ProcessSnapshotEntry,
380) -> generated_protocol::ProcessSnapshotEntry {
381    entry.clone()
382}
383
384fn from_generated_process_snapshot_entry(
385    entry: generated_protocol::ProcessSnapshotEntry,
386) -> ProcessSnapshotEntry {
387    entry
388}
389
390fn to_generated_ext_envelope(envelope: &ExtEnvelope) -> generated_protocol::ExtEnvelope {
391    envelope.clone()
392}
393
394fn from_generated_ext_envelope(envelope: generated_protocol::ExtEnvelope) -> ExtEnvelope {
395    envelope
396}
397
398fn to_generated_request_payload(
399    payload: &RequestPayload,
400) -> Result<generated_protocol::RequestPayload, ProtocolCodecError> {
401    Ok(match payload {
402        RequestPayload::Authenticate(inner) => {
403            generated_protocol::RequestPayload::AuthenticateRequest(inner.clone())
404        }
405        RequestPayload::OpenSession(inner) => {
406            generated_protocol::RequestPayload::OpenSessionRequest(inner.clone())
407        }
408        RequestPayload::CreateVm(inner) => {
409            generated_protocol::RequestPayload::CreateVmRequest(inner.clone())
410        }
411        RequestPayload::DisposeVm(inner) => generated_protocol::RequestPayload::DisposeVmRequest(
412            generated_protocol::DisposeVmRequest {
413                reason: to_generated_dispose_reason(&inner.reason),
414            },
415        ),
416        RequestPayload::BootstrapRootFilesystem(inner) => {
417            generated_protocol::RequestPayload::BootstrapRootFilesystemRequest(inner.clone())
418        }
419        RequestPayload::ConfigureVm(inner) => {
420            generated_protocol::RequestPayload::ConfigureVmRequest(inner.clone())
421        }
422        RequestPayload::RegisterHostCallbacks(inner) => {
423            generated_protocol::RequestPayload::RegisterHostCallbacksRequest(inner.clone())
424        }
425        RequestPayload::CreateLayer(_) => generated_protocol::RequestPayload::CreateLayerRequest,
426        RequestPayload::SealLayer(inner) => {
427            generated_protocol::RequestPayload::SealLayerRequest(inner.clone())
428        }
429        RequestPayload::ImportSnapshot(inner) => {
430            generated_protocol::RequestPayload::ImportSnapshotRequest(inner.clone())
431        }
432        RequestPayload::ExportSnapshot(inner) => {
433            generated_protocol::RequestPayload::ExportSnapshotRequest(inner.clone())
434        }
435        RequestPayload::CreateOverlay(inner) => {
436            generated_protocol::RequestPayload::CreateOverlayRequest(inner.clone())
437        }
438        RequestPayload::GuestFilesystemCall(inner) => {
439            generated_protocol::RequestPayload::GuestFilesystemCallRequest(inner.clone())
440        }
441        RequestPayload::SnapshotRootFilesystem(inner) => {
442            generated_protocol::RequestPayload::SnapshotRootFilesystemRequest(inner.clone())
443        }
444        RequestPayload::ListMounts(_) => generated_protocol::RequestPayload::ListMountsRequest,
445        RequestPayload::Execute(inner) => {
446            generated_protocol::RequestPayload::ExecuteRequest(inner.clone())
447        }
448        RequestPayload::WriteStdin(inner) => {
449            generated_protocol::RequestPayload::WriteStdinRequest(inner.clone())
450        }
451        RequestPayload::CloseStdin(inner) => {
452            generated_protocol::RequestPayload::CloseStdinRequest(inner.clone())
453        }
454        RequestPayload::KillProcess(inner) => {
455            generated_protocol::RequestPayload::KillProcessRequest(inner.clone())
456        }
457        RequestPayload::GetProcessSnapshot(_) => {
458            generated_protocol::RequestPayload::GetProcessSnapshotRequest
459        }
460        RequestPayload::GetResourceSnapshot(_) => {
461            generated_protocol::RequestPayload::GetResourceSnapshotRequest
462        }
463        RequestPayload::FindListener(inner) => {
464            generated_protocol::RequestPayload::FindListenerRequest(inner.clone())
465        }
466        RequestPayload::FindBoundUdp(inner) => {
467            generated_protocol::RequestPayload::FindBoundUdpRequest(inner.clone())
468        }
469        RequestPayload::VmFetch(inner) => {
470            generated_protocol::RequestPayload::VmFetchRequest(inner.clone())
471        }
472        RequestPayload::GetSignalState(inner) => {
473            generated_protocol::RequestPayload::GetSignalStateRequest(inner.clone())
474        }
475        RequestPayload::GetZombieTimerCount(_) => {
476            generated_protocol::RequestPayload::GetZombieTimerCountRequest
477        }
478        RequestPayload::HostFilesystemCall(inner) => {
479            generated_protocol::RequestPayload::HostFilesystemCallRequest(
480                generated_protocol::HostFilesystemCallRequest {
481                    operation: to_generated_filesystem_operation(&inner.operation),
482                    path: inner.path.clone(),
483                    payload_size_bytes: inner.payload_size_bytes,
484                },
485            )
486        }
487        RequestPayload::PersistenceLoad(inner) => {
488            generated_protocol::RequestPayload::PersistenceLoadRequest(inner.clone())
489        }
490        RequestPayload::PersistenceFlush(inner) => {
491            generated_protocol::RequestPayload::PersistenceFlushRequest(inner.clone())
492        }
493        RequestPayload::Ext(inner) => {
494            generated_protocol::RequestPayload::ExtEnvelope(to_generated_ext_envelope(inner))
495        }
496        RequestPayload::GuestKernelCall(inner) => {
497            generated_protocol::RequestPayload::GuestKernelCallRequest(inner.clone())
498        }
499        RequestPayload::ResizePty(inner) => {
500            generated_protocol::RequestPayload::ResizePtyRequest(inner.clone())
501        }
502        RequestPayload::LinkPackage(inner) => {
503            generated_protocol::RequestPayload::LinkPackageRequest(inner.clone())
504        }
505        RequestPayload::ProvidedCommands(_) => {
506            generated_protocol::RequestPayload::ProvidedCommandsRequest
507        }
508        RequestPayload::ShellExecution(inner) => {
509            generated_protocol::RequestPayload::ShellExecutionRequest(inner.clone())
510        }
511        RequestPayload::ArgvExecution(inner) => {
512            generated_protocol::RequestPayload::ArgvExecutionRequest(inner.clone())
513        }
514        RequestPayload::JavaScriptExecution(inner) => {
515            generated_protocol::RequestPayload::JavaScriptExecutionRequest(inner.clone())
516        }
517        RequestPayload::JavaScriptEvaluation(inner) => {
518            generated_protocol::RequestPayload::JavaScriptEvaluationRequest(inner.clone())
519        }
520        RequestPayload::JavaScriptFileExecution(inner) => {
521            generated_protocol::RequestPayload::JavaScriptFileExecutionRequest(inner.clone())
522        }
523        RequestPayload::TypeScriptExecution(inner) => {
524            generated_protocol::RequestPayload::TypeScriptExecutionRequest(inner.clone())
525        }
526        RequestPayload::TypeScriptEvaluation(inner) => {
527            generated_protocol::RequestPayload::TypeScriptEvaluationRequest(inner.clone())
528        }
529        RequestPayload::TypeScriptFileExecution(inner) => {
530            generated_protocol::RequestPayload::TypeScriptFileExecutionRequest(inner.clone())
531        }
532        RequestPayload::TypeScriptCheck(inner) => {
533            generated_protocol::RequestPayload::TypeScriptCheckRequest(inner.clone())
534        }
535        RequestPayload::TypeScriptProjectCheck(inner) => {
536            generated_protocol::RequestPayload::TypeScriptProjectCheckRequest(inner.clone())
537        }
538        RequestPayload::NpmProjectInstall(inner) => {
539            generated_protocol::RequestPayload::NpmProjectInstallRequest(inner.clone())
540        }
541        RequestPayload::NpmPackageInstall(inner) => {
542            generated_protocol::RequestPayload::NpmPackageInstallRequest(inner.clone())
543        }
544        RequestPayload::NpmScriptExecution(inner) => {
545            generated_protocol::RequestPayload::NpmScriptExecutionRequest(inner.clone())
546        }
547        RequestPayload::NpmPackageExecution(inner) => {
548            generated_protocol::RequestPayload::NpmPackageExecutionRequest(inner.clone())
549        }
550        RequestPayload::PythonExecution(inner) => {
551            generated_protocol::RequestPayload::PythonExecutionRequest(inner.clone())
552        }
553        RequestPayload::PythonEvaluation(inner) => {
554            generated_protocol::RequestPayload::PythonEvaluationRequest(inner.clone())
555        }
556        RequestPayload::PythonFileExecution(inner) => {
557            generated_protocol::RequestPayload::PythonFileExecutionRequest(inner.clone())
558        }
559        RequestPayload::PythonModuleExecution(inner) => {
560            generated_protocol::RequestPayload::PythonModuleExecutionRequest(inner.clone())
561        }
562        RequestPayload::PythonInstall(inner) => {
563            generated_protocol::RequestPayload::PythonInstallRequest(inner.clone())
564        }
565        RequestPayload::CreateContext(inner) => {
566            generated_protocol::RequestPayload::CreateContextRequest(inner.clone())
567        }
568        RequestPayload::GetExecution(inner) => {
569            generated_protocol::RequestPayload::GetExecutionRequest(inner.clone())
570        }
571        RequestPayload::ListExecutions(_) => {
572            generated_protocol::RequestPayload::ListExecutionsRequest
573        }
574        RequestPayload::WaitExecution(inner) => {
575            generated_protocol::RequestPayload::WaitExecutionRequest(inner.clone())
576        }
577        RequestPayload::CancelExecution(inner) => {
578            generated_protocol::RequestPayload::CancelExecutionRequest(inner.clone())
579        }
580        RequestPayload::SignalExecution(inner) => {
581            generated_protocol::RequestPayload::SignalExecutionRequest(inner.clone())
582        }
583        RequestPayload::ResetExecution(inner) => {
584            generated_protocol::RequestPayload::ResetExecutionRequest(inner.clone())
585        }
586        RequestPayload::DeleteExecution(inner) => {
587            generated_protocol::RequestPayload::DeleteExecutionRequest(inner.clone())
588        }
589        RequestPayload::WriteExecutionStdin(inner) => {
590            generated_protocol::RequestPayload::WriteExecutionStdinRequest(inner.clone())
591        }
592        RequestPayload::CloseExecutionStdin(inner) => {
593            generated_protocol::RequestPayload::CloseExecutionStdinRequest(inner.clone())
594        }
595        RequestPayload::ResizeExecutionPty(inner) => {
596            generated_protocol::RequestPayload::ResizeExecutionPtyRequest(inner.clone())
597        }
598        RequestPayload::ReadExecutionOutput(inner) => {
599            generated_protocol::RequestPayload::ReadExecutionOutputRequest(inner.clone())
600        }
601    })
602}
603
604fn from_generated_request_payload(
605    payload: generated_protocol::RequestPayload,
606) -> Result<RequestPayload, ProtocolCodecError> {
607    Ok(match payload {
608        generated_protocol::RequestPayload::AuthenticateRequest(inner) => {
609            RequestPayload::Authenticate(inner)
610        }
611        generated_protocol::RequestPayload::OpenSessionRequest(inner) => {
612            RequestPayload::OpenSession(inner)
613        }
614        generated_protocol::RequestPayload::CreateVmRequest(inner) => {
615            RequestPayload::CreateVm(inner)
616        }
617        generated_protocol::RequestPayload::DisposeVmRequest(inner) => {
618            RequestPayload::DisposeVm(DisposeVmRequest {
619                reason: from_generated_dispose_reason(inner.reason),
620            })
621        }
622        generated_protocol::RequestPayload::BootstrapRootFilesystemRequest(inner) => {
623            RequestPayload::BootstrapRootFilesystem(inner)
624        }
625        generated_protocol::RequestPayload::ConfigureVmRequest(inner) => {
626            RequestPayload::ConfigureVm(inner)
627        }
628        generated_protocol::RequestPayload::RegisterHostCallbacksRequest(inner) => {
629            RequestPayload::RegisterHostCallbacks(inner)
630        }
631        generated_protocol::RequestPayload::CreateLayerRequest => {
632            RequestPayload::CreateLayer(CreateLayerRequest {})
633        }
634        generated_protocol::RequestPayload::SealLayerRequest(inner) => {
635            RequestPayload::SealLayer(inner)
636        }
637        generated_protocol::RequestPayload::ImportSnapshotRequest(inner) => {
638            RequestPayload::ImportSnapshot(inner)
639        }
640        generated_protocol::RequestPayload::ExportSnapshotRequest(inner) => {
641            RequestPayload::ExportSnapshot(inner)
642        }
643        generated_protocol::RequestPayload::CreateOverlayRequest(inner) => {
644            RequestPayload::CreateOverlay(inner)
645        }
646        generated_protocol::RequestPayload::GuestFilesystemCallRequest(inner) => {
647            RequestPayload::GuestFilesystemCall(inner)
648        }
649        generated_protocol::RequestPayload::SnapshotRootFilesystemRequest(inner) => {
650            RequestPayload::SnapshotRootFilesystem(inner)
651        }
652        generated_protocol::RequestPayload::ListMountsRequest => {
653            RequestPayload::ListMounts(ListMountsRequest {})
654        }
655        generated_protocol::RequestPayload::ExecuteRequest(inner) => RequestPayload::Execute(inner),
656        generated_protocol::RequestPayload::WriteStdinRequest(inner) => {
657            RequestPayload::WriteStdin(inner)
658        }
659        generated_protocol::RequestPayload::CloseStdinRequest(inner) => {
660            RequestPayload::CloseStdin(inner)
661        }
662        generated_protocol::RequestPayload::KillProcessRequest(inner) => {
663            RequestPayload::KillProcess(inner)
664        }
665        generated_protocol::RequestPayload::GetProcessSnapshotRequest => {
666            RequestPayload::GetProcessSnapshot(GetProcessSnapshotRequest {})
667        }
668        generated_protocol::RequestPayload::GetResourceSnapshotRequest => {
669            RequestPayload::GetResourceSnapshot(GetResourceSnapshotRequest {})
670        }
671        generated_protocol::RequestPayload::FindListenerRequest(inner) => {
672            RequestPayload::FindListener(inner)
673        }
674        generated_protocol::RequestPayload::FindBoundUdpRequest(inner) => {
675            RequestPayload::FindBoundUdp(inner)
676        }
677        generated_protocol::RequestPayload::VmFetchRequest(inner) => RequestPayload::VmFetch(inner),
678        generated_protocol::RequestPayload::GetSignalStateRequest(inner) => {
679            RequestPayload::GetSignalState(inner)
680        }
681        generated_protocol::RequestPayload::GetZombieTimerCountRequest => {
682            RequestPayload::GetZombieTimerCount(GetZombieTimerCountRequest {})
683        }
684        generated_protocol::RequestPayload::HostFilesystemCallRequest(inner) => {
685            RequestPayload::HostFilesystemCall(HostFilesystemCallRequest {
686                operation: from_generated_filesystem_operation(inner.operation),
687                path: inner.path,
688                payload_size_bytes: inner.payload_size_bytes,
689            })
690        }
691        generated_protocol::RequestPayload::PersistenceLoadRequest(inner) => {
692            RequestPayload::PersistenceLoad(inner)
693        }
694        generated_protocol::RequestPayload::PersistenceFlushRequest(inner) => {
695            RequestPayload::PersistenceFlush(inner)
696        }
697        generated_protocol::RequestPayload::ExtEnvelope(inner) => {
698            RequestPayload::Ext(from_generated_ext_envelope(inner))
699        }
700        generated_protocol::RequestPayload::GuestKernelCallRequest(inner) => {
701            RequestPayload::GuestKernelCall(inner)
702        }
703        generated_protocol::RequestPayload::ResizePtyRequest(inner) => {
704            RequestPayload::ResizePty(inner)
705        }
706        generated_protocol::RequestPayload::LinkPackageRequest(inner) => {
707            RequestPayload::LinkPackage(inner)
708        }
709        generated_protocol::RequestPayload::ProvidedCommandsRequest => {
710            RequestPayload::ProvidedCommands(ProvidedCommandsRequest {})
711        }
712        generated_protocol::RequestPayload::ShellExecutionRequest(inner) => {
713            RequestPayload::ShellExecution(inner)
714        }
715        generated_protocol::RequestPayload::ArgvExecutionRequest(inner) => {
716            RequestPayload::ArgvExecution(inner)
717        }
718        generated_protocol::RequestPayload::JavaScriptExecutionRequest(inner) => {
719            RequestPayload::JavaScriptExecution(inner)
720        }
721        generated_protocol::RequestPayload::JavaScriptEvaluationRequest(inner) => {
722            RequestPayload::JavaScriptEvaluation(inner)
723        }
724        generated_protocol::RequestPayload::JavaScriptFileExecutionRequest(inner) => {
725            RequestPayload::JavaScriptFileExecution(inner)
726        }
727        generated_protocol::RequestPayload::TypeScriptExecutionRequest(inner) => {
728            RequestPayload::TypeScriptExecution(inner)
729        }
730        generated_protocol::RequestPayload::TypeScriptEvaluationRequest(inner) => {
731            RequestPayload::TypeScriptEvaluation(inner)
732        }
733        generated_protocol::RequestPayload::TypeScriptFileExecutionRequest(inner) => {
734            RequestPayload::TypeScriptFileExecution(inner)
735        }
736        generated_protocol::RequestPayload::TypeScriptCheckRequest(inner) => {
737            RequestPayload::TypeScriptCheck(inner)
738        }
739        generated_protocol::RequestPayload::TypeScriptProjectCheckRequest(inner) => {
740            RequestPayload::TypeScriptProjectCheck(inner)
741        }
742        generated_protocol::RequestPayload::NpmProjectInstallRequest(inner) => {
743            RequestPayload::NpmProjectInstall(inner)
744        }
745        generated_protocol::RequestPayload::NpmPackageInstallRequest(inner) => {
746            RequestPayload::NpmPackageInstall(inner)
747        }
748        generated_protocol::RequestPayload::NpmScriptExecutionRequest(inner) => {
749            RequestPayload::NpmScriptExecution(inner)
750        }
751        generated_protocol::RequestPayload::NpmPackageExecutionRequest(inner) => {
752            RequestPayload::NpmPackageExecution(inner)
753        }
754        generated_protocol::RequestPayload::PythonExecutionRequest(inner) => {
755            RequestPayload::PythonExecution(inner)
756        }
757        generated_protocol::RequestPayload::PythonEvaluationRequest(inner) => {
758            RequestPayload::PythonEvaluation(inner)
759        }
760        generated_protocol::RequestPayload::PythonFileExecutionRequest(inner) => {
761            RequestPayload::PythonFileExecution(inner)
762        }
763        generated_protocol::RequestPayload::PythonModuleExecutionRequest(inner) => {
764            RequestPayload::PythonModuleExecution(inner)
765        }
766        generated_protocol::RequestPayload::PythonInstallRequest(inner) => {
767            RequestPayload::PythonInstall(inner)
768        }
769        generated_protocol::RequestPayload::CreateContextRequest(inner) => {
770            RequestPayload::CreateContext(inner)
771        }
772        generated_protocol::RequestPayload::GetExecutionRequest(inner) => {
773            RequestPayload::GetExecution(inner)
774        }
775        generated_protocol::RequestPayload::ListExecutionsRequest => {
776            RequestPayload::ListExecutions(ListExecutionsRequest {})
777        }
778        generated_protocol::RequestPayload::WaitExecutionRequest(inner) => {
779            RequestPayload::WaitExecution(inner)
780        }
781        generated_protocol::RequestPayload::CancelExecutionRequest(inner) => {
782            RequestPayload::CancelExecution(inner)
783        }
784        generated_protocol::RequestPayload::SignalExecutionRequest(inner) => {
785            RequestPayload::SignalExecution(inner)
786        }
787        generated_protocol::RequestPayload::ResetExecutionRequest(inner) => {
788            RequestPayload::ResetExecution(inner)
789        }
790        generated_protocol::RequestPayload::DeleteExecutionRequest(inner) => {
791            RequestPayload::DeleteExecution(inner)
792        }
793        generated_protocol::RequestPayload::WriteExecutionStdinRequest(inner) => {
794            RequestPayload::WriteExecutionStdin(inner)
795        }
796        generated_protocol::RequestPayload::CloseExecutionStdinRequest(inner) => {
797            RequestPayload::CloseExecutionStdin(inner)
798        }
799        generated_protocol::RequestPayload::ResizeExecutionPtyRequest(inner) => {
800            RequestPayload::ResizeExecutionPty(inner)
801        }
802        generated_protocol::RequestPayload::ReadExecutionOutputRequest(inner) => {
803            RequestPayload::ReadExecutionOutput(inner)
804        }
805    })
806}
807
808fn to_generated_response_payload(
809    payload: &ResponsePayload,
810) -> Result<generated_protocol::ResponsePayload, ProtocolCodecError> {
811    Ok(match payload {
812        ResponsePayload::Authenticated(inner) => {
813            generated_protocol::ResponsePayload::AuthenticatedResponse(inner.clone())
814        }
815        ResponsePayload::SessionOpened(inner) => {
816            generated_protocol::ResponsePayload::SessionOpenedResponse(inner.clone())
817        }
818        ResponsePayload::VmCreated(inner) => {
819            generated_protocol::ResponsePayload::VmCreatedResponse(inner.clone())
820        }
821        ResponsePayload::VmDisposed(inner) => {
822            generated_protocol::ResponsePayload::VmDisposedResponse(inner.clone())
823        }
824        ResponsePayload::RootFilesystemBootstrapped(inner) => {
825            generated_protocol::ResponsePayload::RootFilesystemBootstrappedResponse(inner.clone())
826        }
827        ResponsePayload::VmConfigured(inner) => {
828            generated_protocol::ResponsePayload::VmConfiguredResponse(inner.clone())
829        }
830        ResponsePayload::HostCallbacksRegistered(inner) => {
831            generated_protocol::ResponsePayload::HostCallbacksRegisteredResponse(inner.clone())
832        }
833        ResponsePayload::LayerCreated(inner) => {
834            generated_protocol::ResponsePayload::LayerCreatedResponse(inner.clone())
835        }
836        ResponsePayload::LayerSealed(inner) => {
837            generated_protocol::ResponsePayload::LayerSealedResponse(inner.clone())
838        }
839        ResponsePayload::SnapshotImported(inner) => {
840            generated_protocol::ResponsePayload::SnapshotImportedResponse(inner.clone())
841        }
842        ResponsePayload::SnapshotExported(inner) => {
843            generated_protocol::ResponsePayload::SnapshotExportedResponse(
844                generated_protocol::SnapshotExportedResponse {
845                    layer_id: inner.layer_id.clone(),
846                    entries: inner.entries.clone(),
847                },
848            )
849        }
850        ResponsePayload::OverlayCreated(inner) => {
851            generated_protocol::ResponsePayload::OverlayCreatedResponse(inner.clone())
852        }
853        ResponsePayload::GuestFilesystemResult(inner) => {
854            generated_protocol::ResponsePayload::GuestFilesystemResultResponse(
855                generated_protocol::GuestFilesystemResultResponse {
856                    operation: to_generated_guest_filesystem_operation(&inner.operation),
857                    path: inner.path.clone(),
858                    content: inner.content.clone(),
859                    encoding: inner
860                        .encoding
861                        .as_ref()
862                        .map(to_generated_root_filesystem_entry_encoding),
863                    entries: inner.entries.clone(),
864                    stat: inner.stat.as_ref().map(to_generated_guest_filesystem_stat),
865                    exists: inner.exists,
866                    target: inner.target.clone(),
867                },
868            )
869        }
870        ResponsePayload::RootFilesystemSnapshot(inner) => {
871            generated_protocol::ResponsePayload::RootFilesystemSnapshotResponse(
872                generated_protocol::RootFilesystemSnapshotResponse {
873                    entries: inner.entries.clone(),
874                },
875            )
876        }
877        ResponsePayload::MountsListed(inner) => {
878            generated_protocol::ResponsePayload::ListMountsResponse(inner.clone())
879        }
880        ResponsePayload::ProcessStarted(inner) => {
881            generated_protocol::ResponsePayload::ProcessStartedResponse(inner.clone())
882        }
883        ResponsePayload::StdinWritten(inner) => {
884            generated_protocol::ResponsePayload::StdinWrittenResponse(inner.clone())
885        }
886        ResponsePayload::StdinClosed(inner) => {
887            generated_protocol::ResponsePayload::StdinClosedResponse(inner.clone())
888        }
889        ResponsePayload::ProcessKilled(inner) => {
890            generated_protocol::ResponsePayload::ProcessKilledResponse(inner.clone())
891        }
892        ResponsePayload::ProcessSnapshot(inner) => {
893            generated_protocol::ResponsePayload::ProcessSnapshotResponse(
894                generated_protocol::ProcessSnapshotResponse {
895                    processes: inner
896                        .processes
897                        .iter()
898                        .map(to_generated_process_snapshot_entry)
899                        .collect(),
900                },
901            )
902        }
903        ResponsePayload::ResourceSnapshot(inner) => {
904            generated_protocol::ResponsePayload::ResourceSnapshotResponse(inner.clone())
905        }
906        ResponsePayload::ListenerSnapshot(inner) => {
907            generated_protocol::ResponsePayload::ListenerSnapshotResponse(inner.clone())
908        }
909        ResponsePayload::BoundUdpSnapshot(inner) => {
910            generated_protocol::ResponsePayload::BoundUdpSnapshotResponse(inner.clone())
911        }
912        ResponsePayload::VmFetchResult(inner) => {
913            generated_protocol::ResponsePayload::VmFetchResponse(inner.clone())
914        }
915        ResponsePayload::SignalState(inner) => {
916            generated_protocol::ResponsePayload::SignalStateResponse(inner.clone())
917        }
918        ResponsePayload::ZombieTimerCount(inner) => {
919            generated_protocol::ResponsePayload::ZombieTimerCountResponse(inner.clone())
920        }
921        ResponsePayload::FilesystemResult(inner) => {
922            generated_protocol::ResponsePayload::FilesystemResultResponse(
923                generated_protocol::FilesystemResultResponse {
924                    operation: to_generated_filesystem_operation(&inner.operation),
925                    status: inner.status.clone(),
926                    payload_size_bytes: inner.payload_size_bytes,
927                },
928            )
929        }
930        ResponsePayload::PermissionDecision(inner) => {
931            generated_protocol::ResponsePayload::PermissionDecisionResponse(
932                generated_protocol::PermissionDecisionResponse {
933                    capability: inner.capability.clone(),
934                    decision: to_generated_permission_mode(&inner.decision),
935                },
936            )
937        }
938        ResponsePayload::PersistenceState(inner) => {
939            generated_protocol::ResponsePayload::PersistenceStateResponse(inner.clone())
940        }
941        ResponsePayload::PersistenceFlushed(inner) => {
942            generated_protocol::ResponsePayload::PersistenceFlushedResponse(inner.clone())
943        }
944        ResponsePayload::Rejected(inner) => {
945            generated_protocol::ResponsePayload::RejectedResponse(inner.clone())
946        }
947        ResponsePayload::ExtResult(inner) => {
948            generated_protocol::ResponsePayload::ExtEnvelope(to_generated_ext_envelope(inner))
949        }
950        ResponsePayload::GuestKernelResult(inner) => {
951            generated_protocol::ResponsePayload::GuestKernelResultResponse(inner.clone())
952        }
953        ResponsePayload::PtyResized(inner) => {
954            generated_protocol::ResponsePayload::PtyResizedResponse(inner.clone())
955        }
956        ResponsePayload::PackageLinked(inner) => {
957            generated_protocol::ResponsePayload::PackageLinkedResponse(inner.clone())
958        }
959        ResponsePayload::ProvidedCommands(inner) => {
960            generated_protocol::ResponsePayload::ProvidedCommandsResponse(inner.clone())
961        }
962        ResponsePayload::ExecutionAccepted(inner) => {
963            generated_protocol::ResponsePayload::ExecutionAcceptedResponse(inner.clone())
964        }
965        ResponsePayload::ExecutionCompleted(inner) => {
966            generated_protocol::ResponsePayload::ExecutionCompletedResponse(inner.clone())
967        }
968        ResponsePayload::ExecutionEvaluation(inner) => {
969            generated_protocol::ResponsePayload::ExecutionEvaluationResponse(inner.clone())
970        }
971        ResponsePayload::TypeScriptCheck(inner) => {
972            generated_protocol::ResponsePayload::TypeScriptCheckResponse(inner.clone())
973        }
974        ResponsePayload::ExecutionDescriptor(inner) => {
975            generated_protocol::ResponsePayload::ExecutionDescriptorResponse(inner.clone())
976        }
977        ResponsePayload::ExecutionList(inner) => {
978            generated_protocol::ResponsePayload::ExecutionListResponse(inner.clone())
979        }
980        ResponsePayload::ExecutionDeleted(inner) => {
981            generated_protocol::ResponsePayload::ExecutionDeletedResponse(inner.clone())
982        }
983        ResponsePayload::ExecutionIo(inner) => {
984            generated_protocol::ResponsePayload::ExecutionIoResponse(inner.clone())
985        }
986        ResponsePayload::ExecutionOutputPage(inner) => {
987            generated_protocol::ResponsePayload::ExecutionOutputPageResponse(inner.clone())
988        }
989    })
990}
991
992fn from_generated_response_payload(
993    payload: generated_protocol::ResponsePayload,
994) -> Result<ResponsePayload, ProtocolCodecError> {
995    Ok(match payload {
996        generated_protocol::ResponsePayload::AuthenticatedResponse(inner) => {
997            ResponsePayload::Authenticated(inner)
998        }
999        generated_protocol::ResponsePayload::SessionOpenedResponse(inner) => {
1000            ResponsePayload::SessionOpened(inner)
1001        }
1002        generated_protocol::ResponsePayload::VmCreatedResponse(inner) => {
1003            ResponsePayload::VmCreated(inner)
1004        }
1005        generated_protocol::ResponsePayload::VmDisposedResponse(inner) => {
1006            ResponsePayload::VmDisposed(inner)
1007        }
1008        generated_protocol::ResponsePayload::RootFilesystemBootstrappedResponse(inner) => {
1009            ResponsePayload::RootFilesystemBootstrapped(inner)
1010        }
1011        generated_protocol::ResponsePayload::VmConfiguredResponse(inner) => {
1012            ResponsePayload::VmConfigured(inner)
1013        }
1014        generated_protocol::ResponsePayload::HostCallbacksRegisteredResponse(inner) => {
1015            ResponsePayload::HostCallbacksRegistered(inner)
1016        }
1017        generated_protocol::ResponsePayload::LayerCreatedResponse(inner) => {
1018            ResponsePayload::LayerCreated(inner)
1019        }
1020        generated_protocol::ResponsePayload::LayerSealedResponse(inner) => {
1021            ResponsePayload::LayerSealed(inner)
1022        }
1023        generated_protocol::ResponsePayload::SnapshotImportedResponse(inner) => {
1024            ResponsePayload::SnapshotImported(inner)
1025        }
1026        generated_protocol::ResponsePayload::SnapshotExportedResponse(inner) => {
1027            ResponsePayload::SnapshotExported(SnapshotExportedResponse {
1028                layer_id: inner.layer_id,
1029                entries: inner.entries,
1030            })
1031        }
1032        generated_protocol::ResponsePayload::OverlayCreatedResponse(inner) => {
1033            ResponsePayload::OverlayCreated(inner)
1034        }
1035        generated_protocol::ResponsePayload::GuestFilesystemResultResponse(inner) => {
1036            ResponsePayload::GuestFilesystemResult(GuestFilesystemResultResponse {
1037                operation: from_generated_guest_filesystem_operation(inner.operation),
1038                path: inner.path,
1039                content: inner.content,
1040                encoding: inner
1041                    .encoding
1042                    .map(from_generated_root_filesystem_entry_encoding),
1043                entries: inner.entries,
1044                stat: inner.stat.map(from_generated_guest_filesystem_stat),
1045                exists: inner.exists,
1046                target: inner.target,
1047            })
1048        }
1049        generated_protocol::ResponsePayload::RootFilesystemSnapshotResponse(inner) => {
1050            ResponsePayload::RootFilesystemSnapshot(RootFilesystemSnapshotResponse {
1051                entries: inner.entries,
1052            })
1053        }
1054        generated_protocol::ResponsePayload::ListMountsResponse(inner) => {
1055            ResponsePayload::MountsListed(inner)
1056        }
1057        generated_protocol::ResponsePayload::ProcessStartedResponse(inner) => {
1058            ResponsePayload::ProcessStarted(inner)
1059        }
1060        generated_protocol::ResponsePayload::StdinWrittenResponse(inner) => {
1061            ResponsePayload::StdinWritten(inner)
1062        }
1063        generated_protocol::ResponsePayload::StdinClosedResponse(inner) => {
1064            ResponsePayload::StdinClosed(inner)
1065        }
1066        generated_protocol::ResponsePayload::ProcessKilledResponse(inner) => {
1067            ResponsePayload::ProcessKilled(inner)
1068        }
1069        generated_protocol::ResponsePayload::ProcessSnapshotResponse(inner) => {
1070            ResponsePayload::ProcessSnapshot(ProcessSnapshotResponse {
1071                processes: inner
1072                    .processes
1073                    .into_iter()
1074                    .map(from_generated_process_snapshot_entry)
1075                    .collect(),
1076            })
1077        }
1078        generated_protocol::ResponsePayload::ResourceSnapshotResponse(inner) => {
1079            ResponsePayload::ResourceSnapshot(inner)
1080        }
1081        generated_protocol::ResponsePayload::ListenerSnapshotResponse(inner) => {
1082            ResponsePayload::ListenerSnapshot(inner)
1083        }
1084        generated_protocol::ResponsePayload::BoundUdpSnapshotResponse(inner) => {
1085            ResponsePayload::BoundUdpSnapshot(inner)
1086        }
1087        generated_protocol::ResponsePayload::VmFetchResponse(inner) => {
1088            ResponsePayload::VmFetchResult(inner)
1089        }
1090        generated_protocol::ResponsePayload::SignalStateResponse(inner) => {
1091            ResponsePayload::SignalState(inner)
1092        }
1093        generated_protocol::ResponsePayload::ZombieTimerCountResponse(inner) => {
1094            ResponsePayload::ZombieTimerCount(inner)
1095        }
1096        generated_protocol::ResponsePayload::FilesystemResultResponse(inner) => {
1097            ResponsePayload::FilesystemResult(FilesystemResultResponse {
1098                operation: from_generated_filesystem_operation(inner.operation),
1099                status: inner.status,
1100                payload_size_bytes: inner.payload_size_bytes,
1101            })
1102        }
1103        generated_protocol::ResponsePayload::PermissionDecisionResponse(inner) => {
1104            ResponsePayload::PermissionDecision(PermissionDecisionResponse {
1105                capability: inner.capability,
1106                decision: from_generated_permission_mode(inner.decision),
1107            })
1108        }
1109        generated_protocol::ResponsePayload::PersistenceStateResponse(inner) => {
1110            ResponsePayload::PersistenceState(inner)
1111        }
1112        generated_protocol::ResponsePayload::PersistenceFlushedResponse(inner) => {
1113            ResponsePayload::PersistenceFlushed(inner)
1114        }
1115        generated_protocol::ResponsePayload::RejectedResponse(inner) => {
1116            ResponsePayload::Rejected(inner)
1117        }
1118        generated_protocol::ResponsePayload::ExtEnvelope(inner) => {
1119            ResponsePayload::ExtResult(from_generated_ext_envelope(inner))
1120        }
1121        generated_protocol::ResponsePayload::GuestKernelResultResponse(inner) => {
1122            ResponsePayload::GuestKernelResult(inner)
1123        }
1124        generated_protocol::ResponsePayload::PtyResizedResponse(inner) => {
1125            ResponsePayload::PtyResized(inner)
1126        }
1127        generated_protocol::ResponsePayload::PackageLinkedResponse(inner) => {
1128            ResponsePayload::PackageLinked(inner)
1129        }
1130        generated_protocol::ResponsePayload::ProvidedCommandsResponse(inner) => {
1131            ResponsePayload::ProvidedCommands(inner)
1132        }
1133        generated_protocol::ResponsePayload::ExecutionAcceptedResponse(inner) => {
1134            ResponsePayload::ExecutionAccepted(inner)
1135        }
1136        generated_protocol::ResponsePayload::ExecutionCompletedResponse(inner) => {
1137            ResponsePayload::ExecutionCompleted(inner)
1138        }
1139        generated_protocol::ResponsePayload::ExecutionEvaluationResponse(inner) => {
1140            ResponsePayload::ExecutionEvaluation(inner)
1141        }
1142        generated_protocol::ResponsePayload::TypeScriptCheckResponse(inner) => {
1143            ResponsePayload::TypeScriptCheck(inner)
1144        }
1145        generated_protocol::ResponsePayload::ExecutionDescriptorResponse(inner) => {
1146            ResponsePayload::ExecutionDescriptor(inner)
1147        }
1148        generated_protocol::ResponsePayload::ExecutionListResponse(inner) => {
1149            ResponsePayload::ExecutionList(inner)
1150        }
1151        generated_protocol::ResponsePayload::ExecutionDeletedResponse(inner) => {
1152            ResponsePayload::ExecutionDeleted(inner)
1153        }
1154        generated_protocol::ResponsePayload::ExecutionIoResponse(inner) => {
1155            ResponsePayload::ExecutionIo(inner)
1156        }
1157        generated_protocol::ResponsePayload::ExecutionOutputPageResponse(inner) => {
1158            ResponsePayload::ExecutionOutputPage(inner)
1159        }
1160    })
1161}
1162
1163fn to_generated_event_payload(payload: &EventPayload) -> generated_protocol::EventPayload {
1164    match payload {
1165        EventPayload::VmLifecycle(inner) => generated_protocol::EventPayload::VmLifecycleEvent(
1166            generated_protocol::VmLifecycleEvent {
1167                state: to_generated_vm_lifecycle_state(&inner.state),
1168            },
1169        ),
1170        EventPayload::ProcessOutput(inner) => generated_protocol::EventPayload::ProcessOutputEvent(
1171            generated_protocol::ProcessOutputEvent {
1172                process_id: inner.process_id.clone(),
1173                channel: to_generated_stream_channel(&inner.channel),
1174                chunk: inner.chunk.clone(),
1175            },
1176        ),
1177        EventPayload::ProcessExited(inner) => {
1178            generated_protocol::EventPayload::ProcessExitedEvent(inner.clone())
1179        }
1180        EventPayload::Structured(inner) => {
1181            generated_protocol::EventPayload::StructuredEvent(inner.clone())
1182        }
1183        EventPayload::Ext(inner) => {
1184            generated_protocol::EventPayload::ExtEnvelope(to_generated_ext_envelope(inner))
1185        }
1186        EventPayload::ExecutionOutput(inner) => {
1187            generated_protocol::EventPayload::ExecutionOutputEvent(inner.clone())
1188        }
1189        EventPayload::ExecutionCompleted(inner) => {
1190            generated_protocol::EventPayload::ExecutionCompletedEvent(inner.clone())
1191        }
1192    }
1193}
1194
1195fn from_generated_event_payload(payload: generated_protocol::EventPayload) -> EventPayload {
1196    match payload {
1197        generated_protocol::EventPayload::VmLifecycleEvent(inner) => {
1198            EventPayload::VmLifecycle(VmLifecycleEvent {
1199                state: from_generated_vm_lifecycle_state(inner.state),
1200            })
1201        }
1202        generated_protocol::EventPayload::ProcessOutputEvent(inner) => {
1203            EventPayload::ProcessOutput(ProcessOutputEvent {
1204                process_id: inner.process_id,
1205                channel: from_generated_stream_channel(inner.channel),
1206                chunk: inner.chunk,
1207            })
1208        }
1209        generated_protocol::EventPayload::ProcessExitedEvent(inner) => {
1210            EventPayload::ProcessExited(inner)
1211        }
1212        generated_protocol::EventPayload::StructuredEvent(inner) => EventPayload::Structured(inner),
1213        generated_protocol::EventPayload::ExtEnvelope(inner) => {
1214            EventPayload::Ext(from_generated_ext_envelope(inner))
1215        }
1216        generated_protocol::EventPayload::ExecutionOutputEvent(inner) => {
1217            EventPayload::ExecutionOutput(inner)
1218        }
1219        generated_protocol::EventPayload::ExecutionCompletedEvent(inner) => {
1220            EventPayload::ExecutionCompleted(inner)
1221        }
1222    }
1223}
1224
1225fn to_generated_sidecar_request_payload(
1226    payload: &SidecarRequestPayload,
1227) -> Result<generated_protocol::SidecarRequestPayload, ProtocolCodecError> {
1228    Ok(match payload {
1229        SidecarRequestPayload::HostCallback(inner) => {
1230            generated_protocol::SidecarRequestPayload::HostCallbackRequest(inner.clone())
1231        }
1232        SidecarRequestPayload::JsBridgeCall(inner) => {
1233            generated_protocol::SidecarRequestPayload::JsBridgeCallRequest(inner.clone())
1234        }
1235        SidecarRequestPayload::Ext(inner) => {
1236            generated_protocol::SidecarRequestPayload::ExtEnvelope(to_generated_ext_envelope(inner))
1237        }
1238    })
1239}
1240
1241fn from_generated_sidecar_request_payload(
1242    payload: generated_protocol::SidecarRequestPayload,
1243) -> Result<SidecarRequestPayload, ProtocolCodecError> {
1244    Ok(match payload {
1245        generated_protocol::SidecarRequestPayload::HostCallbackRequest(inner) => {
1246            SidecarRequestPayload::HostCallback(inner)
1247        }
1248        generated_protocol::SidecarRequestPayload::JsBridgeCallRequest(inner) => {
1249            SidecarRequestPayload::JsBridgeCall(inner)
1250        }
1251        generated_protocol::SidecarRequestPayload::ExtEnvelope(inner) => {
1252            SidecarRequestPayload::Ext(from_generated_ext_envelope(inner))
1253        }
1254    })
1255}
1256
1257fn to_generated_sidecar_response_payload(
1258    payload: &SidecarResponsePayload,
1259) -> Result<generated_protocol::SidecarResponsePayload, ProtocolCodecError> {
1260    Ok(match payload {
1261        SidecarResponsePayload::HostCallbackResult(inner) => {
1262            generated_protocol::SidecarResponsePayload::HostCallbackResultResponse(inner.clone())
1263        }
1264        SidecarResponsePayload::JsBridgeResult(inner) => {
1265            generated_protocol::SidecarResponsePayload::JsBridgeResultResponse(inner.clone())
1266        }
1267        SidecarResponsePayload::ExtResult(inner) => {
1268            generated_protocol::SidecarResponsePayload::ExtEnvelope(to_generated_ext_envelope(
1269                inner,
1270            ))
1271        }
1272    })
1273}
1274
1275fn from_generated_sidecar_response_payload(
1276    payload: generated_protocol::SidecarResponsePayload,
1277) -> Result<SidecarResponsePayload, ProtocolCodecError> {
1278    Ok(match payload {
1279        generated_protocol::SidecarResponsePayload::HostCallbackResultResponse(inner) => {
1280            SidecarResponsePayload::HostCallbackResult(inner)
1281        }
1282        generated_protocol::SidecarResponsePayload::JsBridgeResultResponse(inner) => {
1283            SidecarResponsePayload::JsBridgeResult(inner)
1284        }
1285        generated_protocol::SidecarResponsePayload::ExtEnvelope(inner) => {
1286            SidecarResponsePayload::ExtResult(from_generated_ext_envelope(inner))
1287        }
1288    })
1289}
1290
1291macro_rules! impl_bare_newtype_union_enum {
1292    (
1293        $name:ident,
1294        $json_name:ident,
1295        $(#[$json_attr:meta])*
1296        {
1297            $($variant:ident($ty:ty) = $tag:literal),+ $(,)?
1298        }
1299    ) => {
1300        #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1301        $(#[$json_attr])*
1302        enum $json_name {
1303            $($variant($ty)),+
1304        }
1305
1306        impl From<&$name> for $json_name {
1307            fn from(value: &$name) -> Self {
1308                match value {
1309                    $($name::$variant(inner) => Self::$variant(inner.clone()),)+
1310                }
1311            }
1312        }
1313
1314        impl From<$json_name> for $name {
1315            fn from(value: $json_name) -> Self {
1316                match value {
1317                    $($json_name::$variant(inner) => Self::$variant(inner),)+
1318                }
1319            }
1320        }
1321
1322        impl Serialize for $name {
1323            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1324            where
1325                S: Serializer,
1326            {
1327                if serializer.is_human_readable() {
1328                    $json_name::from(self).serialize(serializer)
1329                } else {
1330                    match self {
1331                        $(Self::$variant(inner) => serialize_bare_newtype_tag(serializer, $tag, inner),)+
1332                    }
1333                }
1334            }
1335        }
1336
1337        impl<'de> Deserialize<'de> for $name {
1338            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1339            where
1340                D: Deserializer<'de>,
1341            {
1342                if deserializer.is_human_readable() {
1343                    Ok($json_name::deserialize(deserializer)?.into())
1344                } else {
1345                    struct UnionVisitor;
1346
1347                    impl<'de> Visitor<'de> for UnionVisitor {
1348                        type Value = $name;
1349
1350                        fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1351                            write!(formatter, "a {} BARE union", stringify!($name))
1352                        }
1353
1354                        fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
1355                        where
1356                            A: SeqAccess<'de>,
1357                        {
1358                            let serde_bare::Uint(tag) = seq
1359                                .next_element()?
1360                                .ok_or_else(|| de::Error::custom(concat!("missing ", stringify!($name), " tag")))?;
1361                            match tag {
1362                                $(
1363                                    $tag => {
1364                                        let payload = seq.next_element::<$ty>()?.ok_or_else(|| {
1365                                            de::Error::custom(format!(
1366                                                "missing {} payload for tag {}",
1367                                                stringify!($variant),
1368                                                $tag
1369                                            ))
1370                                        })?;
1371                                        Ok($name::$variant(payload))
1372                                    }
1373                                )+
1374                                _ => Err(de::Error::custom(format!(
1375                                    "unknown {} tag: {}",
1376                                    stringify!($name),
1377                                    tag
1378                                ))),
1379                            }
1380                        }
1381                    }
1382
1383                    deserializer.deserialize_tuple(2, UnionVisitor)
1384                }
1385            }
1386        }
1387    };
1388}
1389
1390pub type ProtocolSchema = crate::wire::ProtocolSchema;
1391
1392pub type OwnershipScope = crate::wire::OwnershipScope;
1393
1394#[derive(Debug, Clone, PartialEq, Eq)]
1395pub enum ProtocolFrame {
1396    Request(RequestFrame),
1397    Response(ResponseFrame),
1398    Event(EventFrame),
1399    SidecarRequest(SidecarRequestFrame),
1400    SidecarResponse(SidecarResponseFrame),
1401    Control(ControlFrame),
1402}
1403
1404pub type ControlFrame = crate::wire::ControlFrame;
1405pub type ControlPayload = crate::wire::ControlPayload;
1406pub type ShutdownControl = crate::wire::ShutdownControl;
1407
1408#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1409pub struct RequestFrame {
1410    pub schema: ProtocolSchema,
1411    pub request_id: RequestId,
1412    pub ownership: OwnershipScope,
1413    pub payload: RequestPayload,
1414}
1415
1416impl RequestFrame {
1417    pub fn new(request_id: RequestId, ownership: OwnershipScope, payload: RequestPayload) -> Self {
1418        Self {
1419            schema: ProtocolSchema::current(),
1420            request_id,
1421            ownership,
1422            payload,
1423        }
1424    }
1425}
1426
1427#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1428pub struct ResponseFrame {
1429    pub schema: ProtocolSchema,
1430    pub request_id: RequestId,
1431    pub ownership: OwnershipScope,
1432    pub payload: ResponsePayload,
1433}
1434
1435impl ResponseFrame {
1436    pub fn new(request_id: RequestId, ownership: OwnershipScope, payload: ResponsePayload) -> Self {
1437        Self {
1438            schema: ProtocolSchema::current(),
1439            request_id,
1440            ownership,
1441            payload,
1442        }
1443    }
1444}
1445
1446#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1447pub struct SidecarRequestFrame {
1448    pub schema: ProtocolSchema,
1449    pub request_id: RequestId,
1450    pub ownership: OwnershipScope,
1451    pub payload: SidecarRequestPayload,
1452}
1453
1454impl SidecarRequestFrame {
1455    pub fn new(
1456        request_id: RequestId,
1457        ownership: OwnershipScope,
1458        payload: SidecarRequestPayload,
1459    ) -> Self {
1460        Self {
1461            schema: ProtocolSchema::current(),
1462            request_id,
1463            ownership,
1464            payload,
1465        }
1466    }
1467}
1468
1469#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1470pub struct SidecarResponseFrame {
1471    pub schema: ProtocolSchema,
1472    pub request_id: RequestId,
1473    pub ownership: OwnershipScope,
1474    pub payload: SidecarResponsePayload,
1475}
1476
1477impl SidecarResponseFrame {
1478    pub fn new(
1479        request_id: RequestId,
1480        ownership: OwnershipScope,
1481        payload: SidecarResponsePayload,
1482    ) -> Self {
1483        Self {
1484            schema: ProtocolSchema::current(),
1485            request_id,
1486            ownership,
1487            payload,
1488        }
1489    }
1490}
1491
1492#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1493pub struct EventFrame {
1494    pub schema: ProtocolSchema,
1495    pub ownership: OwnershipScope,
1496    pub payload: EventPayload,
1497}
1498
1499impl EventFrame {
1500    pub fn new(ownership: OwnershipScope, payload: EventPayload) -> Self {
1501        Self {
1502            schema: ProtocolSchema::current(),
1503            ownership,
1504            payload,
1505        }
1506    }
1507}
1508
1509#[derive(Debug, Clone, PartialEq, Eq)]
1510pub enum RequestPayload {
1511    Authenticate(AuthenticateRequest),
1512    OpenSession(OpenSessionRequest),
1513    CreateVm(CreateVmRequest),
1514    DisposeVm(DisposeVmRequest),
1515    BootstrapRootFilesystem(BootstrapRootFilesystemRequest),
1516    ConfigureVm(ConfigureVmRequest),
1517    RegisterHostCallbacks(RegisterHostCallbacksRequest),
1518    CreateLayer(CreateLayerRequest),
1519    SealLayer(SealLayerRequest),
1520    ImportSnapshot(ImportSnapshotRequest),
1521    ExportSnapshot(ExportSnapshotRequest),
1522    CreateOverlay(CreateOverlayRequest),
1523    GuestFilesystemCall(GuestFilesystemCallRequest),
1524    SnapshotRootFilesystem(SnapshotRootFilesystemRequest),
1525    ListMounts(ListMountsRequest),
1526    Execute(ExecuteRequest),
1527    WriteStdin(WriteStdinRequest),
1528    CloseStdin(CloseStdinRequest),
1529    KillProcess(KillProcessRequest),
1530    GetProcessSnapshot(GetProcessSnapshotRequest),
1531    FindListener(FindListenerRequest),
1532    FindBoundUdp(FindBoundUdpRequest),
1533    VmFetch(VmFetchRequest),
1534    GetSignalState(GetSignalStateRequest),
1535    GetZombieTimerCount(GetZombieTimerCountRequest),
1536    HostFilesystemCall(HostFilesystemCallRequest),
1537    PersistenceLoad(PersistenceLoadRequest),
1538    PersistenceFlush(PersistenceFlushRequest),
1539    Ext(ExtEnvelope),
1540    GuestKernelCall(GuestKernelCallRequest),
1541    ResizePty(ResizePtyRequest),
1542    GetResourceSnapshot(GetResourceSnapshotRequest),
1543    LinkPackage(LinkPackageRequest),
1544    ProvidedCommands(ProvidedCommandsRequest),
1545    ShellExecution(ShellExecutionRequest),
1546    ArgvExecution(ArgvExecutionRequest),
1547    JavaScriptExecution(JavaScriptExecutionRequest),
1548    JavaScriptEvaluation(JavaScriptEvaluationRequest),
1549    JavaScriptFileExecution(JavaScriptFileExecutionRequest),
1550    TypeScriptExecution(TypeScriptExecutionRequest),
1551    TypeScriptEvaluation(TypeScriptEvaluationRequest),
1552    TypeScriptFileExecution(TypeScriptFileExecutionRequest),
1553    TypeScriptCheck(TypeScriptCheckRequest),
1554    TypeScriptProjectCheck(TypeScriptProjectCheckRequest),
1555    NpmProjectInstall(NpmProjectInstallRequest),
1556    NpmPackageInstall(NpmPackageInstallRequest),
1557    NpmScriptExecution(NpmScriptExecutionRequest),
1558    NpmPackageExecution(NpmPackageExecutionRequest),
1559    PythonExecution(PythonExecutionRequest),
1560    PythonEvaluation(PythonEvaluationRequest),
1561    PythonFileExecution(PythonFileExecutionRequest),
1562    PythonModuleExecution(PythonModuleExecutionRequest),
1563    PythonInstall(PythonInstallRequest),
1564    CreateContext(CreateContextRequest),
1565    GetExecution(GetExecutionRequest),
1566    ListExecutions(ListExecutionsRequest),
1567    WaitExecution(WaitExecutionRequest),
1568    CancelExecution(CancelExecutionRequest),
1569    SignalExecution(SignalExecutionRequest),
1570    ResetExecution(ResetExecutionRequest),
1571    DeleteExecution(DeleteExecutionRequest),
1572    WriteExecutionStdin(WriteExecutionStdinRequest),
1573    CloseExecutionStdin(CloseExecutionStdinRequest),
1574    ResizeExecutionPty(ResizeExecutionPtyRequest),
1575    ReadExecutionOutput(ReadExecutionOutputRequest),
1576}
1577
1578#[derive(Debug, Clone, PartialEq, Eq)]
1579pub enum ResponsePayload {
1580    Authenticated(AuthenticatedResponse),
1581    SessionOpened(SessionOpenedResponse),
1582    VmCreated(VmCreatedResponse),
1583    VmDisposed(VmDisposedResponse),
1584    RootFilesystemBootstrapped(RootFilesystemBootstrappedResponse),
1585    VmConfigured(VmConfiguredResponse),
1586    HostCallbacksRegistered(HostCallbacksRegisteredResponse),
1587    LayerCreated(LayerCreatedResponse),
1588    LayerSealed(LayerSealedResponse),
1589    SnapshotImported(SnapshotImportedResponse),
1590    SnapshotExported(SnapshotExportedResponse),
1591    OverlayCreated(OverlayCreatedResponse),
1592    GuestFilesystemResult(GuestFilesystemResultResponse),
1593    RootFilesystemSnapshot(RootFilesystemSnapshotResponse),
1594    MountsListed(ListMountsResponse),
1595    ProcessStarted(ProcessStartedResponse),
1596    StdinWritten(StdinWrittenResponse),
1597    StdinClosed(StdinClosedResponse),
1598    ProcessKilled(ProcessKilledResponse),
1599    ProcessSnapshot(ProcessSnapshotResponse),
1600    ListenerSnapshot(ListenerSnapshotResponse),
1601    BoundUdpSnapshot(BoundUdpSnapshotResponse),
1602    VmFetchResult(VmFetchResponse),
1603    SignalState(SignalStateResponse),
1604    ZombieTimerCount(ZombieTimerCountResponse),
1605    FilesystemResult(FilesystemResultResponse),
1606    PermissionDecision(PermissionDecisionResponse),
1607    PersistenceState(PersistenceStateResponse),
1608    PersistenceFlushed(PersistenceFlushedResponse),
1609    Rejected(RejectedResponse),
1610    ExtResult(ExtEnvelope),
1611    GuestKernelResult(GuestKernelResultResponse),
1612    PtyResized(PtyResizedResponse),
1613    ResourceSnapshot(ResourceSnapshotResponse),
1614    PackageLinked(PackageLinkedResponse),
1615    ProvidedCommands(ProvidedCommandsResponse),
1616    ExecutionAccepted(ExecutionAcceptedResponse),
1617    ExecutionCompleted(ExecutionCompletedResponse),
1618    ExecutionEvaluation(ExecutionEvaluationResponse),
1619    TypeScriptCheck(TypeScriptCheckResponse),
1620    ExecutionDescriptor(ExecutionDescriptorResponse),
1621    ExecutionList(ExecutionListResponse),
1622    ExecutionDeleted(ExecutionDeletedResponse),
1623    ExecutionIo(ExecutionIoResponse),
1624    ExecutionOutputPage(ExecutionOutputPageResponse),
1625}
1626
1627#[derive(Debug, Clone, PartialEq, Eq)]
1628pub enum SidecarRequestPayload {
1629    HostCallback(HostCallbackRequest),
1630    JsBridgeCall(JsBridgeCallRequest),
1631    Ext(ExtEnvelope),
1632}
1633
1634#[derive(Debug, Clone, PartialEq, Eq)]
1635pub enum SidecarResponsePayload {
1636    HostCallbackResult(HostCallbackResultResponse),
1637    JsBridgeResult(JsBridgeResultResponse),
1638    ExtResult(ExtEnvelope),
1639}
1640
1641#[derive(Debug, Clone, PartialEq, Eq)]
1642pub enum EventPayload {
1643    VmLifecycle(VmLifecycleEvent),
1644    ProcessOutput(ProcessOutputEvent),
1645    ProcessExited(ProcessExitedEvent),
1646    Structured(StructuredEvent),
1647    Ext(ExtEnvelope),
1648    ExecutionOutput(ExecutionOutputEvent),
1649    ExecutionCompleted(ExecutionCompletedEvent),
1650}
1651
1652pub type SidecarPlacement = crate::wire::SidecarPlacement;
1653
1654pub type SidecarPlacementShared = crate::wire::SidecarPlacementShared;
1655
1656pub type SidecarPlacementExplicit = crate::wire::SidecarPlacementExplicit;
1657
1658pub type GuestRuntimeKind = crate::wire::GuestRuntimeKind;
1659
1660pub type DisposeReason = crate::wire::DisposeReason;
1661
1662pub type FilesystemOperation = crate::wire::FilesystemOperation;
1663
1664pub type GuestFilesystemOperation = crate::wire::GuestFilesystemOperation;
1665
1666pub type PermissionMode = crate::wire::PermissionMode;
1667
1668pub type FsPermissionRule = crate::wire::FsPermissionRule;
1669
1670pub type PatternPermissionRule = crate::wire::PatternPermissionRule;
1671
1672pub type FsPermissionRuleSet = crate::wire::FsPermissionRuleSet;
1673
1674pub type PatternPermissionRuleSet = crate::wire::PatternPermissionRuleSet;
1675
1676pub type FsPermissionScope = crate::wire::FsPermissionScope;
1677
1678pub type PatternPermissionScope = crate::wire::PatternPermissionScope;
1679
1680pub type PermissionsPolicy = crate::wire::PermissionsPolicy;
1681
1682pub type RootFilesystemEntryKind = crate::wire::RootFilesystemEntryKind;
1683
1684pub type RootFilesystemMode = crate::wire::RootFilesystemMode;
1685
1686pub type RootFilesystemLowerDescriptor = crate::wire::RootFilesystemLowerDescriptor;
1687
1688pub type SnapshotRootFilesystemLower = crate::wire::SnapshotRootFilesystemLower;
1689
1690pub type StreamChannel = crate::wire::StreamChannel;
1691
1692pub type VmLifecycleState = crate::wire::VmLifecycleState;
1693
1694pub type AuthenticateRequest = crate::wire::AuthenticateRequest;
1695
1696pub type OpenSessionRequest = crate::wire::OpenSessionRequest;
1697
1698pub type CreateVmRequest = crate::wire::CreateVmRequest;
1699
1700#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1701pub struct DisposeVmRequest {
1702    pub reason: DisposeReason,
1703}
1704
1705pub type BootstrapRootFilesystemRequest = crate::wire::BootstrapRootFilesystemRequest;
1706
1707pub type RootFilesystemDescriptor = crate::wire::RootFilesystemDescriptor;
1708
1709pub type RootFilesystemEntryEncoding = crate::wire::RootFilesystemEntryEncoding;
1710
1711pub type RootFilesystemEntry = crate::wire::RootFilesystemEntry;
1712
1713pub type ConfigureVmRequest = crate::wire::ConfigureVmRequest;
1714
1715#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1716pub struct CreateLayerRequest {}
1717
1718pub type SealLayerRequest = crate::wire::SealLayerRequest;
1719
1720pub type ImportSnapshotRequest = crate::wire::ImportSnapshotRequest;
1721
1722pub type ExportSnapshotRequest = crate::wire::ExportSnapshotRequest;
1723
1724pub type CreateOverlayRequest = crate::wire::CreateOverlayRequest;
1725
1726pub type GuestFilesystemCallRequest = crate::wire::GuestFilesystemCallRequest;
1727
1728pub type GuestKernelCallRequest = crate::wire::GuestKernelCallRequest;
1729pub type ResizePtyRequest = crate::wire::ResizePtyRequest;
1730pub type PackageDescriptor = crate::wire::PackageDescriptor;
1731pub type AgentosProjectedAgent = crate::wire::AgentosProjectedAgent;
1732pub type PackageCommands = crate::wire::PackageCommands;
1733pub type ProjectedCommand = crate::wire::ProjectedCommand;
1734pub type LinkPackageRequest = crate::wire::LinkPackageRequest;
1735
1736#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1737pub struct ProvidedCommandsRequest {}
1738
1739pub type GuestKernelResultResponse = crate::wire::GuestKernelResultResponse;
1740pub type PtyResizedResponse = crate::wire::PtyResizedResponse;
1741pub type PackageLinkedResponse = crate::wire::PackageLinkedResponse;
1742pub type ProvidedCommandsResponse = crate::wire::ProvidedCommandsResponse;
1743
1744pub type SnapshotRootFilesystemRequest = crate::wire::SnapshotRootFilesystemRequest;
1745
1746#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1747pub struct ListMountsRequest {}
1748
1749pub type MountDescriptor = crate::wire::MountDescriptor;
1750
1751pub type MountInfo = crate::wire::MountInfo;
1752
1753pub type MountPluginDescriptor = crate::wire::MountPluginDescriptor;
1754
1755pub type SoftwareDescriptor = crate::wire::SoftwareDescriptor;
1756
1757pub type ProjectedModuleDescriptor = crate::wire::ProjectedModuleDescriptor;
1758
1759pub type WasmPermissionTier = crate::wire::WasmPermissionTier;
1760
1761pub type ExecuteRequest = crate::wire::ExecuteRequest;
1762
1763pub type ExecutionState = crate::wire::ExecutionState;
1764pub type ExecutionOutcome = crate::wire::ExecutionOutcome;
1765pub type RetainedExecutionLanguage = crate::wire::RetainedExecutionLanguage;
1766pub type ExecutionStreamChannel = crate::wire::ExecutionStreamChannel;
1767pub type JavaScriptModuleFormat = crate::wire::JavaScriptModuleFormat;
1768pub type ExecutionIdentityOptions = crate::wire::ExecutionIdentityOptions;
1769pub type ExecutionPtyOptions = crate::wire::ExecutionPtyOptions;
1770pub type ExecutionOutputCapture = crate::wire::ExecutionOutputCapture;
1771pub type ExecutionOutputOptions = crate::wire::ExecutionOutputOptions;
1772pub type ProcessExecutionOptions = crate::wire::ProcessExecutionOptions;
1773pub type ShellExecutionRequest = crate::wire::ShellExecutionRequest;
1774pub type ArgvExecutionRequest = crate::wire::ArgvExecutionRequest;
1775pub type JavaScriptExecutionRequest = crate::wire::JavaScriptExecutionRequest;
1776pub type JavaScriptEvaluationRequest = crate::wire::JavaScriptEvaluationRequest;
1777pub type JavaScriptFileExecutionRequest = crate::wire::JavaScriptFileExecutionRequest;
1778pub type TypeScriptExecutionRequest = crate::wire::TypeScriptExecutionRequest;
1779pub type TypeScriptEvaluationRequest = crate::wire::TypeScriptEvaluationRequest;
1780pub type TypeScriptFileExecutionRequest = crate::wire::TypeScriptFileExecutionRequest;
1781pub type TypeScriptCheckRequest = crate::wire::TypeScriptCheckRequest;
1782pub type TypeScriptProjectCheckRequest = crate::wire::TypeScriptProjectCheckRequest;
1783pub type NpmProjectInstallRequest = crate::wire::NpmProjectInstallRequest;
1784pub type NpmPackageInstallRequest = crate::wire::NpmPackageInstallRequest;
1785pub type NpmScriptExecutionRequest = crate::wire::NpmScriptExecutionRequest;
1786pub type NpmPackageExecutionRequest = crate::wire::NpmPackageExecutionRequest;
1787pub type PythonExecutionRequest = crate::wire::PythonExecutionRequest;
1788pub type PythonEvaluationRequest = crate::wire::PythonEvaluationRequest;
1789pub type PythonFileExecutionRequest = crate::wire::PythonFileExecutionRequest;
1790pub type PythonModuleExecutionRequest = crate::wire::PythonModuleExecutionRequest;
1791pub type PythonInstallRequest = crate::wire::PythonInstallRequest;
1792pub type CreateContextRequest = crate::wire::CreateContextRequest;
1793pub type GetExecutionRequest = crate::wire::GetExecutionRequest;
1794#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1795pub struct ListExecutionsRequest {}
1796pub type WaitExecutionRequest = crate::wire::WaitExecutionRequest;
1797pub type CancelExecutionRequest = crate::wire::CancelExecutionRequest;
1798pub type SignalExecutionRequest = crate::wire::SignalExecutionRequest;
1799pub type ResetExecutionRequest = crate::wire::ResetExecutionRequest;
1800pub type DeleteExecutionRequest = crate::wire::DeleteExecutionRequest;
1801pub type WriteExecutionStdinRequest = crate::wire::WriteExecutionStdinRequest;
1802pub type CloseExecutionStdinRequest = crate::wire::CloseExecutionStdinRequest;
1803pub type ResizeExecutionPtyRequest = crate::wire::ResizeExecutionPtyRequest;
1804pub type ReadExecutionOutputRequest = crate::wire::ReadExecutionOutputRequest;
1805
1806pub type WriteStdinRequest = crate::wire::WriteStdinRequest;
1807
1808pub type CloseStdinRequest = crate::wire::CloseStdinRequest;
1809
1810pub type KillProcessRequest = crate::wire::KillProcessRequest;
1811
1812#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1813pub struct GetProcessSnapshotRequest {}
1814
1815#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1816pub struct GetResourceSnapshotRequest {}
1817
1818pub type FindListenerRequest = crate::wire::FindListenerRequest;
1819
1820pub type FindBoundUdpRequest = crate::wire::FindBoundUdpRequest;
1821
1822pub type VmFetchRequest = crate::wire::VmFetchRequest;
1823
1824pub type GetSignalStateRequest = crate::wire::GetSignalStateRequest;
1825
1826#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
1827pub struct GetZombieTimerCountRequest {}
1828
1829pub type HostFilesystemCallRequest = crate::wire::HostFilesystemCallRequest;
1830
1831pub type PersistenceLoadRequest = crate::wire::PersistenceLoadRequest;
1832
1833pub type PersistenceFlushRequest = crate::wire::PersistenceFlushRequest;
1834
1835pub type RegisterHostCallbacksRequest = crate::wire::RegisterHostCallbacksRequest;
1836
1837pub type RegisteredHostCallbackDefinition = crate::wire::RegisteredHostCallbackDefinition;
1838
1839pub type RegisteredHostCallbackExample = crate::wire::RegisteredHostCallbackExample;
1840
1841pub type HostCallbackRequest = crate::wire::HostCallbackRequest;
1842
1843pub type JsBridgeCallRequest = crate::wire::JsBridgeCallRequest;
1844
1845pub type AuthenticatedResponse = crate::wire::AuthenticatedResponse;
1846
1847pub type SessionOpenedResponse = crate::wire::SessionOpenedResponse;
1848
1849pub type VmCreatedResponse = crate::wire::VmCreatedResponse;
1850
1851pub type VmDisposedResponse = crate::wire::VmDisposedResponse;
1852
1853pub type RootFilesystemBootstrappedResponse = crate::wire::RootFilesystemBootstrappedResponse;
1854
1855pub type VmConfiguredResponse = crate::wire::VmConfiguredResponse;
1856
1857pub type HostCallbacksRegisteredResponse = crate::wire::HostCallbacksRegisteredResponse;
1858
1859pub type GuestFilesystemStat = crate::wire::GuestFilesystemStat;
1860
1861pub type GuestDirEntry = crate::wire::GuestDirEntry;
1862
1863pub type GuestFilesystemResultResponse = crate::wire::GuestFilesystemResultResponse;
1864
1865pub type RootFilesystemSnapshotResponse = crate::wire::RootFilesystemSnapshotResponse;
1866
1867pub type ListMountsResponse = crate::wire::ListMountsResponse;
1868
1869pub type LayerCreatedResponse = crate::wire::LayerCreatedResponse;
1870
1871pub type LayerSealedResponse = crate::wire::LayerSealedResponse;
1872
1873pub type SnapshotImportedResponse = crate::wire::SnapshotImportedResponse;
1874
1875pub type SnapshotExportedResponse = crate::wire::SnapshotExportedResponse;
1876
1877pub type OverlayCreatedResponse = crate::wire::OverlayCreatedResponse;
1878
1879pub type ProcessStartedResponse = crate::wire::ProcessStartedResponse;
1880
1881pub type StdinWrittenResponse = crate::wire::StdinWrittenResponse;
1882
1883pub type StdinClosedResponse = crate::wire::StdinClosedResponse;
1884
1885pub type ProcessKilledResponse = crate::wire::ProcessKilledResponse;
1886
1887pub type ProcessSnapshotStatus = crate::wire::ProcessSnapshotStatus;
1888
1889pub type ProcessSnapshotEntry = crate::wire::ProcessSnapshotEntry;
1890
1891pub type ProcessSnapshotResponse = crate::wire::ProcessSnapshotResponse;
1892
1893pub type QueueSnapshotEntry = crate::wire::QueueSnapshotEntry;
1894
1895pub type ResourceSnapshotResponse = crate::wire::ResourceSnapshotResponse;
1896
1897pub type SocketStateEntry = crate::wire::SocketStateEntry;
1898
1899pub type ListenerSnapshotResponse = crate::wire::ListenerSnapshotResponse;
1900
1901pub type BoundUdpSnapshotResponse = crate::wire::BoundUdpSnapshotResponse;
1902
1903pub type VmFetchResponse = crate::wire::VmFetchResponse;
1904pub type ExecutionDescriptor = crate::wire::ExecutionDescriptor;
1905pub type ExecutionErrorData = crate::wire::ExecutionErrorData;
1906pub type ExecutionAcceptedResponse = crate::wire::ExecutionAcceptedResponse;
1907pub type ExecutionCompletedResponse = crate::wire::ExecutionCompletedResponse;
1908pub type ExecutionEvaluationResponse = crate::wire::ExecutionEvaluationResponse;
1909pub type TypeScriptDiagnostic = crate::wire::TypeScriptDiagnostic;
1910pub type TypeScriptCheckResponse = crate::wire::TypeScriptCheckResponse;
1911pub type ExecutionDescriptorResponse = crate::wire::ExecutionDescriptorResponse;
1912pub type ExecutionListResponse = crate::wire::ExecutionListResponse;
1913pub type ExecutionDeletedResponse = crate::wire::ExecutionDeletedResponse;
1914pub type ExecutionIoResponse = crate::wire::ExecutionIoResponse;
1915pub type ExecutionOutputEvent = crate::wire::ExecutionOutputEvent;
1916pub type ExecutionOutputPageResponse = crate::wire::ExecutionOutputPageResponse;
1917pub type ExecutionCompletedEvent = crate::wire::ExecutionCompletedEvent;
1918
1919pub type SignalDispositionAction = crate::wire::SignalDispositionAction;
1920
1921pub type SignalHandlerRegistration = crate::wire::SignalHandlerRegistration;
1922
1923pub type SignalStateResponse = crate::wire::SignalStateResponse;
1924
1925pub type ZombieTimerCountResponse = crate::wire::ZombieTimerCountResponse;
1926
1927pub type FilesystemResultResponse = crate::wire::FilesystemResultResponse;
1928
1929pub type PermissionDecisionResponse = crate::wire::PermissionDecisionResponse;
1930
1931pub type PersistenceStateResponse = crate::wire::PersistenceStateResponse;
1932
1933pub type PersistenceFlushedResponse = crate::wire::PersistenceFlushedResponse;
1934
1935pub type HostCallbackResultResponse = crate::wire::HostCallbackResultResponse;
1936
1937pub type JsBridgeResultResponse = crate::wire::JsBridgeResultResponse;
1938
1939pub type RejectedResponse = crate::wire::RejectedResponse;
1940
1941pub type VmLifecycleEvent = crate::wire::VmLifecycleEvent;
1942
1943pub type ProcessOutputEvent = crate::wire::ProcessOutputEvent;
1944
1945pub type ProcessExitedEvent = crate::wire::ProcessExitedEvent;
1946
1947pub type StructuredEvent = crate::wire::StructuredEvent;
1948
1949impl_bare_newtype_union_enum!(
1950    ProtocolFrame,
1951    JsonProtocolFrame,
1952    #[serde(tag = "frame_type", rename_all = "snake_case")]
1953    {
1954        Request(RequestFrame) = 0,
1955        Response(ResponseFrame) = 1,
1956        Event(EventFrame) = 2,
1957        SidecarRequest(SidecarRequestFrame) = 3,
1958        SidecarResponse(SidecarResponseFrame) = 4,
1959        Control(ControlFrame) = 5,
1960    }
1961);
1962
1963impl_bare_newtype_union_enum!(
1964    RequestPayload,
1965    JsonRequestPayload,
1966    #[serde(tag = "type", rename_all = "snake_case")]
1967    {
1968        Authenticate(AuthenticateRequest) = 0,
1969        OpenSession(OpenSessionRequest) = 1,
1970        CreateVm(CreateVmRequest) = 2,
1971        DisposeVm(DisposeVmRequest) = 3,
1972        BootstrapRootFilesystem(BootstrapRootFilesystemRequest) = 4,
1973        ConfigureVm(ConfigureVmRequest) = 5,
1974        RegisterHostCallbacks(RegisterHostCallbacksRequest) = 6,
1975        CreateLayer(CreateLayerRequest) = 7,
1976        SealLayer(SealLayerRequest) = 8,
1977        ImportSnapshot(ImportSnapshotRequest) = 9,
1978        ExportSnapshot(ExportSnapshotRequest) = 10,
1979        CreateOverlay(CreateOverlayRequest) = 11,
1980        GuestFilesystemCall(GuestFilesystemCallRequest) = 12,
1981        SnapshotRootFilesystem(SnapshotRootFilesystemRequest) = 13,
1982        Execute(ExecuteRequest) = 14,
1983        WriteStdin(WriteStdinRequest) = 15,
1984        CloseStdin(CloseStdinRequest) = 16,
1985        KillProcess(KillProcessRequest) = 17,
1986        GetProcessSnapshot(GetProcessSnapshotRequest) = 18,
1987        FindListener(FindListenerRequest) = 19,
1988        FindBoundUdp(FindBoundUdpRequest) = 20,
1989        GetSignalState(GetSignalStateRequest) = 21,
1990        GetZombieTimerCount(GetZombieTimerCountRequest) = 22,
1991        HostFilesystemCall(HostFilesystemCallRequest) = 23,
1992        PersistenceLoad(PersistenceLoadRequest) = 24,
1993        PersistenceFlush(PersistenceFlushRequest) = 25,
1994        VmFetch(VmFetchRequest) = 26,
1995        Ext(ExtEnvelope) = 27,
1996        GuestKernelCall(GuestKernelCallRequest) = 28,
1997        ResizePty(ResizePtyRequest) = 29,
1998        GetResourceSnapshot(GetResourceSnapshotRequest) = 30,
1999        LinkPackage(LinkPackageRequest) = 31,
2000        ProvidedCommands(ProvidedCommandsRequest) = 32,
2001        ListMounts(ListMountsRequest) = 33,
2002        ShellExecution(ShellExecutionRequest) = 34,
2003        ArgvExecution(ArgvExecutionRequest) = 35,
2004        JavaScriptExecution(JavaScriptExecutionRequest) = 36,
2005        JavaScriptEvaluation(JavaScriptEvaluationRequest) = 37,
2006        JavaScriptFileExecution(JavaScriptFileExecutionRequest) = 38,
2007        TypeScriptExecution(TypeScriptExecutionRequest) = 39,
2008        TypeScriptEvaluation(TypeScriptEvaluationRequest) = 40,
2009        TypeScriptFileExecution(TypeScriptFileExecutionRequest) = 41,
2010        TypeScriptCheck(TypeScriptCheckRequest) = 42,
2011        TypeScriptProjectCheck(TypeScriptProjectCheckRequest) = 43,
2012        NpmProjectInstall(NpmProjectInstallRequest) = 44,
2013        NpmPackageInstall(NpmPackageInstallRequest) = 45,
2014        NpmScriptExecution(NpmScriptExecutionRequest) = 46,
2015        NpmPackageExecution(NpmPackageExecutionRequest) = 47,
2016        PythonExecution(PythonExecutionRequest) = 48,
2017        PythonEvaluation(PythonEvaluationRequest) = 49,
2018        PythonFileExecution(PythonFileExecutionRequest) = 50,
2019        PythonModuleExecution(PythonModuleExecutionRequest) = 51,
2020        PythonInstall(PythonInstallRequest) = 52,
2021        CreateContext(CreateContextRequest) = 53,
2022        GetExecution(GetExecutionRequest) = 54,
2023        ListExecutions(ListExecutionsRequest) = 55,
2024        WaitExecution(WaitExecutionRequest) = 56,
2025        CancelExecution(CancelExecutionRequest) = 57,
2026        SignalExecution(SignalExecutionRequest) = 58,
2027        ResetExecution(ResetExecutionRequest) = 59,
2028        DeleteExecution(DeleteExecutionRequest) = 60,
2029        WriteExecutionStdin(WriteExecutionStdinRequest) = 61,
2030        CloseExecutionStdin(CloseExecutionStdinRequest) = 62,
2031        ResizeExecutionPty(ResizeExecutionPtyRequest) = 63,
2032        ReadExecutionOutput(ReadExecutionOutputRequest) = 64,
2033    }
2034);
2035
2036impl_bare_newtype_union_enum!(
2037    ResponsePayload,
2038    JsonResponsePayload,
2039    #[serde(tag = "type", rename_all = "snake_case")]
2040    {
2041        Authenticated(AuthenticatedResponse) = 0,
2042        SessionOpened(SessionOpenedResponse) = 1,
2043        VmCreated(VmCreatedResponse) = 2,
2044        VmDisposed(VmDisposedResponse) = 3,
2045        RootFilesystemBootstrapped(RootFilesystemBootstrappedResponse) = 4,
2046        VmConfigured(VmConfiguredResponse) = 5,
2047        HostCallbacksRegistered(HostCallbacksRegisteredResponse) = 6,
2048        LayerCreated(LayerCreatedResponse) = 7,
2049        LayerSealed(LayerSealedResponse) = 8,
2050        SnapshotImported(SnapshotImportedResponse) = 9,
2051        SnapshotExported(SnapshotExportedResponse) = 10,
2052        OverlayCreated(OverlayCreatedResponse) = 11,
2053        GuestFilesystemResult(GuestFilesystemResultResponse) = 12,
2054        RootFilesystemSnapshot(RootFilesystemSnapshotResponse) = 13,
2055        ProcessStarted(ProcessStartedResponse) = 14,
2056        StdinWritten(StdinWrittenResponse) = 15,
2057        StdinClosed(StdinClosedResponse) = 16,
2058        ProcessKilled(ProcessKilledResponse) = 17,
2059        ProcessSnapshot(ProcessSnapshotResponse) = 18,
2060        ListenerSnapshot(ListenerSnapshotResponse) = 19,
2061        BoundUdpSnapshot(BoundUdpSnapshotResponse) = 20,
2062        SignalState(SignalStateResponse) = 21,
2063        ZombieTimerCount(ZombieTimerCountResponse) = 22,
2064        FilesystemResult(FilesystemResultResponse) = 23,
2065        PermissionDecision(PermissionDecisionResponse) = 24,
2066        PersistenceState(PersistenceStateResponse) = 25,
2067        PersistenceFlushed(PersistenceFlushedResponse) = 26,
2068        Rejected(RejectedResponse) = 27,
2069        VmFetchResult(VmFetchResponse) = 28,
2070        ExtResult(ExtEnvelope) = 29,
2071        GuestKernelResult(GuestKernelResultResponse) = 30,
2072        PtyResized(PtyResizedResponse) = 31,
2073        ResourceSnapshot(ResourceSnapshotResponse) = 32,
2074        PackageLinked(PackageLinkedResponse) = 33,
2075        ProvidedCommands(ProvidedCommandsResponse) = 34,
2076        MountsListed(ListMountsResponse) = 35,
2077        ExecutionAccepted(ExecutionAcceptedResponse) = 36,
2078        ExecutionCompleted(ExecutionCompletedResponse) = 37,
2079        ExecutionEvaluation(ExecutionEvaluationResponse) = 38,
2080        TypeScriptCheck(TypeScriptCheckResponse) = 39,
2081        ExecutionDescriptor(ExecutionDescriptorResponse) = 40,
2082        ExecutionList(ExecutionListResponse) = 41,
2083        ExecutionDeleted(ExecutionDeletedResponse) = 42,
2084        ExecutionIo(ExecutionIoResponse) = 43,
2085        ExecutionOutputPage(ExecutionOutputPageResponse) = 44,
2086    }
2087);
2088
2089impl_bare_newtype_union_enum!(
2090    SidecarRequestPayload,
2091    JsonSidecarRequestPayload,
2092    #[serde(tag = "type", rename_all = "snake_case")]
2093    {
2094        HostCallback(HostCallbackRequest) = 0,
2095        JsBridgeCall(JsBridgeCallRequest) = 1,
2096        Ext(ExtEnvelope) = 2,
2097    }
2098);
2099
2100impl_bare_newtype_union_enum!(
2101    SidecarResponsePayload,
2102    JsonSidecarResponsePayload,
2103    #[allow(clippy::enum_variant_names)]
2104    #[serde(tag = "type", rename_all = "snake_case")]
2105    {
2106        HostCallbackResult(HostCallbackResultResponse) = 0,
2107        JsBridgeResult(JsBridgeResultResponse) = 1,
2108        ExtResult(ExtEnvelope) = 2,
2109    }
2110);
2111
2112impl_bare_newtype_union_enum!(
2113    EventPayload,
2114    JsonEventPayload,
2115    #[serde(tag = "type", rename_all = "snake_case")]
2116    {
2117        VmLifecycle(VmLifecycleEvent) = 0,
2118        ProcessOutput(ProcessOutputEvent) = 1,
2119        ProcessExited(ProcessExitedEvent) = 2,
2120        Structured(StructuredEvent) = 3,
2121        Ext(ExtEnvelope) = 4,
2122        ExecutionOutput(ExecutionOutputEvent) = 5,
2123        ExecutionCompleted(ExecutionCompletedEvent) = 6,
2124    }
2125);
2126
2127fn serialize_payload(
2128    frame: &ProtocolFrame,
2129    payload_codec: NativePayloadCodec,
2130) -> Result<Vec<u8>, ProtocolCodecError> {
2131    match payload_codec {
2132        NativePayloadCodec::Json => serde_json::to_vec(frame)
2133            .map_err(|error| ProtocolCodecError::SerializeFailure(error.to_string())),
2134        NativePayloadCodec::Bare => serde_bare::to_vec(&to_generated_protocol_frame(frame)?)
2135            .map_err(|error| ProtocolCodecError::SerializeFailure(error.to_string())),
2136    }
2137}
2138
2139fn deserialize_payload(
2140    payload: &[u8],
2141    payload_codec: NativePayloadCodec,
2142) -> Result<ProtocolFrame, ProtocolCodecError> {
2143    match payload_codec {
2144        NativePayloadCodec::Json => serde_json::from_slice(payload)
2145            .map_err(|error| ProtocolCodecError::DeserializeFailure(error.to_string())),
2146        NativePayloadCodec::Bare => {
2147            let frame: generated_protocol::ProtocolFrame = serde_bare::from_slice(payload)
2148                .map_err(|error| ProtocolCodecError::DeserializeFailure(error.to_string()))?;
2149            from_generated_protocol_frame(frame)
2150        }
2151    }
2152}
2153
2154#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2155pub enum NativePayloadCodec {
2156    Json,
2157    Bare,
2158}
2159
2160impl NativePayloadCodec {
2161    pub fn sniff(payload: &[u8]) -> Self {
2162        match payload.first() {
2163            Some(b'{') => Self::Json,
2164            _ => Self::Bare,
2165        }
2166    }
2167
2168    pub fn alternate(self) -> Self {
2169        match self {
2170            Self::Json => Self::Bare,
2171            Self::Bare => Self::Json,
2172        }
2173    }
2174}
2175
2176#[derive(Debug, Clone)]
2177pub struct NativeFrameCodec {
2178    max_frame_bytes: usize,
2179    payload_codec: NativePayloadCodec,
2180}
2181
2182impl NativeFrameCodec {
2183    pub fn new(max_frame_bytes: usize) -> Self {
2184        Self::with_payload_codec(max_frame_bytes, NativePayloadCodec::Json)
2185    }
2186
2187    pub fn with_payload_codec(max_frame_bytes: usize, payload_codec: NativePayloadCodec) -> Self {
2188        Self {
2189            max_frame_bytes,
2190            payload_codec,
2191        }
2192    }
2193
2194    pub fn max_frame_bytes(&self) -> usize {
2195        self.max_frame_bytes
2196    }
2197
2198    pub fn payload_codec(&self) -> NativePayloadCodec {
2199        self.payload_codec
2200    }
2201
2202    pub fn encode(&self, frame: &ProtocolFrame) -> Result<Vec<u8>, ProtocolCodecError> {
2203        self.encode_with_codec(frame, self.payload_codec)
2204    }
2205
2206    pub fn encode_with_codec(
2207        &self,
2208        frame: &ProtocolFrame,
2209        payload_codec: NativePayloadCodec,
2210    ) -> Result<Vec<u8>, ProtocolCodecError> {
2211        validate_frame(frame)?;
2212
2213        let payload = serialize_payload(frame, payload_codec)?;
2214        if payload.len() > self.max_frame_bytes {
2215            return Err(ProtocolCodecError::FrameTooLarge {
2216                size: payload.len(),
2217                max: self.max_frame_bytes,
2218            });
2219        }
2220
2221        let length =
2222            u32::try_from(payload.len()).map_err(|_| ProtocolCodecError::FrameTooLarge {
2223                size: payload.len(),
2224                max: u32::MAX as usize,
2225            })?;
2226
2227        let mut encoded = Vec::with_capacity(4 + payload.len());
2228        encoded.extend_from_slice(&length.to_be_bytes());
2229        encoded.extend_from_slice(&payload);
2230        Ok(encoded)
2231    }
2232
2233    pub fn decode(&self, bytes: &[u8]) -> Result<ProtocolFrame, ProtocolCodecError> {
2234        self.decode_detected(bytes).map(|(frame, _)| frame)
2235    }
2236
2237    pub fn decode_with_codec(
2238        &self,
2239        bytes: &[u8],
2240        payload_codec: NativePayloadCodec,
2241    ) -> Result<ProtocolFrame, ProtocolCodecError> {
2242        let payload = self.checked_payload(bytes)?;
2243        let frame = deserialize_payload(payload, payload_codec)?;
2244        validate_frame(&frame)?;
2245        Ok(frame)
2246    }
2247
2248    pub fn decode_detected(
2249        &self,
2250        bytes: &[u8],
2251    ) -> Result<(ProtocolFrame, NativePayloadCodec), ProtocolCodecError> {
2252        let payload = self.checked_payload(bytes)?;
2253        let primary = NativePayloadCodec::sniff(payload);
2254
2255        match deserialize_payload(payload, primary) {
2256            Ok(frame) => {
2257                validate_frame(&frame)?;
2258                Ok((frame, primary))
2259            }
2260            Err(primary_error) => {
2261                let alternate = primary.alternate();
2262                let frame = deserialize_payload(payload, alternate).map_err(|_| primary_error)?;
2263                validate_frame(&frame)?;
2264                Ok((frame, alternate))
2265            }
2266        }
2267    }
2268
2269    fn checked_payload<'a>(&self, bytes: &'a [u8]) -> Result<&'a [u8], ProtocolCodecError> {
2270        if bytes.len() < 4 {
2271            return Err(ProtocolCodecError::TruncatedFrame {
2272                actual: bytes.len(),
2273            });
2274        }
2275
2276        let declared =
2277            u32::from_be_bytes(bytes[..4].try_into().expect("length prefix is four bytes"))
2278                as usize;
2279        if declared > self.max_frame_bytes {
2280            return Err(ProtocolCodecError::FrameTooLarge {
2281                size: declared,
2282                max: self.max_frame_bytes,
2283            });
2284        }
2285
2286        let actual = bytes.len() - 4;
2287        if declared != actual {
2288            return Err(ProtocolCodecError::LengthPrefixMismatch { declared, actual });
2289        }
2290        Ok(&bytes[4..])
2291    }
2292}
2293
2294impl Default for NativeFrameCodec {
2295    fn default() -> Self {
2296        Self::new(DEFAULT_MAX_FRAME_BYTES)
2297    }
2298}
2299
2300#[derive(Debug)]
2301pub struct ResponseTracker {
2302    pending: HashMap<RequestId, PendingRequest>,
2303    completed: HashSet<RequestId>,
2304    completed_order: VecDeque<RequestId>,
2305    completed_cap: usize,
2306}
2307
2308#[derive(Debug)]
2309pub struct SidecarResponseTracker {
2310    pending: HashMap<RequestId, PendingSidecarRequest>,
2311    completed: HashSet<RequestId>,
2312    completed_order: VecDeque<RequestId>,
2313    completed_cap: usize,
2314}
2315
2316impl ResponseTracker {
2317    pub fn with_completed_cap(completed_cap: usize) -> Self {
2318        Self {
2319            pending: HashMap::new(),
2320            completed: HashSet::new(),
2321            completed_order: VecDeque::new(),
2322            completed_cap: completed_cap.max(1),
2323        }
2324    }
2325
2326    pub fn completed_count(&self) -> usize {
2327        self.completed.len()
2328    }
2329
2330    pub fn register_request(&mut self, request: &RequestFrame) -> Result<(), ResponseTrackerError> {
2331        if self.pending.contains_key(&request.request_id)
2332            || self.completed.contains(&request.request_id)
2333        {
2334            return Err(ResponseTrackerError::DuplicateRequestId {
2335                request_id: request.request_id,
2336            });
2337        }
2338
2339        self.pending.insert(
2340            request.request_id,
2341            PendingRequest {
2342                ownership: request.ownership.clone(),
2343                expected_response: request.payload.expected_response(),
2344            },
2345        );
2346        Ok(())
2347    }
2348
2349    pub fn accept_response(
2350        &mut self,
2351        response: &ResponseFrame,
2352    ) -> Result<(), ResponseTrackerError> {
2353        if self.completed.contains(&response.request_id) {
2354            return Err(ResponseTrackerError::DuplicateResponse {
2355                request_id: response.request_id,
2356            });
2357        }
2358
2359        let pending = self.pending.get(&response.request_id).ok_or(
2360            ResponseTrackerError::UnmatchedResponse {
2361                request_id: response.request_id,
2362            },
2363        )?;
2364
2365        if pending.ownership != response.ownership {
2366            return Err(ResponseTrackerError::OwnershipMismatch {
2367                request_id: response.request_id,
2368                expected: Box::new(pending.ownership.clone()),
2369                actual: Box::new(response.ownership.clone()),
2370            });
2371        }
2372
2373        if !pending.expected_response.matches(&response.payload) {
2374            return Err(ResponseTrackerError::ResponseKindMismatch {
2375                request_id: response.request_id,
2376                expected: pending.expected_response.as_str().to_string(),
2377                actual: response.payload.kind_name().to_string(),
2378            });
2379        }
2380
2381        self.pending
2382            .remove(&response.request_id)
2383            .expect("pending response should still exist after validation");
2384        self.completed.insert(response.request_id);
2385        self.completed_order.push_back(response.request_id);
2386        while self.completed.len() > self.completed_cap {
2387            if let Some(evicted) = self.completed_order.pop_front() {
2388                self.completed.remove(&evicted);
2389            }
2390        }
2391        Ok(())
2392    }
2393}
2394
2395impl Default for ResponseTracker {
2396    fn default() -> Self {
2397        Self::with_completed_cap(DEFAULT_COMPLETED_RESPONSE_CAP)
2398    }
2399}
2400
2401impl SidecarResponseTracker {
2402    pub fn with_completed_cap(completed_cap: usize) -> Self {
2403        Self {
2404            pending: HashMap::new(),
2405            completed: HashSet::new(),
2406            completed_order: VecDeque::new(),
2407            completed_cap: completed_cap.max(1),
2408        }
2409    }
2410
2411    pub fn pending_count(&self) -> usize {
2412        self.pending.len()
2413    }
2414
2415    pub fn completed_count(&self) -> usize {
2416        self.completed.len()
2417    }
2418
2419    pub fn register_request(
2420        &mut self,
2421        request: &SidecarRequestFrame,
2422    ) -> Result<(), SidecarResponseTrackerError> {
2423        if self.pending.contains_key(&request.request_id)
2424            || self.completed.contains(&request.request_id)
2425        {
2426            return Err(SidecarResponseTrackerError::DuplicateRequestId {
2427                request_id: request.request_id,
2428            });
2429        }
2430
2431        self.pending.insert(
2432            request.request_id,
2433            PendingSidecarRequest {
2434                ownership: request.ownership.clone(),
2435                expected_response: request.payload.expected_response(),
2436            },
2437        );
2438        Ok(())
2439    }
2440
2441    pub fn accept_response(
2442        &mut self,
2443        response: &SidecarResponseFrame,
2444    ) -> Result<(), SidecarResponseTrackerError> {
2445        if self.completed.contains(&response.request_id) {
2446            return Err(SidecarResponseTrackerError::DuplicateResponse {
2447                request_id: response.request_id,
2448            });
2449        }
2450
2451        let pending = self.pending.get(&response.request_id).ok_or(
2452            SidecarResponseTrackerError::UnmatchedResponse {
2453                request_id: response.request_id,
2454            },
2455        )?;
2456
2457        if pending.ownership != response.ownership {
2458            return Err(SidecarResponseTrackerError::OwnershipMismatch {
2459                request_id: response.request_id,
2460                expected: Box::new(pending.ownership.clone()),
2461                actual: Box::new(response.ownership.clone()),
2462            });
2463        }
2464
2465        if !pending.expected_response.matches(&response.payload) {
2466            return Err(SidecarResponseTrackerError::ResponseKindMismatch {
2467                request_id: response.request_id,
2468                expected: pending.expected_response.as_str().to_string(),
2469                actual: response.payload.kind_name().to_string(),
2470            });
2471        }
2472
2473        self.pending
2474            .remove(&response.request_id)
2475            .expect("pending sidecar response should still exist after validation");
2476        self.completed.insert(response.request_id);
2477        self.completed_order.push_back(response.request_id);
2478        while self.completed.len() > self.completed_cap {
2479            if let Some(evicted) = self.completed_order.pop_front() {
2480                self.completed.remove(&evicted);
2481            }
2482        }
2483        Ok(())
2484    }
2485}
2486
2487impl Default for SidecarResponseTracker {
2488    fn default() -> Self {
2489        Self::with_completed_cap(DEFAULT_COMPLETED_RESPONSE_CAP)
2490    }
2491}
2492
2493#[derive(Debug, Clone, PartialEq, Eq)]
2494pub enum ResponseTrackerError {
2495    DuplicateRequestId {
2496        request_id: RequestId,
2497    },
2498    UnmatchedResponse {
2499        request_id: RequestId,
2500    },
2501    DuplicateResponse {
2502        request_id: RequestId,
2503    },
2504    OwnershipMismatch {
2505        request_id: RequestId,
2506        expected: Box<OwnershipScope>,
2507        actual: Box<OwnershipScope>,
2508    },
2509    ResponseKindMismatch {
2510        request_id: RequestId,
2511        expected: String,
2512        actual: String,
2513    },
2514}
2515
2516impl fmt::Display for ResponseTrackerError {
2517    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2518        match self {
2519            Self::DuplicateRequestId { request_id } => {
2520                write!(f, "request id {request_id} is already tracked")
2521            }
2522            Self::UnmatchedResponse { request_id } => {
2523                write!(
2524                    f,
2525                    "response id {request_id} does not match any pending request"
2526                )
2527            }
2528            Self::DuplicateResponse { request_id } => {
2529                write!(f, "response id {request_id} has already been completed")
2530            }
2531            Self::OwnershipMismatch {
2532                request_id,
2533                expected,
2534                actual,
2535            } => write!(
2536                f,
2537                "response id {request_id} used ownership {:?}, expected {:?}",
2538                actual, expected
2539            ),
2540            Self::ResponseKindMismatch {
2541                request_id,
2542                expected,
2543                actual,
2544            } => write!(
2545                f,
2546                "response id {request_id} carried {actual}, expected {expected}",
2547            ),
2548        }
2549    }
2550}
2551
2552impl Error for ResponseTrackerError {}
2553
2554#[derive(Debug, Clone, PartialEq, Eq)]
2555pub enum SidecarResponseTrackerError {
2556    DuplicateRequestId {
2557        request_id: RequestId,
2558    },
2559    UnmatchedResponse {
2560        request_id: RequestId,
2561    },
2562    DuplicateResponse {
2563        request_id: RequestId,
2564    },
2565    OwnershipMismatch {
2566        request_id: RequestId,
2567        expected: Box<OwnershipScope>,
2568        actual: Box<OwnershipScope>,
2569    },
2570    ResponseKindMismatch {
2571        request_id: RequestId,
2572        expected: String,
2573        actual: String,
2574    },
2575}
2576
2577impl fmt::Display for SidecarResponseTrackerError {
2578    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2579        match self {
2580            Self::DuplicateRequestId { request_id } => {
2581                write!(f, "sidecar request id {request_id} is already tracked")
2582            }
2583            Self::UnmatchedResponse { request_id } => {
2584                write!(
2585                    f,
2586                    "sidecar response id {request_id} does not match any pending request"
2587                )
2588            }
2589            Self::DuplicateResponse { request_id } => {
2590                write!(
2591                    f,
2592                    "sidecar response id {request_id} has already been completed"
2593                )
2594            }
2595            Self::OwnershipMismatch {
2596                request_id,
2597                expected,
2598                actual,
2599            } => write!(
2600                f,
2601                "sidecar response id {request_id} used ownership {:?}, expected {:?}",
2602                actual, expected
2603            ),
2604            Self::ResponseKindMismatch {
2605                request_id,
2606                expected,
2607                actual,
2608            } => write!(
2609                f,
2610                "sidecar response id {request_id} carried {actual}, expected {expected}",
2611            ),
2612        }
2613    }
2614}
2615
2616impl Error for SidecarResponseTrackerError {}
2617
2618#[derive(Debug, Clone, PartialEq, Eq)]
2619struct PendingRequest {
2620    ownership: OwnershipScope,
2621    expected_response: ExpectedResponseKind,
2622}
2623
2624#[derive(Debug, Clone, PartialEq, Eq)]
2625struct PendingSidecarRequest {
2626    ownership: OwnershipScope,
2627    expected_response: ExpectedSidecarResponseKind,
2628}
2629
2630#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2631enum ExpectedResponseKind {
2632    Authenticated,
2633    SessionOpened,
2634    VmCreated,
2635    VmDisposed,
2636    RootFilesystemBootstrapped,
2637    VmConfigured,
2638    HostCallbacksRegistered,
2639    LayerCreated,
2640    LayerSealed,
2641    SnapshotImported,
2642    SnapshotExported,
2643    OverlayCreated,
2644    GuestFilesystemResult,
2645    RootFilesystemSnapshot,
2646    ProcessStarted,
2647    StdinWritten,
2648    StdinClosed,
2649    ProcessKilled,
2650    ProcessSnapshot,
2651    ResourceSnapshot,
2652    ListenerSnapshot,
2653    BoundUdpSnapshot,
2654    VmFetchResult,
2655    SignalState,
2656    ZombieTimerCount,
2657    FilesystemResult,
2658    // `PermissionDecision` is a sidecar-initiated callback response, so no host
2659    // request maps to it in `expected_response_kind`; kept for protocol symmetry.
2660    #[allow(dead_code)]
2661    PermissionDecision,
2662    PersistenceState,
2663    PersistenceFlushed,
2664    ExtResult,
2665    GuestKernelResult,
2666    PtyResized,
2667    PackageLinked,
2668    ProvidedCommands,
2669    MountsListed,
2670    ExecutionOperation,
2671    ExecutionCompleted,
2672    ExecutionEvaluation,
2673    TypeScriptCheck,
2674    ExecutionDescriptor,
2675    ExecutionList,
2676    ExecutionDeleted,
2677    ExecutionIo,
2678    ExecutionOutputPage,
2679}
2680
2681#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2682enum ExpectedSidecarResponseKind {
2683    HostCallback,
2684    JsBridge,
2685    Ext,
2686}
2687
2688impl ExpectedResponseKind {
2689    fn as_str(self) -> &'static str {
2690        match self {
2691            Self::Authenticated => "authenticated",
2692            Self::SessionOpened => "session_opened",
2693            Self::VmCreated => "vm_created",
2694            Self::VmDisposed => "vm_disposed",
2695            Self::RootFilesystemBootstrapped => "root_filesystem_bootstrapped",
2696            Self::VmConfigured => "vm_configured",
2697            Self::HostCallbacksRegistered => "host_callbacks_registered",
2698            Self::LayerCreated => "layer_created",
2699            Self::LayerSealed => "layer_sealed",
2700            Self::SnapshotImported => "snapshot_imported",
2701            Self::SnapshotExported => "snapshot_exported",
2702            Self::OverlayCreated => "overlay_created",
2703            Self::GuestFilesystemResult => "guest_filesystem_result",
2704            Self::RootFilesystemSnapshot => "root_filesystem_snapshot",
2705            Self::ProcessStarted => "process_started",
2706            Self::StdinWritten => "stdin_written",
2707            Self::StdinClosed => "stdin_closed",
2708            Self::ProcessKilled => "process_killed",
2709            Self::ProcessSnapshot => "process_snapshot",
2710            Self::ResourceSnapshot => "resource_snapshot",
2711            Self::ListenerSnapshot => "listener_snapshot",
2712            Self::BoundUdpSnapshot => "bound_udp_snapshot",
2713            Self::VmFetchResult => "vm_fetch_result",
2714            Self::SignalState => "signal_state",
2715            Self::ZombieTimerCount => "zombie_timer_count",
2716            Self::FilesystemResult => "filesystem_result",
2717            Self::PermissionDecision => "permission_decision",
2718            Self::PersistenceState => "persistence_state",
2719            Self::PersistenceFlushed => "persistence_flushed",
2720            Self::ExtResult => "ext_result",
2721            Self::GuestKernelResult => "guest_kernel_result",
2722            Self::PtyResized => "pty_resized",
2723            Self::PackageLinked => "package_linked",
2724            Self::ProvidedCommands => "provided_commands_response",
2725            Self::MountsListed => "mounts_listed",
2726            Self::ExecutionOperation => "execution_operation",
2727            Self::ExecutionCompleted => "execution_completed",
2728            Self::ExecutionEvaluation => "execution_evaluation",
2729            Self::TypeScriptCheck => "type_script_check",
2730            Self::ExecutionDescriptor => "execution_descriptor",
2731            Self::ExecutionList => "execution_list",
2732            Self::ExecutionDeleted => "execution_deleted",
2733            Self::ExecutionIo => "execution_io",
2734            Self::ExecutionOutputPage => "execution_output_page",
2735        }
2736    }
2737
2738    fn matches(self, payload: &ResponsePayload) -> bool {
2739        match payload {
2740            ResponsePayload::Rejected(_) => true,
2741            ResponsePayload::ExecutionAccepted(_) | ResponsePayload::ExecutionCompleted(_)
2742                if self == Self::ExecutionOperation =>
2743            {
2744                true
2745            }
2746            _ => payload.kind_name() == self.as_str(),
2747        }
2748    }
2749}
2750
2751impl ExpectedSidecarResponseKind {
2752    fn as_str(self) -> &'static str {
2753        match self {
2754            Self::HostCallback => "host_callback_result",
2755            Self::JsBridge => "js_bridge_result",
2756            Self::Ext => "ext_result",
2757        }
2758    }
2759
2760    fn matches(self, payload: &SidecarResponsePayload) -> bool {
2761        payload.kind_name() == self.as_str()
2762    }
2763}
2764
2765impl RequestPayload {
2766    fn ownership_requirement(&self) -> OwnershipRequirement {
2767        match self {
2768            Self::Authenticate(_) | Self::OpenSession(_) => OwnershipRequirement::Connection,
2769            Self::CreateVm(_) | Self::PersistenceLoad(_) | Self::PersistenceFlush(_) => {
2770                OwnershipRequirement::Session
2771            }
2772            Self::DisposeVm(_)
2773            | Self::BootstrapRootFilesystem(_)
2774            | Self::ConfigureVm(_)
2775            | Self::RegisterHostCallbacks(_)
2776            | Self::CreateLayer(_)
2777            | Self::SealLayer(_)
2778            | Self::ImportSnapshot(_)
2779            | Self::ExportSnapshot(_)
2780            | Self::CreateOverlay(_)
2781            | Self::GuestFilesystemCall(_)
2782            | Self::SnapshotRootFilesystem(_)
2783            | Self::ListMounts(_)
2784            | Self::Execute(_)
2785            | Self::WriteStdin(_)
2786            | Self::CloseStdin(_)
2787            | Self::KillProcess(_)
2788            | Self::GetProcessSnapshot(_)
2789            | Self::GetResourceSnapshot(_)
2790            | Self::FindListener(_)
2791            | Self::FindBoundUdp(_)
2792            | Self::VmFetch(_)
2793            | Self::GetSignalState(_)
2794            | Self::GetZombieTimerCount(_)
2795            | Self::GuestKernelCall(_)
2796            | Self::ResizePty(_)
2797            | Self::LinkPackage(_)
2798            | Self::ProvidedCommands(_)
2799            | Self::ShellExecution(_)
2800            | Self::ArgvExecution(_)
2801            | Self::JavaScriptExecution(_)
2802            | Self::JavaScriptEvaluation(_)
2803            | Self::JavaScriptFileExecution(_)
2804            | Self::TypeScriptExecution(_)
2805            | Self::TypeScriptEvaluation(_)
2806            | Self::TypeScriptFileExecution(_)
2807            | Self::TypeScriptCheck(_)
2808            | Self::TypeScriptProjectCheck(_)
2809            | Self::NpmProjectInstall(_)
2810            | Self::NpmPackageInstall(_)
2811            | Self::NpmScriptExecution(_)
2812            | Self::NpmPackageExecution(_)
2813            | Self::PythonExecution(_)
2814            | Self::PythonEvaluation(_)
2815            | Self::PythonFileExecution(_)
2816            | Self::PythonModuleExecution(_)
2817            | Self::PythonInstall(_)
2818            | Self::CreateContext(_)
2819            | Self::GetExecution(_)
2820            | Self::ListExecutions(_)
2821            | Self::WaitExecution(_)
2822            | Self::CancelExecution(_)
2823            | Self::SignalExecution(_)
2824            | Self::ResetExecution(_)
2825            | Self::DeleteExecution(_)
2826            | Self::WriteExecutionStdin(_)
2827            | Self::CloseExecutionStdin(_)
2828            | Self::ResizeExecutionPty(_)
2829            | Self::ReadExecutionOutput(_)
2830            | Self::HostFilesystemCall(_) => OwnershipRequirement::Vm,
2831            Self::Ext(_) => OwnershipRequirement::Any,
2832        }
2833    }
2834
2835    fn expected_response(&self) -> ExpectedResponseKind {
2836        match self {
2837            Self::Authenticate(_) => ExpectedResponseKind::Authenticated,
2838            Self::OpenSession(_) => ExpectedResponseKind::SessionOpened,
2839            Self::CreateVm(_) => ExpectedResponseKind::VmCreated,
2840            Self::DisposeVm(_) => ExpectedResponseKind::VmDisposed,
2841            Self::BootstrapRootFilesystem(_) => ExpectedResponseKind::RootFilesystemBootstrapped,
2842            Self::ConfigureVm(_) => ExpectedResponseKind::VmConfigured,
2843            Self::RegisterHostCallbacks(_) => ExpectedResponseKind::HostCallbacksRegistered,
2844            Self::CreateLayer(_) => ExpectedResponseKind::LayerCreated,
2845            Self::SealLayer(_) => ExpectedResponseKind::LayerSealed,
2846            Self::ImportSnapshot(_) => ExpectedResponseKind::SnapshotImported,
2847            Self::ExportSnapshot(_) => ExpectedResponseKind::SnapshotExported,
2848            Self::CreateOverlay(_) => ExpectedResponseKind::OverlayCreated,
2849            Self::GuestFilesystemCall(_) => ExpectedResponseKind::GuestFilesystemResult,
2850            Self::SnapshotRootFilesystem(_) => ExpectedResponseKind::RootFilesystemSnapshot,
2851            Self::ListMounts(_) => ExpectedResponseKind::MountsListed,
2852            Self::Execute(_) => ExpectedResponseKind::ProcessStarted,
2853            Self::WriteStdin(_) => ExpectedResponseKind::StdinWritten,
2854            Self::CloseStdin(_) => ExpectedResponseKind::StdinClosed,
2855            Self::KillProcess(_) => ExpectedResponseKind::ProcessKilled,
2856            Self::GetProcessSnapshot(_) => ExpectedResponseKind::ProcessSnapshot,
2857            Self::GetResourceSnapshot(_) => ExpectedResponseKind::ResourceSnapshot,
2858            Self::FindListener(_) => ExpectedResponseKind::ListenerSnapshot,
2859            Self::FindBoundUdp(_) => ExpectedResponseKind::BoundUdpSnapshot,
2860            Self::VmFetch(_) => ExpectedResponseKind::VmFetchResult,
2861            Self::GetSignalState(_) => ExpectedResponseKind::SignalState,
2862            Self::GetZombieTimerCount(_) => ExpectedResponseKind::ZombieTimerCount,
2863            Self::HostFilesystemCall(_) => ExpectedResponseKind::FilesystemResult,
2864            Self::PersistenceLoad(_) => ExpectedResponseKind::PersistenceState,
2865            Self::PersistenceFlush(_) => ExpectedResponseKind::PersistenceFlushed,
2866            Self::Ext(_) => ExpectedResponseKind::ExtResult,
2867            Self::GuestKernelCall(_) => ExpectedResponseKind::GuestKernelResult,
2868            Self::ResizePty(_) => ExpectedResponseKind::PtyResized,
2869            Self::LinkPackage(_) => ExpectedResponseKind::PackageLinked,
2870            Self::ProvidedCommands(_) => ExpectedResponseKind::ProvidedCommands,
2871            Self::ShellExecution(_)
2872            | Self::ArgvExecution(_)
2873            | Self::JavaScriptExecution(_)
2874            | Self::JavaScriptFileExecution(_)
2875            | Self::TypeScriptExecution(_)
2876            | Self::TypeScriptFileExecution(_)
2877            | Self::NpmProjectInstall(_)
2878            | Self::NpmPackageInstall(_)
2879            | Self::NpmScriptExecution(_)
2880            | Self::NpmPackageExecution(_)
2881            | Self::PythonExecution(_)
2882            | Self::PythonFileExecution(_)
2883            | Self::PythonModuleExecution(_)
2884            | Self::PythonInstall(_) => ExpectedResponseKind::ExecutionOperation,
2885            Self::JavaScriptEvaluation(_)
2886            | Self::TypeScriptEvaluation(_)
2887            | Self::PythonEvaluation(_) => ExpectedResponseKind::ExecutionEvaluation,
2888            Self::TypeScriptCheck(_) | Self::TypeScriptProjectCheck(_) => {
2889                ExpectedResponseKind::TypeScriptCheck
2890            }
2891            Self::CreateContext(_)
2892            | Self::GetExecution(_)
2893            | Self::CancelExecution(_)
2894            | Self::SignalExecution(_)
2895            | Self::ResetExecution(_) => ExpectedResponseKind::ExecutionDescriptor,
2896            Self::ListExecutions(_) => ExpectedResponseKind::ExecutionList,
2897            Self::WaitExecution(_) => ExpectedResponseKind::ExecutionCompleted,
2898            Self::DeleteExecution(_) => ExpectedResponseKind::ExecutionDeleted,
2899            Self::WriteExecutionStdin(_)
2900            | Self::CloseExecutionStdin(_)
2901            | Self::ResizeExecutionPty(_) => ExpectedResponseKind::ExecutionIo,
2902            Self::ReadExecutionOutput(_) => ExpectedResponseKind::ExecutionOutputPage,
2903        }
2904    }
2905}
2906
2907impl SidecarRequestPayload {
2908    fn ownership_requirement(&self) -> OwnershipRequirement {
2909        OwnershipRequirement::Vm
2910    }
2911
2912    fn expected_response(&self) -> ExpectedSidecarResponseKind {
2913        match self {
2914            Self::HostCallback(_) => ExpectedSidecarResponseKind::HostCallback,
2915            Self::JsBridgeCall(_) => ExpectedSidecarResponseKind::JsBridge,
2916            Self::Ext(_) => ExpectedSidecarResponseKind::Ext,
2917        }
2918    }
2919}
2920
2921impl ResponsePayload {
2922    fn ownership_requirement(&self) -> OwnershipRequirement {
2923        match self {
2924            Self::Authenticated(_) | Self::SessionOpened(_) => OwnershipRequirement::Connection,
2925            Self::VmCreated(_) | Self::PersistenceState(_) | Self::PersistenceFlushed(_) => {
2926                OwnershipRequirement::Session
2927            }
2928            Self::Rejected(_) => OwnershipRequirement::Any,
2929            Self::VmDisposed(_)
2930            | Self::RootFilesystemBootstrapped(_)
2931            | Self::VmConfigured(_)
2932            | Self::HostCallbacksRegistered(_)
2933            | Self::LayerCreated(_)
2934            | Self::LayerSealed(_)
2935            | Self::SnapshotImported(_)
2936            | Self::SnapshotExported(_)
2937            | Self::OverlayCreated(_)
2938            | Self::GuestFilesystemResult(_)
2939            | Self::RootFilesystemSnapshot(_)
2940            | Self::MountsListed(_)
2941            | Self::ProcessStarted(_)
2942            | Self::StdinWritten(_)
2943            | Self::StdinClosed(_)
2944            | Self::ProcessKilled(_)
2945            | Self::ProcessSnapshot(_)
2946            | Self::ResourceSnapshot(_)
2947            | Self::ListenerSnapshot(_)
2948            | Self::BoundUdpSnapshot(_)
2949            | Self::VmFetchResult(_)
2950            | Self::SignalState(_)
2951            | Self::ZombieTimerCount(_)
2952            | Self::FilesystemResult(_)
2953            | Self::PermissionDecision(_)
2954            | Self::GuestKernelResult(_)
2955            | Self::PtyResized(_)
2956            | Self::PackageLinked(_)
2957            | Self::ProvidedCommands(_)
2958            | Self::ExecutionAccepted(_)
2959            | Self::ExecutionCompleted(_)
2960            | Self::ExecutionEvaluation(_)
2961            | Self::TypeScriptCheck(_)
2962            | Self::ExecutionDescriptor(_)
2963            | Self::ExecutionList(_)
2964            | Self::ExecutionDeleted(_)
2965            | Self::ExecutionIo(_)
2966            | Self::ExecutionOutputPage(_) => OwnershipRequirement::Vm,
2967            Self::ExtResult(_) => OwnershipRequirement::Any,
2968        }
2969    }
2970
2971    fn kind_name(&self) -> &'static str {
2972        match self {
2973            Self::Authenticated(_) => "authenticated",
2974            Self::SessionOpened(_) => "session_opened",
2975            Self::VmCreated(_) => "vm_created",
2976            Self::VmDisposed(_) => "vm_disposed",
2977            Self::RootFilesystemBootstrapped(_) => "root_filesystem_bootstrapped",
2978            Self::VmConfigured(_) => "vm_configured",
2979            Self::HostCallbacksRegistered(_) => "host_callbacks_registered",
2980            Self::LayerCreated(_) => "layer_created",
2981            Self::LayerSealed(_) => "layer_sealed",
2982            Self::SnapshotImported(_) => "snapshot_imported",
2983            Self::SnapshotExported(_) => "snapshot_exported",
2984            Self::OverlayCreated(_) => "overlay_created",
2985            Self::GuestFilesystemResult(_) => "guest_filesystem_result",
2986            Self::RootFilesystemSnapshot(_) => "root_filesystem_snapshot",
2987            Self::MountsListed(_) => "mounts_listed",
2988            Self::ProcessStarted(_) => "process_started",
2989            Self::StdinWritten(_) => "stdin_written",
2990            Self::StdinClosed(_) => "stdin_closed",
2991            Self::ProcessKilled(_) => "process_killed",
2992            Self::ProcessSnapshot(_) => "process_snapshot",
2993            Self::ResourceSnapshot(_) => "resource_snapshot",
2994            Self::ListenerSnapshot(_) => "listener_snapshot",
2995            Self::BoundUdpSnapshot(_) => "bound_udp_snapshot",
2996            Self::VmFetchResult(_) => "vm_fetch_result",
2997            Self::SignalState(_) => "signal_state",
2998            Self::ZombieTimerCount(_) => "zombie_timer_count",
2999            Self::FilesystemResult(_) => "filesystem_result",
3000            Self::PermissionDecision(_) => "permission_decision",
3001            Self::PersistenceState(_) => "persistence_state",
3002            Self::PersistenceFlushed(_) => "persistence_flushed",
3003            Self::Rejected(_) => "rejected",
3004            Self::ExtResult(_) => "ext_result",
3005            Self::GuestKernelResult(_) => "guest_kernel_result",
3006            Self::PtyResized(_) => "pty_resized",
3007            Self::PackageLinked(_) => "package_linked",
3008            Self::ProvidedCommands(_) => "provided_commands_response",
3009            Self::ExecutionAccepted(_) => "execution_accepted",
3010            Self::ExecutionCompleted(_) => "execution_completed",
3011            Self::ExecutionEvaluation(_) => "execution_evaluation",
3012            Self::TypeScriptCheck(_) => "type_script_check",
3013            Self::ExecutionDescriptor(_) => "execution_descriptor",
3014            Self::ExecutionList(_) => "execution_list",
3015            Self::ExecutionDeleted(_) => "execution_deleted",
3016            Self::ExecutionIo(_) => "execution_io",
3017            Self::ExecutionOutputPage(_) => "execution_output_page",
3018        }
3019    }
3020}
3021
3022impl SidecarResponsePayload {
3023    fn ownership_requirement(&self) -> OwnershipRequirement {
3024        OwnershipRequirement::Vm
3025    }
3026
3027    fn kind_name(&self) -> &'static str {
3028        match self {
3029            Self::HostCallbackResult(_) => "host_callback_result",
3030            Self::JsBridgeResult(_) => "js_bridge_result",
3031            Self::ExtResult(_) => "ext_result",
3032        }
3033    }
3034}
3035
3036impl EventPayload {
3037    fn ownership_requirement(&self) -> OwnershipRequirement {
3038        match self {
3039            Self::Structured(_) => OwnershipRequirement::SessionOrVm,
3040            Self::VmLifecycle(_)
3041            | Self::ProcessOutput(_)
3042            | Self::ProcessExited(_)
3043            | Self::ExecutionOutput(_)
3044            | Self::ExecutionCompleted(_) => OwnershipRequirement::Vm,
3045            Self::Ext(_) => OwnershipRequirement::Any,
3046        }
3047    }
3048}
3049
3050pub fn validate_frame(frame: &ProtocolFrame) -> Result<(), ProtocolCodecError> {
3051    match frame {
3052        ProtocolFrame::Request(request) => validate_request(request),
3053        ProtocolFrame::Response(response) => validate_response(response),
3054        ProtocolFrame::Event(event) => validate_event(event),
3055        ProtocolFrame::SidecarRequest(request) => validate_sidecar_request(request),
3056        ProtocolFrame::SidecarResponse(response) => validate_sidecar_response(response),
3057        ProtocolFrame::Control(control) => validate_schema(&control.schema),
3058    }
3059}
3060
3061fn validate_request(request: &RequestFrame) -> Result<(), ProtocolCodecError> {
3062    validate_schema(&request.schema)?;
3063    validate_request_id_direction(request.request_id, RequestDirection::Host)?;
3064
3065    validate_ownership(&request.ownership)?;
3066    validate_requirement(request.payload.ownership_requirement(), &request.ownership)?;
3067    if let RequestPayload::Authenticate(authenticate) = &request.payload {
3068        if authenticate.auth_token.is_empty() {
3069            return Err(ProtocolCodecError::EmptyAuthToken);
3070        }
3071    }
3072
3073    Ok(())
3074}
3075
3076fn validate_response(response: &ResponseFrame) -> Result<(), ProtocolCodecError> {
3077    validate_schema(&response.schema)?;
3078    validate_request_id_direction(response.request_id, RequestDirection::Host)?;
3079
3080    validate_ownership(&response.ownership)?;
3081    validate_requirement(
3082        response.payload.ownership_requirement(),
3083        &response.ownership,
3084    )?;
3085    Ok(())
3086}
3087
3088fn validate_sidecar_request(request: &SidecarRequestFrame) -> Result<(), ProtocolCodecError> {
3089    validate_schema(&request.schema)?;
3090    validate_request_id_direction(request.request_id, RequestDirection::Sidecar)?;
3091    validate_ownership(&request.ownership)?;
3092    validate_requirement(request.payload.ownership_requirement(), &request.ownership)?;
3093    Ok(())
3094}
3095
3096fn validate_sidecar_response(response: &SidecarResponseFrame) -> Result<(), ProtocolCodecError> {
3097    validate_schema(&response.schema)?;
3098    validate_request_id_direction(response.request_id, RequestDirection::Sidecar)?;
3099    validate_ownership(&response.ownership)?;
3100    validate_requirement(
3101        response.payload.ownership_requirement(),
3102        &response.ownership,
3103    )?;
3104    Ok(())
3105}
3106
3107fn validate_event(event: &EventFrame) -> Result<(), ProtocolCodecError> {
3108    validate_schema(&event.schema)?;
3109    validate_ownership(&event.ownership)?;
3110    validate_requirement(event.payload.ownership_requirement(), &event.ownership)?;
3111    Ok(())
3112}
3113
3114fn validate_schema(schema: &ProtocolSchema) -> Result<(), ProtocolCodecError> {
3115    if schema.name != PROTOCOL_NAME || schema.version != PROTOCOL_VERSION {
3116        return Err(ProtocolCodecError::UnsupportedSchema {
3117            name: schema.name.clone(),
3118            version: schema.version,
3119        });
3120    }
3121
3122    Ok(())
3123}
3124
3125fn validate_ownership(ownership: &OwnershipScope) -> Result<(), ProtocolCodecError> {
3126    match ownership {
3127        OwnershipScope::ConnectionOwnership(inner) => {
3128            validate_non_empty("connection_id", &inner.connection_id)
3129        }
3130        OwnershipScope::SessionOwnership(inner) => {
3131            validate_non_empty("connection_id", &inner.connection_id)?;
3132            validate_non_empty("session_id", &inner.session_id)
3133        }
3134        OwnershipScope::VmOwnership(inner) => {
3135            validate_non_empty("connection_id", &inner.connection_id)?;
3136            validate_non_empty("session_id", &inner.session_id)?;
3137            validate_non_empty("vm_id", &inner.vm_id)
3138        }
3139    }
3140}
3141
3142fn validate_non_empty(field: &'static str, value: &str) -> Result<(), ProtocolCodecError> {
3143    if value.is_empty() {
3144        return Err(ProtocolCodecError::EmptyOwnershipField { field });
3145    }
3146
3147    Ok(())
3148}
3149
3150fn validate_request_id_direction(
3151    request_id: RequestId,
3152    direction: RequestDirection,
3153) -> Result<(), ProtocolCodecError> {
3154    if request_id == 0 {
3155        return Err(ProtocolCodecError::InvalidRequestId);
3156    }
3157
3158    let matches_direction = match direction {
3159        RequestDirection::Host => request_id > 0,
3160        RequestDirection::Sidecar => request_id < 0,
3161    };
3162    if matches_direction {
3163        Ok(())
3164    } else {
3165        Err(ProtocolCodecError::InvalidRequestDirection {
3166            request_id,
3167            expected: direction,
3168        })
3169    }
3170}
3171
3172fn validate_requirement(
3173    required: OwnershipRequirement,
3174    ownership: &OwnershipScope,
3175) -> Result<(), ProtocolCodecError> {
3176    let actual = match ownership {
3177        OwnershipScope::ConnectionOwnership(..) => OwnershipRequirement::Connection,
3178        OwnershipScope::SessionOwnership(..) => OwnershipRequirement::Session,
3179        OwnershipScope::VmOwnership(..) => OwnershipRequirement::Vm,
3180    };
3181
3182    let valid = match required {
3183        OwnershipRequirement::Any => true,
3184        OwnershipRequirement::Connection => {
3185            matches!(ownership, OwnershipScope::ConnectionOwnership(..))
3186        }
3187        OwnershipRequirement::Session => matches!(ownership, OwnershipScope::SessionOwnership(..)),
3188        OwnershipRequirement::Vm => matches!(ownership, OwnershipScope::VmOwnership(..)),
3189        OwnershipRequirement::SessionOrVm => {
3190            matches!(
3191                ownership,
3192                OwnershipScope::SessionOwnership(..) | OwnershipScope::VmOwnership(..)
3193            )
3194        }
3195    };
3196
3197    if valid {
3198        Ok(())
3199    } else {
3200        Err(ProtocolCodecError::InvalidOwnershipScope { required, actual })
3201    }
3202}
3203
3204// ---------------------------------------------------------------------------
3205// JavaScript sync-RPC request types (deserialized from guest Node.js processes)
3206// ---------------------------------------------------------------------------
3207
3208#[derive(Debug, Clone, Deserialize)]
3209pub struct JavascriptPosixSpawnFileAction {
3210    pub command: u32,
3211    #[serde(rename = "guestFd", default)]
3212    pub guest_fd: Option<i32>,
3213    pub fd: i32,
3214    #[serde(rename = "sourceFd")]
3215    pub source_fd: i32,
3216    #[serde(rename = "guestSourceFd", default)]
3217    pub guest_source_fd: Option<i32>,
3218    pub oflag: i32,
3219    pub mode: u32,
3220    pub path: String,
3221    /// Runner-local public guest descriptors selected by closefrom. These do
3222    /// not have kernel mappings, but the child bootstrap must still suppress
3223    /// their untagged aliases while retaining private tagged preopens.
3224    #[serde(rename = "closeFromGuestFds", default)]
3225    pub close_from_guest_fds: Vec<u32>,
3226}
3227
3228#[derive(Debug, Clone, Deserialize, Serialize)]
3229#[serde(rename_all = "camelCase")]
3230pub struct JavascriptSpawnHostNetFd {
3231    pub guest_fd: u32,
3232    #[serde(default)]
3233    pub close_on_exec: bool,
3234    #[serde(default)]
3235    pub socket_id: Option<String>,
3236    #[serde(default)]
3237    pub server_id: Option<String>,
3238    #[serde(default)]
3239    pub udp_socket_id: Option<String>,
3240    /// Runner-visible socket metadata needed to reconstruct the libc-facing
3241    /// descriptor in the child. Resource ownership is never trusted from this
3242    /// object: the sidecar resolves and clones the named parent resource.
3243    #[serde(default)]
3244    pub metadata: Value,
3245}
3246
3247#[derive(Debug, Deserialize, Default)]
3248pub struct JavascriptChildProcessPtyOptions {
3249    #[serde(default)]
3250    pub cols: Option<u16>,
3251    #[serde(default)]
3252    pub rows: Option<u16>,
3253}
3254
3255#[derive(Debug, Deserialize, Default)]
3256pub struct JavascriptChildProcessSpawnOptions {
3257    #[serde(default)]
3258    pub argv0: Option<String>,
3259    /// Guest descriptors marked FD_CLOEXEC in libc's runner-local descriptor
3260    /// table. Native exec applies these at the same commit point as the kernel
3261    /// table; runner-local handles are closed by the in-place image swap.
3262    #[serde(rename = "cloexecFds", default)]
3263    pub cloexec_fds: Vec<u32>,
3264    /// The sidecar-managed WASM runner has already validated the replacement
3265    /// module and will swap images in place after the sidecar commits kernel
3266    /// metadata. Other process.exec callers use the separate-execution path.
3267    #[serde(rename = "localReplacement", default)]
3268    pub local_replacement: bool,
3269    /// Runner-private executable descriptor used only by the dedicated
3270    /// process.exec_fd_image_commit route. Generic guest process.exec requests
3271    /// cannot turn this into an FD-backed replacement.
3272    #[serde(rename = "executableFd", default)]
3273    pub executable_fd: Option<u32>,
3274    #[serde(default)]
3275    pub cwd: Option<String>,
3276    #[serde(default)]
3277    pub env: BTreeMap<String, String>,
3278    #[serde(rename = "internalBootstrapEnv", default)]
3279    pub internal_bootstrap_env: BTreeMap<String, String>,
3280    /// POSIX spawn attributes already validated by the WASM host-import
3281    /// boundary. The sidecar validates them again before applying attributes
3282    /// that belong to the kernel process table.
3283    #[serde(rename = "spawnAttrFlags", default)]
3284    pub spawn_attr_flags: u32,
3285    /// Exact `posix_spawn` bypasses PATH lookup, including for bare names.
3286    #[serde(rename = "spawnExactPath", default)]
3287    pub spawn_exact_path: bool,
3288    /// `posix_spawnp` uses the caller's PATH, which can differ from envp.
3289    #[serde(rename = "spawnSearchPath", default)]
3290    pub spawn_search_path: Option<String>,
3291    #[serde(rename = "spawnSchedPolicy", default)]
3292    pub spawn_sched_policy: Option<i32>,
3293    #[serde(rename = "spawnSchedPriority", default)]
3294    pub spawn_sched_priority: Option<i32>,
3295    #[serde(rename = "spawnPgroup", default)]
3296    pub spawn_pgroup: Option<i32>,
3297    #[serde(rename = "spawnSignalDefaults", default)]
3298    pub spawn_signal_defaults: Vec<u32>,
3299    #[serde(rename = "spawnSignalMask", default)]
3300    pub spawn_signal_mask: Vec<u32>,
3301    #[serde(rename = "spawnFileActions", default)]
3302    pub spawn_file_actions: Vec<JavascriptPosixSpawnFileAction>,
3303    /// Guest-to-kernel descriptor namespace captured by the WASM runner at
3304    /// spawn time. WASI preopens occupy guest descriptors that do not exist in
3305    /// the kernel table, so file actions cannot safely assume the two numeric
3306    /// namespaces are identical.
3307    #[serde(rename = "spawnFdMappings", default)]
3308    pub spawn_fd_mappings: Vec<[u32; 2]>,
3309    /// Host-network descriptors occupy the guest fd namespace but are backed
3310    /// by sidecar-owned socket descriptions rather than kernel fd-table slots.
3311    /// They must therefore be inherited explicitly instead of being coerced
3312    /// into the private kernel descriptor namespace.
3313    #[serde(rename = "spawnHostNetFds", default)]
3314    pub spawn_host_net_fds: Vec<JavascriptSpawnHostNetFd>,
3315    #[serde(default)]
3316    pub input: Option<Value>,
3317    #[serde(default)]
3318    pub shell: bool,
3319    #[serde(default)]
3320    pub detached: bool,
3321    #[serde(default)]
3322    pub stdio: Vec<String>,
3323    #[serde(default)]
3324    pub timeout: Option<u64>,
3325    #[serde(rename = "killSignal", default)]
3326    pub kill_signal: Option<String>,
3327    #[serde(default)]
3328    pub pty: Option<JavascriptChildProcessPtyOptions>,
3329}
3330
3331#[derive(Debug, Deserialize)]
3332pub struct JavascriptChildProcessSpawnRequest {
3333    pub command: String,
3334    #[serde(default)]
3335    pub args: Vec<String>,
3336    #[serde(default)]
3337    pub options: JavascriptChildProcessSpawnOptions,
3338}
3339
3340#[derive(Debug, Deserialize)]
3341pub struct JavascriptNetConnectRequest {
3342    #[serde(default)]
3343    pub host: Option<String>,
3344    #[serde(default)]
3345    pub port: Option<u16>,
3346    #[serde(default)]
3347    pub family: Option<u8>,
3348    #[serde(default)]
3349    pub path: Option<String>,
3350    #[serde(rename = "abstractPathHex", default)]
3351    pub abstract_path_hex: Option<String>,
3352    #[serde(rename = "boundServerId", default)]
3353    pub bound_server_id: Option<String>,
3354    #[serde(rename = "localAddress", default)]
3355    pub local_address: Option<String>,
3356    #[serde(rename = "localPort", default)]
3357    pub local_port: Option<u16>,
3358    #[serde(rename = "localReservation", default)]
3359    pub local_reservation: Option<String>,
3360}
3361
3362#[derive(Debug, Deserialize)]
3363pub struct JavascriptNetBindConnectedUnixRequest {
3364    #[serde(rename = "socketId")]
3365    pub socket_id: String,
3366    #[serde(default)]
3367    pub path: Option<String>,
3368    #[serde(rename = "abstractPathHex", default)]
3369    pub abstract_path_hex: Option<String>,
3370    #[serde(default)]
3371    pub autobind: bool,
3372}
3373
3374#[derive(Debug, Deserialize)]
3375pub struct JavascriptNetReserveTcpPortRequest {
3376    #[serde(default)]
3377    pub host: Option<String>,
3378    #[serde(default)]
3379    pub port: Option<u16>,
3380}
3381
3382#[derive(Debug, Deserialize)]
3383pub struct JavascriptNetListenRequest {
3384    #[serde(default)]
3385    pub host: Option<String>,
3386    #[serde(default)]
3387    pub port: Option<u16>,
3388    #[serde(default)]
3389    pub path: Option<String>,
3390    #[serde(rename = "abstractPathHex", default)]
3391    pub abstract_path_hex: Option<String>,
3392    #[serde(rename = "boundServerId", default)]
3393    pub bound_server_id: Option<String>,
3394    #[serde(default)]
3395    pub autobind: bool,
3396    #[serde(default)]
3397    pub backlog: Option<u32>,
3398    #[serde(rename = "localReservation", default)]
3399    pub local_reservation: Option<String>,
3400}
3401
3402#[derive(Debug, Deserialize)]
3403pub struct JavascriptDgramCreateSocketRequest {
3404    #[serde(rename = "type")]
3405    pub socket_type: String,
3406}
3407
3408#[derive(Debug, Deserialize)]
3409pub struct JavascriptDgramBindRequest {
3410    #[serde(default)]
3411    pub address: Option<String>,
3412    #[serde(default)]
3413    pub port: u16,
3414}
3415
3416#[derive(Debug, Deserialize)]
3417pub struct JavascriptDgramSendRequest {
3418    #[serde(default)]
3419    pub address: Option<String>,
3420    #[serde(default)]
3421    pub port: Option<u16>,
3422}
3423
3424#[derive(Debug, Deserialize)]
3425pub struct JavascriptDgramConnectRequest {
3426    #[serde(default)]
3427    pub address: Option<String>,
3428    pub port: u16,
3429}
3430
3431#[derive(Debug, Deserialize)]
3432pub struct JavascriptDnsLookupRequest {
3433    pub hostname: String,
3434    #[serde(default)]
3435    pub family: Option<u8>,
3436}
3437
3438#[derive(Debug, Deserialize)]
3439pub struct JavascriptDnsResolveRequest {
3440    pub hostname: String,
3441    #[serde(default)]
3442    pub rrtype: Option<String>,
3443}