mirror of
https://github.com/openai/codex.git
synced 2026-09-13 11:47:17 +00:00
initial draft
This commit is contained in:
@@ -4636,14 +4636,7 @@ async fn tool_call_metadata_stamps_guardian_direct_review_when_feature_enabled()
|
||||
async fn tool_call_metadata_stamps_policy_source_without_review_decision_when_feature_enabled() {
|
||||
let (sess, tc, rx, expected_sandbox_policy) = setup_tool_call_metadata_runtime_test().await;
|
||||
|
||||
sess.record_call_approval_outcome(
|
||||
"call-policy-runtime-1".to_string(),
|
||||
ApprovalOutcomeMetadata {
|
||||
review_decision: None,
|
||||
approval_source: codex_protocol::models::ApprovalSourceMetadata::Policy,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
sess.record_policy_outcome("call-policy-runtime-1").await;
|
||||
sess.record_response_item_and_emit_turn_item(
|
||||
tc.as_ref(),
|
||||
function_call_item("call-policy-runtime-1"),
|
||||
@@ -4794,6 +4787,87 @@ async fn tool_call_metadata_can_be_restamped_after_approval_outcome() {
|
||||
));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn tool_call_metadata_snapshot_stamps_guardian_approval_source() {
|
||||
let (_session, turn_context_raw) = make_session_and_context().await;
|
||||
let turn_context = Arc::new(turn_context_raw);
|
||||
let expected_sandbox_policy = sandbox_policy_to_metadata(turn_context.sandbox_policy.get());
|
||||
let item = ResponseItem::FunctionCall {
|
||||
id: None,
|
||||
name: "shell".to_string(),
|
||||
namespace: None,
|
||||
arguments: "{}".to_string(),
|
||||
call_id: "call-guardian-1".to_string(),
|
||||
metadata: None,
|
||||
};
|
||||
let snapshot = ToolApprovalMetadataSnapshot {
|
||||
approval_outcomes_by_call_id: HashMap::from([(
|
||||
"call-guardian-1".to_string(),
|
||||
crate::state::ApprovalOutcomeMetadata {
|
||||
review_decision: Some(codex_protocol::models::ReviewDecisionMetadata::Denied),
|
||||
approval_source: codex_protocol::models::ApprovalSourceMetadata::Guardian,
|
||||
},
|
||||
)]),
|
||||
pending_approval_call_ids: HashSet::new(),
|
||||
};
|
||||
|
||||
let stamped =
|
||||
stamp_tool_approval_metadata_with_snapshot(turn_context.as_ref(), item, Some(&snapshot));
|
||||
|
||||
assert!(matches!(
|
||||
stamped,
|
||||
ResponseItem::FunctionCall {
|
||||
metadata: Some(metadata),
|
||||
..
|
||||
} if metadata.is_tool_call_escalated == Some(true)
|
||||
&& metadata.review_decision
|
||||
== Some(codex_protocol::models::ReviewDecisionMetadata::Denied)
|
||||
&& metadata.approval_source
|
||||
== Some(codex_protocol::models::ApprovalSourceMetadata::Guardian)
|
||||
&& metadata.sandbox_policy == Some(expected_sandbox_policy)
|
||||
));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn tool_call_metadata_snapshot_stamps_policy_approval_source_without_review_decision() {
|
||||
let (_session, turn_context_raw) = make_session_and_context().await;
|
||||
let turn_context = Arc::new(turn_context_raw);
|
||||
let expected_sandbox_policy = sandbox_policy_to_metadata(turn_context.sandbox_policy.get());
|
||||
let item = ResponseItem::FunctionCall {
|
||||
id: None,
|
||||
name: "shell".to_string(),
|
||||
namespace: None,
|
||||
arguments: "{}".to_string(),
|
||||
call_id: "call-policy-1".to_string(),
|
||||
metadata: None,
|
||||
};
|
||||
let snapshot = ToolApprovalMetadataSnapshot {
|
||||
approval_outcomes_by_call_id: HashMap::from([(
|
||||
"call-policy-1".to_string(),
|
||||
crate::state::ApprovalOutcomeMetadata {
|
||||
review_decision: None,
|
||||
approval_source: codex_protocol::models::ApprovalSourceMetadata::Policy,
|
||||
},
|
||||
)]),
|
||||
pending_approval_call_ids: HashSet::new(),
|
||||
};
|
||||
|
||||
let stamped =
|
||||
stamp_tool_approval_metadata_with_snapshot(turn_context.as_ref(), item, Some(&snapshot));
|
||||
|
||||
assert!(matches!(
|
||||
stamped,
|
||||
ResponseItem::FunctionCall {
|
||||
metadata: Some(metadata),
|
||||
..
|
||||
} if metadata.is_tool_call_escalated == Some(true)
|
||||
&& metadata.review_decision.is_none()
|
||||
&& metadata.approval_source
|
||||
== Some(codex_protocol::models::ApprovalSourceMetadata::Policy)
|
||||
&& metadata.sandbox_policy == Some(expected_sandbox_policy)
|
||||
));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn steer_input_requires_active_turn() {
|
||||
let (sess, _tc, _rx) = make_session_and_context_with_rx().await;
|
||||
|
||||
@@ -532,30 +532,14 @@ impl CoreShellActionProvider {
|
||||
) -> anyhow::Result<EscalationDecision> {
|
||||
let action = match decision {
|
||||
Decision::Forbidden => {
|
||||
self.session
|
||||
.record_call_approval_outcome(
|
||||
self.call_id.clone(),
|
||||
ApprovalOutcomeMetadata {
|
||||
review_decision: None,
|
||||
approval_source: ApprovalSourceMetadata::Policy,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
self.session.record_policy_outcome(&self.call_id).await;
|
||||
EscalationDecision::deny(Some("Execution forbidden by policy".to_string()))
|
||||
}
|
||||
Decision::Prompt => {
|
||||
if execve_prompt_is_rejected_by_policy(self.approval_policy, &decision_source)
|
||||
.is_some()
|
||||
{
|
||||
self.session
|
||||
.record_call_approval_outcome(
|
||||
self.call_id.clone(),
|
||||
ApprovalOutcomeMetadata {
|
||||
review_decision: None,
|
||||
approval_source: ApprovalSourceMetadata::Policy,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
self.session.record_policy_outcome(&self.call_id).await;
|
||||
EscalationDecision::deny(Some("Execution forbidden by policy".to_string()))
|
||||
} else {
|
||||
match self
|
||||
|
||||
Reference in New Issue
Block a user