Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions changelog.d/fixes/xai-oauth-test-connection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb
35 changes: 20 additions & 15 deletions src/app/api/providers/[id]/test/oauthTestConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,23 @@ const CLINE_OAUTH_TEST_CONFIG = {
refreshable: true,
};

// Shared api.x.ai chat probe for apikey `xai` and OAuth `xai-oauth` / alias `xao`.
const XAI_CHAT_OAUTH_TEST_CONFIG = {
url: "https://api.x.ai/v1/chat/completions",
method: "POST",
authHeader: "Authorization",
authPrefix: "Bearer ",
extraHeaders: { "Content-Type": "application/json" },
body: JSON.stringify({
model: "grok-4.3",
messages: [{ role: "user", content: "ping" }],
max_tokens: 1,
stream: false,
reasoning: { effort: "high" },
}),
refreshable: true,
};

// OAuth provider test endpoints. Extracted from route.ts (#7610) so adding a
// provider entry doesn't grow the frozen route.ts file past its check-file-size
// cap — this module carries no logic of its own beyond the GitLab URL builder.
Expand Down Expand Up @@ -63,21 +80,9 @@ export const OAUTH_TEST_CONFIG = {
authPrefix: "Bearer ",
refreshable: true,
},
xai: {
url: "https://api.x.ai/v1/chat/completions",
method: "POST",
authHeader: "Authorization",
authPrefix: "Bearer ",
extraHeaders: { "Content-Type": "application/json" },
body: JSON.stringify({
model: "grok-4.3",
messages: [{ role: "user", content: "ping" }],
max_tokens: 1,
stream: false,
reasoning: { effort: "high" },
}),
refreshable: true,
},
xai: XAI_CHAT_OAUTH_TEST_CONFIG,
"xai-oauth": XAI_CHAT_OAUTH_TEST_CONFIG,
xao: XAI_CHAT_OAUTH_TEST_CONFIG,
github: {
url: "https://api.github.com/user",
method: "GET",
Expand Down
1 change: 0 additions & 1 deletion tests/unit/oauth-test-config-8408.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ const GRANDFATHERED_WITHOUT_TEST_CONFIG = new Set([
"zed-hosted",
"trae",
"windsurf",
"xai-oauth",
]);

test("#8408: devin-cli and agy are present in OAUTH_TEST_CONFIG", () => {
Expand Down
56 changes: 56 additions & 0 deletions tests/unit/xai-oauth-test-supported.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import test from "node:test";
import assert from "node:assert/strict";

// xai-oauth was grandfathered without OAUTH_TEST_CONFIG (#8408), so dashboard
// "Test Connection" always returned "Provider test not supported" and stored
// testStatus=error on a working OAuth account. Mirror grok-cli #7610 coverage.
const { testOAuthConnection } = await import("../../src/app/api/providers/[id]/test/route.ts");
const { OAUTH_TEST_CONFIG } =
await import("../../src/app/api/providers/[id]/test/oauthTestConfig.ts");

const originalFetch = globalThis.fetch;

test.afterEach(() => {
globalThis.fetch = originalFetch;
});

test("OAUTH_TEST_CONFIG covers xai-oauth and alias xao", () => {
assert.ok((OAUTH_TEST_CONFIG as Record<string, unknown>)["xai-oauth"]);
assert.ok((OAUTH_TEST_CONFIG as Record<string, unknown>).xao);
});

test("xai-oauth Test Connection is no longer unsupported", async () => {
globalThis.fetch = async () =>
new Response(JSON.stringify({ choices: [{ message: { content: "ok" } }] }), {
status: 200,
headers: { "content-type": "application/json" },
});

const result = await testOAuthConnection({
provider: "xai-oauth",
accessToken: "healthy-access-token",
refreshToken: "healthy-refresh-token",
tokenExpiresAt: new Date(Date.now() + 3600_000).toISOString(),
});

assert.notEqual(result.diagnosis?.type, "unsupported");
assert.notEqual(result.error, "Provider test not supported");
assert.equal(result.valid, true);
});

test("xao alias Test Connection uses the same probe", async () => {
let calledUrl = "";
globalThis.fetch = async (url) => {
calledUrl = String(url);
return new Response("{}", { status: 200, headers: { "content-type": "application/json" } });
};

const result = await testOAuthConnection({
provider: "xao",
accessToken: "healthy-access-token",
tokenExpiresAt: new Date(Date.now() + 3600_000).toISOString(),
});

assert.equal(result.valid, true);
assert.equal(calledUrl, "https://api.x.ai/v1/chat/completions");
});
Loading