Feat/flow batchexecute migration - #39
Merged
Merged
Conversation
Flow moved off labs.google in September 2026 and stopped minting the `Bearer ya29.…` the aisandbox-pa REST API needed. The rewritten frontend signs every call with the session cookie plus a per-page `at` token against one batchexecute endpoint, so nothing can be replayed from here: the agent builds the envelope, the extension runs it in the Flow tab. flow_batch.py holds the codec, the request builders and the readers, ported from the flowgen bridge along with the traps that cost it hours — the poll's third uuid is the scene and not the media, "Media not found." is a complaint rather than a verdict, the listing decides where the poll only hints, a media id arrives before the clip is fetchable, and image aspect (1 = square) does not share video aspect's encoding (1 = portrait). flow_client keeps its old surface and answers in the old REST shapes, so the worker's parsers, the operation poller and the DB writers never learn which transport ran. The legacy path stays behind USE_BATCH_RPC=0 as a post-mortem tool. Upscale, r2v and start+end-frame chaining have no captured payload and now fail as UNSUPPORTED_ON_BATCH_API instead of reaching for the dead bearer; FLOW_ALLOW_DEGRADED=1 drops the latter two to plain i2v. refresh_project_urls stops being a stub — the media rpc re-signs a stored id, which is exactly what /fk-refresh-urls always wanted. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015JkgMuy89iJ9qc1NkRdPk5
Only the page can sign a batchexecute call, so the new `batch_rpc` handler mints a reCAPTCHA through the existing grecaptcha bridge and runs the POST in the tab's MAIN world, where `at` / `f.sid` / `bl` live. The project listing is past 17 MB for the one entry we want, so the runner cuts it to an 800-byte window around the operation id before handing it back rather than pushing the rest through the bridge. Every tab lookup now goes through one `flowUrls` list that includes flow.google.com. Matching only the old URL is what produced `CAPTCHA_FAILED: NO_FLOW_TAB` against a Flow tab sitting right there. Captcha solving tries each Flow tab in turn and reloads discarded ones instead of returning on the first miss — one stale tab used to veto every generation. The bearer capture, the aisandbox-pa proxy and the telemetry are kept for USE_BATCH_RPC=0 and an old pinned tab, and are labelled as such. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015JkgMuy89iJ9qc1NkRdPk5
project.createProject went with the migration — the labs.google tRPC
endpoint it lived on is unauthenticated now, and calling it just fails.
Every batchexecute call is scoped to a project, so one is made once in
the Flow UI and its uuid supplied per project as `flow_project_id` or
pinned as FLOW_PROJECT_ID.
Reading the id back is split out so it works either way: the batch path
answers `{"projectId": …}`, the legacy tRPC path buried it under
result/data/json/result.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015JkgMuy89iJ9qc1NkRdPk5
An unported capability and a missing Flow project are configuration answers, not something five retries can reach — UNSUPPORTED_ON_BATCH_API and NO_FLOW_PROJECT now fail once instead of burning the retry budget on every scene of a pipeline run. The other direction for the poll: an operation can report "Media not found." and still deliver a finished clip, so the complaint is carried alongside a still-pending round and only quoted if we time out, where it is the one piece of context worth having. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015JkgMuy89iJ9qc1NkRdPk5
The two transports answer a media lookup differently: the batch path hands back a freshly signed url, the legacy REST path inlined the bytes as base64. Try the url first and keep the encoded content as the fallback, so an expired scene url still resolves on either path. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015JkgMuy89iJ9qc1NkRdPk5
What the migration changes for whoever runs this next: a Flow project has to be pinned, one signed-in flow.google.com tab has to stay open, and `flow_key_present: false` is now normal rather than a fault. fk-doctor gains the batch path's error taxonomy — NO_AT_TOKEN, NO_FLOW_PROJECT, UNSUPPORTED_ON_BATCH_API — and loses the advice that sent people looking for a bearer token that is not coming back. The skills whose behaviour actually changed say so where you would hit it: chaining and upscale name what they cannot do and offer the degraded fallback, change-model explains that only the quality tier survives the fold onto the three accepted names, refresh-urls describes what it does now that it works. docs/CAPTURE.md is the way back for the three unported payloads: record the action, diff the slots, throw the capture away. Guessing at Google's positional payloads does not work — a reference image in the wrong slot is accepted and then silently ignored. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015JkgMuy89iJ9qc1NkRdPk5
main gained Omni Flash, multi-profile extension failover, the Low Priority workflow schema and the review CLI providers while this branch was porting Flow onto batchexecute. Four textual conflicts, and three places where the merge was clean but wrong: `_send` now routes only through extensions that captured a bearer token. No profile on the batch path ever captures one — it authenticates with the session cookie in the page — so every request would have answered NO_FLOW_KEY. The token requirement follows the transport now, and the failover list learned the batch path's profile-local failures (NO_AT_TOKEN, FLOW_TAB_DISCARDED), which is exactly the "this tab can't, another can" class it was built for. The retry shortcut reads a bare uuid as a Low Priority workflow name it cannot re-poll, and resubmits. Batch operation ids are bare uuids, and they *are* recoverable — the status poll finds them in the project listing — so on that path a retry would have abandoned a running render and paid for a second one. The heuristic is now per-transport. Omni Flash speaks the pre-migration REST and tRPC endpoints and has no captured batchexecute payload, so it joins upscale, r2v and chaining in failing with UNSUPPORTED_ON_BATCH_API instead of dying on a 401 five retries deep. Its wire-contract tests are pinned to the legacy path, where those contracts are still exactly right, and the batch path's refusal is covered on its own. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015JkgMuy89iJ9qc1NkRdPk5
crisng95
added a commit
that referenced
this pull request
Sep 17, 2026
First release since v1.1.0 (2026-05-09), and it is one arc: Flow moved to flow.google.com in September 2026 and stopped minting the bearer the old REST API needed, so the transport was rebuilt on batchexecute (#39), the dead REST path deleted (#49), the image API migrated (#42), and the Omni image-conditioned modes ported back on top of it (#48/#50). Also fixes a version drift this release would otherwise have deepened. ccf89c6 put "0.2.0" in two places in agent/main.py; 939b956 bumped only the FastAPI line, so /health has reported 0.2.0 ever since while the app said 1.1.0 — three releases stale, on the endpoint CLAUDE.md tells you to curl before anything else. /health now reads app.version, so there is one string to bump instead of two literals that agree only by luck. extension/manifest.json is deliberately not bumped. It tracks the extension's own lifecycle, it is at 0.3.2, and a bump there forces a user-visible reload. Verified: 272 passed; /health and app.version both report 1.2.0, checked by calling the handler rather than reading the source. Not verified: the Omni envelopes from #48. They are live-verified per that PR and the tests lock their shape, but nothing has submitted through a signed-in Flow tab since the merge resolution. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E5BJVhNgerhFTUgmfnKTSj
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.
No description provided.