Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
78fb69e
Add xAI Grok subscription OAuth alongside the existing API key path.
pridemusvaire Jul 25, 2026
b867570
test: cover xAI OAuth disconnect and OAuth-only sandbox gateway marker
pridemusvaire Jul 25, 2026
b7e9563
fix: address xAI OAuth review findings for control-plane auth and tests
pridemusvaire Jul 25, 2026
17fc504
Merge branch 'develop' into feat/xai-grok-subscription-oauth
pridemusvaire Jul 25, 2026
2af8791
test: cover xAI Grok subscription UI dual-path in Settings and setup
pridemusvaire Jul 25, 2026
45e25d3
Merge branch 'develop' into feat/xai-grok-subscription-oauth
pridemusvaire Jul 25, 2026
34ca6c9
fix: mock isXaiSubscriptionConnected in tests and harden XaiConnectDi…
pridemusvaire Jul 25, 2026
aade2d2
fix: only persist xAI OAuth for the active device flow
pridemusvaire Jul 25, 2026
8485e9d
fix: claim xAI device flow before device-code HTTP
pridemusvaire Jul 25, 2026
4e4820f
fix: lock xAI disconnect against in-flight poll persist
pridemusvaire Jul 25, 2026
26fe86a
fix: harden xAI disconnect vs refresh and OAuth precedence
pridemusvaire Jul 25, 2026
e14df26
fix: preserve xai models when deleting BYOK while SuperGrok stays
pridemusvaire Jul 25, 2026
feea95a
fix: finish deferred xAI connect polish
pridemusvaire Jul 25, 2026
0c5a53d
feat: split Grok subscription into its own provider and add usage bar
pridemusvaire Jul 26, 2026
a949fdd
fix: address code review findings for SuperGrok provider alias
pridemusvaire Jul 26, 2026
149deeb
fix: finish remaining SuperGrok review polish
pridemusvaire Jul 26, 2026
ee6382e
fix: mock getFreshXaiAccessToken in SuperGrok usage tests
pridemusvaire Jul 26, 2026
7fe4a2f
fix: show Connect Grok subscription for SuperGrok OAuth
pridemusvaire Jul 26, 2026
af84cea
fix: offer SuperGrok connect on the xAI setup surface
pridemusvaire Jul 26, 2026
cdbba3b
fix: parse live Grok billing payload for usage bars
pridemusvaire Jul 26, 2026
594c912
Merge remote-tracking branch 'origin/develop' into feat/xai-grok-subs…
mrubens Jul 26, 2026
8d5cd71
fix: group xai models under the Grok subscription in model selectors
mrubens Jul 26, 2026
b4a9ddd
improve: show one aggregate usage bar for the Grok subscription
mrubens Jul 26, 2026
a69e298
chore: scope the gitleaks allowlist to the client id only
mrubens Jul 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Roomote gitleaks configuration.
# Extends default rules; only add allowlist entries with a concrete reason.
#
# Scope allowlists to the specific value, never to a whole file: a path
# allowlist exempts every future line in that file from every rule.

title = "Roomote"

[allowlist]
description = "False positives and intentional public identifiers"

# Public Grok CLI OAuth client id reused by peer tools for SuperGrok
# device-code login. This is not a secret; it is the same client_id published
# by ecosystem agents (Hermes, OpenClaw, CC Switch) for auth.x.ai. It is
# UUID-shaped, which is the only reason the default rules flag it.
regexes = [
'''b1a00492-073a-47ea-816f-4c329264a828''',
]

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 50 additions & 0 deletions apps/api/src/handlers/inference/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
} from '@roomote/types';
import {
getFreshChatGptAccessToken,
getFreshXaiAccessToken,
getGitHubCopilotAccessToken,
resolveModelProviderEnvValue,
} from '@roomote/db/server';
Expand All @@ -32,6 +33,8 @@ export type GatewayUpstreamResolution =
* - `api-key`: inject the deployment's static key at the request path.
* - `chatgpt-oauth`: mint a fresh subscription access token, add the
* account-id header, and collapse the request onto the Codex backend.
* - `xai-oauth`: prefer a connected Grok subscription access token, then
* fall back to `XAI_API_KEY`.
*/
export async function resolveGatewayUpstream(
provider: InferenceGatewayProvider,
Expand All @@ -46,6 +49,10 @@ export async function resolveGatewayUpstream(
return resolveGitHubCopilotUpstream(provider, upstreamPath, search);
}

if (provider.authStrategy === 'xai-oauth') {
return resolveXaiUpstream(provider, upstreamPath, search);
}

const [apiKey, upstreamBaseUrl] = await Promise.all([
resolveModelProviderEnvValue(provider.envVarNames),
resolveProviderUpstreamBaseUrl(provider),
Expand Down Expand Up @@ -76,6 +83,49 @@ export async function resolveGatewayUpstream(
};
}

/**
* xAI supports both SuperGrok OAuth and a BYOK API key. Prefer a connected
* subscription (fresh access token) so subscription users never need a key;
* fall back to the deployment key when only that is configured.
*/
async function resolveXaiUpstream(
provider: InferenceGatewayProvider,
upstreamPath: string,
search: string,
): Promise<GatewayUpstreamResolution> {
const [oauthToken, apiKey, upstreamBaseUrl] = await Promise.all([
getFreshXaiAccessToken(),
resolveModelProviderEnvValue(provider.envVarNames),
resolveProviderUpstreamBaseUrl(provider),
]);

const bearer = oauthToken?.access ?? apiKey;

if (!bearer) {
return {
ok: false,
status: 404,
error:
'No connected xAI Grok subscription or XAI_API_KEY is available for this deployment',
};
}

return {
ok: true,
resolved: {
upstreamUrl: `${upstreamBaseUrl}${upstreamPath}${search}`,
headers: provider.authHeader
? {
[provider.authHeader.name]: formatProviderAuthHeaderValue(
provider,
bearer,
),
}
: {},
},
};
}

async function resolveGitHubCopilotUpstream(
provider: InferenceGatewayProvider,
upstreamPath: string,
Expand Down
3 changes: 2 additions & 1 deletion apps/docs/environment-variables.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ as per-task auth tokens or workspace paths.
| `AI_GATEWAY_API_KEY` | Provider key | Vercel AI Gateway API key. |
| `OPENAI_API_KEY` | Provider key | OpenAI API key. |
| `ANTHROPIC_API_KEY` | Provider key | Anthropic API key. |
| `XAI_API_KEY` | Provider key | xAI / Grok API key. |
| `XAI_API_KEY` | Provider key | xAI / Grok API key. Optional when a SuperGrok / eligible X Premium+ subscription is connected from **Settings > Models**. |
| `XAI_OAUTH_CLIENT_ID` | Optional | Override for the public Grok CLI OAuth client id used by the SuperGrok device-code connect flow. Defaults to the public CLI client id. |
| `MOONSHOT_API_KEY` | Provider key | Moonshot AI / Kimi Open Platform API key. |
| `KIMI_API_KEY` | Provider key | Kimi for Coding API key for `kimi-for-coding/...` models. |
| `MINIMAX_API_KEY` | Provider key | MiniMax API key. |
Expand Down
22 changes: 13 additions & 9 deletions apps/docs/models.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ Configure models from **Settings > Models**.
An inference provider is the service that hosts or routes model calls. Roomote
supports providers such as OpenRouter, Vercel AI Gateway, Baseten,
Together AI, OpenAI, Anthropic, Moonshot AI, Kimi for Coding, MiniMax, Z.AI,
Z.AI Coding Plan, OpenCode, Amazon Bedrock, Google Gemini, xAI, GitHub Copilot,
ChatGPT subscriptions, and OpenAI-compatible endpoints such as LiteLLM, Ollama,
and vLLM.
Z.AI Coding Plan, OpenCode, Amazon Bedrock, Google Gemini, xAI (API key or
Grok subscription), GitHub Copilot, ChatGPT subscriptions, and
OpenAI-compatible endpoints such as LiteLLM, Ollama, and vLLM.

You can connect more than one inference provider in the same deployment. That
lets you mix and match models by provider instead of betting the whole
Expand Down Expand Up @@ -138,12 +138,16 @@ list.
- **Models** controls the provider/model pairs that are available, the default
model, and specialized model roles.

For subscription-based providers (ChatGPT, GitHub Copilot, and Kimi for
Coding), the provider row also shows current plan usage when the provider
reports it, such as remaining Copilot premium requests or the percent used of
the ChatGPT 5-hour and weekly limits. These numbers come from unofficial
provider endpoints, so the usage line is hidden whenever the provider does not
return usable data.
For subscription-based providers (ChatGPT, GitHub Copilot, Kimi for Coding, and
xAI Grok / SuperGrok), the provider row also shows current plan usage when the
provider reports it, such as remaining Copilot premium requests, the percent
used of the ChatGPT 5-hour and weekly limits, or Grok included-usage windows.
These numbers come from unofficial provider endpoints, so the usage line is
hidden whenever the provider does not return usable data.

xAI can be connected with an API key, a SuperGrok or eligible X Premium+
subscription, or both. When both are configured, the subscription is preferred
at runtime for `xai/` models.

Admins can enable or disable models from the task model list. The default model
must stay enabled, because Roomote uses it when a task does not request a
Expand Down
Loading
Loading