systemprompt_models/events/
a2a_event.rs1use 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#[derive(Debug, Clone, Copy)]
94pub struct A2AEventBuilder;
95
96impl A2AEventBuilder {
97 pub fn task_submitted(
98 task_id: TaskId,
99 context_id: ContextId,
100 agent_name: String,
101 input: Option<serde_json::Value>,
102 ) -> A2AEvent {
103 A2AEvent::TaskSubmitted {
104 timestamp: Utc::now(),
105 payload: TaskSubmittedPayload {
106 task_id,
107 context_id,
108 agent_name,
109 input,
110 },
111 }
112 }
113
114 pub fn task_status_update(
115 task_id: TaskId,
116 context_id: ContextId,
117 state: TaskState,
118 message: Option<String>,
119 ) -> A2AEvent {
120 A2AEvent::TaskStatusUpdate {
121 timestamp: Utc::now(),
122 payload: TaskStatusUpdatePayload {
123 task_id,
124 context_id,
125 state,
126 message,
127 },
128 }
129 }
130
131 pub fn artifact_created(
132 task_id: TaskId,
133 context_id: ContextId,
134 artifact: Artifact,
135 ) -> A2AEvent {
136 A2AEvent::ArtifactCreated {
137 timestamp: Utc::now(),
138 payload: Box::new(ArtifactCreatedPayload {
139 task_id,
140 context_id,
141 artifact,
142 }),
143 }
144 }
145
146 pub fn artifact_updated(payload: ArtifactUpdatedPayload) -> A2AEvent {
147 A2AEvent::ArtifactUpdated {
148 timestamp: Utc::now(),
149 payload,
150 }
151 }
152
153 pub fn agent_message(
154 task_id: TaskId,
155 context_id: ContextId,
156 message_id: MessageId,
157 content: String,
158 ) -> A2AEvent {
159 A2AEvent::AgentMessage {
160 timestamp: Utc::now(),
161 payload: AgentMessagePayload {
162 task_id,
163 context_id,
164 message_id,
165 content,
166 },
167 }
168 }
169
170 pub fn input_required(task_id: TaskId, context_id: ContextId, prompt: String) -> A2AEvent {
171 A2AEvent::InputRequired {
172 timestamp: Utc::now(),
173 payload: InputRequiredPayload {
174 task_id,
175 context_id,
176 prompt,
177 },
178 }
179 }
180
181 pub fn auth_required(task_id: TaskId, context_id: ContextId, auth_url: String) -> A2AEvent {
182 A2AEvent::AuthRequired {
183 timestamp: Utc::now(),
184 payload: AuthRequiredPayload {
185 task_id,
186 context_id,
187 auth_url,
188 },
189 }
190 }
191
192 pub fn json_rpc_response(id: serde_json::Value, result: serde_json::Value) -> A2AEvent {
193 A2AEvent::JsonRpcResponse {
194 timestamp: Utc::now(),
195 payload: JsonRpcResponsePayload { id, result },
196 }
197 }
198
199 pub fn json_rpc_error(
200 id: serde_json::Value,
201 code: i32,
202 message: String,
203 data: Option<serde_json::Value>,
204 ) -> A2AEvent {
205 A2AEvent::JsonRpcError {
206 timestamp: Utc::now(),
207 payload: JsonRpcErrorPayload {
208 id,
209 code,
210 message,
211 data,
212 },
213 }
214 }
215}