fix command duration display (#1806)
we were always displaying "0ms" before. <img width="731" height="101" alt="Screenshot 2025-08-02 at 10 51 22 PM" src="https://github.com/user-attachments/assets/f56814ed-b9a4-4164-9e78-181c60ce19b7" />
This commit is contained in:
@@ -396,11 +396,15 @@ impl Session {
|
|||||||
&self,
|
&self,
|
||||||
sub_id: &str,
|
sub_id: &str,
|
||||||
call_id: &str,
|
call_id: &str,
|
||||||
stdout: &str,
|
output: &ExecToolCallOutput,
|
||||||
stderr: &str,
|
|
||||||
exit_code: i32,
|
|
||||||
is_apply_patch: bool,
|
is_apply_patch: bool,
|
||||||
) {
|
) {
|
||||||
|
let ExecToolCallOutput {
|
||||||
|
stdout,
|
||||||
|
stderr,
|
||||||
|
duration,
|
||||||
|
exit_code,
|
||||||
|
} = output;
|
||||||
// Because stdout and stderr could each be up to 100 KiB, we send
|
// Because stdout and stderr could each be up to 100 KiB, we send
|
||||||
// truncated versions.
|
// truncated versions.
|
||||||
const MAX_STREAM_OUTPUT: usize = 5 * 1024; // 5KiB
|
const MAX_STREAM_OUTPUT: usize = 5 * 1024; // 5KiB
|
||||||
@@ -412,14 +416,15 @@ impl Session {
|
|||||||
call_id: call_id.to_string(),
|
call_id: call_id.to_string(),
|
||||||
stdout,
|
stdout,
|
||||||
stderr,
|
stderr,
|
||||||
success: exit_code == 0,
|
success: *exit_code == 0,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
EventMsg::ExecCommandEnd(ExecCommandEndEvent {
|
EventMsg::ExecCommandEnd(ExecCommandEndEvent {
|
||||||
call_id: call_id.to_string(),
|
call_id: call_id.to_string(),
|
||||||
stdout,
|
stdout,
|
||||||
stderr,
|
stderr,
|
||||||
exit_code,
|
duration: *duration,
|
||||||
|
exit_code: *exit_code,
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1775,23 +1780,21 @@ async fn handle_container_exec_with_params(
|
|||||||
stdout,
|
stdout,
|
||||||
stderr,
|
stderr,
|
||||||
duration,
|
duration,
|
||||||
} = output;
|
} = &output;
|
||||||
|
|
||||||
sess.notify_exec_command_end(
|
sess.notify_exec_command_end(
|
||||||
&sub_id,
|
&sub_id,
|
||||||
&call_id,
|
&call_id,
|
||||||
&stdout,
|
&output,
|
||||||
&stderr,
|
|
||||||
exit_code,
|
|
||||||
exec_command_context.apply_patch.is_some(),
|
exec_command_context.apply_patch.is_some(),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let is_success = exit_code == 0;
|
let is_success = *exit_code == 0;
|
||||||
let content = format_exec_output(
|
let content = format_exec_output(
|
||||||
if is_success { &stdout } else { &stderr },
|
if is_success { stdout } else { stderr },
|
||||||
exit_code,
|
*exit_code,
|
||||||
duration,
|
*duration,
|
||||||
);
|
);
|
||||||
|
|
||||||
ResponseInputItem::FunctionCallOutput {
|
ResponseInputItem::FunctionCallOutput {
|
||||||
@@ -1900,23 +1903,16 @@ async fn handle_sandbox_error(
|
|||||||
stdout,
|
stdout,
|
||||||
stderr,
|
stderr,
|
||||||
duration,
|
duration,
|
||||||
} = retry_output;
|
} = &retry_output;
|
||||||
|
|
||||||
sess.notify_exec_command_end(
|
sess.notify_exec_command_end(&sub_id, &call_id, &retry_output, is_apply_patch)
|
||||||
&sub_id,
|
.await;
|
||||||
&call_id,
|
|
||||||
&stdout,
|
|
||||||
&stderr,
|
|
||||||
exit_code,
|
|
||||||
is_apply_patch,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
let is_success = exit_code == 0;
|
let is_success = *exit_code == 0;
|
||||||
let content = format_exec_output(
|
let content = format_exec_output(
|
||||||
if is_success { &stdout } else { &stderr },
|
if is_success { stdout } else { stderr },
|
||||||
exit_code,
|
*exit_code,
|
||||||
duration,
|
*duration,
|
||||||
);
|
);
|
||||||
|
|
||||||
ResponseInputItem::FunctionCallOutput {
|
ResponseInputItem::FunctionCallOutput {
|
||||||
|
|||||||
@@ -523,6 +523,8 @@ pub struct ExecCommandEndEvent {
|
|||||||
pub stderr: String,
|
pub stderr: String,
|
||||||
/// The command's exit code.
|
/// The command's exit code.
|
||||||
pub exit_code: i32,
|
pub exit_code: i32,
|
||||||
|
/// The duration of the command execution.
|
||||||
|
pub duration: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||||
|
|||||||
@@ -177,8 +177,7 @@ async fn live_shell_function_call() {
|
|||||||
match ev.msg {
|
match ev.msg {
|
||||||
EventMsg::ExecCommandBegin(codex_core::protocol::ExecCommandBeginEvent {
|
EventMsg::ExecCommandBegin(codex_core::protocol::ExecCommandBeginEvent {
|
||||||
command,
|
command,
|
||||||
call_id: _,
|
..
|
||||||
cwd: _,
|
|
||||||
}) => {
|
}) => {
|
||||||
assert_eq!(command, vec!["echo", MARKER]);
|
assert_eq!(command, vec!["echo", MARKER]);
|
||||||
saw_begin = true;
|
saw_begin = true;
|
||||||
@@ -186,8 +185,7 @@ async fn live_shell_function_call() {
|
|||||||
EventMsg::ExecCommandEnd(codex_core::protocol::ExecCommandEndEvent {
|
EventMsg::ExecCommandEnd(codex_core::protocol::ExecCommandEndEvent {
|
||||||
stdout,
|
stdout,
|
||||||
exit_code,
|
exit_code,
|
||||||
call_id: _,
|
..
|
||||||
stderr: _,
|
|
||||||
}) => {
|
}) => {
|
||||||
assert_eq!(exit_code, 0, "echo returned non‑zero exit code");
|
assert_eq!(exit_code, 0, "echo returned non‑zero exit code");
|
||||||
assert!(stdout.contains(MARKER));
|
assert!(stdout.contains(MARKER));
|
||||||
|
|||||||
@@ -106,7 +106,6 @@ impl EventProcessorWithHumanOutput {
|
|||||||
|
|
||||||
struct ExecCommandBegin {
|
struct ExecCommandBegin {
|
||||||
command: Vec<String>,
|
command: Vec<String>,
|
||||||
start_time: Instant,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PatchApplyBegin {
|
struct PatchApplyBegin {
|
||||||
@@ -228,7 +227,6 @@ impl EventProcessor for EventProcessorWithHumanOutput {
|
|||||||
call_id.clone(),
|
call_id.clone(),
|
||||||
ExecCommandBegin {
|
ExecCommandBegin {
|
||||||
command: command.clone(),
|
command: command.clone(),
|
||||||
start_time: Instant::now(),
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
ts_println!(
|
ts_println!(
|
||||||
@@ -244,16 +242,14 @@ impl EventProcessor for EventProcessorWithHumanOutput {
|
|||||||
call_id,
|
call_id,
|
||||||
stdout,
|
stdout,
|
||||||
stderr,
|
stderr,
|
||||||
|
duration,
|
||||||
exit_code,
|
exit_code,
|
||||||
}) => {
|
}) => {
|
||||||
let exec_command = self.call_id_to_command.remove(&call_id);
|
let exec_command = self.call_id_to_command.remove(&call_id);
|
||||||
let (duration, call) = if let Some(ExecCommandBegin {
|
let (duration, call) = if let Some(ExecCommandBegin { command, .. }) = exec_command
|
||||||
command,
|
|
||||||
start_time,
|
|
||||||
}) = exec_command
|
|
||||||
{
|
{
|
||||||
(
|
(
|
||||||
format!(" in {}", format_elapsed(start_time)),
|
format!(" in {}", format_duration(duration)),
|
||||||
format!("{}", escape_command(&command).style(self.bold)),
|
format!("{}", escape_command(&command).style(self.bold)),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
use codex_core::codex_wrapper::CodexConversation;
|
use codex_core::codex_wrapper::CodexConversation;
|
||||||
use codex_core::codex_wrapper::init_codex;
|
use codex_core::codex_wrapper::init_codex;
|
||||||
@@ -390,6 +389,7 @@ impl ChatWidget<'_> {
|
|||||||
EventMsg::ExecCommandEnd(ExecCommandEndEvent {
|
EventMsg::ExecCommandEnd(ExecCommandEndEvent {
|
||||||
call_id,
|
call_id,
|
||||||
exit_code,
|
exit_code,
|
||||||
|
duration,
|
||||||
stdout,
|
stdout,
|
||||||
stderr,
|
stderr,
|
||||||
}) => {
|
}) => {
|
||||||
@@ -400,7 +400,7 @@ impl ChatWidget<'_> {
|
|||||||
exit_code,
|
exit_code,
|
||||||
stdout,
|
stdout,
|
||||||
stderr,
|
stderr,
|
||||||
duration: Duration::from_secs(0),
|
duration,
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user