hive-c0re/hive-sh4re: remove the ask/answer wire protocol + core routing

This commit is contained in:
damocles 2026-08-30 01:18:17 +02:00
commit 2850270829
23 changed files with 177 additions and 851 deletions

View file

@ -104,9 +104,9 @@ async fn main() -> Result<()> {
// ---------- shared turn helpers ----------
/// Surface a `SYSTEM_SENDER` message in the live event bus + tracing
/// log. Both agents and the manager receive `QuestionAnswered`,
/// `ContainerCrash`, reparent notifications, and friends; the parse
/// and log path is identical. Quiet no-op when `from` isn't
/// log. Both agents and the manager receive `ContainerCrash`,
/// reparent notifications, and friends; the parse and log path is
/// identical. Quiet no-op when `from` isn't
/// `SYSTEM_SENDER`.
fn log_system_event(bus: &Bus, from: &str, body: &str) {
if from != SYSTEM_SENDER {

View file

@ -255,7 +255,7 @@ shared closer
assert!(!rendered.contains("<!-- /role:"));
// Shared tools appear.
assert!(rendered.contains("mcp__hyperhive__recv"));
assert!(rendered.contains("mcp__hyperhive__ask"));
assert!(rendered.contains("mcp__hyperhive__send"));
}
#[test]

View file

@ -254,14 +254,7 @@ fn enrich_tool_use_entry(entry: &mut Value) {
/// `_category: "rich"` so the client can distinguish without re-implementing
/// the tool name list.
fn is_rich_tool(name: &str) -> bool {
matches!(
name,
"Edit"
| "mcp__bash__run"
| "mcp__hyperhive__send"
| "mcp__hyperhive__ask"
| "mcp__hyperhive__answer"
)
matches!(name, "Edit" | "mcp__bash__run" | "mcp__hyperhive__send")
}
/// Pre-compute the expandable body for rich tool entries.
@ -271,7 +264,7 @@ fn is_rich_tool(name: &str) -> bool {
/// - `"diff"` → `api.detailsDiff` (colour-coded `+`/`-` lines)
/// - `"plain"` → `api.details` (plain `<pre>` block)
/// - `"markdown"` → `api.detailsOpenMd` (markdown rendered via marked + `DOMPurify`,
/// default-open; used for message-bearing tools: send, ask, answer)
/// default-open; used for message-bearing tools: `send`)
///
/// Returns `None` for tools that have no body at all.
///
@ -318,9 +311,7 @@ fn rich_tool_body(name: &str, input: &Value) -> Option<(String, &'static str)> {
Some((format!("$ {cmd}"), "plain"))
}
}
// Message-bearing tools: body is markdown text rendered by the client.
// The ask form (operator reply slot) is still mounted client-side;
// only the raw body text moves to the backend here.
// Message-bearing tool: body is markdown text rendered by the client.
"mcp__hyperhive__send" => {
let body = input.get("body").and_then(Value::as_str).unwrap_or("");
if body.is_empty() {
@ -329,22 +320,6 @@ fn rich_tool_body(name: &str, input: &Value) -> Option<(String, &'static str)> {
Some((body.to_owned(), "markdown"))
}
}
"mcp__hyperhive__ask" => {
let q = input.get("question").and_then(Value::as_str).unwrap_or("");
if q.is_empty() {
None
} else {
Some((q.to_owned(), "markdown"))
}
}
"mcp__hyperhive__answer" => {
let a = input.get("answer").and_then(Value::as_str).unwrap_or("");
if a.is_empty() {
None
} else {
Some((a.to_owned(), "markdown"))
}
}
_ => None,
}
}
@ -354,8 +329,6 @@ fn tool_icon(name: &str) -> &'static str {
match name {
"mcp__hyperhive__send" => "📤",
"mcp__hyperhive__recv" => "📥",
"mcp__hyperhive__ask" => "",
"mcp__hyperhive__answer" => "✍️",
"mcp__hyperhive__remind" => "",
"mcp__hyperhive__set_status" => "🏷️",
"mcp__hyperhive__get_loose_ends" => "🪢",
@ -470,10 +443,10 @@ fn fmt_builtin_tool(name: &str, short: &str, input: &Value) -> String {
}
}
/// Summary for message-bearing hyperhive tools (send / ask / answer).
/// Summary for `send`, the one message-bearing hyperhive tool.
///
/// Format: `"{short} → {recipient}"` or `"{short} #{id}"` with ` · NL`
/// appended when the body spans multiple lines.
/// Format: `"{short} → {recipient}"` with ` · NL` appended when the body
/// spans multiple lines.
fn fmt_hyperhive_message_tool(name: &str, short: &str, input: &Value) -> String {
match name {
"mcp__hyperhive__send" => {
@ -485,30 +458,6 @@ fn fmt_hyperhive_message_tool(name: &str, short: &str, input: &Value) -> String
format!("{short}{to}")
}
}
"mcp__hyperhive__ask" => {
let to = input
.get("to")
.and_then(Value::as_str)
.unwrap_or("operator");
let lines = sv(input, "question").lines().count();
if lines > 1 {
format!("{short}{to} · {lines}L")
} else {
format!("{short}{to}")
}
}
"mcp__hyperhive__answer" => {
let id = input
.get("id")
.and_then(Value::as_u64)
.map_or_else(|| "?".to_owned(), |n| n.to_string());
let lines = sv(input, "answer").lines().count();
if lines > 1 {
format!("{short} #{id} · {lines}L")
} else {
format!("{short} #{id}")
}
}
_ => fmt_args_generic(short, input),
}
}
@ -516,9 +465,7 @@ fn fmt_hyperhive_message_tool(name: &str, short: &str, input: &Value) -> String
/// `mcp__hyperhive__*` tools.
fn fmt_hyperhive_tool(name: &str, short: &str, input: &Value) -> String {
match name {
"mcp__hyperhive__send" | "mcp__hyperhive__ask" | "mcp__hyperhive__answer" => {
fmt_hyperhive_message_tool(name, short, input)
}
"mcp__hyperhive__send" => fmt_hyperhive_message_tool(name, short, input),
"mcp__hyperhive__recv" => {
let mut parts = Vec::new();
if let Some(w) = input.get("wait_seconds").and_then(Value::as_u64) {