Skip to content

feat(video): native Google Veo + xAI Grok Imagine async video providers (#278)#282

Merged
jpr5 merged 4 commits into
mainfrom
feat/video-veo-grok
Jun 28, 2026
Merged

feat(video): native Google Veo + xAI Grok Imagine async video providers (#278)#282
jpr5 merged 4 commits into
mainfrom
feat/video-veo-grok

Conversation

@jpr5

@jpr5 jpr5 commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Closes #278.

Adds first-class aimock support for two async video-generation providers, mirroring the existing Sora / OpenRouter / fal job-lifecycle model — replay and live record-mode proxy for both.

Google Veo (Gemini)

  • POST /v1beta/models/{model}:predictLongRunning{ name }, then GET /v1beta/operations/{name} poll → { done:false }{ done:true, response.generateVideoResponse.generatedSamples[].video.uri }, with poll-count progression.
  • Files-API uri is served as-is (aimock does not proxy the video bytes — Veo's envelope carries no cost field).
  • Record mode forwards 1:1 to the configured veo upstream and eager-captures the fixture on done:true.

xAI Grok Imagine

  • POST /v1/videos/generations{ request_id } (multipart rejected with 400), then GET /v1/videos/{request_id}{ status: pending|done|failed|expired, progress, video, usage.cost_in_usd_ticks }. Progress synthesized from poll count; cost_in_usd_ticks = USD × 1e10.
  • Shares /v1/videos/{id} with Sora: job-map-first lookup, falling through to the unchanged Sora handler on a miss (pinned byte-for-byte by a test).
  • Record mode forwards 1:1 to the configured grok upstream and eager-captures on terminal status.

Shared proxy helpers were extracted into src/video-proxy-shared.ts (behavior-preserving; openrouter-video re-pointed at it, its 233 tests green before & after).

Verification

  • Full suite 4113 passing (127 files), build + exports + lint + format + tsc --noEmit all clean.
  • Both providers have red-green-proven replay + record tests against a credential-free fake local upstream (no real Veo/xAI keys needed).
  • Reviewed via a 4-round, 9-agent-per-round CR loop converged to zero (Procedure 3 bucket-c audit: 0 promotions). Behavioral fixes (failed-seed progress, status-dispatch error journaling for both providers, empty-url placeholder) each landed with a red→green covering test.

Known follow-ups (not blocking)

  • Verify @google/genai forwards x-test-id on operations.getVideosOperation polls; if it does not, Veo would need testId conveyance via the operation name (like OpenRouter's testIdSuffix) for non-default-testId clients. Consistent with Sora's contract today.
  • Minor hardening logged: guard Grok's poll-URL build like Veo's; reconcile the capture-latch reset discipline across the two; Number.isFinite guards + warns on malformed upstream duration/cost.

🤖 Generated with Claude Code

@pkg-pr-new

pkg-pr-new Bot commented Jun 26, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@copilotkit/aimock@282

commit: d00981c

jpr5 added 4 commits June 26, 2026 15:55
…ideo providers (#278)

Introduce the shared async-video proxy module and wire server dispatch,
types, and metrics for Veo/Grok providers.
…rd-mode (#278)

Implement the native Veo predictLongRunning poll lifecycle with record-mode
fixtures, tests, and provider docs.
…fe dispatch (#278)

Add the native xAI Grok Imagine video provider with record-mode fixtures,
Sora-safe dispatch, tests, and provider docs.
Document the Veo and Grok Imagine video providers in the sidebar and README,
and record the changelog entry.
@jpr5 jpr5 force-pushed the feat/video-veo-grok branch from 1e61168 to d00981c Compare June 26, 2026 22:56
@jpr5 jpr5 merged commit 5c88ba5 into main Jun 28, 2026
23 checks passed
@jpr5 jpr5 deleted the feat/video-veo-grok branch June 28, 2026 04:24
jpr5 added a commit that referenced this pull request Jun 28, 2026
…-class + docs (#285)

## What

Completes the (still-unreleased) #274 `blocks` fixture-ordering feature
so it works **uniformly across every provider**, and makes blocks-only
fixtures **first-class**. Builds on #283 (blocks v1) and #282 (async
video), both already on `main` under `[Unreleased]`.

No version bump — stays `1.34.0`. The dedicated `chore: release v1.35.0`
PR owns the bump.

## Why

#283 shipped `blocks` for a subset of providers and left the record-side
capture + several provider builders out of scope, with blocks-only
fixtures treated as by-design-unsupported. To ship the feature as
*complete* for 1.35.0, it needs to: capture/replay block order on the
remaining providers, accept a fixture that is *just* `{ blocks: [...]
}`, and document the feature where authors actually look.

## Changes

**Feature completion**
- **First-class blocks-only fixtures** — a response may be `{ blocks:
[...] }` with no `content`/`toolCalls`; the shared recognizer was
relaxed *additively* (legacy recognition byte-identical).
- **Record side** — block-order capture added to the Cohere, Bedrock
(event-stream), and Gemini-Interactions collapsers;
`normalizeToolArguments` zero-arg ("{}") fix. Gemini-Interactions is
args-only by design (step-index can't reconcile arrival-order blocks).
- **Replay builders** — Cohere, Bedrock (invoke), Bedrock-Converse, and
Gemini-Interactions now honor `blocks` ordering (streaming +
non-streaming where the wire allows).
- **toolCall `arguments`** may be a JSON object or a string (objects
auto-stringify), consistently across top-level toolCalls and block
toolCalls.
- **Validation hardening** — `validateBlocks` rejects empty-text blocks
and warns on blocks/content divergence.

**Completion gaps found + fixed during code review** (each with a local
red→green on the real surface)
- Ollama **non-streaming** dropped the entire payload for a blocks-only
fixture (F0 made it newly reachable) — now backfills content/tool_calls
from blocks.
- Realtime + Gemini-Live WS surfaces silently dropped blocks-only
payloads — now honor blocks.
- Programmatic `addFixture` with object block args returned HTTP 500
(bypassed normalize) — `resolveFixtureBlocks` now tolerates object args.
- A valid `{ content: "", blocks: [...] }` fixture spuriously
hard-errored at load — suppressed when non-empty blocks drive output.
- Gemini-Live empty-text block leaked past `truncateAfterChunks` and
shifted recorded-timing indices — guard now skips emission cleanly.

**Docs**
- `docs/fixtures/index.html`: per-provider observability matrix,
blocks-only authoring, reasoning cells.
- Authoring on-ramps: `write-fixtures` skill/command, `docs/examples`
(worked **tool-first** example), `docs/record-replay`, root + pytest
READMEs.
- A runnable `fixtures/examples/llm/blocks-tool-first.json` with a
permanent loadability test.

## Wire limitations (documented, not gaps)

OpenAI-chat, Ollama, and Cohere **non-streaming** expose separate
content/tool_calls fields, so order is not observable on the wire —
payload is delivered, order is a no-op. Captured in the observability
matrix.

## Test plan

- Full suite: **144 files / 4244 tests** pass
- `tsc --noEmit`, `eslint`, `prettier --check`, `build`, `test:exports`
(node10/node16-CJS/ESM/bundler) all green
- Every behavioral fix verified red→green on the real surface (live
endpoint / real WS / real loader), independently re-confirmed in review

## Known non-blocking follow-ups

Pre-existing items (predate this branch) and minor polish are tracked
but intentionally out of scope: a shared stringify helper to de-dup the
three normalize sites, JSON-serializability check for object args at
load time, and assorted pre-existing collapser/request-converter edge
cases.
@jpr5 jpr5 mentioned this pull request Jun 28, 2026
jpr5 added a commit that referenced this pull request Jun 28, 2026
## Release v1.35.0

Version bump cut off latest `main` (includes #285 blocks-completion and
#286 video-testid).

### Version surfaces bumped (1.34.0 → 1.35.0)

These five literal build surfaces track the aimock npm release line and
were bumped together:

1. `package.json` — `"version"` → `1.35.0`
2. `.claude-plugin/plugin.json` — `"version"` → `1.35.0`
3. `.claude-plugin/marketplace.json` — `plugins[0].source.version` →
`^1.35.0` (caret preserved)
4. `charts/aimock/Chart.yaml` — `appVersion` → `"1.35.0"`
5. `packages/aimock-pytest/src/aimock_pytest/_version.py` —
`AIMOCK_VERSION` → `"1.35.0"`

### Deliberately NOT changed (independently versioned)

Verified against release history — these do **not** track the aimock
release line and follow their own cadence, so they are left as-is:

- `charts/aimock/Chart.yaml` `version:` stays **`0.1.0`** (Helm chart
version — independent of the app it packages)
- `packages/aimock-pytest/pyproject.toml` `version` stays **`0.4.0`**
(the Python package's own release cadence, distinct from the npm release
it pins via `AIMOCK_VERSION`)

### Hygiene fix

- `packages/aimock-pytest/README.md` — corrected the stale
`--aimock-version` default from `1.33.0` → `1.35.0` to match
`AIMOCK_VERSION`.

### CHANGELOG

- Renamed the accumulated `## [Unreleased]` section to `## [1.35.0] -
2026-06-27` and inserted a fresh empty `## [Unreleased]` above it.
Bullet contents unchanged.

### What's in 1.35.0

- **`blocks` feature completed across all providers** — ordered
text/tool-call block streaming now honored on replay across Anthropic,
OpenAI (Responses + chat-completions), Gemini, Ollama, Cohere, Bedrock
(invoke + Converse), and Gemini Interactions, with record-side block
capture where the wire protocol allows (#274).
- **Blocks-only fixtures are first-class** — a non-empty `blocks` array
is a complete response shape on its own (no `content`/`toolCalls`
required); `validateBlocks` rejects malformed arrays at load time
(#274).
- **Veo / Grok multi-tenant testId isolation** — native Google Veo and
xAI Grok Imagine async video lifecycle mocks with record-mode live
proxying and per-tenant testId isolation (#278, #282).

### Publishing

Publishing is **not** performed here. The release is cut and verified;
the actual publish is the manual `npm run release` step, pending
maintainer action.

### Verification

- `npm run build` — clean (exit 0)
- `npx vitest run` — **4250/4250 passed**, 144/144 files (exit 0)
- `npm run test:exports` — all 🟢 (node10 / node16 CJS+ESM / bundler,
across all entry points)
- Type-emitting build clean (`.d.ts` emit succeeded; no separate `tsc`
script in this package)
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.

Native support for async video generation: Google Veo (:predictLongRunning) and xAI Grok Imagine (/v1/videos/generations)

1 participant