Files
steipete--codexbar/Sources/CodexBar/InlineUsageDashboardContent.swift
2026-07-13 12:22:33 +08:00

915 lines
38 KiB
Swift

import CodexBarCore
import SwiftUI
struct InlineUsageDashboardModel: Equatable {
struct KPI: Equatable {
let title: String
let value: String
let emphasis: Bool
}
struct Point: Equatable, Identifiable {
let id: String
let label: String
let value: Double
let accessibilityValue: String
}
enum ValueStyle: Equatable {
case currencyUSD
case currency(symbol: String)
case tokens
case points
}
let accessibilityLabel: String
let valueStyle: ValueStyle
let kpis: [KPI]
let points: [Point]
let detailLines: [String]
/// Provider branding color used to fill the mini usage bars. When nil the bars fall back to a
/// neutral palette derived from `valueStyle`.
var barColor: Color?
/// ISO 4217 currency code for cost dashboards. When non-nil, `MiniUsageBars` shows a max-cost scale label.
/// Nil for token/points dashboards.
var currencyCode: String?
}
extension UsageMenuCardView.Model {
static func apiProviderUsageNotes(input: Input) -> [String]? {
if input.provider == .openai,
let usage = input.snapshot?.openAIAPIUsage
{
return self.openAIAPIUsageNotes(usage)
}
if input.provider == .deepgram,
let usage = input.snapshot?.deepgramUsage
{
return usage.displayLines
}
if input.provider == .clawrouter,
let usage = input.snapshot?.clawRouterUsage
{
var notes = [
"\(UsageFormatter.tokenCountString(usage.requestCount)) \(L("requests")) · " +
"\(UsageFormatter.tokenCountString(usage.totalTokens)) \(L("tokens"))",
]
if usage.errorCount > 0 {
notes.append("\(usage.successCount) succeeded · \(usage.errorCount) failed")
}
if !usage.providers.isEmpty {
let mix = usage.providers.prefix(5)
.map { "\($0.provider): \(UsageFormatter.tokenCountString($0.requestCount))" }
.joined(separator: " · ")
notes.append("Routed providers: \(mix)")
}
return notes
}
if input.provider == .wayfinder,
let usage = input.snapshot?.wayfinderUsage
{
return usage.displayLines
}
if input.provider == .minimax,
input.showOptionalCreditsAndExtraUsage,
let billing = input.snapshot?.minimaxUsage?.billingSummary
{
return [
String(format: L("Today: %@ tokens"), UsageFormatter.tokenCountString(billing.todayTokens)),
String(
format: L("Last 30 days: %@ tokens"),
UsageFormatter.tokenCountString(billing.last30DaysTokens)),
]
}
if input.provider == .deepseek,
input.showOptionalCreditsAndExtraUsage,
let usage = input.snapshot?.deepseekUsage
{
let symbol = usage.currency == "CNY" ? "¥" : "$"
let todayCostStr = usage.todayCost.map { "\(symbol)\(String(format: "%.4f", max(0, $0)))" } ?? "—"
return [
String(
format: L("Today: %@ · %@ tokens"),
todayCostStr,
UsageFormatter.tokenCountString(usage.todayTokens)),
String(format: L("This month: %@ tokens"), UsageFormatter.tokenCountString(usage.currentMonthTokens)),
]
}
if input.provider == .poe,
let usage = input.snapshot?.poeUsage
{
return self.poeUsageNotes(usage, now: input.now)
}
if input.provider == .ollama,
input.snapshot?.identity?.loginMethod == "API key"
{
return [L("API key verified. Ollama does not expose Cloud quota limits through the API.")]
}
return nil
}
static func openAIAPIUsageNotes(_ usage: OpenAIAPIUsageSnapshot) -> [String] {
let today = usage.currentDay
let seven = usage.last7Days
let thirty = usage.last30Days
let historyLabel = usage.historyWindowLabel
let todayNote = String(
format: L("Today: %@ · %@ tokens"),
UsageFormatter.usdString(today.costUSD),
UsageFormatter.tokenCountString(today.totalTokens))
let sevenDayNote = "7d: \(UsageFormatter.usdString(seven.costUSD)) · " +
"\(UsageFormatter.tokenCountString(seven.requests)) \(L("requests"))"
let thirtyDayNote =
"\(historyLabel): \(UsageFormatter.tokenCountString(thirty.totalTokens)) \(L("tokens")) · " +
"\(UsageFormatter.tokenCountString(thirty.requests)) \(L("requests"))"
var notes: [String] = [
todayNote,
sevenDayNote,
thirtyDayNote,
]
if let topModel = usage.topModels.first {
notes.append("\(L("Top model")): \(topModel.name)")
}
return notes
}
static func poeUsageNotes(
_ usage: PoeUsageHistorySnapshot,
now: Date = Date(),
calendar: Calendar = .current) -> [String]
{
let today = usage.currentDay(now: now, calendar: calendar)
let week = usage.last7Days
let month = usage.last30Days
let todayUSD = today.costUSD.map { " · \(UsageFormatter.usdString($0))" } ?? ""
let weekUSD = week.costUSD.map { " · \(UsageFormatter.usdString($0))" } ?? ""
let monthUSD = month.costUSD.map { " · \(UsageFormatter.usdString($0))" } ?? ""
let todayLine = "Today: \(Self.pointsSummary(today.points)) · " +
"\(UsageFormatter.tokenCountString(today.requests)) \(L("requests"))\(todayUSD)"
let weekLine = "7d: \(Self.pointsSummary(week.points)) · " +
"\(UsageFormatter.tokenCountString(week.requests)) \(L("requests"))\(weekUSD)"
let monthLine = "30d: \(Self.pointsSummary(month.points)) · " +
"\(UsageFormatter.tokenCountString(month.requests)) \(L("requests"))\(monthUSD)"
var notes = [
todayLine,
weekLine,
monthLine,
]
if let topModel = usage.topModels.first {
notes.append("\(L("Top model")): \(topModel.name) (\(Self.pointsSummary(topModel.points)))")
}
if !usage.topUsageTypes.isEmpty {
let mix = usage.topUsageTypes.prefix(2)
.map { "\($0.name): \(Self.pointsSummary($0.points))" }
.joined(separator: " · ")
notes.append("Usage mix: \(mix)")
}
return notes
}
static func inlineUsageDashboard(input: Input) -> InlineUsageDashboardModel? {
guard var model = self.resolveInlineUsageDashboard(input: input) else { return nil }
model.barColor = Self.inlineDashboardBarColor(for: input.provider)
return model
}
/// Provider branding color for the inline usage bars, matching the provider's switcher tab and
/// detailed cost-history chart.
static func inlineDashboardBarColor(for provider: UsageProvider) -> Color {
let color = ProviderDescriptorRegistry.descriptor(for: provider).branding.color
return Color(red: color.red, green: color.green, blue: color.blue)
}
private static func resolveInlineUsageDashboard(input: Input) -> InlineUsageDashboardModel? {
if self.usesProviderCostHistoryAsPrimaryDashboard(input.provider),
let tokenSnapshot = primaryCostHistorySnapshot(input: input),
!tokenSnapshot.daily.isEmpty
{
return self.costHistoryInlineDashboard(
provider: input.provider,
snapshot: tokenSnapshot,
comparisonPeriodsEnabled: input.costComparisonPeriodsEnabled)
}
if input.provider == .claude,
let usage = input.snapshot?.claudeAdminAPIUsage
{
return Self.claudeAdminAPIInlineDashboard(usage)
}
if input.provider == .openrouter,
let usage = input.snapshot?.openRouterUsage
{
return Self.openRouterInlineDashboard(usage)
}
if input.provider == .crossmodel,
let usage = input.snapshot?.crossModelUsage
{
return Self.crossModelInlineDashboard(usage)
}
if input.provider == .zai,
let modelUsage = input.snapshot?.zaiUsage?.modelUsage
{
return Self.zaiInlineDashboard(modelUsage: modelUsage, now: input.now)
}
if input.provider == .minimax,
input.showOptionalCreditsAndExtraUsage,
let billing = input.snapshot?.minimaxUsage?.billingSummary,
!billing.daily.isEmpty
{
return Self.minimaxInlineDashboard(billing)
}
if input.provider == .deepseek,
input.showOptionalCreditsAndExtraUsage,
let usage = input.snapshot?.deepseekUsage,
!usage.daily.isEmpty
{
return Self.deepseekInlineDashboard(usage)
}
if input.provider == .poe,
let usage = input.snapshot?.poeUsage,
!usage.daily.isEmpty
{
return Self.poeInlineDashboard(usage, now: input.now)
}
if [.codex, .claude, .vertexai, .bedrock].contains(input.provider),
input.tokenCostInlineDashboardEnabled,
let tokenSnapshot = input.tokenSnapshot,
!tokenSnapshot.daily.isEmpty
{
return Self.costHistoryInlineDashboard(
provider: input.provider,
snapshot: tokenSnapshot,
comparisonPeriodsEnabled: input.costComparisonPeriodsEnabled)
}
return nil
}
static func usesProviderCostHistoryAsPrimaryDashboard(_ provider: UsageProvider) -> Bool {
provider == .openai || provider == .mistral
}
static func primaryCostHistorySnapshot(input: Input) -> CostUsageTokenSnapshot? {
switch input.provider {
case .openai:
if let projected = input.snapshot?.openAIAPIUsage?.toCostUsageTokenSnapshot() {
return projected
}
return input.snapshot == nil ? input.tokenSnapshot : nil
case .mistral:
if let projected = input.snapshot?.mistralUsage?.toCostUsageTokenSnapshot() {
return projected
}
return input.snapshot == nil ? input.tokenSnapshot : nil
default:
return input.tokenSnapshot
}
}
static func poeInlineDashboard(
_ usage: PoeUsageHistorySnapshot,
now: Date = Date(),
calendar: Calendar = .current) -> InlineUsageDashboardModel
{
let today = usage.currentDay(now: now, calendar: calendar)
let week = usage.last7Days
let month = usage.last30Days
let points = usage.daily.suffix(30).map {
InlineUsageDashboardModel.Point(
id: $0.day,
label: Self.shortDayLabel($0.day),
value: $0.points,
accessibilityValue: "\($0.day): \(Self.pointsSummary($0.points))")
}
var details = ["30d requests: \(UsageFormatter.tokenCountString(month.requests))"]
if let topModel = usage.topModel {
details.append("\(L("Top model")): \(topModel)")
}
if !usage.topUsageTypes.isEmpty {
let mix = usage.topUsageTypes.prefix(3)
.map { "\($0.name): \(Self.pointsSummary($0.points))" }
.joined(separator: " · ")
details.append("Usage mix: \(mix)")
}
if let usd = today.costUSD, usd > 0 {
details.append("Today USD: \(UsageFormatter.usdString(usd))")
}
if let usd = week.costUSD, usd > 0 {
details.append("7d USD: \(UsageFormatter.usdString(usd))")
}
if let usd = month.costUSD, usd > 0 {
details.append("30d USD: \(UsageFormatter.usdString(usd))")
}
let recent = usage.recentEntries(limit: 2)
if !recent.isEmpty {
let text = recent.map { "\($0.model) \(Self.pointsSummary($0.points))" }.joined(separator: " · ")
details.append("Recent: \(text)")
}
return InlineUsageDashboardModel(
accessibilityLabel: "Poe points usage trend",
valueStyle: .points,
kpis: [
.init(title: L("Today"), value: Self.pointsSummary(today.points), emphasis: true),
.init(title: "7d", value: Self.pointsSummary(week.points), emphasis: false),
.init(title: "30d", value: Self.pointsSummary(month.points), emphasis: false),
.init(title: L("Requests"), value: UsageFormatter.tokenCountString(month.requests), emphasis: false),
],
points: points,
detailLines: details)
}
static func pointsSummary(_ value: Double) -> String {
let clamped = max(0, value)
if clamped.rounded() == clamped {
return "\(UsageFormatter.tokenCountString(Int(clamped))) points"
}
return "\(String(format: "%.1f", clamped)) points"
}
private static func costHistoryInlineDashboard(
provider: UsageProvider,
snapshot: CostUsageTokenSnapshot,
comparisonPeriodsEnabled: Bool) -> InlineUsageDashboardModel
{
let historyDays = max(1, min(365, snapshot.historyDays))
let historyTitle = snapshot.historyLabel
?? (historyDays == 1
? L("Today")
: historyDays == 30
? L("30d cost")
: "\(String(format: L("Last %d days"), historyDays)) \(L("Cost"))")
let tokenHistoryTitle = snapshot.historyLabel.map { "\($0) \(L("tokens"))" }
?? (historyDays == 1
? L("Today tokens")
: historyDays == 30
? L("30d tokens")
: String(format: L("%@ tokens"), String(format: L("Last %d days"), historyDays)))
let requestHistoryTitle = snapshot.historyLabel.map { "\($0) \(L("requests"))" }
?? (historyDays == 1
? L("Today requests")
: historyDays == 30
? L("30d requests")
: String(format: L("%@ requests"), String(format: L("Last %d days"), historyDays)))
let periodLabel = snapshot.historyLabel?.lowercased()
?? (historyDays == 1 ? "today" : "\(historyDays) day")
let points = snapshot.daily.suffix(historyDays).compactMap { entry -> InlineUsageDashboardModel.Point? in
guard let cost = entry.costUSD else { return nil }
return InlineUsageDashboardModel.Point(
id: entry.date,
label: Self.shortDayLabel(entry.date),
value: cost,
accessibilityValue: "\(entry.date): \(Self.costString(cost, currencyCode: snapshot.currencyCode))")
}
let latest = CostUsageTokenSnapshot.latestEntry(in: snapshot.daily)
let usesLatestPrimary = provider == .bedrock || provider == .mistral
let primaryCostUSD = usesLatestPrimary ? latest?.costUSD : snapshot.sessionCostUSD
var details: [String] = []
if comparisonPeriodsEnabled {
details.append(contentsOf: snapshot.comparisonSummaries().map {
Self.costWindowLine(summary: $0, currencyCode: snapshot.currencyCode)
})
}
if let topModel = Self.topCostModel(from: snapshot.daily) {
details.append("\(L("Top model")): \(Self.shortModelName(topModel))")
}
if let requestCount = snapshot.last30DaysRequests {
details.append("\(requestHistoryTitle): \(UsageFormatter.tokenCountString(requestCount)) \(L("requests"))")
}
if let hint = Self.tokenUsageHint(provider: provider) {
details.append(hint)
} else {
details.append(L("cost_estimate_hint"))
}
let providerName = ProviderDefaults.metadata[provider]?.displayName ?? provider.rawValue
var model = InlineUsageDashboardModel(
accessibilityLabel: "\(providerName) \(periodLabel) cost trend",
valueStyle: Self.costValueStyle(currencyCode: snapshot.currencyCode),
kpis: [
.init(
title: usesLatestPrimary ? L("Latest") : L("Today"),
value: primaryCostUSD.map { Self.costString($0, currencyCode: snapshot.currencyCode) } ?? "—",
emphasis: true),
.init(
title: historyTitle,
value: snapshot.last30DaysCostUSD
.map { Self.costString($0, currencyCode: snapshot.currencyCode) } ?? "—",
emphasis: false),
.init(
title: tokenHistoryTitle,
value: snapshot.last30DaysTokens.map(UsageFormatter.tokenCountString) ?? "—",
emphasis: false),
] + Self.costHistoryTrailingKPIs(snapshot: snapshot, latest: latest),
points: points,
detailLines: details)
model.currencyCode = snapshot.currencyCode
return model
}
private static func costHistoryTrailingKPIs(
snapshot: CostUsageTokenSnapshot,
latest: CostUsageDailyReport.Entry?)
-> [InlineUsageDashboardModel.KPI]
{
if let requests = snapshot.last30DaysRequests {
return [
.init(
title: L("Requests"),
value: UsageFormatter.tokenCountString(requests),
emphasis: false),
]
}
return [
.init(
title: L("Latest tokens"),
value: latest?.totalTokens.map(UsageFormatter.tokenCountString) ?? "—",
emphasis: false),
]
}
fileprivate static func claudeAdminAPIInlineDashboard(_ usage: ClaudeAdminAPIUsageSnapshot)
-> InlineUsageDashboardModel
{
let today = usage.currentDay
let last7 = usage.last7Days
let last30 = usage.last30Days
let points = usage.daily.suffix(30).map {
InlineUsageDashboardModel.Point(
id: $0.day,
label: Self.shortDayLabel($0.day),
value: $0.costUSD,
accessibilityValue: "\($0.day): \(UsageFormatter.usdString($0.costUSD))")
}
var details = [
"30d: \(UsageFormatter.tokenCountString(last30.totalTokens)) \(L("tokens"))",
"\(L("Cache read")): \(UsageFormatter.tokenCountString(last30.cacheReadInputTokens)) \(L("tokens"))",
]
if let topModel = usage.topModels.first {
details.append("\(L("Top model")): \(Self.shortModelName(topModel.name))")
}
var model = InlineUsageDashboardModel(
accessibilityLabel: L("Claude Admin API 30 day spend trend"),
valueStyle: .currencyUSD,
kpis: [
.init(title: L("Today"), value: UsageFormatter.usdString(today.costUSD), emphasis: true),
.init(title: L("7d spend"), value: UsageFormatter.usdString(last7.costUSD), emphasis: false),
.init(
title: L("30d spend"),
value: UsageFormatter.usdString(last30.costUSD),
emphasis: false),
.init(
title: L("Today tokens"),
value: UsageFormatter.tokenCountString(today.totalTokens),
emphasis: false),
],
points: points,
detailLines: details)
model.currencyCode = "USD"
return model
}
private static func crossModelInlineDashboard(_ usage: CrossModelUsageSnapshot) -> InlineUsageDashboardModel? {
let periodValues: [(String, String, Double?)] = [
("day", L("Today"), usage.daily?.cost),
("week", L("Week"), usage.weekly?.cost),
("month", L("Month"), usage.monthly?.cost),
]
let points = periodValues.compactMap { id, label, value -> InlineUsageDashboardModel.Point? in
guard let value else { return nil }
return InlineUsageDashboardModel.Point(
id: id,
label: label,
value: value,
accessibilityValue: "\(label): \(usage.currencyString(value))")
}
var model = InlineUsageDashboardModel(
accessibilityLabel: L("CrossModel API spend trend"),
valueStyle: Self.costValueStyle(currencyCode: usage.currency),
kpis: [
.init(title: L("Balance"), value: usage.balanceDisplay, emphasis: true),
.init(
title: L("Today"),
value: usage.daily.map { usage.currencyString($0.cost) } ?? "—",
emphasis: false),
.init(
title: L("Week"),
value: usage.weekly.map { usage.currencyString($0.cost) } ?? "—",
emphasis: false),
.init(
title: L("Month"),
value: usage.monthly.map { usage.currencyString($0.cost) } ?? "—",
emphasis: false),
],
points: points,
detailLines: [])
model.currencyCode = usage.currency
return model
}
private static func openRouterInlineDashboard(_ usage: OpenRouterUsageSnapshot) -> InlineUsageDashboardModel? {
let periodValues: [(String, String, Double?)] = [
("day", L("Today"), usage.keyUsageDaily),
("week", L("Week"), usage.keyUsageWeekly),
("month", L("Month"), usage.keyUsageMonthly),
]
let points = periodValues.compactMap { id, label, value -> InlineUsageDashboardModel.Point? in
guard let value else { return nil }
let formattedValue = Self.openRouterCurrencyString(value)
return InlineUsageDashboardModel.Point(
id: id,
label: label,
value: value,
accessibilityValue: String(format: L("%@: %@"), label, formattedValue))
}
guard !points.isEmpty else { return nil }
var details: [String] = []
if let rate = usage.rateLimit {
details.append(String(format: L("Rate limit: %d / %@"), rate.requests, rate.interval))
}
switch usage.keyQuotaStatus {
case .available:
if let remaining = usage.keyRemaining {
details.append(String(
format: L("%@: %@"),
L("Key remaining"),
Self.openRouterCurrencyString(remaining)))
}
case .noLimitConfigured:
details.append(L("No limit set for the API key"))
case .unavailable:
details.append(L("API key limit unavailable right now"))
}
var model = InlineUsageDashboardModel(
accessibilityLabel: L("OpenRouter API key spend trend"),
valueStyle: .currencyUSD,
kpis: [
.init(title: L("Balance"), value: Self.openRouterCurrencyString(usage.balance), emphasis: true),
.init(
title: L("Today"),
value: usage.keyUsageDaily.map(Self.openRouterCurrencyString) ?? "—",
emphasis: false),
.init(
title: L("Week"),
value: usage.keyUsageWeekly.map(Self.openRouterCurrencyString) ?? "—",
emphasis: false),
.init(
title: L("Month"),
value: usage.keyUsageMonthly.map(Self.openRouterCurrencyString) ?? "—",
emphasis: false),
],
points: points,
detailLines: details)
model.currencyCode = "USD"
return model
}
private static func zaiInlineDashboard(modelUsage: ZaiModelUsageData, now: Date) -> InlineUsageDashboardModel? {
let bars = ZaiHourlyBars.from(modelData: modelUsage, range: .last24h, now: now)
guard !bars.isEmpty else { return nil }
let total = bars.reduce(0) { $0 + $1.totalTokens }
let latest = bars.last
let peak = bars.max { $0.totalTokens < $1.totalTokens }
let points = bars.enumerated().map { index, bar in
InlineUsageDashboardModel.Point(
id: "\(index)-\(bar.label)",
label: bar.label,
value: Double(bar.totalTokens),
accessibilityValue: "\(bar.label): \(UsageFormatter.tokenCountString(bar.totalTokens)) \(L("tokens"))")
}
let topModel = Self.topZaiModel(from: bars)
return InlineUsageDashboardModel(
accessibilityLabel: L("z.ai hourly token trend"),
valueStyle: .tokens,
kpis: [
.init(title: L("24h tokens"), value: UsageFormatter.tokenCountString(total), emphasis: true),
.init(
title: L("Latest hour"),
value: latest.map { UsageFormatter.tokenCountString($0.totalTokens) } ?? "—",
emphasis: false),
.init(
title: L("Peak hour"),
value: peak.map { UsageFormatter.tokenCountString($0.totalTokens) } ?? "—",
emphasis: false),
.init(title: L("Models"), value: "\(modelUsage.modelNames.count)", emphasis: false),
],
points: points,
detailLines: topModel.map { ["\(L("Top model")): \(Self.shortModelName($0))"] } ?? [])
}
private static func minimaxInlineDashboard(_ billing: MiniMaxBillingSummary) -> InlineUsageDashboardModel {
let points = billing.daily.suffix(30).map {
InlineUsageDashboardModel.Point(
id: $0.day,
label: Self.shortDayLabel($0.day),
value: Double($0.tokens),
accessibilityValue: "\($0.day): \(UsageFormatter.tokenCountString($0.tokens)) \(L("tokens"))")
}
var details = [L("30d billing history from MiniMax web session")]
if let topModel = billing.topModels.first {
details.append("\(L("Top model")): \(Self.shortModelName(topModel.name))")
}
if let topMethod = billing.topMethods.first {
details.append("\(L("Top method")): \(Self.shortModelName(topMethod.name))")
}
if let cash = billing.last30DaysCash {
details.append("\(L("30d cash")): \(Self.minimaxCashString(cash))")
}
return InlineUsageDashboardModel(
accessibilityLabel: L("MiniMax 30 day token usage trend"),
valueStyle: .tokens,
kpis: [
.init(
title: L("Today"),
value: UsageFormatter.tokenCountString(billing.todayTokens),
emphasis: true),
.init(
title: L("30d tokens"),
value: UsageFormatter.tokenCountString(billing.last30DaysTokens),
emphasis: false),
.init(
title: L("Today cash"),
value: billing.todayCash.map(Self.minimaxCashString) ?? "—",
emphasis: false),
.init(
title: L("Models"),
value: "\(billing.topModels.count)",
emphasis: false),
],
points: points,
detailLines: details)
}
private static func deepseekInlineDashboard(_ usage: DeepSeekUsageSummary) -> InlineUsageDashboardModel {
let symbol = usage.currency == "CNY" ? "¥" : "$"
let points = usage.daily.suffix(30).map {
InlineUsageDashboardModel.Point(
id: $0.date,
label: Self.shortDayLabel($0.date),
value: Double($0.totalTokens),
accessibilityValue: "\($0.date): \(UsageFormatter.tokenCountString($0.totalTokens)) \(L("tokens"))")
}
var details: [String] = []
if let topModel = usage.topModel {
details.append("\(L("Top model")): \(Self.shortModelName(topModel))")
}
if let cacheHit = usage.categoryBreakdown.first(where: { $0.category == .promptCacheHitToken }) {
details.append("\(L("cache-hit input")): \(UsageFormatter.tokenCountString(cacheHit.tokens))")
}
if let cacheMiss = usage.categoryBreakdown.first(where: { $0.category == .promptCacheMissToken }) {
details.append("\(L("cache-miss input")): \(UsageFormatter.tokenCountString(cacheMiss.tokens))")
}
if let output = usage.categoryBreakdown.first(where: { $0.category == .responseToken }) {
details.append("\(L("output")): \(UsageFormatter.tokenCountString(output.tokens))")
}
details.append("\(L("requests")): \(usage.currentMonthRequestCount)")
let todayCostStr = usage.todayCost.map { "\(symbol)\(String(format: "%.4f", max(0, $0)))" } ?? "—"
let monthCostStr = usage.currentMonthCost.map { "\(symbol)\(String(format: "%.4f", max(0, $0)))" } ?? "—"
let monthTokensStr = UsageFormatter.tokenCountString(usage.currentMonthTokens)
return InlineUsageDashboardModel(
accessibilityLabel: L("DeepSeek 30 day token usage trend"),
valueStyle: .tokens,
kpis: [
.init(
title: L("Today"),
value: "\(todayCostStr) · \(UsageFormatter.tokenCountString(usage.todayTokens))",
emphasis: true),
.init(
title: L("This month"),
value: "\(monthCostStr) · \(monthTokensStr)",
emphasis: false),
.init(
title: L("Models"),
value: usage.topModel.map { Self.shortModelName($0) } ?? "—",
emphasis: false),
.init(
title: L("Requests"),
value: "\(usage.currentMonthRequestCount)",
emphasis: false),
],
points: points,
detailLines: details)
}
private static func topMistralModel(from entries: [MistralDailyUsageBucket]) -> String? {
var tokens: [String: Int] = [:]
for entry in entries {
for model in entry.models {
tokens[model.name, default: 0] += model.totalTokens
}
}
return tokens.max {
if $0.value == $1.value { return $0.key > $1.key }
return $0.value < $1.value
}?.key
}
private static func topZaiModel(from bars: [ZaiHourlyBar]) -> String? {
var tokens: [String: Int] = [:]
for bar in bars {
for segment in bar.segments {
tokens[segment.model, default: 0] += segment.tokens
}
}
return tokens.max {
if $0.value == $1.value { return $0.key > $1.key }
return $0.value < $1.value
}?.key
}
private static func openRouterCurrencyString(_ value: Double) -> String {
String(format: "$%.2f", value)
}
private static func minimaxCashString(_ value: Double) -> String {
String(format: "%.2f", max(0, value))
}
private static func costString(_ value: Double, currencyCode: String) -> String {
UsageFormatter.currencyString(value, currencyCode: currencyCode)
}
private static func costValueStyle(currencyCode: String) -> InlineUsageDashboardModel.ValueStyle {
if currencyCode == "USD" { return .currencyUSD }
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.currencyCode = currencyCode
formatter.locale = Locale(identifier: "en_US")
let symbol = formatter.currencySymbol ?? currencyCode
return .currency(symbol: symbol)
}
private static func shortDayLabel(_ day: String) -> String {
let pieces = day.split(separator: "-")
guard pieces.count == 3, let rawDay = Int(pieces[2]) else { return day }
return "\(rawDay)"
}
private static func shortModelName(_ name: String) -> String {
let trimmed = name.trimmingCharacters(in: .whitespacesAndNewlines)
guard trimmed.count > 26 else { return trimmed }
return String(trimmed.prefix(25)) + "…"
}
private static func topCostModel(from entries: [CostUsageDailyReport.Entry]) -> String? {
var scores: [String: (cost: Double, tokens: Int)] = [:]
for entry in entries {
for model in entry.modelBreakdowns ?? [] {
var score = scores[model.modelName] ?? (0, 0)
score.cost += model.costUSD ?? 0
score.tokens += model.totalTokens ?? 0
scores[model.modelName] = score
}
}
return scores.max {
if $0.value.cost == $1.value.cost { return $0.value.tokens < $1.value.tokens }
return $0.value.cost < $1.value.cost
}?.key
}
}
struct InlineUsageDashboardContent: View {
private let model: InlineUsageDashboardModel
@Environment(\.menuItemHighlighted) private var isHighlighted
init(model: InlineUsageDashboardModel) {
self.model = model
}
var body: some View {
VStack(alignment: .leading, spacing: 10) {
self.kpis
if !self.model.points.isEmpty {
MiniUsageBars(model: self.model)
.frame(height: 58)
.accessibilityLabel(self.model.accessibilityLabel)
}
self.detailLines
}
.frame(maxWidth: .infinity, alignment: .leading)
}
private var kpis: some View {
LazyVGrid(
columns: [
GridItem(.flexible(minimum: 118), alignment: .leading),
GridItem(.flexible(minimum: 100), alignment: .leading),
],
alignment: .leading,
spacing: 6)
{
ForEach(Array(self.model.kpis.enumerated()), id: \.offset) { _, kpi in
KPIBlock(title: kpi.title, value: kpi.value, emphasis: kpi.emphasis)
}
}
}
private var detailLines: some View {
VStack(alignment: .leading, spacing: 3) {
ForEach(Array(self.model.detailLines.enumerated()), id: \.offset) { _, line in
Text(line)
.font(.caption)
.foregroundStyle(MenuHighlightStyle.secondary(self.isHighlighted))
.lineLimit(1)
}
}
}
private struct KPIBlock: View {
let title: String
let value: String
let emphasis: Bool
@Environment(\.menuItemHighlighted) private var isHighlighted
var body: some View {
VStack(alignment: .leading, spacing: 1) {
Text(self.title)
.font(.caption2)
.foregroundStyle(MenuHighlightStyle.secondary(self.isHighlighted))
.lineLimit(1)
Text(self.value)
.font(self.emphasis ? .headline : .subheadline)
.fontWeight(.semibold)
.foregroundStyle(MenuHighlightStyle.primary(self.isHighlighted))
.lineLimit(1)
.minimumScaleFactor(0.72)
}
.frame(maxWidth: .infinity, alignment: .leading)
}
}
private struct MiniUsageBars: View {
let model: InlineUsageDashboardModel
@Environment(\.menuItemHighlighted) private var isHighlighted
var body: some View {
let scale = UsageChartScale(values: self.model.points.map(\.value))
VStack(alignment: .trailing, spacing: 2) {
if let currencyCode = self.model.currencyCode, scale.maximum > 0 {
Text(UsageFormatter.compactCurrencyString(scale.maximum, currencyCode: currencyCode))
.font(.caption2)
.foregroundStyle(MenuHighlightStyle.secondary(self.isHighlighted))
.monospacedDigit()
.lineLimit(1)
.allowsTightening(true)
}
GeometryReader { geometry in
HStack(alignment: .bottom, spacing: 2) {
ForEach(self.model.points) { point in
RoundedRectangle(cornerRadius: 1.5, style: .continuous)
.fill(self.fill(for: point, scale: scale))
.frame(maxWidth: .infinity)
.frame(height: self.height(for: point, scale: scale, available: geometry.size.height))
.accessibilityLabel(point.accessibilityValue)
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)
.overlay(alignment: .bottomLeading) {
Rectangle()
.fill(MenuHighlightStyle.secondary(self.isHighlighted).opacity(0.22))
.frame(height: 1)
}
}
}
}
private func height(
for point: InlineUsageDashboardModel.Point,
scale: UsageChartScale,
available: CGFloat) -> CGFloat
{
let ratio = scale.fraction(for: point.value)
guard ratio > 0 else { return 1 }
return max(3, CGFloat(ratio) * available)
}
private func fill(for point: InlineUsageDashboardModel.Point, scale: UsageChartScale) -> Color {
let ratio = max(0.18, scale.fraction(for: point.value))
if self.isHighlighted {
return Color.white.opacity(0.55 + ratio * 0.35)
}
return self.baseColor.opacity(0.42 + ratio * 0.58)
}
private var baseColor: Color {
if let barColor = self.model.barColor {
return barColor
}
switch self.model.valueStyle {
case .currencyUSD, .currency:
return Color(red: 0.81, green: 0.56, blue: 0.24)
case .tokens:
return Color(red: 0.48, green: 0.41, blue: 0.86)
case .points:
return Color(red: 0.16, green: 0.62, blue: 0.36)
}
}
}
}