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(
|
#[tool(
|
||||||
description = "Run a shell command in the background. Returns a task ID immediately — \
|
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 \
|
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; \
|
`from: \"bash-task-<id>\"` carrying the exit status plus a `Read(<path>)` \
|
||||||
handle it on a future turn. Use `status` to poll the task status within \
|
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) — \
|
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. \
|
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 \
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let out_snippet = stdout_tail.as_deref().unwrap_or("").trim();
|
// Pass only whether each stream produced (trimmed) output — `send_wake`
|
||||||
let err_snippet = stderr_tail.as_deref().unwrap_or("").trim();
|
// emits a `Read(<path>)` pointer to the captured `.out`/`.err` files
|
||||||
send_wake(socket, &id, &summary, Some((out_snippet, err_snippet))).await;
|
// 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.
|
/// 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,
|
socket: &Path,
|
||||||
id: &str,
|
id: &str,
|
||||||
summary: &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::io::{AsyncBufReadExt as _, BufReader};
|
||||||
use tokio::net::UnixStream;
|
use tokio::net::UnixStream;
|
||||||
let mut body = format!("bash task `{id}` finished: {summary}");
|
let mut body = format!("bash task `{id}` finished: {summary}");
|
||||||
if let Some((stdout, stderr)) = output {
|
if let Some((has_stdout, has_stderr)) = output
|
||||||
if !stdout.is_empty() {
|
&& (has_stdout || has_stderr)
|
||||||
body.push_str("\n\nstdout:\n```\n");
|
{
|
||||||
body.push_str(stdout);
|
body.push_str("\n\noutput captured — read the full text with:");
|
||||||
body.push_str("\n```");
|
if has_stdout {
|
||||||
|
let _ = write!(body, "\n Read({})", crate::paths::task_out(id).display());
|
||||||
}
|
}
|
||||||
if !stderr.is_empty() {
|
if has_stderr {
|
||||||
body.push_str("\n\nstderr:\n```\n");
|
let _ = write!(
|
||||||
body.push_str(stderr);
|
body,
|
||||||
body.push_str("\n```");
|
"\n Read({}) # stderr",
|
||||||
|
crate::paths::task_err(id).display()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let req = hive_sh4re::AgentRequest::Wake {
|
let req = hive_sh4re::AgentRequest::Wake {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue