fix(#2426): bash wake gives status + read() pointer, not inline stdout/stderr
This commit is contained in:
parent
5869f34390
commit
f5c8a6a8db
2 changed files with 29 additions and 15 deletions
|
|
@ -238,8 +238,9 @@ impl BashMcp {
|
|||
#[tool(
|
||||
description = "Run a shell command in the background. Returns a task ID immediately — \
|
||||
do NOT wait inline. When the command finishes, the harness fires a wake with \
|
||||
`from: \"bash-task-<id>\"` and the exit code + last stdout lines in the body; \
|
||||
handle it on a future turn. Use `status` to poll the task status within \
|
||||
`from: \"bash-task-<id>\"` carrying the exit status plus a `Read(<path>)` \
|
||||
pointer to the captured `.out`/`.err` files (not the output text itself — \
|
||||
read only what you need); handle it on a future turn. Use `status` to poll the task status within \
|
||||
the same turn if needed. `timeout_secs` defaults to `None` (no timeout) — \
|
||||
task runs until natural exit; pass an explicit value to kill after N seconds. \
|
||||
Pass `wait_seconds` (capped at 30) to wait inline for fast commands: when the \
|
||||
|
|
|
|||
|
|
@ -575,9 +575,12 @@ async fn run_task(mut task: TaskFile, socket: &Path) {
|
|||
return;
|
||||
}
|
||||
|
||||
let out_snippet = stdout_tail.as_deref().unwrap_or("").trim();
|
||||
let err_snippet = stderr_tail.as_deref().unwrap_or("").trim();
|
||||
send_wake(socket, &id, &summary, Some((out_snippet, err_snippet))).await;
|
||||
// Pass only whether each stream produced (trimmed) output — `send_wake`
|
||||
// emits a `Read(<path>)` pointer to the captured `.out`/`.err` files
|
||||
// rather than inlining the tail into the wake body.
|
||||
let has_stdout = !stdout_tail.as_deref().unwrap_or("").trim().is_empty();
|
||||
let has_stderr = !stderr_tail.as_deref().unwrap_or("").trim().is_empty();
|
||||
send_wake(socket, &id, &summary, Some((has_stdout, has_stderr))).await;
|
||||
}
|
||||
|
||||
/// Run `bash -c cmd` in its own process group, streaming output to files.
|
||||
|
|
@ -730,21 +733,31 @@ pub(crate) async fn send_wake(
|
|||
socket: &Path,
|
||||
id: &str,
|
||||
summary: &str,
|
||||
output: Option<(&str, &str)>,
|
||||
// `(has_stdout, has_stderr)` — whether the task produced non-empty
|
||||
// stdout / stderr. `None` for the interrupted path (no captured output
|
||||
// to point at). Deliberately NOT the output text: the wake gives the
|
||||
// agent the status + a `Read(<path>)` pointer to the captured files
|
||||
// rather than inlining the tail, which would flood the agent's context
|
||||
// on every task completion.
|
||||
output: Option<(bool, bool)>,
|
||||
) {
|
||||
use std::fmt::Write as _;
|
||||
use tokio::io::{AsyncBufReadExt as _, BufReader};
|
||||
use tokio::net::UnixStream;
|
||||
let mut body = format!("bash task `{id}` finished: {summary}");
|
||||
if let Some((stdout, stderr)) = output {
|
||||
if !stdout.is_empty() {
|
||||
body.push_str("\n\nstdout:\n```\n");
|
||||
body.push_str(stdout);
|
||||
body.push_str("\n```");
|
||||
if let Some((has_stdout, has_stderr)) = output
|
||||
&& (has_stdout || has_stderr)
|
||||
{
|
||||
body.push_str("\n\noutput captured — read the full text with:");
|
||||
if has_stdout {
|
||||
let _ = write!(body, "\n Read({})", crate::paths::task_out(id).display());
|
||||
}
|
||||
if !stderr.is_empty() {
|
||||
body.push_str("\n\nstderr:\n```\n");
|
||||
body.push_str(stderr);
|
||||
body.push_str("\n```");
|
||||
if has_stderr {
|
||||
let _ = write!(
|
||||
body,
|
||||
"\n Read({}) # stderr",
|
||||
crate::paths::task_err(id).display()
|
||||
);
|
||||
}
|
||||
}
|
||||
let req = hive_sh4re::AgentRequest::Wake {
|
||||
|
|
|
|||
Loading…
Reference in a new issue