Skip to main content

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