mirror of
https://github.com/openai/codex.git
synced 2026-10-19 17:28:46 +00:00
## What changed - Add optional `plugin_id` and `script_path` fields to execution approval and guardian assessment events. - Propagate validated plugin attribution through delegated approvals, guardian-reviewed command items, app-server notifications, thread history, and rollout traces. - Preserve attribution on both started and completed command items, including declined commands. ## Testing - Extend core, app-server, thread-history, and rollout-trace tests to cover plugin attribution propagation and serialization. GitOrigin-RevId: 723684d010cab04142918d7a95e06ed95d008da1
138 lines
4.7 KiB
Rust
138 lines
4.7 KiB
Rust
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;
|
|
use crate::ExecutionStatus;
|
|
|
|
#[test]
|
|
fn sub_agent_activity_is_a_terminal_tool_runtime_event() -> anyhow::Result<()> {
|
|
let agent_thread_id = ThreadId::new();
|
|
let event = EventMsg::SubAgentActivity(SubAgentActivityEvent {
|
|
event_id: "call-spawn".to_string(),
|
|
occurred_at_ms: 1234,
|
|
agent_thread_id,
|
|
agent_path: AgentPath::try_from("/root/reviewer").map_err(anyhow::Error::msg)?,
|
|
kind: SubAgentActivityKind::Started,
|
|
});
|
|
|
|
let Some(ToolRuntimeTraceEvent::Ended {
|
|
tool_call_id,
|
|
status,
|
|
payload,
|
|
}) = tool_runtime_trace_event(&event)
|
|
else {
|
|
panic!("expected terminal tool runtime event");
|
|
};
|
|
|
|
assert_eq!(tool_call_id, "call-spawn");
|
|
assert_eq!(status, ExecutionStatus::Completed);
|
|
assert_eq!(
|
|
serde_json::to_value(payload)?,
|
|
json!({
|
|
"event_id": "call-spawn",
|
|
"occurred_at_ms": 1234,
|
|
"agent_thread_id": agent_thread_id,
|
|
"agent_path": "/root/reviewer",
|
|
"kind": "started"
|
|
})
|
|
);
|
|
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(),
|
|
plugin_id: Some("sample@openai-curated".to_string()),
|
|
script_path: Some("scripts/run.py".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(),
|
|
plugin_id: Some("sample@openai-curated".to_string()),
|
|
script_path: Some("scripts/run.py".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",
|
|
"plugin_id": "sample@openai-curated",
|
|
"script_path": "scripts/run.py",
|
|
"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",
|
|
"plugin_id": "sample@openai-curated",
|
|
"script_path": "scripts/run.py",
|
|
"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(())
|
|
}
|