Skip to main content

walrus_daemon/hook/task/
mod.rs

1//! Task registry — in-memory tracking of agent work units.
2//!
3//! [`TaskRegistry`] stores [`Task`] records with concurrency control,
4//! parent/sub-task hierarchy, and inbox-based blocking for user approval.
5
6use compact_str::CompactString;
7use tokio::sync::{oneshot, watch};
8use tokio::task::AbortHandle;
9use tokio::time::Instant;
10
11pub use config::TasksConfig;
12pub use registry::TaskRegistry;
13
14pub mod config;
15mod registry;
16pub(crate) mod tool;
17
18/// Task execution status.
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum TaskStatus {
21    /// Waiting for a concurrency slot.
22    Queued,
23    /// Actively running.
24    InProgress,
25    /// Blocked waiting for user approval.
26    Blocked,
27    /// Completed successfully.
28    Finished,
29    /// Completed with error.
30    Failed,
31}
32
33impl std::fmt::Display for TaskStatus {
34    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35        match self {
36            Self::Queued => write!(f, "queued"),
37            Self::InProgress => write!(f, "in_progress"),
38            Self::Blocked => write!(f, "blocked"),
39            Self::Finished => write!(f, "finished"),
40            Self::Failed => write!(f, "failed"),
41        }
42    }
43}
44
45/// Pending user approval item — blocks task until resolved.
46pub struct InboxItem {
47    /// Description of what needs approval (tool name + args summary).
48    pub question: String,
49    /// Channel to send the user's response through.
50    pub reply: oneshot::Sender<String>,
51}
52
53impl std::fmt::Debug for InboxItem {
54    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55        f.debug_struct("InboxItem")
56            .field("question", &self.question)
57            .finish()
58    }
59}
60
61/// A tracked unit of agent work.
62pub struct Task {
63    /// Unique task identifier.
64    pub id: u64,
65    /// Parent task ID for sub-task hierarchy.
66    pub parent_id: Option<u64>,
67    /// Session allocated for this task's execution.
68    pub session_id: Option<u64>,
69    /// Agent assigned to this task.
70    pub agent: CompactString,
71    /// Current execution status.
72    pub status: TaskStatus,
73    /// Origin of this task ("user" or agent name).
74    pub created_by: CompactString,
75    /// Human-readable task description / message.
76    pub description: String,
77    /// Final result content (set on Finished).
78    pub result: Option<String>,
79    /// Error message (set on Failed).
80    pub error: Option<String>,
81    /// Pending approval item (set when status is Blocked).
82    pub blocked_on: Option<InboxItem>,
83    /// Cumulative prompt tokens used.
84    pub prompt_tokens: u64,
85    /// Cumulative completion tokens used.
86    pub completion_tokens: u64,
87    /// When this task was created.
88    pub created_at: Instant,
89    /// Handle to abort the spawned execution task.
90    pub abort_handle: Option<AbortHandle>,
91    /// Whether this task was created via `spawn_task` (auto-dispatched).
92    /// False for `create_task` entries (delivered by heartbeat).
93    pub spawned: bool,
94    /// Watch channel for status change notifications (used by await_tasks).
95    pub status_tx: watch::Sender<TaskStatus>,
96}