mirror of
https://github.com/openai/codex.git
synced 2026-10-24 23:54:33 +00:00
Skip Guardian scoring in User approval mode (#42256)
## What changed - Skip Guardian prewarming and asynchronous scoring when `approvalsReviewer` is `"user"`, including when the reviewer changes during an active turn. - Automatically accept ordinary `node_repl.js` execution confirmations in this mode while continuing to surface sensitive-action checks and requests for user input. - Cover transitions between User approval, automatic review, and Full Access in the app-server integration tests. GitOrigin-RevId: 599c8ebb672728b9bf3d64c34377ddec230325f8
This commit is contained in:
@@ -733,6 +733,20 @@ impl CodexThread {
|
||||
self.session.thread_config_snapshot().await
|
||||
}
|
||||
|
||||
/// Returns the active turn's reviewer, including live updates, or the thread default.
|
||||
pub async fn approvals_reviewer_for_turn(&self, turn_id: &str) -> ApprovalsReviewer {
|
||||
if let Some((turn, settings, _)) = self
|
||||
.session
|
||||
.active_turn_context_and_strict_auto_review()
|
||||
.await
|
||||
&& turn.sub_id == turn_id
|
||||
{
|
||||
settings.approvals_reviewer()
|
||||
} else {
|
||||
self.config_snapshot().await.approvals_reviewer
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns thread-owned settings suitable for rollout persistence and resume.
|
||||
pub async fn thread_settings_snapshot(&self) -> ThreadSettingsSnapshot {
|
||||
self.session.thread_settings_snapshot().await
|
||||
|
||||
@@ -726,19 +726,34 @@ async fn review_guardian_mcp_elicitation(
|
||||
};
|
||||
let step_settings = turn_context.current_settings.load_full();
|
||||
|
||||
// User approval skips ordinary CUA checks, not separate sensitive requests.
|
||||
let user_cua_execution = step_settings.approvals_reviewer() == ApprovalsReviewer::User
|
||||
&& is_node_repl_backed_server(&request.server_name)
|
||||
&& request.elicitation.meta().is_some_and(|meta| {
|
||||
metadata_str(meta, MCP_ELICITATION_TOOL_NAME_KEY) == Some("js")
|
||||
&& metadata_str(meta, MCP_ELICITATION_CONNECTOR_ID_KEY) == Some("node_repl")
|
||||
&& metadata_str(meta, MCP_ELICITATION_APPROVAL_KIND_KEY)
|
||||
== Some(MCP_ELICITATION_APPROVAL_KIND_MCP_TOOL_CALL)
|
||||
&& meta.get(MCP_ELICITATION_SENSITIVE_ACTION_KEY) != Some(&Value::Bool(true))
|
||||
&& meta.get("codex_requires_user_input") != Some(&Value::Bool(true))
|
||||
});
|
||||
|
||||
// Full Access skips inference, not the active-turn and cancellation checks.
|
||||
if turn_context.environments.has_full_access(
|
||||
turn_context.approval_policy(),
|
||||
&turn_context
|
||||
.config
|
||||
.permissions
|
||||
.effective_permission_profile(),
|
||||
) && matches!(
|
||||
&request.elicitation,
|
||||
Elicitation::Mcp(rmcp::model::ElicitRequestParams::FormElicitationParams {
|
||||
requested_schema, ..
|
||||
}) if requested_schema.properties.is_empty()
|
||||
) {
|
||||
if (user_cua_execution
|
||||
|| turn_context.environments.has_full_access(
|
||||
turn_context.approval_policy(),
|
||||
&turn_context
|
||||
.config
|
||||
.permissions
|
||||
.effective_permission_profile(),
|
||||
))
|
||||
&& matches!(
|
||||
&request.elicitation,
|
||||
Elicitation::Mcp(rmcp::model::ElicitRequestParams::FormElicitationParams {
|
||||
requested_schema, ..
|
||||
}) if requested_schema.properties.is_empty()
|
||||
)
|
||||
{
|
||||
let decision = if cancellation_token.is_cancelled() {
|
||||
ReviewDecision::Abort
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user