Fix: update parallel tool call exec approval to approve on request id (#11162)

### Summary

In parallel tool call, exec command approvals were not approved at
request level but at a turn level. i.e. when a single request is
approved, the system currently treats all requests in turn as approved.

### Before

https://github.com/user-attachments/assets/d50ed129-b3d2-4b2f-97fa-8601eb11f6a8

### After

https://github.com/user-attachments/assets/36528a43-a4aa-4775-9e12-f13287ef19fc
This commit is contained in:
Shijie Rao
2026-02-10 09:38:00 -08:00
committed by GitHub
parent 47356ff83c
commit c4b771a16f
15 changed files with 190 additions and 135 deletions

View File

@@ -1032,11 +1032,16 @@ async fn handle_container_exec_user_approved_records_tool_decision() {
.await
.unwrap();
wait_for_event(&codex, |ev| matches!(ev, EventMsg::ExecApprovalRequest(_))).await;
let approval_event =
wait_for_event(&codex, |ev| matches!(ev, EventMsg::ExecApprovalRequest(_))).await;
let EventMsg::ExecApprovalRequest(approval) = approval_event else {
panic!("expected ExecApprovalRequest event");
};
codex
.submit(Op::ExecApproval {
id: "0".into(),
id: approval.call_id,
turn_id: None,
decision: ReviewDecision::Approved,
})
.await
@@ -1092,11 +1097,16 @@ async fn handle_container_exec_user_approved_for_session_records_tool_decision()
.await
.unwrap();
wait_for_event(&codex, |ev| matches!(ev, EventMsg::ExecApprovalRequest(_))).await;
let approval_event =
wait_for_event(&codex, |ev| matches!(ev, EventMsg::ExecApprovalRequest(_))).await;
let EventMsg::ExecApprovalRequest(approval) = approval_event else {
panic!("expected ExecApprovalRequest event");
};
codex
.submit(Op::ExecApproval {
id: "0".into(),
id: approval.call_id,
turn_id: None,
decision: ReviewDecision::ApprovedForSession,
})
.await
@@ -1152,11 +1162,16 @@ async fn handle_sandbox_error_user_approves_retry_records_tool_decision() {
.await
.unwrap();
wait_for_event(&codex, |ev| matches!(ev, EventMsg::ExecApprovalRequest(_))).await;
let approval_event =
wait_for_event(&codex, |ev| matches!(ev, EventMsg::ExecApprovalRequest(_))).await;
let EventMsg::ExecApprovalRequest(approval) = approval_event else {
panic!("expected ExecApprovalRequest event");
};
codex
.submit(Op::ExecApproval {
id: "0".into(),
id: approval.call_id,
turn_id: None,
decision: ReviewDecision::Approved,
})
.await
@@ -1212,11 +1227,16 @@ async fn handle_container_exec_user_denies_records_tool_decision() {
.await
.unwrap();
wait_for_event(&codex, |ev| matches!(ev, EventMsg::ExecApprovalRequest(_))).await;
let approval_event =
wait_for_event(&codex, |ev| matches!(ev, EventMsg::ExecApprovalRequest(_))).await;
let EventMsg::ExecApprovalRequest(approval) = approval_event else {
panic!("expected ExecApprovalRequest event");
};
codex
.submit(Op::ExecApproval {
id: "0".into(),
id: approval.call_id,
turn_id: None,
decision: ReviewDecision::Denied,
})
.await
@@ -1272,11 +1292,16 @@ async fn handle_sandbox_error_user_approves_for_session_records_tool_decision()
.await
.unwrap();
wait_for_event(&codex, |ev| matches!(ev, EventMsg::ExecApprovalRequest(_))).await;
let approval_event =
wait_for_event(&codex, |ev| matches!(ev, EventMsg::ExecApprovalRequest(_))).await;
let EventMsg::ExecApprovalRequest(approval) = approval_event else {
panic!("expected ExecApprovalRequest event");
};
codex
.submit(Op::ExecApproval {
id: "0".into(),
id: approval.call_id,
turn_id: None,
decision: ReviewDecision::ApprovedForSession,
})
.await
@@ -1333,11 +1358,16 @@ async fn handle_sandbox_error_user_denies_records_tool_decision() {
.await
.unwrap();
wait_for_event(&codex, |ev| matches!(ev, EventMsg::ExecApprovalRequest(_))).await;
let approval_event =
wait_for_event(&codex, |ev| matches!(ev, EventMsg::ExecApprovalRequest(_))).await;
let EventMsg::ExecApprovalRequest(approval) = approval_event else {
panic!("expected ExecApprovalRequest event");
};
codex
.submit(Op::ExecApproval {
id: "0".into(),
id: approval.call_id,
turn_id: None,
decision: ReviewDecision::Denied,
})
.await