hive-bash-mcp: drop the command from the running-task todo entirely
Per mara: just show the task name, don't show any command — if an agent doesn't name a task itself it still gets the id back in the run tool's own result, so the todo doesn't need to repeat it. Drops short_cmd_label (and its tests) added in the previous commit; the summary is now just "bash task `<id>` running".
This commit is contained in:
parent
31c34939ef
commit
90cd602d4e
1 changed files with 10 additions and 68 deletions
|
|
@ -517,34 +517,6 @@ fn poll_once(socket: &Path, claimed: &Arc<Mutex<HashSet<String>>>) {
|
|||
// Task execution
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Max characters kept from the command's first line when building the
|
||||
/// "running" todo summary (see `short_cmd_label`).
|
||||
const CMD_LABEL_MAX_CHARS: usize = 100;
|
||||
|
||||
/// Build a short, single-line label for `cmd` to use in the "running"
|
||||
/// todo summary. `cmd` can be an entire multi-line script (heredocs are
|
||||
/// a common agent pattern) — embedding it whole balloons the todo body
|
||||
/// in every UI that renders it, so this keeps only the first non-blank
|
||||
/// line, char-truncated to `CMD_LABEL_MAX_CHARS`, with a trailing `…`
|
||||
/// whenever either the line itself was cut or more lines follow. The
|
||||
/// full command is still on disk in the task file for `status`/`view`.
|
||||
fn short_cmd_label(cmd: &str) -> String {
|
||||
let mut lines = cmd.lines().map(str::trim).filter(|l| !l.is_empty());
|
||||
let first = lines.next().unwrap_or("");
|
||||
let more_lines = lines.next().is_some();
|
||||
let char_truncated = first.chars().count() > CMD_LABEL_MAX_CHARS;
|
||||
let label: String = if char_truncated {
|
||||
first.chars().take(CMD_LABEL_MAX_CHARS).collect()
|
||||
} else {
|
||||
first.to_owned()
|
||||
};
|
||||
if char_truncated || more_lines {
|
||||
format!("{label}…")
|
||||
} else {
|
||||
label
|
||||
}
|
||||
}
|
||||
|
||||
async fn run_task(mut task: TaskFile, socket: &Path) {
|
||||
let id = task.id.clone();
|
||||
tracing::info!(id = %id, cmd = %task.cmd, "bash_runner: starting task");
|
||||
|
|
@ -554,12 +526,15 @@ async fn run_task(mut task: TaskFile, socket: &Path) {
|
|||
if let Err(e) = write_task(&task) {
|
||||
tracing::warn!(id = %id, error = ?e, "bash_runner: write running state failed");
|
||||
}
|
||||
upsert_bash_todo(
|
||||
socket,
|
||||
&id,
|
||||
format!("bash task `{id}` running: `{}`", short_cmd_label(&task.cmd)),
|
||||
)
|
||||
.await;
|
||||
// No command text in the summary: `id` is already the human-chosen
|
||||
// `name` when the caller passed one, and even the auto-generated
|
||||
// hex id was already returned to the agent in the `run` tool's own
|
||||
// result — the todo only needs to say which task, not repeat the
|
||||
// command. An unbounded raw command (e.g. a multi-line heredoc
|
||||
// script) would balloon every UI that renders todo summaries; the
|
||||
// full command stays on disk in the task file for `status`/`view`
|
||||
// instead.
|
||||
upsert_bash_todo(socket, &id, format!("bash task `{id}` running")).await;
|
||||
// Best-effort: tally the normalised command head for the /stats
|
||||
// "favorite tools" view. Counted once per execution, regardless of
|
||||
// exit status. Never fails the task.
|
||||
|
|
@ -858,43 +833,10 @@ fn done_summary(id: &str, summary: &str, output: Option<(bool, bool)>) -> String
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{CMD_LABEL_MAX_CHARS, short_cmd_label, validate_task_name};
|
||||
use super::validate_task_name;
|
||||
use crate::test_util::with_harness_dir;
|
||||
use hive_types::Ident;
|
||||
|
||||
#[test]
|
||||
fn short_cmd_label_short_single_line_is_unchanged() {
|
||||
assert_eq!(short_cmd_label("echo hi"), "echo hi");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn short_cmd_label_trims_and_skips_leading_blank_lines() {
|
||||
assert_eq!(short_cmd_label("\n\n echo hi \nmore stuff"), "echo hi…");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn short_cmd_label_flags_multiline_even_when_first_line_is_short() {
|
||||
// The whole point: a short first line followed by a long heredoc
|
||||
// body must still read as truncated, not as the complete command.
|
||||
let cmd = "cat > script.sh <<'SH'\n#!/usr/bin/env bash\necho hi\nSH\n";
|
||||
let label = short_cmd_label(cmd);
|
||||
assert_eq!(label, "cat > script.sh <<'SH'…");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn short_cmd_label_char_truncates_a_long_single_line() {
|
||||
let long = "x".repeat(CMD_LABEL_MAX_CHARS + 50);
|
||||
let label = short_cmd_label(&long);
|
||||
assert_eq!(label.chars().count(), CMD_LABEL_MAX_CHARS + 1); // +1 for the `…`
|
||||
assert!(label.ends_with('…'));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn short_cmd_label_handles_empty_command() {
|
||||
assert_eq!(short_cmd_label(""), "");
|
||||
assert_eq!(short_cmd_label(" \n \n"), "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn accepts_ident_names() {
|
||||
for ok in ["build", "ci-check", "t1", "task-123", "abc"] {
|
||||
|
|
|
|||
Loading…
Reference in a new issue