Skip to main content

codex_mobile_wire/
envelopes.rs

1use codex_mobile_contracts::{
2    ApiError, DirectoryBookmarkRecord, DirectoryHistoryRecord, PendingServerRequestRecord,
3    RuntimeStatusSnapshot, RuntimeSummary,
4};
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7
8#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
9#[serde(rename_all = "camelCase")]
10pub struct PersistedEvent {
11    pub seq: i64,
12    pub event_type: String,
13    pub runtime_id: Option<String>,
14    pub thread_id: Option<String>,
15    pub payload: Value,
16    pub created_at_ms: i64,
17}
18
19#[derive(Debug, Deserialize)]
20#[serde(tag = "kind", rename_all = "snake_case")]
21pub enum ClientEnvelope {
22    Hello {
23        device_id: String,
24        last_ack_seq: Option<i64>,
25    },
26    Request {
27        request_id: String,
28        action: String,
29        #[serde(default)]
30        payload: Value,
31    },
32    AckEvents {
33        last_seq: i64,
34    },
35    Ping,
36}
37
38#[derive(Debug, Serialize, Deserialize)]
39#[serde(tag = "kind")]
40pub enum ServerEnvelope {
41    #[serde(rename = "hello")]
42    Hello {
43        #[serde(rename = "bridgeVersion")]
44        bridge_version: String,
45        #[serde(rename = "protocolVersion")]
46        protocol_version: i32,
47        runtime: Box<RuntimeStatusSnapshot>,
48        runtimes: Vec<RuntimeSummary>,
49        #[serde(rename = "directoryBookmarks")]
50        directory_bookmarks: Vec<DirectoryBookmarkRecord>,
51        #[serde(rename = "directoryHistory")]
52        directory_history: Vec<DirectoryHistoryRecord>,
53        #[serde(rename = "pending_requests")]
54        pending_requests: Vec<PendingServerRequestRecord>,
55    },
56    #[serde(rename = "response")]
57    Response {
58        #[serde(rename = "request_id")]
59        request_id: String,
60        success: bool,
61        #[serde(skip_serializing_if = "Option::is_none")]
62        data: Option<Value>,
63        #[serde(skip_serializing_if = "Option::is_none")]
64        error: Option<ApiError>,
65    },
66    #[serde(rename = "event")]
67    Event {
68        seq: i64,
69        #[serde(rename = "event_type")]
70        event_type: String,
71        #[serde(skip_serializing_if = "Option::is_none")]
72        #[serde(rename = "runtime_id")]
73        runtime_id: Option<String>,
74        #[serde(skip_serializing_if = "Option::is_none")]
75        #[serde(rename = "thread_id")]
76        thread_id: Option<String>,
77        payload: Value,
78    },
79    #[serde(rename = "pong")]
80    Pong {
81        #[serde(rename = "server_time_ms")]
82        server_time_ms: i64,
83    },
84}
85
86pub fn ok_response(request_id: String, data: Value) -> ServerEnvelope {
87    ServerEnvelope::Response {
88        request_id,
89        success: true,
90        data: Some(data),
91        error: None,
92    }
93}
94
95pub fn event_envelope(event: PersistedEvent) -> ServerEnvelope {
96    ServerEnvelope::Event {
97        seq: event.seq,
98        event_type: event.event_type,
99        runtime_id: event.runtime_id,
100        thread_id: event.thread_id,
101        payload: event.payload,
102    }
103}