systemprompt_models/events/
a2a_event.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use systemprompt_identifiers::{ContextId, MessageId, TaskId};
4
5use super::a2a_event_type::A2AEventType;
6use super::payloads::a2a::{
7    AgentMessagePayload, ArtifactCreatedPayload, ArtifactUpdatedPayload, AuthRequiredPayload,
8    InputRequiredPayload, JsonRpcErrorPayload, JsonRpcResponsePayload, TaskStatusUpdatePayload,
9    TaskSubmittedPayload,
10};
11use crate::a2a::{Artifact, TaskState};
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
14#[serde(tag = "type", rename_all = "SCREAMING_SNAKE_CASE")]
15pub enum A2AEvent {
16    TaskSubmitted {
17        timestamp: DateTime<Utc>,
18        #[serde(flatten)]
19        payload: TaskSubmittedPayload,
20    },
21    TaskStatusUpdate {
22        timestamp: DateTime<Utc>,
23        #[serde(flatten)]
24        payload: TaskStatusUpdatePayload,
25    },
26    ArtifactCreated {
27        timestamp: DateTime<Utc>,
28        #[serde(flatten)]
29        payload: Box<ArtifactCreatedPayload>,
30    },
31    ArtifactUpdated {
32        timestamp: DateTime<Utc>,
33        #[serde(flatten)]
34        payload: ArtifactUpdatedPayload,
35    },
36    AgentMessage {
37        timestamp: DateTime<Utc>,
38        #[serde(flatten)]
39        payload: AgentMessagePayload,
40    },
41    InputRequired {
42        timestamp: DateTime<Utc>,
43        #[serde(flatten)]
44        payload: InputRequiredPayload,
45    },
46    AuthRequired {
47        timestamp: DateTime<Utc>,
48        #[serde(flatten)]
49        payload: AuthRequiredPayload,
50    },
51    JsonRpcResponse {
52        timestamp: DateTime<Utc>,
53        #[serde(flatten)]
54        payload: JsonRpcResponsePayload,
55    },
56    JsonRpcError {
57        timestamp: DateTime<Utc>,
58        #[serde(flatten)]
59        payload: JsonRpcErrorPayload,
60    },
61}
62
63impl A2AEvent {
64    pub const fn event_type(&self) -> A2AEventType {
65        match self {
66            Self::TaskSubmitted { .. } => A2AEventType::TaskSubmitted,
67            Self::TaskStatusUpdate { .. } => A2AEventType::TaskStatusUpdate,
68            Self::ArtifactCreated { .. } => A2AEventType::ArtifactCreated,
69            Self::ArtifactUpdated { .. } => A2AEventType::ArtifactUpdated,
70            Self::AgentMessage { .. } => A2AEventType::AgentMessage,
71            Self::InputRequired { .. } => A2AEventType::InputRequired,
72            Self::AuthRequired { .. } => A2AEventType::AuthRequired,
73            Self::JsonRpcResponse { .. } => A2AEventType::JsonRpcResponse,
74            Self::JsonRpcError { .. } => A2AEventType::JsonRpcError,
75        }
76    }
77
78    pub const fn timestamp(&self) -> DateTime<Utc> {
79        match self {
80            Self::TaskSubmitted { timestamp, .. }
81            | Self::TaskStatusUpdate { timestamp, .. }
82            | Self::ArtifactCreated { timestamp, .. }
83            | Self::ArtifactUpdated { timestamp, .. }
84            | Self::AgentMessage { timestamp, .. }
85            | Self::InputRequired { timestamp, .. }
86            | Self::AuthRequired { timestamp, .. }
87            | Self::JsonRpcResponse { timestamp, .. }
88            | Self::JsonRpcError { timestamp, .. } => *timestamp,
89        }
90    }
91
92}
93
94#[derive(Debug, Clone, Copy)]
95pub struct A2AEventBuilder;
96
97impl A2AEventBuilder {
98    pub fn task_submitted(
99        task_id: TaskId,
100        context_id: ContextId,
101        agent_name: String,
102        input: Option<serde_json::Value>,
103    ) -> A2AEvent {
104        A2AEvent::TaskSubmitted {
105            timestamp: Utc::now(),
106            payload: TaskSubmittedPayload {
107                task_id,
108                context_id,
109                agent_name,
110                input,
111            },
112        }
113    }
114
115    pub fn task_status_update(
116        task_id: TaskId,
117        context_id: ContextId,
118        state: TaskState,
119        message: Option<String>,
120    ) -> A2AEvent {
121        A2AEvent::TaskStatusUpdate {
122            timestamp: Utc::now(),
123            payload: TaskStatusUpdatePayload {
124                task_id,
125                context_id,
126                state,
127                message,
128            },
129        }
130    }
131
132    pub fn artifact_created(
133        task_id: TaskId,
134        context_id: ContextId,
135        artifact: Artifact,
136    ) -> A2AEvent {
137        A2AEvent::ArtifactCreated {
138            timestamp: Utc::now(),
139            payload: Box::new(ArtifactCreatedPayload {
140                task_id,
141                context_id,
142                artifact,
143            }),
144        }
145    }
146
147    pub fn artifact_updated(payload: ArtifactUpdatedPayload) -> A2AEvent {
148        A2AEvent::ArtifactUpdated {
149            timestamp: Utc::now(),
150            payload,
151        }
152    }
153
154    pub fn agent_message(
155        task_id: TaskId,
156        context_id: ContextId,
157        message_id: MessageId,
158        content: String,
159    ) -> A2AEvent {
160        A2AEvent::AgentMessage {
161            timestamp: Utc::now(),
162            payload: AgentMessagePayload {
163                task_id,
164                context_id,
165                message_id,
166                content,
167            },
168        }
169    }
170
171    pub fn input_required(task_id: TaskId, context_id: ContextId, prompt: String) -> A2AEvent {
172        A2AEvent::InputRequired {
173            timestamp: Utc::now(),
174            payload: InputRequiredPayload {
175                task_id,
176                context_id,
177                prompt,
178            },
179        }
180    }
181
182    pub fn auth_required(task_id: TaskId, context_id: ContextId, auth_url: String) -> A2AEvent {
183        A2AEvent::AuthRequired {
184            timestamp: Utc::now(),
185            payload: AuthRequiredPayload {
186                task_id,
187                context_id,
188                auth_url,
189            },
190        }
191    }
192
193    pub fn json_rpc_response(id: serde_json::Value, result: serde_json::Value) -> A2AEvent {
194        A2AEvent::JsonRpcResponse {
195            timestamp: Utc::now(),
196            payload: JsonRpcResponsePayload { id, result },
197        }
198    }
199
200    pub fn json_rpc_error(
201        id: serde_json::Value,
202        code: i32,
203        message: String,
204        data: Option<serde_json::Value>,
205    ) -> A2AEvent {
206        A2AEvent::JsonRpcError {
207            timestamp: Utc::now(),
208            payload: JsonRpcErrorPayload {
209                id,
210                code,
211                message,
212                data,
213            },
214        }
215    }
216}