Skip to content

Add Grok (xAI) provider#570

Open
BryanTegomoh wants to merge 3 commits intosteipete:mainfrom
BryanTegomoh:feature/grok-provider
Open

Add Grok (xAI) provider#570
BryanTegomoh wants to merge 3 commits intosteipete:mainfrom
BryanTegomoh:feature/grok-provider

Conversation

@BryanTegomoh
Copy link

@BryanTegomoh BryanTegomoh commented Mar 19, 2026

Summary

  • Adds Grok/xAI as a new provider with a two-strategy fetch pipeline
  • Primary: xAI Management API (management-api.x.ai) for real billing data (spending limits, invoice preview, usage percentage)
  • Fallback: Regular API key status check (api.x.ai/v1/api-key) showing active/blocked state
  • Settings: API Key, Management Key (for billing endpoints), Team ID

Implementation

6 new files (~350 lines of new Swift):

  • GrokSettingsReader - env var: XAI_API_KEY (per official xAI docs), XAI_MANAGEMENT_API_KEY, XAI_TEAM_ID
  • GrokUsageFetcher - two fetch paths (billing + key status) with Decodable response models
  • GrokProviderDescriptor - descriptor with two-strategy pipeline (GrokManagementFetchStrategy primary, GrokAPIFetchStrategy fallback)
  • GrokProviderImplementation - settings UI (2 secure fields + team ID text field + console link)
  • GrokSettingsStore - config persistence (management key via cookieHeader, team ID via workspaceID)
  • ProviderIcon-grok.svg - X-shaped icon

10 modified files (~15 lines each):

  • Providers.swift - case grok in UsageProvider + IconStyle
  • ProviderTokenResolver.swift - grokToken() + grokResolution()
  • ProviderConfigEnvironment.swift - management key + team ID injection
  • LogCategories.swift, ProviderImplementationRegistry.swift, UsageStore.swift
  • CostUsageScanner.swift, TokenAccountCLI.swift - exhaustive switch cases
  • CodexBarWidgetProvider.swift, CodexBarWidgetViews.swift - widget stubs

xAI Management API

xAI exposes billing data via a Management API (https://management-api.x.ai/v1):

  • GET /v1/billing/teams/{team_id}/postpaid/spending-limits - usage cap
  • GET /v1/billing/teams/{team_id}/postpaid/invoice/preview - current usage amount
  • Requires a Management API Key (Console > Settings > Management Keys)

This gives real usage percentage bars rather than just key status.

Environment Variables

All env var names verified against official xAI documentation:

  • XAI_API_KEY - standard API key (official)
  • XAI_MANAGEMENT_API_KEY - management API key (per management API docs)
  • XAI_TEAM_ID - team identifier (defaults to "default")

Test plan

  • swift build --target CodexBarCore compiles clean
  • swift build --target CodexBarCLI compiles clean
  • Settings > Providers: "Grok" appears with toggle, API key, Management key, Team ID fields
  • With Management key + Team ID: usage bar shows billing data
  • With only API key: shows key active/blocked status (fallback)
  • No regressions on other providers

Two-strategy fetch pipeline:
- Primary: Management API billing data (spending limits + invoice preview)
- Fallback: Regular API key status check

Settings: API key, Management key (for billing), Team ID
Copilot AI review requested due to automatic review settings March 19, 2026 03:27
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8417b65f58

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +6 to +9
public enum GrokProviderDescriptor {
static func makeDescriptor() -> ProviderDescriptor {
ProviderDescriptor(
id: .grok,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0 Badge Add GrokProviderDescriptor to the registry

UsageProvider.allCases now includes .grok, but ProviderDescriptorRegistry.descriptorsByID in Sources/CodexBarCore/Providers/ProviderDescriptor.swift:55-78 still has no .grok entry. The bootstrap loop there preconditions on any missing provider, so the first descriptor lookup (for example app startup via ProviderRegistry.shared) crashes with Missing ProviderDescriptor for grok before the new provider can be used.

Useful? React with 👍 / 👎.

Comment on lines +35 to +39
public struct GrokSpendingLimitsResponse: Decodable, Sendable {
public let hardLimit: Double?
public let softLimit: Double?
public let monthlyBudget: Double?
public let currentSpend: Double?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Match xAI's actual Management API billing schema

xAI's Billing Management docs expose postpaid/spending-limits as a nested spendingLimits object and invoice/preview as coreInvoice/effectiveSpendingLimit fields in USD cents, not flat hard_limit/total_amount doubles. Decoding those 200 responses into GrokSpendingLimitsResponse/GrokInvoicePreviewResponse will therefore throw parseFailed, so a configuration that only has XAI_MANAGEMENT_KEY never yields a balance snapshot and either falls back to the less useful API-key status path or errors out entirely.

Useful? React with 👍 / 👎.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Grok/xAI usage provider to CodexBar, including a two-stage fetch pipeline (Management API billing as primary, API key status as fallback), along with supporting settings UI, config/env plumbing, and basic widget/UI integration.

Changes:

  • Introduces Grok provider core implementation (settings reader, usage fetcher, descriptor + fetch strategies).
  • Adds app-side settings persistence/UI for Grok (API key, Management key, Team ID) and provider icon/branding.
  • Wires Grok into shared enums/switches (providers list, token resolver, config env injection, CLI/widget stubs).

Reviewed changes

Copilot reviewed 15 out of 16 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
Sources/CodexBarWidget/CodexBarWidgetViews.swift Adds Grok display name and widget color mapping.
Sources/CodexBarWidget/CodexBarWidgetProvider.swift Marks Grok as not yet supported in widgets (returns nil).
Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner.swift Treats Grok as unsupported for cost usage scanning (empty report).
Sources/CodexBarCore/Providers/ProviderTokenResolver.swift Adds Grok token + resolution helpers.
Sources/CodexBarCore/Providers/Providers.swift Adds .grok to UsageProvider and IconStyle.
Sources/CodexBarCore/Providers/Grok/GrokUsageFetcher.swift Implements Management API billing fetch + API key status fetch with decoding/models.
Sources/CodexBarCore/Providers/Grok/GrokSettingsReader.swift Reads Grok/xAI-related env vars (API key, management key, team ID, URL overrides).
Sources/CodexBarCore/Providers/Grok/GrokProviderDescriptor.swift Registers Grok descriptor and two-strategy fetch pipeline.
Sources/CodexBarCore/Logging/LogCategories.swift Adds Grok usage logging category.
Sources/CodexBarCore/Config/ProviderConfigEnvironment.swift Injects Grok management key/team ID and API key into the environment.
Sources/CodexBarCLI/TokenAccountCLI.swift Updates switch exhaustiveness for Grok (no token account snapshot).
Sources/CodexBar/UsageStore.swift Adds Grok debug log message for token resolution.
Sources/CodexBar/Resources/ProviderIcon-grok.svg Adds Grok provider icon asset.
Sources/CodexBar/Providers/Shared/ProviderImplementationRegistry.swift Registers Grok settings implementation.
Sources/CodexBar/Providers/Grok/GrokSettingsStore.swift Persists Grok API key, management key, and team ID via ProviderConfig fields.
Sources/CodexBar/Providers/Grok/GrokProviderImplementation.swift Adds Grok provider settings UI (secure fields + team ID + console links).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +70 to +71
func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool {
true // Fall back to regular API key strategy
style: .link,
isVisible: nil,
perform: {
if let url = URL(string: "https://console.x.ai/team/default/management-keys") {
Comment on lines +4 to +8
public struct GrokSettingsReader: Sendable {
public static let apiKeyEnvironmentKeys = [
"XAI_API_KEY",
"GROK_API_KEY",
]
Comment on lines +16 to +17
if let teamID = config.workspaceID, !teamID.isEmpty {
env[GrokSettingsReader.teamIDEnvironmentKey] = teamID
public var errorDescription: String? {
switch self {
case .missingCredentials:
"Missing xAI/Grok API key."
Comment on lines +26 to +30
/// Team ID, stored in the workspaceID field
var grokTeamID: String {
get { self.configSnapshot.providerConfig(for: .grok)?.workspaceID ?? "default" }
set {
self.updateProviderConfig(provider: .grok) { entry in
- XAI_MANAGEMENT_KEY → XAI_MANAGEMENT_API_KEY (per official xAI docs)
- Remove unofficial GROK_API_KEY (only XAI_API_KEY is documented)
- cleaned() returns String? to match Zai/MiniMax/Kilo pattern
- Move GrokSettingsError to GrokSettingsReader (matches ZaiSettingsError placement)
- Add ensureGrokAPITokenLoaded() stub (matches ensureZaiAPITokenLoaded pattern)
@ratulsarna
Copy link
Collaborator

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3a2f664279

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

case synthetic
case warp
case openrouter
case grok

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0 Badge Register Grok descriptor in ProviderDescriptorRegistry

Adding .grok to UsageProvider here makes it part of UsageProvider.allCases, but ProviderDescriptorRegistry.descriptorsByID was not updated with .grok (checked Sources/CodexBarCore/Providers/ProviderDescriptor.swift, map at lines 55-78). During bootstrap, the loop over allCases hits preconditionFailure("Missing ProviderDescriptor for grok"), which will crash as soon as descriptor metadata is accessed (startup path for app/CLI config).

Useful? React with 👍 / 👎.

Comment on lines +70 to +71
func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool {
true // Fall back to regular API key strategy

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve management-fetch errors when fallback is unavailable

This unconditional true causes the pipeline to drop real management API errors whenever only a management key is configured (no API key): GrokManagementFetchStrategy fails, fallback proceeds, GrokAPIFetchStrategy is unavailable, and ProviderFetchPlan returns noAvailableStrategy instead of the original 4xx/5xx/network error. That makes misconfigured or failing management credentials much harder to diagnose.

Useful? React with 👍 / 👎.

- Add .grok to ProviderDescriptorRegistry.descriptorsByID (startup crash)
- Rewrite billing Decodable models to match actual xAI Management API
  response: nested spendingLimits with cent-string vals, coreInvoice
  with amountBeforeVat, effectiveSpendingLimit at top level
- shouldFallback only on credential errors, not API/network failures
- Fix management key URL to team-agnostic path
- Trim workspaceID before env injection
- Split missingCredentials into missingAPIKey / missingManagementKey
- Fix management key placeholder to match actual format (xai-token-...)
- Add explicit browserCookieOrder: nil to metadata
@BryanTegomoh
Copy link
Author

@ratulsarna Addressed all review feedback:

  • Descriptor registry entry (startup crash)
  • Billing models rewritten against live Management API responses
  • shouldFallback conditional on credential errors only
  • Management key URL, workspaceID trimming, error message split

Verified decoding against a live account:

Spending limits: effectiveSl = 30000 cents → $300.00
Invoice preview: amountBeforeVat = 16544 cents → $165.44
CodexBar display: $165.44 / $300.00 (55.1% used)

The Management API returns nested {"val": "30000"} cent-string wrappers and coreInvoice.amountBeforeVat as a flat string, both handled now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants