75 lines · 2.9 KB · Swift
RawDownload
import Foundation#if canImport(FoundationNetworking)import FoundationNetworking#endif public struct CopilotUsageFetcher: Sendable {    private let token: String     public init(token: String) {        self.token = token    }     public func fetch() async throws -> UsageSnapshot {        guard let url = URL(string: "https://api.github.com/copilot_internal/user") else {            throw URLError(.badURL)        }         var request = URLRequest(url: url)        // Use the GitHub OAuth token directly, not the Copilot token.        request.setValue("token \(self.token)", forHTTPHeaderField: "Authorization")        self.addCommonHeaders(to: &request)         let (data, response) = try await URLSession.shared.data(for: request)         guard let httpResponse = response as? HTTPURLResponse else {            throw URLError(.badServerResponse)        }         if httpResponse.statusCode == 401 || httpResponse.statusCode == 403 {            throw URLError(.userAuthenticationRequired)        }         guard httpResponse.statusCode == 200 else {            throw URLError(.badServerResponse)        }         let usage = try JSONDecoder().decode(CopilotUsageResponse.self, from: data)         let primary = self.makeRateWindow(from: usage.quotaSnapshots.premiumInteractions)        let secondary = self.makeRateWindow(from: usage.quotaSnapshots.chat)         let identity = ProviderIdentitySnapshot(            providerID: .copilot,            accountEmail: nil,            accountOrganization: nil,            loginMethod: usage.copilotPlan.capitalized)        return UsageSnapshot(            primary: primary ?? .init(usedPercent: 0, windowMinutes: nil, resetsAt: nil, resetDescription: nil),            secondary: secondary,            tertiary: nil,            providerCost: nil,            updatedAt: Date(),            identity: identity)    }     private func addCommonHeaders(to request: inout URLRequest) {        request.setValue("application/json", forHTTPHeaderField: "Accept")        request.setValue("vscode/1.96.2", forHTTPHeaderField: "Editor-Version")        request.setValue("copilot-chat/0.26.7", forHTTPHeaderField: "Editor-Plugin-Version")        request.setValue("GitHubCopilotChat/0.26.7", forHTTPHeaderField: "User-Agent")        request.setValue("2025-04-01", forHTTPHeaderField: "X-Github-Api-Version")    }     private func makeRateWindow(from snapshot: CopilotUsageResponse.QuotaSnapshot?) -> RateWindow? {        guard let snapshot else { return nil }        // percent_remaining is 0-100 based on the JSON example in the web app source        let usedPercent = max(0, 100 - snapshot.percentRemaining)         return RateWindow(            usedPercent: usedPercent,            windowMinutes: nil, // Not provided            resetsAt: nil, // Not provided per-quota in the simplified snapshot            resetDescription: nil)    }}