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
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}