import CodexBarCoreimport Foundation extension UsageStore { struct APIKeyDebugContext { let label: String let resolution: ProviderTokenResolution? let configToken: String? let hasEnvToken: Bool let hasTokenAccount: Bool } func openAIAPIKeyDebugContext(processEnvironment: [String: String]) -> APIKeyDebugContext { self.apiKeyDebugContext( provider: .openai, label: "OPENAI_API_KEY", processEnvironment: processEnvironment, resolution: ProviderTokenResolver.openAIAPIResolution, hasEnvToken: { OpenAIAPISettingsReader.apiKey(environment: $0) != nil }) } func azureOpenAIAPIKeyDebugContext(processEnvironment: [String: String]) -> APIKeyDebugContext { let config = self.settings.providerConfig(for: .azureopenai) let environment = ProviderConfigEnvironment.applyProviderConfigOverrides( base: processEnvironment, provider: .azureopenai, config: config) return APIKeyDebugContext( label: "AZURE_OPENAI_API_KEY", resolution: ProviderTokenResolver.azureOpenAIResolution(environment: environment), configToken: config?.sanitizedAPIKey, hasEnvToken: AzureOpenAISettingsReader.apiKey(environment: processEnvironment) != nil, hasTokenAccount: false) } func openRouterAPIKeyDebugContext(processEnvironment: [String: String]) -> APIKeyDebugContext { self.apiKeyDebugContext( provider: .openrouter, label: "OPENROUTER_API_KEY", processEnvironment: processEnvironment, resolution: ProviderTokenResolver.openRouterResolution, hasEnvToken: { OpenRouterSettingsReader.apiToken(environment: $0) != nil }) } func crossModelAPIKeyDebugContext(processEnvironment: [String: String]) -> APIKeyDebugContext { self.apiKeyDebugContext( provider: .crossmodel, label: "CROSSMODEL_API_KEY", processEnvironment: processEnvironment, resolution: ProviderTokenResolver.crossModelResolution, hasEnvToken: { CrossModelSettingsReader.apiToken(environment: $0) != nil }) } func elevenLabsAPIKeyDebugContext(processEnvironment: [String: String]) -> APIKeyDebugContext { self.apiKeyDebugContext( provider: .elevenlabs, label: "ELEVENLABS_API_KEY", processEnvironment: processEnvironment, resolution: ProviderTokenResolver.elevenLabsResolution, hasEnvToken: { ElevenLabsSettingsReader.apiKey(environment: $0) != nil }) } func apiKeyDebugContext( provider: UsageProvider, label: String, processEnvironment: [String: String], resolution: ([String: String]) -> ProviderTokenResolution?, hasEnvToken: ([String: String]) -> Bool) -> APIKeyDebugContext { let config = self.settings.providerConfig(for: provider) let environment = ProviderConfigEnvironment.applyAPIKeyOverride( base: processEnvironment, provider: provider, config: config) return APIKeyDebugContext( label: label, resolution: resolution(environment), configToken: config?.sanitizedAPIKey, hasEnvToken: hasEnvToken(processEnvironment), hasTokenAccount: false) } nonisolated static func apiKeyDebugLine(_ context: APIKeyDebugContext) -> String { self.apiKeyDebugLine( label: context.label, resolution: context.resolution, configToken: context.configToken, hasEnvToken: context.hasEnvToken, hasTokenAccount: context.hasTokenAccount) } nonisolated static func apiKeyDebugLine( label: String, resolution: ProviderTokenResolution?, configToken: String?, hasEnvToken: Bool, hasTokenAccount: Bool = false) -> String { let hasAny = resolution != nil let hasConfigToken = !(configToken?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ?? true) let source: String = if resolution == nil { "none" } else if hasTokenAccount, hasEnvToken { "settings-token-account (overrides env)" } else if hasTokenAccount { "settings-token-account" } else if hasConfigToken, hasEnvToken { "settings-config (overrides env)" } else if hasConfigToken { "settings-config" } else { resolution?.source.rawValue ?? "environment" } return "\(label)=\(hasAny ? "present" : "missing") source=\(source)" }}
import CodexBarCore
import Foundation
extension UsageStore {
struct APIKeyDebugContext {
let label: String
let resolution: ProviderTokenResolution?
let configToken: String?
let hasEnvToken: Bool
let hasTokenAccount: Bool
}
func openAIAPIKeyDebugContext(processEnvironment: [String: String]) -> APIKeyDebugContext {
self.apiKeyDebugContext(
provider: .openai,
label: "OPENAI_API_KEY",
processEnvironment: processEnvironment,
resolution: ProviderTokenResolver.openAIAPIResolution,
hasEnvToken: { OpenAIAPISettingsReader.apiKey(environment: $0) != nil })
}
func azureOpenAIAPIKeyDebugContext(processEnvironment: [String: String]) -> APIKeyDebugContext {
let config = self.settings.providerConfig(for: .azureopenai)
let environment = ProviderConfigEnvironment.applyProviderConfigOverrides(
base: processEnvironment,
provider: .azureopenai,
config: config)
return APIKeyDebugContext(
label: "AZURE_OPENAI_API_KEY",
resolution: ProviderTokenResolver.azureOpenAIResolution(environment: environment),
configToken: config?.sanitizedAPIKey,
hasEnvToken: AzureOpenAISettingsReader.apiKey(environment: processEnvironment) != nil,
hasTokenAccount: false)
}
func openRouterAPIKeyDebugContext(processEnvironment: [String: String]) -> APIKeyDebugContext {
self.apiKeyDebugContext(
provider: .openrouter,
label: "OPENROUTER_API_KEY",
processEnvironment: processEnvironment,
resolution: ProviderTokenResolver.openRouterResolution,
hasEnvToken: { OpenRouterSettingsReader.apiToken(environment: $0) != nil })
}
func crossModelAPIKeyDebugContext(processEnvironment: [String: String]) -> APIKeyDebugContext {
self.apiKeyDebugContext(
provider: .crossmodel,
label: "CROSSMODEL_API_KEY",
processEnvironment: processEnvironment,
resolution: ProviderTokenResolver.crossModelResolution,
hasEnvToken: { CrossModelSettingsReader.apiToken(environment: $0) != nil })
}
func elevenLabsAPIKeyDebugContext(processEnvironment: [String: String]) -> APIKeyDebugContext {
self.apiKeyDebugContext(
provider: .elevenlabs,
label: "ELEVENLABS_API_KEY",
processEnvironment: processEnvironment,
resolution: ProviderTokenResolver.elevenLabsResolution,
hasEnvToken: { ElevenLabsSettingsReader.apiKey(environment: $0) != nil })
}
func apiKeyDebugContext(
provider: UsageProvider,
label: String,
processEnvironment: [String: String],
resolution: ([String: String]) -> ProviderTokenResolution?,
hasEnvToken: ([String: String]) -> Bool) -> APIKeyDebugContext
{
let config = self.settings.providerConfig(for: provider)
let environment = ProviderConfigEnvironment.applyAPIKeyOverride(
base: processEnvironment,
provider: provider,
config: config)
return APIKeyDebugContext(
label: label,
resolution: resolution(environment),
configToken: config?.sanitizedAPIKey,
hasEnvToken: hasEnvToken(processEnvironment),
hasTokenAccount: false)
}
nonisolated static func apiKeyDebugLine(_ context: APIKeyDebugContext) -> String {
self.apiKeyDebugLine(
label: context.label,
resolution: context.resolution,
configToken: context.configToken,
hasEnvToken: context.hasEnvToken,
hasTokenAccount: context.hasTokenAccount)
}
nonisolated static func apiKeyDebugLine(
label: String,
resolution: ProviderTokenResolution?,
configToken: String?,
hasEnvToken: Bool,
hasTokenAccount: Bool = false) -> String
{
let hasAny = resolution != nil
let hasConfigToken = !(configToken?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ?? true)
let source: String = if resolution == nil {
"none"
} else if hasTokenAccount, hasEnvToken {
"settings-token-account (overrides env)"
} else if hasTokenAccount {
"settings-token-account"
} else if hasConfigToken, hasEnvToken {
"settings-config (overrides env)"
} else if hasConfigToken {
"settings-config"
} else {
resolution?.source.rawValue ?? "environment"
}
return "\(label)=\(hasAny ? "present" : "missing") source=\(source)"
}
}