668 lines · 27.8 KB · Swift
RawDownload
import Foundation enum CostUsagePricing {    private static let codexPriorityInputTokenLimit = 272_000     struct CodexPricing {        let inputCostPerToken: Double        let outputCostPerToken: Double        let cacheReadInputCostPerToken: Double?        let displayLabel: String?         let thresholdTokens: Int?        let inputCostPerTokenAboveThreshold: Double?        let outputCostPerTokenAboveThreshold: Double?        let cacheReadInputCostPerTokenAboveThreshold: Double?        let priorityInputCostPerToken: Double?        let priorityOutputCostPerToken: Double?        let priorityCacheReadInputCostPerToken: Double?         init(            inputCostPerToken: Double,            outputCostPerToken: Double,            cacheReadInputCostPerToken: Double?,            displayLabel: String?,            thresholdTokens: Int? = nil,            inputCostPerTokenAboveThreshold: Double? = nil,            outputCostPerTokenAboveThreshold: Double? = nil,            cacheReadInputCostPerTokenAboveThreshold: Double? = nil,            priorityInputCostPerToken: Double? = nil,            priorityOutputCostPerToken: Double? = nil,            priorityCacheReadInputCostPerToken: Double? = nil)        {            self.inputCostPerToken = inputCostPerToken            self.outputCostPerToken = outputCostPerToken            self.cacheReadInputCostPerToken = cacheReadInputCostPerToken            self.displayLabel = displayLabel            self.thresholdTokens = thresholdTokens            self.inputCostPerTokenAboveThreshold = inputCostPerTokenAboveThreshold            self.outputCostPerTokenAboveThreshold = outputCostPerTokenAboveThreshold            self.cacheReadInputCostPerTokenAboveThreshold = cacheReadInputCostPerTokenAboveThreshold            self.priorityInputCostPerToken = priorityInputCostPerToken            self.priorityOutputCostPerToken = priorityOutputCostPerToken            self.priorityCacheReadInputCostPerToken = priorityCacheReadInputCostPerToken        }    }     struct ClaudePricing {        let inputCostPerToken: Double        let outputCostPerToken: Double        let cacheCreationInputCostPerToken: Double        let cacheReadInputCostPerToken: Double         let thresholdTokens: Int?        let inputCostPerTokenAboveThreshold: Double?        let outputCostPerTokenAboveThreshold: Double?        let cacheCreationInputCostPerTokenAboveThreshold: Double?        let cacheReadInputCostPerTokenAboveThreshold: Double?    }     private struct ClaudeCostTokens {        let input: Int        let cacheRead: Int        let cacheCreation: Int        let cacheCreation1h: Int        let output: Int    }     private static let codex: [String: CodexPricing] = [        "gpt-5": CodexPricing(            inputCostPerToken: 1.25e-6,            outputCostPerToken: 1e-5,            cacheReadInputCostPerToken: 1.25e-7,            displayLabel: nil),        "gpt-5-codex": CodexPricing(            inputCostPerToken: 1.25e-6,            outputCostPerToken: 1e-5,            cacheReadInputCostPerToken: 1.25e-7,            displayLabel: nil),        "gpt-5-mini": CodexPricing(            inputCostPerToken: 2.5e-7,            outputCostPerToken: 2e-6,            cacheReadInputCostPerToken: 2.5e-8,            displayLabel: nil),        "gpt-5-nano": CodexPricing(            inputCostPerToken: 5e-8,            outputCostPerToken: 4e-7,            cacheReadInputCostPerToken: 5e-9,            displayLabel: nil),        "gpt-5-pro": CodexPricing(            inputCostPerToken: 1.5e-5,            outputCostPerToken: 1.2e-4,            cacheReadInputCostPerToken: nil,            displayLabel: nil),        "gpt-5.1": CodexPricing(            inputCostPerToken: 1.25e-6,            outputCostPerToken: 1e-5,            cacheReadInputCostPerToken: 1.25e-7,            displayLabel: nil),        "gpt-5.1-codex": CodexPricing(            inputCostPerToken: 1.25e-6,            outputCostPerToken: 1e-5,            cacheReadInputCostPerToken: 1.25e-7,            displayLabel: nil),        "gpt-5.1-codex-max": CodexPricing(            inputCostPerToken: 1.25e-6,            outputCostPerToken: 1e-5,            cacheReadInputCostPerToken: 1.25e-7,            displayLabel: nil),        "gpt-5.1-codex-mini": CodexPricing(            inputCostPerToken: 2.5e-7,            outputCostPerToken: 2e-6,            cacheReadInputCostPerToken: 2.5e-8,            displayLabel: nil),        "gpt-5.2": CodexPricing(            inputCostPerToken: 1.75e-6,            outputCostPerToken: 1.4e-5,            cacheReadInputCostPerToken: 1.75e-7,            displayLabel: nil),        "gpt-5.2-codex": CodexPricing(            inputCostPerToken: 1.75e-6,            outputCostPerToken: 1.4e-5,            cacheReadInputCostPerToken: 1.75e-7,            displayLabel: nil),        "gpt-5.2-pro": CodexPricing(            inputCostPerToken: 2.1e-5,            outputCostPerToken: 1.68e-4,            cacheReadInputCostPerToken: nil,            displayLabel: nil),        "gpt-5.3-codex": CodexPricing(            inputCostPerToken: 1.75e-6,            outputCostPerToken: 1.4e-5,            cacheReadInputCostPerToken: 1.75e-7,            displayLabel: nil),        "gpt-5.3-codex-spark": CodexPricing(            inputCostPerToken: 0,            outputCostPerToken: 0,            cacheReadInputCostPerToken: 0,            displayLabel: "Research Preview"),        "gpt-5.4": CodexPricing(            inputCostPerToken: 2.5e-6,            outputCostPerToken: 1.5e-5,            cacheReadInputCostPerToken: 2.5e-7,            displayLabel: nil,            thresholdTokens: 272_000,            inputCostPerTokenAboveThreshold: 5e-6,            outputCostPerTokenAboveThreshold: 2.25e-5,            cacheReadInputCostPerTokenAboveThreshold: 5e-7,            priorityInputCostPerToken: 5e-6,            priorityOutputCostPerToken: 3e-5,            priorityCacheReadInputCostPerToken: 5e-7),        "gpt-5.4-mini": CodexPricing(            inputCostPerToken: 7.5e-7,            outputCostPerToken: 4.5e-6,            cacheReadInputCostPerToken: 7.5e-8,            displayLabel: nil,            priorityInputCostPerToken: 1.5e-6,            priorityOutputCostPerToken: 9e-6,            priorityCacheReadInputCostPerToken: 1.5e-7),        "gpt-5.4-nano": CodexPricing(            inputCostPerToken: 2e-7,            outputCostPerToken: 1.25e-6,            cacheReadInputCostPerToken: 2e-8,            displayLabel: nil),        "gpt-5.4-pro": CodexPricing(            inputCostPerToken: 3e-5,            outputCostPerToken: 1.8e-4,            cacheReadInputCostPerToken: nil,            displayLabel: nil),        "gpt-5.5": CodexPricing(            inputCostPerToken: 5e-6,            outputCostPerToken: 3e-5,            cacheReadInputCostPerToken: 5e-7,            displayLabel: nil,            thresholdTokens: 272_000,            inputCostPerTokenAboveThreshold: 1e-5,            outputCostPerTokenAboveThreshold: 4.5e-5,            cacheReadInputCostPerTokenAboveThreshold: 1e-6,            priorityInputCostPerToken: 1.25e-5,            priorityOutputCostPerToken: 7.5e-5,            priorityCacheReadInputCostPerToken: 1.25e-6),        "gpt-5.5-pro": CodexPricing(            inputCostPerToken: 3e-5,            outputCostPerToken: 1.8e-4,            cacheReadInputCostPerToken: nil,            displayLabel: nil),    ]     static func codexBuiltInPricingFingerprint() -> String {        var parts = ["priorityInputTokenLimit=\(self.codexPriorityInputTokenLimit)"]        for model in self.codex.keys.sorted() {            guard let pricing = self.codex[model] else { continue }            parts.append([                "model=\(model)",                self.optionalPricingFingerprint(pricing.inputCostPerToken),                self.optionalPricingFingerprint(pricing.outputCostPerToken),                self.optionalPricingFingerprint(pricing.cacheReadInputCostPerToken),                pricing.displayLabel ?? "nil",                pricing.thresholdTokens.map(String.init) ?? "nil",                self.optionalPricingFingerprint(pricing.inputCostPerTokenAboveThreshold),                self.optionalPricingFingerprint(pricing.outputCostPerTokenAboveThreshold),                self.optionalPricingFingerprint(pricing.cacheReadInputCostPerTokenAboveThreshold),                self.optionalPricingFingerprint(pricing.priorityInputCostPerToken),                self.optionalPricingFingerprint(pricing.priorityOutputCostPerToken),                self.optionalPricingFingerprint(pricing.priorityCacheReadInputCostPerToken),            ].joined(separator: "|"))        }        return parts.joined(separator: "\n")    }     private static func optionalPricingFingerprint(_ value: Double?) -> String {        guard let value else { return "nil" }        return String(format: "%.17g", value)    }     private static let claude: [String: ClaudePricing] = [        "claude-fable-5": ClaudePricing(            inputCostPerToken: 1e-5,            outputCostPerToken: 5e-5,            cacheCreationInputCostPerToken: 1.25e-5,            cacheReadInputCostPerToken: 1e-6,            thresholdTokens: nil,            inputCostPerTokenAboveThreshold: nil,            outputCostPerTokenAboveThreshold: nil,            cacheCreationInputCostPerTokenAboveThreshold: nil,            cacheReadInputCostPerTokenAboveThreshold: nil),        "claude-haiku-4-5-20251001": ClaudePricing(            inputCostPerToken: 1e-6,            outputCostPerToken: 5e-6,            cacheCreationInputCostPerToken: 1.25e-6,            cacheReadInputCostPerToken: 1e-7,            thresholdTokens: nil,            inputCostPerTokenAboveThreshold: nil,            outputCostPerTokenAboveThreshold: nil,            cacheCreationInputCostPerTokenAboveThreshold: nil,            cacheReadInputCostPerTokenAboveThreshold: nil),        "claude-haiku-4-5": ClaudePricing(            inputCostPerToken: 1e-6,            outputCostPerToken: 5e-6,            cacheCreationInputCostPerToken: 1.25e-6,            cacheReadInputCostPerToken: 1e-7,            thresholdTokens: nil,            inputCostPerTokenAboveThreshold: nil,            outputCostPerTokenAboveThreshold: nil,            cacheCreationInputCostPerTokenAboveThreshold: nil,            cacheReadInputCostPerTokenAboveThreshold: nil),        "claude-opus-4-5-20251101": ClaudePricing(            inputCostPerToken: 5e-6,            outputCostPerToken: 2.5e-5,            cacheCreationInputCostPerToken: 6.25e-6,            cacheReadInputCostPerToken: 5e-7,            thresholdTokens: nil,            inputCostPerTokenAboveThreshold: nil,            outputCostPerTokenAboveThreshold: nil,            cacheCreationInputCostPerTokenAboveThreshold: nil,            cacheReadInputCostPerTokenAboveThreshold: nil),        "claude-opus-4-5": ClaudePricing(            inputCostPerToken: 5e-6,            outputCostPerToken: 2.5e-5,            cacheCreationInputCostPerToken: 6.25e-6,            cacheReadInputCostPerToken: 5e-7,            thresholdTokens: nil,            inputCostPerTokenAboveThreshold: nil,            outputCostPerTokenAboveThreshold: nil,            cacheCreationInputCostPerTokenAboveThreshold: nil,            cacheReadInputCostPerTokenAboveThreshold: nil),        "claude-opus-4-6-20260205": ClaudePricing(            inputCostPerToken: 5e-6,            outputCostPerToken: 2.5e-5,            cacheCreationInputCostPerToken: 6.25e-6,            cacheReadInputCostPerToken: 5e-7,            thresholdTokens: nil,            inputCostPerTokenAboveThreshold: nil,            outputCostPerTokenAboveThreshold: nil,            cacheCreationInputCostPerTokenAboveThreshold: nil,            cacheReadInputCostPerTokenAboveThreshold: nil),        "claude-opus-4-6": ClaudePricing(            inputCostPerToken: 5e-6,            outputCostPerToken: 2.5e-5,            cacheCreationInputCostPerToken: 6.25e-6,            cacheReadInputCostPerToken: 5e-7,            thresholdTokens: nil,            inputCostPerTokenAboveThreshold: nil,            outputCostPerTokenAboveThreshold: nil,            cacheCreationInputCostPerTokenAboveThreshold: nil,            cacheReadInputCostPerTokenAboveThreshold: nil),        "claude-opus-4-7": ClaudePricing(            inputCostPerToken: 5e-6,            outputCostPerToken: 2.5e-5,            cacheCreationInputCostPerToken: 6.25e-6,            cacheReadInputCostPerToken: 5e-7,            thresholdTokens: nil,            inputCostPerTokenAboveThreshold: nil,            outputCostPerTokenAboveThreshold: nil,            cacheCreationInputCostPerTokenAboveThreshold: nil,            cacheReadInputCostPerTokenAboveThreshold: nil),        "claude-opus-4-8": ClaudePricing(            inputCostPerToken: 5e-6,            outputCostPerToken: 2.5e-5,            cacheCreationInputCostPerToken: 6.25e-6,            cacheReadInputCostPerToken: 5e-7,            thresholdTokens: nil,            inputCostPerTokenAboveThreshold: nil,            outputCostPerTokenAboveThreshold: nil,            cacheCreationInputCostPerTokenAboveThreshold: nil,            cacheReadInputCostPerTokenAboveThreshold: nil),        "claude-sonnet-4-5": ClaudePricing(            inputCostPerToken: 3e-6,            outputCostPerToken: 1.5e-5,            cacheCreationInputCostPerToken: 3.75e-6,            cacheReadInputCostPerToken: 3e-7,            thresholdTokens: 200_000,            inputCostPerTokenAboveThreshold: 6e-6,            outputCostPerTokenAboveThreshold: 2.25e-5,            cacheCreationInputCostPerTokenAboveThreshold: 7.5e-6,            cacheReadInputCostPerTokenAboveThreshold: 6e-7),        "claude-sonnet-4-6": ClaudePricing(            inputCostPerToken: 3e-6,            outputCostPerToken: 1.5e-5,            cacheCreationInputCostPerToken: 3.75e-6,            cacheReadInputCostPerToken: 3e-7,            thresholdTokens: nil,            inputCostPerTokenAboveThreshold: nil,            outputCostPerTokenAboveThreshold: nil,            cacheCreationInputCostPerTokenAboveThreshold: nil,            cacheReadInputCostPerTokenAboveThreshold: nil),        "claude-sonnet-4-5-20250929": ClaudePricing(            inputCostPerToken: 3e-6,            outputCostPerToken: 1.5e-5,            cacheCreationInputCostPerToken: 3.75e-6,            cacheReadInputCostPerToken: 3e-7,            thresholdTokens: 200_000,            inputCostPerTokenAboveThreshold: 6e-6,            outputCostPerTokenAboveThreshold: 2.25e-5,            cacheCreationInputCostPerTokenAboveThreshold: 7.5e-6,            cacheReadInputCostPerTokenAboveThreshold: 6e-7),        "claude-opus-4-20250514": ClaudePricing(            inputCostPerToken: 1.5e-5,            outputCostPerToken: 7.5e-5,            cacheCreationInputCostPerToken: 1.875e-5,            cacheReadInputCostPerToken: 1.5e-6,            thresholdTokens: nil,            inputCostPerTokenAboveThreshold: nil,            outputCostPerTokenAboveThreshold: nil,            cacheCreationInputCostPerTokenAboveThreshold: nil,            cacheReadInputCostPerTokenAboveThreshold: nil),        "claude-opus-4-1": ClaudePricing(            inputCostPerToken: 1.5e-5,            outputCostPerToken: 7.5e-5,            cacheCreationInputCostPerToken: 1.875e-5,            cacheReadInputCostPerToken: 1.5e-6,            thresholdTokens: nil,            inputCostPerTokenAboveThreshold: nil,            outputCostPerTokenAboveThreshold: nil,            cacheCreationInputCostPerTokenAboveThreshold: nil,            cacheReadInputCostPerTokenAboveThreshold: nil),        "claude-sonnet-4-20250514": ClaudePricing(            inputCostPerToken: 3e-6,            outputCostPerToken: 1.5e-5,            cacheCreationInputCostPerToken: 3.75e-6,            cacheReadInputCostPerToken: 3e-7,            thresholdTokens: 200_000,            inputCostPerTokenAboveThreshold: 6e-6,            outputCostPerTokenAboveThreshold: 2.25e-5,            cacheCreationInputCostPerTokenAboveThreshold: 7.5e-6,            cacheReadInputCostPerTokenAboveThreshold: 6e-7),    ]     private static let claudeFullContextStandardPricingCutoff = Date(timeIntervalSince1970: 1_773_360_000)    private static let claudeHistoricalLongContext: [String: ClaudePricing] = [        "claude-opus-4-6": ClaudePricing(            inputCostPerToken: 5e-6,            outputCostPerToken: 2.5e-5,            cacheCreationInputCostPerToken: 6.25e-6,            cacheReadInputCostPerToken: 5e-7,            thresholdTokens: 200_000,            inputCostPerTokenAboveThreshold: 1e-5,            outputCostPerTokenAboveThreshold: 3.75e-5,            cacheCreationInputCostPerTokenAboveThreshold: 1.25e-5,            cacheReadInputCostPerTokenAboveThreshold: 1e-6),        "claude-sonnet-4-6": ClaudePricing(            inputCostPerToken: 3e-6,            outputCostPerToken: 1.5e-5,            cacheCreationInputCostPerToken: 3.75e-6,            cacheReadInputCostPerToken: 3e-7,            thresholdTokens: 200_000,            inputCostPerTokenAboveThreshold: 6e-6,            outputCostPerTokenAboveThreshold: 2.25e-5,            cacheCreationInputCostPerTokenAboveThreshold: 7.5e-6,            cacheReadInputCostPerTokenAboveThreshold: 6e-7),    ]     private static let codexModelsDevProviderID = "openai"    private static let claudeModelsDevProviderID = "anthropic"     static func normalizeCodexModel(_ raw: String) -> String {        var trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines)        if trimmed.hasPrefix("openai/") {            trimmed = String(trimmed.dropFirst("openai/".count))        }         if self.codex[trimmed] != nil {            return trimmed        }         if let datedSuffix = trimmed.range(of: #"-\d{4}-\d{2}-\d{2}$"#, options: .regularExpression) {            let base = String(trimmed[..<datedSuffix.lowerBound])            if self.codex[base] != nil {                return base            }        }        return trimmed    }     static func codexDisplayLabel(model: String) -> String? {        let key = self.normalizeCodexModel(model)        return self.codex[key]?.displayLabel    }     static func normalizeClaudeModel(_ raw: String) -> String {        var trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines)        if trimmed.hasPrefix("anthropic.") {            trimmed = String(trimmed.dropFirst("anthropic.".count))        }         if let lastDot = trimmed.lastIndex(of: "."),           trimmed.contains("claude-")        {            let tail = String(trimmed[trimmed.index(after: lastDot)...])            if tail.hasPrefix("claude-") {                trimmed = tail            }        }         if let vRange = trimmed.range(of: #"-v\d+:\d+$"#, options: .regularExpression) {            trimmed.removeSubrange(vRange)        }         if let baseRange = trimmed.range(of: #"-\d{8}$"#, options: .regularExpression) {            let base = String(trimmed[..<baseRange.lowerBound])            if self.claude[base] != nil {                return base            }        }         return trimmed    }     static func codexCostUSD(        model: String,        inputTokens: Int,        cachedInputTokens: Int,        outputTokens: Int,        modelsDevCatalog: ModelsDevCatalog? = nil,        modelsDevCacheRoot: URL? = nil) -> Double?    {        let key = self.normalizeCodexModel(model)        if let lookup = self.modelsDevLookup(            providerID: self.codexModelsDevProviderID,            model: model,            catalog: modelsDevCatalog,            cacheRoot: modelsDevCacheRoot)        {            return self.codexCostUSD(                pricing: lookup.pricing,                thresholdTokens: self.codex[key]?.thresholdTokens,                inputTokens: inputTokens,                cachedInputTokens: cachedInputTokens,                outputTokens: outputTokens)        }         guard let pricing = self.codex[key] else { return nil }        return self.codexCostUSD(            pricing: pricing,            inputTokens: inputTokens,            cachedInputTokens: cachedInputTokens,            outputTokens: outputTokens)    }     static func codexPriorityCostUSD(        model: String,        inputTokens: Int,        cachedInputTokens: Int = 0,        outputTokens: Int) -> Double?    {        let key = self.normalizeCodexModel(model)        guard let pricing = self.codex[key],              let priorityInputCostPerToken = pricing.priorityInputCostPerToken,              let priorityOutputCostPerToken = pricing.priorityOutputCostPerToken        else { return nil }        if max(0, inputTokens) > self.codexPriorityInputTokenLimit {            return nil        }         let priorityPricing = CodexPricing(            inputCostPerToken: priorityInputCostPerToken,            outputCostPerToken: priorityOutputCostPerToken,            cacheReadInputCostPerToken: pricing.priorityCacheReadInputCostPerToken,            displayLabel: nil)        return self.codexCostUSD(            pricing: priorityPricing,

Lines 1–500 of 668.