Skip to main content

a2a_rust/
jsonrpc.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4/// Required JSON-RPC version marker.
5pub const JSONRPC_VERSION: &str = "2.0";
6/// Required A2A protocol version header value.
7pub const PROTOCOL_VERSION: &str = "1.0";
8
9/// JSON-RPC parse error code.
10pub const PARSE_ERROR: i32 = -32700;
11/// JSON-RPC invalid request error code.
12pub const INVALID_REQUEST: i32 = -32600;
13/// JSON-RPC method not found error code.
14pub const METHOD_NOT_FOUND: i32 = -32601;
15/// JSON-RPC invalid params error code.
16pub const INVALID_PARAMS: i32 = -32602;
17/// JSON-RPC internal error code.
18pub const INTERNAL_ERROR: i32 = -32603;
19
20/// A2A task-not-found error code.
21pub const TASK_NOT_FOUND: i32 = -32001;
22/// A2A task-not-cancelable error code.
23pub const TASK_NOT_CANCELABLE: i32 = -32002;
24/// A2A push-notifications-not-supported error code.
25pub const PUSH_NOTIFICATION_NOT_SUPPORTED: i32 = -32003;
26/// A2A unsupported-operation error code.
27pub const UNSUPPORTED_OPERATION: i32 = -32004;
28/// A2A unsupported-content-type error code.
29pub const CONTENT_TYPE_NOT_SUPPORTED: i32 = -32005;
30/// A2A invalid-agent-response error code.
31pub const INVALID_AGENT_RESPONSE: i32 = -32006;
32/// A2A extended-agent-card-not-configured error code.
33pub const EXTENDED_AGENT_CARD_NOT_CONFIGURED: i32 = -32007;
34/// A2A extension-support-required error code.
35pub const EXTENSION_SUPPORT_REQUIRED: i32 = -32008;
36/// A2A version-not-supported error code.
37pub const VERSION_NOT_SUPPORTED: i32 = -32009;
38
39/// JSON-RPC method name for `SendMessage`.
40pub const METHOD_SEND_MESSAGE: &str = "SendMessage";
41/// JSON-RPC method name for `SendStreamingMessage`.
42pub const METHOD_SEND_STREAMING_MESSAGE: &str = "SendStreamingMessage";
43/// JSON-RPC method name for `GetTask`.
44pub const METHOD_GET_TASK: &str = "GetTask";
45/// JSON-RPC method name for `ListTasks`.
46pub const METHOD_LIST_TASKS: &str = "ListTasks";
47/// JSON-RPC method name for `CancelTask`.
48pub const METHOD_CANCEL_TASK: &str = "CancelTask";
49/// JSON-RPC method name for `SubscribeToTask`.
50pub const METHOD_SUBSCRIBE_TO_TASK: &str = "SubscribeToTask";
51/// JSON-RPC method name for `CreateTaskPushNotificationConfig`.
52pub const METHOD_CREATE_TASK_PUSH_NOTIFICATION_CONFIG: &str = "CreateTaskPushNotificationConfig";
53/// JSON-RPC method name for `GetTaskPushNotificationConfig`.
54pub const METHOD_GET_TASK_PUSH_NOTIFICATION_CONFIG: &str = "GetTaskPushNotificationConfig";
55/// JSON-RPC method name for `ListTaskPushNotificationConfigs`.
56pub const METHOD_LIST_TASK_PUSH_NOTIFICATION_CONFIGS: &str = "ListTaskPushNotificationConfigs";
57/// JSON-RPC method name for `DeleteTaskPushNotificationConfig`.
58pub const METHOD_DELETE_TASK_PUSH_NOTIFICATION_CONFIG: &str = "DeleteTaskPushNotificationConfig";
59/// JSON-RPC method name for `GetExtendedAgentCard`.
60pub const METHOD_GET_EXTENDED_AGENT_CARD: &str = "GetExtendedAgentCard";
61
62/// JSON-RPC 2.0 request envelope.
63#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct JsonRpcRequest {
65    #[serde(default = "jsonrpc_version")]
66    /// JSON-RPC protocol version, always `"2.0"`.
67    pub jsonrpc: String,
68    /// Method name to invoke on the remote peer.
69    pub method: String,
70    #[serde(default, skip_serializing_if = "Option::is_none")]
71    /// Optional method parameters encoded as a JSON object.
72    pub params: Option<Value>,
73    /// Request identifier echoed by the peer in the response.
74    pub id: JsonRpcId,
75}
76
77/// JSON-RPC 2.0 response envelope.
78#[derive(Debug, Clone, Serialize, Deserialize)]
79pub struct JsonRpcResponse {
80    #[serde(default = "jsonrpc_version")]
81    /// JSON-RPC protocol version, always `"2.0"`.
82    pub jsonrpc: String,
83    #[serde(skip_serializing_if = "Option::is_none")]
84    /// Successful result payload.
85    pub result: Option<Value>,
86    #[serde(skip_serializing_if = "Option::is_none")]
87    /// Error payload returned when the call fails.
88    pub error: Option<JsonRpcError>,
89    /// Response identifier copied from the request.
90    pub id: JsonRpcId,
91}
92
93/// JSON-RPC 2.0 error object.
94#[derive(Debug, Clone, Serialize, Deserialize)]
95pub struct JsonRpcError {
96    /// Numeric error code.
97    pub code: i32,
98    /// Human-readable error message.
99    pub message: String,
100    #[serde(default, skip_serializing_if = "Option::is_none")]
101    /// Optional protocol-specific error data.
102    pub data: Option<Value>,
103}
104
105/// Allowed JSON-RPC request/response identifier forms.
106#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
107#[serde(untagged)]
108pub enum JsonRpcId {
109    /// String request identifier.
110    String(String),
111    /// Numeric request identifier.
112    Number(i64),
113    /// Explicit null identifier.
114    Null,
115}
116
117fn jsonrpc_version() -> String {
118    JSONRPC_VERSION.to_owned()
119}
120
121#[cfg(test)]
122mod tests {
123    use super::JsonRpcId;
124
125    #[test]
126    fn jsonrpc_id_null_serializes_as_null() {
127        let json = serde_json::to_string(&JsonRpcId::Null).expect("id should serialize");
128        assert_eq!(json, "null");
129
130        let round_trip: JsonRpcId = serde_json::from_str("null").expect("id should deserialize");
131        assert!(matches!(round_trip, JsonRpcId::Null));
132    }
133}