399 lines
16 KiB
TypeScript
399 lines
16 KiB
TypeScript
/**
|
|
* TokenExtractionConfig — Login & cookie extraction configs for web-cookie providers
|
|
*
|
|
* Each config describes how to:
|
|
* 1. Open a browser window/navigate to the provider's login page
|
|
* 2. Detect successful login (URL change + token presence)
|
|
* 3. Extract session cookies / tokens from the browser context
|
|
*
|
|
* Used by InAppLoginService (Electron BrowserWindow path) and
|
|
* the Playwright-based login flow (dashboard API).
|
|
*/
|
|
|
|
// ─── Types ──────────────────────────────────────────────────────────────────
|
|
|
|
/** Describes where to extract credential data from after login */
|
|
export type TokenSource =
|
|
| { type: "cookie"; name: string; domain?: string }
|
|
| { type: "localStorage"; key: string }
|
|
| { type: "sessionStorage"; key: string }
|
|
| { type: "header"; name: string };
|
|
|
|
export interface PollingConfig {
|
|
/** Milliseconds between extraction polls (default 1000) */
|
|
pollInterval: number;
|
|
/** Total timeout in ms (default 300000 = 5 min) */
|
|
timeout: number;
|
|
/** Minimum time in ms before first extraction attempt (default 5000) */
|
|
minLoginTime: number;
|
|
}
|
|
|
|
export interface TokenExtractionConfig {
|
|
/** Matches the executor's provider ID (e.g. "claude-web", "gemini-web") */
|
|
providerId: string;
|
|
/** Human-readable name shown in dashboard UI */
|
|
displayName: string;
|
|
/** The URL to navigate to for login */
|
|
loginUrl: string;
|
|
/** The provider's home page URL (for cookie domain binding) */
|
|
homeUrl: string;
|
|
/** Optional regex. If current URL matches → login is likely complete */
|
|
successUrlPattern?: RegExp;
|
|
/** Sources to extract credentials from after login */
|
|
tokenSources: TokenSource[];
|
|
/** Polling behaviour */
|
|
pollingConfig: PollingConfig;
|
|
/** Short instructions shown to the user in the login modal */
|
|
instructions: string;
|
|
/** Optional: cookie domain override for cookie injection */
|
|
cookieDomain?: string;
|
|
}
|
|
|
|
// ─── Defaults ───────────────────────────────────────────────────────────────
|
|
|
|
const DEFAULT_POLLING: PollingConfig = {
|
|
pollInterval: 1000,
|
|
timeout: 300_000,
|
|
minLoginTime: 5000,
|
|
};
|
|
|
|
const QUICK_POLLING: PollingConfig = {
|
|
pollInterval: 800,
|
|
timeout: 120_000,
|
|
minLoginTime: 3000,
|
|
};
|
|
|
|
// ─── Helper ──────────────────────────────────────────────────────────────────
|
|
|
|
function config(
|
|
providerId: string,
|
|
displayName: string,
|
|
loginUrl: string,
|
|
homeUrl: string,
|
|
tokenSources: TokenSource[],
|
|
instructions: string,
|
|
opts?: {
|
|
successUrlPattern?: RegExp;
|
|
pollingConfig?: Partial<PollingConfig>;
|
|
cookieDomain?: string;
|
|
}
|
|
): TokenExtractionConfig {
|
|
return {
|
|
providerId,
|
|
displayName,
|
|
loginUrl,
|
|
homeUrl,
|
|
tokenSources,
|
|
instructions,
|
|
pollingConfig: { ...DEFAULT_POLLING, ...opts?.pollingConfig },
|
|
successUrlPattern: opts?.successUrlPattern,
|
|
cookieDomain: opts?.cookieDomain,
|
|
};
|
|
}
|
|
|
|
// ─── Configuration Map ──────────────────────────────────────────────────────
|
|
|
|
const RAW_CONFIGS: TokenExtractionConfig[] = [
|
|
// ── Claude Web ────────────────────────────────────────────
|
|
config(
|
|
"claude-web",
|
|
"Claude Web",
|
|
"https://claude.ai/login",
|
|
"https://claude.ai",
|
|
[{ type: "cookie", name: "sessionKey", domain: ".claude.ai" }],
|
|
"Log in to your Claude account at claude.ai. After login, the session cookie will be extracted automatically."
|
|
),
|
|
|
|
// ── ChatGPT Web ───────────────────────────────────────────
|
|
config(
|
|
"chatgpt-web",
|
|
"ChatGPT Web",
|
|
"https://chatgpt.com/auth/login",
|
|
"https://chatgpt.com",
|
|
[{ type: "cookie", name: "__Secure-next-auth.session-token", domain: ".chatgpt.com" }],
|
|
"Log in to ChatGPT. The __Secure-next-auth.session-token cookie will be extracted after login."
|
|
),
|
|
|
|
// ── Gemini Web ────────────────────────────────────────────
|
|
config(
|
|
"gemini-web",
|
|
"Gemini Web",
|
|
"https://gemini.google.com/app",
|
|
"https://gemini.google.com",
|
|
[
|
|
{ type: "cookie", name: "__Secure-1PSID", domain: ".google.com" },
|
|
{ type: "cookie", name: "__Secure-1PSIDTS", domain: ".google.com" },
|
|
],
|
|
"Log in to your Google account at gemini.google.com. Both __Secure-1PSID and __Secure-1PSIDTS cookies will be extracted.",
|
|
{ cookieDomain: ".google.com" }
|
|
),
|
|
|
|
// ── Grok Web ──────────────────────────────────────────────
|
|
config(
|
|
"grok-web",
|
|
"Grok Web",
|
|
"https://grok.com/login",
|
|
"https://grok.com",
|
|
[{ type: "cookie", name: "sso", domain: ".grok.com" }],
|
|
"Log in to your xAI account at grok.com. The sso session cookie will be extracted."
|
|
),
|
|
|
|
// ── Perplexity Web ────────────────────────────────────────
|
|
config(
|
|
"perplexity-web",
|
|
"Perplexity Web",
|
|
"https://www.perplexity.ai/login",
|
|
"https://www.perplexity.ai",
|
|
[{ type: "cookie", name: "__Secure-next-auth.session-token", domain: ".perplexity.ai" }],
|
|
"Log in to Perplexity. The __Secure-next-auth.session-token cookie will be extracted.",
|
|
{ cookieDomain: ".perplexity.ai" }
|
|
),
|
|
|
|
// ── DeepSeek Web ──────────────────────────────────────────
|
|
config(
|
|
"deepseek-web",
|
|
"DeepSeek Web",
|
|
"https://chat.deepseek.com/sign_in",
|
|
"https://chat.deepseek.com",
|
|
[
|
|
{ type: "cookie", name: "user-token", domain: ".deepseek.com" },
|
|
{ type: "localStorage", key: "userToken" },
|
|
],
|
|
"Log in to DeepSeek at chat.deepseek.com. The user-token cookie will be extracted.",
|
|
{ cookieDomain: ".deepseek.com" }
|
|
),
|
|
|
|
// ── Qwen Web ──────────────────────────────────────────────
|
|
// The v2 API sits behind Alibaba's "baxia" WAF, which needs the full browser
|
|
// cookie jar (cna + ssxmod_itna/itna2 + token), not just the bearer token.
|
|
// Capture the WAF cookies alongside the localStorage token (#3288).
|
|
config(
|
|
"qwen-web",
|
|
"Qwen Web (Tongyi)",
|
|
"https://chat.qwen.ai/",
|
|
"https://chat.qwen.ai",
|
|
[
|
|
{ type: "localStorage", key: "token" },
|
|
{ type: "cookie", name: "token", domain: ".chat.qwen.ai" },
|
|
{ type: "cookie", name: "cna", domain: ".chat.qwen.ai" },
|
|
{ type: "cookie", name: "ssxmod_itna", domain: ".chat.qwen.ai" },
|
|
{ type: "cookie", name: "ssxmod_itna2", domain: ".chat.qwen.ai" },
|
|
{ type: "cookie", name: "XSRF_TOKEN", domain: ".chat.qwen.ai" },
|
|
],
|
|
"Log in to Qwen at chat.qwen.ai using your Alibaba account. The session token and the " +
|
|
"Alibaba WAF cookies (cna, ssxmod_itna) will be extracted — all are required by the v2 API.",
|
|
{ cookieDomain: ".chat.qwen.ai" }
|
|
),
|
|
|
|
// ── Kimi Web ──────────────────────────────────────────────
|
|
config(
|
|
"kimi-web",
|
|
"Kimi (Moonshot)",
|
|
"https://www.kimi.com/",
|
|
"https://www.kimi.com",
|
|
[{ type: "cookie", name: "kimi-auth", domain: ".kimi.com" }],
|
|
"Log in to Kimi at www.kimi.com (international). The kimi-auth JWT cookie will be extracted.",
|
|
{ cookieDomain: ".kimi.com" }
|
|
),
|
|
|
|
// ── Blackbox Web ──────────────────────────────────────────
|
|
config(
|
|
"blackbox-web",
|
|
"Blackbox AI",
|
|
"https://app.blackbox.ai/login",
|
|
"https://app.blackbox.ai",
|
|
[
|
|
{ type: "cookie", name: "connect.sid", domain: ".blackbox.ai" },
|
|
{ type: "localStorage", key: "token" },
|
|
],
|
|
"Log in to Blackbox AI at app.blackbox.ai using Google/GitHub. The session cookie will be extracted.",
|
|
{ cookieDomain: ".blackbox.ai" }
|
|
),
|
|
|
|
// ── Poe Web ───────────────────────────────────────────────
|
|
config(
|
|
"poe-web",
|
|
"Poe (Quora)",
|
|
"https://poe.com/login",
|
|
"https://poe.com",
|
|
[{ type: "cookie", name: "p-b", domain: ".poe.com" }],
|
|
"Log in to Poe at poe.com. The session cookie will be extracted.",
|
|
{ cookieDomain: ".poe.com" }
|
|
),
|
|
|
|
// ── Copilot Web ───────────────────────────────────────────
|
|
config(
|
|
"copilot-web",
|
|
"Microsoft Copilot",
|
|
"https://copilot.microsoft.com/",
|
|
"https://copilot.microsoft.com",
|
|
[{ type: "cookie", name: "RPSCAuth", domain: ".microsoft.com" }],
|
|
"Log in with your Microsoft account at copilot.microsoft.com. The session auth cookie will be extracted.",
|
|
{ cookieDomain: ".microsoft.com" }
|
|
),
|
|
|
|
// ── DuckDuckGo Web ────────────────────────────────────────
|
|
config(
|
|
"duckduckgo-web",
|
|
"DuckDuckGo AI Chat",
|
|
"https://duckduckgo.com/?q=DuckDuckGo+AI+Chat&ia=chat&duckai=1",
|
|
"https://duckduckgo.com",
|
|
[{ type: "cookie", name: "duckai", domain: ".duckduckgo.com" }],
|
|
"Open DuckDuckGo AI Chat. Some models may require a free account. The duckai cookie will be extracted.",
|
|
{
|
|
cookieDomain: ".duckduckgo.com",
|
|
pollingConfig: QUICK_POLLING,
|
|
}
|
|
),
|
|
|
|
// ── Dola Web ──────────────────────────────────────────────
|
|
config(
|
|
"doubao-web",
|
|
"Dola (ByteDance)",
|
|
"https://www.dola.com/",
|
|
"https://www.dola.com",
|
|
[
|
|
{ type: "cookie", name: "sessionid", domain: ".dola.com" },
|
|
{ type: "cookie", name: "ttwid", domain: ".dola.com" },
|
|
{ type: "cookie", name: "s_v_web_id", domain: ".dola.com" },
|
|
],
|
|
"Log in to Dola at www.dola.com with your ByteDance account. sessionid, ttwid, and s_v_web_id will be extracted.",
|
|
{ cookieDomain: ".dola.com" }
|
|
),
|
|
|
|
// ── T3 Chat Web ───────────────────────────────────────────
|
|
config(
|
|
"t3-chat-web",
|
|
"T3 Chat",
|
|
"https://t3.chat/login",
|
|
"https://t3.chat",
|
|
[{ type: "localStorage", key: "token" }],
|
|
"Log in to T3 Chat at t3.chat using Google/GitHub. The token from localStorage will be extracted.",
|
|
{ pollingConfig: QUICK_POLLING }
|
|
),
|
|
|
|
// ── Venice Web ────────────────────────────────────────────
|
|
config(
|
|
"venice-web",
|
|
"Venice AI",
|
|
"https://venice.ai/login",
|
|
"https://venice.ai",
|
|
[
|
|
{ type: "cookie", name: "venice_session", domain: ".venice.ai" },
|
|
{ type: "localStorage", key: "token" },
|
|
],
|
|
"Log in to Venice AI at venice.ai. The session cookie will be extracted.",
|
|
{ cookieDomain: ".venice.ai" }
|
|
),
|
|
|
|
// ── v0 Dev Web ────────────────────────────────────────────
|
|
config(
|
|
"v0-vercel-web",
|
|
"v0 by Vercel",
|
|
"https://v0.dev/login",
|
|
"https://v0.dev",
|
|
[{ type: "cookie", name: "__Secure-next-auth.session-token", domain: ".v0.dev" }],
|
|
"Log in to v0.dev with your Vercel/Google/GitHub account. The session cookie will be extracted.",
|
|
{ cookieDomain: ".v0.dev" }
|
|
),
|
|
|
|
// ── Muse / Spark Web ──────────────────────────────────────
|
|
config(
|
|
"muse-spark-web",
|
|
"Meta AI (Muse)",
|
|
"https://www.meta.ai/",
|
|
"https://www.meta.ai",
|
|
[{ type: "cookie", name: "session", domain: ".meta.ai" }],
|
|
"Log in to Meta AI at meta.ai with your Facebook/Instagram account. The session cookie will be extracted.",
|
|
{ cookieDomain: ".meta.ai" }
|
|
),
|
|
|
|
// ── Adapta Web ────────────────────────────────────────────
|
|
config(
|
|
"adapta-web",
|
|
"Adapta AI",
|
|
"https://agent.adapta.one/login",
|
|
"https://agent.adapta.one",
|
|
[{ type: "cookie", name: "__session", domain: ".adapta.one" }],
|
|
"Log in to Adapta at agent.adapta.one. The session token will be extracted.",
|
|
{ cookieDomain: ".adapta.one" }
|
|
),
|
|
|
|
// ── VeoAI Free Web ────────────────────────────────────────
|
|
config(
|
|
"veoaifree-web",
|
|
"VeoAI Free",
|
|
"https://veoaifree.com/",
|
|
"https://veoaifree.com",
|
|
[{ type: "cookie", name: "wordpress_logged_in", domain: ".veoaifree.com" }],
|
|
"Log in to VeoAI Free at veoaifree.com. The WordPress session cookie will be extracted.",
|
|
{
|
|
cookieDomain: ".veoaifree.com",
|
|
pollingConfig: QUICK_POLLING,
|
|
}
|
|
),
|
|
|
|
// ── Missing Provider: ChatGLM (Zhipu) ──────────────────────
|
|
config(
|
|
"chatglm-web",
|
|
"ChatGLM (Zhipu AI)",
|
|
"https://chatglm.cn/",
|
|
"https://chatglm.cn",
|
|
[
|
|
{ type: "cookie", name: "chatglm_session", domain: ".chatglm.cn" },
|
|
{ type: "localStorage", key: "token" },
|
|
],
|
|
"Log in to ChatGLM at chatglm.cn with your phone number. The session token will be extracted.",
|
|
{ cookieDomain: ".chatglm.cn" }
|
|
),
|
|
|
|
// ── Missing Provider: Xiaomi MiMo ──────────────────────────
|
|
config(
|
|
"xiaomimimo-web",
|
|
"Xiaomi MiMo AI Studio",
|
|
"https://aistudio.xiaomimimo.com/login",
|
|
"https://aistudio.xiaomimimo.com",
|
|
[
|
|
{ type: "cookie", name: "session", domain: ".xiaomimimo.com" },
|
|
{ type: "localStorage", key: "access_token" },
|
|
],
|
|
"Log in to Xiaomi MiMo AI Studio at aistudio.xiaomimimo.com. The session token will be extracted.",
|
|
{ cookieDomain: ".xiaomimimo.com" }
|
|
),
|
|
|
|
// ── Missing Provider: Manus ────────────────────────────────
|
|
config(
|
|
"manus-web",
|
|
"Manus AI",
|
|
"https://manus.im/login",
|
|
"https://manus.im",
|
|
[
|
|
{ type: "cookie", name: "manus_session", domain: ".manus.im" },
|
|
{ type: "localStorage", key: "auth_token" },
|
|
],
|
|
"Log in to Manus at manus.im. The session cookie will be extracted.",
|
|
{ cookieDomain: ".manus.im" }
|
|
),
|
|
];
|
|
|
|
// ─── Registry ───────────────────────────────────────────────────────────────
|
|
|
|
const CONFIG_MAP = new Map<string, TokenExtractionConfig>();
|
|
|
|
for (const cfg of RAW_CONFIGS) {
|
|
CONFIG_MAP.set(cfg.providerId, cfg);
|
|
}
|
|
|
|
/** Get extraction config for a specific provider */
|
|
export function getExtractionConfig(providerId: string): TokenExtractionConfig | undefined {
|
|
return CONFIG_MAP.get(providerId);
|
|
}
|
|
|
|
/** List all registered extraction configs */
|
|
export function listExtractionConfigs(): TokenExtractionConfig[] {
|
|
return [...RAW_CONFIGS];
|
|
}
|
|
|
|
/** The shared config map — used by LoginManager and InAppLoginService */
|
|
export const TOKEN_EXTRACTION_CONFIGS = CONFIG_MAP;
|