feat(providers): add xAI Grok OAuth with capability-gated X Search (#5035)

This commit is contained in:
chengyongru
2026-07-23 11:55:16 +08:00
committed by GitHub
parent c22efb5f7a
commit c7393c785e
38 changed files with 3881 additions and 104 deletions
+25 -2
View File
@@ -16,6 +16,8 @@ import type {
NetworkSafetySettingsUpdate,
PairingPayload,
ProviderModelsPayload,
ProviderOAuthCompletionResult,
ProviderOAuthLoginResult,
ProviderSettingsUpdate,
SessionDeleteResult,
SessionAutomationsPayload,
@@ -51,6 +53,7 @@ function isSlashCommandLifecycle(value: unknown): value is SlashCommandLifecycle
}
const CHANNEL_VALUES_HEADER = "X-Nanobot-Channel-Values";
const API_SERVICE_VALUES_HEADER = "X-Nanobot-API-Service-Values";
const OAUTH_CODE_HEADER = "X-Nanobot-OAuth-Code";
export class ApiError extends Error {
status: number;
@@ -809,6 +812,7 @@ export async function updateProviderSettings(
if (update.apiKey !== undefined) query.set("api_key", update.apiKey);
if (update.apiBase !== undefined) query.set("api_base", update.apiBase);
if (update.apiType !== undefined) query.set("api_type", update.apiType);
if (update.proxy !== undefined) query.set("proxy", update.proxy);
return request<SettingsPayload>(
`${base}/api/settings/provider/update?${query}`,
token,
@@ -819,12 +823,31 @@ export async function loginProviderOAuth(
token: string,
provider: string,
base: string = "",
): Promise<SettingsPayload> {
): Promise<ProviderOAuthLoginResult> {
const query = new URLSearchParams();
query.set("provider", provider);
return request<SettingsPayload>(
return request<ProviderOAuthLoginResult>(
`${base}/api/settings/provider/oauth-login?${query}`,
token,
{ cache: "no-store" },
);
}
export async function completeProviderOAuth(
token: string,
provider: string,
flowId: string,
authorizationCode?: string,
base: string = "",
): Promise<ProviderOAuthCompletionResult> {
const query = new URLSearchParams();
query.set("provider", provider);
query.set("flow_id", flowId);
const headers = authorizationCode ? { [OAUTH_CODE_HEADER]: authorizationCode } : undefined;
return request<ProviderOAuthCompletionResult>(
`${base}/api/settings/provider/oauth-login/complete?${query}`,
token,
{ cache: "no-store", ...(headers ? { headers } : {}) },
);
}
+5
View File
@@ -131,6 +131,8 @@ export const PROVIDER_BRAND_ALIASES: Record<string, string> = {
minimaxAnthropic: "minimax",
minimax_anthropic: "minimax",
openai_codex: "openai",
"xai-grok": "xai",
xai_grok: "xai",
xiaomi: "xiaomi_mimo",
volcengine_coding_plan: "volcengine",
};
@@ -141,6 +143,8 @@ export const PROVIDER_LABEL_ALIASES: Record<string, string> = {
minimaxAnthropic: "MiniMax",
minimax_anthropic: "MiniMax",
openai_codex: "OpenAI",
"xai-grok": "xAI",
xai_grok: "xAI",
volcengine_coding_plan: "Volcengine",
};
@@ -194,6 +198,7 @@ const PROVIDER_BRANDS: Record<string, ProviderBrand> = {
xiaomi_mimo: brand("mimo.xiaomi.com", "#FF6900", "MI", [
"https://mimo.xiaomi.com/mimo-v2-pro/assets/logo.svg",
]),
xai: brand("x.ai", "#111827", "xAI"),
zhipu: brand("z.ai", "#155EEF", "Z", [
"https://z-cdn.chatglm.cn/z-ai/static/logo.svg",
"https://www.google.com/s2/favicons?domain=z.ai&sz=64",
+19
View File
@@ -377,6 +377,23 @@ export interface ProviderModelsPayload {
fetched_at?: number;
}
export interface ProviderOAuthAuthorizationRequired {
status: "authorization_required";
provider: string;
flow_id: string;
authorization_url: string;
expires_in: number;
}
export interface ProviderOAuthPending {
status: "pending";
provider: string;
flow_id: string;
}
export type ProviderOAuthLoginResult = SettingsPayload | ProviderOAuthAuthorizationRequired;
export type ProviderOAuthCompletionResult = SettingsPayload | ProviderOAuthPending;
export interface SettingsPayload {
surface?: RuntimeSurface;
runtime_surface?: RuntimeSurface;
@@ -430,6 +447,7 @@ export interface SettingsPayload {
oauth_account?: string | null;
oauth_expires_at?: number | null;
oauth_login_supported?: boolean;
proxy?: string | null;
}>;
web_search: {
provider: string;
@@ -936,6 +954,7 @@ export interface ProviderSettingsUpdate {
apiKey?: string;
apiBase?: string;
apiType?: "auto" | "chat_completions" | "responses";
proxy?: string;
}
export interface WebSearchSettingsUpdate {