Skip to content

feat: move Seedance and Omni video onto the job contract - #351

Merged
kiyeonjeon21 merged 1 commit into
mainfrom
feat/seedance-omni-video-contract
Oct 4, 2026
Merged

kiyeonjeon21 merged 1 commit into
mainfrom
feat/seedance-omni-video-contract

Conversation

@kiyeonjeon21

Copy link
Copy Markdown
Contributor

Third PR of the provider interface work (after #349 and #350). With this, every video provider except Veo (shutting down 2026-10-22) is on the contract.

Seedance

  • fal's queue API instead of the blocking subscribe. A paid job keeps its request ID from the moment it is accepted, so it can be polled or cancelled after a crash. Before, a crash mid-wait lost it.
  • "COMPLETED but failed" is handled. fal documents that a COMPLETED status can still be a failure, so error is checked first. A rejection raised when the result is read, like the likeness 422, is reported as a failed job of kind likeness (code content_policy_violation).
  • Bug fix: local frames are no longer dropped. A data-URI first frame used to be ignored, so image-to-video silently became text-to-video. It is now uploaded to fal storage, as references already were.
  • Tests run the real @fal-ai/client SDK against the fake network instead of mocking subscribe. Every earlier assertion is kept.

Omni

  • Background mode: submits with background: true and polls GET /interactions/{id}, then the Files API until the video is ACTIVE.
    • The docs list background only for text models, but Omni accepts it.
    • The completed interaction carries the video URI, contrary to the docs' note.
    • Both were probed live and recorded in google.md.
  • The job handle is the session handle: edit and extend chain with previous_interaction_id. Cancel uses the documented POST /interactions/{id}/cancel.
  • A filtered result reads as moderation: a completed interaction with no video is reported as moderation. Omni's filter can finish that way.

Compatibility

Both keep a blocking generateVideo that submits and waits, so CLI callers are unchanged until the CLI moves to the contract (next PR).

Verification

  • Contract suite: Seedance and Omni both pass.
  • Provider-specific tests:
    • Seedance: endpoint routing for fast and 2.5, duration clamping, data-URI upload, reference grouping, the likeness 422 at result time, and the blocking wrapper.
    • Omni: request shape, inline frames, refusing a URL frame, edit and extend chaining, and file PROCESSING before ACTIVE.
  • Checks: pnpm build, lint, typecheck, tests (providers 205, CLI 1215, MCP 73), pre-push gate.
  • Live:
    • vibe generate video -p seedance --seedance-model fast --resolution 480p --duration 4: 4.1 s, 864x496.
    • vibe generate video -p omni --resolution 360p: 10.0 s, 640x360.
    • Omni edit through the contract ("make it a snowy night") on that interaction: same boat and framing, now snowing at night, 70 s end to end.
    • About $2.3 in total.

https://claude.ai/code/session_011S1BLTaFctZNQzGERpkCuA

Seedance
- Runs on fal's queue API (submit, status, result, cancel) instead of the
  blocking `subscribe`, so a paid job keeps its request ID from the moment
  it is accepted and can be polled or cancelled after a crash.
- A COMPLETED status can still be a failure: `error` is checked first, and
  a rejection raised when the result is read (the likeness 422) is a failed
  job with kind `likeness`, not a thrown read.
- A data-URI first or last frame is uploaded to fal storage instead of
  being silently dropped (which turned image-to-video into text-to-video).
- Tests run the real fal SDK against the fake network.

Omni
- Submits with `background: true` and polls the interaction, then the
  Files API until the video is ACTIVE. Omni accepts background mode although
  the docs list only text models; the completed interaction carries the
  video URI (probed live).
- Edit and extend chain with `previous_interaction_id`, so an Omni job
  handle is its session handle. Cancel uses POST /interactions/{id}/cancel.
- A completed interaction with no video reads as moderation.

Both keep a blocking `generateVideo` that submits and waits, so CLI
callers are unchanged until the CLI moves to the contract.

Claude-Session: https://claude.ai/code/session_011S1BLTaFctZNQzGERpkCuA
@vercel

vercel Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
vibeframe Ready Ready Preview Oct 4, 2026 2:26pm UTC

Request Review

@kiyeonjeon21
kiyeonjeon21 merged commit 7597627 into main Oct 4, 2026
6 checks passed
@kiyeonjeon21
kiyeonjeon21 deleted the feat/seedance-omni-video-contract branch October 4, 2026 14:31

This branch was successfully deployed

1 active deployment
Preview — 8745cc5f Deployed Oct 4, 2026 by vercel[bot]
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