codex-mobile-wire 0.3.7

Shared wire protocol types for codex-mobile rust components.
Documentation
use codex_mobile_contracts::{
    ApiError, DirectoryBookmarkRecord, DirectoryHistoryRecord, PendingServerRequestRecord,
    RuntimeStatusSnapshot, RuntimeSummary,
};
use serde::{Deserialize, Serialize};
use serde_json::Value;

#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct PersistedEvent {
    pub seq: i64,
    pub event_type: String,
    pub runtime_id: Option<String>,
    pub thread_id: Option<String>,
    pub payload: Value,
    pub created_at_ms: i64,
}

#[derive(Debug, Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum ClientEnvelope {
    Hello {
        device_id: String,
        last_ack_seq: Option<i64>,
    },
    Request {
        request_id: String,
        action: String,
        #[serde(default)]
        payload: Value,
    },
    AckEvents {
        last_seq: i64,
    },
    Ping,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "kind")]
pub enum ServerEnvelope {
    #[serde(rename = "hello")]
    Hello {
        #[serde(rename = "bridgeVersion")]
        bridge_version: String,
        #[serde(rename = "protocolVersion")]
        protocol_version: i32,
        runtime: Box<RuntimeStatusSnapshot>,
        runtimes: Vec<RuntimeSummary>,
        #[serde(rename = "directoryBookmarks")]
        directory_bookmarks: Vec<DirectoryBookmarkRecord>,
        #[serde(rename = "directoryHistory")]
        directory_history: Vec<DirectoryHistoryRecord>,
        #[serde(rename = "pending_requests")]
        pending_requests: Vec<PendingServerRequestRecord>,
    },
    #[serde(rename = "response")]
    Response {
        #[serde(rename = "request_id")]
        request_id: String,
        success: bool,
        #[serde(skip_serializing_if = "Option::is_none")]
        data: Option<Value>,
        #[serde(skip_serializing_if = "Option::is_none")]
        error: Option<ApiError>,
    },
    #[serde(rename = "event")]
    Event {
        seq: i64,
        #[serde(rename = "event_type")]
        event_type: String,
        #[serde(skip_serializing_if = "Option::is_none")]
        #[serde(rename = "runtime_id")]
        runtime_id: Option<String>,
        #[serde(skip_serializing_if = "Option::is_none")]
        #[serde(rename = "thread_id")]
        thread_id: Option<String>,
        payload: Value,
    },
    #[serde(rename = "pong")]
    Pong {
        #[serde(rename = "server_time_ms")]
        server_time_ms: i64,
    },
}

pub fn ok_response(request_id: String, data: Value) -> ServerEnvelope {
    ServerEnvelope::Response {
        request_id,
        success: true,
        data: Some(data),
        error: None,
    }
}

pub fn event_envelope(event: PersistedEvent) -> ServerEnvelope {
    ServerEnvelope::Event {
        seq: event.seq,
        event_type: event.event_type,
        runtime_id: event.runtime_id,
        thread_id: event.thread_id,
        payload: event.payload,
    }
}