Skip to content

Commit 27695ee

Browse files
committed
chore: release v1.31.0
### Added - OpenRouter async video job lifecycle mock — submit, poll, content download, model listing (#262) - Record-mode live proxying for the OpenRouter video surface; captured videos replay later (#265) ### Changed - Recording proxies now strip aimock-internal control headers on every provider path (#265) ### Fixed - Recorder and fal record paths hardened — timeouts, threshold sanitizing, persist errors (#265) - attw ^0.18 fixes the test:exports crash (#263); OpenAI /v1/videos docs corrected (#264)
1 parent 056313b commit 27695ee

7 files changed

Lines changed: 17 additions & 145 deletions

File tree

.claude-plugin/marketplace.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"source": {
1010
"source": "npm",
1111
"package": "@copilotkit/aimock",
12-
"version": "^1.28.0"
12+
"version": "^1.31.0"
1313
},
1414
"description": "Fixture authoring skill for @copilotkit/aimock — LLM, multimedia (image/TTS/transcription/video), MCP, A2A, AG-UI, vector, embeddings, structured output, sequential responses, streaming physics, record/replay, agent loop patterns, and debugging"
1515
}

.claude-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "aimock",
3-
"version": "1.28.0",
3+
"version": "1.31.0",
44
"description": "Fixture authoring guidance for @copilotkit/aimock — LLM, multimedia, MCP, A2A, AG-UI, vector, and service mocking",
55
"author": {
66
"name": "CopilotKit"

CHANGELOG.md

Lines changed: 10 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -2,149 +2,21 @@
22

33
## [Unreleased]
44

5+
## [1.31.0] - 2026-06-10
6+
57
### Added
68

7-
- **OpenRouter async video lifecycle** — mocks OpenRouter's dedicated video-generation job API
8-
alongside the existing OpenAI-shaped `/v1/videos` handler; both draw from the same
9-
`endpoint: "video"` fixture pool. `POST /api/v1/videos` matches fixtures on `prompt`/`model`
10-
(endpoint `video`) and returns a `{ id, polling_url, status: "pending" }` job envelope (a
11-
model-less submit assumes the default `bytedance/seedance-2.0` model for fixture matching); the
12-
envelope reports `"pending"` for API fidelity even though, under the default thresholds, the job
13-
is already seeded terminal internally at submit. `GET /api/v1/videos/{jobId}` advances
14-
`pending → in_progress → completed | failed` per the new `openRouterVideo` poll-threshold config
15-
(same poll-threshold semantics as `falQueue`), adding `unsigned_urls` + `usage.cost` on
16-
completion and the fixture's `error` message on failure (a default "Video generation failed"
17-
message is used when the fixture has no `error` field). Because the job is server-side terminal
18-
at submit by default, content is downloadable with zero polls if the client constructs the
19-
content URL itself — the documented client flow still needs one status poll to learn
20-
`unsigned_urls`. `GET /api/v1/videos/{jobId}/content?index=0` requires Bearer auth (401
21-
otherwise) and serves the fixture's `b64` bytes — or a built-in minimal MP4 `ftyp` placeholder —
22-
always as `Content-Type: video/mp4` (matching production even when the client sends
23-
`Accept: application/octet-stream`). Status polls and the models listing are served without auth
24-
— only the content endpoint enforces Bearer (a deliberate, documented divergence). The `index`
25-
query param is accepted but ignored (jobs are single-video) — except when the content endpoint
26-
live-proxies an upstream (record mode's proxy-only operation, or the in-flight capture window
27-
below), where it selects the position-aligned upstream `unsigned_urls` entry — and the content
28-
endpoint does not advance job state — content URLs are only learned from a completed status poll
29-
(API fidelity; diverges from fal's advance-on-result). `GET /api/v1/videos/models` synthesizes
30-
the video-model
31-
listing from loaded video fixtures that specify a string `match.model` (falling back to a
32-
built-in default set otherwise). Video fixtures gain optional `error`, `b64`, and `cost` fields.
33-
Record mode is supported via the `"openrouter"` provider key
34-
(`record.providers.openrouter` / `--provider-openrouter <url>`) as a live interactive proxy: an
35-
unmatched submit is forwarded upstream and answered with a mock-rewritten envelope (fresh aimock
36-
jobId, `polling_url` pointing back at the mock with the testId embedded), and each client poll
37-
is proxied upstream and relayed with the mock identifiers substituted — `id`, a present
38-
`polling_url`, and a present `unsigned_urls` array (same length, one mock content URL per index)
39-
are rewritten (a non-array `unsigned_urls` cannot be index-rewritten and is stripped from the
40-
relay with a warning instead of leaking the upstream value); every other field (including
41-
`usage`, untouched — a non-number `usage.cost` warns but passes through) is relayed verbatim.
42-
When the upstream reports `completed`, the poll is relayed immediately and the eager capture
43-
runs in the background: `unsigned_urls[0]` is origin-checked against the configured provider
44-
and fetched server-side after the first completed poll has been answered — an SDK poller is
45-
never blocked on a multi-minute video download; the polling client's Bearer is forwarded only
46-
same-origin (off-origin content hosts are fetched without auth, with a warning) — and the
47-
bytes are persisted as a normal video fixture (`match.userMessage` = prompt, `match.model` =
48-
the submitted model as recorded by the standard model-normalization rules — date suffixes
49-
stripped unless `recordFullModelVersion`; model-less submits record the assumed default model
50-
`video.id` = the upstream job id) that replays in-session and across sessions. While the
51-
capture is in flight, the job is already observable as completed: status polls relay the
52-
upstream body and the content endpoint live-proxies downloads (no 400 window). A capture
53-
FAILURE — no usable `unsigned_urls`, an invalid content URL, or a content fetch that errors on
54-
headers, status, or body — persists NOTHING and leaves the job a live proxy, so the next
55-
completed poll retries the capture (each failure warns); the only degraded persist (fixture
56-
written without `b64`) is the over-cap path below, where a retry would always re-exceed the cap.
57-
`failed` jobs persist `{ status: "failed", error }` fixtures; `cancelled`/`expired` upstream
58-
statuses (not representable in `video.status`) pass through verbatim with a warning and are
59-
never recorded; an upstream `failed` body whose `error` is the canonical
60-
`{ message, code }` object records the extracted message (an unusable non-null `error` value
61-
warns and is omitted from the fixture; an explicit `null` is omitted without the warn).
62-
Recorded `b64` is capped at `record.openRouterVideo.maxContentBytes`
63-
(default 32 MB decoded, `0` = unlimited, negative/non-integer values are treated as the default
64-
with a `createServer` warning; exported as `OPENROUTER_VIDEO_DEFAULT_MAX_CONTENT_BYTES`): the
65-
cap guards memory as well as disk — a capture whose upstream response declares an over-cap
66-
`Content-Length` is skipped without downloading, an undeclared-length capture is streamed with
67-
the byte count enforced during the read (on exceed the download aborts and nothing oversized is
68-
retained), and in both cases the fixture is persisted without `b64` (with a `_warning` in the
69-
fixture file) and the placeholder is served even same-session. `GET /api/v1/videos/models` is
70-
relayed verbatim from the upstream in record mode (journaled `source: "proxy"`, never recorded
71-
as a fixture), falling back to the fixture-driven synthesis on upstream failure; strict mode
72-
disables the models proxy entirely. Strict mode wins over record (503 on a no-match, nothing
73-
proxied — a chaos roll on a strict no-fixture submit is labeled `source: "internal"`), and an
74-
effective-strict request also 503s a record job's status polls and live-proxied content
75-
downloads ("strict means nothing reaches an upstream", honoring per-request `X-AIMock-Strict`
76-
overrides). A missing provider URL warns and falls through to 404; upstream failures return 502
77-
`proxy_error` (a hung models fetch instead falls back 200 to the synthesized listing). The
78-
small-JSON upstream fetches (submit, poll, models) honor `record.upstreamTimeoutMs` (default
79-
30s) as a total deadline; the byte-bearing content fetches (eager capture, content relay) gate
80-
only the response headers on `upstreamTimeoutMs` and stream the body under
81-
`record.bodyTimeoutMs` idle semantics (re-armed per chunk), so a steadily-downloading long
82-
render never times out — only a mid-body stall aborts. Every proxied journal entry carries
83-
`source: "proxy"` (the synthesized models fallback after a failed proxy attempt is labeled
84-
`source: "internal"`), a fixture-write failure surfaces as an `X-AIMock-Record-Error` header on
85-
the relayed poll on the failed branch (the completed branch's capture is detached from the
86-
relay, so its persist failures are logged instead), and each successful (2xx) proxied poll, each
87-
replay-job poll, AND each successful content serve/relay refreshes the job's 1-hour TTL so long
88-
generations — and long download sessions — are not evicted mid-recording (or mid-polling); a
89-
relayed upstream 401/403 does NOT refresh the TTL.
90-
Upstream `401`/`403` rejections pass through to the client verbatim on all three proxied
91-
surfaces — submit, status poll, and content download — for real-API fidelity (the relayed
92-
401/403 bodies deliberately bypass the mock's identifier/URL rewriting: auth-error envelopes
93-
carry no job URLs, and fidelity of the provider's error body wins). Disabling recording
94-
mid-flight (`disableRecording()`) makes
95-
every later poll of an orphaned record job fail loudly with 502 before contacting the upstream —
96-
and content downloads too, when the job is completed (a pending/in_progress orphan's download
97-
still 400s as not-completed first; the 502 gate sits behind the completed check). Under
98-
`record.proxyOnly` nothing is persisted or cached: jobs stay
99-
live proxies after terminal polls and content downloads are live-proxied from the stored
100-
upstream `unsigned_urls[index]` on every fetch, with the bytes STREAMED to the client as they
101-
arrive — the video is never buffered in memory and the first bytes reach the client while the
102-
upstream is still sending (the same streamed relay serves capture-window downloads;
103-
position-aligned with the relayed array; an out-of-range or unusable index warns and falls back
104-
to index 0; same same-origin Bearer gate as the capture path; an upstream 401/403 on the
105-
content fetch passes through to the client for real-API fidelity). The four
106-
`handleOpenRouterVideo*` handlers,
107-
`OpenRouterVideoJobMap`, and `OPENROUTER_VIDEO_MAX_ENTRIES` are exported from the package root
108-
(matching the sibling video/fal surfaces). The CLI warns when
109-
`--upstream-timeout-ms`/`--body-timeout-ms` — or any `--provider-*` flag — are passed without
110-
`--record`/`--proxy-only` (previously parsed and silently dropped).
9+
- OpenRouter async video job lifecycle mock — submit, poll, content download, model listing (#262)
10+
- Record-mode live proxying for the OpenRouter video surface; captured videos replay later (#265)
11111

11212
### Changed
11313

114-
- **Proxy header forwarding (all providers)** — requests forwarded to a recording upstream now
115-
strip the mock-internal control headers `x-test-id`, `x-aimock-strict`, `x-aimock-context`, and
116-
the `x-aimock-chaos-*` prefix family on every provider proxy path (not just the new OpenRouter
117-
video surface). These headers are meaningless — and potentially confusing or leaky — on a real
118-
provider's wire; everything else still passes through as before. Note that because `x-test-id`
119-
is now stripped upstream, recording THROUGH a second aimock instance loses testId scoping on
120-
the inner instance.
121-
- **fal queue walk: same-origin envelope URLs** — the recording queue walk (fal and the legacy
122-
fal-audio path) now adopts the `status_url`/`response_url` an upstream submit envelope nominates
123-
only when they are same-origin with the configured upstream (the gate the OpenRouter video proxy
124-
applies to envelope `polling_url`s). Every walk fetch forwards the client's headers — including
125-
`Authorization` — so an envelope nominating a foreign host must never receive them; off-origin,
126-
unparseable, or absent envelope URLs fall back to the constructed canonical paths on the
127-
upstream origin, with a warning.
128-
129-
### Fixed
130-
131-
- **fal queue thresholds** — the progression resolver — now shared with the OpenRouter video
132-
surface — also sanitizes the pre-existing `falQueue` config: non-finite
133-
`pollsBeforeInProgress`/`pollsBeforeCompleted` values (NaN, Infinity) are treated as unset instead
134-
of stranding jobs short of a terminal status, negative/fractional values are floored and clamped
135-
to non-negative integers, and `createServer` now warns on invalid `falQueue`/`openRouterVideo`
136-
threshold values.
137-
- **fal queue walk: per-fetch timeout** — each of the walk's submit/status/result fetches is now
138-
bounded by `record.upstreamTimeoutMs` (30s default, additionally clamped to the walk's remaining
139-
`record.fal.timeoutMs` budget). Previously the walk-level timeout only fired BETWEEN polls, so a
140-
hung upstream socket could pin the walk indefinitely; it now surfaces through the existing
141-
502/no-fixture failure handling.
142-
- **fal queue walk: `pollIntervalMs: 0`** — a zero poll interval no longer produces a spurious
143-
"Queue walk timed out" on the first non-terminal poll; the walk only times out when the
144-
`timeoutMs` budget is actually exhausted ("poll as fast as possible" is a valid configuration).
145-
- **fal/fal-audio queue-walk persist failures** — a fixture-write failure on the queue-walk record
146-
paths now surfaces as an `X-AIMock-Record-Error` header on the synthesized envelope (parity with
147-
the generic recorder relay and the OpenRouter video failed branch).
14+
- Recording proxies now strip aimock-internal control headers on every provider path (#265)
15+
16+
### Fixed
17+
18+
- Recorder and fal record paths hardened — timeouts, threshold sanitizing, persist errors (#265)
19+
- attw ^0.18 fixes the test:exports crash (#263); OpenAI /v1/videos docs corrected (#264)
14820

14921
## [1.30.0] - 2026-06-09
15022

charts/aimock/Chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ name: aimock
33
description: Mock infrastructure for AI application testing (OpenAI, Anthropic, Gemini, MCP, A2A, vector)
44
type: application
55
version: 0.1.0
6-
appVersion: "1.30.0"
6+
appVersion: "1.31.0"

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@copilotkit/aimock",
3-
"version": "1.30.0",
4-
"description": "Mock infrastructure for AI application testing — LLM APIs, image generation, text-to-speech, transcription, audio generation, video generation, MCP tools, A2A agents, AG-UI event streams, vector databases, search, rerank, and moderation. One package, one port, zero dependencies.",
3+
"version": "1.31.0",
4+
"description": "Mock infrastructure for AI application testing — LLM APIs, image generation, image editing, text-to-speech, transcription, audio translation, audio generation, video generation, embeddings, MCP tools, A2A agents, AG-UI event streams, vector databases, search, rerank, and moderation. One package, one port, zero dependencies.",
55
"license": "MIT",
66
"keywords": [
77
"mock",

packages/aimock-pytest/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ aimock.reset() # alias for reset_fixtures()
7373

7474
```
7575
--aimock-node PATH Path to node binary
76-
--aimock-version VER aimock npm version (default: 1.7.0)
76+
--aimock-version VER aimock npm version (default: 1.31.0)
7777
```
7878

7979
## Environment Variables

packages/aimock-pytest/src/aimock_pytest/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@
88
control routes ship in the next release). Keep it tracking npm releases.
99
"""
1010

11-
AIMOCK_VERSION = "1.28.0"
11+
AIMOCK_VERSION = "1.31.0"

0 commit comments

Comments
 (0)