From b70209836ece0ae21d700e4805eb51480efdfd73 Mon Sep 17 00:00:00 2001 From: iris Date: Fri, 19 Jun 2026 12:37:14 +0200 Subject: [PATCH] hive-sh4re: lift TaskFile + TaskStatus from hive-bash-mcp Move the bash-task on-disk schema (TaskFile + TaskStatus) into hive-sh4re, the shared wire-types crate, and re-export them from hive-bash-mcp::protocol so existing in-crate imports keep compiling. This gives hive-ag3nt's agent web UI a canonical type to deserialize when reading the bash-tasks dir for a running-tasks panel, instead of a parallel struct that would silently drift from the daemon's persisted format. Both crates already depend on hive-sh4re, so no new dependency edges. --- hive-bash-mcp/src/protocol.rs | 48 +++++--------------------------- hive-sh4re/src/lib.rs | 52 +++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 41 deletions(-) diff --git a/hive-bash-mcp/src/protocol.rs b/hive-bash-mcp/src/protocol.rs index 4638a409..cb106047 100644 --- a/hive-bash-mcp/src/protocol.rs +++ b/hive-bash-mcp/src/protocol.rs @@ -8,47 +8,13 @@ use serde::{Deserialize, Serialize}; // Task state (shared between runner and protocol) // --------------------------------------------------------------------------- -/// 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 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: i64, - #[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 [`crate::runner::SUMMARY_BYTES`] of stdout. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub stdout_tail: Option, - /// Last [`crate::runner::SUMMARY_BYTES`] of stderr. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub stderr_tail: Option, -} +// `TaskFile` + `TaskStatus` are the bash-task on-disk schema. They live in +// `hive-sh4re` (the shared wire-types crate) so the agent web UI in +// `hive-ag3nt` can deserialize the same canonical type when reading the +// tasks dir for its running-tasks panel — no parallel copy to drift. Both +// are re-exported here so existing `crate::protocol::{TaskFile, TaskStatus}` +// imports across this crate keep compiling unchanged. +pub use hive_sh4re::{TaskFile, TaskStatus}; // --------------------------------------------------------------------------- // Request / response diff --git a/hive-sh4re/src/lib.rs b/hive-sh4re/src/lib.rs index 73f7234c..8cdb9f47 100644 --- a/hive-sh4re/src/lib.rs +++ b/hive-sh4re/src/lib.rs @@ -380,6 +380,58 @@ pub enum CancelLooseEndKind { Approval, } +// --------------------------------------------------------------------------- +// Bash-task on-disk schema (shared with `hive-bash-mcp`) +// --------------------------------------------------------------------------- + +/// Lifecycle state of a bash task. +/// +/// 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-ag3nt` (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. +#[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: i64, + #[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, +} + /// Unified request enum for both agent and manager sockets. The agent's /// identity is the socket it arrived on. Privileged variants are marked /// `*(privileged)*` — an agent socket returns `Err` for them server-side.