feat(videos): Runway (Gen/Veo) adapter on /v1/videos#817
Conversation
Add the Runway Developer API as the fourth provider on the unified
/v1/videos surface (first overseas provider), mirroring the existing
Alibaba/Zhipu/Volcengine dispatch exactly.
- provider string `runwayml` (models.dev canonical id), alias `runway`
following the zhipuai/zhipu precedent
- submit POST /v1/text_to_video: {model, promptText, duration?, ratio?};
`size` WIDTHxHEIGHT maps to `ratio` WIDTH:HEIGHT (the 2024-11-06
resolution form) by separator swap, mirroring the DashScope x->*
treatment; unset params omitted
- poll GET /v1/tasks/{id}: status PENDING/THROTTLED->queued,
RUNNING->in_progress, SUCCEEDED->completed, FAILED/CANCELLED->failed;
output[0] signed URL for the 302; failure/failureCode -> error object
- mandatory X-Runway-Version header wired on BOTH submit and poll via a
new minimal all-request-header hook (distinct from the DashScope
submit-only async marker)
- no api_base suffix stripped (documented base is the bare host; /v1 is
per-path)
All invariants preserved by construction: 3-segment id codec, submit
quota-enforced / GETs exempt, guardrail-before-quota, uniform 404 folds
on GETs, bounded metric labels, zero-token submit UsageEvent, 302
restricted to http/https, task-id charset guard.
Field shapes verified against the official runwayml SDK (sdk-python
_client.py, resources/text_to_video.py, resources/tasks.py,
types/task_retrieve_response.py) and
https://docs.dev.runwayml.com/api-details/versions/2024-11-06/.
Overseas providers whose download URLs need auth (Veo, Sora) are
deferred to the content-streaming-proxy work.
Refs api7/AISIX-Cloud#1118
|
Warning Review limit reached
Next review available in: 37 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
… pin version-header isolation Audit follow-ups (all LOW/NOTE): - fixtures used gen4_5 (underscore); Runway's canonical id is gen4.5 (dot) — the pass-through code is model-agnostic but a CP catalog or docs entry copying gen4_5 would 400 upstream. - clarify in comments that this is Runway-hosted Veo (veo3/veo3.1), distinct from Google-direct Veo (deferred, needs x-goog-api-key). - assert the X-Runway-Version header does not bleed onto other providers' submit requests.
|
@coderabbitai review |
✅ Action performedReview finished.
|
Adds the Runway Developer API as the fourth provider on the unified
/v1/videossurface — the first overseas provider — mirroring the existing Alibaba/Zhipu/Volcengine dispatch (PRs #811, #814) exactly. Refsapi7/AISIX-Cloud#1118.Why Runway (and why not Veo/Sora)
Runway's task
outputis an array of signed, self-authenticating URLs (long-lived signed JWT blobs, expiring 24–48h) — fetchable with no credentials, a clean fit for the existing 302 content route. Providers whose download URL requires a provider auth header (Google Veo'sx-goog-api-key, Sora) are deferred to the content-streaming-proxy work and deliberately not added here.Mapping table (verified against official docs + SDK)
https://api.dev.runwayml.com(bare host;/v1is per-path)src/runwayml/_client.pybase_urlX-Runway-Version: 2024-11-06, required on every call_client.pydefault header + docs 2024-11-06Authorization: Bearer <key>_client.pyPOST /v1/text_to_video→{ model, promptText, duration?, ratio? }resources/text_to_video.py,types/text_to_video_create_params.py{ id }(no status) →queuedtypes/text_to_video_create_response.pyGET /v1/tasks/{id}resources/tasks.pyprompt→promptText(camelCase wire alias)text_to_video_create_params.pyaliasseconds→duration(int)sizeWxH→ratioW:H(2024-11-06 expresses output resolution asWIDTH:HEIGHT, a per-model enum; lossless separator swap, mirrors DashScopex→*)text_to_video_create_params.pyallowedratiovaluesoutput[0](bare array of signed URLs, present only onSUCCEEDED)types/task_retrieve_response.pyfailure(human) →error.message,failureCode(camelCase alias) →error.codeStatus normalisation
PENDING/THROTTLEDqueuedRUNNINGin_progressSUCCEEDEDcompletedFAILED/CANCELLED/ otherfailedPer-fact verification
https://api.dev.runwayml.com(no/v1suffix). No root-stripper invented (the documented api_base carries no version suffix, per brief).X-Runway-Versionmust ride submit AND poll (unlike DashScope's submit-only async marker). Wired via a new minimalall_request_header()hook applied unconditionally inprovider_call; asserted on both legs in unit + e2e.ratio= resolution — the 2024-11-06 version replaced aspect enums (16:9) with pixel-resolution strings (1280:720).size→ratiois therefore a faithful separator swap, not a dropped/invented mapping.ratiois required for several models, so omittingsizelets the provider return its own "ratio required" 400 rather than inventing a default.failure/failureCode(camelCase), surfaced through the unified error object like Ark'serror.{code,message}.Invariants preserved by construction (for Runway too)
3-segment
video_idcodec, submitquota::enforce(Some(&model_rl))/ GETsenforce(None), guardrail-before-quota on the prompt, uniform 404video_not_foundon GETs (unsupported-provider + ACL-denied folds), bounded metric labels (resolved display_name /UNRESOLVEDsentinel), zero-token UsageEvent on submit only, 302 restricted to absolute http/https, task-id charset guard before URL interpolation.Test evidence
Unit (
cargo test -p aisix-proxy --lib videos): 41 passed, 0 failed — 5 new Runway tests (status-map table, ratio separator-swap + malformed rejection, submit-body shape, full submit→poll→content journey assertingX-Runway-Versionon both legs, failed-taskfailure/failureCode), plus the root-stripper and URL-composition tables extended; all existing Alibaba/Zhipu/Ark tests stay green.E2E:
videosfamily: 6 passed — new Runway journey against a mock upstream serving Runway-shaped responses, asserting the version header reached the upstream on the submit POST and both poll GETs,promptText/duration/ratiowire shape, and the 302 tooutput[0].passthroughfamily: 12 passed (no regression).Gate:
cargo fmt --checkclean,cargo clippy --workspace --tests0 warnings,cargo build --bin aisixok.Notes
This DP adapter reads the free-form
providerstring; a matching CP catalog entry (runwaymlprovider + video model) is control-plane follow-up work underAISIX-Cloud#1118, same as the existing three video providers.