79 lines
3.0 KiB
Swift
79 lines
3.0 KiB
Swift
import Foundation
|
|
|
|
public struct KiloResolvedBearerToken: Sendable, Equatable {
|
|
public let token: String
|
|
public let sourceLabel: String
|
|
|
|
public init(token: String, sourceLabel: String) {
|
|
self.token = token
|
|
self.sourceLabel = sourceLabel
|
|
}
|
|
}
|
|
|
|
/// Resolves the Kilo bearer token shared by usage fetches and organization discovery.
|
|
///
|
|
/// Behavior mirrors the per-strategy resolution in `KiloProviderDescriptor`:
|
|
/// - `.api`: explicit `apiKey`, falling back to `KILO_API_KEY` env var.
|
|
/// - `.cli`: token from `~/.local/share/kilo/auth.json` (`kilo.access`).
|
|
/// - `.auto`: API first, falling back to CLI when API credentials are missing.
|
|
public enum KiloBearerTokenResolver {
|
|
public static func resolve(
|
|
source: KiloUsageDataSource,
|
|
apiKey: String?,
|
|
environment: [String: String] = ProcessInfo.processInfo.environment) throws -> KiloResolvedBearerToken
|
|
{
|
|
switch source {
|
|
case .api:
|
|
return try self.resolveAPI(apiKey: apiKey, environment: environment)
|
|
case .cli:
|
|
return try self.resolveCLI(environment: environment)
|
|
case .auto:
|
|
if let resolved = try? self.resolveAPI(apiKey: apiKey, environment: environment) {
|
|
return resolved
|
|
}
|
|
return try self.resolveCLI(environment: environment)
|
|
}
|
|
}
|
|
|
|
private static func resolveAPI(
|
|
apiKey: String?,
|
|
environment: [String: String]) throws -> KiloResolvedBearerToken
|
|
{
|
|
let direct = KiloSettingsReader.cleaned(apiKey)
|
|
let envValue = KiloSettingsReader.cleaned(environment[KiloSettingsReader.apiTokenKey])
|
|
if let token = direct ?? envValue {
|
|
return KiloResolvedBearerToken(token: token, sourceLabel: "api")
|
|
}
|
|
throw KiloUsageError.missingCredentials
|
|
}
|
|
|
|
private static func resolveCLI(
|
|
environment: [String: String]) throws -> KiloResolvedBearerToken
|
|
{
|
|
let url = self.authFileURL(environment: environment)
|
|
guard FileManager.default.fileExists(atPath: url.path) else {
|
|
throw KiloUsageError.cliSessionMissing(url.path)
|
|
}
|
|
let data: Data
|
|
do {
|
|
data = try Data(contentsOf: url)
|
|
} catch {
|
|
throw KiloUsageError.cliSessionUnreadable(url.path)
|
|
}
|
|
guard let token = KiloSettingsReader.parseAuthToken(data: data) else {
|
|
throw KiloUsageError.cliSessionInvalid(url.path)
|
|
}
|
|
return KiloResolvedBearerToken(token: token, sourceLabel: "cli")
|
|
}
|
|
|
|
static func authFileURL(environment: [String: String]) -> URL {
|
|
if let home = KiloSettingsReader.cleaned(environment["HOME"]) {
|
|
let expandedHome = NSString(string: home).expandingTildeInPath
|
|
return KiloSettingsReader.defaultAuthFileURL(
|
|
homeDirectory: URL(fileURLWithPath: expandedHome, isDirectory: true))
|
|
}
|
|
return KiloSettingsReader.defaultAuthFileURL(
|
|
homeDirectory: FileManager.default.homeDirectoryForCurrentUser)
|
|
}
|
|
}
|