import Foundation // swiftformat:disable:next redundantSendablestruct AntigravityQuotaSummary: Sendable, Equatable { let description: String? let groups: [AntigravityQuotaSummaryGroup]} // swiftformat:disable:next redundantSendablestruct AntigravityQuotaSummaryGroup: Sendable, Equatable { let displayName: String let description: String? let buckets: [AntigravityQuotaSummaryBucket]} // swiftformat:disable:next redundantSendablestruct AntigravityQuotaSummaryBucket: Sendable, Equatable { let bucketId: String let displayName: String let remainingFraction: Double? let resetTime: Date? let resetDescription: String? let disabled: Bool init( bucketId: String, displayName: String, remainingFraction: Double?, resetTime: Date? = nil, resetDescription: String?, disabled: Bool) { self.bucketId = bucketId self.displayName = displayName self.remainingFraction = remainingFraction self.resetTime = resetTime self.resetDescription = resetDescription self.disabled = disabled }} extension AntigravityStatusProbe { static func parseQuotaSummaryResponse(_ data: Data) throws -> AntigravityStatusSnapshot { let decoder = JSONDecoder() let response = try decoder.decode(QuotaSummaryResponse.self, from: data) if let invalid = Self.invalidCode(response.code) { throw AntigravityStatusProbeError.apiError(invalid) } let payload = response.response ?? response.summary ?? response.rootPayload guard let payload else { throw AntigravityStatusProbeError.parseFailed("Missing quota summary") } let groups = payload.groups.compactMap(self.quotaSummaryGroup(from:)) guard !groups.isEmpty else { throw AntigravityStatusProbeError.parseFailed("Missing quota groups") } return AntigravityStatusSnapshot( quotaSummary: AntigravityQuotaSummary( description: payload.description, groups: groups), accountEmail: nil, accountPlan: nil, source: .local) } private static func quotaSummaryGroup(from payload: QuotaSummaryGroupPayload) -> AntigravityQuotaSummaryGroup? { let displayName = payload.displayName?.trimmingCharacters(in: .whitespacesAndNewlines) let buckets = (payload.buckets ?? []).compactMap(self.quotaSummaryBucket(from:)) guard !buckets.isEmpty else { return nil } return AntigravityQuotaSummaryGroup( displayName: self.nonEmpty(displayName) ?? "Quota", description: payload.description, buckets: buckets) } private static func quotaSummaryBucket(from payload: QuotaSummaryBucketPayload) -> AntigravityQuotaSummaryBucket? { let bucketId = payload.bucketId?.trimmingCharacters(in: .whitespacesAndNewlines) let displayName = payload.displayName?.trimmingCharacters(in: .whitespacesAndNewlines) guard let resolvedBucketId = bucketId, !resolvedBucketId.isEmpty else { return nil } let resetTime = payload.resetTime.flatMap { Self.parseDate($0) } return AntigravityQuotaSummaryBucket( bucketId: resolvedBucketId, displayName: self.nonEmpty(displayName) ?? resolvedBucketId, remainingFraction: payload.resolvedRemainingFraction, resetTime: resetTime, resetDescription: payload.description, disabled: payload.disabled ?? false) } private static func nonEmpty(_ value: String?) -> String? { guard let value, !value.isEmpty else { return nil } return value }} private struct QuotaSummaryResponse: Decodable { let code: CodeValue? let message: String? let response: QuotaSummaryPayload? let summary: QuotaSummaryPayload? let description: String? let groups: [QuotaSummaryGroupPayload]? var rootPayload: QuotaSummaryPayload? { guard let groups else { return nil } return QuotaSummaryPayload(description: self.description, groups: groups) }} private struct QuotaSummaryPayload: Decodable { let description: String? let groups: [QuotaSummaryGroupPayload] init(description: String?, groups: [QuotaSummaryGroupPayload]) { self.description = description self.groups = groups } private enum CodingKeys: String, CodingKey { case description case groups } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) self.description = try container.decodeIfPresent(String.self, forKey: .description) self.groups = try container.decodeIfPresent([QuotaSummaryGroupPayload].self, forKey: .groups) ?? [] }} private struct QuotaSummaryGroupPayload: Decodable { let displayName: String? let description: String? let buckets: [QuotaSummaryBucketPayload]?} private struct QuotaSummaryBucketPayload: Decodable { let bucketId: String? let displayName: String? let description: String? let disabled: Bool? let remainingFraction: Double? let remaining: QuotaSummaryRemainingPayload? let resetTime: String? var resolvedRemainingFraction: Double? { self.remainingFraction ?? self.remaining?.remainingFraction }} private struct QuotaSummaryRemainingPayload: Decodable { let remainingFraction: Double? private enum CodingKeys: String, CodingKey { case remainingFraction case oneofCase = "case" case value } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) if let remainingFraction = try container.decodeIfPresent(Double.self, forKey: .remainingFraction) { self.remainingFraction = remainingFraction return } let oneofCase = try container.decodeIfPresent(String.self, forKey: .oneofCase) if oneofCase == "remainingFraction" { self.remainingFraction = try container.decodeIfPresent(Double.self, forKey: .value) } else { self.remainingFraction = nil } }}
import Foundation
// swiftformat:disable:next redundantSendable
struct AntigravityQuotaSummary: Sendable, Equatable {
let description: String?
let groups: [AntigravityQuotaSummaryGroup]
}
// swiftformat:disable:next redundantSendable
struct AntigravityQuotaSummaryGroup: Sendable, Equatable {
let displayName: String
let description: String?
let buckets: [AntigravityQuotaSummaryBucket]
}
// swiftformat:disable:next redundantSendable
struct AntigravityQuotaSummaryBucket: Sendable, Equatable {
let bucketId: String
let displayName: String
let remainingFraction: Double?
let resetTime: Date?
let resetDescription: String?
let disabled: Bool
init(
bucketId: String,
displayName: String,
remainingFraction: Double?,
resetTime: Date? = nil,
resetDescription: String?,
disabled: Bool)
{
self.bucketId = bucketId
self.displayName = displayName
self.remainingFraction = remainingFraction
self.resetTime = resetTime
self.resetDescription = resetDescription
self.disabled = disabled
}
}
extension AntigravityStatusProbe {
static func parseQuotaSummaryResponse(_ data: Data) throws -> AntigravityStatusSnapshot {
let decoder = JSONDecoder()
let response = try decoder.decode(QuotaSummaryResponse.self, from: data)
if let invalid = Self.invalidCode(response.code) {
throw AntigravityStatusProbeError.apiError(invalid)
}
let payload = response.response ?? response.summary ?? response.rootPayload
guard let payload else {
throw AntigravityStatusProbeError.parseFailed("Missing quota summary")
}
let groups = payload.groups.compactMap(self.quotaSummaryGroup(from:))
guard !groups.isEmpty else {
throw AntigravityStatusProbeError.parseFailed("Missing quota groups")
}
return AntigravityStatusSnapshot(
quotaSummary: AntigravityQuotaSummary(
description: payload.description,
groups: groups),
accountEmail: nil,
accountPlan: nil,
source: .local)
}
private static func quotaSummaryGroup(from payload: QuotaSummaryGroupPayload) -> AntigravityQuotaSummaryGroup? {
let displayName = payload.displayName?.trimmingCharacters(in: .whitespacesAndNewlines)
let buckets = (payload.buckets ?? []).compactMap(self.quotaSummaryBucket(from:))
guard !buckets.isEmpty else { return nil }
return AntigravityQuotaSummaryGroup(
displayName: self.nonEmpty(displayName) ?? "Quota",
description: payload.description,
buckets: buckets)
}
private static func quotaSummaryBucket(from payload: QuotaSummaryBucketPayload) -> AntigravityQuotaSummaryBucket? {
let bucketId = payload.bucketId?.trimmingCharacters(in: .whitespacesAndNewlines)
let displayName = payload.displayName?.trimmingCharacters(in: .whitespacesAndNewlines)
guard let resolvedBucketId = bucketId, !resolvedBucketId.isEmpty else { return nil }
let resetTime = payload.resetTime.flatMap { Self.parseDate($0) }
return AntigravityQuotaSummaryBucket(
bucketId: resolvedBucketId,
displayName: self.nonEmpty(displayName) ?? resolvedBucketId,
remainingFraction: payload.resolvedRemainingFraction,
resetTime: resetTime,
resetDescription: payload.description,
disabled: payload.disabled ?? false)
}
private static func nonEmpty(_ value: String?) -> String? {
guard let value, !value.isEmpty else { return nil }
return value
}
}
private struct QuotaSummaryResponse: Decodable {
let code: CodeValue?
let message: String?
let response: QuotaSummaryPayload?
let summary: QuotaSummaryPayload?
let description: String?
let groups: [QuotaSummaryGroupPayload]?
var rootPayload: QuotaSummaryPayload? {
guard let groups else { return nil }
return QuotaSummaryPayload(description: self.description, groups: groups)
}
}
private struct QuotaSummaryPayload: Decodable {
let description: String?
let groups: [QuotaSummaryGroupPayload]
init(description: String?, groups: [QuotaSummaryGroupPayload]) {
self.description = description
self.groups = groups
}
private enum CodingKeys: String, CodingKey {
case description
case groups
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.description = try container.decodeIfPresent(String.self, forKey: .description)
self.groups = try container.decodeIfPresent([QuotaSummaryGroupPayload].self, forKey: .groups) ?? []
}
}
private struct QuotaSummaryGroupPayload: Decodable {
let displayName: String?
let description: String?
let buckets: [QuotaSummaryBucketPayload]?
}
private struct QuotaSummaryBucketPayload: Decodable {
let bucketId: String?
let displayName: String?
let description: String?
let disabled: Bool?
let remainingFraction: Double?
let remaining: QuotaSummaryRemainingPayload?
let resetTime: String?
var resolvedRemainingFraction: Double? {
self.remainingFraction ?? self.remaining?.remainingFraction
}
}
private struct QuotaSummaryRemainingPayload: Decodable {
let remainingFraction: Double?
private enum CodingKeys: String, CodingKey {
case remainingFraction
case oneofCase = "case"
case value
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
if let remainingFraction = try container.decodeIfPresent(Double.self, forKey: .remainingFraction) {
self.remainingFraction = remainingFraction
return
}
let oneofCase = try container.decodeIfPresent(String.self, forKey: .oneofCase)
if oneofCase == "remainingFraction" {
self.remainingFraction = try container.decodeIfPresent(Double.self, forKey: .value)
} else {
self.remainingFraction = nil
}
}
}