1use serde::{Deserialize, Serialize};
8use serde_json::Value;
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct JsonRpcRequest {
13 pub jsonrpc: String,
14 #[serde(skip_serializing_if = "Option::is_none")]
15 pub id: Option<Value>,
16 pub method: String,
17 #[serde(default, skip_serializing_if = "Option::is_none")]
18 pub params: Option<Value>,
19 #[serde(rename = "sessionId", skip_serializing_if = "Option::is_none")]
20 pub session_id: Option<String>,
21 #[serde(rename = "agentId", skip_serializing_if = "Option::is_none")]
22 pub agent_id: Option<String>,
23 #[serde(rename = "_ext", skip_serializing_if = "Option::is_none")]
24 pub extensions: Option<Value>,
25}
26
27impl JsonRpcRequest {
28 pub fn new(method: impl Into<String>, params: Option<Value>) -> Self {
30 Self {
31 jsonrpc: "2.0".to_string(),
32 id: Some(Value::String(uuid::Uuid::new_v4().to_string())),
33 method: method.into(),
34 params,
35 session_id: None,
36 agent_id: None,
37 extensions: None,
38 }
39 }
40
41 pub fn notification(method: impl Into<String>, params: Option<Value>) -> Self {
43 Self {
44 jsonrpc: "2.0".to_string(),
45 id: None,
46 method: method.into(),
47 params,
48 session_id: None,
49 agent_id: None,
50 extensions: None,
51 }
52 }
53
54 pub fn with_session_id(mut self, session_id: impl Into<String>) -> Self {
56 self.session_id = Some(session_id.into());
57 self
58 }
59
60 pub fn with_agent_id(mut self, agent_id: impl Into<String>) -> Self {
62 self.agent_id = Some(agent_id.into());
63 self
64 }
65
66 pub fn with_extensions(mut self, extensions: Value) -> Self {
68 self.extensions = Some(extensions);
69 self
70 }
71
72 pub fn is_notification(&self) -> bool {
74 self.id.is_none()
75 }
76}
77
78#[derive(Debug, Clone, Serialize, Deserialize)]
80pub struct JsonRpcError {
81 pub code: i32,
82 pub message: String,
83 #[serde(skip_serializing_if = "Option::is_none")]
84 pub data: Option<Value>,
85}
86
87impl JsonRpcError {
88 pub fn parse_error() -> Self {
90 Self {
91 code: -32700,
92 message: "Parse error".to_string(),
93 data: None,
94 }
95 }
96
97 pub fn invalid_request() -> Self {
99 Self {
100 code: -32600,
101 message: "Invalid Request".to_string(),
102 data: None,
103 }
104 }
105
106 pub fn method_not_found() -> Self {
108 Self {
109 code: -32601,
110 message: "Method not found".to_string(),
111 data: None,
112 }
113 }
114
115 pub fn internal_error() -> Self {
117 Self {
118 code: -32603,
119 message: "Internal error".to_string(),
120 data: None,
121 }
122 }
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct JsonRpcResponse {
128 pub jsonrpc: String,
129 pub id: Value,
130 #[serde(skip_serializing_if = "Option::is_none")]
131 pub result: Option<Value>,
132 #[serde(skip_serializing_if = "Option::is_none")]
133 pub error: Option<JsonRpcError>,
134 #[serde(rename = "sessionId", skip_serializing_if = "Option::is_none")]
135 pub session_id: Option<String>,
136 #[serde(rename = "_ext", skip_serializing_if = "Option::is_none")]
137 pub extensions: Option<Value>,
138}
139
140impl JsonRpcResponse {
141 pub fn success(id: Value, result: Value) -> Self {
143 Self {
144 jsonrpc: "2.0".to_string(),
145 id,
146 result: Some(result),
147 error: None,
148 session_id: None,
149 extensions: None,
150 }
151 }
152
153 pub fn error(id: Value, error: JsonRpcError) -> Self {
155 Self {
156 jsonrpc: "2.0".to_string(),
157 id,
158 result: None,
159 error: Some(error),
160 session_id: None,
161 extensions: None,
162 }
163 }
164
165 pub fn is_error(&self) -> bool {
167 self.error.is_some()
168 }
169}
170
171#[derive(Debug, Clone, Serialize, Deserialize)]
173#[serde(untagged)]
174pub enum JsonRpcMessage {
175 Request(JsonRpcRequest),
176 Response(JsonRpcResponse),
177}
178
179impl JsonRpcMessage {
180 pub fn parse(json: &str) -> Result<Self, serde_json::Error> {
182 serde_json::from_str(json)
183 }
184
185 pub fn to_json(&self) -> Result<String, serde_json::Error> {
187 serde_json::to_string(self)
188 }
189
190 pub fn id(&self) -> Option<&Value> {
192 match self {
193 Self::Request(req) => req.id.as_ref(),
194 Self::Response(res) => Some(&res.id),
195 }
196 }
197}