use thiserror::Error;
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum ClaudeCodeAuthError {
#[error("Claude Code credentials not found at `{path}` — run `claude login` first")]
CredentialsMissing {
path: String,
},
#[error("Claude Code credential file `{path}` has no OAuth section")]
OAuthSectionMissing {
path: String,
},
#[error("Claude Code OAuth refresh token absent — re-authenticate via `claude login`")]
RefreshTokenMissing,
#[error("Claude Code OAuth refresh failed: {message}")]
RefreshHttp {
message: String,
},
#[error("Claude Code credential file `{path}` is not valid JSON: {source}")]
InvalidStorage {
path: String,
#[source]
source: serde_json::Error,
},
#[error("Claude Code credential file `{path}` IO failed: {source}")]
Io {
path: String,
#[source]
source: std::io::Error,
},
#[error("home directory not resolvable — supply the credentials path explicitly")]
HomeUnresolved,
}
pub type ClaudeCodeAuthResult<T> = Result<T, ClaudeCodeAuthError>;
impl From<ClaudeCodeAuthError> for entelix_core::Error {
fn from(err: ClaudeCodeAuthError) -> Self {
use entelix_core::auth::AuthError;
let message = err.to_string();
match err {
ClaudeCodeAuthError::CredentialsMissing { .. }
| ClaudeCodeAuthError::OAuthSectionMissing { .. }
| ClaudeCodeAuthError::HomeUnresolved => Self::Auth(AuthError::missing_from(message)),
ClaudeCodeAuthError::RefreshTokenMissing => {
Self::Auth(AuthError::expired_with(message))
}
ClaudeCodeAuthError::RefreshHttp { .. } => {
Self::Auth(AuthError::source_unreachable(message))
}
ClaudeCodeAuthError::InvalidStorage { .. } | ClaudeCodeAuthError::Io { .. } => {
Self::Auth(AuthError::refused(message))
}
}
}
}