Peter Steinbergerfix: cache provider cookies680ce0910 months agoHistory
131 lines · 5.1 KB · Swift
RawDownload
import CodexBarMacroSupportimport Foundation @ProviderDescriptorRegistration@ProviderDescriptorDefinitionpublic enum OpenCodeProviderDescriptor {    static func makeDescriptor() -> ProviderDescriptor {        ProviderDescriptor(            id: .opencode,            metadata: ProviderMetadata(                id: .opencode,                displayName: "OpenCode",                sessionLabel: "5-hour",                weeklyLabel: "Weekly",                opusLabel: nil,                supportsOpus: false,                supportsCredits: false,                creditsHint: "",                toggleTitle: "Show OpenCode usage",                cliName: "opencode",                defaultEnabled: false,                isPrimaryProvider: false,                usesAccountFallback: false,                browserCookieOrder: ProviderBrowserCookieDefaults.defaultImportOrder,                dashboardURL: "https://opencode.ai",                statusPageURL: nil),            branding: ProviderBranding(                iconStyle: .opencode,                iconResourceName: "ProviderIcon-opencode",                color: ProviderColor(red: 59 / 255, green: 130 / 255, blue: 246 / 255)),            tokenCost: ProviderTokenCostConfig(                supportsTokenCost: false,                noDataMessage: { "OpenCode cost summary is not supported." }),            fetchPlan: ProviderFetchPlan(                sourceModes: [.auto, .web],                pipeline: ProviderFetchPipeline(resolveStrategies: { _ in [OpenCodeUsageFetchStrategy()] })),            cli: ProviderCLIConfig(                name: "opencode",                versionDetector: nil))    }} struct OpenCodeUsageFetchStrategy: ProviderFetchStrategy {    let id: String = "opencode.web"    let kind: ProviderFetchKind = .web     func isAvailable(_ context: ProviderFetchContext) async -> Bool {        guard context.settings?.opencode?.cookieSource != .off else { return false }        return true    }     func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult {        let workspaceOverride = context.settings?.opencode?.workspaceID            ?? context.env["CODEXBAR_OPENCODE_WORKSPACE_ID"]        let cookieSource = context.settings?.opencode?.cookieSource ?? .auto        do {            let cookieHeader = try Self.resolveCookieHeader(context: context, allowCached: true)            let snapshot = try await OpenCodeUsageFetcher.fetchUsage(                cookieHeader: cookieHeader,                timeout: context.webTimeout,                workspaceIDOverride: workspaceOverride)            return self.makeResult(                usage: snapshot.toUsageSnapshot(),                sourceLabel: "web")        } catch OpenCodeUsageError.invalidCredentials where cookieSource != .manual {            #if os(macOS)            CookieHeaderCache.clear(provider: .opencode)            let cookieHeader = try Self.resolveCookieHeader(context: context, allowCached: false)            let snapshot = try await OpenCodeUsageFetcher.fetchUsage(                cookieHeader: cookieHeader,                timeout: context.webTimeout,                workspaceIDOverride: workspaceOverride)            return self.makeResult(                usage: snapshot.toUsageSnapshot(),                sourceLabel: "web")            #else            throw OpenCodeUsageError.invalidCredentials            #endif        }    }     func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool {        false    }     private static func resolveCookieHeader(context: ProviderFetchContext, allowCached: Bool) throws -> String {        if let settings = context.settings?.opencode, settings.cookieSource == .manual {            if let header = CookieHeaderNormalizer.normalize(settings.manualCookieHeader) {                let pairs = CookieHeaderNormalizer.pairs(from: header)                let hasAuthCookie = pairs.contains { pair in                    pair.name == "auth" || pair.name == "__Host-auth"                }                if hasAuthCookie {                    return header                }            }            throw OpenCodeSettingsError.invalidCookie        }         #if os(macOS)        if allowCached,           let cached = CookieHeaderCache.load(provider: .opencode),           !cached.cookieHeader.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty        {            return cached.cookieHeader        }        let session = try OpenCodeCookieImporter.importSession(browserDetection: context.browserDetection)        CookieHeaderCache.store(            provider: .opencode,            cookieHeader: session.cookieHeader,            sourceLabel: session.sourceLabel)        return session.cookieHeader        #else        throw OpenCodeSettingsError.missingCookie        #endif    }} enum OpenCodeSettingsError: LocalizedError {    case missingCookie    case invalidCookie     var errorDescription: String? {        switch self {        case .missingCookie:            "No OpenCode session cookies found in browsers."        case .invalidCookie:            "OpenCode cookie header is invalid."        }    }}