75 lines
2.4 KiB
Rust
75 lines
2.4 KiB
Rust
//! Codex OAuth サブモジュール内部のエラー型。
|
||
//!
|
||
//! `LlmClient` 境界に渡す際は `to_client_error` で `ClientError` に
|
||
//! 変換する。`Permanent` 系(refresh_token 失効)は `codex login` の
|
||
//! 再実行案内付きメッセージにする。
|
||
|
||
use std::path::PathBuf;
|
||
|
||
use llm_worker::llm_client::ClientError;
|
||
use thiserror::Error;
|
||
|
||
#[derive(Debug, Error)]
|
||
pub enum CodexAuthError {
|
||
#[error(
|
||
"not logged in to ChatGPT: {0} not found. Run `codex login` and ensure cli_auth_credentials_store = \"file\"."
|
||
)]
|
||
NotLoggedIn(PathBuf),
|
||
|
||
#[error("malformed ~/.codex/auth.json: {0}")]
|
||
MalformedAuthJson(String),
|
||
|
||
#[error("io error: {0}")]
|
||
Io(String),
|
||
|
||
#[error("token refresh failed (transient): {0}")]
|
||
RefreshTransient(String),
|
||
|
||
/// refresh_token が永続的に失効。再ログインが必要。
|
||
#[error("token refresh failed permanently ({reason:?}): {message}")]
|
||
RefreshPermanent {
|
||
reason: PermanentReason,
|
||
message: String,
|
||
},
|
||
|
||
#[error("invalid header value: {0}")]
|
||
InvalidHeader(String),
|
||
}
|
||
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||
pub enum PermanentReason {
|
||
Expired,
|
||
Reused,
|
||
Revoked,
|
||
Other,
|
||
}
|
||
|
||
impl CodexAuthError {
|
||
/// `LlmClient` トランスポート境界向けに変換する。
|
||
pub fn to_client_error(self) -> ClientError {
|
||
match self {
|
||
CodexAuthError::NotLoggedIn(_)
|
||
| CodexAuthError::MalformedAuthJson(_)
|
||
| CodexAuthError::Io(_)
|
||
| CodexAuthError::InvalidHeader(_) => ClientError::Config(self.to_string()),
|
||
CodexAuthError::RefreshTransient(msg) => ClientError::Api {
|
||
status: None,
|
||
code: Some("refresh_transient".into()),
|
||
message: msg,
|
||
retry_after: None,
|
||
},
|
||
CodexAuthError::RefreshPermanent { reason, message } => ClientError::Api {
|
||
status: Some(401),
|
||
code: Some(match reason {
|
||
PermanentReason::Expired => "refresh_token_expired".into(),
|
||
PermanentReason::Reused => "refresh_token_reused".into(),
|
||
PermanentReason::Revoked => "refresh_token_invalidated".into(),
|
||
PermanentReason::Other => "refresh_token_failed".into(),
|
||
}),
|
||
message: format!("{message}. Please run `codex login` again."),
|
||
retry_after: None,
|
||
},
|
||
}
|
||
}
|
||
}
|