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 @@ -4,6 +4,7 @@

### Added
- Agent Sessions: list and focus live local or SSH-discovered Codex and Claude Code sessions from the menu and CLI.
- Kimi K2: add a Usage Dashboard shortcut to the human-facing legacy credits page. Thanks @joeVenner!
- Codex: add a provider option to hide Spark quota rows without hiding credits or other extra usage (#2013). Thanks @intellectronica!
- Wayfinder: add opt-in local gateway health, routing, savings, and latency usage with configurable loopback URL support. Thanks @tcballard!
- Claude CLI: surface model-scoped weekly limits alongside all-model usage without duplicating matching web limits. Thanks @janpollak!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public enum KimiK2ProviderDescriptor {
isPrimaryProvider: false,
usesAccountFallback: false,
browserCookieOrder: nil,
dashboardURL: nil,
dashboardURL: "https://kimrel.com/my-credits",
statusPageURL: nil),
branding: ProviderBranding(
iconStyle: .kimi,
Expand Down
36 changes: 36 additions & 0 deletions Tests/CodexBarTests/MenuDescriptorKimiK2Tests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import CodexBarCore
import Testing
@testable import CodexBar

@MainActor
@Suite(.serialized)
struct MenuDescriptorKimiK2Tests {
@Test
func `kimi K2 menu exposes the usage dashboard action`() {
let settings = testSettingsStore(suiteName: "MenuDescriptorKimiK2Tests-dashboard")
settings.statusChecksEnabled = false
settings.refreshFrequency = .manual
settings.mergeIcons = false
let store = UsageStore(
fetcher: UsageFetcher(environment: [:]),
browserDetection: BrowserDetection(cacheTTL: 0),
settings: settings)

let descriptor = MenuDescriptor.build(
provider: .kimik2,
store: store,
settings: settings,
account: AccountInfo(email: nil, plan: nil),
updateReady: false)
let actions = descriptor.sections
.flatMap(\.entries)
.compactMap { entry -> (String, MenuDescriptor.MenuAction)? in
guard case let .action(title, action) = entry else { return nil }
return (title, action)
}

#expect(actions.contains { title, action in
title == "Usage Dashboard" && action == .dashboard
})
}
}
6 changes: 4 additions & 2 deletions Tests/CodexBarTests/ProviderMetadataStatusLinkTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ struct ProviderMetadataStatusLinkTests {
}

@Test
func `kimi K2 metadata does not present legacy endpoint as official`() throws {
func `kimi K2 metadata identifies the unofficial provider and its credits dashboard`() throws {
let meta = try #require(ProviderDefaults.metadata[.kimik2])

#expect(meta.displayName == "Kimi K2 (unofficial)")
#expect(meta.toggleTitle == "Show unofficial Kimi K2 usage")
#expect(meta.dashboardURL == nil)
// The dashboard URL must be a human-facing browser page, not the bearer-token
// credits API endpoint (which returns HTTP 401 to an unauthenticated browser).
#expect(meta.dashboardURL == "https://kimrel.com/my-credits")
}
}
1 change: 1 addition & 0 deletions docs/kimi-k2.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ key for that legacy endpoint to pull your remaining balance and usage.

- Credits are the billing unit; CodexBar computes used percent as `consumed / (consumed + remaining)`.
- There is no explicit reset timestamp in the API, so the snapshot has no reset time.
- The menu's Usage Dashboard action opens the legacy service's human-facing credits page at `https://kimrel.com/my-credits`.
- Environment variables take precedence over config.

## Key files
Expand Down