Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
- Packaging: skip slow widget App Intents metadata during dev restarts and preserve the previous app bundle if required metadata generation times out.
- Claude: keep Team and Personal Max plan-utilization history separate when the same email appears on multiple Claude accounts (#213).
- Claude: keep the last successful usage card visible across transient probe timeouts while still clearing stale data after Claude auth changes.
- Claude: label Extra usage denominators as the monthly cap so recharge balances are not confused with the maximum spend limit (#975).
- Claude: wait for the CLI usage panel to finish rendering after the Current session label so slow Claude Code builds do not produce false "Missing Current session" errors (#959).
- Claude: label five-hour session pace as "Projected empty" so it is not confused with the reset countdown (#960).
- Claude: show Enterprise spend-limit usage in automatic menu bar metrics and expose the Extra usage metric picker when spend data is available (#964).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -931,7 +931,7 @@ extension ClaudeUsageFetcher {
used: normalized.used,
limit: normalized.limit,
currencyCode: code,
period: isSpendLimit ? "Spend limit" : "Monthly",
period: isSpendLimit ? "Spend limit" : "Monthly cap",
resetsAt: nil,
updatedAt: Date())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -957,7 +957,7 @@ private enum ClaudeWebExtraUsageCost {
used: usedAmount,
limit: limitAmount,
currencyCode: currencyCode,
period: "Monthly",
period: "Monthly cap",
resetsAt: nil,
updatedAt: Date())
}
Expand Down
2 changes: 2 additions & 0 deletions Tests/CodexBarTests/ClaudeOAuthTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ struct ClaudeOAuthTests {
#expect(snap.providerCost?.currencyCode == "USD")
#expect(snap.providerCost?.limit == 20.5)
#expect(snap.providerCost?.used == 3.25)
#expect(snap.providerCost?.period == "Monthly cap")
}

@Test
Expand All @@ -195,6 +196,7 @@ struct ClaudeOAuthTests {
#expect(snap.providerCost?.currencyCode == "USD")
#expect(snap.providerCost?.limit == 20)
#expect(snap.providerCost?.used == 5.2)
#expect(snap.providerCost?.period == "Monthly cap")
}

@Test
Expand Down
2 changes: 1 addition & 1 deletion Tests/CodexBarTests/ClaudeUsageTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,7 @@ struct ClaudeUsageTests {
#expect(cost?.currencyCode == "EUR")
#expect(cost?.limit == 20)
#expect(cost?.used == 0)
#expect(cost?.period == "Monthly")
#expect(cost?.period == "Monthly cap")
}

@Test
Expand Down
2 changes: 1 addition & 1 deletion Tests/CodexBarTests/ClaudeWebEnterpriseUsageTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ struct ClaudeWebEnterpriseUsageTests {
#expect(parsed.extraUsageCost?.used == 41.32)
#expect(parsed.extraUsageCost?.limit == 1000)
#expect(parsed.extraUsageCost?.currencyCode == "USD")
#expect(parsed.extraUsageCost?.period == "Monthly")
#expect(parsed.extraUsageCost?.period == "Monthly cap")
}
}
42 changes: 42 additions & 0 deletions Tests/CodexBarTests/MenuCardModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,48 @@ struct MiniMaxMenuCardModelTests {
}
}

struct ClaudeMenuCardCostTests {
@Test
func `claude extra usage labels monthly denominator as cap`() throws {
let now = Date()
let metadata = try #require(ProviderDefaults.metadata[.claude])
let snapshot = UsageSnapshot(
primary: RateWindow(usedPercent: 0, windowMinutes: nil, resetsAt: nil, resetDescription: nil),
secondary: nil,
tertiary: nil,
providerCost: ProviderCostSnapshot(
used: 5,
limit: 20,
currencyCode: "USD",
period: "Monthly cap",
updatedAt: now),
updatedAt: now,
identity: nil)

let model = UsageMenuCardView.Model.make(.init(
provider: .claude,
metadata: metadata,
snapshot: snapshot,
credits: nil,
creditsError: nil,
dashboard: nil,
dashboardError: nil,
tokenSnapshot: nil,
tokenError: nil,
account: AccountInfo(email: nil, plan: nil),
isRefreshing: false,
lastError: nil,
usageBarsShowUsed: false,
resetTimeDisplayStyle: .countdown,
tokenCostUsageEnabled: false,
showOptionalCreditsAndExtraUsage: true,
hidePersonalInfo: false,
now: now))

#expect(model.providerCost?.spendLine == "Monthly cap: $5.00 / $20.00")
}
}

struct MenuCardModelTests {
@Test
func `builds metrics using remaining percent`() throws {
Expand Down