Commit Graph

10 Commits

Author SHA1 Message Date
diegosouzapw
46932961d4 refactor(env): promote hardcoded URLs and circuit-breaker timeouts to environment
Centralizes a handful of hardcoded URLs, fetch timeouts, and circuit-breaker
constants behind opt-in environment variables. Behavior is unchanged when
the variables are unset because every call site keeps its current default.

- open-sse/services/usage.ts: extracts CROF_USAGE_URL,
  GEMINI_CLI_USAGE_URL, CODEWHISPERER_BASE_URL constants backed by
  OMNIROUTE_CROF_USAGE_URL, OMNIROUTE_GEMINI_CLI_USAGE_URL, and
  OMNIROUTE_CODEWHISPERER_BASE_URL. Lets operators redirect quota probes
  through corporate mirrors or a test fixture.
- open-sse/config/constants.ts: PROVIDER_PROFILES circuit-breaker
  thresholds and reset timeouts now honor OMNIROUTE_CIRCUIT_BREAKER_*
  env vars (oauth/api-key/local) with the same defaults as before.
- src/shared/utils/fetchTimeout.ts: DEFAULT_TIMEOUT_MS reads
  OMNIROUTE_DEFAULT_FETCH_TIMEOUT_MS (fallback 120000) so deployments can
  raise the global fallback without changing FETCH_TIMEOUT_MS semantics.
- open-sse/services/chatgptTlsClient.ts: DEFAULT_TIMEOUT_MS and
  HARD_TIMEOUT_GRACE_MS now honor OMNIROUTE_CHATGPT_TLS_TIMEOUT_MS and
  OMNIROUTE_CHATGPT_TLS_GRACE_MS (defaults 60000 / 10000).
- .env.example: documents the 11 new variables in the URLs and TIMEOUT
  sections.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 10:55:33 -03:00
diegosouzapw
0594b1d2ea fix(providers): correct pollinations requests and provider dashboard state
Update Pollinations request transformation to send the selected model
and stream flag so requests match the active endpoint behavior.

Align the ChatGPT TLS client with shared proxy resolution so dashboard
proxy context is honored before falling back to environment settings.
Also refresh provider display names across dashboard pages, correct the
Claude extra-usage toggle messaging and visual state, and mark
Pollinations as offering a free public endpoint.
2026-05-11 15:51:05 -03:00
Diego Rodrigues de Sa e Souza
3d75fb3fae Release v3.8.0 (#2073)
Integrated into release/v3.8.0
2026-05-10 00:55:06 -03:00
diegosouzapw
3c42c9aac3 fix(providers): resolve ChatGPT Web authentication failure by aligning TLS fingerprint User-Agent strings (#1925) 2026-05-04 02:03:10 -03:00
backryun
a16e47c593 fix(providers): refresh web client user agents (#1699)
Integrated release/v3.7.2 changes — refreshed web client user agents, env docs, Gemini OAuth fix
2026-04-28 02:41:19 -03:00
Payne
8a8fcc77a8 feat(chatgpt-web): image generation + edit (Open WebUI compatible) (#1607)
Integrated into release/v3.7.0
2026-04-25 23:51:37 -03:00
Payne
99331f777e chatgpt-web: address PR #1596 review feedback (#1597)
Integrated into release/v3.7.0. Thank you for the contribution @trader-payne!
2026-04-25 12:13:46 -03:00
Payne
35a1f6a529 chatgpt-web: address PR #1593 review round 2 (#1596)
Integrated into release/v3.7.0. Thank you for the contribution @trader-payne!
2026-04-25 11:54:23 -03:00
Payne
fc80a986f2 chatgpt-web: address PR #1593 review feedback
Round of fixes addressing the gemini-code-assist and chatgpt-codex review
comments on the initial PR.

## High priority

- **PoW solver no longer blocks the event loop** (gemini #1, #2). The 100k
  prekey solver and 500k proof-of-work solver were synchronous SHA3-512
  loops that pinned a CPU core for tens to hundreds of milliseconds per
  request. Both are now async and `await`-yield to the event loop every
  1000 iterations via setImmediate, so concurrent requests and I/O still
  get scheduled. Wall time is approximately the same; what changes is
  fairness, not throughput.

- **Real upstream streaming for stream=true requests** (codex #6). The
  conv call now passes `stream: true` through to the TLS client when the
  caller asked for streaming. The TLS client uses tls-client-node's
  streamOutputPath primitive to write the response body to a temp file
  as it arrives, and we tail that file as a ReadableStream so clients
  see chunks in real time instead of getting one buffered burst at the
  end. Also peeks the first 256 bytes — if the response starts with
  `{` it's almost certainly a JSON error envelope, so we wait for the
  full body and surface as a non-streaming error response.

## Medium priority

- **Per-cookie device id** (gemini #3). Replaced the single
  process-wide DEVICE_ID with a per-cookie SHA-256-derived UUID that's
  stable across requests for one connection but unique per cookie. This
  matches how the browser's persistent oai-did cookie behaves and
  avoids cross-account fingerprint sharing. Cache is bounded to 200
  entries with FIFO eviction.

- **Removed dead conv-cache code** (gemini #4). The convCache /
  convLookup / convStore trio (~70 LOC) was unused — conversationId is
  hard-pinned to null because Temporary Chat conversation_ids 404 on
  reuse. Deleted entirely; the comment explains why we don't persist.

- **No more console.log in the conv 4xx path** (gemini #5). Replaced
  with log?.warn so it respects the application's logging
  configuration.

- **Bound the warmup cache** (codex #7). The (cookie, accessToken) ->
  timestamp map was unbounded; long-running multi-user deployments
  with rotating tokens would grow it forever. Now capped at 200
  entries with FIFO eviction (Map iteration order = insertion order).

- **Honor abort signals in TLS fetch** (codex #8). tlsFetchChatGpt now
  checks options.signal before issuing the upstream call, after the
  call returns, and the streaming body listens for abort to stop
  tailing the temp file. tls-client-node's koffi binding can't cancel
  an in-flight request mid-call, but we no longer process / re-emit a
  response that the caller has already given up on.

## Tests

All 27 chatgpt-web tests still pass; updated several to find calls by
URL via findIndex rather than hardcoded indices, since the warmup
sequence (/me, /conversations, /models) and two-stage Sentinel
(prepare + chat-requirements) shifted positional offsets.

Manually verified end-to-end:
- Non-streaming completions
- Streaming completions (real-time chunks; SSE [DONE] terminator)
- Multi-turn with full history each turn (memory preserved correctly)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 13:32:43 +00:00
Payne
299793e788 feat: add ChatGPT Web (Plus/Pro) session provider
Adds a new chatgpt-web provider that routes through chatgpt.com's internal
backend-api using a Plus/Pro subscription session cookie, enabling access
to GPT-5.x models without an OpenAI API key.

Heavier than perplexity-web/grok-web because chatgpt.com layers more bot
protection — this PR builds out the full pipeline needed to look like a
real browser session.

## New executor: open-sse/executors/chatgpt-web.ts

Auth/request pipeline (per chat completion):
  1. exchangeSession()              GET /api/auth/session    cookie -> JWT (cached ~5min)
  2. fetchDpl()                     GET /                    scrape data-build + script src
  3. runSessionWarmup()             GET /backend-api/me, /conversations, /models
  4. POST /sentinel/chat-requirements/prepare   -> prepare_token
  5. POST /sentinel/chat-requirements           -> chat-requirements-token + PoW seed/diff
  6. solveProofOfWork()             SHA3-512 loop -> "gAAAAAB..." sentinel proof token
  7. POST /backend-api/f/conversation           with all sentinel headers
  8. parse SSE stream -> OpenAI chat.completion[.chunk] format

Notable details:
- 18-element prekey config matching chat2api/openai-sentinel (browser fingerprint
  values, U+2212 MINUS SIGN in `webdriver−false`). Thin shapes get escalated to
  mandatory Turnstile.
- Two-stage Sentinel handshake (/prepare + /chat-requirements) — sending only
  the prepare result returns a 403 "Unusual activity" response.
- `turnstile.required: true` from Sentinel is treated as advisory; the conv
  endpoint accepts requests without a Turnstile token as long as PoW + chat-
  requirements-token are valid. Optional bring-your-own Turnstile via
  `providerSpecificData.turnstileToken` for accounts that hard-require it.
- SSE parser tracks message_id and resets the accumulator on a new turn —
  chatgpt.com echoes prior assistant messages (with status finished_successfully)
  before sending the new turn.
- entity["...","value", ...] internal markup stripped from output (browser
  renders these client-side).
- Conversation-continuity cache disabled by default: we send
  history_and_training_disabled: true (Temporary Chat mode) and those
  conversation_ids expire too fast to reuse — re-using returned 404. Each
  request now sends conversation_id: null and replays full history, matching
  what Open WebUI and OpenAI-API-style clients send anyway.

## TLS impersonation: open-sse/services/chatgptTlsClient.ts

ChatGPT's Cloudflare config pins cf_clearance to JA3/JA4 TLS fingerprint +
HTTP/2 SETTINGS frame. Plain Node Undici fetch always returns
cf-mitigated: challenge regardless of cookies. The wrapper module loads
`tls-client-node` (Firefox 148 fingerprint) in native runtime mode (.so via
koffi) — managed mode spawns a sidecar that conflicts with OmniRoute's
global fetch proxy patch.

- Lazy singleton TLSClient with process exit hooks
- Streaming-capable (file tail) and non-streaming modes
- Test injection point: __setTlsFetchOverrideForTesting() lets unit tests mock
  the client without touching globalThis.fetch

## Provider wiring

- open-sse/executors/index.ts — register ChatGptWebExecutor with cgpt-web alias
- open-sse/config/providerRegistry.ts — registry entry, format=openai,
  authHeader=cookie, model gpt-5.3-instant
- src/shared/constants/providers.ts — WEB_COOKIE_PROVIDERS UI metadata
  (icon, color, authHint)
- src/lib/providers/validation.ts — validateChatGptWebProvider hits
  /api/auth/session via the TLS client, detects cf-mitigated/HTML responses
  and returns a clear "paste full Cookie line" hint instead of a generic
  "Invalid"
- next.config.mjs — mark tls-client-node, koffi, tough-cookie as external
  packages (Turbopack can't bundle the native .so)

## Cookie format

Validator and executor accept any of:
  - bare value:                       "eyJhbGc..."
  - unchunked cookie line:            "__Secure-next-auth.session-token=eyJ..."
  - chunked cookie line:              "__Secure-next-auth.session-token.0=...; __Secure-next-auth.session-token.1=..."
  - full DevTools Cookie header line: "Cookie: __Secure-next-auth.session-token.0=...; cf_clearance=...; ..."

NextAuth chunks the JWE when it exceeds 4KB; chunked cookies pass through
verbatim (NextAuth reassembles server-side). Recommend pasting the full
DevTools Cookie line so cf_clearance, __cf_bm, _cfuvid, _puid travel along —
without cf_clearance, Cloudflare blocks the request before NextAuth sees it.

## Tests

tests/unit/chatgpt-web.test.ts — 27 tests, all passing:
- Registration + alias resolution
- Token exchange (cookie -> Bearer flow)
- Token cache TTL
- Refreshed cookie surfaced via onCredentialsRefreshed callback
- Sentinel call ordering (session -> prepare -> chat-requirements -> conv)
- Sentinel chat-requirements-token forwarded on conv request
- PoW token has gAAAAAB prefix
- Turnstile.required: true does NOT block conv (passes through)
- Non-streaming chat.completion JSON
- Streaming SSE chunks ending with [DONE]
- Cumulative-parts diffing yields non-overlapping deltas
- Errors: 401 session, 403 sentinel, 429 conv rate-limit
- Empty messages -> 400 without any fetch
- Missing apiKey -> 401 without any fetch
- Cookie format: bare value, unchunked, chunked, "Cookie: ..." DevTools line
- Conversation continuity: each call starts a fresh conversation
- Browser-like headers on conv POST (UA, Origin, Sec-Fetch-Site, Accept)
- Payload shape (action, model=gpt-5-3, history_and_training_disabled)
- Provider registry contains chatgpt-web with gpt-5.3-instant model

Verification: typecheck:core clean, lint clean (no new warnings),
end-to-end manually verified across single-turn, multi-turn (memory
preserved), streaming, and Open WebUI-style sequential growing-history
flows.

## References

- bogdanfinn/tls-client (Go) — TLS impersonation upstream
- fatihkabakk/tls-client-node — Node bindings
- lanqian528/chat2api — Sentinel/PoW/prekey reference impl (Python)
- leetanshaj/openai-sentinel — Prekey config + SHA3-512 solver

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 13:04:02 +00:00