Add safety check notification and error handling (#19055)

Adds a new app-server notification that fires when a user account has
been flagged for potential safety reasons.
This commit is contained in:
Eric Traut authored and GitHub committed 2026-04-22 22:24:12 -07:00
1 parent 02170996e6
commit bbff4ee61a
61 files changed
+1414 -15

No files matched your search

+52
View File
@@ -97,6 +97,7 @@ use codex_app_server_protocol::ItemStartedNotification;
use codex_app_server_protocol::McpServerStartupState;
use codex_app_server_protocol::McpServerStatusDetail;
use codex_app_server_protocol::McpServerStatusUpdatedNotification;
use codex_app_server_protocol::ModelVerification as AppServerModelVerification;
use codex_app_server_protocol::ServerNotification;
use codex_app_server_protocol::ServerRequest;
use codex_app_server_protocol::ThreadItem;
@@ -194,6 +195,8 @@ use codex_protocol::protocol::McpStartupStatus;
use codex_protocol::protocol::McpStartupUpdateEvent;
use codex_protocol::protocol::McpToolCallBeginEvent;
use codex_protocol::protocol::McpToolCallEndEvent;
#[cfg(test)]
use codex_protocol::protocol::ModelVerification as CoreModelVerification;
use codex_protocol::protocol::Op;
use codex_protocol::protocol::PatchApplyBeginEvent;
use codex_protocol::protocol::RateLimitReachedType;
@@ -256,6 +259,7 @@ const MULTI_AGENT_ENABLE_TITLE: &str = "Enable subagents?";
const MULTI_AGENT_ENABLE_YES: &str = "Yes, enable";
const MULTI_AGENT_ENABLE_NO: &str = "Not now";
const MULTI_AGENT_ENABLE_NOTICE: &str = "Subagents will be enabled in the next session.";
const TRUSTED_ACCESS_FOR_CYBER_VERIFICATION_WARNING: &str = "Your account was flagged for potentially high-risk cyber activity. Requests may be slower while additional verification is applied. To regain faster access, apply for trusted access: https://chatgpt.com/cyber or learn more: https://developers.openai.com/codex/concepts/cyber-safety";
const MEMORIES_DOC_URL: &str = "https://developers.openai.com/codex/memories";
const MEMORIES_ENABLE_TITLE: &str = "Enable memories?";
const MEMORIES_ENABLE_YES: &str = "Yes, enable";
@@ -651,6 +655,15 @@ fn app_server_rate_limit_error_kind(info: &AppServerCodexErrorInfo) -> Option<Ra
}
}
#[cfg(test)]
fn is_core_cyber_policy_error(info: &CoreCodexErrorInfo) -> bool {
matches!(info, CoreCodexErrorInfo::CyberPolicy)
}
fn is_app_server_cyber_policy_error(info: &AppServerCodexErrorInfo) -> bool {
matches!(info, AppServerCodexErrorInfo::CyberPolicy)
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) enum ExternalEditorState {
#[default]
@@ -3040,6 +3053,16 @@ impl ChatWidget {
self.maybe_send_next_queued_input();
}
fn on_cyber_policy_error(&mut self) {
self.submit_pending_steers_after_interrupt = false;
self.finalize_turn();
self.add_to_history(history_cell::new_cyber_policy_error_event());
self.request_redraw();
// After an error ends the turn, try sending the next queued input.
self.maybe_send_next_queued_input();
}
fn workspace_owner_usage_nudge_enabled(&self) -> bool {
self.config
.features
@@ -3105,6 +3128,11 @@ impl ChatWidget {
.as_ref()
.is_some_and(|info| self.handle_app_server_steer_rejected_error(info))
{
} else if codex_error_info
.as_ref()
.is_some_and(is_app_server_cyber_policy_error)
{
self.on_cyber_policy_error();
} else if let Some(info) = codex_error_info
.as_ref()
.and_then(app_server_rate_limit_error_kind)
@@ -3125,6 +3153,19 @@ impl ChatWidget {
self.request_redraw();
}
#[cfg(test)]
fn on_core_model_verification(&mut self, verifications: &[CoreModelVerification]) {
if verifications.contains(&CoreModelVerification::TrustedAccessForCyber) {
self.on_warning(TRUSTED_ACCESS_FOR_CYBER_VERIFICATION_WARNING);
}
}
fn on_app_server_model_verification(&mut self, verifications: &[AppServerModelVerification]) {
if verifications.contains(&AppServerModelVerification::TrustedAccessForCyber) {
self.on_warning(TRUSTED_ACCESS_FOR_CYBER_VERIFICATION_WARNING);
}
}
/// Record one MCP startup update, promoting it into either the active startup
/// round or a buffered "next" round.
///
@@ -6579,6 +6620,9 @@ impl ChatWidget {
self.refresh_skills_for_current_cwd(/*force_reload*/ true);
}
ServerNotification::ModelRerouted(_) => {}
ServerNotification::ModelVerification(notification) => {
self.on_app_server_model_verification(&notification.verifications)
}
ServerNotification::Warning(notification) => self.on_warning(notification.message),
ServerNotification::GuardianWarning(notification) => {
self.on_warning(notification.message)
@@ -7084,6 +7128,9 @@ impl ChatWidget {
| EventMsg::GuardianWarning(WarningEvent { message }) => self.on_warning(message),
EventMsg::GuardianAssessment(ev) => self.on_guardian_assessment(ev),
EventMsg::ModelReroute(_) => {}
EventMsg::ModelVerification(event) => {
self.on_core_model_verification(&event.verifications)
}
EventMsg::Error(ErrorEvent {
message,
codex_error_info,
@@ -7092,6 +7139,11 @@ impl ChatWidget {
.as_ref()
.is_some_and(|info| self.handle_steer_rejected_error(info))
{
} else if codex_error_info
.as_ref()
.is_some_and(is_core_cyber_policy_error)
{
self.on_cyber_policy_error();
} else if let Some(kind) = codex_error_info
.as_ref()
.and_then(core_rate_limit_error_kind)