mirror of
https://github.com/THU-MAIC/OpenMAIC.git
synced 2026-10-02 09:24:43 +08:00
* fix(media): poll and download Veo videos the Gemini API way
The Veo adapter targets generativelanguage.googleapis.com but polled
with Vertex AI's models/{model}:fetchPredictOperation and read inline
response.videos[].bytesBase64Encoded. The Gemini API reads operations
with GET v1beta/{name} and returns
response.generateVideoResponse.generatedSamples[].video.uri, fetched
with the same API key.
- Poll with GET v1beta/{operationName}.
- Download the sample URI with x-goog-api-key into a data URL, always
through the configured base URL's origin and without following
redirects, like the other adapter calls. Inline bytes are still
accepted when present.
- Report RAI-filtered operations as a failure with their reasons.
- Catalog: Gemini API model IDs for Veo 3.1 (-preview, plus Lite) and
only the 16:9 / 9:16 aspect ratios the API accepts.
Fixes #1694
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* fix(media): follow the Veo download redirect through a validated transport
The Gemini API file URI can answer with a redirect to storage (Google's
own example downloads it with `curl -L`), which the download refused, so
a generation could fail after a successful poll.
- VideoGenerationConfig gets an optional downloadFetchImpl. fetchImpl is
the pinned transport that refuses every 3xx, so the download needs its
own one.
- lib/server/media-provider-fetch.ts adds mediaDownloadFetch and
managedMediaDownloadFetch: providerFetch with redirects followed, each
hop re-validated under the operator address policy, pinned to the
vetted DNS answers, and stripped of x-goog-api-key once it leaves the
origin (fetchWithRedirectValidation). withVideoProviderFetch installs
both transports.
- The server video call sites (the generate route, classroom media
generation, the agent runtime) inject it; the adapter still does not
import server code.
- downloadVideo follows redirects only through the injected transport and
keeps redirect: 'manual' + assertNotRedirected without it.
- Test: a 302 to another origin yields the data URL and the second hop
carries no x-goog-api-key; without the transport the 302 is refused.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>