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:
Adam Perry @ OpenAI authored and GitHub committed 2026-06-18 05:00:04 +00:00
1 parent 285eff6c3e
commit 3931bc2bde
56 files changed
+566 -125

No files matched your search

@@ -1,10 +1,15 @@
use codex_protocol::AgentPath;
use codex_protocol::ThreadId;
use codex_protocol::protocol::EventMsg;
use codex_protocol::protocol::ExecCommandBeginEvent;
use codex_protocol::protocol::ExecCommandEndEvent;
use codex_protocol::protocol::ExecCommandSource;
use codex_protocol::protocol::ExecCommandStatus;
use codex_protocol::protocol::SubAgentActivityEvent;
use codex_protocol::protocol::SubAgentActivityKind;
use pretty_assertions::assert_eq;
use serde_json::json;
use std::time::Duration;
use super::ToolRuntimeTraceEvent;
use super::tool_runtime_trace_event;
@@ -44,3 +49,81 @@ fn sub_agent_activity_is_a_terminal_tool_runtime_event() -> anyhow::Result<()> {
);
Ok(())
}
#[test]
fn exec_command_trace_payloads_use_inferred_native_cwd() -> anyhow::Result<()> {
// Convention inference depends on the URI spelling, not the test host, so exercise both
// Windows and POSIX paths on every platform.
let begin = EventMsg::ExecCommandBegin(ExecCommandBeginEvent {
call_id: "call-begin".to_string(),
process_id: Some("process-1".to_string()),
turn_id: "turn-1".to_string(),
started_at_ms: 1234,
command: vec!["pwd".to_string()],
cwd: "file:///C:/windows".parse()?,
parsed_cmd: Vec::new(),
source: ExecCommandSource::Agent,
interaction_input: None,
});
let end = EventMsg::ExecCommandEnd(ExecCommandEndEvent {
call_id: "call-end".to_string(),
process_id: None,
turn_id: "turn-1".to_string(),
completed_at_ms: 2345,
command: vec!["pwd".to_string()],
cwd: "file:///workspace/project".parse()?,
parsed_cmd: Vec::new(),
source: ExecCommandSource::UnifiedExecInteraction,
interaction_input: Some("input".to_string()),
stdout: "output".to_string(),
stderr: String::new(),
aggregated_output: "output".to_string(),
exit_code: 0,
duration: Duration::from_millis(250),
formatted_output: "output".to_string(),
status: ExecCommandStatus::Completed,
});
let Some(ToolRuntimeTraceEvent::Started { payload, .. }) = tool_runtime_trace_event(&begin)
else {
panic!("expected started tool runtime event");
};
assert_eq!(
serde_json::to_value(payload)?,
json!({
"call_id": "call-begin",
"process_id": "process-1",
"turn_id": "turn-1",
"started_at_ms": 1234,
"command": ["pwd"],
"cwd": r"C:\windows",
"parsed_cmd": [],
"source": "agent"
})
);
let Some(ToolRuntimeTraceEvent::Ended { payload, .. }) = tool_runtime_trace_event(&end) else {
panic!("expected ended tool runtime event");
};
assert_eq!(
serde_json::to_value(payload)?,
json!({
"call_id": "call-end",
"turn_id": "turn-1",
"completed_at_ms": 2345,
"command": ["pwd"],
"cwd": "/workspace/project",
"parsed_cmd": [],
"source": "unified_exec_interaction",
"interaction_input": "input",
"stdout": "output",
"stderr": "",
"aggregated_output": "output",
"exit_code": 0,
"duration": {"secs": 0, "nanos": 250000000},
"formatted_output": "output",
"status": "completed"
})
);
Ok(())
}