Skip to content

fix(extension): make generation work on flow.google.com (captcha, tabs, batchexecute RPCs) - #13

Open
santoshray02 wants to merge 5 commits into
kodelyx:mainfrom
santoshray02:fix/extension-captcha-tab-and-token-refresh
Open

santoshray02 wants to merge 5 commits into
kodelyx:mainfrom
santoshray02:fix/extension-captcha-tab-and-token-refresh

Conversation

@santoshray02

@santoshray02 santoshray02 commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Generation had been failing for a week with CAPTCHA_FAILED: CONTENT_TIMEOUT while /health kept reporting healthy. Three separate causes, all fallout from the move from labs.google/fx/tools/flow to flow.google.com:

  1. The Flow bearer is only observable during the labs.googleflow.google.com handoff. Reloading a flow.google.com tab never re-captures it, so the token was never obtained (has_flow_key: false) and could never refresh. Token refresh now drives an extension-owned tab through TOKEN_URL.
  2. reCAPTCHA Enterprise is only loaded on /project/<id> pages, never on the home page the old FLOW_URL now redirects to. On-demand tabs open the request's projectId (or the last project page seen), and project tabs are preferred over other Flow tabs.
  3. The first tab matching a Flow URL was used blindly. A tab with a dead bridge (opened before an extension reload, or one that never loaded injected.js) swallowed GET_CAPTCHA for 25 s. Tabs are now pinged (PING_BRIDGEFLOW_AGENT_PING/PONG) before use and skipped if they do not answer.

Hardening found necessary while debugging

  • Every await on the tab-lookup path is bounded (withTimeout) so one Chrome API call that never settles cannot park the shared getOrOpenFlowTab promise and silently stall every later request.
  • GET_CAPTCHA is re-dispatched until injected.js answers (it loads async; a first dispatch could be lost); injected.js dedups by requestId and caps grecaptcha.execute at 15 s.
  • The Google API fetch and callback delivery carry timeouts.
  • The last 200 [Flow Agent] console lines persist to chrome.storage.local.debugLog so stalls can be diagnosed after the fact.

Update 2026-09-18: generation now runs through flow.google.com batchexecute RPCs (536ae3a)

Since the 2026-09-11 rollout of the new Angular frontend, the fixes above could not help on this account: the page never calls aisandbox-pa any more, so there is no bearer to capture, and aisandbox-pa rejects every auth the extension can present (cookie SAPISIDHASH400 Origin doesn't match Host for XD3, from both flow.google.com and a rewritten labs.google origin — see #16 for that attempt).

The last commit replays the page's own RPCs from inside a Flow tab, where cookies, the CSRF token (WIZ_global_data.SNlM0e) and origin all line up:

RPC Role
ogiZ0b generate image (synchronous, ~25 s)
YhhmEf submit text-to-video
jwpduf poll status (6 queued → 2 running → 3 done)
as29s record with the signed flow-content.google URL
nzlxg credits

Results are mapped back into the aisandbox-pa REST shapes, so nothing in the Python server changes. Payloads and enums were captured from real sessions; image aspect enums were confirmed by generating one image per value and reading the returned dimensions, the portrait video variant via an aborted submit at $0.

Because the agent only routes work to clients that reported a token, the extension now proves the cookie session with a real nzlxg call and reports a flow-session marker in its place. The marker ages out like a token and is re-proven; it is never sent to aisandbox-pa as a bearer — endpoints without an RPC mapping fail fast with NOT_SUPPORTED_ON_FLOW_GOOGLE_COM instead of a misleading 401. The labs.google handoff capture stays as a fallback for accounts still on the old frontend.

Not covered yet: image-to-video, start/end frames, reference images and upsampling (separate rpc ids, e.g. eb1hJf for i2v) — these return NOT_SUPPORTED_ON_FLOW_GOOGLE_COM.

Verification

  • Measured on a live Pro account: grecaptcha.enterprise is present on flow.google.com/project/… and absent on flow.google.com/ (0 recaptcha scripts after 20 s); the bearer was captured only via the labs.google handoff.
  • End to end (before the frontend switch): a 4 s text-to-video clip generated in 88 s through the extension (credits 1050 → 1043, 1280×720 H.264/AAC).
  • End to end on the new frontend (2026-09-18, 536ae3a): /v1/images/generations 1024×1024 in 26 s with the requested aspect honoured; /v1/videos/generations 1280×720 landscape and 720×1280 portrait 8 s H.264+AAC clips in ~60 s each; /v1/credits returns the real balance.
  • node --check clean on background.js, content.js, injected.js; tests/test_extension_flow_urls.py (7 tests) passes.

Related: #10 (captcha/host findings), follows #11, supersedes the REST/SAPISIDHASH approach in #16.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GkWggBWEKrNTR4B5opZ3bo

김우주 and others added 4 commits September 7, 2026 16:50
fix: recognize current Flow host and preserve upload failures
Generation had been failing for a week with CAPTCHA_FAILED: CONTENT_TIMEOUT
even though /health reported healthy. Three separate causes, all from the
move from labs.google/fx/tools/flow to flow.google.com:

- The Flow bearer is only observable during the labs.google -> flow.google.com
  handoff. Reloading a flow.google.com tab never re-captures it, so the
  token was never obtained (has_flow_key false) and could never refresh.
  Token refresh now drives an extension-owned tab through TOKEN_URL.
- reCAPTCHA Enterprise is only loaded on /project/<id> pages, never on the
  home page the old FLOW_URL now redirects to. On-demand tabs open the
  request's projectId (or the last project page seen), and project tabs
  are preferred over other Flow tabs.
- The first tab matching a Flow URL was used blindly. A tab with a dead
  bridge (opened before an extension reload, or never loaded injected.js)
  swallowed GET_CAPTCHA for 25s. Tabs are now pinged (PING_BRIDGE ->
  FLOW_AGENT_PING/PONG) before use and skipped if they do not answer.

Hardening found necessary while debugging:
- Every await on the tab-lookup path is bounded (withTimeout) so one
  Chrome API call that never settles cannot park the shared
  getOrOpenFlowTab promise and silently stall every later request.
- GET_CAPTCHA is re-dispatched until injected.js answers (it loads async;
  a first dispatch could be lost); injected.js dedups by requestId and
  caps grecaptcha.execute at 15s.
- The Google API fetch and callback delivery carry timeouts.
- The last 200 '[Flow Agent]' console lines persist to
  chrome.storage.local.debugLog so stalls can be diagnosed after the fact.

Verified end to end: a 4s text-to-video clip generated in 88s through the
extension (credits 1050 -> 1043).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GkWggBWEKrNTR4B5opZ3bo
@bmbcompanybrazil-maker

Copy link
Copy Markdown

Thanks for this fix, it is what made flow.google.com work for us. One follow-up on top of it: after the extension closes its own work tab, the next request can adopt a user-owned flow.google.com/ home tab and captcha then fails with grecaptcha not available. Stacked fix (targets this PR's branch): santoshray02#1

…atchexecute RPCs

Google's new Flow frontend never calls aisandbox-pa, and that endpoint
rejects every auth this extension can present: there is no ya29 bearer to
capture, and SAPISIDHASH is refused with "Origin doesn't match Host for XD3"
from both flow.google.com and a rewritten labs.google origin. Since the
2026-09-11 rollout every generation on this account failed, and the tab /
token-refresh fixes in this branch could not help because there was no
token to refresh.

Replay the page's own RPCs from inside a Flow tab instead, where cookies,
the CSRF token (WIZ_global_data.SNlM0e) and origin all line up:

  ogiZ0b  generate image (sync, ~25 s)
  YhhmEf  submit text-to-video
  jwpduf  poll status (6 queued, 2 running, 3 done)
  as29s   record with the signed flow-content.google URL
  nzlxg   credits

Results are mapped back into the aisandbox-pa REST shapes so the Python
side (generate_image, generate_video, poll_status, download_*) is untouched.
Payloads and enums were captured from real sessions on 2026-09-18; the image
aspect enums were confirmed by generating one image per value and reading
the returned dimensions, the portrait video variant (enum 1, model key
suffix _portrait) via an aborted submit at $0.

There is no bearer to report any more, and the agent only routes work to
clients that reported one, so the extension now proves the cookie session
with a real nzlxg call and reports a FLOW_SESSION_KEY marker in its place.
The marker ages out like a token and is re-proven; it is never sent to
aisandbox-pa as a bearer — endpoints without an RPC mapping fail fast with
NOT_SUPPORTED_ON_FLOW_GOOGLE_COM instead of a misleading 401. The labs.google
handoff capture stays as a fallback for accounts still on the old frontend.

Verified live: /v1/images/generations 1024x1024 in 26 s (the requested aspect
is honoured, which composer-driven automation could not do), /v1/videos/
generations 1280x720 landscape and 720x1280 portrait 8 s H.264+AAC clips in
~60 s, /v1/credits returns the real balance.

Not covered yet: image-to-video, frames, reference images and upsampling
(separate rpc ids, e.g. eb1hJf for i2v).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@santoshray02 santoshray02 changed the title fix(extension): make captcha and token capture work on flow.google.com fix(extension): make generation work on flow.google.com (captcha, tabs, batchexecute RPCs) Sep 18, 2026
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.

3 participants