Skip to content

feat(videos): Zhipu (CogVideoX) and Ark (Seedance) adapters on /v1/videos#814

Merged
moonming merged 2 commits into
mainfrom
feat/videos-endpoint-p1-zhipu-ark
Jul 24, 2026
Merged

feat(videos): Zhipu (CogVideoX) and Ark (Seedance) adapters on /v1/videos#814
moonming merged 2 commits into
mainfrom
feat/videos-endpoint-p1-zhipu-ark

Conversation

@moonming

@moonming moonming commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

Second PR of api7/AISIX-Cloud#1118 Phase 1: extends the unified /v1/videos submit → poll → content surface (shipped DashScope-only in the previous PR) with two more provider mappings, dispatched by the Model's open provider string (case-insensitive). Any unmapped provider keeps the existing behavior: typed 501 not_implemented on submit, folded to a uniform 404 on the GET routes.

All surface invariants are unchanged and re-verified by the existing test suite: 3-segment video_id codec (b64url(entry_id : b64url(alias) : task_id)), submit = enforce(Some(&model_rl)) / GETs = enforce(None) (poll exemption by design), guardrail-before-quota on the submit prompt, uniform 404 disclosure fold on GETs, bounded metric labels, one zero-token UsageEvent per submit, http(s)-only 302 content redirect, charset-guarded task ids.

Provider mappings (doc citations)

zhipuai — BigModel CogVideoX

Contract source: https://docs.bigmodel.cn/api-reference/%E6%A8%A1%E5%9E%8B-api/%E8%A7%86%E9%A2%91%E7%94%9F%E6%88%90%E5%BC%82%E6%AD%A5

unified provider
submit POST {root}/api/paas/v4/videos/generations, Authorization: Bearer, flat body {model, prompt, …}; response {model, id, request_id, task_status}
poll GET {root}/api/paas/v4/async-result/{id}
seconds duration (int)
size size verbatim — the vendor documents the same WIDTHxHEIGHT spelling ("1920x1080", "1280x720", …)
status PROCESSING→in_progress, SUCCESS→completed, FAIL/other→failed; the vendor has no distinct queued state, so an accepted submit reports in_progress
video URL video_result[0].url
errors nested {error: {code, message}} envelope, passed through the standard 4xx rendering

Root derivation: the control-plane catalog pre-fills api_base https://open.bigmodel.cn/api/paas/v4; the adapter strips one trailing /api/paas/v4 so the native task paths are never doubled (mirrors the DashScope compatible-mode stripper, with tests).

volcengine — Ark Seedance

Contract source: the official Ark SDK (volcengine-python-sdk, volcenginesdkarkruntime/resources/content_generation/tasks.py and types/content_generation/content_generation_task.py) — the vendor's doc pages (docs.volcengine.com/docs/82379/2298881 and the ModelArk mirror) render client-side only and return no static content, so per the repo research rules the SDK source is the citable contract.

unified provider
submit POST {root}/api/v3/contents/generations/tasks, bearer auth, body {model, content: [{type: "text", text: prompt}], duration?} — the exact field set of the SDK's tasks.create(model=…, content=…, duration=…, resolution=…, ratio=…); response {id} (ContentGenerationTaskID)
poll GET {root}/api/v3/contents/generations/tasks/{id} (ContentGenerationTask)
seconds duration (int, top-level)
size not forwarded — the vendor expresses output dimensions as resolution ("720p"/"1080p") + ratio ("16:9", …) quality tiers, which cannot represent an arbitrary WIDTHxHEIGHT without a lossy invented mapping; the value is still shape-validated so malformed input fails identically across providers, a debug log records the drop, and the provider default applies. A tier-mapping design (shared with the wan2.7 follow-up) is tracked in the internal issue.
status queued→queued, running→in_progress, succeeded→completed, failed/cancelled/expired/other→failed; the create response carries no status, so a fresh submit reports queued
video URL content.video_url
errors task-level error {code, message} surfaces through the unified error object

Provider-string note: the public model catalog carries no canonical id for this vendor, so the open provider string volcengine matches the vendor's own name; the control-plane catalog quirk entry is separate tracked follow-up work.

Structure

The provider-specific pieces fold into one internal VideoProvider enum (root / submit_url / poll_url / submit_body / parse_submit / parse_poll / DashScope-only async header), reducing every provider response to two normalised views (SubmitView, PollView) the handlers consume. A plain match at three providers — deliberately no trait objects or registry. Adding a fourth adapter is a new match arm plus tests, not another copy of handler logic.

Deferred (tracked in the internal issue)

  • MiniMax (Files-API fetch indirection) — Phase 2.
  • Per-second cost schema — separate control-plane PR; video usage events remain zero-token until then.
  • CP catalog entry for the volcengine vendor (provider quirk/prefill) — separate CP work.
  • Content streaming proxy for providers whose URLs need gateway credentials — Phase 3; this surface stays 302-redirect.
  • size → tier mapping for tier-based vendors (Ark resolution/ratio, wan2.7) — needs a deliberate, documented mapping decision.

Test evidence

  • Unit (videos.rs, now 35 cases): per-provider status-mapping tables; Zhipu/Ark submit-body shape (including size verbatim for Zhipu, size dropped under every name for Ark, malformed-size fast-fail); per-provider root stripping + full URL composition; Zhipu nested error envelope on 4xx; Ark failure error {code,message} mapping; full-journey wiremock tests per provider (submit wire assertions + poll + content 302, and no DashScope header bleeding across vendors); every pre-existing invariant test (codec, ACL fold, metric-label boundedness, rpm cap with poll exemption, scheme validation, allowed_cidrs) unchanged and green.
  • E2E (tests/e2e/src/cases/videos-providers-e2e.test.ts, source-blind, real binary + etcd + provider-shaped mock upstreams): one submit→poll→content-302 journey per new provider with upstream wire assertions; the DashScope journeys in videos-e2e.test.ts stay green.
  • Gate: cargo fmt clean; cargo clippy --workspace --tests 0 warnings; cargo test -p aisix-proxy --lib 703 passed; cargo build --bin aisix ok; e2e videos (3/3) + videos-providers (2/2) + passthrough family (7/7) all passed against the rebuilt binary.

Summary by CodeRabbit

  • New Features

    • Added video generation support for Zhipu and Ark/Seedance providers alongside DashScope.
    • Standardized video submission, polling, status reporting, errors, and content redirects across providers.
    • Added provider-specific request handling and validation for video settings.
  • Bug Fixes

    • Improved handling of upstream errors and failed video downloads.
    • Content redirects now occur only for completed videos with valid HTTPS or HTTP URLs.
  • Tests

    • Added end-to-end coverage for submission, polling, status normalization, and content retrieval across supported providers.

…1/videos

Extend the unified video-generation surface (api7/AISIX-Cloud#1118
Phase 1, second PR) from DashScope-only to three provider mappings,
dispatched by the Model's open `provider` string:

- `zhipuai` — BigModel CogVideoX: submit POST
  {root}/api/paas/v4/videos/generations with a flat {model, prompt,
  duration, size} body (the vendor documents the unified WIDTHxHEIGHT
  size spelling, forwarded verbatim); poll GET
  {root}/api/paas/v4/async-result/{id}; statuses PROCESSING/SUCCESS/
  FAIL normalise to in_progress/completed/failed (the vendor has no
  distinct queued state); the video URL is video_result[0].url.
- `volcengine` — Ark Seedance: submit POST
  {root}/api/v3/contents/generations/tasks with {model, content:
  [{type:"text", text}], duration} (field set per the official Ark
  SDK); the create response carries only the task id (queued); poll
  GET {root}/api/v3/contents/generations/tasks/{id}; statuses queued/
  running/succeeded/failed/cancelled normalise onto the unified enum;
  the video URL is content.video_url. `size` is not forwarded — the
  vendor expresses dimensions as resolution/ratio quality tiers, and
  inventing a lossy WIDTHxHEIGHT→tier mapping is worse than the
  provider default.

The provider-specific pieces (URL derivation with per-vendor api_base
suffix stripping, submit body, submit/poll response parsing, the
DashScope-only async header) fold into one VideoProvider enum matched
in three places, so a fourth adapter is a new match arm rather than
another copy of the handler logic. Every existing invariant is
unchanged: 3-segment video id codec, submit-only model rate limiting,
guardrail-before-quota, uniform 404 on the GET routes, bounded metric
labels, zero-token UsageEvent on submit, http(s)-only 302 content
redirect, charset-guarded task ids.

Unit: per-provider status tables, submit wire assertions, root/URL
composition, nested-error-envelope passthrough, Ark failure detail.
E2E: one submit→poll→content-302 journey per new provider against
provider-shaped mock upstreams; DashScope journeys unchanged.
@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@moonming, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 42 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 22d8c355-b4f6-4f62-8243-ec8131bd90ee

📥 Commits

Reviewing files that changed from the base of the PR and between 91753bf and a1e1b48.

📒 Files selected for processing (1)
  • crates/aisix-proxy/src/videos.rs
📝 Walkthrough

Walkthrough

The /v1/videos API now supports DashScope, Zhipu, and Ark providers through normalized submit, poll, status, error, and content handling. Unit and E2E tests cover provider routing, request mapping, polling, redirects, and failure responses.

Changes

Multi-provider video adapters

Layer / File(s) Summary
Provider contracts and request shaping
crates/aisix-proxy/src/videos.rs
Adds provider endpoint mappings, normalized task views, status conversion, and provider-specific request body construction with shared WIDTHxHEIGHT validation.
Provider dispatch and upstream calls
crates/aisix-proxy/src/videos.rs
Selects supported providers, composes submit and poll URLs, applies provider-specific headers, performs authenticated calls, and parses multiple error envelope formats.
Normalized video lifecycle
crates/aisix-proxy/src/videos.rs
Uses normalized results for creation, polling, response construction, failure details, and validated completed-video redirects.
Provider journey validation
crates/aisix-proxy/src/videos.rs, tests/e2e/src/cases/videos-providers-e2e.test.ts
Adds unit and E2E coverage for Zhipu and Ark request wiring, status mapping, nested errors, polling, redirects, and unsupported-provider fixtures.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • api7/aisix#811: Covers the shared /v1/videos flow that this change extends with multi-provider routing.
🚥 Pre-merge checks | ✅ 6
✅ Passed checks (6 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding Zhipu and Ark video adapters to /v1/videos.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
E2e Test Quality Review ✅ Passed New E2E tests cover the full submit→poll→content flow for Zhipu and Ark with realistic seeded app+mock upstreams, and the structure/readability is solid.
Security Check ✅ Passed No issues found: the new video paths avoid logging secrets, validate redirects and task IDs, and enforce ACL/IP checks with immediate returns.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/videos-endpoint-p1-zhipu-ark

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…ias, FAIL-path test

- per-field as_u64 so a present-but-null output_video_duration still
  falls back to usage.duration
- accept the common 'zhipu' spelling alongside the catalog-canonical
  'zhipuai' on the videos dispatch
- pin the Zhipu FAIL poll journey (generic video_generation_failed
  error object; the vendor task payload carries no failure detail)
@moonming

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@moonming
moonming merged commit 0f90a98 into main Jul 24, 2026
12 checks passed
@moonming
moonming deleted the feat/videos-endpoint-p1-zhipu-ark branch July 24, 2026 02:59
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.

1 participant