Skip to content
Open
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
4 changes: 3 additions & 1 deletion Sources/CodexBarCore/Providers/Zai/ZaiUsageStats.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ extension ZaiLimitEntry {
if let computed = self.computedUsedPercent {
return computed
}
return self.percentage
// The raw API percentage can fall outside 0...100 (z.ai omits/misreports quota fields);
// clamp it like computedUsedPercent and every sibling provider instead of surfacing it raw.
return min(100, max(0, self.percentage))
}

public var windowMinutes: Int? {
Expand Down
52 changes: 52 additions & 0 deletions TestsLinux/ZaiUsedPercentLinuxTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#if os(Linux)
import CodexBarCore
import Foundation
import Testing

struct ZaiUsedPercentLinuxTests {
/// usage == nil forces computedUsedPercent to return nil, exercising the raw-percentage fallback.
private func fallbackUsedPercent(_ percentage: Double) -> Double {
ZaiLimitEntry(
type: .tokensLimit,
unit: .hours,
number: 5,
usage: nil,
currentValue: nil,
remaining: nil,
percentage: percentage,
usageDetails: [],
nextResetTime: nil).usedPercent
}

@Test
func `raw percentage fallback clamps above 100`() {
#expect(self.fallbackUsedPercent(150) == 100)
}

@Test
func `raw percentage fallback clamps below 0`() {
#expect(self.fallbackUsedPercent(-5) == 0)
}

@Test
func `raw percentage fallback preserves an in-range value`() {
#expect(self.fallbackUsedPercent(42) == 42)
}

@Test
func `computed path takes precedence and ignores the raw percentage`() {
// usage(limit)=100, currentValue(used)=25 -> computed 25%, so the raw 999 must not leak.
let entry = ZaiLimitEntry(
type: .tokensLimit,
unit: .hours,
number: 5,
usage: 100,
currentValue: 25,
remaining: nil,
percentage: 999,
usageDetails: [],
nextResetTime: nil)
#expect(entry.usedPercent == 25)
}
}
#endif