claude_agent/
task_queue.rs1use std::collections::HashMap;
5use std::sync::Arc;
6use tokio::sync::Mutex;
7
8use crate::agents::{self, AgentResult};
9
10#[derive(Debug, Clone, PartialEq)]
11pub enum TaskStatus {
12 Pending,
13 Running,
14 Completed,
15 Failed,
16}
17
18#[derive(Debug, Clone)]
19pub struct TaskEntry {
20 pub id: String,
21 pub prompt: String,
22 pub status: TaskStatus,
23 pub result: Option<AgentResult>,
24}
25
26pub struct TaskQueue {
27 tasks: Arc<Mutex<HashMap<String, TaskEntry>>>,
28}
29
30impl Default for TaskQueue {
31 fn default() -> Self {
32 Self::new()
33 }
34}
35
36impl TaskQueue {
37 pub fn new() -> Self {
38 Self {
39 tasks: Arc::new(Mutex::new(HashMap::new())),
40 }
41 }
42
43 pub async fn submit(&self, prompt: &str, cwd: &str) -> String {
45 let task_id = uuid::Uuid::new_v4().to_string()[..8].to_string();
46
47 let entry = TaskEntry {
48 id: task_id.clone(),
49 prompt: prompt.to_string(),
50 status: TaskStatus::Pending,
51 result: None,
52 };
53
54 self.tasks.lock().await.insert(task_id.clone(), entry);
55
56 let tasks = self.tasks.clone();
58 let tid = task_id.clone();
59 let p = prompt.to_string();
60 let c = cwd.to_string();
61
62 tokio::spawn(async move {
63 if let Some(entry) = tasks.lock().await.get_mut(&tid) {
65 entry.status = TaskStatus::Running;
66 }
67
68 let result = agents::spawn_agent(&p, &c, None).await;
69
70 let mut tasks = tasks.lock().await;
71 if let Some(entry) = tasks.get_mut(&tid) {
72 match result {
73 Ok(r) => {
74 entry.status = if r.is_error { TaskStatus::Failed } else { TaskStatus::Completed };
75 entry.result = Some(r);
76 }
77 Err(e) => {
78 entry.status = TaskStatus::Failed;
79 entry.result = Some(AgentResult {
80 agent_id: tid.clone(),
81 output: format!("Task error: {e}"),
82 is_error: true,
83 duration_ms: 0,
84 });
85 }
86 }
87 }
88 });
89
90 task_id
91 }
92
93 pub async fn status(&self, task_id: &str) -> Option<TaskEntry> {
95 self.tasks.lock().await.get(task_id).cloned()
96 }
97
98 pub async fn list(&self) -> Vec<TaskEntry> {
100 self.tasks.lock().await.values().cloned().collect()
101 }
102
103 pub async fn result(&self, task_id: &str) -> Option<AgentResult> {
105 self.tasks.lock().await
106 .get(task_id)
107 .and_then(|e| e.result.clone())
108 }
109
110 pub async fn active_count(&self) -> usize {
112 self.tasks.lock().await.values()
113 .filter(|t| matches!(t.status, TaskStatus::Pending | TaskStatus::Running))
114 .count()
115 }
116}