//! JSON-RPC wire envelopes used by exec-server. //! //! Exec-server uses the Codex JSON-RPC dialect, which omits the //! `"jsonrpc": "2.0"` field on the wire. use std::fmt; use codex_protocol::protocol::W3cTraceContext; use serde::Deserialize; use serde::Serialize; pub const JSONRPC_VERSION: &str = "2.0"; #[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Deserialize, Serialize, Hash, Eq)] #[serde(untagged)] pub enum RequestId { String(String), Integer(i64), } impl fmt::Display for RequestId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::String(value) => f.write_str(value), Self::Integer(value) => write!(f, "{value}"), } } } pub type Result = serde_json::Value; /// Any valid exec-server JSON-RPC object that can be decoded from or encoded onto the wire. #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] #[serde(untagged)] pub enum JSONRPCMessage { Request(JSONRPCRequest), Notification(JSONRPCNotification), Response(JSONRPCResponse), Error(JSONRPCError), } /// A request that expects a response. #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct JSONRPCRequest { pub id: RequestId, pub method: String, #[serde(default, skip_serializing_if = "Option::is_none")] pub params: Option, #[serde(default, skip_serializing_if = "Option::is_none")] pub trace: Option, } /// A notification that does not expect a response. #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct JSONRPCNotification { pub method: String, #[serde(default, skip_serializing_if = "Option::is_none")] pub params: Option, } /// A successful response to a request. #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct JSONRPCResponse { pub id: RequestId, pub result: Result, } /// A response indicating that a request failed. #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct JSONRPCError { pub error: JSONRPCErrorError, pub id: RequestId, } #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct JSONRPCErrorError { pub code: i64, #[serde(default, skip_serializing_if = "Option::is_none")] pub data: Option, pub message: String, }