diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json
index 429f850b..ed44d8ce 100644
--- a/.claude-plugin/marketplace.json
+++ b/.claude-plugin/marketplace.json
@@ -9,7 +9,7 @@
"source": {
"source": "npm",
"package": "@copilotkit/aimock",
- "version": "^1.46.0"
+ "version": "^1.47.0"
},
"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"
}
diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json
index 6295719e..d84cafe7 100644
--- a/.claude-plugin/plugin.json
+++ b/.claude-plugin/plugin.json
@@ -1,6 +1,6 @@
{
"name": "aimock",
- "version": "1.46.0",
+ "version": "1.47.0",
"description": "Fixture authoring guidance for @copilotkit/aimock — LLM, multimedia, MCP, A2A, AG-UI, vector, and service mocking",
"author": {
"name": "CopilotKit"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a6712c6f..d3986aa4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,28 +1,17 @@
# @copilotkit/aimock
-## [Unreleased]
+## [1.47.0] - 2026-10-26
### Added
-- Fixture `citations` serve OpenAI Responses `url_citation` annotations; fixture `files` serve Gemini `inlineData` parts (#550 by @abhiaiyer91)
-- Fixture `citations` also serve Chat Completions `url_citation` annotations (`message.annotations`, one streamed `delta.annotations` chunk), Anthropic `web_search_result_location` citations on text blocks (`citations_delta` when streaming), and Gemini `groundingMetadata` (`groundingChunks` + `groundingSupports`, byte offsets). A citation with `type: "file"` (`fileId`, `filename`, optional `index`, which defaults to the end of the text) serves an OpenAI Responses `file_citation` annotation on `output_text`, streamed through `response.output_text.annotation.added`; Chat Completions, Anthropic and Gemini skip it. Closes #547.
-- Fixture `files` serve OpenAI Responses `image_generation_call` output items (`result` holds the base64 bytes), streamed with the `response.image_generation_call.*` events. Chat Completions and Anthropic Messages reject a fixture with `files` with a 500 carrying `aimock_unsupported_generated_file` (new `UnsupportedGeneratedFileError`). Closes #548.
-- Malformed fixture `citations` or `files` (not an array, a missing or mistyped field, a non-integer offset, an offset outside the text, or citations on a turn with no text: tool calls only, `blocks` with no text block, or empty content) answer a 500 before any content is written: `aimock_invalid_fixture_citation` or `aimock_invalid_fixture_file`. A non-`image/*` file on the OpenAI Responses API answers a 500 with `aimock_unsupported_generated_file`. This is the same on every wire that reads these keys, with or without a misbehavior fault: the fixture is checked on its original turn before any fault applies (only an invalid misbehavior config answers its own 400 or 501 first). A valid fixture under a fault that changes the reply text is served without its `citations`. Only Chat Completions, Anthropic Messages, Gemini and OpenAI Responses read these keys; other wires ignore them.
-- Fixture load validation warns about malformed `citations` and `files`, with the same problem description the 500 carries (the 500 message adds an `aimock: invalid fixture` prefix; the warning adds which 500 the requests answer). The fixture still loads.
-- `InvalidFixtureOutputError` (the error behind `aimock_invalid_fixture_citation` and `aimock_invalid_fixture_file`) is exported from `@copilotkit/aimock`.
-- Opt-in fixture `nonStreamingTimingAllProviders: true` delays non-streaming replies on OpenAI chat, Anthropic, Responses, Gemini/Vertex, Gemini Interactions, Cohere, Bedrock invoke/converse and Ollama; `nonStreamingTiming` is unchanged (OpenAI chat only); error replies are never delayed. On the OpenAI Responses API the wait also counts the stream frames that fixture `citations` and generated `files` add
-- Raw passthrough fixtures: a `raw` response (`wire`, `events`, `json`, optional `status`, `headers`, and `done` on `openai-chat`) sends provider events or JSON exactly as written, with only the named wire's framing, on the HTTP LLM wires (OpenAI Responses and Chat Completions, Anthropic, Gemini/Vertex, Gemini Interactions, Cohere, Ollama `/api/chat` as `ollama` and `/api/generate` as `ollama-generate`, Bedrock invoke and converse). A raw fixture matches only its own wire. A request whose mode has no body answers that wire's 500 with `aimock_raw_mode_unavailable`; an invalid raw fixture added in code answers a 500 with `aimock_raw_fixture_invalid`, and `--validate-on-load` reports it at load. Streaming timing, truncation, disconnects and chaos apply; misbehavior faults skip raw fixtures. A non-streaming raw reply follows `nonStreamingTiming` like a typed fixture: `nonStreamingTiming: true` delays it on OpenAI Chat Completions only, `nonStreamingTimingAllProviders: true` on every provider; a raw reply with status 400 or above is never delayed, and with a `json` it answers JSON even to a streaming request. WebSocket Responses answers a raw fixture with an error event with the code `aimock_raw_mode_unavailable`. New exported types `RawResponse`, `RawWireId` and `WireId` ([#549](https://github.com/CopilotKit/aimock/issues/549))
+- Fixture `citations` serve sources on Responses, Chat Completions, Claude and Gemini (#550, #578)
+- Fixture `files` serve generated images on Gemini and OpenAI Responses (#550, #578)
+- Raw passthrough fixtures send provider SSE events or JSON exactly as written (#580)
+- Opt-in `nonStreamingTimingAllProviders` delays non-streaming replies on every provider (#579)
### Fixed
-- Misbehavior faults on Chat Completions, Anthropic Messages, Gemini and the OpenAI Responses API (HTTP and WebSocket): a fixture the wire rejects (generated `files` on Chat Completions or Anthropic, a non-`image/*` file on Responses, malformed `citations` or `files`) is never faulted. It takes the normal path, is journaled as a 500 that keeps its fixture, and consumes no fault `times` budget or seed ordinal; `aimock_misbehavior_total` does not count it. A non-stream Chat Completions fault is journaled before its timing wait.
-- Journal accuracy: a client that hangs up during the timing wait of any non-stream Chat Completions reply (faulted or not) is journaled as interrupted, not as served.
-- Client disconnects stop delivery (no more chunks or waits) on OpenAI chat, Anthropic, Responses, Gemini/Vertex, Gemini Interactions, Cohere, Bedrock, Ollama, transcription streams and the Responses, Realtime and Gemini Live WebSockets
-- Client disconnects on those surfaces are journaled as `interrupted` with `interruptReason: "client aborted"` (HTTP `status: 0` when nothing was sent); aimock-caused teardowns record `"disconnect"`. Journal snapshots of hung-up requests now carry these fields
-- WebSocket: a client TCP FIN without a close frame now closes the connection at once (1006) and ends the turn
-- Daily drift: the OpenAI Responses K9 reasoning-exhaustion probes (HTTP and WebSocket) request `gpt-5.4-mini`. OpenAI retired `o4-mini` on 2026-10-23 (its `/v1/models` `shutdown_date`), and it has answered `404 model_not_found` since. The probe model is one constant, `OPENAI_K9_PROBE_MODEL`. The usage check accepts `output_tokens` equal to `output_tokens_details.reasoning_tokens` (gpt-5.4-mini spends the 32-token cap on reasoning; o4-mini reported 0). The event-order check is unchanged, and the retained o4-mini replay fixtures are still graded against o4-mini. Drift harness only; aimock behavior is unchanged (#584).
-- Daily drift: a preflight checks every model the live drift probes pin (`src/__tests__/drift/probe-models.ts`) against the provider's own retirement data before the run. A retired model fails the run with `probe model X retired on DATE — update OpenAI Chat Completions
raw passthrough fixture with
wire: "openai-chat".
+ Fixture citations serve url_citation annotations. A fixture with
+ generated files answers a 500, because Chat Completions has no place for
+ them. See Citations and generated files.
+
| citations | +array | ++ Source citations for the reply text, served on OpenAI Responses, Chat Completions, + Claude and Gemini (see + Citations and generated files) + | +
| files | +array | +
+ Model-generated files { mimeType, data }, served on Gemini and OpenAI
+ Responses (see Citations and generated files)
+ |
+
| systemFingerprint | string | @@ -1012,6 +1029,113 @@
+ A text reply can carry source citations, and a reply can carry model-generated files such
+ as images. Add citations or files next to content,
+ and aimock serves them in each provider's own wire shape, streaming and non-streaming. Use
+ them to test how your app shows sources and renders generated images.
+
{
+ "match": { "userMessage": "capital of France" },
+ "response": {
+ "content": "Paris is the capital of France.",
+ "citations": [
+ { "url": "https://en.wikipedia.org/wiki/Paris", "title": "Paris", "startIndex": 0, "endIndex": 5 },
+ { "type": "file", "fileId": "file-abc123", "filename": "notes.pdf" }
+ ]
+ }
+}
+
+ A URL citation needs url; title, startIndex and
+ endIndex are optional, and the span defaults to the whole text. Offsets are
+ JavaScript string positions in the reply text. A file citation (type: "file")
+ needs fileId and filename; its optional
+ index defaults to the end of the text.
+
{
+ "match": { "userMessage": "draw a cat" },
+ "response": {
+ "content": "Here is a cat.",
+ "files": [{ "mimeType": "image/png", "data": "iVBORw0KGgo..." }]
+ }
+}
+
+ data holds the base64 file bytes. Files are sent before the reply text and
+ tool calls.
+
| Wire | +citations |
+ files |
+
|---|---|---|
| OpenAI Responses (HTTP and WebSocket) | +
+ url_citation and file_citation annotations on
+ output_text, streamed with
+ response.output_text.annotation.added
+ |
+
+ image_generation_call output items (image/* only),
+ streamed with the response.image_generation_call.* events
+ |
+
| Chat Completions (OpenAI, Azure, OpenRouter) | +
+ url_citation in message.annotations; one
+ delta.annotations chunk when streaming. File citations are skipped
+ |
+ 500 aimock_unsupported_generated_file |
+
| Claude Messages | +
+ web_search_result_location citations on text blocks;
+ citations_delta when streaming. File citations are skipped
+ |
+ 500 aimock_unsupported_generated_file |
+
| Gemini and Vertex AI | +
+ groundingMetadata (groundingChunks and
+ groundingSupports, byte offsets). File citations are skipped
+ |
+ inlineData parts |
+
| Every other wire | +Ignored | +Ignored | +
+ Errors: a malformed citations or files value
+ (wrong type, missing field, an offset outside the text, or citations on a reply with no
+ text) answers a 500 with aimock_invalid_fixture_citation or
+ aimock_invalid_fixture_file before any content is sent. A non-image file on
+ the Responses API answers aimock_unsupported_generated_file. On the
+ Responses WebSocket these come as an error event. Fixture loading warns about the same
+ problems, and the fixture still loads.
+
| — | Yes | +|||||||||||||||||||||||||||||
| Citations | +URL | +URL + file | +URL | +URL | +— | +URL | +— | +URL | +— | +— | +URL | +|||||||||||||||||||
| Generated files | +Error | +Images | +Error | +Yes | +— | +Yes | +— | +Error | +— | +— | +Error | +|||||||||||||||||||
| Custom Tool Calls‡ | Error | diff --git a/docs/gemini/index.html b/docs/gemini/index.html index 852a1ecb..d8046f93 100644 --- a/docs/gemini/index.html +++ b/docs/gemini/index.html @@ -58,6 +58,11 @@
| Provider-native source citations | +
+ Built-in ✓ 1.47.0+ + |
+
+ manual | +manual | +manual | +ND | +ND | +manual | +manual | +
|---|---|---|---|---|---|---|---|---|
| Model-generated images in replies | +
+ Built-in ✓ 1.47.0+ + |
+
+ manual | +manual | +manual | +ND | +ND | +manual | +manual | +
| Client disconnect stops the reply on every provider | +
+ Built-in ✓ 1.47.0+ + |
+
+ ND | +ND | +ND | +partial | +partial | +ND | +ND | +
| Streaming physics | Built-in ✓ | diff --git a/docs/responses-api/index.html b/docs/responses-api/index.html index 41b26874..04ca811a 100644 --- a/docs/responses-api/index.html +++ b/docs/responses-api/index.html @@ -58,6 +58,12 @@