From c095dbf73daeb319023146a2ad0ed75028d9aeff Mon Sep 17 00:00:00 2001 From: backryun Date: Thu, 6 Aug 2026 10:31:36 +0900 Subject: [PATCH] fix(types): align web provider support contracts (#9139) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Validated in local merge-train (devbox-vm-06-dev002) @ combined-tip (FAST gates: typecheck/complexity/cognitive/changelog/vitest — only pre-existing audit.test.ts flake). Evidence: /home/diegosouzapw/dev/proxys/OmniRoute/.claude/worktrees/merge-train-20260805-222248-suite.log --- open-sse/executors/chatgpt-web.ts | 10 +++++----- open-sse/executors/duckduckgo-web.ts | 5 ----- open-sse/executors/duckduckgo-web/challenge.ts | 5 +++++ src/shared/providers/webSessionCredentials.ts | 5 +++-- tests/unit/duckduckgo-challenge-split.test.ts | 2 ++ 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/open-sse/executors/chatgpt-web.ts b/open-sse/executors/chatgpt-web.ts index eee1dace6e..15fc3b7355 100644 --- a/open-sse/executors/chatgpt-web.ts +++ b/open-sse/executors/chatgpt-web.ts @@ -44,7 +44,6 @@ const SENTINEL_PREPARE_URL = `${CHATGPT_BASE}/backend-api/sentinel/chat-requirem const SENTINEL_CR_URL = `${CHATGPT_BASE}/backend-api/sentinel/chat-requirements`; const CONV_URL = `${CHATGPT_BASE}/backend-api/f/conversation`; const USER_LAST_USED_MODEL_CONFIG_URL = `${CHATGPT_BASE}/backend-api/settings/user_last_used_model_config`; - const DEFAULT_PRO_POLL_TIMEOUT_MS = 20 * 60_000; const DEFAULT_PRO_POLL_INTERVAL_MS = 4_000; @@ -2263,7 +2262,7 @@ interface ResolverContext { deviceId: string; cookie: string; signal?: AbortSignal | null; - log?: { debug?: (tag: string, msg: string) => void; warn?: (tag: string, msg: string) => void }; + log?: Partial void>>; /** * Absolute base URL that downstream clients should use to fetch cached * images served by /v1/chatgpt-web/image/. Derived from the inbound @@ -2697,9 +2696,10 @@ async function pollForAsyncImage( const message = node?.message; const parts = message?.content?.parts; if (!Array.isArray(parts)) continue; - const pointers = extractImagePointers(parts).map( - (pointer) => ({ pointer, messageId: message?.id }) - ); + const pointers = extractImagePointers(parts).map((pointer) => ({ + pointer, + messageId: message?.id, + })); if (pointers.length === 0) continue; const at = message?.create_time ?? 0; if (!newest || at >= newest.at) newest = { pointers, at }; diff --git a/open-sse/executors/duckduckgo-web.ts b/open-sse/executors/duckduckgo-web.ts index 4a761373b1..72abad4f84 100644 --- a/open-sse/executors/duckduckgo-web.ts +++ b/open-sse/executors/duckduckgo-web.ts @@ -137,11 +137,6 @@ interface DuckDuckGoModelCapabilities { reasoningEffort: string | null; } -type DuckDuckGoChallengeResult = { - client_hashes?: unknown; - [key: string]: unknown; -}; - let durablePublicKey: JsonWebKey | null = null; function extractDuckDuckGoContent(data: unknown): string { diff --git a/open-sse/executors/duckduckgo-web/challenge.ts b/open-sse/executors/duckduckgo-web/challenge.ts index 4c3f3a6132..3c0159ba3a 100644 --- a/open-sse/executors/duckduckgo-web/challenge.ts +++ b/open-sse/executors/duckduckgo-web/challenge.ts @@ -102,6 +102,11 @@ export function sha256Base64(value: string): string { return createHash("sha256").update(value, "utf8").digest("base64"); } +type DuckDuckGoChallengeResult = { + client_hashes?: unknown; + [key: string]: unknown; +}; + export async function solveDuckDuckGoChallenge( challenge: string, userAgent: string diff --git a/src/shared/providers/webSessionCredentials.ts b/src/shared/providers/webSessionCredentials.ts index 5c89d7cab1..1c55c2382b 100644 --- a/src/shared/providers/webSessionCredentials.ts +++ b/src/shared/providers/webSessionCredentials.ts @@ -299,7 +299,7 @@ export const WEB_SESSION_CREDENTIAL_REQUIREMENTS = { hintFallback: "Open arena.ai, sign in, then copy the full Cookie header from a Network request. Include arena-auth-prod-v1.0 and arena-auth-prod-v1.1 (and further chunks if present), preferably with cf_clearance. Do not paste only the empty arena-auth-prod-v1 cookie. Optional: providerSpecificData.recaptchaV3Token if create-evaluation still returns 403.", }, - "promptql": { + promptql: { kind: "token", credentialName: "Bearer JWT (optional: projectId, session Cookie)", placeholder: "eyJ... (Authorization Bearer from prompt.ql.app)", @@ -317,7 +317,8 @@ export const WEB_SESSION_CREDENTIAL_REQUIREMENTS = { acceptsFullCookieHeader: true, storageKeys: ["cookie", "token", "access_token", "accessToken"], }, -} satisfies Record; +} satisfies Record & + Record; export function getWebSessionCredentialRequirement( providerId: unknown diff --git a/tests/unit/duckduckgo-challenge-split.test.ts b/tests/unit/duckduckgo-challenge-split.test.ts index cc4a7bd8a3..0ea9a98070 100644 --- a/tests/unit/duckduckgo-challenge-split.test.ts +++ b/tests/unit/duckduckgo-challenge-split.test.ts @@ -16,6 +16,7 @@ test("leaf hosts the solver and does not import the host", () => { const src = readFileSync(LEAF, "utf8"); assert.match(src, /export async function solveDuckDuckGoChallenge\b/); assert.match(src, /export function makeDuckDuckGoFeSignals\b/); + assert.match(src, /type DuckDuckGoChallengeResult\s*=/); assert.doesNotMatch(src, /from "\.\.\/duckduckgo-web\.ts"/); // The vm sandbox timeout must survive the move (security invariant). assert.match(src, /timeout/); @@ -24,6 +25,7 @@ test("leaf hosts the solver and does not import the host", () => { test("host imports the solver back from the leaf", () => { const host = readFileSync(HOST, "utf8"); assert.match(host, /from "\.\/duckduckgo-web\/challenge\.ts"/); + assert.doesNotMatch(host, /type DuckDuckGoChallengeResult\s*=/); }); test("makeDuckDuckGoFeSignals returns a base64 string", async () => {