Files
claudechecker/ClaudeChecker/Models.swift
T

130 lines
3.8 KiB
Swift

import Foundation
// MARK: - Models
struct AgentLimit: Identifiable {
let id = UUID()
var agent: AgentType
var window: WindowType
var usedPercent: Double
var timeRemaining: String
var resetDate: Date
var projectedHit: ProjectedHit
var burnRate: Double
var burnHistory: [Double]
var isLive: Bool
var usageLabel: String {
switch usedPercent {
case ..<30: return "low"
case 30..<70: return "med"
default: return "high"
}
}
}
enum AgentType: String {
case claude = "Claude"
}
enum WindowType: String {
case fiveHour = "5h"
case sevenDay = "7d"
var label: String { rawValue }
}
enum ProjectedHit {
case afterReset
case at(Date)
var display: String {
switch self {
case .afterReset: return "after reset"
case .at(let date):
let fmt = DateFormatter()
let cal = Calendar.current
if cal.isDateInToday(date) { fmt.dateFormat = "'today' h:mm a" }
else if cal.isDateInTomorrow(date) { fmt.dateFormat = "'tmw' h:mm a" }
else { fmt.dateFormat = "MMM d, h:mm a" }
return fmt.string(from: date)
}
}
}
// MARK: - API Response — /api/organizations/{id}/usage
struct UsageResponse: Decodable {
let fiveHour: UsageWindow?
let sevenDay: UsageWindow?
let extraUsage: ExtraUsage?
enum CodingKeys: String, CodingKey {
case fiveHour = "five_hour"
case sevenDay = "seven_day"
case extraUsage = "extra_usage"
}
init(from decoder: Decoder) throws {
let c = try decoder.container(keyedBy: CodingKeys.self)
fiveHour = try c.decodeIfPresent(UsageWindow.self, forKey: .fiveHour)
sevenDay = try c.decodeIfPresent(UsageWindow.self, forKey: .sevenDay)
extraUsage = try c.decodeIfPresent(ExtraUsage.self, forKey: .extraUsage)
}
}
struct UsageWindow: Codable {
let utilization: Double
let resetsAt: String?
enum CodingKeys: String, CodingKey {
case utilization
case resetsAt = "resets_at"
}
}
struct ExtraUsage: Codable {
let isEnabled: Bool
let currency: String?
enum CodingKeys: String, CodingKey {
case isEnabled = "is_enabled"
case currency
}
init(from decoder: Decoder) throws {
let c = try decoder.container(keyedBy: CodingKeys.self)
isEnabled = (try? c.decodeIfPresent(Bool.self, forKey: .isEnabled)) ?? false
currency = try? c.decodeIfPresent(String.self, forKey: .currency)
}
}
struct PrepaidCredits: Decodable {
let amount: Double?
let currency: String?
enum CodingKeys: String, CodingKey { case amount, currency }
init(from decoder: Decoder) throws {
let c = try decoder.container(keyedBy: CodingKeys.self)
amount = try? c.decodeIfPresent(Double.self, forKey: .amount)
currency = try? c.decodeIfPresent(String.self, forKey: .currency)
}
}
struct OverageSpendLimit: Decodable {
let isEnabled: Bool
let usedCredits: Double?
let monthlyCreditLimit: Double?
let currency: String?
enum CodingKeys: String, CodingKey {
case isEnabled = "is_enabled"
case usedCredits = "used_credits"
case monthlyCreditLimit = "monthly_credit_limit"
case currency
}
init(from decoder: Decoder) throws {
let c = try decoder.container(keyedBy: CodingKeys.self)
isEnabled = (try? c.decodeIfPresent(Bool.self, forKey: .isEnabled)) ?? false
usedCredits = try? c.decodeIfPresent(Double.self, forKey: .usedCredits)
monthlyCreditLimit = try? c.decodeIfPresent(Double.self, forKey: .monthlyCreditLimit)
currency = try? c.decodeIfPresent(String.self, forKey: .currency)
}
}
// (Bootstrap models removed — org ID is configured directly)