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}