mirror of
https://github.com/openai/codex.git
synced 2026-04-24 14:45:27 +00:00
changes
This commit is contained in:
2
codex-rs/Cargo.lock
generated
2
codex-rs/Cargo.lock
generated
@@ -2418,8 +2418,6 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"codex-utils-absolute-path",
|
||||
"codex-utils-plugins",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror 2.0.18",
|
||||
]
|
||||
|
||||
|
||||
@@ -106,6 +106,7 @@ use crate::model_provider_info::WireApi;
|
||||
use crate::response_debug_context::extract_response_debug_context;
|
||||
use crate::response_debug_context::extract_response_debug_context_from_api_error;
|
||||
use crate::response_debug_context::telemetry_api_error_message;
|
||||
use codex_login::auth::RefreshTokenFailedError;
|
||||
use crate::response_debug_context::telemetry_transport_error_message;
|
||||
use crate::tools::spec::create_tools_json_for_responses_api;
|
||||
use crate::util::FeedbackRequestTags;
|
||||
@@ -1587,6 +1588,7 @@ async fn handle_unauthorized(
|
||||
Ok(UnauthorizedRecoveryExecution { mode, phase })
|
||||
}
|
||||
Err(RefreshTokenError::Permanent(failed)) => {
|
||||
let recovery_reason = format_permanent_refresh_recovery_reason(&failed);
|
||||
session_telemetry.record_auth_recovery(
|
||||
mode,
|
||||
phase,
|
||||
@@ -1595,7 +1597,7 @@ async fn handle_unauthorized(
|
||||
debug.cf_ray.as_deref(),
|
||||
debug.auth_error.as_deref(),
|
||||
debug.auth_error_code.as_deref(),
|
||||
/*recovery_reason*/ None,
|
||||
Some(recovery_reason.as_str()),
|
||||
/*auth_state_changed*/ None,
|
||||
);
|
||||
emit_feedback_auth_recovery_tags(
|
||||
@@ -1610,6 +1612,7 @@ async fn handle_unauthorized(
|
||||
Err(CodexErr::RefreshTokenFailed(failed))
|
||||
}
|
||||
Err(RefreshTokenError::Transient(other)) => {
|
||||
let recovery_reason = format_transient_refresh_recovery_reason(&other);
|
||||
session_telemetry.record_auth_recovery(
|
||||
mode,
|
||||
phase,
|
||||
@@ -1618,7 +1621,7 @@ async fn handle_unauthorized(
|
||||
debug.cf_ray.as_deref(),
|
||||
debug.auth_error.as_deref(),
|
||||
debug.auth_error_code.as_deref(),
|
||||
/*recovery_reason*/ None,
|
||||
Some(recovery_reason.as_str()),
|
||||
/*auth_state_changed*/ None,
|
||||
);
|
||||
emit_feedback_auth_recovery_tags(
|
||||
@@ -1667,6 +1670,18 @@ async fn handle_unauthorized(
|
||||
Err(map_api_error(ApiError::Transport(transport)))
|
||||
}
|
||||
|
||||
fn format_permanent_refresh_recovery_reason(failed: &RefreshTokenFailedError) -> String {
|
||||
format!(
|
||||
"failed_reason={}; message={}",
|
||||
failed.reason.as_str(),
|
||||
failed.message
|
||||
)
|
||||
}
|
||||
|
||||
fn format_transient_refresh_recovery_reason(error: &std::io::Error) -> String {
|
||||
format!("message={error}")
|
||||
}
|
||||
|
||||
fn api_error_http_status(error: &ApiError) -> Option<u16> {
|
||||
match error {
|
||||
ApiError::Transport(TransportError::Http { status, .. }) => Some(status.as_u16()),
|
||||
|
||||
@@ -2,6 +2,10 @@ use super::AuthRequestTelemetryContext;
|
||||
use super::ModelClient;
|
||||
use super::PendingUnauthorizedRetry;
|
||||
use super::UnauthorizedRecoveryExecution;
|
||||
use super::format_permanent_refresh_recovery_reason;
|
||||
use super::format_transient_refresh_recovery_reason;
|
||||
use codex_login::auth::RefreshTokenFailedError;
|
||||
use codex_login::auth::RefreshTokenFailedReason;
|
||||
use codex_otel::SessionTelemetry;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::openai_models::ModelInfo;
|
||||
@@ -115,3 +119,45 @@ fn auth_request_telemetry_context_tracks_attached_auth_and_retry_phase() {
|
||||
assert_eq!(auth_context.recovery_mode, Some("managed"));
|
||||
assert_eq!(auth_context.recovery_phase, Some("refresh_token"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn refresh_token_failed_reason_label_uses_stable_values() {
|
||||
assert_eq!(
|
||||
RefreshTokenFailedReason::Expired.as_str(),
|
||||
"expired"
|
||||
);
|
||||
assert_eq!(
|
||||
RefreshTokenFailedReason::Exhausted.as_str(),
|
||||
"exhausted"
|
||||
);
|
||||
assert_eq!(
|
||||
RefreshTokenFailedReason::Revoked.as_str(),
|
||||
"revoked"
|
||||
);
|
||||
assert_eq!(
|
||||
RefreshTokenFailedReason::Other.as_str(),
|
||||
"other"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn refresh_token_error_formats_permanent_recovery_reason() {
|
||||
let error = RefreshTokenFailedError::new(
|
||||
RefreshTokenFailedReason::Expired,
|
||||
"refresh token expired",
|
||||
);
|
||||
let reason = format_permanent_refresh_recovery_reason(&error);
|
||||
|
||||
assert_eq!(
|
||||
reason,
|
||||
"failed_reason=expired; message=refresh token expired"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn refresh_token_error_formats_transient_recovery_reason() {
|
||||
let error = std::io::Error::other("temporary refresh failure");
|
||||
let reason = format_transient_refresh_recovery_reason(&error);
|
||||
|
||||
assert_eq!(reason, "message=temporary refresh failure");
|
||||
}
|
||||
|
||||
@@ -23,3 +23,14 @@ pub enum RefreshTokenFailedReason {
|
||||
Revoked,
|
||||
Other,
|
||||
}
|
||||
|
||||
impl RefreshTokenFailedReason {
|
||||
pub fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
Self::Expired => "expired",
|
||||
Self::Exhausted => "exhausted",
|
||||
Self::Revoked => "revoked",
|
||||
Self::Other => "other",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user