mirror of
https://github.com/openai/codex.git
synced 2026-11-07 20:30:33 +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:
@@ -36,6 +36,7 @@ use codex_protocol::approvals::NetworkApprovalProtocol;
|
||||
use codex_protocol::config_types::ApprovalsReviewer;
|
||||
use codex_protocol::error::CodexErr;
|
||||
use codex_protocol::models::AdditionalPermissionProfile;
|
||||
use codex_protocol::openai_models::ModelInfo;
|
||||
use codex_protocol::protocol::AskForApproval;
|
||||
use codex_protocol::protocol::FileChange;
|
||||
use codex_protocol::protocol::NetworkPolicyRuleAction;
|
||||
@@ -452,7 +453,7 @@ struct ApprovalResolution {
|
||||
}
|
||||
|
||||
impl ApprovalResolution {
|
||||
fn into_tool_result(self) -> Result<ReviewDecision, ToolError> {
|
||||
fn into_tool_result(self, model_info: &ModelInfo) -> Result<ReviewDecision, ToolError> {
|
||||
let source = self.source;
|
||||
match self.decision {
|
||||
ReviewDecision::ApprovedMcpPolicyAmendment => {
|
||||
@@ -474,7 +475,9 @@ impl ApprovalResolution {
|
||||
Err(ToolError::Rejected(rejection.to_string()))
|
||||
}
|
||||
ReviewDecision::Denied { rejection } => Err(ToolError::Rejected(rejection)),
|
||||
ReviewDecision::TimedOut => Err(ToolError::Rejected(guardian_timeout_message())),
|
||||
ReviewDecision::TimedOut => {
|
||||
Err(ToolError::Rejected(guardian_timeout_message(model_info)))
|
||||
}
|
||||
ReviewDecision::Abort => Err(ToolError::Codex(CodexErr::TurnAborted)),
|
||||
decision => Ok(decision),
|
||||
}
|
||||
@@ -543,7 +546,7 @@ impl Session {
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
resolution.into_tool_result()
|
||||
resolution.into_tool_result(&ctx.review_context.turn().model_info)
|
||||
}
|
||||
|
||||
async fn request_reviewer_approval(
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use super::*;
|
||||
use codex_models_manager::model_info::model_info_from_slug;
|
||||
use codex_protocol::approvals::NetworkPolicyAmendment;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
@@ -15,7 +16,7 @@ fn approval_resolution_rejects_denied_network_policy_amendment() {
|
||||
};
|
||||
|
||||
assert!(matches!(
|
||||
resolution.into_tool_result(),
|
||||
resolution.into_tool_result(&model_info_from_slug("acting-model")),
|
||||
Err(ToolError::Rejected(rejection)) if rejection == "rejected by user"
|
||||
));
|
||||
}
|
||||
@@ -28,7 +29,7 @@ fn approval_resolution_rejects_mcp_policy_amendment() {
|
||||
};
|
||||
|
||||
assert!(matches!(
|
||||
resolution.into_tool_result(),
|
||||
resolution.into_tool_result(&model_info_from_slug("acting-model")),
|
||||
Err(ToolError::Rejected(rejection)) if rejection == "Error while requesting approval"
|
||||
));
|
||||
}
|
||||
@@ -41,7 +42,7 @@ fn approval_resolution_aborts_turn_when_approval_is_aborted() {
|
||||
};
|
||||
|
||||
assert!(matches!(
|
||||
resolution.into_tool_result(),
|
||||
resolution.into_tool_result(&model_info_from_slug("acting-model")),
|
||||
Err(ToolError::Codex(error))
|
||||
if matches!(
|
||||
error.details(),
|
||||
@@ -50,6 +51,30 @@ fn approval_resolution_aborts_turn_when_approval_is_aborted() {
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn approval_resolution_uses_acting_model_timeout_instructions() {
|
||||
let mut model = model_info_from_slug("acting-model");
|
||||
for timeout_instructions in ["Catalog timeout instructions.", ""] {
|
||||
model.model_messages = Some(
|
||||
serde_json::from_value(serde_json::json!({
|
||||
"auto_review": {
|
||||
"timeout_instructions": timeout_instructions,
|
||||
},
|
||||
}))
|
||||
.expect("model messages should deserialize"),
|
||||
);
|
||||
let resolution = ApprovalResolution {
|
||||
decision: ReviewDecision::TimedOut,
|
||||
source: ApprovalResolutionSource::Guardian,
|
||||
};
|
||||
|
||||
assert!(matches!(
|
||||
resolution.into_tool_result(&model),
|
||||
Err(ToolError::Rejected(rejection)) if rejection == timeout_instructions
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn guardian_cwd_preserves_drive_shaped_local_posix_path() {
|
||||
let native_cwd = AbsolutePathBuf::try_from(std::path::PathBuf::from("/C:/workspace"))
|
||||
|
||||
@@ -551,7 +551,9 @@ impl CoreShellActionProvider {
|
||||
EscalationDecision::deny(Some(rejection))
|
||||
}
|
||||
ReviewDecision::TimedOut => EscalationDecision::deny(Some(
|
||||
crate::guardian::guardian_timeout_message(),
|
||||
crate::guardian::guardian_timeout_message(
|
||||
&self.review_context.turn().model_info,
|
||||
),
|
||||
)),
|
||||
ReviewDecision::ApprovedMcpPolicyAmendment => {
|
||||
error!("Shell escalation received ApprovedMcpPolicyAmendment");
|
||||
|
||||
Reference in New Issue
Block a user