mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
unified-exec: retain PathUri in command events (#28780)
## Why App-server must report command events containing foreign-platform paths without changing existing client or rollout path-string formats. ## What changed - retain `PathUri` through exec command begin/end events - convert cwd values to `LegacyAppPathString` at the app-server compatibility boundary - drop command actions with foreign paths and log them - serialize rollout-trace cwd values using their inferred native path representation - restore Wine coverage for retained Windows cwd values and successful completion
This commit is contained in:
1 parent
285eff6c3e
commit
3931bc2bde
56 files changed
+566
-125
No files matched your search
@@ -23,6 +23,7 @@ use crate::protocol::v2::PatchApplyStatus;
|
||||
use crate::protocol::v2::PatchChangeKind;
|
||||
use crate::protocol::v2::ThreadItem;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::parse_command::ParsedCommand;
|
||||
use codex_protocol::protocol::ApplyPatchApprovalRequestEvent;
|
||||
use codex_protocol::protocol::ExecApprovalRequestEvent;
|
||||
use codex_protocol::protocol::ExecCommandBeginEvent;
|
||||
@@ -34,8 +35,11 @@ use codex_protocol::protocol::PatchApplyBeginEvent;
|
||||
use codex_protocol::protocol::PatchApplyEndEvent;
|
||||
use codex_shell_command::parse_command::parse_command;
|
||||
use codex_shell_command::parse_command::shlex_join;
|
||||
use codex_utils_path_uri::PathConvention;
|
||||
use codex_utils_path_uri::PathUri;
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use tracing::warn;
|
||||
|
||||
pub fn build_file_change_approval_request_item(
|
||||
payload: &ApplyPatchApprovalRequestEvent,
|
||||
@@ -69,7 +73,7 @@ pub fn build_command_execution_approval_request_item(
|
||||
ThreadItem::CommandExecution {
|
||||
id: payload.call_id.clone(),
|
||||
command: shlex_join(&payload.command),
|
||||
cwd: payload.cwd.clone(),
|
||||
cwd: payload.cwd.clone().into(),
|
||||
process_id: None,
|
||||
source: CommandExecutionSource::Agent,
|
||||
status: CommandExecutionStatus::InProgress,
|
||||
@@ -86,19 +90,15 @@ pub fn build_command_execution_approval_request_item(
|
||||
}
|
||||
|
||||
pub fn build_command_execution_begin_item(payload: &ExecCommandBeginEvent) -> ThreadItem {
|
||||
let command_actions = command_actions_for_path_uri(&payload.parsed_cmd, &payload.cwd);
|
||||
ThreadItem::CommandExecution {
|
||||
id: payload.call_id.clone(),
|
||||
command: shlex_join(&payload.command),
|
||||
cwd: payload.cwd.clone(),
|
||||
cwd: payload.cwd.clone().into(),
|
||||
process_id: payload.process_id.clone(),
|
||||
source: payload.source.into(),
|
||||
status: CommandExecutionStatus::InProgress,
|
||||
command_actions: payload
|
||||
.parsed_cmd
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|parsed| CommandAction::from_core_with_cwd(parsed, &payload.cwd))
|
||||
.collect(),
|
||||
command_actions,
|
||||
aggregated_output: None,
|
||||
exit_code: None,
|
||||
duration_ms: None,
|
||||
@@ -112,26 +112,63 @@ pub fn build_command_execution_end_item(payload: &ExecCommandEndEvent) -> Thread
|
||||
Some(payload.aggregated_output.clone())
|
||||
};
|
||||
let duration_ms = i64::try_from(payload.duration.as_millis()).unwrap_or(i64::MAX);
|
||||
let command_actions = command_actions_for_path_uri(&payload.parsed_cmd, &payload.cwd);
|
||||
|
||||
ThreadItem::CommandExecution {
|
||||
id: payload.call_id.clone(),
|
||||
command: shlex_join(&payload.command),
|
||||
cwd: payload.cwd.clone(),
|
||||
cwd: payload.cwd.clone().into(),
|
||||
process_id: payload.process_id.clone(),
|
||||
source: payload.source.into(),
|
||||
status: (&payload.status).into(),
|
||||
command_actions: payload
|
||||
.parsed_cmd
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|parsed| CommandAction::from_core_with_cwd(parsed, &payload.cwd))
|
||||
.collect(),
|
||||
command_actions,
|
||||
aggregated_output,
|
||||
exit_code: Some(payload.exit_code),
|
||||
duration_ms: Some(duration_ms),
|
||||
}
|
||||
}
|
||||
|
||||
fn command_actions_for_path_uri(parsed_cmd: &[ParsedCommand], cwd: &PathUri) -> Vec<CommandAction> {
|
||||
// TODO(anp): Carry PathUri into CommandAction so foreign Read actions retain resolved paths.
|
||||
// Until then, omit those actions rather than project a foreign cwd onto the host.
|
||||
let native_cwd = if cwd.infer_path_convention() == Some(PathConvention::native()) {
|
||||
cwd.to_abs_path().ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
parsed_cmd
|
||||
.iter()
|
||||
.cloned()
|
||||
.filter_map(|parsed| match parsed {
|
||||
ParsedCommand::Read { cmd, name, path } => match native_cwd.as_ref() {
|
||||
Some(native_cwd) => Some(CommandAction::Read {
|
||||
command: cmd,
|
||||
name,
|
||||
path: native_cwd.join(path),
|
||||
}),
|
||||
None => {
|
||||
warn!(
|
||||
command = cmd,
|
||||
%cwd,
|
||||
"omitting read command action whose path cannot be resolved against a foreign cwd"
|
||||
);
|
||||
None
|
||||
}
|
||||
},
|
||||
ParsedCommand::ListFiles { cmd, path } => {
|
||||
Some(CommandAction::ListFiles { command: cmd, path })
|
||||
}
|
||||
ParsedCommand::Search { cmd, query, path } => Some(CommandAction::Search {
|
||||
command: cmd,
|
||||
query,
|
||||
path,
|
||||
}),
|
||||
ParsedCommand::Unknown { cmd } => Some(CommandAction::Unknown { command: cmd }),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Build a guardian-derived [`ThreadItem`].
|
||||
///
|
||||
/// Currently this only synthesizes [`ThreadItem::CommandExecution`] for
|
||||
@@ -150,7 +187,7 @@ pub fn build_item_from_guardian_event(
|
||||
Some(ThreadItem::CommandExecution {
|
||||
id: id.clone(),
|
||||
command,
|
||||
cwd: cwd.clone(),
|
||||
cwd: cwd.clone().into(),
|
||||
process_id: None,
|
||||
source: CommandExecutionSource::Agent,
|
||||
status,
|
||||
@@ -186,7 +223,7 @@ pub fn build_item_from_guardian_event(
|
||||
Some(ThreadItem::CommandExecution {
|
||||
id: id.clone(),
|
||||
command,
|
||||
cwd: cwd.clone(),
|
||||
cwd: cwd.clone().into(),
|
||||
process_id: None,
|
||||
source: CommandExecutionSource::Agent,
|
||||
status,
|
||||
@@ -315,3 +352,7 @@ fn format_file_change_diff(change: &FileChange) -> String {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "item_builders_tests.rs"]
|
||||
mod tests;
|
||||
Reference in new issue
Block a user