Skip to content

feat(gemini-web): expose image generation through /v1/images/generations (closes #10466) - #10494

Merged
diegosouzapw merged 10 commits into
diegosouzapw:release/v3.8.50from
Abhishek4512009:feat/gemini-web-image-generation
Aug 18, 2026
Merged

diegosouzapw merged 10 commits into
diegosouzapw:release/v3.8.50from
Abhishek4512009:feat/gemini-web-image-generation

Conversation

@Abhishek4512009

Copy link
Copy Markdown
Contributor

Summary

Adds a gemini-web image-generation path so a valid Gemini Web session can generate images (Nano Banana) through POST /v1/images/generations, following the existing chatgpt-web web-session precedent.

  • Registry: gemini-web image provider entry (format: "gemini-web", cookie auth, alias gweb) with the nano-banana-web model. The -web suffix is deliberate: the bare nano-banana id is owned by adobe-firefly (operator decision 2026-07-31, pinned by the cheaperinference-image-models guard), and parseImageModel's bare-model scan walks providers in insertion order — a bare id here would have stolen that resolution. A regression test pins this.
  • Executor (gemini-web.ts): new parseStreamResponseImages() extracts generated-image URLs from the StreamGenerate candidate extension block — inner[4][0][12][7][0], URL at entry[0][3][3] (handles both the string and list forms), dedupes across cumulative frames, upgrades to =s2048 full resolution, and deliberately skips web-search thumbnails at [12][1] so scraped images are never served as generated. Image mode (x_gemini_web_image_mode) captures every StreamGenerate frame (images can land in a later frame than the text), resolves on first image, and gets a 90s window. Chat mode is byte-for-byte unchanged — the original first-response capture path is preserved verbatim.
  • Handler (handlers/imageGeneration/providers/geminiWeb.ts): drives the executor in image mode with an explicit generation-directive prompt (the web UI otherwise answers with web-search images instead of generating), caps n at 4 (each n is a separate ~30-60s web turn), returns URLs or b64_json (downloads the public googleusercontent asset), and surfaces the assistant's refusal text in the 502 when no image was produced. Injectable executor + image fetcher for tests.
  • Dispatch: branch on format === "gemini-web" in handleImageGeneration.

Related Issues

Validation

Change type: provider (new image-generation capability for an existing web-cookie provider).

  • Focused unit suite: tests/unit/gemini-web-image-generation-10466.test.ts — 21 tests, all passing
  • Fixtures built from the documented StreamGenerate frame layout for generated images (corroborated by gpt4free's Gemini provider and HanaokaYuzu/Gemini-API's _parse_candidate): string + list URL forms, cumulative-frame dedupe, web-search-image exclusion, size-directive handling, malformed-line tolerance
  • Handler coverage: success (url + b64_json), refusal visibility, missing prompt/cookie, n-cap, executor error passthrough, sequential n>1
  • Registry wiring: gemini-web/nano-banana-web + gweb/ alias resolution, and the bare nano-banana → adobe-firefly regression guard
  • npx eslint on all touched files — clean (2 pre-existing any warnings in gemini-web.ts unchanged, verified against the unmodified file)
  • npx tsc -p open-sse/tsconfig.json — 0 errors
  • Adjacent regression suites all green: gemini-web (6 test files), chatgpt-web-image-silentdrop, image-generation-handler, image-generation-route, image-registry-gpt56, cheaperinference-image-models, adobe-firefly, freepik-image-handler, microsoft-designer-web, nanobanana-image-generation, image-generation-baseurl-3205 — 195 tests passing

Coverage Notes

  • The Playwright browser transport is covered indirectly: handler behavior is validated via the injected fake executor; the frame parser is validated against realistic captured-shape fixtures. A live browser round-trip against a real Gemini session is the remaining verification step (no live session was available in this environment at PR time) — happy to run it once a session cookie is configured.

Reviewer Notes

  • Protocol stability: the image frame layout is reverse-engineered (no official API), same category as the existing gemini-web chat path — behavior may change upstream. The layout is documented in the parser's docstring with its corroborating sources.
  • v1 scope: text-to-image only; image-to-image editing through the session (upload path) is not implemented.
  • Model id: nano-banana-web rather than bare nano-banana to avoid hijacking adobe-firefly's owned alias (see above + regression test).

user.email added 5 commits August 15, 2026 09:32
…oses diegosouzapw#10389)

Reverse-engineered access to the free, anonymous Cloudflare AI Playground:
chat runs over a PartySocket WebSocket speaking Cloudflare's cf_agent RPC
protocol with zero credentials (no account, no API key, no cookies). The
WS upgrade is gated on a browser-grade TLS fingerprint, so the executor
drives a headless Chromium via Playwright and speaks the protocol from
inside the page context.

- registry entry: cloudflare-playground (alias cfp), authType none,
  curated 20-model catalog (GLM 5.2, Kimi K2.7 Code, DeepSeek V4 Pro,
  gpt-oss-120B, Llama 3.3 70B, Qwen2.5 Coder 32B, ...) captured from the
  live getModels RPC (2026-08-15)
- executor: cf_agent frame stream -> OpenAI SSE translation, id-filtered
  parser (RPC done:true frames cannot kill the stream), in-band upstream
  errors mapped to HTTP 429/502, abort + timeout handling, clean errors
- noauth UI entry with reverse-engineered-endpoint notice
- tests: 12 unit tests using real captured frames (incl. the 3021
  rate-limit error) + fake transport; ESLint clean; open-sse typecheck clean
Bundlers with keepNames (esbuild/tsx, webpack) inject a __name() call into
serialized function bodies. page.evaluate(openPlaygroundSession) therefore
threw ReferenceError: __name is not defined in real browser sessions.
Define the helper on window before evaluating the session opener.
The standalone shim duplicated the executor's frame-parsing and transport
logic and is superseded by open-sse/executors/cloudflare-playground.ts.
Requested in PR diegosouzapw#10442 review.
…ons (closes diegosouzapw#10466)

Adds a gemini-web image-generation path following the chatgpt-web precedent:

- imageRegistry: gemini-web provider entry (format gemini-web, cookie auth)
  with the nano-banana-web model. The -web suffix keeps the bare
  nano-banana id owned by adobe-firefly (operator decision 2026-07-31).
- gemini-web executor: new parseStreamResponseImages() extracts generated
  image URLs from the StreamGenerate candidate extension block
  (inner[4][0][12][7][0], url at entry[0][3][3] — string or list form),
  dedupes cumulative frames, upgrades to =s2048, and deliberately skips
  web-search thumbnails at [12][1]. Image mode (x_gemini_web_image_mode)
  captures every StreamGenerate frame, resolves on first image, and gets
  a 90s window; chat mode is byte-for-byte unchanged.
- handlers/imageGeneration/providers/geminiWeb.ts: drives the executor in
  image mode with an explicit generation directive prompt (the web UI
  otherwise answers with web-search images), caps n at 4, returns URLs or
  b64_json (downloads the public googleusercontent asset), and surfaces
  refusal text when no image was produced.
- Dispatch branch on format gemini-web in handleImageGeneration.

Tests: 21 new tests with fixtures built from the documented frame layout
(string/list url forms, cumulative-frame dedupe, web-image exclusion,
size-directive handling, refusal visibility, n-cap, b64_json, registry
wiring incl. the bare nano-banana → adobe-firefly regression guard).
Adjacent suites: gemini-web (6 files), chatgpt-web image, image handler,
route, registry, adobe-firefly, freepik, designer — all green.
ESLint clean on touched files (2 pre-existing any warnings unchanged);
tsc -p open-sse 0 errors.
@diegosouzapw

Copy link
Copy Markdown
Owner

Revisão do PR #10494: encontrei três pontos importantes antes do merge. Em cloudflare-playground.ts:309-310, o ramo “Attention Required” retorna após lançar o Chromium sem chamar close(), o que pode acumular processos em cada bloqueio. No streaming, o timeout fecha o transporte e o finally emite apenas [DONE] (439-442, 529-537), fazendo respostas vazias/parciais parecerem concluídas; isso também contraria a regra de não engolir erros em SSE. Na imagem Gemini, o handler propaga o status do executor, mas o fallback de credenciais só tenta outra conta para HTTP 401 (geminiWeb.ts:123-145; imageCredentialRetry.ts:95-98), então sessões expiradas/bloqueadas que caem nos caminhos 400/500 não fazem fallback como exige a issue #10466. Também recomendo separar o Cloudflare Playground/#10389 deste PR para reduzir o escopo. Os testes unitários e o diff hygiene probe foram revisados; não foi possível executar uma rodada browser-backed no head do PR, portanto as claims estão marcadas como PLAUSIBLE.

user.email and others added 2 commits August 17, 2026 22:24
… accounts for gemini-web images

Addresses pre-merge review findings on diegosouzapw#10494 (closes diegosouzapw#10466):

- cloudflare-playground executor: close the launched browser on EVERY
  non-success start() path, including the detected Cloudflare "Attention
  Required" challenge branch (was leaking a Chromium process per blocked
  request).
- cloudflare-playground executor: a streaming chat timeout now emits an
  explicit timeout_error SSE chunk before [DONE] instead of silently
  completing, so a client can no longer mistake an empty/partial timed-out
  stream for a successful answer. Timeout duration is now injectable for
  deterministic tests.
- gemini-web image handler + imageCredentialRetry: classify the underlying
  GeminiWebExecutor's expired/blocked-session failure modes (400/500, per
  its own Playwright timeout/catch-all branches) as retryable, so
  executeImageWithCredentialFallback advances to the next eligible account
  instead of only doing so on a plain 401.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
…i-web-image-generation

Resolves 51 conflicts, all in auto-generated/regenerated artifacts (provider
count mirrors in docs/i18n/*/llm.txt, docs/reference/PROVIDER_REFERENCE.md,
README.md/AGENTS.md/llm.txt/package.json provider-count text, and 4 static
SVG diagrams) — none in this PR's actual feature/fix code, which merged
cleanly. Resolution took the base's more current content for every
conflicted auto-generated file, then regenerated docs/reference/PROVIDER_REFERENCE.md
(`npm run gen:provider-reference`) and hand-updated the remaining
provider-count mentions (AGENTS.md, llm.txt, package.json description, and
the 4 SVG diagrams' embedded "341 providers" text) from 341 -> 342 to match
the live catalog after this branch's Cloudflare Playground provider addition.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
@diegosouzapw

Copy link
Copy Markdown
Owner

Pushed the 3 mandatory pre-merge fixes from review:

  1. Browser/transport leak (cloudflare-playground.ts): the detected-Cloudflare-challenge branch now closes the launched browser on every non-success start() path (was only closed in the catch path before). Added a regression test asserting close() is called.
  2. Streaming timeout misreported as success (cloudflare-playground.ts): a server-side chat timeout now emits an explicit timeout_error SSE chunk before [DONE] instead of silently completing. Added tests for both an empty-timeout stream and a partial-then-timeout stream.
  3. Image-account fallback gap (geminiWeb.ts + imageCredentialRetry.ts): the underlying GeminiWebExecutor's expired/blocked-session failure modes (400/500, from its own Playwright timeout/catch-all branches) are now classified as retryable, so executeImageWithCredentialFallback advances to the next eligible account instead of only doing so on a plain 401. Added a multi-account regression test and an invalid-session test driving the real executor's actual status code.

Also merged current release/v3.8.50 into this branch — the PR had drifted ~100 commits behind (it's built on top of the still-open Cloudflare Playground PR #10442, so both feature sets travel together here per the existing bundling). All 51 merge conflicts were in auto-generated/regenerated artifacts (provider-count mirrors across docs/i18n/*/llm.txt, docs/reference/PROVIDER_REFERENCE.md, README.md/AGENTS.md/llm.txt/package.json, and 4 static SVG diagrams) — none in this PR's feature/fix code, which merged cleanly. Regenerated PROVIDER_REFERENCE.md via npm run gen:provider-reference and hand-updated the remaining provider-count mentions (341 → 342) to match the live catalog after this branch's Cloudflare Playground addition.

⚠️ base-red inherited: #9985 — typecheck:core/dashboard-typecheck now surface open-sse/services/compression/engines/omniglyphAdapter.ts TS2339, confirmed byte-identical to the current release/v3.8.50 tip (not touched by this branch) — a pre-existing base defect, not introduced here.

Full validation run: typecheck:core (1 pre-existing base-red, unrelated to this PR), ESLint clean on touched files, check-complexity/check-cognitive-complexity/check-test-discovery/check-dashboard-typecheck all within their ratchet baselines, check-changelog-integrity now clean post-merge. New/updated tests (19 across the two touched suites) all pass. One pre-existing, out-of-scope finding not touched: open-sse/config/imageRegistry.ts is 1017 lines (cap 1000) — from this PR's original diff, not the review findings above.

…> 342)

The previous merge commit resolved all 51 auto-generated-file conflicts by
taking release/v3.8.50's content, which still said 341 providers. Merging in
this branch's Cloudflare Playground provider brings the live catalog to 342,
so npm run check:docs-counts-sync now flags stale claims. Fix:

- docs/reference/PROVIDER_REFERENCE.md: regenerated via
  `npm run gen:provider-reference`.
- README.md/AGENTS.md/llm.txt/package.json description: 341 -> 342.
- docs/diagrams/{readme-hero,promise-pillars,comparison-table,cli-terminal}.svg:
  341 -> 342 in the embedded "NNN providers" text (targeted replace, matched
  against the exact pattern check-docs-counts-sync.mjs validates).

check:docs-counts-sync and check:changelog-integrity are both clean after
this commit.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
diegosouzapw pushed a commit that referenced this pull request Aug 18, 2026
…owth

Three independent, already-approved provider PRs (#10542 aihorde,
#10494 gemini-web image, #10594 freepik/magnific) boarded together in
the 2026-08-18 merge-train each add a small, additive registry entry
to open-sse/config/imageRegistry.ts. None crosses the 1000-line cap
alone; combined they push it from 996 to 1019. Owner-authorized
blanket rebaseline approval for this merge batch.
user.email and others added 2 commits August 18, 2026 09:08
Used by open-sse/executors/cloudflare-playground.ts but missing from
.env.example and docs/reference/ENVIRONMENT.md, caught by the
env-doc-sync gate when combined with other PRs in the release
merge-train.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
…i-web-image-generation

# Conflicts:
#	AGENTS.md
#	docs/diagrams/cli-terminal.svg
#	docs/diagrams/comparison-table.svg
#	docs/diagrams/promise-pillars.svg
#	docs/diagrams/readme-hero.svg
#	docs/reference/PROVIDER_REFERENCE.md
#	llm.txt
#	package.json
@diegosouzapw
diegosouzapw merged commit 885cd8c into diegosouzapw:release/v3.8.50 Aug 18, 2026
1 of 3 checks passed
HouMinXi pushed a commit to HouMinXi/OmniRoute that referenced this pull request Aug 20, 2026
…ons (closes diegosouzapw#10466) (diegosouzapw#10494)

* feat(providers): add Cloudflare AI Playground as No Auth provider (closes diegosouzapw#10389)

Reverse-engineered access to the free, anonymous Cloudflare AI Playground:
chat runs over a PartySocket WebSocket speaking Cloudflare's cf_agent RPC
protocol with zero credentials (no account, no API key, no cookies). The
WS upgrade is gated on a browser-grade TLS fingerprint, so the executor
drives a headless Chromium via Playwright and speaks the protocol from
inside the page context.

- registry entry: cloudflare-playground (alias cfp), authType none,
  curated 20-model catalog (GLM 5.2, Kimi K2.7 Code, DeepSeek V4 Pro,
  gpt-oss-120B, Llama 3.3 70B, Qwen2.5 Coder 32B, ...) captured from the
  live getModels RPC (2026-08-15)
- executor: cf_agent frame stream -> OpenAI SSE translation, id-filtered
  parser (RPC done:true frames cannot kill the stream), in-band upstream
  errors mapped to HTTP 429/502, abort + timeout handling, clean errors
- noauth UI entry with reverse-engineered-endpoint notice
- tests: 12 unit tests using real captured frames (incl. the 3021
  rate-limit error) + fake transport; ESLint clean; open-sse typecheck clean

* fix(providers): define __name helper in page context before evaluate

Bundlers with keepNames (esbuild/tsx, webpack) inject a __name() call into
serialized function bodies. page.evaluate(openPlaygroundSession) therefore
threw ReferenceError: __name is not defined in real browser sessions.
Define the helper on window before evaluating the session opener.

* fix(providers): sync docs counts, golden snapshots and add reasoning_content support for cloudflare-playground

* chore: remove ad-hoc cfp-shim debug script per review feedback

The standalone shim duplicated the executor's frame-parsing and transport
logic and is superseded by open-sse/executors/cloudflare-playground.ts.
Requested in PR diegosouzapw#10442 review.

* feat(gemini-web): expose image generation through /v1/images/generations (closes diegosouzapw#10466)

Adds a gemini-web image-generation path following the chatgpt-web precedent:

- imageRegistry: gemini-web provider entry (format gemini-web, cookie auth)
  with the nano-banana-web model. The -web suffix keeps the bare
  nano-banana id owned by adobe-firefly (operator decision 2026-07-31).
- gemini-web executor: new parseStreamResponseImages() extracts generated
  image URLs from the StreamGenerate candidate extension block
  (inner[4][0][12][7][0], url at entry[0][3][3] — string or list form),
  dedupes cumulative frames, upgrades to =s2048, and deliberately skips
  web-search thumbnails at [12][1]. Image mode (x_gemini_web_image_mode)
  captures every StreamGenerate frame, resolves on first image, and gets
  a 90s window; chat mode is byte-for-byte unchanged.
- handlers/imageGeneration/providers/geminiWeb.ts: drives the executor in
  image mode with an explicit generation directive prompt (the web UI
  otherwise answers with web-search images), caps n at 4, returns URLs or
  b64_json (downloads the public googleusercontent asset), and surfaces
  refusal text when no image was produced.
- Dispatch branch on format gemini-web in handleImageGeneration.

Tests: 21 new tests with fixtures built from the documented frame layout
(string/list url forms, cumulative-frame dedupe, web-image exclusion,
size-directive handling, refusal visibility, n-cap, b64_json, registry
wiring incl. the bare nano-banana → adobe-firefly regression guard).
Adjacent suites: gemini-web (6 files), chatgpt-web image, image handler,
route, registry, adobe-firefly, freepik, designer — all green.
ESLint clean on touched files (2 pre-existing any warnings unchanged);
tsc -p open-sse 0 errors.

* fix(media): close browser leak, surface timeout errors, and fall back accounts for gemini-web images

Addresses pre-merge review findings on diegosouzapw#10494 (closes diegosouzapw#10466):

- cloudflare-playground executor: close the launched browser on EVERY
  non-success start() path, including the detected Cloudflare "Attention
  Required" challenge branch (was leaking a Chromium process per blocked
  request).
- cloudflare-playground executor: a streaming chat timeout now emits an
  explicit timeout_error SSE chunk before [DONE] instead of silently
  completing, so a client can no longer mistake an empty/partial timed-out
  stream for a successful answer. Timeout duration is now injectable for
  deterministic tests.
- gemini-web image handler + imageCredentialRetry: classify the underlying
  GeminiWebExecutor's expired/blocked-session failure modes (400/500, per
  its own Playwright timeout/catch-all branches) as retryable, so
  executeImageWithCredentialFallback advances to the next eligible account
  instead of only doing so on a plain 401.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* docs: regenerate provider counts after merging release/v3.8.50 (341 -> 342)

The previous merge commit resolved all 51 auto-generated-file conflicts by
taking release/v3.8.50's content, which still said 341 providers. Merging in
this branch's Cloudflare Playground provider brings the live catalog to 342,
so npm run check:docs-counts-sync now flags stale claims. Fix:

- docs/reference/PROVIDER_REFERENCE.md: regenerated via
  `npm run gen:provider-reference`.
- README.md/AGENTS.md/llm.txt/package.json description: 341 -> 342.
- docs/diagrams/{readme-hero,promise-pillars,comparison-table,cli-terminal}.svg:
  341 -> 342 in the embedded "NNN providers" text (targeted replace, matched
  against the exact pattern check-docs-counts-sync.mjs validates).

check:docs-counts-sync and check:changelog-integrity are both clean after
this commit.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* docs(env): document CLOUDFLARE_PLAYGROUND_CHROME_PATH

Used by open-sse/executors/cloudflare-playground.ts but missing from
.env.example and docs/reference/ENVIRONMENT.md, caught by the
env-doc-sync gate when combined with other PRs in the release
merge-train.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: user.email <freakymustard67@gmail.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
giauphan pushed a commit to giauphan/OmniRoute that referenced this pull request Aug 20, 2026
…ons (closes diegosouzapw#10466) (diegosouzapw#10494)

* feat(providers): add Cloudflare AI Playground as No Auth provider (closes diegosouzapw#10389)

Reverse-engineered access to the free, anonymous Cloudflare AI Playground:
chat runs over a PartySocket WebSocket speaking Cloudflare's cf_agent RPC
protocol with zero credentials (no account, no API key, no cookies). The
WS upgrade is gated on a browser-grade TLS fingerprint, so the executor
drives a headless Chromium via Playwright and speaks the protocol from
inside the page context.

- registry entry: cloudflare-playground (alias cfp), authType none,
  curated 20-model catalog (GLM 5.2, Kimi K2.7 Code, DeepSeek V4 Pro,
  gpt-oss-120B, Llama 3.3 70B, Qwen2.5 Coder 32B, ...) captured from the
  live getModels RPC (2026-08-15)
- executor: cf_agent frame stream -> OpenAI SSE translation, id-filtered
  parser (RPC done:true frames cannot kill the stream), in-band upstream
  errors mapped to HTTP 429/502, abort + timeout handling, clean errors
- noauth UI entry with reverse-engineered-endpoint notice
- tests: 12 unit tests using real captured frames (incl. the 3021
  rate-limit error) + fake transport; ESLint clean; open-sse typecheck clean

* fix(providers): define __name helper in page context before evaluate

Bundlers with keepNames (esbuild/tsx, webpack) inject a __name() call into
serialized function bodies. page.evaluate(openPlaygroundSession) therefore
threw ReferenceError: __name is not defined in real browser sessions.
Define the helper on window before evaluating the session opener.

* fix(providers): sync docs counts, golden snapshots and add reasoning_content support for cloudflare-playground

* chore: remove ad-hoc cfp-shim debug script per review feedback

The standalone shim duplicated the executor's frame-parsing and transport
logic and is superseded by open-sse/executors/cloudflare-playground.ts.
Requested in PR diegosouzapw#10442 review.

* feat(gemini-web): expose image generation through /v1/images/generations (closes diegosouzapw#10466)

Adds a gemini-web image-generation path following the chatgpt-web precedent:

- imageRegistry: gemini-web provider entry (format gemini-web, cookie auth)
  with the nano-banana-web model. The -web suffix keeps the bare
  nano-banana id owned by adobe-firefly (operator decision 2026-07-31).
- gemini-web executor: new parseStreamResponseImages() extracts generated
  image URLs from the StreamGenerate candidate extension block
  (inner[4][0][12][7][0], url at entry[0][3][3] — string or list form),
  dedupes cumulative frames, upgrades to =s2048, and deliberately skips
  web-search thumbnails at [12][1]. Image mode (x_gemini_web_image_mode)
  captures every StreamGenerate frame, resolves on first image, and gets
  a 90s window; chat mode is byte-for-byte unchanged.
- handlers/imageGeneration/providers/geminiWeb.ts: drives the executor in
  image mode with an explicit generation directive prompt (the web UI
  otherwise answers with web-search images), caps n at 4, returns URLs or
  b64_json (downloads the public googleusercontent asset), and surfaces
  refusal text when no image was produced.
- Dispatch branch on format gemini-web in handleImageGeneration.

Tests: 21 new tests with fixtures built from the documented frame layout
(string/list url forms, cumulative-frame dedupe, web-image exclusion,
size-directive handling, refusal visibility, n-cap, b64_json, registry
wiring incl. the bare nano-banana → adobe-firefly regression guard).
Adjacent suites: gemini-web (6 files), chatgpt-web image, image handler,
route, registry, adobe-firefly, freepik, designer — all green.
ESLint clean on touched files (2 pre-existing any warnings unchanged);
tsc -p open-sse 0 errors.

* fix(media): close browser leak, surface timeout errors, and fall back accounts for gemini-web images

Addresses pre-merge review findings on diegosouzapw#10494 (closes diegosouzapw#10466):

- cloudflare-playground executor: close the launched browser on EVERY
  non-success start() path, including the detected Cloudflare "Attention
  Required" challenge branch (was leaking a Chromium process per blocked
  request).
- cloudflare-playground executor: a streaming chat timeout now emits an
  explicit timeout_error SSE chunk before [DONE] instead of silently
  completing, so a client can no longer mistake an empty/partial timed-out
  stream for a successful answer. Timeout duration is now injectable for
  deterministic tests.
- gemini-web image handler + imageCredentialRetry: classify the underlying
  GeminiWebExecutor's expired/blocked-session failure modes (400/500, per
  its own Playwright timeout/catch-all branches) as retryable, so
  executeImageWithCredentialFallback advances to the next eligible account
  instead of only doing so on a plain 401.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* docs: regenerate provider counts after merging release/v3.8.50 (341 -> 342)

The previous merge commit resolved all 51 auto-generated-file conflicts by
taking release/v3.8.50's content, which still said 341 providers. Merging in
this branch's Cloudflare Playground provider brings the live catalog to 342,
so npm run check:docs-counts-sync now flags stale claims. Fix:

- docs/reference/PROVIDER_REFERENCE.md: regenerated via
  `npm run gen:provider-reference`.
- README.md/AGENTS.md/llm.txt/package.json description: 341 -> 342.
- docs/diagrams/{readme-hero,promise-pillars,comparison-table,cli-terminal}.svg:
  341 -> 342 in the embedded "NNN providers" text (targeted replace, matched
  against the exact pattern check-docs-counts-sync.mjs validates).

check:docs-counts-sync and check:changelog-integrity are both clean after
this commit.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* docs(env): document CLOUDFLARE_PLAYGROUND_CHROME_PATH

Used by open-sse/executors/cloudflare-playground.ts but missing from
.env.example and docs/reference/ENVIRONMENT.md, caught by the
env-doc-sync gate when combined with other PRs in the release
merge-train.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: user.email <freakymustard67@gmail.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…owth

Three independent, already-approved provider PRs (diegosouzapw#10542 aihorde,
diegosouzapw#10494 gemini-web image, diegosouzapw#10594 freepik/magnific) boarded together in
the 2026-08-18 merge-train each add a small, additive registry entry
to open-sse/config/imageRegistry.ts. None crosses the 1000-line cap
alone; combined they push it from 996 to 1019. Owner-authorized
blanket rebaseline approval for this merge batch.
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…ons (closes diegosouzapw#10466) (diegosouzapw#10494)

* feat(providers): add Cloudflare AI Playground as No Auth provider (closes diegosouzapw#10389)

Reverse-engineered access to the free, anonymous Cloudflare AI Playground:
chat runs over a PartySocket WebSocket speaking Cloudflare's cf_agent RPC
protocol with zero credentials (no account, no API key, no cookies). The
WS upgrade is gated on a browser-grade TLS fingerprint, so the executor
drives a headless Chromium via Playwright and speaks the protocol from
inside the page context.

- registry entry: cloudflare-playground (alias cfp), authType none,
  curated 20-model catalog (GLM 5.2, Kimi K2.7 Code, DeepSeek V4 Pro,
  gpt-oss-120B, Llama 3.3 70B, Qwen2.5 Coder 32B, ...) captured from the
  live getModels RPC (2026-08-15)
- executor: cf_agent frame stream -> OpenAI SSE translation, id-filtered
  parser (RPC done:true frames cannot kill the stream), in-band upstream
  errors mapped to HTTP 429/502, abort + timeout handling, clean errors
- noauth UI entry with reverse-engineered-endpoint notice
- tests: 12 unit tests using real captured frames (incl. the 3021
  rate-limit error) + fake transport; ESLint clean; open-sse typecheck clean

* fix(providers): define __name helper in page context before evaluate

Bundlers with keepNames (esbuild/tsx, webpack) inject a __name() call into
serialized function bodies. page.evaluate(openPlaygroundSession) therefore
threw ReferenceError: __name is not defined in real browser sessions.
Define the helper on window before evaluating the session opener.

* fix(providers): sync docs counts, golden snapshots and add reasoning_content support for cloudflare-playground

* chore: remove ad-hoc cfp-shim debug script per review feedback

The standalone shim duplicated the executor's frame-parsing and transport
logic and is superseded by open-sse/executors/cloudflare-playground.ts.
Requested in PR diegosouzapw#10442 review.

* feat(gemini-web): expose image generation through /v1/images/generations (closes diegosouzapw#10466)

Adds a gemini-web image-generation path following the chatgpt-web precedent:

- imageRegistry: gemini-web provider entry (format gemini-web, cookie auth)
  with the nano-banana-web model. The -web suffix keeps the bare
  nano-banana id owned by adobe-firefly (operator decision 2026-07-31).
- gemini-web executor: new parseStreamResponseImages() extracts generated
  image URLs from the StreamGenerate candidate extension block
  (inner[4][0][12][7][0], url at entry[0][3][3] — string or list form),
  dedupes cumulative frames, upgrades to =s2048, and deliberately skips
  web-search thumbnails at [12][1]. Image mode (x_gemini_web_image_mode)
  captures every StreamGenerate frame, resolves on first image, and gets
  a 90s window; chat mode is byte-for-byte unchanged.
- handlers/imageGeneration/providers/geminiWeb.ts: drives the executor in
  image mode with an explicit generation directive prompt (the web UI
  otherwise answers with web-search images), caps n at 4, returns URLs or
  b64_json (downloads the public googleusercontent asset), and surfaces
  refusal text when no image was produced.
- Dispatch branch on format gemini-web in handleImageGeneration.

Tests: 21 new tests with fixtures built from the documented frame layout
(string/list url forms, cumulative-frame dedupe, web-image exclusion,
size-directive handling, refusal visibility, n-cap, b64_json, registry
wiring incl. the bare nano-banana → adobe-firefly regression guard).
Adjacent suites: gemini-web (6 files), chatgpt-web image, image handler,
route, registry, adobe-firefly, freepik, designer — all green.
ESLint clean on touched files (2 pre-existing any warnings unchanged);
tsc -p open-sse 0 errors.

* fix(media): close browser leak, surface timeout errors, and fall back accounts for gemini-web images

Addresses pre-merge review findings on diegosouzapw#10494 (closes diegosouzapw#10466):

- cloudflare-playground executor: close the launched browser on EVERY
  non-success start() path, including the detected Cloudflare "Attention
  Required" challenge branch (was leaking a Chromium process per blocked
  request).
- cloudflare-playground executor: a streaming chat timeout now emits an
  explicit timeout_error SSE chunk before [DONE] instead of silently
  completing, so a client can no longer mistake an empty/partial timed-out
  stream for a successful answer. Timeout duration is now injectable for
  deterministic tests.
- gemini-web image handler + imageCredentialRetry: classify the underlying
  GeminiWebExecutor's expired/blocked-session failure modes (400/500, per
  its own Playwright timeout/catch-all branches) as retryable, so
  executeImageWithCredentialFallback advances to the next eligible account
  instead of only doing so on a plain 401.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* docs: regenerate provider counts after merging release/v3.8.50 (341 -> 342)

The previous merge commit resolved all 51 auto-generated-file conflicts by
taking release/v3.8.50's content, which still said 341 providers. Merging in
this branch's Cloudflare Playground provider brings the live catalog to 342,
so npm run check:docs-counts-sync now flags stale claims. Fix:

- docs/reference/PROVIDER_REFERENCE.md: regenerated via
  `npm run gen:provider-reference`.
- README.md/AGENTS.md/llm.txt/package.json description: 341 -> 342.
- docs/diagrams/{readme-hero,promise-pillars,comparison-table,cli-terminal}.svg:
  341 -> 342 in the embedded "NNN providers" text (targeted replace, matched
  against the exact pattern check-docs-counts-sync.mjs validates).

check:docs-counts-sync and check:changelog-integrity are both clean after
this commit.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* docs(env): document CLOUDFLARE_PLAYGROUND_CHROME_PATH

Used by open-sse/executors/cloudflare-playground.ts but missing from
.env.example and docs/reference/ENVIRONMENT.md, caught by the
env-doc-sync gate when combined with other PRs in the release
merge-train.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: user.email <freakymustard67@gmail.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(gemini-web): expose image generation through /v1/images/generations

2 participants