Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion Sources/CodexBar/MenuCardView+ModelHelpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,10 @@ extension UsageMenuCardView.Model {
} else {
L("Unavailable")
}
let cloudSpendDetail = Self.cursorCloudAgentSpendDetail(
provider: input.provider,
namedWindow: namedWindow,
snapshot: snapshot)
return Metric(
id: namedWindow.id,
title: namedWindow.title,
Expand All @@ -570,13 +574,28 @@ extension UsageMenuCardView.Model {
statusText: statusText,
resetText: usageKnown ? resetText : nil,
detailText: nil,
detailLeftText: usageKnown ? paceDetail?.leftLabel : nil,
detailLeftText: usageKnown ? (cloudSpendDetail ?? paceDetail?.leftLabel) : nil,
detailRightText: usageKnown ? paceDetail?.rightLabel : nil,
pacePercent: usageKnown ? paceDetail?.pacePercent : nil,
paceOnTop: paceDetail?.paceOnTop ?? true)
}
}

/// Currency detail for Cursor's Cloud agent attribution window (share of cycle spend).
private static func cursorCloudAgentSpendDetail(
provider: UsageProvider,
namedWindow: NamedRateWindow,
snapshot: UsageSnapshot) -> String?
{
guard provider == .cursor,
namedWindow.id == CursorCloudAgentUsage.windowID,
let cloud = snapshot.cursorCloudAgentUsage,
cloud.usedUSD > 0
else { return nil }
let spend = UsageFormatter.currencyString(cloud.usedUSD, currencyCode: "USD")
return String(format: L("%@ this cycle"), spend)
}

private static func isCodexSparkRateWindow(_ namedWindow: NamedRateWindow) -> Bool {
namedWindow.id == CodexAdditionalRateLimitMapper.sparkWindowID ||
namedWindow.id == CodexAdditionalRateLimitMapper.sparkWeeklyWindowID
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/ar.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,7 @@
"Latest billing day" = "آخر يوم فوترة";
"Latest billing day (%@)" = "آخر يوم فوترة (%@)";
"%@ left" = "%@ متبقٍ";
"%@ this cycle" = "%@ في هذه الدورة";
"Resets %@" = "إعادة التعيين %@";
"Resets in %@" = "إعادة التعيين في %@";
"Resets now" = "إعادة التعيين الآن";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/ca.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,7 @@
/* Noves traduccions */
"%@ is unavailable in the current environment." = "%@ no està disponible en l'entorn actual.";
"%@ left" = "Queden %@";
"%@ this cycle" = "%@ en aquest cicle";
"%@ · %@" = "%@ · %@";
"%@: %@ · %@ tokens" = "%@: %@ · %@ tokens";
"%@: %@" = "%@: %@";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/de.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,7 @@
"Latest billing day" = "Letzter Abrechnungstag";
"Latest billing day (%@)" = "Letzter Abrechnungstag (%@)";
"%@ left" = "%@ übrig";
"%@ this cycle" = "%@ in diesem Zyklus";
"Resets %@" = "Setzt %@ zurück";
"Resets in %@" = "Zurückgesetzt in %@";
"Resets now" = "Wird jetzt zurückgesetzt";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,7 @@
"Latest billing day" = "Latest billing day";
"Latest billing day (%@)" = "Latest billing day (%@)";
"%@ left" = "%@ left";
"%@ this cycle" = "%@ this cycle";
"Resets %@" = "Resets %@";
"Resets in %@" = "Resets in %@";
"Resets now" = "Resets now";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/es.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -1018,3 +1018,4 @@
"section_links" = "Enlaces";
"Show Codex Spark usage" = "Mostrar el uso de Codex Spark";
"Shows Codex Spark quota rows in the menu and provider preview. Requires optional credits and extra usage in Display settings." = "Muestra las filas de cuota de Codex Spark en el menú y en la vista previa del proveedor. Requiere activar «Mostrar créditos + uso adicional» en los ajustes de Pantalla.";
"%@ this cycle" = "%@ en este ciclo";
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/fa.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,7 @@
"Latest billing day" = "آخرین روز صورتحساب";
"Latest billing day (%@)" = "آخرین روز صورتحساب (%@)";
"%@ left" = "%@ باقی مانده";
"%@ this cycle" = "%@ در این دوره";
"Resets %@" = "ریست %@";
"Resets in %@" = "ریست ها در %@";
"Resets now" = "اکنون بازنشانی می شود";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/fr.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,7 @@
"Latest billing day" = "Dernier jour de facturation";
"Latest billing day (%@)" = "Dernier jour de facturation (%@)";
"%@ left" = "%@ restant";
"%@ this cycle" = "%@ pour ce cycle";
"Resets %@" = "Réinitialise %@";
"Resets in %@" = "Réinitialisé dans %@";
"Resets now" = "Réinitialise maintenant";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/gl.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,7 @@
"Open Status Page" = "Abrir a páxina de estado";
"%@ is unavailable in the current environment." = "%@ non está dispoñible no contorno actual.";
"%@ left" = "%@ restante";
"%@ this cycle" = "%@ neste ciclo";
"%@ · %@" = "%@ · %@";
"%@: %@" = "%@: %@";
"%@: %@ · %@ tokens" = "%@: %@ · %@ tokens";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/id.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,7 @@
"Latest billing day" = "Hari tagihan terbaru";
"Latest billing day (%@)" = "Hari tagihan terbaru (%@)";
"%@ left" = "%@ tersisa";
"%@ this cycle" = "%@ siklus ini";
"Resets %@" = "Reset %@";
"Resets in %@" = "Reset dalam %@";
"Resets now" = "Reset sekarang";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/it.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,7 @@
"Latest billing day" = "Ultimo giorno di fatturazione";
"Latest billing day (%@)" = "Ultimo giorno di fatturazione (%@)";
"%@ left" = "%@ rimasto";
"%@ this cycle" = "%@ in questo ciclo";
"Resets %@" = "Si resetta %@";
"Resets in %@" = "Si reimposta tra %@";
"Resets now" = "Si resetta ora";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/ja.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,7 @@
"Latest billing day" = "直近の請求日";
"Latest billing day (%@)" = "直近の請求日(%@)";
"%@ left" = "残り %@";
"%@ this cycle" = "このサイクル %@";
"Resets %@" = "%@ にリセット";
"Resets in %@" = "%@ 後にリセット";
"Resets now" = "まもなくリセット";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/ko.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,7 @@
"Latest billing day" = "최근 청구일";
"Latest billing day (%@)" = "최근 청구일(%@)";
"%@ left" = "%@ 남음";
"%@ this cycle" = "이번 주기 %@";
"Resets %@" = "%@에 재설정";
"Resets in %@" = "%@ 후 재설정";
"Resets now" = "지금 재설정";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/nl.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,7 @@
"Latest billing day" = "Laatste factuurdag";
"Latest billing day (%@)" = "Laatste factuurdag (%@)";
"%@ left" = "%@ over";
"%@ this cycle" = "%@ deze cyclus";
"Resets %@" = "Reset %@";
"Resets in %@" = "Resetten over %@";
"Resets now" = "Wordt nu gereset";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/pl.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,7 @@
"Latest billing day" = "Najnowszy dzień rozliczeniowy";
"Latest billing day (%@)" = "Najnowszy dzień rozliczeniowy (%@)";
"%@ left" = "%@ pozostało";
"%@ this cycle" = "%@ w tym cyklu";
"Resets %@" = "Reset %@";
"Resets in %@" = "Reset za %@";
"Resets now" = "Reset teraz";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/pt-BR.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,7 @@
"Latest billing day" = "Último dia de cobrança";
"Latest billing day (%@)" = "Último dia de cobrança (%@)";
"%@ left" = "%@ restante";
"%@ this cycle" = "%@ neste ciclo";
"Resets %@" = "Renova %@";
"Resets in %@" = "Renova em %@";
"Resets now" = "Renova agora";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/ru.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,7 @@
"Latest billing day" = "Последний день биллинга";
"Latest billing day (%@)" = "Последний день биллинга (%@)";
"%@ left" = "%@ осталось";
"%@ this cycle" = "%@ за этот цикл";
"Resets %@" = "Сброс %@";
"Resets in %@" = "Сбрасывается через %@";
"Resets now" = "Сбрасывается сейчас";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/sv.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,7 @@
"Latest billing day" = "Senaste faktureringsdag";
"Latest billing day (%@)" = "Senaste faktureringsdag (%@)";
"%@ left" = "%@ kvar";
"%@ this cycle" = "%@ den här cykeln";
"Resets %@" = "Återställs %@";
"Resets in %@" = "Återställs om %@";
"Resets now" = "Återställs nu";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/th.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,7 @@
"Latest billing day" = "วันเรียกเก็บเงินล่าสุด";
"Latest billing day (%@)" = "วันเรียกเก็บเงินล่าสุด (%@)";
"%@ left" = "เหลือ %@";
"%@ this cycle" = "%@ ในรอบนี้";
"Resets %@" = "รีเซ็ต %@";
"Resets in %@" = "รีเซ็ตใน %@";
"Resets now" = "รีเซ็ตเดี๋ยวนี้";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/tr.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,7 @@
"Latest billing day" = "Son faturalandırma günü";
"Latest billing day (%@)" = "Son faturalandırma günü (%@)";
"%@ left" = "%@ kaldı";
"%@ this cycle" = "bu dönemde %@";
"Resets %@" = "Sıfırlanma: %@";
"Resets in %@" = "%@ içinde sıfırlanır";
"Resets now" = "Şimdi sıfırlanır";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/uk.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,7 @@
"Latest billing day" = "Останній розрахунковий день";
"Latest billing day (%@)" = "Останній розрахунковий день (%@)";
"%@ left" = "Залишилося %@";
"%@ this cycle" = "%@ за цей цикл";
"Resets %@" = "Скидання %@";
"Resets in %@" = "Скидання через %@";
"Resets now" = "Скидає зараз";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/vi.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,7 @@
"Latest billing day" = "Ngày thanh toán muộn nhất";
"Latest billing day (%@)" = "Ngày thanh toán muộn nhất ( %@ )";
"%@ left" = "còn lại %@";
"%@ this cycle" = "%@ chu kỳ này";
"Resets %@" = "Đặt lại %@";
"Resets in %@" = "Đặt lại sau %@";
"Resets now" = "Đặt lại ngay";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,7 @@
"Latest billing day" = "最近结算日";
"Latest billing day (%@)" = "最近结算日(%@)";
"%@ left" = "%@ 剩余";
"%@ this cycle" = "本周期 %@";
"Resets %@" = "重置于 %@";
"Resets in %@" = "%@后重置";
"Resets now" = "立即重置";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,7 @@
"≈ %d%% run-out risk" = "約 %d%% 機率會用完";
"No available fetch strategy for %@." = "%@ 沒有可用的取得策略。";
"%@ left" = "剩餘 %@";
"%@ this cycle" = "本週期 %@";
"Manual cleanup: cache" = "手動清理:快取";
"This month" = "本月";
"Manual cleanup: archived sessions" = "手動清理:封存的工作階段";
Expand Down
48 changes: 48 additions & 0 deletions Sources/CodexBarCLI/CLIRenderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ enum CLIRenderer {
now: now,
lines: &lines)
self.appendTertiaryLines(snapshot: snapshot, labels: labels, context: context, now: now, lines: &lines)
self.appendExtraRateWindowLines(
provider: provider,
snapshot: snapshot,
context: context,
now: now,
lines: &lines)
self.appendMiMoBalanceLine(snapshot: snapshot, useColor: context.useColor, lines: &lines)
self.appendCrossModelUsageLines(snapshot: snapshot, useColor: context.useColor, lines: &lines)
self.appendClawRouterUsageLines(snapshot: snapshot, useColor: context.useColor, lines: &lines)
Expand Down Expand Up @@ -98,6 +104,12 @@ enum CLIRenderer {
now: now,
lines: &lines)
self.appendTertiaryLines(snapshot: snapshot, labels: labels, context: context, now: now, lines: &lines)
self.appendExtraRateWindowLines(
provider: provider,
snapshot: snapshot,
context: context,
now: now,
lines: &lines)
self.appendMiMoBalanceLine(snapshot: snapshot, useColor: context.useColor, lines: &lines)
self.appendCrossModelUsageLines(snapshot: snapshot, useColor: context.useColor, lines: &lines)
self.appendClawRouterUsageLines(snapshot: snapshot, useColor: context.useColor, lines: &lines)
Expand Down Expand Up @@ -429,6 +441,18 @@ enum CLIRenderer {
resetStyle: resetStyle,
now: now))
}
if provider == .cursor, let extraRateWindows = snapshot.extraRateWindows {
for named in extraRateWindows
where named.id == CursorCloudAgentUsage.windowID && named.usageKnown
{
metrics.append(self.makeCardMetric(
provider: provider,
label: named.title,
window: named.window,
resetStyle: resetStyle,
now: now))
}
}
return metrics
}

Expand Down Expand Up @@ -768,6 +792,30 @@ enum CLIRenderer {
}
}

private static func appendExtraRateWindowLines(
provider: UsageProvider,
snapshot: UsageSnapshot,
context: RenderContext,
now: Date,
lines: inout [String])
{
guard provider == .cursor, let extraRateWindows = snapshot.extraRateWindows else { return }
for named in extraRateWindows
where named.id == CursorCloudAgentUsage.windowID && named.usageKnown
{
lines.append(self.rateLine(title: named.title, window: named.window, useColor: context.useColor))
if let cloud = snapshot.cursorCloudAgentUsage,
cloud.usedUSD > 0
{
let spend = UsageFormatter.currencyString(cloud.usedUSD, currencyCode: "USD")
lines.append(self.subtleLine("\(spend) this cycle", useColor: context.useColor))
}
if let reset = self.resetLine(for: named.window, style: context.resetStyle, now: now) {
lines.append(self.subtleLine(reset, useColor: context.useColor))
}
}
}

private static func appendDeepgramLines(
snapshot: UsageSnapshot,
useColor: Bool,
Expand Down
28 changes: 28 additions & 0 deletions Sources/CodexBarCore/Providers/Cursor/CursorRequestUsage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,31 @@ public struct CursorRequestUsage: Codable, Sendable {
max(0, 100 - self.usedPercent)
}
}

/// Aggregated Cursor Cloud Agent spend for the current billing cycle.
///
/// Cloud Agents draw from the same included/API/on-demand pools as local usage. This value is
/// spend *attribution* (share of cycle chargeable spend), not a separate quota.
public struct CursorCloudAgentUsage: Codable, Sendable, Equatable {
public static let windowID = "cursor-cloud"
public static let windowTitle = "Cloud"

/// Cloud agent spend in USD for the billing cycle.
public let usedUSD: Double
/// Total chargeable spend in USD for the same cycle (local + cloud).
public let totalSpendUSD: Double
/// Number of chargeable cloud-agent events included in `usedUSD`.
public let eventCount: Int

public init(usedUSD: Double, totalSpendUSD: Double, eventCount: Int) {
self.usedUSD = usedUSD
self.totalSpendUSD = totalSpendUSD
self.eventCount = eventCount
}

/// Share of cycle spend attributed to cloud agents (0-100).
public var usedPercent: Double {
guard self.totalSpendUSD > 0 else { return 0 }
return max(0, min(100, (self.usedUSD / self.totalSpendUSD) * 100))
}
}
Loading