use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JsonRpcRequest {
pub jsonrpc: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<Value>,
pub method: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub params: Option<Value>,
#[serde(rename = "sessionId", skip_serializing_if = "Option::is_none")]
pub session_id: Option<String>,
#[serde(rename = "agentId", skip_serializing_if = "Option::is_none")]
pub agent_id: Option<String>,
#[serde(rename = "_ext", skip_serializing_if = "Option::is_none")]
pub extensions: Option<Value>,
}
impl JsonRpcRequest {
pub fn new(method: impl Into<String>, params: Option<Value>) -> Self {
Self {
jsonrpc: "2.0".to_string(),
id: Some(Value::String(uuid::Uuid::new_v4().to_string())),
method: method.into(),
params,
session_id: None,
agent_id: None,
extensions: None,
}
}
pub fn notification(method: impl Into<String>, params: Option<Value>) -> Self {
Self {
jsonrpc: "2.0".to_string(),
id: None,
method: method.into(),
params,
session_id: None,
agent_id: None,
extensions: None,
}
}
pub fn with_session_id(mut self, session_id: impl Into<String>) -> Self {
self.session_id = Some(session_id.into());
self
}
pub fn with_agent_id(mut self, agent_id: impl Into<String>) -> Self {
self.agent_id = Some(agent_id.into());
self
}
pub fn with_extensions(mut self, extensions: Value) -> Self {
self.extensions = Some(extensions);
self
}
pub fn is_notification(&self) -> bool {
self.id.is_none()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JsonRpcError {
pub code: i32,
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<Value>,
}
impl JsonRpcError {
pub fn parse_error() -> Self {
Self {
code: -32700,
message: "Parse error".to_string(),
data: None,
}
}
pub fn invalid_request() -> Self {
Self {
code: -32600,
message: "Invalid Request".to_string(),
data: None,
}
}
pub fn method_not_found() -> Self {
Self {
code: -32601,
message: "Method not found".to_string(),
data: None,
}
}
pub fn internal_error() -> Self {
Self {
code: -32603,
message: "Internal error".to_string(),
data: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JsonRpcResponse {
pub jsonrpc: String,
pub id: Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub result: Option<Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<JsonRpcError>,
#[serde(rename = "sessionId", skip_serializing_if = "Option::is_none")]
pub session_id: Option<String>,
#[serde(rename = "_ext", skip_serializing_if = "Option::is_none")]
pub extensions: Option<Value>,
}
impl JsonRpcResponse {
pub fn success(id: Value, result: Value) -> Self {
Self {
jsonrpc: "2.0".to_string(),
id,
result: Some(result),
error: None,
session_id: None,
extensions: None,
}
}
pub fn error(id: Value, error: JsonRpcError) -> Self {
Self {
jsonrpc: "2.0".to_string(),
id,
result: None,
error: Some(error),
session_id: None,
extensions: None,
}
}
pub fn is_error(&self) -> bool {
self.error.is_some()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum JsonRpcMessage {
Request(JsonRpcRequest),
Response(JsonRpcResponse),
}
impl JsonRpcMessage {
pub fn parse(json: &str) -> Result<Self, serde_json::Error> {
serde_json::from_str(json)
}
pub fn to_json(&self) -> Result<String, serde_json::Error> {
serde_json::to_string(self)
}
pub fn id(&self) -> Option<&Value> {
match self {
Self::Request(req) => req.id.as_ref(),
Self::Response(res) => Some(&res.id),
}
}
}