Synced from monorepo
Synced from monorepo Changes: - Report invalid MCP server config instead of failing startup - Keep completed terminal output when the gateway connection is lost - Show a duration-only detail view for single-task task output - Don't let a stale registry turn counter hide local sessions - Raise the file-descriptor soft limit on Linux and log effective limits at startup - Stop aborting when HTTP client construction fails - Make session thread and runtime spawn failures recoverable - Fix main-prompt paste parity in the question freeform input - Fire SessionEnd hooks on /exit and headless quit - Embed the deployment-config signing public key - Repaint paste-chip background on inline panel inputs - Security: prevent acceptEdits from auto-approving agent writes into the always-trusted global hook root - Fix stacked "Worked for" markers so parks render as status and turns close with exactly one marker - Parse hooks from config files - Add a remote kill-switch for managed-config signature verification - Security: fix workspace file-reference resolution bypassing workspace filesystem confinement Source-Revision: d02693a856a54f1030695b36b91d276e96b30b23
This commit is contained in:
parent
6e38642082
commit
47348d13ec
138 changed files with 7283 additions and 5796 deletions
|
|
@ -801,16 +801,14 @@ impl ToolOutput {
|
|||
format!("=== Task {} ===", r.task_id),
|
||||
format!("Command: {}", r.command),
|
||||
format!("Status: {}", r.status),
|
||||
format!("Started: {}", r.started),
|
||||
format!("Duration: {:.2}s", r.duration_secs),
|
||||
];
|
||||
if let Some(ref ended) = r.ended {
|
||||
lines.push(format!("Ended: {}", ended));
|
||||
}
|
||||
lines.push(format!("Duration: {:.2}s", r.duration_secs));
|
||||
if let Some(code) = r.exit_code {
|
||||
lines.push(format!("Exit Code: {}", code));
|
||||
}
|
||||
lines.push(format!("Output File: {}", r.output_file));
|
||||
if !r.output_file.is_empty() {
|
||||
lines.push(format!("Output File: {}", r.output_file));
|
||||
}
|
||||
lines.push(String::new());
|
||||
lines.push("=== Output ===".to_string());
|
||||
if r.output.is_empty() {
|
||||
|
|
@ -1641,6 +1639,55 @@ mod tests {
|
|||
assert_eq!(json["Result"]["task_id"], "task-1");
|
||||
assert_eq!(json["Result"]["status"], "running");
|
||||
}
|
||||
/// The single-task detail view is duration-only: absolute `started` /
|
||||
/// `ended` instants stay on the wire struct but must not reach the prompt.
|
||||
#[test]
|
||||
fn task_output_prompt_is_duration_only() {
|
||||
let out = ToolOutput::TaskOutput(TaskOutputOutput::Result(TaskOutputResult {
|
||||
task_id: "task-1".into(),
|
||||
command: "sleep 10".into(),
|
||||
status: "completed".into(),
|
||||
exit_code: Some(0),
|
||||
started: "2026-03-09T00:00:00Z".into(),
|
||||
ended: Some("2026-03-09T00:00:05Z".into()),
|
||||
duration_secs: 5.0,
|
||||
output: "hello".into(),
|
||||
output_file: "/tmp/task-1.log".into(),
|
||||
truncated: false,
|
||||
truncation_hint: String::new(),
|
||||
raw_output_bytes: 5,
|
||||
}));
|
||||
let prompt = out.to_prompt_format();
|
||||
assert!(prompt.contains("Duration: 5.00s"), "{prompt}");
|
||||
assert!(prompt.contains("Output File: /tmp/task-1.log"), "{prompt}");
|
||||
assert!(
|
||||
!prompt.contains("Started") && !prompt.contains("Ended"),
|
||||
"absolute instants must not be model-visible: {prompt}"
|
||||
);
|
||||
assert!(
|
||||
!prompt.contains("2026-03-09"),
|
||||
"no wall-clock date may survive into the prompt: {prompt}"
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn task_output_prompt_omits_empty_output_file() {
|
||||
let out = ToolOutput::TaskOutput(TaskOutputOutput::Result(TaskOutputResult {
|
||||
task_id: "task-2".into(),
|
||||
command: "true".into(),
|
||||
status: "completed".into(),
|
||||
exit_code: Some(0),
|
||||
started: String::new(),
|
||||
ended: None,
|
||||
duration_secs: 0.1,
|
||||
output: "done".into(),
|
||||
output_file: String::new(),
|
||||
truncated: false,
|
||||
truncation_hint: String::new(),
|
||||
raw_output_bytes: 4,
|
||||
}));
|
||||
let prompt = out.to_prompt_format();
|
||||
assert!(!prompt.contains("Output File"), "{prompt}");
|
||||
}
|
||||
fn make_result(status: &str, raw_output_bytes: usize) -> TaskOutputResult {
|
||||
TaskOutputResult {
|
||||
task_id: "t".into(),
|
||||
|
|
|
|||
Loading…
Reference in a new issue