feat(video): add OpenRouter and Vertex AI (Veo) video generation
Video generation was xAI-only. Adds an adapter layer under
open-sse/handlers/videoProviders/ so /v1/videos/* can target OpenRouter or
Google Cloud credentials. A provider with no adapter keeps the exact previous
behaviour (raw body to {baseUrl}/{action}, poll {baseUrl}/{id}, verbatim
passthrough), so the xAI path is unchanged.
- openrouter: async job shape identical to xAI; creation POSTs to the /videos
collection root (no /generations suffix) and the registry HTTP-Referer /
X-Title headers are applied. Bodies pass through verbatim.
- vertex: two-way translation, since Veo does not speak the OpenAI-ish videos
shape. create -> :predictLongRunning { instances[], parameters{} }, poll ->
:fetchPredictOperation (Veo has no REST GET poll). The operation resource
name is base64url-encoded into the job id so GET /v1/videos/{id} stays a
flat path. Access tokens are minted from Service Account JSON via the
existing refreshVertexToken; raw API keys are rejected up front. The
operation response maps back onto the { id, status, video, videos } shape
clients already poll.
- videoCore: the request plan is rebuilt per attempt, so the 401 -> refresh
once -> retry once path picks up the refreshed token. Adapter validation
errors return 400 before any upstream call, so a malformed request can never
create a billable job.
- videoGeneration: GET /v1/videos/{id} resolves the provider from the pinned
x-connection-id connection, then ?provider=, then falls back to the xAI
default.
- registry: openrouter and vertex gain videoConfig, the video serviceKind and
video-kind models (Veo 3.1 / 3 / 2, Sora 2 Pro, Seedance 2.0).
This commit is contained in:
@@ -29,6 +29,7 @@ vi.mock("@/sse/services/auth.js", () => authMocks);
|
||||
vi.mock("@/sse/services/tokenRefresh.js", () => tokenMocks);
|
||||
vi.mock("@/lib/localDb", () => ({
|
||||
getSettings: vi.fn(async () => ({ requireApiKey: false })),
|
||||
getProviderConnectionById: vi.fn(async () => ({ id: "conn-5", provider: "xai" })),
|
||||
getComboByName: vi.fn(async () => null),
|
||||
getModelAliases: vi.fn(async () => ({})),
|
||||
getProviderNodes: vi.fn(async () => []),
|
||||
|
||||
Reference in New Issue
Block a user