-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Codex: distinguish API estimates from subscription bills #2181
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
6c1bc67
0ed0de0
f8d7dec
3fabe80
88c0d36
4ad2613
49212f8
6fa2509
d737a0a
288e823
09f0fbe
31c8e34
96363a7
e5d2b76
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -343,12 +343,21 @@ extension UsageMenuCardView.Model { | |
| comparisonPeriodsEnabled: Bool) -> InlineUsageDashboardModel | ||
| { | ||
| let historyDays = max(1, min(365, snapshot.historyDays)) | ||
| let historyTitle = snapshot.historyLabel | ||
| let defaultHistoryTitle = snapshot.historyLabel | ||
| ?? (historyDays == 1 | ||
| ? L("Today") | ||
| : historyDays == 30 | ||
| ? L("30d cost") | ||
| : "\(String(format: L("Last %d days"), historyDays)) \(L("Cost"))") | ||
| let codexHistoryPeriod = snapshot.historyLabel | ||
| ?? (historyDays == 1 | ||
| ? L("Today") | ||
| : historyDays == 30 | ||
| ? "30d" | ||
| : String(format: L("Last %d days"), historyDays)) | ||
| let historyTitle = provider == .codex | ||
| ? "\(codexHistoryPeriod) · \(L("codex_api_estimate_header"))" | ||
| : defaultHistoryTitle | ||
| let tokenHistoryTitle = snapshot.historyLabel.map { "\($0) \(L("tokens"))" } | ||
| ?? (historyDays == 1 | ||
| ? L("Today tokens") | ||
|
|
@@ -388,19 +397,28 @@ extension UsageMenuCardView.Model { | |
| details | ||
| .append("\(requestHistoryTitle): \(UsageFormatter.tokenCountString(requestCount)) \(L("requests"))") | ||
| } | ||
| if let hint = Self.tokenUsageHint(provider: provider) { | ||
| details.append(hint) | ||
| let hintLines = Self.tokenUsageHintLines(provider: provider) | ||
| if hintLines.isEmpty == false { | ||
| details.append(contentsOf: hintLines) | ||
| } else { | ||
| details.append(L("cost_estimate_hint")) | ||
| } | ||
| } | ||
| let providerName = ProviderDefaults.metadata[provider]?.displayName ?? provider.rawValue | ||
| let codexEstimateHeader = L("codex_api_estimate_header") | ||
| let accessibilityLabel = if provider == .codex { | ||
| "\(providerName) \(periodLabel) \(codexEstimateHeader) trend" | ||
| } else { | ||
| "\(providerName) \(periodLabel) cost trend" | ||
| } | ||
| var model = InlineUsageDashboardModel( | ||
| accessibilityLabel: "\(providerName) \(periodLabel) cost trend", | ||
| accessibilityLabel: accessibilityLabel, | ||
| valueStyle: Self.costValueStyle(currencyCode: snapshot.currencyCode), | ||
| kpis: [ | ||
| .init( | ||
| title: usesLatestPrimary ? L("Latest") : L("Today"), | ||
| title: provider == .codex | ||
| ? "\(L("Today")) · \(L("codex_api_estimate_header"))" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When Useful? React with 👍 / 👎. |
||
| : usesLatestPrimary ? L("Latest") : L("Today"), | ||
| value: primaryCostUSD.map { Self.costString($0, currencyCode: snapshot.currencyCode) } ?? "—", | ||
| emphasis: true), | ||
| .init( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -169,21 +169,34 @@ extension UsageMenuCardView.Model { | |
| } | ||
|
|
||
| static func tokenUsageHint(provider: UsageProvider) -> String? { | ||
| let lines = Self.tokenUsageHintLines(provider: provider) | ||
| return lines.isEmpty ? nil : lines.joined(separator: "\n") | ||
| } | ||
|
|
||
| static func tokenUsageHeader(provider: UsageProvider) -> String { | ||
| provider == .codex ? L("codex_api_estimate_header") : L("cost_header_estimated") | ||
|
Comment on lines
+176
to
+177
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This adds a provider-specific token-usage header, but the Settings provider detail still renders Codex token USD as Useful? React with 👍 / 👎. |
||
| } | ||
|
|
||
| static func tokenUsageHintLines(provider: UsageProvider) -> [String] { | ||
| switch provider { | ||
| case .codex: | ||
| L("Estimated from local Codex logs for the selected account.") | ||
| [ | ||
| L("Estimated from local Codex logs for the selected account."), | ||
| L("codex_api_estimate_not_billed"), | ||
| L("codex_api_estimate_hint"), | ||
| ] | ||
| case .claude: | ||
| UsageFormatter.costEstimateHint(provider: provider) | ||
| [UsageFormatter.costEstimateHint(provider: provider)] | ||
| case .vertexai: | ||
| L("cost_estimate_hint") | ||
| [L("cost_estimate_hint")] | ||
| case .bedrock: | ||
| L("AWS Cost Explorer billing can lag.") | ||
| [L("AWS Cost Explorer billing can lag.")] | ||
| case .openai: | ||
| L("Reported by OpenAI Admin API organization usage.") | ||
| [L("Reported by OpenAI Admin API organization usage.")] | ||
| case .mistral: | ||
| L("Reported by Mistral billing usage.") | ||
| [L("Reported by Mistral billing usage.")] | ||
| default: | ||
| nil | ||
| [] | ||
| } | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the app is running in a non-English locale and the Codex inline dashboard uses the default 30-day window, this literal bypasses the existing localized
30dkey, so the second KPI becomes mixed-language like30d · API-equivalent estimateeven though the previous 30-day cost label was localized throughL("30d cost"). UseL("30d")for this period before appending the Codex-specific header.Useful? React with 👍 / 👎.