mod dependency_ops;
mod query_ops;
mod status_ops;
mod time_tracking;
#[cfg(test)]
mod tests;
use anyhow::{Context, Result};
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
use brainwires_core::{Task, TaskPriority};
pub use time_tracking::{TaskStats, TaskTimeInfo, TimeStats, format_duration_secs};
#[derive(Debug, Clone)]
pub struct TaskManager {
pub(crate) tasks: Arc<RwLock<HashMap<String, Task>>>,
}
impl TaskManager {
pub fn new() -> Self {
Self {
tasks: Arc::new(RwLock::new(HashMap::new())),
}
}
#[tracing::instrument(name = "agent.task.create", skip(self, description))]
pub async fn create_task(
&self,
description: String,
parent_id: Option<String>,
priority: TaskPriority,
) -> Result<String> {
let task_id = uuid::Uuid::new_v4().to_string();
let mut task = Task::new(task_id.clone(), description);
task.priority = priority;
let mut tasks = self.tasks.write().await;
if let Some(ref pid) = parent_id {
let parent = tasks
.get_mut(pid)
.context(format!("Parent task '{}' not found", pid))?;
parent.add_child(task_id.clone());
task.parent_id = Some(pid.clone());
}
tasks.insert(task_id.clone(), task);
Ok(task_id)
}
pub async fn add_subtask(&self, parent_id: String, description: String) -> Result<String> {
self.create_task(description, Some(parent_id), TaskPriority::Normal)
.await
}
pub async fn get_task(&self, task_id: &str) -> Option<Task> {
let tasks = self.tasks.read().await;
tasks.get(task_id).cloned()
}
pub async fn clear(&self) {
let mut tasks = self.tasks.write().await;
tasks.clear();
}
pub async fn count(&self) -> usize {
let tasks = self.tasks.read().await;
tasks.len()
}
pub async fn load_tasks(&self, tasks_to_load: Vec<Task>) {
let mut tasks = self.tasks.write().await;
tasks.clear();
for task in tasks_to_load {
tasks.insert(task.id.clone(), task);
}
}
pub async fn export_tasks(&self) -> Vec<Task> {
self.get_all_tasks().await
}
pub async fn assign_task(&self, task_id: &str, agent_id: &str) -> Result<()> {
let mut tasks = self.tasks.write().await;
let task = tasks
.get_mut(task_id)
.context(format!("Task '{}' not found", task_id))?;
task.assigned_to = Some(agent_id.to_string());
task.updated_at = chrono::Utc::now().timestamp();
Ok(())
}
}
impl Default for TaskManager {
fn default() -> Self {
Self::new()
}
}