import Foundation// MARK: - Abacus Usage Errorpublic enum AbacusUsageError: LocalizedError, Sendable, Equatable { case noSessionCookie case sessionExpired case networkError(String) case parseFailed(String) case unauthorized /// Whether this error indicates an authentication/session problem that /// should trigger cache eviction. public var isRecoverable: Bool { switch self { case .unauthorized, .sessionExpired: true default: false } } public var isAuthRelated: Bool { self.isRecoverable } /// Whether browser-import scanning should continue to later sessions after /// this failure. Imported sessions can differ by profile/browser, so we keep /// scanning on per-session fetch failures and surface the first one only if /// every candidate is exhausted. var shouldTryNextImportedSession: Bool { switch self { case .unauthorized, .sessionExpired, .networkError, .parseFailed: true case .noSessionCookie: false } } /// Whether a cached cookie header should be evicted before falling back to /// a fresh browser import. Parse/auth failures usually indicate that the /// cached session is stale or no longer accepted. var shouldClearCachedCookie: Bool { switch self { case .unauthorized, .sessionExpired, .parseFailed: true case .networkError, .noSessionCookie: false } } public var errorDescription: String? { switch self { case .noSessionCookie: "No Abacus AI session found. Please log in to apps.abacus.ai in your browser " + "or paste a Cookie header in manual mode." case .sessionExpired: "Abacus AI session expired. Please log in again." case let .networkError(msg): "Abacus AI API error: \(msg)" case let .parseFailed(msg): "Could not parse Abacus AI usage: \(msg)" case .unauthorized: "Unauthorized. Please log in to Abacus AI." } }}#if !os(macOS)extension AbacusUsageError { public static let notSupported = AbacusUsageError.networkError("Abacus AI is only supported on macOS.")}#endif
import Foundation
// MARK: - Abacus Usage Error
public enum AbacusUsageError: LocalizedError, Sendable, Equatable {
case noSessionCookie
case sessionExpired
case networkError(String)
case parseFailed(String)
case unauthorized
/// Whether this error indicates an authentication/session problem that
/// should trigger cache eviction.
public var isRecoverable: Bool {
switch self {
case .unauthorized, .sessionExpired: true
default: false
}
}
public var isAuthRelated: Bool {
self.isRecoverable
}
/// Whether browser-import scanning should continue to later sessions after
/// this failure. Imported sessions can differ by profile/browser, so we keep
/// scanning on per-session fetch failures and surface the first one only if
/// every candidate is exhausted.
var shouldTryNextImportedSession: Bool {
switch self {
case .unauthorized, .sessionExpired, .networkError, .parseFailed: true
case .noSessionCookie: false
}
}
/// Whether a cached cookie header should be evicted before falling back to
/// a fresh browser import. Parse/auth failures usually indicate that the
/// cached session is stale or no longer accepted.
var shouldClearCachedCookie: Bool {
switch self {
case .unauthorized, .sessionExpired, .parseFailed: true
case .networkError, .noSessionCookie: false
}
}
public var errorDescription: String? {
switch self {
case .noSessionCookie:
"No Abacus AI session found. Please log in to apps.abacus.ai in your browser "
+ "or paste a Cookie header in manual mode."
case .sessionExpired:
"Abacus AI session expired. Please log in again."
case let .networkError(msg):
"Abacus AI API error: \(msg)"
case let .parseFailed(msg):
"Could not parse Abacus AI usage: \(msg)"
case .unauthorized:
"Unauthorized. Please log in to Abacus AI."
}
}
}
#if !os(macOS)
extension AbacusUsageError {
public static let notSupported = AbacusUsageError.networkError("Abacus AI is only supported on macOS.")
}
#endif