83 lines · 2.7 KB · Swift
RawDownload
import Foundation public enum ClaudeOAuthKeychainPromptMode: String, Sendable, Codable, CaseIterable {    case never    case onlyOnUserAction    case always} public enum ClaudeOAuthKeychainPromptPreference {    private static let userDefaultsKey = "claudeOAuthKeychainPromptMode"     #if DEBUG    @TaskLocal private static var taskOverride: ClaudeOAuthKeychainPromptMode?    #endif     public static func current(userDefaults: UserDefaults = .standard) -> ClaudeOAuthKeychainPromptMode {        self.effectiveMode(userDefaults: userDefaults)    }     public static func storedMode(userDefaults: UserDefaults = .standard) -> ClaudeOAuthKeychainPromptMode {        #if DEBUG        if let taskOverride { return taskOverride }        #endif        if let raw = userDefaults.string(forKey: self.userDefaultsKey),           let mode = ClaudeOAuthKeychainPromptMode(rawValue: raw)        {            return mode        }        return .onlyOnUserAction    }     public static func isApplicable(        readStrategy: ClaudeOAuthKeychainReadStrategy = ClaudeOAuthKeychainReadStrategyPreference.current()) -> Bool    {        readStrategy == .securityFramework    }     public static func effectiveMode(        userDefaults: UserDefaults = .standard,        readStrategy: ClaudeOAuthKeychainReadStrategy = ClaudeOAuthKeychainReadStrategyPreference.current())        -> ClaudeOAuthKeychainPromptMode    {        guard self.isApplicable(readStrategy: readStrategy) else {            return .always        }        return self.storedMode(userDefaults: userDefaults)    }     public static func securityFrameworkFallbackMode(        userDefaults: UserDefaults = .standard,        readStrategy: ClaudeOAuthKeychainReadStrategy = ClaudeOAuthKeychainReadStrategyPreference.current())        -> ClaudeOAuthKeychainPromptMode    {        if readStrategy == .securityCLIExperimental {            return self.storedMode(userDefaults: userDefaults)        }        return self.effectiveMode(userDefaults: userDefaults, readStrategy: readStrategy)    }     #if DEBUG    public static func withTaskOverrideForTesting<T>(        _ mode: ClaudeOAuthKeychainPromptMode?,        operation: () throws -> T) rethrows -> T    {        try self.$taskOverride.withValue(mode) {            try operation()        }    }     public static func withTaskOverrideForTesting<T>(        _ mode: ClaudeOAuthKeychainPromptMode?,        operation: () async throws -> T) async rethrows -> T    {        try await self.$taskOverride.withValue(mode) {            try await operation()        }    }     public static var currentTaskOverrideForTesting: ClaudeOAuthKeychainPromptMode? {        self.taskOverride    }    #endif}