mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Fix quoted command rendering in tui_app_server (#15825)
When `tui_app_server` is enabled, shell commands in the transcript render as fully quoted invocations like `/bin/zsh -lc "..."`. The non-app-server TUI correctly shows the parsed command body. Root cause: The app-server stores `ThreadItem::CommandExecution.command` as a shell-quoted string. When `tui_app_server` bridges that item back into the exec renderer, it was passing `vec![command]` unchanged instead of splitting the string back into argv. That prevented `strip_bash_lc_and_escape()` from recognizing the shell wrapper, so the renderer displayed the wrapper literally. Solution: Add a shared command-string splitter that round-trips shell-quoted commands back into argv when it is safe to do so, while preserving non-roundtrippable inputs as a single string. Use that helper everywhere `tui_app_server` reconstructs exec commands from app-server payloads, including live command-execution items, replayed thread items, and exec approval requests. This restores the same command display behavior as the direct TUI path without breaking Windows-style commands that cannot be safely round-tripped.
This commit is contained in:
committed by
GitHub
Unverified
parent
4b50446ffa
commit
b565f05d79
@@ -16,6 +16,22 @@ pub(crate) fn strip_bash_lc_and_escape(command: &[String]) -> String {
|
||||
escape_command(command)
|
||||
}
|
||||
|
||||
pub(crate) fn split_command_string(command: &str) -> Vec<String> {
|
||||
let Some(parts) = shlex::split(command) else {
|
||||
return vec![command.to_string()];
|
||||
};
|
||||
match shlex::try_join(parts.iter().map(String::as_str)) {
|
||||
Ok(round_trip)
|
||||
if round_trip == command
|
||||
|| (!command.contains(":\\")
|
||||
&& shlex::split(&round_trip).as_ref() == Some(&parts)) =>
|
||||
{
|
||||
parts
|
||||
}
|
||||
_ => vec![command.to_string()],
|
||||
}
|
||||
}
|
||||
|
||||
/// If `path` is absolute and inside $HOME, return the part *after* the home
|
||||
/// directory; otherwise, return the path as-is. Note if `path` is the homedir,
|
||||
/// this will return and empty path.
|
||||
@@ -67,4 +83,25 @@ mod tests {
|
||||
let cmdline = strip_bash_lc_and_escape(&args);
|
||||
assert_eq!(cmdline, "echo hello");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn split_command_string_round_trips_shell_wrappers() {
|
||||
let command =
|
||||
shlex::try_join(["/bin/zsh", "-lc", r#"python3 -c 'print("Hello, world!")'"#])
|
||||
.expect("round-trippable command");
|
||||
assert_eq!(
|
||||
split_command_string(&command),
|
||||
vec![
|
||||
"/bin/zsh".to_string(),
|
||||
"-lc".to_string(),
|
||||
r#"python3 -c 'print("Hello, world!")'"#.to_string(),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn split_command_string_preserves_non_roundtrippable_windows_commands() {
|
||||
let command = r#"C:\Program Files\Git\bin\bash.exe -lc "echo hi""#;
|
||||
assert_eq!(split_command_string(command), vec![command.to_string()]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user