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. Load more
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,