gitdataai/libs/agent/task/mod.rs

78 lines
2.2 KiB
Rust

//! Agent task service — managing task/sub-agent execution lifecycle.
//!
//! A task (`agent_task` record) can be:
//! - A **root task**: initiated by a user or system event.
//! The parent/Supervisor agent spawns sub-tasks and coordinates their results.
//! - A **sub-task**: a unit of work executed by a sub-agent.
//!
//! Execution flow:
//! 1. Create task record (status = pending)
//! 2. Notify listeners (WebSocket: task_started)
//! 3. Spawn execution (tokio::spawn or via room queue)
//! 4. Update progress (status = running, progress = "step 2/5: ...")
//! 5. On completion: update output + status = done / error + status = failed
//! 6. Notify listeners (WebSocket: task_done)
//! 7. If root task: notify parent/Supervisor to aggregate results
//!
//! This module is intentionally kept simple and synchronous with the DB.
//! Long-running execution is delegated to the caller (tokio::spawn).
pub mod events;
pub mod lifecycle;
pub mod store;
pub mod tree;
use db::database::AppDatabase;
pub use events::{NoOpPublisher, TaskEvent, TaskEventPublisher, TaskEvents};
pub use lifecycle::TaskLifecycle;
/// Service for managing agent tasks (root tasks and sub-tasks).
#[derive(Clone)]
pub struct TaskService {
db: AppDatabase,
events: TaskEvents,
}
impl TaskService {
pub fn new(db: AppDatabase) -> Self {
Self {
db,
events: TaskEvents::noop(),
}
}
pub fn with_events(db: AppDatabase, events: TaskEvents) -> Self {
Self { db, events }
}
pub(crate) fn db(&self) -> &AppDatabase {
&self.db
}
pub(crate) fn events(&self) -> &TaskEvents {
&self.events
}
}
/// Builder for TaskService so that the events publisher can be set independently
/// of the database connection.
#[derive(Clone, Default)]
pub struct TaskServiceBuilder {
events: Option<TaskEvents>,
}
impl TaskServiceBuilder {
pub fn with_events(mut self, events: TaskEvents) -> Self {
self.events = Some(events);
self
}
pub async fn build(self, db: AppDatabase) -> TaskService {
TaskService {
db,
events: self.events.unwrap_or_else(TaskEvents::noop),
}
}
}