mirror of
https://github.com/openai/codex.git
synced 2026-10-31 19:28:49 +00:00
Use model-specific auto-review outcome instructions (#39741)
## What changed - Add `rejection_instructions` and `timeout_instructions` to catalog-provided auto-review messages. - Use the acting model's instructions for denied and timed-out reviews across tool approvals, shell escalation, and MCP elicitation responses. - Fall back to the existing instructions only when a catalog value is absent, while preserving explicit empty-string overrides. ## Testing - Cover catalog overrides, legacy fallbacks, empty values, and separation between acting-model and reviewer-model messages. GitOrigin-RevId: c5b2c2dbdaefd45d1d658651dd1abaeb6d8c93da
This commit is contained in:
@@ -29,6 +29,7 @@ use codex_protocol::mcp_approval_meta::TOOL_DESCRIPTION_KEY as MCP_ELICITATION_T
|
||||
use codex_protocol::mcp_approval_meta::TOOL_NAME_KEY as MCP_ELICITATION_TOOL_NAME_KEY;
|
||||
use codex_protocol::mcp_approval_meta::TOOL_PARAMS_KEY as MCP_ELICITATION_TOOL_PARAMS_KEY;
|
||||
use codex_protocol::mcp_approval_meta::TOOL_TITLE_KEY as MCP_ELICITATION_TOOL_TITLE_KEY;
|
||||
use codex_protocol::openai_models::ModelInfo;
|
||||
use codex_rmcp_client::Elicitation;
|
||||
use rmcp::model::ElicitationAction;
|
||||
use rmcp::model::RequestMetaObject;
|
||||
@@ -784,8 +785,9 @@ async fn review_guardian_mcp_elicitation(
|
||||
)
|
||||
.await;
|
||||
|
||||
return Ok(matches!(decision, ReviewDecision::Approved)
|
||||
.then(|| mcp_elicitation_response_from_guardian_decision(decision)));
|
||||
return Ok(matches!(decision, ReviewDecision::Approved).then(|| {
|
||||
mcp_elicitation_response_from_guardian_decision(decision, &turn_context.model_info)
|
||||
}));
|
||||
}
|
||||
|
||||
let approval_policy = mcp_config.approval_policy.value();
|
||||
@@ -855,6 +857,7 @@ async fn review_guardian_mcp_elicitation(
|
||||
.await;
|
||||
Ok(Some(mcp_elicitation_response_from_guardian_decision(
|
||||
decision,
|
||||
&turn_context.model_info,
|
||||
)))
|
||||
}
|
||||
|
||||
@@ -1005,6 +1008,7 @@ fn mcp_elicitation_request_id(id: &RequestId) -> String {
|
||||
|
||||
fn mcp_elicitation_response_from_guardian_decision(
|
||||
decision: ReviewDecision,
|
||||
model_info: &ModelInfo,
|
||||
) -> ElicitationResponse {
|
||||
match decision {
|
||||
ReviewDecision::Approved
|
||||
@@ -1017,9 +1021,9 @@ fn mcp_elicitation_response_from_guardian_decision(
|
||||
meta: Some(mcp_elicitation_auto_meta()),
|
||||
},
|
||||
ReviewDecision::Denied { rejection } => mcp_elicitation_decline_with_message(rejection),
|
||||
ReviewDecision::TimedOut => {
|
||||
mcp_elicitation_decline_with_message(crate::guardian::guardian_timeout_message())
|
||||
}
|
||||
ReviewDecision::TimedOut => mcp_elicitation_decline_with_message(
|
||||
crate::guardian::guardian_timeout_message(model_info),
|
||||
),
|
||||
ReviewDecision::Abort => ElicitationResponse {
|
||||
action: ElicitationAction::Cancel,
|
||||
content: None,
|
||||
|
||||
@@ -217,8 +217,9 @@ fn guardian_elicitation_review_request_declines_unsupported_opt_in_shapes() {
|
||||
|
||||
#[test]
|
||||
fn guardian_decisions_map_to_elicitation_responses_without_session_state() {
|
||||
let model = codex_models_manager::model_info::model_info_from_slug("acting-model");
|
||||
assert_eq!(
|
||||
mcp_elicitation_response_from_guardian_decision(ReviewDecision::Approved),
|
||||
mcp_elicitation_response_from_guardian_decision(ReviewDecision::Approved, &model),
|
||||
ElicitationResponse {
|
||||
action: ElicitationAction::Accept,
|
||||
content: Some(json!({})),
|
||||
@@ -228,9 +229,10 @@ fn guardian_decisions_map_to_elicitation_responses_without_session_state() {
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
mcp_elicitation_response_from_guardian_decision(ReviewDecision::denied(
|
||||
"Denied by Guardian",
|
||||
)),
|
||||
mcp_elicitation_response_from_guardian_decision(
|
||||
ReviewDecision::denied("Denied by Guardian"),
|
||||
&model,
|
||||
),
|
||||
ElicitationResponse {
|
||||
action: ElicitationAction::Decline,
|
||||
content: None,
|
||||
@@ -241,18 +243,18 @@ fn guardian_decisions_map_to_elicitation_responses_without_session_state() {
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
mcp_elicitation_response_from_guardian_decision(ReviewDecision::TimedOut),
|
||||
mcp_elicitation_response_from_guardian_decision(ReviewDecision::TimedOut, &model),
|
||||
ElicitationResponse {
|
||||
action: ElicitationAction::Decline,
|
||||
content: None,
|
||||
meta: Some(json!({
|
||||
"approvals_reviewer": ApprovalsReviewer::AutoReview,
|
||||
"message": crate::guardian::guardian_timeout_message(),
|
||||
"message": crate::guardian::guardian_timeout_message(&model),
|
||||
})),
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
mcp_elicitation_response_from_guardian_decision(ReviewDecision::Abort),
|
||||
mcp_elicitation_response_from_guardian_decision(ReviewDecision::Abort, &model),
|
||||
ElicitationResponse {
|
||||
action: ElicitationAction::Cancel,
|
||||
content: None,
|
||||
@@ -262,3 +264,29 @@ fn guardian_decisions_map_to_elicitation_responses_without_session_state() {
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn guardian_elicitation_timeout_uses_acting_model_instructions() {
|
||||
let mut model = codex_models_manager::model_info::model_info_from_slug("acting-model");
|
||||
for timeout_instructions in ["Catalog timeout instructions.", ""] {
|
||||
model.model_messages = Some(
|
||||
serde_json::from_value(json!({
|
||||
"auto_review": {
|
||||
"timeout_instructions": timeout_instructions,
|
||||
},
|
||||
}))
|
||||
.expect("model messages should deserialize"),
|
||||
);
|
||||
assert_eq!(
|
||||
mcp_elicitation_response_from_guardian_decision(ReviewDecision::TimedOut, &model),
|
||||
ElicitationResponse {
|
||||
action: ElicitationAction::Decline,
|
||||
content: None,
|
||||
meta: Some(json!({
|
||||
"approvals_reviewer": ApprovalsReviewer::AutoReview,
|
||||
"message": timeout_instructions,
|
||||
})),
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user