ai_api / src /lib /providers /validation /webProvidersA.ts
Yogesh
initial deploy
cd8bd0a
Raw
History Blame Contribute Delete
25.5 kB
// Web-cookie provider key validators (part A): deepseek-web, qwen-web, grok-web, chatgpt-web,
// perplexity-web, blackbox-web. Extracted from validation.ts (god-file decomposition) β€” top-level
// functions with no dispatcher-state captures; behavior is byte-identical to the original inline defs.
import { addModelsSuffix } from "./urlHelpers";
import { applyCustomUserAgent } from "./headers";
import { toValidationErrorResult, validationRead, validationWrite } from "./transport";
import {
buildGrokCookieHeader,
buildQwenCookieHeader,
extractCookieValue,
extractQwenToken,
normalizeSessionCookieHeader,
} from "@/lib/providers/webCookieAuth";
export async function validateDeepSeekWebProvider({ apiKey }: any) {
if (!apiKey) {
return {
valid: false,
error:
"Missing userToken β€” paste the value from DevTools β†’ Application β†’ Local Storage β†’ chat.deepseek.com β†’ userToken",
};
}
let token = apiKey;
try {
const parsed = JSON.parse(token);
if (typeof parsed?.value === "string") token = parsed.value;
} catch {
// not JSON, use as-is
}
try {
const resp = await fetch("https://chat.deepseek.com/api/v0/users/current", {
headers: {
Authorization: `Bearer ${token}`,
Accept: "*/*",
Origin: "https://chat.deepseek.com",
Referer: "https://chat.deepseek.com/",
"User-Agent":
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36",
"X-App-Version": "20241129.1",
"X-Client-Platform": "web",
},
});
if (resp.status === 401 || resp.status === 403) {
return {
valid: false,
error: "userToken is invalid or expired β€” get a fresh one from localStorage",
};
}
if (!resp.ok) {
return { valid: false, error: `DeepSeek returned HTTP ${resp.status}` };
}
const json = await resp.json();
const bizData = json?.data?.biz_data || json?.biz_data;
if (!bizData?.token) {
return {
valid: false,
error: `DeepSeek did not return an access token: ${json?.msg || "unknown error"}`,
};
}
return { valid: true, error: null };
} catch (error: any) {
return toValidationErrorResult(error);
}
}
// qwen-web has no `modelsUrl` in its registry entry, so the generic OpenAI-compatible
// validator derived a probe URL of `https://chat.qwen.ai/api/v2/models` (via
// addModelsSuffix) β€” a non-existent path that answers with a 307 redirect, which the
// outbound guard blocked and the route then mislabeled as an SSRF block (#3288/#3758).
// This specialty validator probes the real session-validity endpoint instead
// (`GET /api/v2/user`, the same one Chat2API uses), mirroring the executor's anti-bot
// headers + cookie-jar replay. It uses plain fetch (like the other web-cookie
// validators) so it never hits the addModelsSuffix/redirect path.
export async function validateQwenWebProvider({ apiKey }: any) {
const rawCred = String(apiKey ?? "").trim();
if (!rawCred) {
return {
valid: false,
error:
"Missing Qwen session β€” paste the full chat.qwen.ai Cookie header (must include token, cna and ssxmod_itna)",
};
}
const token = extractQwenToken(rawCred);
const cookieHeader = buildQwenCookieHeader(rawCred);
if (!token && !cookieHeader) {
return {
valid: false,
error: "Could not find a Qwen token/cookie in the pasted value",
};
}
try {
const headers: Record<string, string> = {
Accept: "*/*",
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
Origin: "https://chat.qwen.ai",
Referer: "https://chat.qwen.ai/",
source: "web",
"bx-v": "2.5.36",
};
if (token) headers["Authorization"] = `Bearer ${token}`;
if (cookieHeader) headers["Cookie"] = cookieHeader;
const resp = await fetch("https://chat.qwen.ai/api/v2/user", { headers });
const contentType = resp.headers.get("content-type") || "";
if (resp.status === 401 || resp.status === 403) {
return {
valid: false,
error:
"Qwen session is invalid or expired β€” re-login at https://chat.qwen.ai and paste a fresh full Cookie header",
};
}
// Alibaba's WAF / retired-v1 gateway answers with an HTML challenge page (or 504)
// instead of JSON. A bearer token alone is no longer enough for the v2 endpoint.
if (contentType.includes("text/html") || resp.status === 504) {
return {
valid: false,
error:
"Qwen blocked the request with its anti-bot WAF. Re-login at https://chat.qwen.ai and paste a fresh full Cookie header (must include cna, ssxmod_itna and token) β€” a bearer token alone is not accepted.",
};
}
if (!resp.ok) {
return { valid: false, error: `Qwen returned HTTP ${resp.status}` };
}
// Parse JSON response and verify we have a real user object
// Qwen returns HTTP 200 even for invalid tokens, so we must check the body
try {
const data = await resp.json();
const user = data?.user || data?.data?.user;
if (!user) {
return {
valid: false,
error:
"Qwen session token is invalid or expired β€” re-login at https://chat.qwen.ai and paste a fresh full Cookie header",
};
}
} catch (parseError) {
return {
valid: false,
error: "Qwen returned invalid JSON response",
};
}
return { valid: true, error: null };
} catch (error) {
return toValidationErrorResult(error);
}
}
/**
* Heuristic for a Grok 403 that is an anti-bot / IP-reputation block rather than
* a genuine upstream API error (issue #3474).
*
* Returns true when the body reads like an anti-bot rejection β€” Grok's literal
* "Request rejected by anti-bot rules." text, or a bare/non-structured forbidden
* body that carries no parseable upstream `error.message`. Returns false for a
* structured upstream API error (e.g. `{"error":{"message":"Model is not found"}}`),
* which must keep surfacing its body to the user/maintainer.
*
* Callers should run `isCloudflareChallenge()` first; this covers the non-HTML
* anti-bot cases that Cloudflare-challenge detection does not.
*/
export function isGrokAntiBotBlock(body: string | null | undefined): boolean {
const text = (body || "").trim();
if (!text) return true; // empty 403 body β€” pre-auth block, treat as anti-bot
if (/anti-bot|forbidden|access denied|blocked|rate.?limit/i.test(text)) return true;
// A structured upstream API error has a parseable JSON `error.message`; if one
// is present this is a real upstream error, not an anti-bot block.
try {
const parsed = JSON.parse(text);
if (parsed && typeof parsed?.error?.message === "string") return false;
} catch {
// Non-JSON 403 body with no recognizable structure β†’ treat as anti-bot block.
return true;
}
return false;
}
export async function validateGrokWebProvider({ apiKey, providerSpecificData = {} }: any) {
try {
const token = extractCookieValue(apiKey, "sso");
if (!token) {
return {
valid: false,
error: "Missing sso cookie β€” paste the value (or the full grok.com cookie line)",
};
}
// Use the TLS-impersonating client β€” Cloudflare on grok.com pins
// cf_clearance to JA3/JA4 + HTTP/2 SETTINGS, so plain Node fetch always
// gets "Request rejected by anti-bot rules." regardless of cookies (#3180).
const { tlsFetchGrok, TlsClientUnavailableError, isCloudflareChallenge } =
await import("@omniroute/open-sse/services/grokTlsClient.ts");
// Generate the same Cloudflare-bypass headers the GrokWebExecutor uses.
const randomHex = (n: number) => {
const a = new Uint8Array(n);
crypto.getRandomValues(a);
return Array.from(a, (b) => b.toString(16).padStart(2, "0")).join("");
};
const statsigMsg = `e:TypeError: Cannot read properties of null (reading 'children')`;
const traceId = randomHex(16);
const spanId = randomHex(8);
let response;
try {
response = await tlsFetchGrok("https://grok.com/rest/app-chat/conversations/new", {
method: "POST",
headers: applyCustomUserAgent(
{
Accept: "*/*",
"Accept-Encoding": "gzip, deflate, br, zstd",
"Accept-Language": "en-US,en;q=0.9",
Baggage:
"sentry-environment=production,sentry-release=d6add6fb0460641fd482d767a335ef72b9b6abb8,sentry-public_key=b311e0f2690c81f25e2c4cf6d4f7ce1c",
"Cache-Control": "no-cache",
"Content-Type": "application/json",
Cookie: buildGrokCookieHeader(apiKey),
Origin: "https://grok.com",
Pragma: "no-cache",
Referer: "https://grok.com/",
"Sec-Ch-Ua": '"Google Chrome";v="147", "Chromium";v="147", "Not(A:Brand";v="24"',
"Sec-Ch-Ua-Mobile": "?0",
"Sec-Ch-Ua-Platform": '"macOS"',
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"User-Agent":
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36",
"x-statsig-id": btoa(statsigMsg),
"x-xai-request-id": crypto.randomUUID(),
traceparent: `00-${traceId}-${spanId}-00`,
},
providerSpecificData
),
body: JSON.stringify({
temporary: true,
modeId: "fast",
message: "test",
fileAttachments: [],
imageAttachments: [],
disableSearch: true,
enableImageGeneration: false,
returnImageBytes: false,
returnRawGrokInXaiRequest: false,
enableImageStreaming: false,
imageGenerationCount: 0,
forceConcise: true,
toolOverrides: {},
enableSideBySide: false,
sendFinalMetadata: false,
isReasoning: false,
disableTextFollowUps: true,
disableMemory: true,
forceSideBySide: false,
isAsyncChat: false,
disableSelfHarmShortCircuit: false,
}),
timeoutMs: 15_000,
});
} catch (err: any) {
if (err instanceof TlsClientUnavailableError) {
return {
valid: false,
error: `TLS impersonation client unavailable: ${err.message}`,
};
}
throw err;
}
let errorDetail = "";
try {
errorDetail = (response.text || "").slice(0, 240);
} catch {}
// Detect Cloudflare challenge pages even with a 200 status from tls-client-node
if (isCloudflareChallenge(errorDetail)) {
return {
valid: false,
error: "Grok validation blocked by Cloudflare anti-bot. Try a residential IP or proxy.",
};
}
if (response.status >= 200 && response.status < 300) {
return { valid: true, error: null };
}
if (response.status === 401) {
return {
valid: false,
error: "Invalid SSO cookie β€” re-paste from grok.com DevTools β†’ Cookies β†’ sso",
};
}
if (response.status === 403) {
// Grok uses 403 for auth failures, entitlement issues, geo blocks,
// anti-bot/IP-reputation rejections, and resource errors. Classify before
// messaging β€” a misleading "invalid cookie" verdict on an IP-reputation
// block (issue #3474) sends users chasing a cookie that is actually fine.
//
// 1. Auth-shaped β†’ the cookie/session is the problem; re-paste it.
if (/invalid-credentials|unauthenticated|unauthorized/i.test(errorDetail)) {
return {
valid: false,
error: "Invalid SSO cookie β€” re-paste from grok.com DevTools β†’ Cookies β†’ sso",
};
}
// 2. Anti-bot / Cloudflare / IP-reputation block β†’ the cookie is likely
// fine; the request was rejected before auth was even evaluated. This is
// not code-fixable: the datacenter/VPS IP is flagged. A Cloudflare
// challenge body, Grok's "anti-bot rules" rejection, or a bare/non-JSON
// forbidden body (no structured upstream `error.message`) all map here.
if (isCloudflareChallenge(errorDetail) || isGrokAntiBotBlock(errorDetail)) {
return {
valid: false,
error:
"Grok returned 403 (anti-bot/Cloudflare block). Your sso cookie is likely fine β€” " +
"this is an IP-reputation block on the request, not an auth failure. Retry from a " +
"residential IP or configure a proxy for grok-web.",
};
}
// 3. Structured upstream error (e.g. probe model renamed) β†’ surface the body
// so the user/maintainer sees the real cause instead of a wrong verdict.
return {
valid: false,
error: `Grok rejected validation (403)${errorDetail ? `: ${errorDetail.slice(0, 160)}` : ""}`,
};
}
if (response.status === 429) {
return { valid: false, error: "Grok rate limited during validation (429)" };
}
if (response.status >= 500) {
return { valid: false, error: `Grok unavailable (${response.status})` };
}
return {
valid: false,
error: `Grok validation failed (${response.status})${errorDetail ? `: ${errorDetail}` : ""}`,
};
} catch (error: any) {
return toValidationErrorResult(error);
}
}
export async function validateChatGptWebProvider({ apiKey, providerSpecificData = {} }: any) {
try {
// Accept bare value, unchunked cookie, chunked (.0/.1) cookies, or full
// "Cookie: ..." DevTools line. Pass through verbatim once recognised.
let cookieHeader = String(apiKey || "").trim();
if (/^cookie\s*:\s*/i.test(cookieHeader)) {
cookieHeader = cookieHeader.replace(/^cookie\s*:\s*/i, "");
}
if (!/__Secure-next-auth\.session-token(?:\.\d+)?\s*=/.test(cookieHeader)) {
cookieHeader = `__Secure-next-auth.session-token=${cookieHeader}`;
}
// Use the TLS-impersonating client β€” Cloudflare on chatgpt.com pins
// cf_clearance to JA3/JA4 + HTTP/2 SETTINGS, so plain Node fetch always
// gets cf-mitigated: challenge regardless of cookies.
const { tlsFetchChatGpt, TlsClientUnavailableError } =
await import("@omniroute/open-sse/services/chatgptTlsClient.ts");
let response;
try {
response = await tlsFetchChatGpt("https://chatgpt.com/api/auth/session", {
method: "GET",
headers: applyCustomUserAgent(
{
Accept: "application/json",
"Accept-Language": "en-US,en;q=0.9",
"Cache-Control": "no-cache",
Cookie: cookieHeader,
Origin: "https://chatgpt.com",
Pragma: "no-cache",
Referer: "https://chatgpt.com/",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"User-Agent":
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:148.0) Gecko/20100101 Firefox/148.0",
},
providerSpecificData
),
timeoutMs: 30_000,
});
} catch (err: any) {
if (err instanceof TlsClientUnavailableError) {
return {
valid: false,
error: `${err.message} (chatgpt-web requires this β€” without it, Cloudflare blocks every request)`,
};
}
throw err;
}
const contentType = response.headers.get("content-type") || "";
const cfRay = response.headers.get("cf-ray");
const cfMitigated = response.headers.get("cf-mitigated");
if (response.status === 401 || response.status === 403) {
const bodyText = response.text || "";
if (cfMitigated || /just a moment|cloudflare|cf-chl|attention required/i.test(bodyText)) {
return {
valid: false,
error:
"Cloudflare blocked the validator β€” open chatgpt.com in your browser, then copy the FULL Cookie line from DevTools (Network β†’ request β†’ Cookie) including cf_clearance, __cf_bm, _cfuvid, and the session-token chunks.",
};
}
return {
valid: false,
error:
"Invalid ChatGPT session cookie β€” re-paste __Secure-next-auth.session-token from chatgpt.com DevTools β†’ Cookies",
};
}
if (response.status >= 500) {
return { valid: false, error: `ChatGPT unavailable (${response.status})` };
}
if (response.status >= 400) {
return { valid: false, error: `Validation failed: ${response.status}` };
}
if (!contentType.includes("json")) {
return {
valid: false,
error: `ChatGPT returned non-JSON (${contentType || "no content-type"}${cfRay ? `, cf-ray=${cfRay}` : ""}) β€” paste the FULL Cookie line including cf_clearance, __cf_bm, _cfuvid alongside the session-token chunks.`,
};
}
let data: any = {};
try {
data = JSON.parse(response.text || "{}");
} catch {
return {
valid: false,
error:
"ChatGPT session response was not JSON β€” paste the FULL Cookie line including cf_clearance and __cf_bm.",
};
}
if (!data?.accessToken) {
return {
valid: false,
error: "ChatGPT session expired β€” log into chatgpt.com and copy a fresh cookie",
};
}
return { valid: true, error: null };
} catch (error: any) {
return toValidationErrorResult(error);
}
}
export async function validatePerplexityWebProvider({ apiKey, providerSpecificData = {} }: any) {
try {
let sessionToken = apiKey;
let bearerToken: string | null = null;
if (sessionToken.startsWith("__Secure-next-auth.session-token=")) {
sessionToken = sessionToken.slice("__Secure-next-auth.session-token=".length);
} else if (/^bearer\s+/i.test(sessionToken)) {
bearerToken = sessionToken.replace(/^bearer\s+/i, "").trim();
sessionToken = "";
}
const timezone =
typeof Intl !== "undefined" ? Intl.DateTimeFormat().resolvedOptions().timeZone : "UTC";
const headers = applyCustomUserAgent(
{
"Content-Type": "application/json",
Accept: "text/event-stream",
Origin: "https://www.perplexity.ai",
Referer: "https://www.perplexity.ai/",
// Firefox 148 β€” must match the firefox_148 TLS profile of perplexityTlsClient (issue #2459).
"User-Agent":
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:148.0) Gecko/20100101 Firefox/148.0",
"X-App-ApiClient": "default",
"X-App-ApiVersion": "client-1.11.0",
...(bearerToken
? { Authorization: `Bearer ${bearerToken}` }
: sessionToken
? { Cookie: `__Secure-next-auth.session-token=${sessionToken}` }
: {}),
},
providerSpecificData
);
// Perplexity is behind Cloudflare Enterprise which pins JA3/JA4 to a real
// browser handshake β€” plain fetch is challenged with a 403 page from
// VPS/datacenter IPs even with a valid cookie. Use the Firefox-fingerprinted
// TLS client so the validator's verdict reflects the cookie, not the IP (issue #2459).
const { tlsFetchPerplexity, isCloudflareChallenge, TlsClientUnavailableError } =
await import("@omniroute/open-sse/services/perplexityTlsClient.ts");
let response: { status: number; text: string | null };
try {
response = await tlsFetchPerplexity("https://www.perplexity.ai/rest/sse/perplexity_ask", {
method: "POST",
headers,
body: JSON.stringify({
query_str: "test",
params: {
query_str: "test",
search_focus: "internet",
mode: "concise",
model_preference: "default",
sources: ["web"],
attachments: [],
frontend_uuid: crypto.randomUUID(),
frontend_context_uuid: crypto.randomUUID(),
version: "client-1.11.0",
language: "en-US",
timezone,
search_recency_filter: null,
is_incognito: true,
use_schematized_api: true,
last_backend_uuid: null,
},
}),
timeoutMs: 30_000,
});
} catch (err) {
if (err instanceof TlsClientUnavailableError) {
return {
valid: false,
error: `${err.message} perplexity-web requires it β€” without it Cloudflare blocks every request.`,
};
}
throw err;
}
if (response.status === 401 || response.status === 403) {
if (isCloudflareChallenge(response.text)) {
return {
valid: false,
error:
"Cloudflare is blocking connections from this server's IP (TLS fingerprint rejected). " +
"The session cookie may still be valid β€” install tls-client-node's native binary or route " +
"perplexity-web through a residential proxy.",
};
}
return {
valid: false,
error:
"Invalid Perplexity session cookie β€” re-paste __Secure-next-auth.session-token from perplexity.ai",
};
}
if (response.status === 200 || (response.status >= 400 && response.status < 500)) {
return { valid: true, error: null };
}
if (response.status >= 500) {
return { valid: false, error: `Perplexity unavailable (${response.status})` };
}
return { valid: false, error: `Validation failed: ${response.status}` };
} catch (error: any) {
return toValidationErrorResult(error);
}
}
export async function validateBlackboxWebProvider({ apiKey, providerSpecificData = {} }: any) {
try {
const cookieHeader = normalizeSessionCookieHeader(apiKey, "next-auth.session-token");
const sessionHeaders = applyCustomUserAgent(
{
Accept: "application/json",
Cookie: cookieHeader,
Origin: "https://app.blackbox.ai",
Referer: "https://app.blackbox.ai/",
"User-Agent":
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/147.0.0.0",
},
providerSpecificData
);
const sessionResponse = await validationRead("https://app.blackbox.ai/api/auth/session", {
method: "GET",
headers: sessionHeaders,
});
const sessionText = await sessionResponse.text();
const sessionPayload = sessionText ? JSON.parse(sessionText) : null;
const userEmail = sessionPayload?.user?.email;
if (!sessionResponse.ok || !userEmail) {
return {
valid: false,
error:
"Invalid Blackbox session cookie β€” re-paste __Secure-authjs.session-token from app.blackbox.ai",
};
}
const subscriptionHeaders = applyCustomUserAgent(
{
"Content-Type": "application/json",
Accept: "application/json",
Cookie: cookieHeader,
Origin: "https://app.blackbox.ai",
Referer: "https://app.blackbox.ai/",
"User-Agent":
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/147.0.0.0",
},
providerSpecificData
);
const subscriptionResponse = await validationWrite(
"https://app.blackbox.ai/api/check-subscription",
{
method: "POST",
headers: subscriptionHeaders,
body: JSON.stringify({ email: userEmail }),
}
);
const subscriptionText = await subscriptionResponse.text();
const subscriptionPayload = subscriptionText ? JSON.parse(subscriptionText) : null;
const explicitActive =
subscriptionPayload?.hasActiveSubscription === true ||
subscriptionPayload?.isTrialSubscription === true ||
subscriptionPayload?.status === "PREMIUM";
const explicitInactive =
subscriptionPayload?.hasActiveSubscription === false ||
subscriptionPayload?.status === "FREE";
const requiresAuthentication =
subscriptionPayload?.requiresAuthentication === true ||
/login is required/i.test(subscriptionText || "");
if (subscriptionResponse.status === 401 || subscriptionResponse.status === 403) {
return {
valid: false,
error:
"Invalid Blackbox session cookie β€” re-paste __Secure-authjs.session-token from app.blackbox.ai",
};
}
if (requiresAuthentication) {
return {
valid: false,
error:
"Blackbox session expired β€” re-paste __Secure-authjs.session-token from app.blackbox.ai",
};
}
if (subscriptionResponse.ok && explicitActive) {
return { valid: true, error: null };
}
if (
(subscriptionResponse.ok && explicitInactive) ||
subscriptionPayload?.previouslySubscribed
) {
return {
valid: false,
error:
"Blackbox account authenticated, but no active paid subscription was detected for premium web models.",
};
}
if (subscriptionResponse.ok) {
return { valid: true, error: null };
}
if (subscriptionResponse.status >= 500) {
return { valid: false, error: `Blackbox unavailable (${subscriptionResponse.status})` };
}
return { valid: false, error: `Validation failed: ${subscriptionResponse.status}` };
} catch (error: any) {
return toValidationErrorResult(error);
}
}