Skip to main content

a2a_rs/port/
task_manager.rs

1//! Task management port definitions
2
3#[cfg(feature = "server")]
4use async_trait::async_trait;
5
6use crate::{
7    Message,
8    domain::{
9        A2AError, DeleteTaskPushNotificationConfigParams, GetTaskPushNotificationConfigParams,
10        ListTaskPushNotificationConfigParams, ListTasksParams, ListTasksResult, Task, TaskIdParams,
11        TaskPushNotificationConfig, TaskQueryParams, TaskState,
12    },
13};
14
15/// A trait for managing task lifecycle and operations
16pub trait TaskManager {
17    /// Create a new task
18    fn create_task(&self, task_id: &str, context_id: &str) -> Result<Task, A2AError>;
19
20    /// Get a task by ID with optional history
21    fn get_task(&self, task_id: &str, history_length: Option<u32>) -> Result<Task, A2AError>;
22
23    /// Update task status with an optional message to add to history
24    fn update_task_status(
25        &self,
26        task_id: &str,
27        state: TaskState,
28        message: Option<Message>,
29    ) -> Result<Task, A2AError>;
30
31    /// Cancel a task
32    fn cancel_task(&self, task_id: &str) -> Result<Task, A2AError>;
33
34    /// Check if a task exists
35    fn task_exists(&self, task_id: &str) -> Result<bool, A2AError>;
36
37    /// List tasks with optional filtering
38    fn list_tasks(
39        &self,
40        _context_id: Option<&str>,
41        _limit: Option<u32>,
42    ) -> Result<Vec<Task>, A2AError> {
43        // Default implementation - can be overridden
44        // Basic implementation that doesn't support filtering
45        Err(A2AError::UnsupportedOperation(
46            "Task listing not implemented".to_string(),
47        ))
48    }
49
50    /// Get task metadata
51    fn get_task_metadata(
52        &self,
53        task_id: &str,
54    ) -> Result<serde_json::Map<String, serde_json::Value>, A2AError> {
55        let task = self.get_task(task_id, None)?;
56        Ok(task.metadata.unwrap_or_default())
57    }
58
59    /// Validate task parameters
60    fn validate_task_params(&self, params: &TaskQueryParams) -> Result<(), A2AError> {
61        if params.id.trim().is_empty() {
62            return Err(A2AError::ValidationError {
63                field: "task_id".to_string(),
64                message: "Task ID cannot be empty".to_string(),
65            });
66        }
67
68        if let Some(history_length) = params.history_length {
69            if history_length > 1000 {
70                return Err(A2AError::ValidationError {
71                    field: "history_length".to_string(),
72                    message: "History length cannot exceed 1000".to_string(),
73                });
74            }
75        }
76
77        Ok(())
78    }
79}
80
81#[cfg(feature = "server")]
82#[async_trait]
83/// An async trait for managing task lifecycle and operations
84pub trait AsyncTaskManager: Send + Sync {
85    /// Create a new task
86    async fn create_task(&self, task_id: &str, context_id: &str) -> Result<Task, A2AError>;
87
88    /// Get a task by ID with optional history
89    async fn get_task(&self, task_id: &str, history_length: Option<u32>) -> Result<Task, A2AError>;
90
91    /// Update task status with an optional message to add to history
92    async fn update_task_status(
93        &self,
94        task_id: &str,
95        state: TaskState,
96        message: Option<Message>,
97    ) -> Result<Task, A2AError>;
98
99    /// Cancel a task
100    async fn cancel_task(&self, task_id: &str) -> Result<Task, A2AError>;
101
102    /// Check if a task exists
103    async fn task_exists(&self, task_id: &str) -> Result<bool, A2AError>;
104
105    /// List tasks with optional filtering
106    async fn list_tasks(
107        &self,
108        _context_id: Option<&str>,
109        _limit: Option<u32>,
110    ) -> Result<Vec<Task>, A2AError> {
111        // Default implementation - can be overridden
112        // Basic implementation that doesn't support filtering
113        Err(A2AError::UnsupportedOperation(
114            "Task listing not implemented".to_string(),
115        ))
116    }
117
118    /// Get task metadata
119    async fn get_task_metadata(
120        &self,
121        task_id: &str,
122    ) -> Result<serde_json::Map<String, serde_json::Value>, A2AError> {
123        let task = self.get_task(task_id, None).await?;
124        Ok(task.metadata.unwrap_or_default())
125    }
126
127    /// Validate task parameters
128    async fn validate_task_params(&self, params: &TaskQueryParams) -> Result<(), A2AError> {
129        if params.id.trim().is_empty() {
130            return Err(A2AError::ValidationError {
131                field: "task_id".to_string(),
132                message: "Task ID cannot be empty".to_string(),
133            });
134        }
135
136        if let Some(history_length) = params.history_length {
137            if history_length > 1000 {
138                return Err(A2AError::ValidationError {
139                    field: "history_length".to_string(),
140                    message: "History length cannot exceed 1000".to_string(),
141                });
142            }
143        }
144
145        Ok(())
146    }
147
148    /// Get task with validation
149    async fn get_task_validated(&self, params: &TaskQueryParams) -> Result<Task, A2AError> {
150        self.validate_task_params(params).await?;
151        self.get_task(&params.id, params.history_length).await
152    }
153
154    /// Cancel task with validation
155    async fn cancel_task_validated(&self, params: &TaskIdParams) -> Result<Task, A2AError> {
156        if params.id.trim().is_empty() {
157            return Err(A2AError::ValidationError {
158                field: "task_id".to_string(),
159                message: "Task ID cannot be empty".to_string(),
160            });
161        }
162
163        self.cancel_task(&params.id).await
164    }
165
166    // ===== v0.3.0 New Methods =====
167
168    /// List tasks with comprehensive filtering and pagination (v0.3.0)
169    async fn list_tasks_v3(&self, _params: &ListTasksParams) -> Result<ListTasksResult, A2AError> {
170        // Default implementation returns unsupported error
171        Err(A2AError::UnsupportedOperation(
172            "Task listing with pagination not implemented".to_string(),
173        ))
174    }
175
176    /// Get push notification config by ID (v0.3.0)
177    async fn get_push_notification_config(
178        &self,
179        _params: &GetTaskPushNotificationConfigParams,
180    ) -> Result<TaskPushNotificationConfig, A2AError> {
181        // Default implementation returns unsupported error
182        Err(A2AError::UnsupportedOperation(
183            "Get push notification config not implemented".to_string(),
184        ))
185    }
186
187    /// List all push notification configs for a task (v0.3.0)
188    async fn list_push_notification_configs(
189        &self,
190        _params: &ListTaskPushNotificationConfigParams,
191    ) -> Result<Vec<TaskPushNotificationConfig>, A2AError> {
192        // Default implementation returns unsupported error
193        Err(A2AError::UnsupportedOperation(
194            "List push notification configs not implemented".to_string(),
195        ))
196    }
197
198    /// Delete a specific push notification config (v0.3.0)
199    async fn delete_push_notification_config(
200        &self,
201        _params: &DeleteTaskPushNotificationConfigParams,
202    ) -> Result<(), A2AError> {
203        // Default implementation returns unsupported error
204        Err(A2AError::UnsupportedOperation(
205            "Delete push notification config not implemented".to_string(),
206        ))
207    }
208}