systemprompt_models/a2a/
task.rs1use super::artifact::Artifact;
7use super::message::Message;
8use super::task_metadata::TaskMetadata;
9use serde::{Deserialize, Serialize};
10
11use crate::errors::ParseEnumError;
12use systemprompt_identifiers::{ContextId, TaskId};
13
14#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
15#[serde(rename_all = "camelCase")]
16pub struct Task {
17 pub id: TaskId,
18 pub context_id: ContextId,
19 pub status: TaskStatus,
20 pub history: Option<Vec<Message>>,
21 pub artifacts: Option<Vec<Artifact>>,
22 pub metadata: Option<TaskMetadata>,
23 #[serde(skip_serializing_if = "Option::is_none")]
24 pub created_at: Option<chrono::DateTime<chrono::Utc>>,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 pub last_modified: Option<chrono::DateTime<chrono::Utc>>,
27}
28
29impl Default for Task {
30 fn default() -> Self {
31 let now = chrono::Utc::now();
32 Self {
33 id: TaskId::generate(),
34 context_id: ContextId::generate(),
35 status: TaskStatus::default(),
36 history: None,
37 artifacts: None,
38 metadata: None,
39 created_at: Some(now),
40 last_modified: Some(now),
41 }
42 }
43}
44
45#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
46pub struct TaskStatus {
47 pub state: TaskState,
48 pub message: Option<Message>,
49 pub timestamp: Option<chrono::DateTime<chrono::Utc>>,
50}
51
52impl Default for TaskStatus {
53 fn default() -> Self {
54 Self {
55 state: TaskState::Submitted,
56 message: None,
57 timestamp: None,
58 }
59 }
60}
61
62#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
63pub enum TaskState {
64 #[serde(rename = "TASK_STATE_PENDING")]
65 Pending,
66 #[serde(rename = "TASK_STATE_SUBMITTED")]
67 Submitted,
68 #[serde(rename = "TASK_STATE_WORKING")]
69 Working,
70 #[serde(rename = "TASK_STATE_COMPLETED")]
71 Completed,
72 #[serde(rename = "TASK_STATE_FAILED")]
73 Failed,
74 #[serde(rename = "TASK_STATE_CANCELED")]
75 Canceled,
76 #[serde(rename = "TASK_STATE_REJECTED")]
77 Rejected,
78 #[serde(rename = "TASK_STATE_INPUT_REQUIRED")]
79 InputRequired,
80 #[serde(rename = "TASK_STATE_AUTH_REQUIRED")]
81 AuthRequired,
82 #[serde(rename = "TASK_STATE_UNKNOWN")]
83 Unknown,
84}
85
86impl TaskState {
87 pub const fn as_str(self) -> &'static str {
88 match self {
89 Self::Pending => "TASK_STATE_PENDING",
90 Self::Submitted => "TASK_STATE_SUBMITTED",
91 Self::Working => "TASK_STATE_WORKING",
92 Self::Completed => "TASK_STATE_COMPLETED",
93 Self::Failed => "TASK_STATE_FAILED",
94 Self::Canceled => "TASK_STATE_CANCELED",
95 Self::Rejected => "TASK_STATE_REJECTED",
96 Self::InputRequired => "TASK_STATE_INPUT_REQUIRED",
97 Self::AuthRequired => "TASK_STATE_AUTH_REQUIRED",
98 Self::Unknown => "TASK_STATE_UNKNOWN",
99 }
100 }
101
102 pub const fn is_terminal(&self) -> bool {
103 matches!(
104 self,
105 Self::Completed | Self::Failed | Self::Canceled | Self::Rejected
106 )
107 }
108
109 pub const fn can_transition_to(&self, target: &Self) -> bool {
110 if self.is_terminal() {
111 return false;
112 }
113 match self {
114 Self::Pending => matches!(target, Self::Submitted),
115 Self::Submitted => matches!(
116 target,
117 Self::Working
118 | Self::Completed
119 | Self::Failed
120 | Self::Canceled
121 | Self::Rejected
122 | Self::AuthRequired
123 ),
124 Self::Working => matches!(
125 target,
126 Self::Completed | Self::Failed | Self::Canceled | Self::InputRequired
127 ),
128 Self::InputRequired => matches!(
129 target,
130 Self::Working | Self::Completed | Self::Failed | Self::Canceled
131 ),
132 Self::AuthRequired => matches!(target, Self::Working | Self::Failed | Self::Canceled),
133 _ => false,
134 }
135 }
136}
137
138impl std::str::FromStr for TaskState {
139 type Err = ParseEnumError;
140
141 fn from_str(s: &str) -> Result<Self, Self::Err> {
142 match s {
143 "TASK_STATE_PENDING" | "pending" => Ok(Self::Pending),
144 "TASK_STATE_SUBMITTED" | "submitted" => Ok(Self::Submitted),
145 "TASK_STATE_WORKING" | "working" => Ok(Self::Working),
146 "TASK_STATE_COMPLETED" | "completed" => Ok(Self::Completed),
147 "TASK_STATE_FAILED" | "failed" => Ok(Self::Failed),
148 "TASK_STATE_CANCELED" | "canceled" => Ok(Self::Canceled),
149 "TASK_STATE_REJECTED" | "rejected" => Ok(Self::Rejected),
150 "TASK_STATE_INPUT_REQUIRED" | "input-required" => Ok(Self::InputRequired),
151 "TASK_STATE_AUTH_REQUIRED" | "auth-required" => Ok(Self::AuthRequired),
152 "TASK_STATE_UNKNOWN" | "unknown" => Ok(Self::Unknown),
153 _ => Err(ParseEnumError::new("task state", s)),
154 }
155 }
156}