//! Argument structs for the MCP tools: `serde::Deserialize` + //! `schemars::JsonSchema` derives whose field doc-comments become the //! parameter descriptions claude sees in each tool's input schema. use rmcp::schemars; #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct SendArgs { /// Logical agent name to deliver the message to (e.g. `"manager"`, /// `"alice"`, or the literal `"operator"` for the dashboard's T4LK box). pub to: String, /// Message body. Plain text; the broker doesn't parse it. pub body: String, /// Optional broker row-id of the message this is a reply to. Lets /// the dashboard render conversation threads. Pass the `id` from the /// `DeliveredMessage` you're responding to; omit for new threads. /// Silently ignored if the id is unknown or out of retention. #[serde(default)] pub in_reply_to: Option, } #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct RecvArgs { /// Maximum number of messages to pop in this round-trip. Default /// (None) is 1 (single-message behaviour — exactly what you want /// when you're called to drive a turn off the first wake). Pass /// a higher value (capped at 5 server-side) when you've been /// told the inbox has more queued (the wake prompt mentions /// pending count) and want to drain everything in one tool call. #[serde(default)] pub max: Option, } /// MCP tool args for `ack_until`. #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct AckUntilArgs { /// Highest broker message id to mark handled: every inbox message /// with `id <= up_to` (ids show as `[msg #]` in recv output) /// is acked in one sweep. Pass the highest id you've actually /// seen/triaged — anything above it stays queued for later turns. pub up_to: i64, } /// MCP tool args for `mark_todos_done`. #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct MarkTodosDoneArgs { /// Todo ids to clear (from `get_loose_ends`'s `todo #N` lines). Only /// these ids are acked — not a range. Unknown/already-acked ids are /// silently skipped. pub ids: Vec, } /// MCP tool args for `remind`. Exactly one of `delay_seconds` or /// `at_unix_timestamp` must be set; both / neither is a tool-side error. /// Hides the tagged `ReminderTiming` enum behind a flatter schema so the /// model picks one field instead of building `{"timing_type": "in_seconds", /// "seconds": 60}` shaped objects. #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct RemindArgs { /// Body that lands in your inbox when the reminder fires (sender /// will appear as `reminder`). Soft cap at 4 KiB inline — anything /// larger gets auto-persisted to a file under /// `/agents//state/reminders/auto-.md` and the inbox /// message becomes a short pointer. Pass `file_path` if you want /// to control the destination yourself. pub message: String, /// Fire `delay_seconds` from now (relative). Set this OR /// `at_unix_timestamp`, not both. #[serde(default)] pub delay_seconds: Option, /// Fire at this absolute unix timestamp (seconds since epoch). Set /// this OR `delay_seconds`, not both. #[serde(default)] pub at_unix_timestamp: Option, /// Optional path to a file the scheduler should reference instead of /// inlining a long `message`. Use this for large payloads (research /// notes, file lists, intermediate state). Path must be reachable from /// the agent's container — typically under `/agents//state/`. #[serde(default)] pub file_path: Option, } // ----------------------------------------------------------------------------- // Privileged tool arg types (lifecycle, approvals, scheduling, diagnostics) // ----------------------------------------------------------------------------- #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct RequestInitConfigArgs { /// New sub-agent name (≤9 chars). Queues an `InitConfig` approval; on /// approval hive-c0re creates the child's config repo and seeds it with a /// default `agent.nix`. Approving the follow-up `Spawn` creates the /// container. Config changes — including the child's first — are PRs on /// that repo, made from a clone, reviewed + approved by the operator; /// `/agents//config` is a read-only copy, not an editing surface. pub name: String, /// Optional description shown on the dashboard approval card. #[serde(default)] pub description: Option, } #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct KillArgs { /// Sub-agent name (without the `h-` container prefix). pub name: String, } #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct SetStatusArgs { /// Status text to display on the dashboard card. Pass an empty string to clear. pub text: String, } #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct CreateRepoArgs { /// Repo name — a single segment of letters, digits, `-`, `_`, `.` /// (no leading `-`/`.`). The repo is created as `agents/`. pub repo: String, } #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct GetAgentMetaArgs { /// Logical name of the agent to query (e.g. `"iris"`, `"manager"`). /// Omit to query your own identity + status — replaces the /// previous `whoami` self-introspection tool. #[serde(default)] pub name: Option, } #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct StartArgs { /// Sub-agent name (without the `h-` container prefix). pub name: String, } #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct RestartArgs { /// Sub-agent name (without the `h-` container prefix). pub name: String, } #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct UpdateArgs { /// Sub-agent name (without the `h-` container prefix). pub name: String, } #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct AskArgs { /// The question to surface. pub question: String, /// Optional fixed-choice answers. The dashboard renders these as /// chips alongside a free-text fallback ("Other…") so the operator /// is never trapped by an incomplete list; peer-agent recipients /// see the list in their inbox event and can return any string. #[serde(default)] pub options: Vec, /// When true, options are rendered as checkboxes — the answerer /// can pick any subset. The answer comes back as a single string /// with selections joined by ", ". Ignored when `options` is empty. #[serde(default)] pub multi: bool, /// Optional auto-cancel after `ttl_seconds` (capped server-side at /// 6 hours). On expiry the question resolves with answer /// `[expired]` and the asker receives the usual /// `question_answered` system event (with `answerer: /// "ttl-watchdog"`). `None` (default) = wait indefinitely. #[serde(default)] pub ttl_seconds: Option, /// Recipient. Omit (or pass `"operator"`) to ask the human /// operator via the dashboard. Pass another agent's logical name /// to ask that peer — they receive a `question_asked` event in /// their inbox and answer via `mcp__hyperhive__answer`. #[serde(default)] pub to: Option, } #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct AnswerArgs { /// Id of the question being answered — comes from the /// `question_asked` event in your inbox. pub id: i64, /// Free-text answer body. Soft-capped at 4 KiB by the same /// `MESSAGE_MAX_BYTES` limit as `send`; keep it short or write the /// detail to a file and pass a path. pub answer: String, } #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct CancelLooseEndArgs { /// Which kind of thread to cancel — `"question"` for an open /// `ask` that's still waiting on an answer, `"reminder"` for a /// scheduled `remind` that hasn't fired yet, or `"todo"` for a /// loose-ends-v2 todo (bash/matrix/forge). Use the `kind` /// field straight off the `get_loose_ends` row. pub kind: String, /// Row id from the matching `get_loose_ends` entry (or the /// `question_queued` reply when you submitted it). pub id: i64, } #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct AgentGetLooseEndsArgs { /// Whose loose ends to list. Omit (or `null`) for your own. You may /// also pass a direct child agent's name without any extra capability. /// Pass any other agent name to inspect their threads — requires the /// `query_agent_state` capability; without it the request is rejected /// with an error. The `"*"` hive-wide value is not available on the /// agent socket. #[serde(default)] pub agent: Option, } #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct UpdateMetaInputsArgs { /// Flake input names to update (e.g. `["bitburner-agent", "nixpkgs"]`). /// Pass an empty list to update ALL inputs. #[serde(default)] pub inputs: Vec, /// Optional description shown on the dashboard approval card. #[serde(default)] pub description: Option, } #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct RequestSchedulePromptArgs { /// Recipient agents — one schedule fires to many inboxes at the /// scheduled time. `operator` is a legitimate target (mara: "we /// want to get rid of the manager special case so yes manager /// can be recipient" — the operator slot follows the same rule). pub targets: Vec, /// Message body delivered to each target's inbox at fire time. /// Same size budget as `send` bodies. pub body: String, /// Absolute unix timestamp (seconds) for the FIRST fire. For /// recurring schedules the worker re-arms in /// `interval_seconds` steps from this point on. pub first_fire_at_unix: i64, /// `None` / absent = one-shot. `Some(n > 0)` = recurring every /// `n` seconds. The worker clamps catch-up so a long downtime /// fires ONCE on resume (skipped-cycle count surfaces in the /// per-target `last_result`), not N delayed pulses in a row. #[serde(default)] pub interval_seconds: Option, /// Optional description shown on the dashboard approval card + /// preserved on the schedule row for later operator reference. #[serde(default)] pub description: Option, } #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct FireScheduleNowArgs { /// Schedule id to fire out of band. Get this from a prior /// `list_schedules` call or the approval-resolved event for /// the originating `request_schedule_prompt`. pub id: i64, } #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct CancelScheduleArgs { /// Schedule id from a prior `list_schedules` call or the /// approval-resolved event for a `request_schedule_prompt`. pub id: i64, /// Optional target list. `None` / empty = cancel the entire /// schedule. `Some(["alice", "bob"])` = cancel just those /// recipients (the schedule keeps firing for any remaining /// active targets, and auto-cancels its parent row when every /// target is gone). #[serde(default)] pub targets: Option>, } #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct EditScheduleArgs { /// Schedule id from a prior `list_schedules` call or the /// approval-resolved event for a `request_schedule_prompt`. pub id: i64, /// New body text. Omit to keep the existing one. #[serde(default)] pub body: Option, /// New description. Omit to keep the existing one. (To CLEAR /// the description, use the dashboard PATCH endpoint /// directly — the agent surface intentionally keeps the args /// flat / non-nullable to dodge the doubly-wrapped Option /// schemars quirk; clearing fields is rare and operator-side.) #[serde(default)] pub description: Option, /// Recurring interval in seconds. Omit to keep the existing /// cadence; pass an explicit value to set a new one. Toggling /// recurring↔one-shot (clearing the interval) is operator-only /// for the same reason as `description` above. #[serde(default)] pub interval_seconds: Option, /// New absolute unix timestamp for the next fire. Omit to /// leave the schedule on its current cadence. #[serde(default)] pub next_fire_at_unix: Option, /// Names of new targets to add. Replace-on-conflict: re-adding /// a previously cancelled target resets its history (operator /// intent on re-add = "this target is active again"). #[serde(default)] pub targets_add: Option>, /// Names of targets to cancel. Tombstones preserve per-target /// audit; when no active targets remain the schedule /// auto-cancels. #[serde(default)] pub targets_remove: Option>, } #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct GetLogsArgs { /// Logical agent name to fetch logs for (e.g. `gui`, `iris`). /// hive-c0re maps it to the underlying machine name (`h-gui`) /// itself — pass the plain agent name, not the `h-` form. pub agent: String, /// How many journal lines to return (default: 50, max: 500). #[serde(default)] pub lines: Option, } /// Arguments for `get_host_journal` (capability-gated: `read_host_journal`). #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct GetHostJournalArgs { /// Systemd unit to filter (e.g. `hive-c0re.service`). Omit for all units. #[serde(default)] pub unit: Option, /// nspawn machine name verbatim (e.g. `h-iris`). Omit for host journal. /// Agent containers use the `h-` prefix (e.g. `h-iris`); infrastructure /// containers use their full name (e.g. `hive-ci`, `hive-forge`, /// `hive-matrix`). The gateway has no machine — its nginx runs on the /// host, so read it with `unit: nginx.service` and no `container`. #[serde(default)] pub container: Option, /// Number of lines to return (default 30, max 100). #[serde(default)] pub lines: Option, /// Minimum syslog priority level. #[serde(default)] pub priority: Option, /// Regex to match against log message fields (journalctl --grep). #[serde(default)] pub grep: Option, /// Show entries on or newer than this timestamp (e.g. `-1h`). #[serde(default)] pub since: Option, /// Show entries on or older than this timestamp. #[serde(default)] pub until: Option, }