//! Bash-task on-disk schema, shared with `hive-bash-mcp`. //! //! Canonical home for the bash-task persisted schema: `hive-bash-mcp` //! (the daemon that writes the files) re-exports these from its //! `protocol` module, and `hive-agent` (the agent web UI that reads //! them back for the running-tasks panel) deserializes the same type, so //! the on-disk shape can't drift between writer and reader. Stays here //! rather than moving to a narrower crate: two independent crates //! (`hive-bash-mcp`, `hive-agent`) both need it, so a single-consumer //! crate wouldn't fit — same shared-payload role every other type in //! this crate plays. use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; /// Lifecycle state of a bash task. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "snake_case")] pub enum TaskStatus { Pending, Running, Done, TimedOut, /// Daemon was restarted while the task was running; process is gone. Interrupted, /// Killed on request via `BashKill` (SIGINT or SIGKILL to the task's /// process group). Distinct from `Interrupted` (daemon-restart) and /// `TimedOut` (exceeded `timeout_secs`). Killed, } /// Task metadata + result written to `.json` under the bash-tasks dir. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TaskFile { pub id: String, pub cmd: String, /// Kill timeout in seconds. `None` means no timeout — task runs until /// natural exit. Old task files with a numeric value are still readable /// (serde coerces `u64` → `Some(u64)` is handled by the caller). #[serde(default, skip_serializing_if = "Option::is_none")] pub timeout_secs: Option, pub status: TaskStatus, pub created_at: DateTime, #[serde(default, skip_serializing_if = "Option::is_none")] pub started_at: Option>, #[serde(default, skip_serializing_if = "Option::is_none")] pub completed_at: Option>, #[serde(default, skip_serializing_if = "Option::is_none")] pub exit_code: Option, /// Last `SUMMARY_BYTES` of stdout (see `hive-bash-mcp` runner). #[serde(default, skip_serializing_if = "Option::is_none")] pub stdout_tail: Option, /// Last `SUMMARY_BYTES` of stderr (see `hive-bash-mcp` runner). #[serde(default, skip_serializing_if = "Option::is_none")] pub stderr_tail: Option, }