miyabi_a2a/
task.rs

1//! A2A Task definitions
2
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5
6/// A2A Task - Agent-to-Agent communication task
7///
8/// This represents a task that can be exchanged between agents
9/// for collaborative work. Tasks are stored as GitHub Issues
10/// for persistence and visibility.
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct A2ATask {
13    /// Unique task ID (GitHub Issue number)
14    pub id: u64,
15
16    /// Task title
17    pub title: String,
18
19    /// Task description (markdown)
20    pub description: String,
21
22    /// Task status
23    pub status: TaskStatus,
24
25    /// Task type
26    pub task_type: TaskType,
27
28    /// Assigned agent type (optional)
29    pub agent: Option<String>,
30
31    /// Context ID for filtering related tasks
32    pub context_id: Option<String>,
33
34    /// Priority (0-5, higher = more urgent)
35    pub priority: u8,
36
37    /// Number of retry attempts (for failed tasks)
38    #[serde(default)]
39    pub retry_count: u32,
40
41    /// Created timestamp
42    pub created_at: DateTime<Utc>,
43
44    /// Updated timestamp
45    pub updated_at: DateTime<Utc>,
46
47    /// GitHub Issue URL
48    pub issue_url: String,
49}
50
51/// Task status lifecycle (aligned with A2A Protocol)
52#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
53#[serde(rename_all = "lowercase")]
54pub enum TaskStatus {
55    /// Task submitted, awaiting processing
56    Submitted,
57    /// Task currently being worked on
58    Working,
59    /// Task successfully completed
60    Completed,
61    /// Task failed with errors
62    Failed,
63    /// Task cancelled by user
64    Cancelled,
65}
66
67impl TaskStatus {
68    /// Convert to GitHub label format
69    ///
70    /// # Examples
71    /// ```
72    /// use miyabi_a2a::TaskStatus;
73    ///
74    /// assert_eq!(TaskStatus::Submitted.to_label(), "a2a:submitted");
75    /// assert_eq!(TaskStatus::Working.to_label(), "a2a:working");
76    /// ```
77    pub fn to_label(&self) -> String {
78        format!("a2a:{}", self.to_string().to_lowercase())
79    }
80}
81
82impl std::fmt::Display for TaskStatus {
83    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84        match self {
85            TaskStatus::Submitted => write!(f, "submitted"),
86            TaskStatus::Working => write!(f, "working"),
87            TaskStatus::Completed => write!(f, "completed"),
88            TaskStatus::Failed => write!(f, "failed"),
89            TaskStatus::Cancelled => write!(f, "cancelled"),
90        }
91    }
92}
93
94/// Task type classification
95#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
96#[serde(rename_all = "lowercase")]
97pub enum TaskType {
98    /// Code generation task
99    CodeGeneration,
100    /// Code review task
101    CodeReview,
102    /// Testing task
103    Testing,
104    /// Deployment task
105    Deployment,
106    /// Documentation task
107    Documentation,
108    /// Analysis task
109    Analysis,
110}
111
112impl TaskType {
113    /// Convert to GitHub label format
114    ///
115    /// # Examples
116    /// ```
117    /// use miyabi_a2a::TaskType;
118    ///
119    /// assert_eq!(TaskType::CodeGeneration.to_label(), "a2a:codegen");
120    /// assert_eq!(TaskType::CodeReview.to_label(), "a2a:review");
121    /// ```
122    pub fn to_label(&self) -> String {
123        format!("a2a:{}", self.to_string().to_lowercase())
124    }
125}
126
127impl std::fmt::Display for TaskType {
128    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
129        match self {
130            TaskType::CodeGeneration => write!(f, "codegen"),
131            TaskType::CodeReview => write!(f, "review"),
132            TaskType::Testing => write!(f, "testing"),
133            TaskType::Deployment => write!(f, "deployment"),
134            TaskType::Documentation => write!(f, "documentation"),
135            TaskType::Analysis => write!(f, "analysis"),
136        }
137    }
138}
139
140#[cfg(test)]
141mod tests {
142    use super::*;
143
144    #[test]
145    fn test_task_status_label() {
146        assert_eq!(TaskStatus::Submitted.to_label(), "a2a:submitted");
147        assert_eq!(TaskStatus::Working.to_label(), "a2a:working");
148        assert_eq!(TaskStatus::Completed.to_label(), "a2a:completed");
149    }
150
151    #[test]
152    fn test_task_type_label() {
153        assert_eq!(TaskType::CodeGeneration.to_label(), "a2a:codegen");
154        assert_eq!(TaskType::CodeReview.to_label(), "a2a:review");
155    }
156
157    #[test]
158    fn test_task_status_display() {
159        assert_eq!(TaskStatus::Submitted.to_string(), "submitted");
160        assert_eq!(TaskStatus::Working.to_string(), "working");
161    }
162}