mirror of
https://github.com/openai/codex.git
synced 2026-04-28 18:32:04 +03:00
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:
@@ -1528,7 +1528,8 @@ async fn run_scenario(scenario: &ScenarioSpec) -> Result<()> {
|
||||
}
|
||||
test.codex
|
||||
.submit(Op::ExecApproval {
|
||||
id: "0".into(),
|
||||
id: approval.call_id,
|
||||
turn_id: None,
|
||||
decision: decision.clone(),
|
||||
})
|
||||
.await?;
|
||||
@@ -1549,7 +1550,7 @@ async fn run_scenario(scenario: &ScenarioSpec) -> Result<()> {
|
||||
}
|
||||
test.codex
|
||||
.submit(Op::PatchApproval {
|
||||
id: "0".into(),
|
||||
id: approval.call_id,
|
||||
decision: decision.clone(),
|
||||
})
|
||||
.await?;
|
||||
@@ -1624,10 +1625,10 @@ async fn approving_apply_patch_for_session_skips_future_prompts_for_same_file()
|
||||
sandbox_policy.clone(),
|
||||
)
|
||||
.await?;
|
||||
let _ = expect_patch_approval(&test, call_id_1).await;
|
||||
let approval = expect_patch_approval(&test, call_id_1).await;
|
||||
test.codex
|
||||
.submit(Op::PatchApproval {
|
||||
id: "0".into(),
|
||||
id: approval.call_id,
|
||||
decision: ReviewDecision::ApprovedForSession,
|
||||
})
|
||||
.await?;
|
||||
@@ -1746,7 +1747,8 @@ async fn approving_execpolicy_amendment_persists_policy_and_skips_future_prompts
|
||||
|
||||
test.codex
|
||||
.submit(Op::ExecApproval {
|
||||
id: "0".into(),
|
||||
id: approval.call_id,
|
||||
turn_id: None,
|
||||
decision: ReviewDecision::ApprovedExecpolicyAmendment {
|
||||
proposed_execpolicy_amendment: expected_execpolicy_amendment.clone(),
|
||||
},
|
||||
|
||||
@@ -87,15 +87,19 @@ async fn codex_delegate_forwards_exec_approval_and_proceeds_on_approval() {
|
||||
.await;
|
||||
|
||||
// Expect parent-side approval request (forwarded by delegate).
|
||||
wait_for_event(&test.codex, |ev| {
|
||||
let approval_event = wait_for_event(&test.codex, |ev| {
|
||||
matches!(ev, EventMsg::ExecApprovalRequest(_))
|
||||
})
|
||||
.await;
|
||||
let EventMsg::ExecApprovalRequest(approval) = approval_event else {
|
||||
panic!("expected ExecApprovalRequest event");
|
||||
};
|
||||
|
||||
// Approve via parent; id "0" is the active sub_id in tests.
|
||||
// Approve via parent using the emitted approval call ID.
|
||||
test.codex
|
||||
.submit(Op::ExecApproval {
|
||||
id: "0".into(),
|
||||
id: approval.call_id,
|
||||
turn_id: None,
|
||||
decision: ReviewDecision::Approved,
|
||||
})
|
||||
.await
|
||||
@@ -161,15 +165,18 @@ async fn codex_delegate_forwards_patch_approval_and_proceeds_on_decision() {
|
||||
matches!(ev, EventMsg::EnteredReviewMode(_))
|
||||
})
|
||||
.await;
|
||||
wait_for_event(&test.codex, |ev| {
|
||||
let approval_event = wait_for_event(&test.codex, |ev| {
|
||||
matches!(ev, EventMsg::ApplyPatchApprovalRequest(_))
|
||||
})
|
||||
.await;
|
||||
let EventMsg::ApplyPatchApprovalRequest(approval) = approval_event else {
|
||||
panic!("expected ApplyPatchApprovalRequest event");
|
||||
};
|
||||
|
||||
// Deny via parent so delegate can continue; id "0" is the active sub_id in tests.
|
||||
// Deny via parent so delegate can continue, using the emitted approval call ID.
|
||||
test.codex
|
||||
.submit(Op::PatchApproval {
|
||||
id: "0".into(),
|
||||
id: approval.call_id,
|
||||
decision: ReviewDecision::Denied,
|
||||
})
|
||||
.await
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user