fix(extension): make generation work on flow.google.com (captcha, tabs, batchexecute RPCs) - #13
Open
santoshray02 wants to merge 5 commits into
Conversation
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
Open
|
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 |
…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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Generation had been failing for a week with
CAPTCHA_FAILED: CONTENT_TIMEOUTwhile/healthkept reportinghealthy. Three separate causes, all fallout from the move fromlabs.google/fx/tools/flowtoflow.google.com:labs.google→flow.google.comhandoff. Reloading aflow.google.comtab 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 throughTOKEN_URL./project/<id>pages, never on the home page the oldFLOW_URLnow redirects to. On-demand tabs open the request'sprojectId(or the last project page seen), and project tabs are preferred over other Flow tabs.injected.js) swallowedGET_CAPTCHAfor 25 s. Tabs are now pinged (PING_BRIDGE→FLOW_AGENT_PING/PONG) before use and skipped if they do not answer.Hardening found necessary while debugging
withTimeout) so one Chrome API call that never settles cannot park the sharedgetOrOpenFlowTabpromise and silently stall every later request.GET_CAPTCHAis re-dispatched untilinjected.jsanswers (it loads async; a first dispatch could be lost);injected.jsdedups by requestId and capsgrecaptcha.executeat 15 s.[Flow Agent]console lines persist tochrome.storage.local.debugLogso stalls can be diagnosed after the fact.Update 2026-09-18: generation now runs through
flow.google.combatchexecute 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-paany more, so there is no bearer to capture, andaisandbox-parejects every auth the extension can present (cookieSAPISIDHASH→400 Origin doesn't match Host for XD3, from bothflow.google.comand a rewrittenlabs.googleorigin — 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:ogiZ0bYhhmEfjwpdufas29sflow-content.googleURLnzlxgResults are mapped back into the
aisandbox-paREST 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
nzlxgcall and reports aflow-sessionmarker in its place. The marker ages out like a token and is re-proven; it is never sent toaisandbox-paas a bearer — endpoints without an RPC mapping fail fast withNOT_SUPPORTED_ON_FLOW_GOOGLE_COMinstead of a misleading 401. Thelabs.googlehandoff 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.
eb1hJffor i2v) — these returnNOT_SUPPORTED_ON_FLOW_GOOGLE_COM.Verification
grecaptcha.enterpriseis present onflow.google.com/project/…and absent onflow.google.com/(0 recaptcha scripts after 20 s); the bearer was captured only via thelabs.googlehandoff.536ae3a):/v1/images/generations1024×1024 in 26 s with the requested aspect honoured;/v1/videos/generations1280×720 landscape and 720×1280 portrait 8 s H.264+AAC clips in ~60 s each;/v1/creditsreturns the real balance.node --checkclean onbackground.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