@copilotkit/aimock 1.42.1 → 1.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +65 -0
- package/README.md +108 -16
- package/dist/agui-handler.d.ts.map +1 -1
- package/dist/agui-mock.cjs +1 -1
- package/dist/agui-mock.cjs.map +1 -1
- package/dist/agui-mock.d.cts.map +1 -1
- package/dist/agui-mock.d.ts.map +1 -1
- package/dist/agui-mock.js +1 -1
- package/dist/agui-mock.js.map +1 -1
- package/dist/agui-recorder.cjs +33 -11
- package/dist/agui-recorder.cjs.map +1 -1
- package/dist/agui-recorder.d.cts +10 -1
- package/dist/agui-recorder.d.cts.map +1 -1
- package/dist/agui-recorder.d.ts +10 -1
- package/dist/agui-recorder.d.ts.map +1 -1
- package/dist/agui-recorder.js +33 -11
- package/dist/agui-recorder.js.map +1 -1
- package/dist/agui-types.d.cts +1 -0
- package/dist/agui-types.d.cts.map +1 -1
- package/dist/agui-types.d.ts +1 -0
- package/dist/agui-types.d.ts.map +1 -1
- package/dist/aimock-cli.cjs +38 -10
- package/dist/aimock-cli.cjs.map +1 -1
- package/dist/aimock-cli.d.cts +5 -0
- package/dist/aimock-cli.d.cts.map +1 -1
- package/dist/aimock-cli.d.ts +5 -0
- package/dist/aimock-cli.d.ts.map +1 -1
- package/dist/aimock-cli.js +38 -10
- package/dist/aimock-cli.js.map +1 -1
- package/dist/batches.cjs +458 -0
- package/dist/batches.cjs.map +1 -0
- package/dist/batches.d.cts +57 -0
- package/dist/batches.d.cts.map +1 -0
- package/dist/batches.d.ts +57 -0
- package/dist/batches.d.ts.map +1 -0
- package/dist/batches.js +453 -0
- package/dist/batches.js.map +1 -0
- package/dist/bedrock-converse.cjs +44 -12
- package/dist/bedrock-converse.cjs.map +1 -1
- package/dist/bedrock-converse.d.cts.map +1 -1
- package/dist/bedrock-converse.d.ts.map +1 -1
- package/dist/bedrock-converse.js +46 -14
- package/dist/bedrock-converse.js.map +1 -1
- package/dist/bedrock.cjs +10 -8
- package/dist/bedrock.cjs.map +1 -1
- package/dist/bedrock.d.cts.map +1 -1
- package/dist/bedrock.d.ts.map +1 -1
- package/dist/bedrock.js +12 -10
- package/dist/bedrock.js.map +1 -1
- package/dist/byteplus-video.cjs +3 -3
- package/dist/byteplus-video.cjs.map +1 -1
- package/dist/byteplus-video.js +4 -4
- package/dist/byteplus-video.js.map +1 -1
- package/dist/chaos.cjs +625 -72
- package/dist/chaos.cjs.map +1 -1
- package/dist/chaos.d.cts +164 -7
- package/dist/chaos.d.cts.map +1 -1
- package/dist/chaos.d.ts +164 -7
- package/dist/chaos.d.ts.map +1 -1
- package/dist/chaos.js +616 -74
- package/dist/chaos.js.map +1 -1
- package/dist/cli.cjs +131 -30
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +132 -31
- package/dist/cli.js.map +1 -1
- package/dist/cohere.cjs +37 -9
- package/dist/cohere.cjs.map +1 -1
- package/dist/cohere.d.cts.map +1 -1
- package/dist/cohere.d.ts.map +1 -1
- package/dist/cohere.js +39 -11
- package/dist/cohere.js.map +1 -1
- package/dist/config-loader.cjs +1 -1
- package/dist/config-loader.js +1 -1
- package/dist/constants.cjs +8 -0
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +6 -2
- package/dist/constants.d.ts +6 -2
- package/dist/constants.js +8 -1
- package/dist/constants.js.map +1 -1
- package/dist/convert.cjs +1 -1
- package/dist/convert.cjs.map +1 -1
- package/dist/convert.js +1 -1
- package/dist/convert.js.map +1 -1
- package/dist/echo-text.cjs +65 -0
- package/dist/echo-text.cjs.map +1 -0
- package/dist/echo-text.d.cts +22 -0
- package/dist/echo-text.d.cts.map +1 -0
- package/dist/echo-text.d.ts +22 -0
- package/dist/echo-text.d.ts.map +1 -0
- package/dist/echo-text.js +65 -0
- package/dist/echo-text.js.map +1 -0
- package/dist/elevenlabs-audio.cjs +3 -3
- package/dist/elevenlabs-audio.cjs.map +1 -1
- package/dist/elevenlabs-audio.js +4 -4
- package/dist/elevenlabs-audio.js.map +1 -1
- package/dist/elevenlabs-voice.cjs +1053 -0
- package/dist/elevenlabs-voice.cjs.map +1 -0
- package/dist/elevenlabs-voice.d.cts +72 -0
- package/dist/elevenlabs-voice.d.cts.map +1 -0
- package/dist/elevenlabs-voice.d.ts +72 -0
- package/dist/elevenlabs-voice.d.ts.map +1 -0
- package/dist/elevenlabs-voice.js +1048 -0
- package/dist/elevenlabs-voice.js.map +1 -0
- package/dist/embeddings.cjs +26 -5
- package/dist/embeddings.cjs.map +1 -1
- package/dist/embeddings.d.cts +1 -1
- package/dist/embeddings.d.cts.map +1 -1
- package/dist/embeddings.d.ts +1 -1
- package/dist/embeddings.d.ts.map +1 -1
- package/dist/embeddings.js +27 -6
- package/dist/embeddings.js.map +1 -1
- package/dist/fal-audio.cjs +3 -3
- package/dist/fal-audio.cjs.map +1 -1
- package/dist/fal-audio.js +4 -4
- package/dist/fal-audio.js.map +1 -1
- package/dist/fal.cjs +28 -4
- package/dist/fal.cjs.map +1 -1
- package/dist/fal.d.cts +16 -1
- package/dist/fal.d.cts.map +1 -1
- package/dist/fal.d.ts +16 -1
- package/dist/fal.d.ts.map +1 -1
- package/dist/fal.js +28 -5
- package/dist/fal.js.map +1 -1
- package/dist/files.cjs +1069 -0
- package/dist/files.cjs.map +1 -0
- package/dist/files.d.cts +68 -0
- package/dist/files.d.cts.map +1 -0
- package/dist/files.d.ts +68 -0
- package/dist/files.d.ts.map +1 -0
- package/dist/files.js +1056 -0
- package/dist/files.js.map +1 -0
- package/dist/fine-tuning.cjs +1033 -0
- package/dist/fine-tuning.cjs.map +1 -0
- package/dist/fine-tuning.d.cts +96 -0
- package/dist/fine-tuning.d.cts.map +1 -0
- package/dist/fine-tuning.d.ts +96 -0
- package/dist/fine-tuning.d.ts.map +1 -0
- package/dist/fine-tuning.js +1026 -0
- package/dist/fine-tuning.js.map +1 -0
- package/dist/fixture-loader-services.cjs +116 -0
- package/dist/fixture-loader-services.cjs.map +1 -0
- package/dist/fixture-loader-services.d.cts +48 -0
- package/dist/fixture-loader-services.d.cts.map +1 -0
- package/dist/fixture-loader-services.d.ts +48 -0
- package/dist/fixture-loader-services.d.ts.map +1 -0
- package/dist/fixture-loader-services.js +114 -0
- package/dist/fixture-loader-services.js.map +1 -0
- package/dist/fixture-loader.cjs +0 -0
- package/dist/fixture-loader.cjs.map +1 -1
- package/dist/fixture-loader.d.cts +131 -5
- package/dist/fixture-loader.d.cts.map +1 -1
- package/dist/fixture-loader.d.ts +131 -5
- package/dist/fixture-loader.d.ts.map +1 -1
- package/dist/fixture-loader.js +0 -0
- package/dist/fixture-loader.js.map +1 -1
- package/dist/gemini-embeddings.cjs +44 -4
- package/dist/gemini-embeddings.cjs.map +1 -1
- package/dist/gemini-embeddings.js +46 -6
- package/dist/gemini-embeddings.js.map +1 -1
- package/dist/gemini-interactions.cjs +51 -7
- package/dist/gemini-interactions.cjs.map +1 -1
- package/dist/gemini-interactions.d.cts.map +1 -1
- package/dist/gemini-interactions.d.ts.map +1 -1
- package/dist/gemini-interactions.js +53 -9
- package/dist/gemini-interactions.js.map +1 -1
- package/dist/gemini.cjs +19 -8
- package/dist/gemini.cjs.map +1 -1
- package/dist/gemini.d.cts.map +1 -1
- package/dist/gemini.d.ts.map +1 -1
- package/dist/gemini.js +21 -10
- package/dist/gemini.js.map +1 -1
- package/dist/grok-video.cjs +14 -14
- package/dist/grok-video.cjs.map +1 -1
- package/dist/grok-video.js +15 -15
- package/dist/grok-video.js.map +1 -1
- package/dist/helpers.cjs +497 -10
- package/dist/helpers.cjs.map +1 -1
- package/dist/helpers.d.cts +38 -2
- package/dist/helpers.d.cts.map +1 -1
- package/dist/helpers.d.ts +38 -2
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +487 -12
- package/dist/helpers.js.map +1 -1
- package/dist/images.cjs +57 -125
- package/dist/images.cjs.map +1 -1
- package/dist/images.d.cts.map +1 -1
- package/dist/images.d.ts.map +1 -1
- package/dist/images.js +58 -126
- package/dist/images.js.map +1 -1
- package/dist/index.cjs +71 -9
- package/dist/index.d.cts +17 -7
- package/dist/index.d.ts +17 -7
- package/dist/index.js +21 -11
- package/dist/jest.cjs +24 -12
- package/dist/jest.cjs.map +1 -1
- package/dist/jest.d.cts +6 -3
- package/dist/jest.d.cts.map +1 -1
- package/dist/jest.d.ts +6 -3
- package/dist/jest.d.ts.map +1 -1
- package/dist/jest.js +25 -13
- package/dist/jest.js.map +1 -1
- package/dist/journal.cjs +61 -4
- package/dist/journal.cjs.map +1 -1
- package/dist/journal.d.cts +60 -3
- package/dist/journal.d.cts.map +1 -1
- package/dist/journal.d.ts +60 -3
- package/dist/journal.d.ts.map +1 -1
- package/dist/journal.js +61 -5
- package/dist/journal.js.map +1 -1
- package/dist/live-fixture.cjs +1192 -0
- package/dist/live-fixture.cjs.map +1 -0
- package/dist/live-fixture.js +1187 -0
- package/dist/live-fixture.js.map +1 -0
- package/dist/live-recorder.cjs +256 -0
- package/dist/live-recorder.cjs.map +1 -0
- package/dist/live-recorder.js +254 -0
- package/dist/live-recorder.js.map +1 -0
- package/dist/live-replay.cjs +286 -0
- package/dist/live-replay.cjs.map +1 -0
- package/dist/live-replay.js +285 -0
- package/dist/live-replay.js.map +1 -0
- package/dist/live-sanitize.cjs +196 -0
- package/dist/live-sanitize.cjs.map +1 -0
- package/dist/live-sanitize.js +196 -0
- package/dist/live-sanitize.js.map +1 -0
- package/dist/live-types.d.cts +71 -0
- package/dist/live-types.d.cts.map +1 -0
- package/dist/live-types.d.ts +71 -0
- package/dist/live-types.d.ts.map +1 -0
- package/dist/llmock.cjs +132 -49
- package/dist/llmock.cjs.map +1 -1
- package/dist/llmock.d.cts +51 -5
- package/dist/llmock.d.cts.map +1 -1
- package/dist/llmock.d.ts +51 -5
- package/dist/llmock.d.ts.map +1 -1
- package/dist/llmock.js +133 -50
- package/dist/llmock.js.map +1 -1
- package/dist/mcp-fakes-mount.cjs +216 -0
- package/dist/mcp-fakes-mount.cjs.map +1 -0
- package/dist/mcp-fakes-mount.js +210 -0
- package/dist/mcp-fakes-mount.js.map +1 -0
- package/dist/mcp-fakes.cjs +1619 -0
- package/dist/mcp-fakes.cjs.map +1 -0
- package/dist/mcp-fakes.d.cts +101 -0
- package/dist/mcp-fakes.d.cts.map +1 -0
- package/dist/mcp-fakes.d.ts +101 -0
- package/dist/mcp-fakes.d.ts.map +1 -0
- package/dist/mcp-fakes.js +1614 -0
- package/dist/mcp-fakes.js.map +1 -0
- package/dist/mcp-handler.cjs +331 -17
- package/dist/mcp-handler.cjs.map +1 -1
- package/dist/mcp-handler.js +330 -18
- package/dist/mcp-handler.js.map +1 -1
- package/dist/mcp-mock.cjs +217 -49
- package/dist/mcp-mock.cjs.map +1 -1
- package/dist/mcp-mock.d.cts +66 -1
- package/dist/mcp-mock.d.cts.map +1 -1
- package/dist/mcp-mock.d.ts +66 -1
- package/dist/mcp-mock.d.ts.map +1 -1
- package/dist/mcp-mock.js +218 -50
- package/dist/mcp-mock.js.map +1 -1
- package/dist/mcp-stub.cjs +5 -1
- package/dist/mcp-stub.d.cts +3 -1
- package/dist/mcp-stub.d.ts +3 -1
- package/dist/mcp-stub.js +3 -1
- package/dist/mcp-types.d.cts +6 -0
- package/dist/mcp-types.d.ts +6 -0
- package/dist/message-text.cjs +192 -0
- package/dist/message-text.cjs.map +1 -0
- package/dist/message-text.d.cts +31 -0
- package/dist/message-text.d.cts.map +1 -0
- package/dist/message-text.d.ts +31 -0
- package/dist/message-text.d.ts.map +1 -0
- package/dist/message-text.js +184 -0
- package/dist/message-text.js.map +1 -0
- package/dist/messages.cjs +49 -7
- package/dist/messages.cjs.map +1 -1
- package/dist/messages.d.cts.map +1 -1
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +51 -9
- package/dist/messages.js.map +1 -1
- package/dist/metrics.cjs +278 -45
- package/dist/metrics.cjs.map +1 -1
- package/dist/metrics.d.cts +17 -7
- package/dist/metrics.d.cts.map +1 -1
- package/dist/metrics.d.ts +17 -7
- package/dist/metrics.d.ts.map +1 -1
- package/dist/metrics.js +270 -29
- package/dist/metrics.js.map +1 -1
- package/dist/moderation.cjs +10 -1
- package/dist/moderation.cjs.map +1 -1
- package/dist/moderation.d.cts.map +1 -1
- package/dist/moderation.d.ts.map +1 -1
- package/dist/moderation.js +10 -1
- package/dist/moderation.js.map +1 -1
- package/dist/ollama.cjs +10 -6
- package/dist/ollama.cjs.map +1 -1
- package/dist/ollama.d.cts.map +1 -1
- package/dist/ollama.d.ts.map +1 -1
- package/dist/ollama.js +11 -7
- package/dist/ollama.js.map +1 -1
- package/dist/openapi.cjs +3405 -0
- package/dist/openapi.cjs.map +1 -0
- package/dist/openapi.d.cts +30 -0
- package/dist/openapi.d.cts.map +1 -0
- package/dist/openapi.d.ts +30 -0
- package/dist/openapi.d.ts.map +1 -0
- package/dist/openapi.js +3404 -0
- package/dist/openapi.js.map +1 -0
- package/dist/openrouter-video.cjs +9 -9
- package/dist/openrouter-video.cjs.map +1 -1
- package/dist/openrouter-video.d.cts.map +1 -1
- package/dist/openrouter-video.d.ts.map +1 -1
- package/dist/openrouter-video.js +10 -10
- package/dist/openrouter-video.js.map +1 -1
- package/dist/recorder.cjs +54 -10
- package/dist/recorder.cjs.map +1 -1
- package/dist/recorder.d.cts.map +1 -1
- package/dist/recorder.d.ts.map +1 -1
- package/dist/recorder.js +52 -12
- package/dist/recorder.js.map +1 -1
- package/dist/responses.cjs +47 -7
- package/dist/responses.cjs.map +1 -1
- package/dist/responses.d.cts.map +1 -1
- package/dist/responses.d.ts.map +1 -1
- package/dist/responses.js +48 -9
- package/dist/responses.js.map +1 -1
- package/dist/route-registry.cjs +951 -0
- package/dist/route-registry.cjs.map +1 -0
- package/dist/route-registry.d.cts +33 -0
- package/dist/route-registry.d.cts.map +1 -0
- package/dist/route-registry.d.ts +33 -0
- package/dist/route-registry.d.ts.map +1 -0
- package/dist/route-registry.js +866 -0
- package/dist/route-registry.js.map +1 -0
- package/dist/router.cjs +21 -34
- package/dist/router.cjs.map +1 -1
- package/dist/router.d.cts +4 -1
- package/dist/router.d.cts.map +1 -1
- package/dist/router.d.ts +4 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +21 -35
- package/dist/router.js.map +1 -1
- package/dist/server.cjs +1252 -777
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +5 -1
- package/dist/server.d.cts.map +1 -1
- package/dist/server.d.ts +5 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1185 -710
- package/dist/server.js.map +1 -1
- package/dist/speech.cjs +6 -4
- package/dist/speech.cjs.map +1 -1
- package/dist/speech.js +7 -5
- package/dist/speech.js.map +1 -1
- package/dist/suite.cjs +1 -1
- package/dist/suite.js +1 -1
- package/dist/transcription.cjs +6 -6
- package/dist/transcription.cjs.map +1 -1
- package/dist/transcription.d.cts.map +1 -1
- package/dist/transcription.d.ts.map +1 -1
- package/dist/transcription.js +7 -7
- package/dist/transcription.js.map +1 -1
- package/dist/types.cjs +18 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +320 -17
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.ts +320 -17
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +17 -0
- package/dist/types.js.map +1 -0
- package/dist/validate-cli.cjs +983 -0
- package/dist/validate-cli.cjs.map +1 -0
- package/dist/validate-cli.js +982 -0
- package/dist/validate-cli.js.map +1 -0
- package/dist/vector-stores.cjs +1180 -0
- package/dist/vector-stores.cjs.map +1 -0
- package/dist/vector-stores.d.cts +106 -0
- package/dist/vector-stores.d.cts.map +1 -0
- package/dist/vector-stores.d.ts +106 -0
- package/dist/vector-stores.d.ts.map +1 -0
- package/dist/vector-stores.js +1164 -0
- package/dist/vector-stores.js.map +1 -0
- package/dist/vector-types.d.cts.map +1 -1
- package/dist/vector-types.d.ts.map +1 -1
- package/dist/veo-video.cjs +13 -13
- package/dist/veo-video.cjs.map +1 -1
- package/dist/veo-video.js +14 -14
- package/dist/veo-video.js.map +1 -1
- package/dist/video.cjs +23 -4
- package/dist/video.cjs.map +1 -1
- package/dist/video.d.cts +1 -1
- package/dist/video.d.cts.map +1 -1
- package/dist/video.d.ts +1 -1
- package/dist/video.d.ts.map +1 -1
- package/dist/video.js +24 -5
- package/dist/video.js.map +1 -1
- package/dist/vitest.cjs +23 -11
- package/dist/vitest.cjs.map +1 -1
- package/dist/vitest.d.cts +5 -2
- package/dist/vitest.d.cts.map +1 -1
- package/dist/vitest.d.ts +5 -2
- package/dist/vitest.d.ts.map +1 -1
- package/dist/vitest.js +25 -13
- package/dist/vitest.js.map +1 -1
- package/dist/watcher.cjs +2 -1
- package/dist/watcher.cjs.map +1 -1
- package/dist/watcher.js +2 -1
- package/dist/watcher.js.map +1 -1
- package/dist/ws-framing.cjs +150 -35
- package/dist/ws-framing.cjs.map +1 -1
- package/dist/ws-framing.d.cts +18 -3
- package/dist/ws-framing.d.cts.map +1 -1
- package/dist/ws-framing.d.ts +18 -3
- package/dist/ws-framing.d.ts.map +1 -1
- package/dist/ws-framing.js +151 -36
- package/dist/ws-framing.js.map +1 -1
- package/dist/ws-gemini-live.cjs +2 -2
- package/dist/ws-gemini-live.js +2 -2
- package/dist/ws-live.cjs +401 -0
- package/dist/ws-live.cjs.map +1 -0
- package/dist/ws-live.js +400 -0
- package/dist/ws-live.js.map +1 -0
- package/dist/ws-realtime.cjs +46 -2
- package/dist/ws-realtime.cjs.map +1 -1
- package/dist/ws-realtime.d.cts.map +1 -1
- package/dist/ws-realtime.d.ts.map +1 -1
- package/dist/ws-realtime.js +46 -2
- package/dist/ws-realtime.js.map +1 -1
- package/dist/ws-responses.cjs +16 -4
- package/dist/ws-responses.cjs.map +1 -1
- package/dist/ws-responses.js +16 -4
- package/dist/ws-responses.js.map +1 -1
- package/dist/ws-upstream.cjs +118 -0
- package/dist/ws-upstream.cjs.map +1 -0
- package/dist/ws-upstream.js +115 -0
- package/dist/ws-upstream.js.map +1 -0
- package/fixtures/openai-live-client.json +390 -0
- package/fixtures/openai-live-managed.json +709 -0
- package/package.json +4 -1
package/dist/responses.cjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
const require_model_utils = require('./model-utils.cjs');
|
|
2
2
|
const require_helpers = require('./helpers.cjs');
|
|
3
|
-
const require_router = require('./router.cjs');
|
|
4
3
|
const require_sse_writer = require('./sse-writer.cjs');
|
|
5
|
-
const require_interruption = require('./interruption.cjs');
|
|
6
4
|
const require_chaos = require('./chaos.cjs');
|
|
5
|
+
const require_router = require('./router.cjs');
|
|
7
6
|
const require_recorder = require('./recorder.cjs');
|
|
7
|
+
const require_interruption = require('./interruption.cjs');
|
|
8
8
|
|
|
9
9
|
//#region src/responses.ts
|
|
10
10
|
function extractTextContent(content) {
|
|
@@ -180,6 +180,10 @@ function buildTextStreamEvents(content, model, chunkSize, reasoning, webSearches
|
|
|
180
180
|
});
|
|
181
181
|
return events;
|
|
182
182
|
}
|
|
183
|
+
function requireFixtureToolArguments(value) {
|
|
184
|
+
if (typeof value !== "string") throw new Error("Invalid fixture tool call: \"arguments\" must be a string after normalization");
|
|
185
|
+
return value;
|
|
186
|
+
}
|
|
183
187
|
function buildToolCallStreamEvents(toolCalls, model, chunkSize, reasoning, webSearches, overrides, emitEncryptedReasoning = false, synthesizeSummarylessReasoning = false) {
|
|
184
188
|
const { respId, created, events, prefixOutputItems, nextOutputIndex } = buildResponsePreamble(model, chunkSize, reasoning, webSearches, overrides, emitEncryptedReasoning, synthesizeSummarylessReasoning);
|
|
185
189
|
const fcOutputItems = [];
|
|
@@ -200,7 +204,7 @@ function buildToolCallStreamEvents(toolCalls, model, chunkSize, reasoning, webSe
|
|
|
200
204
|
status: "in_progress"
|
|
201
205
|
}
|
|
202
206
|
});
|
|
203
|
-
const args = tc.arguments;
|
|
207
|
+
const args = requireFixtureToolArguments(tc.arguments);
|
|
204
208
|
for (let i = 0; i < args.length; i += chunkSize) {
|
|
205
209
|
const slice = args.slice(i, i + chunkSize);
|
|
206
210
|
events.push({
|
|
@@ -593,7 +597,7 @@ function buildMessageOutputEvents(content, chunkSize, outputIndex) {
|
|
|
593
597
|
function buildFunctionCallOutputEvents(toolCall, chunkSize, outputIndex) {
|
|
594
598
|
const callId = toolCall.id || require_helpers.generateToolCallId();
|
|
595
599
|
const fcId = require_helpers.generateId("fc");
|
|
596
|
-
const args = toolCall.arguments;
|
|
600
|
+
const args = requireFixtureToolArguments(toolCall.arguments);
|
|
597
601
|
const events = [];
|
|
598
602
|
events.push({
|
|
599
603
|
type: "response.output_item.added",
|
|
@@ -699,7 +703,7 @@ function buildToolCallResponse(toolCalls, model, reasoning, webSearches, overrid
|
|
|
699
703
|
id: require_helpers.generateId("fc"),
|
|
700
704
|
call_id: tc.id || require_helpers.generateToolCallId(),
|
|
701
705
|
name: tc.name,
|
|
702
|
-
arguments: tc.arguments,
|
|
706
|
+
arguments: requireFixtureToolArguments(tc.arguments),
|
|
703
707
|
status: "completed"
|
|
704
708
|
});
|
|
705
709
|
return buildResponseEnvelope(model, output, overrides);
|
|
@@ -757,7 +761,7 @@ function buildFunctionCallOutputItem(tc) {
|
|
|
757
761
|
id: require_helpers.generateId("fc"),
|
|
758
762
|
call_id: tc.id || require_helpers.generateToolCallId(),
|
|
759
763
|
name: tc.name,
|
|
760
|
-
arguments: tc.arguments,
|
|
764
|
+
arguments: requireFixtureToolArguments(tc.arguments),
|
|
761
765
|
status: "completed"
|
|
762
766
|
};
|
|
763
767
|
}
|
|
@@ -869,6 +873,41 @@ async function handleResponses(req, res, raw, fixtures, journal, defaults, setCo
|
|
|
869
873
|
} }));
|
|
870
874
|
return;
|
|
871
875
|
}
|
|
876
|
+
let inputError;
|
|
877
|
+
if (typeof responsesReq.input !== "string" && !Array.isArray(responsesReq.input)) inputError = "input must be a string or an array";
|
|
878
|
+
else if (Array.isArray(responsesReq.input)) for (const [index, item] of responsesReq.input.entries()) {
|
|
879
|
+
if (item === null) {
|
|
880
|
+
inputError = `input[${index}] must not be null`;
|
|
881
|
+
break;
|
|
882
|
+
}
|
|
883
|
+
if ((item.role === "system" || item.role === "developer" || item.role === "user" || item.role === "assistant") && item.content && typeof item.content !== "string" && !Array.isArray(item.content)) {
|
|
884
|
+
inputError = `input[${index}].content must be a string or an array`;
|
|
885
|
+
break;
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
let toolsError;
|
|
889
|
+
if (responsesReq.tools && responsesReq.tools.length !== 0) {
|
|
890
|
+
if (!Array.isArray(responsesReq.tools)) toolsError = "tools must be an array";
|
|
891
|
+
else if (responsesReq.tools.some((tool) => tool === null)) toolsError = "tools entries must not be null";
|
|
892
|
+
}
|
|
893
|
+
const validationError = inputError ?? toolsError;
|
|
894
|
+
if (validationError) {
|
|
895
|
+
journal.add({
|
|
896
|
+
method: req.method ?? "POST",
|
|
897
|
+
path: req.url ?? "/v1/responses",
|
|
898
|
+
headers: require_helpers.flattenHeaders(req.headers),
|
|
899
|
+
body: responsesReq,
|
|
900
|
+
response: {
|
|
901
|
+
status: 400,
|
|
902
|
+
fixture: null
|
|
903
|
+
}
|
|
904
|
+
});
|
|
905
|
+
require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
|
|
906
|
+
message: validationError,
|
|
907
|
+
type: "invalid_request_error"
|
|
908
|
+
} }));
|
|
909
|
+
return;
|
|
910
|
+
}
|
|
872
911
|
const completionReq = responsesToCompletionRequest(responsesReq);
|
|
873
912
|
completionReq._endpointType = "chat";
|
|
874
913
|
completionReq._context = require_helpers.getContext(req);
|
|
@@ -880,7 +919,7 @@ async function handleResponses(req, res, raw, fixtures, journal, defaults, setCo
|
|
|
880
919
|
defaults.logger.debug(`Responses fixture matched for ${req.method ?? "POST"} ${req.url ?? "/v1/responses"}`);
|
|
881
920
|
journal.incrementFixtureMatchCount(fixture, fixtures, testId);
|
|
882
921
|
} else defaults.logger.debug(`No responses fixture matched for ${req.method ?? "POST"} ${req.url ?? "/v1/responses"}`);
|
|
883
|
-
if (require_chaos.
|
|
922
|
+
if (await require_chaos.applyChaosAsync(res, fixture, defaults.chaos, req.headers, req.url, journal, {
|
|
884
923
|
method: req.method ?? "POST",
|
|
885
924
|
path: req.url ?? "/v1/responses",
|
|
886
925
|
headers: require_helpers.flattenHeaders(req.headers),
|
|
@@ -1094,6 +1133,7 @@ async function handleResponses(req, res, raw, fixtures, journal, defaults, setCo
|
|
|
1094
1133
|
|
|
1095
1134
|
//#endregion
|
|
1096
1135
|
exports.buildContentWithToolCallsStreamEvents = buildContentWithToolCallsStreamEvents;
|
|
1136
|
+
exports.buildTextResponse = buildTextResponse;
|
|
1097
1137
|
exports.buildTextStreamEvents = buildTextStreamEvents;
|
|
1098
1138
|
exports.buildToolCallStreamEvents = buildToolCallStreamEvents;
|
|
1099
1139
|
exports.handleResponses = handleResponses;
|
package/dist/responses.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"responses.cjs","names":["generateToolCallId","generateId","isReasoningModel","resolveFixtureBlocks","calculateDelay","delay","flattenHeaders","isJsonObject","getContext","getTestId","matchFixtureDiagnostic","recordMatchOptions","applyChaos","resolveStrictMode","strictNoMatchMessage","strictNoMatchLogLine","strictOverrideField","proxyAndRecord","resolveResponse","isErrorResponse","serializeErrorResponse","isContentWithToolCallsResponse","extractOverrides","resolveReasoningForModel","createInterruptionSignal","isTextResponse","isToolCallResponse"],"sources":["../src/responses.ts"],"sourcesContent":["/**\n * OpenAI Responses API support for aimock.\n *\n * Translates incoming /v1/responses requests into the ChatCompletionRequest\n * format used by the fixture router, and converts fixture responses back into\n * the Responses API streaming (or non-streaming) format expected by @ai-sdk/openai.\n */\n\nimport type * as http from \"node:http\";\nimport type {\n ChatCompletionRequest,\n ChatMessage,\n Fixture,\n FixtureBlock,\n HandlerDefaults,\n ResponseOverrides,\n StreamingProfile,\n ToolCall,\n ToolDefinition,\n} from \"./types.js\";\nimport {\n generateId,\n generateToolCallId,\n resolveFixtureBlocks,\n extractOverrides,\n isTextResponse,\n isToolCallResponse,\n isContentWithToolCallsResponse,\n isErrorResponse,\n serializeErrorResponse,\n flattenHeaders,\n isJsonObject,\n getTestId,\n resolveResponse,\n resolveStrictMode,\n resolveReasoningForModel,\n strictOverrideField,\n getContext,\n strictNoMatchMessage,\n strictNoMatchLogLine,\n} from \"./helpers.js\";\nimport { isReasoningModel } from \"./model-utils.js\";\nimport { matchFixtureDiagnostic, recordMatchOptions } from \"./router.js\";\nimport { writeErrorResponse, delay, calculateDelay } from \"./sse-writer.js\";\nimport { createInterruptionSignal } from \"./interruption.js\";\nimport type { RecordedTimings } from \"./types.js\";\nimport type { Journal } from \"./journal.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\n// ─── Responses API request types ────────────────────────────────────────────\n\ninterface ResponsesInputItem {\n role?: string;\n type?: string;\n content?: string | ResponsesContentPart[];\n call_id?: string;\n name?: string;\n arguments?: string;\n output?: string;\n id?: string;\n}\n\ninterface ResponsesContentPart {\n type: string;\n text?: string;\n}\n\ninterface ResponsesRequest {\n model: string;\n input: string | ResponsesInputItem[];\n instructions?: string;\n tools?: ResponsesToolDef[];\n tool_choice?: string | object;\n stream?: boolean;\n temperature?: number;\n max_output_tokens?: number;\n response_format?: { type: string; [key: string]: unknown };\n // Additional output data requested by the caller, e.g.\n // \"reasoning.encrypted_content\" (gates encrypted-reasoning emission).\n include?: string[];\n // Server-side storage flag. `false` (ZDR / stateless replay) is one of the\n // triggers for encrypted reasoning; see `requestWantsEncryptedReasoning`.\n store?: boolean;\n [key: string]: unknown;\n}\n\ninterface ResponsesToolDef {\n type: \"function\";\n name: string;\n description?: string;\n parameters?: object;\n strict?: boolean;\n}\n\n// ─── Input conversion: Responses → ChatCompletions messages ─────────────────\n\nfunction extractTextContent(content: string | ResponsesContentPart[] | undefined): string {\n if (!content) return \"\";\n if (typeof content === \"string\") return content;\n return content\n .filter((p) => p.type === \"input_text\" || p.type === \"output_text\")\n .map((p) => p.text ?? \"\")\n .join(\"\");\n}\n\nexport function responsesInputToMessages(req: ResponsesRequest): ChatMessage[] {\n const messages: ChatMessage[] = [];\n // Track item_reference placeholders so we can upgrade or clean them up\n const itemReferencePlaceholders = new WeakSet<ChatMessage>();\n\n // instructions field → system message\n if (req.instructions) {\n messages.push({ role: \"system\", content: req.instructions });\n }\n\n // The OpenAI Responses API accepts either a plain string or an array of input items.\n // When a string is passed, treat it as a single user message.\n if (typeof req.input === \"string\") {\n messages.push({ role: \"user\", content: req.input });\n return messages;\n }\n\n for (const item of req.input) {\n if (item.role === \"system\" || item.role === \"developer\") {\n messages.push({ role: \"system\", content: extractTextContent(item.content) });\n } else if (item.role === \"user\") {\n messages.push({ role: \"user\", content: extractTextContent(item.content) });\n } else if (item.role === \"assistant\") {\n messages.push({ role: \"assistant\", content: extractTextContent(item.content) });\n } else if (item.type === \"function_call\") {\n // Previous assistant tool call — emit as assistant message with tool_calls\n messages.push({\n role: \"assistant\",\n content: null,\n tool_calls: [\n {\n id: item.call_id ?? generateToolCallId(),\n type: \"function\",\n function: { name: item.name ?? \"\", arguments: item.arguments ?? \"\" },\n },\n ],\n });\n } else if (item.type === \"function_call_output\") {\n // Bug 1 fix: If there's no preceding assistant message with a matching\n // tool_call for this call_id, synthesize one. This happens when the AI SDK\n // sends [user, item_reference, function_call_output] — the item_reference\n // placeholder (see below) has no tool_calls, so we need a real assistant\n // message with the tool_call for turnIndex counting.\n const hasMatchingToolCall = messages.some(\n (m) => m.role === \"assistant\" && m.tool_calls?.some((tc) => tc.id === item.call_id),\n );\n if (!hasMatchingToolCall) {\n // Check if the last message is an item_reference placeholder — if so,\n // upgrade it to carry the tool_call instead of synthesizing a duplicate.\n const lastMsg = messages[messages.length - 1];\n if (\n lastMsg &&\n lastMsg.role === \"assistant\" &&\n itemReferencePlaceholders.has(lastMsg) &&\n !lastMsg.tool_calls\n ) {\n lastMsg.content = null;\n lastMsg.tool_calls = [\n {\n id: item.call_id ?? generateToolCallId(),\n type: \"function\",\n function: { name: \"\", arguments: \"\" },\n },\n ];\n itemReferencePlaceholders.delete(lastMsg);\n } else {\n // Multi-fco case: look for a recent assistant with tool_calls that\n // belongs to the same turn. After the first fco upgrades a placeholder,\n // subsequent fco's see [assistant(call_A), tool(call_A)] — the last\n // assistant with tool_calls (right before the trailing tool messages)\n // is the correct target.\n let appended = false;\n for (let k = messages.length - 1; k >= 0; k--) {\n const m = messages[k];\n if (m.role === \"assistant\" && m.tool_calls) {\n m.tool_calls.push({\n id: item.call_id ?? generateToolCallId(),\n type: \"function\",\n function: { name: \"\", arguments: \"\" },\n });\n appended = true;\n break;\n }\n // Stop scanning if we hit a user message — different turn\n if (m.role === \"user\") break;\n }\n if (!appended) {\n messages.push({\n role: \"assistant\",\n content: null,\n tool_calls: [\n {\n id: item.call_id ?? generateToolCallId(),\n type: \"function\",\n function: { name: \"\", arguments: \"\" },\n },\n ],\n });\n }\n }\n }\n messages.push({\n role: \"tool\",\n content: item.output ?? \"\",\n tool_call_id: item.call_id,\n });\n } else if (item.type === \"item_reference\") {\n // Bug 6 fix: item_reference items represent prior assistant turns (text\n // or function_call). Push a placeholder so they count in assistantCount.\n // If a subsequent function_call_output arrives, the handler above will\n // upgrade this placeholder to carry tool_calls (avoiding double-count).\n const placeholder: ChatMessage = { role: \"assistant\", content: \"\" };\n itemReferencePlaceholders.add(placeholder);\n messages.push(placeholder);\n } else {\n // Skip local_shell_call, mcp_list_tools, etc. — not needed for fixture\n // matching.\n }\n }\n\n return messages;\n}\n\nfunction responsesToolsToCompletionsTools(\n tools?: ResponsesToolDef[],\n): ToolDefinition[] | undefined {\n if (!tools || tools.length === 0) return undefined;\n return tools\n .filter((t) => t.type === \"function\")\n .map((t) => ({\n type: \"function\" as const,\n function: { name: t.name, description: t.description, parameters: t.parameters },\n }));\n}\n\nexport function responsesToCompletionRequest(req: ResponsesRequest): ChatCompletionRequest {\n return {\n model: req.model,\n messages: responsesInputToMessages(req),\n stream: req.stream,\n temperature: req.temperature,\n max_tokens: req.max_output_tokens,\n tools: responsesToolsToCompletionsTools(req.tools),\n tool_choice: req.tool_choice,\n response_format: req.response_format,\n };\n}\n\n// ─── Response building: fixture → Responses API format ──────────────────────\n\nfunction responsesStatus(finishReason: string | undefined, defaultStatus: string): string {\n if (!finishReason) return defaultStatus;\n if (finishReason === \"stop\") return \"completed\";\n if (finishReason === \"tool_calls\") return \"completed\";\n if (finishReason === \"length\") return \"incomplete\";\n if (finishReason === \"content_filter\") return \"failed\";\n return finishReason;\n}\n\nfunction responsesUsage(overrides?: ResponseOverrides): {\n input_tokens: number;\n output_tokens: number;\n total_tokens: number;\n} {\n if (!overrides?.usage) return { input_tokens: 0, output_tokens: 0, total_tokens: 0 };\n const input = overrides.usage.input_tokens ?? overrides.usage.prompt_tokens ?? 0;\n const output = overrides.usage.output_tokens ?? overrides.usage.completion_tokens ?? 0;\n return {\n input_tokens: input,\n output_tokens: output,\n total_tokens: overrides.usage.total_tokens ?? input + output,\n };\n}\n\nfunction responseId(): string {\n return generateId(\"resp\");\n}\n\nfunction itemId(): string {\n return generateId(\"msg\");\n}\n\n// Streaming events for Responses API\n\nexport interface ResponsesSSEEvent {\n type: string;\n [key: string]: unknown;\n}\n\nexport function buildTextStreamEvents(\n content: string,\n model: string,\n chunkSize: number,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n emitEncryptedReasoning = false,\n synthesizeSummarylessReasoning = false,\n): ResponsesSSEEvent[] {\n const { respId, created, events, prefixOutputItems, nextOutputIndex } = buildResponsePreamble(\n model,\n chunkSize,\n reasoning,\n webSearches,\n overrides,\n emitEncryptedReasoning,\n synthesizeSummarylessReasoning,\n );\n\n const { events: msgEvents, msgItem } = buildMessageOutputEvents(\n content,\n chunkSize,\n nextOutputIndex,\n );\n events.push(...msgEvents);\n\n events.push({\n type: \"response.completed\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: overrides?.model ?? model,\n status: responsesStatus(overrides?.finishReason, \"completed\"),\n output: [...prefixOutputItems, msgItem],\n usage: responsesUsage(overrides),\n },\n });\n\n return events;\n}\n\nexport function buildToolCallStreamEvents(\n toolCalls: ToolCall[],\n model: string,\n chunkSize: number,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n emitEncryptedReasoning = false,\n synthesizeSummarylessReasoning = false,\n): ResponsesSSEEvent[] {\n const { respId, created, events, prefixOutputItems, nextOutputIndex } = buildResponsePreamble(\n model,\n chunkSize,\n reasoning,\n webSearches,\n overrides,\n emitEncryptedReasoning,\n synthesizeSummarylessReasoning,\n );\n\n const fcOutputItems: object[] = [];\n\n for (let idx = 0; idx < toolCalls.length; idx++) {\n const tc = toolCalls[idx];\n const callId = tc.id || generateToolCallId();\n const fcId = generateId(\"fc\");\n const outputIndex = nextOutputIndex + idx;\n\n // output_item.added (function_call)\n events.push({\n type: \"response.output_item.added\",\n output_index: outputIndex,\n item: {\n type: \"function_call\",\n id: fcId,\n call_id: callId,\n name: tc.name,\n arguments: \"\",\n status: \"in_progress\",\n },\n });\n\n // function_call_arguments.delta\n const args = tc.arguments;\n for (let i = 0; i < args.length; i += chunkSize) {\n const slice = args.slice(i, i + chunkSize);\n events.push({\n type: \"response.function_call_arguments.delta\",\n item_id: fcId,\n output_index: outputIndex,\n delta: slice,\n });\n }\n\n // function_call_arguments.done\n events.push({\n type: \"response.function_call_arguments.done\",\n item_id: fcId,\n output_index: outputIndex,\n arguments: args,\n });\n\n const doneItem = {\n type: \"function_call\",\n id: fcId,\n call_id: callId,\n name: tc.name,\n arguments: args,\n status: \"completed\",\n };\n\n // output_item.done\n events.push({\n type: \"response.output_item.done\",\n output_index: outputIndex,\n item: doneItem,\n });\n\n fcOutputItems.push(doneItem);\n }\n\n // response.completed\n events.push({\n type: \"response.completed\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: overrides?.model ?? model,\n status: responsesStatus(overrides?.finishReason, \"completed\"),\n output: [...prefixOutputItems, ...fcOutputItems],\n usage: responsesUsage(overrides),\n },\n });\n\n return events;\n}\n\n/**\n * Whether the incoming Responses request should receive encrypted reasoning.\n *\n * Two observed triggers, gated on EITHER:\n * - `include: [\"reasoning.encrypted_content\"]` — the explicit opt-in, and what\n * `agent-framework-openai` >= 1.11.0 auto-appends on its stateless-replay path\n * (it never sends `store`), so this is the branch that fires for real clients.\n * - `store: false` — captured responses carry the blob when not server-side\n * stored (ZDR) and omit it when stored; kept as a secondary trigger for\n * clients that go stateless without opting in via `include`.\n *\n * Stored / opted-out replays stay byte-identical. Exported so the WebSocket\n * Responses transport can share one gate.\n */\nexport function requestWantsEncryptedReasoning(req: ResponsesRequest): boolean {\n if (requestIncludesEncryptedReasoning(req)) return true;\n return req.store === false;\n}\n\n/**\n * Whether the request carries the EXPLICIT `include` opt-in — a strictly\n * narrower gate than `requestWantsEncryptedReasoning`, which also fires on\n * `store: false`.\n *\n * This is the gate for SYNTHESIZING a reasoning item that the fixture does not\n * declare (see `shouldSynthesizeBlobOnlyReasoning`), and it is deliberately the\n * narrow one. Attaching a field to an item aimock was already emitting is a much\n * smaller step than conjuring a whole output item that did not previously exist,\n * so the larger behavior change gets the gate that is directly observable in the\n * request rather than the inferred `store: false` one. `agent-framework-openai`\n * >= 1.11.0 auto-appends `include` on its stateless-replay path and never sends\n * `store` at all, so the motivating client is fully served by this branch — the\n * narrowing costs the feature nothing.\n *\n * Exported so the WebSocket Responses transport shares one gate.\n */\nexport function requestIncludesEncryptedReasoning(req: ResponsesRequest): boolean {\n const include = req.include;\n return Array.isArray(include) && include.includes(\"reasoning.encrypted_content\");\n}\n\n/**\n * Synthetic stand-in for OpenAI's opaque `reasoning.encrypted_content`. aimock\n * has no real ciphertext; it emits a base64 placeholder derived from the\n * reasoning id (stable for a given item, opaque like the real field). Consumers\n * store it (e.g. as agent-framework `protected_data`) and replay it verbatim;\n * aimock matches on content and ignores the echoed blob. Without it,\n * agent-framework-openai >= 1.11.0 hard-fails a reasoning + multi-tool chain on\n * the follow-up request. See microsoft/agent-framework#7233.\n *\n * aimock skips inbound reasoning items entirely, so it cannot reproduce\n * OpenAI's `invalid_encrypted_content` rejection of a mismatched blob/id — a\n * known replay-only limitation.\n */\nfunction syntheticEncryptedReasoning(reasoningId: string): string {\n return Buffer.from(`aimock-encrypted-reasoning:${reasoningId}`).toString(\"base64\");\n}\n\n/**\n * Build a Responses `reasoning` output item. `summaryText` controls the summary\n * (present for the terminal `done` / non-streaming item, omitted for the\n * in-progress `added` item); `emitEncrypted` controls the blob INDEPENDENTLY of\n * the summary, so a blob with an empty summary is expressible. aimock emits the\n * blob only on the terminal item and omits it on `added`: real OpenAI populates\n * `added` opportunistically, but the field is `anyOf: [string, null]` and\n * non-required, so consumers should read it at `done` and treat `added` as\n * best-effort — omitting there is legal and harmless.\n */\nfunction buildReasoningOutputItem(\n reasoningId: string,\n opts: { summaryText?: string; emitEncrypted?: boolean } = {},\n): Record<string, unknown> {\n const item: Record<string, unknown> = {\n type: \"reasoning\",\n id: reasoningId,\n summary:\n opts.summaryText === undefined ? [] : [{ type: \"summary_text\", text: opts.summaryText }],\n };\n if (opts.emitEncrypted) {\n item.encrypted_content = syntheticEncryptedReasoning(reasoningId);\n }\n return item;\n}\n\n/**\n * Whether to synthesize a summary-LESS reasoning item that exists purely to\n * carry the encrypted blob.\n *\n * Every reasoning item aimock emits otherwise originates in a fixture's declared\n * `reasoning` summary text. But a fixture RECORDED from the real stateless\n * agent-framework flow typically has NO summary — OpenAI returns `summary: []`\n * unless summaries are explicitly requested — so keying the item on a declared\n * summary starves the exact flow this feature exists to serve: fully opted in,\n * yet no reasoning item and therefore no blob. Real OpenAI, for a\n * reasoning-capable model, still returns a reasoning item (`summary: []`) with\n * the blob populated. So synthesize one, gated on:\n *\n * - the EXPLICIT `include` opt-in ONLY (`requestIncludesEncryptedReasoning`),\n * which is NARROWER than the `requestWantsEncryptedReasoning` gate that\n * controls the blob itself. A `store: false` request whose fixture declares no\n * summary therefore gets NO reasoning item, exactly as before this change.\n * Two reasons: (1) creating an output item that did not previously exist is a\n * bigger behavior change than adding a field to an item already being\n * emitted, so it earns the gate that is directly observable in the request\n * rather than the inferred one; (2) the `store: false` trigger's supporting\n * capture evidence is not verifiable from this repo, and a larger change must\n * not be stacked on an unverifiable premise. `agent-framework-openai` >=\n * 1.11.0 sends `include` and never `store`, so nothing is lost.\n * - the REQUESTED model's reasoning capability (aimock#254) — emitting a\n * reasoning item for gpt-4o would be LESS faithful, not more, since that\n * model has no reasoning channel at all. Unlike `resolveReasoningForModel`,\n * which fails open for a declared summary (a recorded summary is evidence the\n * model did reason), there is nothing to preserve here: a synthesized item on\n * a non-reasoning model would be pure fabrication, so this gate is hard.\n *\n * Note this is INDEPENDENT of `emitEncryptedReasoning`: when a fixture DOES\n * declare a summary, the blob still rides on it under either trigger (including\n * `store: false`), unchanged.\n */\nfunction shouldSynthesizeBlobOnlyReasoning(\n reasoning: string | undefined,\n model: string | undefined,\n synthesizeSummarylessReasoning: boolean,\n): boolean {\n if (reasoning) return false; // a declared summary already produces the item\n if (!synthesizeSummarylessReasoning) return false; // no explicit `include` opt-in\n return isReasoningModel(model);\n}\n\n/**\n * `reasoning` is `undefined` for a synthesized blob-only item (see\n * `shouldSynthesizeBlobOnlyReasoning`). In that case the item's `summary` is\n * `[]`, so the summary-part / summary-text events are SKIPPED entirely — they\n * would describe a part that does not exist on the item — leaving a coherent\n * `output_item.added` → `output_item.done` pair with nothing between.\n */\nfunction buildReasoningStreamEvents(\n reasoning: string | undefined,\n chunkSize: number,\n emitEncryptedReasoning = false,\n): ResponsesSSEEvent[] {\n const reasoningId = generateId(\"rs\");\n const events: ResponsesSSEEvent[] = [];\n\n events.push({\n type: \"response.output_item.added\",\n output_index: 0,\n item: buildReasoningOutputItem(reasoningId),\n });\n\n if (reasoning !== undefined) {\n events.push({\n type: \"response.reasoning_summary_part.added\",\n item_id: reasoningId,\n output_index: 0,\n summary_index: 0,\n part: { type: \"summary_text\", text: \"\" },\n });\n\n for (let i = 0; i < reasoning.length; i += chunkSize) {\n const slice = reasoning.slice(i, i + chunkSize);\n events.push({\n type: \"response.reasoning_summary_text.delta\",\n item_id: reasoningId,\n output_index: 0,\n summary_index: 0,\n delta: slice,\n });\n }\n\n events.push({\n type: \"response.reasoning_summary_text.done\",\n item_id: reasoningId,\n output_index: 0,\n summary_index: 0,\n text: reasoning,\n });\n\n events.push({\n type: \"response.reasoning_summary_part.done\",\n item_id: reasoningId,\n output_index: 0,\n summary_index: 0,\n part: { type: \"summary_text\", text: reasoning },\n });\n }\n\n events.push({\n type: \"response.output_item.done\",\n output_index: 0,\n item: buildReasoningOutputItem(reasoningId, {\n summaryText: reasoning,\n emitEncrypted: emitEncryptedReasoning,\n }),\n });\n\n return events;\n}\n\nfunction buildWebSearchStreamEvents(\n queries: string[],\n startOutputIndex: number,\n): ResponsesSSEEvent[] {\n const events: ResponsesSSEEvent[] = [];\n\n for (let i = 0; i < queries.length; i++) {\n const searchId = generateId(\"ws\");\n const outputIndex = startOutputIndex + i;\n\n events.push({\n type: \"response.output_item.added\",\n output_index: outputIndex,\n item: {\n type: \"web_search_call\",\n id: searchId,\n status: \"in_progress\",\n action: { type: \"search\", query: queries[i] },\n },\n });\n\n events.push({\n type: \"response.output_item.done\",\n output_index: outputIndex,\n item: {\n type: \"web_search_call\",\n id: searchId,\n status: \"completed\",\n action: { type: \"search\", query: queries[i] },\n },\n });\n }\n\n return events;\n}\n\n// ─── Shared streaming helpers ────────────────────────────────────────────────\n\ninterface PreambleResult {\n respId: string;\n created: number;\n events: ResponsesSSEEvent[];\n prefixOutputItems: object[];\n nextOutputIndex: number;\n}\n\nfunction buildResponsePreamble(\n model: string,\n chunkSize: number,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n emitEncryptedReasoning = false,\n synthesizeSummarylessReasoning = false,\n): PreambleResult {\n const respId = overrides?.id ?? responseId();\n const created = overrides?.created ?? Math.floor(Date.now() / 1000);\n const effectiveModel = overrides?.model ?? model;\n const events: ResponsesSSEEvent[] = [];\n const prefixOutputItems: object[] = [];\n let nextOutputIndex = 0;\n\n events.push({\n type: \"response.created\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: effectiveModel,\n status: \"in_progress\",\n output: [],\n },\n });\n events.push({\n type: \"response.in_progress\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: effectiveModel,\n status: \"in_progress\",\n output: [],\n },\n });\n\n if (\n reasoning ||\n shouldSynthesizeBlobOnlyReasoning(reasoning, model, synthesizeSummarylessReasoning)\n ) {\n const reasoningEvents = buildReasoningStreamEvents(\n reasoning,\n chunkSize,\n emitEncryptedReasoning,\n );\n events.push(...reasoningEvents);\n const doneEvent = reasoningEvents.find(\n (e) =>\n e.type === \"response.output_item.done\" &&\n (e.item as { type: string })?.type === \"reasoning\",\n );\n if (doneEvent) prefixOutputItems.push(doneEvent.item as object);\n nextOutputIndex++;\n }\n\n if (webSearches && webSearches.length > 0) {\n const searchEvents = buildWebSearchStreamEvents(webSearches, nextOutputIndex);\n events.push(...searchEvents);\n const doneEvents = searchEvents.filter(\n (e) =>\n e.type === \"response.output_item.done\" &&\n (e.item as { type: string })?.type === \"web_search_call\",\n );\n for (const de of doneEvents) prefixOutputItems.push(de.item as object);\n nextOutputIndex += webSearches.length;\n }\n\n return { respId, created, events, prefixOutputItems, nextOutputIndex };\n}\n\ninterface MessageBlockResult {\n events: ResponsesSSEEvent[];\n msgItem: object;\n}\n\nfunction buildMessageOutputEvents(\n content: string,\n chunkSize: number,\n outputIndex: number,\n): MessageBlockResult {\n const msgId = itemId();\n const events: ResponsesSSEEvent[] = [];\n\n events.push({\n type: \"response.output_item.added\",\n output_index: outputIndex,\n item: { type: \"message\", id: msgId, status: \"in_progress\", role: \"assistant\", content: [] },\n });\n events.push({\n type: \"response.content_part.added\",\n item_id: msgId,\n output_index: outputIndex,\n content_index: 0,\n part: { type: \"output_text\", text: \"\", annotations: [] },\n });\n\n for (let i = 0; i < content.length; i += chunkSize) {\n events.push({\n type: \"response.output_text.delta\",\n item_id: msgId,\n output_index: outputIndex,\n content_index: 0,\n delta: content.slice(i, i + chunkSize),\n });\n }\n\n events.push({\n type: \"response.output_text.done\",\n item_id: msgId,\n output_index: outputIndex,\n content_index: 0,\n text: content,\n });\n events.push({\n type: \"response.content_part.done\",\n item_id: msgId,\n output_index: outputIndex,\n content_index: 0,\n part: { type: \"output_text\", text: content, annotations: [] },\n });\n\n const msgItem = {\n type: \"message\",\n id: msgId,\n status: \"completed\",\n role: \"assistant\",\n content: [{ type: \"output_text\", text: content, annotations: [] }],\n };\n\n events.push({ type: \"response.output_item.done\", output_index: outputIndex, item: msgItem });\n\n return { events, msgItem };\n}\n\ninterface FunctionCallBlockResult {\n events: ResponsesSSEEvent[];\n fcItem: object;\n}\n\n/**\n * Emit the output_item.added → arguments deltas → arguments.done →\n * output_item.done events for a single function_call at `outputIndex`,\n * returning the completed item for the final `output` array. Behavior is\n * identical to the inline per-tool-call loop in the legacy path; both the\n * legacy branch and the ordered-blocks branch share this so wire output stays\n * byte-identical for a given (tool, outputIndex).\n */\nfunction buildFunctionCallOutputEvents(\n toolCall: ToolCall,\n chunkSize: number,\n outputIndex: number,\n): FunctionCallBlockResult {\n const callId = toolCall.id || generateToolCallId();\n const fcId = generateId(\"fc\");\n const args = toolCall.arguments;\n const events: ResponsesSSEEvent[] = [];\n\n events.push({\n type: \"response.output_item.added\",\n output_index: outputIndex,\n item: {\n type: \"function_call\",\n id: fcId,\n call_id: callId,\n name: toolCall.name,\n arguments: \"\",\n status: \"in_progress\",\n },\n });\n\n for (let i = 0; i < args.length; i += chunkSize) {\n events.push({\n type: \"response.function_call_arguments.delta\",\n item_id: fcId,\n output_index: outputIndex,\n delta: args.slice(i, i + chunkSize),\n });\n }\n\n events.push({\n type: \"response.function_call_arguments.done\",\n item_id: fcId,\n output_index: outputIndex,\n arguments: args,\n });\n\n const fcItem = {\n type: \"function_call\",\n id: fcId,\n call_id: callId,\n name: toolCall.name,\n arguments: args,\n status: \"completed\",\n };\n events.push({ type: \"response.output_item.done\", output_index: outputIndex, item: fcItem });\n\n return { events, fcItem };\n}\n\n// ─── Non-streaming response builders ────────────────────────────────────────\n\nfunction buildOutputPrefix(\n content: string,\n model: string,\n reasoning?: string,\n webSearches?: string[],\n emitEncryptedReasoning = false,\n synthesizeSummarylessReasoning = false,\n): object[] {\n const output: object[] = [];\n\n if (\n reasoning ||\n shouldSynthesizeBlobOnlyReasoning(reasoning, model, synthesizeSummarylessReasoning)\n ) {\n output.push(\n buildReasoningOutputItem(generateId(\"rs\"), {\n summaryText: reasoning,\n emitEncrypted: emitEncryptedReasoning,\n }),\n );\n }\n\n if (webSearches && webSearches.length > 0) {\n for (const query of webSearches) {\n output.push({\n type: \"web_search_call\",\n id: generateId(\"ws\"),\n status: \"completed\",\n action: { type: \"search\", query },\n });\n }\n }\n\n output.push({\n type: \"message\",\n id: itemId(),\n status: \"completed\",\n role: \"assistant\",\n content: [{ type: \"output_text\", text: content, annotations: [] }],\n });\n\n return output;\n}\n\nfunction buildResponseEnvelope(\n model: string,\n output: object[],\n overrides?: ResponseOverrides,\n): object {\n return {\n id: overrides?.id ?? responseId(),\n object: \"response\",\n created_at: overrides?.created ?? Math.floor(Date.now() / 1000),\n model: overrides?.model ?? model,\n status: responsesStatus(overrides?.finishReason, \"completed\"),\n output,\n usage: responsesUsage(overrides),\n };\n}\n\nfunction buildTextResponse(\n content: string,\n model: string,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n emitEncryptedReasoning = false,\n synthesizeSummarylessReasoning = false,\n): object {\n return buildResponseEnvelope(\n model,\n buildOutputPrefix(\n content,\n model,\n reasoning,\n webSearches,\n emitEncryptedReasoning,\n synthesizeSummarylessReasoning,\n ),\n overrides,\n );\n}\n\nfunction buildToolCallResponse(\n toolCalls: ToolCall[],\n model: string,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n emitEncryptedReasoning = false,\n synthesizeSummarylessReasoning = false,\n): object {\n const output: object[] = [];\n if (\n reasoning ||\n shouldSynthesizeBlobOnlyReasoning(reasoning, model, synthesizeSummarylessReasoning)\n ) {\n output.push(\n buildReasoningOutputItem(generateId(\"rs\"), {\n summaryText: reasoning,\n emitEncrypted: emitEncryptedReasoning,\n }),\n );\n }\n if (webSearches && webSearches.length > 0) {\n for (const query of webSearches) {\n output.push({\n type: \"web_search_call\",\n id: generateId(\"ws\"),\n status: \"completed\",\n action: { type: \"search\", query },\n });\n }\n }\n for (const tc of toolCalls) {\n output.push({\n type: \"function_call\",\n id: generateId(\"fc\"),\n call_id: tc.id || generateToolCallId(),\n name: tc.name,\n arguments: tc.arguments,\n status: \"completed\",\n });\n }\n return buildResponseEnvelope(model, output, overrides);\n}\n\nexport function buildContentWithToolCallsStreamEvents(\n content: string,\n toolCalls: ToolCall[],\n model: string,\n chunkSize: number,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n blocks?: FixtureBlock[],\n emitEncryptedReasoning = false,\n synthesizeSummarylessReasoning = false,\n): ResponsesSSEEvent[] {\n const { respId, created, events, prefixOutputItems, nextOutputIndex } = buildResponsePreamble(\n model,\n chunkSize,\n reasoning,\n webSearches,\n overrides,\n emitEncryptedReasoning,\n synthesizeSummarylessReasoning,\n );\n\n // The output items assembled in emission order (after any reasoning /\n // web-search prefix items). Each output_index is assigned sequentially as we\n // walk the chosen item order, so the `output_index` on every emitted event\n // matches that item's slot in the final `response.completed.output` array.\n const orderedOutputItems: object[] = [];\n\n if (blocks && blocks.length > 0) {\n // NEW PATH: stream items in the fixture's block ARRAY ORDER. A toolCall\n // block placed before a text block therefore yields a function_call item at\n // a LOWER output_index than the message — it leads the output array.\n const ordered = resolveFixtureBlocks(blocks);\n let outputIndex = nextOutputIndex;\n for (const block of ordered) {\n if (block.type === \"text\") {\n const { events: msgEvents, msgItem } = buildMessageOutputEvents(\n block.text,\n chunkSize,\n outputIndex,\n );\n events.push(...msgEvents);\n orderedOutputItems.push(msgItem);\n } else {\n const { events: fcEvents, fcItem } = buildFunctionCallOutputEvents(\n { name: block.name, arguments: block.arguments, id: block.id },\n chunkSize,\n outputIndex,\n );\n events.push(...fcEvents);\n orderedOutputItems.push(fcItem);\n }\n outputIndex += 1;\n }\n } else {\n // LEGACY PATH: message item first, then function_call items — byte-for-byte\n // unchanged from the pre-blocks behavior (message always leads the output).\n const { events: msgEvents, msgItem } = buildMessageOutputEvents(\n content,\n chunkSize,\n nextOutputIndex,\n );\n events.push(...msgEvents);\n orderedOutputItems.push(msgItem);\n\n for (let idx = 0; idx < toolCalls.length; idx++) {\n const fcOutputIndex = nextOutputIndex + 1 + idx;\n const { events: fcEvents, fcItem } = buildFunctionCallOutputEvents(\n toolCalls[idx],\n chunkSize,\n fcOutputIndex,\n );\n events.push(...fcEvents);\n orderedOutputItems.push(fcItem);\n }\n }\n\n events.push({\n type: \"response.completed\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: overrides?.model ?? model,\n status: responsesStatus(overrides?.finishReason, \"completed\"),\n output: [...prefixOutputItems, ...orderedOutputItems],\n usage: responsesUsage(overrides),\n },\n });\n\n return events;\n}\n\nfunction buildFunctionCallOutputItem(tc: { name: string; arguments: string; id?: string }): object {\n return {\n type: \"function_call\",\n id: generateId(\"fc\"),\n call_id: tc.id || generateToolCallId(),\n name: tc.name,\n arguments: tc.arguments,\n status: \"completed\",\n };\n}\n\nfunction buildMessageOutputItem(content: string): object {\n return {\n type: \"message\",\n id: itemId(),\n status: \"completed\",\n role: \"assistant\",\n content: [{ type: \"output_text\", text: content, annotations: [] }],\n };\n}\n\nfunction buildContentWithToolCallsResponse(\n content: string,\n toolCalls: ToolCall[],\n model: string,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n blocks?: FixtureBlock[],\n emitEncryptedReasoning = false,\n synthesizeSummarylessReasoning = false,\n): object {\n if (blocks && blocks.length > 0) {\n // NEW PATH: the non-streaming `output[]` array is positionally observable,\n // so emit the prefix (reasoning / web_search_call), then the blocks in\n // fixture ARRAY ORDER. A toolCall block before a text block therefore\n // yields a function_call item ahead of the message — matching the streaming\n // path's ordering for the same `blocks` fixture.\n const ordered = resolveFixtureBlocks(blocks);\n const output: object[] = [];\n if (\n reasoning ||\n shouldSynthesizeBlobOnlyReasoning(reasoning, model, synthesizeSummarylessReasoning)\n ) {\n output.push(\n buildReasoningOutputItem(generateId(\"rs\"), {\n summaryText: reasoning,\n emitEncrypted: emitEncryptedReasoning,\n }),\n );\n }\n if (webSearches && webSearches.length > 0) {\n for (const query of webSearches) {\n output.push({\n type: \"web_search_call\",\n id: generateId(\"ws\"),\n status: \"completed\",\n action: { type: \"search\", query },\n });\n }\n }\n for (const block of ordered) {\n if (block.type === \"text\") {\n output.push(buildMessageOutputItem(block.text));\n } else {\n output.push(\n buildFunctionCallOutputItem({\n name: block.name,\n arguments: block.arguments,\n id: block.id,\n }),\n );\n }\n }\n return buildResponseEnvelope(model, output, overrides);\n }\n\n // LEGACY PATH: message item first, then function_call items — unchanged.\n const output = buildOutputPrefix(\n content,\n model,\n reasoning,\n webSearches,\n emitEncryptedReasoning,\n synthesizeSummarylessReasoning,\n );\n for (const tc of toolCalls) {\n output.push(buildFunctionCallOutputItem(tc));\n }\n return buildResponseEnvelope(model, output, overrides);\n}\n\n// ─── SSE writer for Responses API ───────────────────────────────────────────\n\ninterface ResponsesStreamOptions {\n latency?: number;\n streamingProfile?: StreamingProfile;\n recordedTimings?: RecordedTimings;\n replaySpeed?: number;\n signal?: AbortSignal;\n onChunkSent?: () => void;\n}\n\nasync function writeResponsesSSEStream(\n res: http.ServerResponse,\n events: ResponsesSSEEvent[],\n optionsOrLatency?: number | ResponsesStreamOptions,\n): Promise<boolean> {\n const opts: ResponsesStreamOptions =\n typeof optionsOrLatency === \"number\" ? { latency: optionsOrLatency } : (optionsOrLatency ?? {});\n const latency = opts.latency ?? 0;\n const profile = opts.streamingProfile;\n const { recordedTimings, replaySpeed } = opts;\n const signal = opts.signal;\n const onChunkSent = opts.onChunkSent;\n\n if (res.writableEnded) return true;\n res.setHeader(\"Content-Type\", \"text/event-stream\");\n res.setHeader(\"Cache-Control\", \"no-cache\");\n res.setHeader(\"Connection\", \"keep-alive\");\n\n let chunkIndex = 0;\n for (const event of events) {\n const chunkDelay = calculateDelay(chunkIndex, profile, latency, recordedTimings, replaySpeed);\n if (chunkDelay > 0) await delay(chunkDelay, signal);\n if (signal?.aborted) return false;\n if (res.writableEnded) return true;\n res.write(`event: ${event.type}\\ndata: ${JSON.stringify(event)}\\n\\n`);\n onChunkSent?.();\n if (signal?.aborted) return false;\n chunkIndex++;\n }\n\n if (!res.writableEnded) {\n res.end();\n }\n return true;\n}\n\n// ─── Request handler ────────────────────────────────────────────────────────\n\nexport async function handleResponses(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n raw: string,\n fixtures: Fixture[],\n journal: Journal,\n defaults: HandlerDefaults,\n setCorsHeaders: (res: http.ServerResponse) => void,\n): Promise<void> {\n setCorsHeaders(res);\n\n let responsesReq: ResponsesRequest;\n try {\n responsesReq = JSON.parse(raw) as ResponsesRequest;\n } catch (parseErr) {\n const detail = parseErr instanceof Error ? parseErr.message : \"unknown\";\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: `Malformed JSON: ${detail}`,\n type: \"invalid_request_error\",\n code: \"invalid_json\",\n },\n }),\n );\n return;\n }\n\n // Reject bodies that parsed but are not a JSON object (e.g. `null`) before\n // touching fields — otherwise `responsesReq.model` throws a TypeError that\n // surfaces as a 500 instead of a 400.\n if (!isJsonObject(responsesReq)) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Request body must be a JSON object\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n // Convert to ChatCompletionRequest for fixture matching\n const completionReq = responsesToCompletionRequest(responsesReq);\n completionReq._endpointType = \"chat\";\n completionReq._context = getContext(req);\n\n // Emit a synthetic `reasoning.encrypted_content` only when the request wants it\n // (opted in via `include`, or stateless `store: false` — mirrors real OpenAI).\n // This is what agent-framework-openai >= 1.11.0 sends on stateless-replay\n // requests; without the blob it hard-fails a reasoning + multi-tool chain.\n // See microsoft/agent-framework#7233.\n const emitEncryptedReasoning = requestWantsEncryptedReasoning(responsesReq);\n // Synthesizing a reasoning item the fixture never declared is a bigger step\n // than adding a field to one already being emitted, so it takes the NARROWER\n // explicit-`include` gate: a `store: false` request with a summary-less fixture\n // keeps emitting no reasoning item at all. See\n // `shouldSynthesizeBlobOnlyReasoning`.\n const synthesizeSummarylessReasoning = requestIncludesEncryptedReasoning(responsesReq);\n\n const testId = getTestId(req);\n const { fixture, skippedBySequenceOrTurn } = matchFixtureDiagnostic(\n fixtures,\n completionReq,\n journal.getFixtureMatchCountsForTest(testId),\n defaults.requestTransform,\n // Record mode proxies on a miss to capture a fresh turn (see record gate\n // below), so keep turnIndex strict to prevent an earlier-turn fixture from\n // shadowing a longer request and skipping the new turn's recording.\n recordMatchOptions(!!defaults.record, defaults.logger),\n );\n\n if (fixture) {\n defaults.logger.debug(\n `Responses fixture matched for ${req.method ?? \"POST\"} ${req.url ?? \"/v1/responses\"}`,\n );\n journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n } else {\n defaults.logger.debug(\n `No responses fixture matched for ${req.method ?? \"POST\"} ${req.url ?? \"/v1/responses\"}`,\n );\n }\n\n if (\n applyChaos(\n res,\n fixture,\n defaults.chaos,\n req.headers,\n req.url,\n journal,\n {\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n },\n fixture ? \"fixture\" : \"proxy\",\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n if (effectiveStrict) {\n const strictStatus = 503;\n const strictMessage = strictNoMatchMessage(skippedBySequenceOrTurn);\n defaults.logger.error(\n strictNoMatchLogLine(\n req.method ?? \"POST\",\n req.url ?? \"/v1/responses\",\n skippedBySequenceOrTurn,\n ),\n );\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: {\n status: strictStatus,\n fixture: null,\n ...strictOverrideField(defaults.strict, req.headers),\n },\n });\n writeErrorResponse(\n res,\n strictStatus,\n JSON.stringify({\n error: {\n message: strictMessage,\n type: \"invalid_request_error\",\n code: \"no_fixture_match\",\n },\n }),\n );\n return;\n }\n if (defaults.record) {\n const outcome = await proxyAndRecord(\n req,\n res,\n completionReq,\n \"openai\",\n req.url ?? \"/v1/responses\",\n fixtures,\n defaults,\n raw,\n );\n if (outcome === \"handled_by_hook\") return;\n if (outcome !== \"not_configured\") {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: res.statusCode ?? 200, fixture: null, source: \"proxy\" },\n });\n return;\n }\n }\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: {\n status: 404,\n fixture: null,\n ...strictOverrideField(defaults.strict, req.headers),\n },\n });\n writeErrorResponse(\n res,\n 404,\n JSON.stringify({\n error: {\n message: \"No fixture matched\",\n type: \"invalid_request_error\",\n code: \"no_fixture_match\",\n },\n }),\n );\n return;\n }\n\n const response = await resolveResponse(fixture, completionReq);\n const latency = fixture.latency ?? defaults.latency;\n const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);\n const fixtureTimings = fixture.recordedTimings;\n const effectiveReplaySpeed = fixture.replaySpeed ?? defaults.replaySpeed;\n\n // Error response\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status, fixture },\n });\n writeErrorResponse(res, status, serializeErrorResponse(response), {\n retryAfter: response.retryAfter,\n });\n return;\n }\n\n // Combined content + tool calls response\n if (isContentWithToolCallsResponse(response)) {\n const overrides = extractOverrides(response);\n // Gate reasoning emission on the requested model's capability (aimock#254).\n const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n const effReasoning = resolveReasoningForModel(\n response.reasoning,\n completionReq.model,\n effectiveStrict,\n defaults.logger,\n );\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (responsesReq.stream !== true) {\n const body = buildContentWithToolCallsResponse(\n response.content ?? \"\",\n response.toolCalls ?? [],\n completionReq.model,\n effReasoning,\n response.webSearches,\n overrides,\n response.blocks,\n emitEncryptedReasoning,\n synthesizeSummarylessReasoning,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildContentWithToolCallsStreamEvents(\n response.content ?? \"\",\n response.toolCalls ?? [],\n completionReq.model,\n chunkSize,\n effReasoning,\n response.webSearches,\n overrides,\n response.blocks,\n emitEncryptedReasoning,\n synthesizeSummarylessReasoning,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeResponsesSSEStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\n recordedTimings: fixtureTimings,\n replaySpeed: effectiveReplaySpeed,\n signal: interruption?.signal,\n onChunkSent: interruption?.tick,\n });\n if (!completed) {\n if (!res.writableEnded) res.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n }\n interruption?.cleanup();\n }\n return;\n }\n\n // Text response\n if (isTextResponse(response)) {\n const overrides = extractOverrides(response);\n // Gate reasoning emission on the requested model's capability (aimock#254).\n const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n const effReasoning = resolveReasoningForModel(\n response.reasoning,\n completionReq.model,\n effectiveStrict,\n defaults.logger,\n );\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (responsesReq.stream !== true) {\n const body = buildTextResponse(\n response.content,\n completionReq.model,\n effReasoning,\n response.webSearches,\n overrides,\n emitEncryptedReasoning,\n synthesizeSummarylessReasoning,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildTextStreamEvents(\n response.content,\n completionReq.model,\n chunkSize,\n effReasoning,\n response.webSearches,\n overrides,\n emitEncryptedReasoning,\n synthesizeSummarylessReasoning,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeResponsesSSEStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\n recordedTimings: fixtureTimings,\n replaySpeed: effectiveReplaySpeed,\n signal: interruption?.signal,\n onChunkSent: interruption?.tick,\n });\n if (!completed) {\n if (!res.writableEnded) res.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n }\n interruption?.cleanup();\n }\n return;\n }\n\n // Tool call response\n if (isToolCallResponse(response)) {\n const overrides = extractOverrides(response);\n // Gate reasoning emission on the requested model's capability (aimock#254).\n const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n const effReasoning = resolveReasoningForModel(\n response.reasoning,\n completionReq.model,\n effectiveStrict,\n defaults.logger,\n );\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (responsesReq.stream !== true) {\n const body = buildToolCallResponse(\n response.toolCalls,\n completionReq.model,\n effReasoning,\n response.webSearches,\n overrides,\n emitEncryptedReasoning,\n synthesizeSummarylessReasoning,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildToolCallStreamEvents(\n response.toolCalls,\n completionReq.model,\n chunkSize,\n effReasoning,\n response.webSearches,\n overrides,\n emitEncryptedReasoning,\n synthesizeSummarylessReasoning,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeResponsesSSEStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\n recordedTimings: fixtureTimings,\n replaySpeed: effectiveReplaySpeed,\n signal: interruption?.signal,\n onChunkSent: interruption?.tick,\n });\n if (!completed) {\n if (!res.writableEnded) res.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n }\n interruption?.cleanup();\n }\n return;\n }\n\n // Unknown response type\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: { message: \"Fixture response did not match any known type\", type: \"server_error\" },\n }),\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"responses.cjs","names":["generateToolCallId","generateId","isReasoningModel","resolveFixtureBlocks","calculateDelay","delay","flattenHeaders","isJsonObject","getContext","getTestId","matchFixtureDiagnostic","recordMatchOptions","applyChaosAsync","resolveStrictMode","strictNoMatchMessage","strictNoMatchLogLine","strictOverrideField","proxyAndRecord","resolveResponse","isErrorResponse","serializeErrorResponse","isContentWithToolCallsResponse","extractOverrides","resolveReasoningForModel","createInterruptionSignal","isTextResponse","isToolCallResponse"],"sources":["../src/responses.ts"],"sourcesContent":["/**\n * OpenAI Responses API support for aimock.\n *\n * Translates incoming /v1/responses requests into the ChatCompletionRequest\n * format used by the fixture router, and converts fixture responses back into\n * the Responses API streaming (or non-streaming) format expected by @ai-sdk/openai.\n */\n\nimport type * as http from \"node:http\";\nimport type {\n ChatCompletionRequest,\n ChatMessage,\n Fixture,\n FixtureBlock,\n HandlerDefaults,\n ResponseOverrides,\n StreamingProfile,\n ToolCall,\n ToolDefinition,\n} from \"./types.js\";\nimport {\n generateId,\n generateToolCallId,\n resolveFixtureBlocks,\n extractOverrides,\n isTextResponse,\n isToolCallResponse,\n isContentWithToolCallsResponse,\n isErrorResponse,\n serializeErrorResponse,\n flattenHeaders,\n isJsonObject,\n getTestId,\n resolveResponse,\n resolveStrictMode,\n resolveReasoningForModel,\n strictOverrideField,\n getContext,\n strictNoMatchMessage,\n strictNoMatchLogLine,\n} from \"./helpers.js\";\nimport { isReasoningModel } from \"./model-utils.js\";\nimport { matchFixtureDiagnostic, recordMatchOptions } from \"./router.js\";\nimport { writeErrorResponse, delay, calculateDelay } from \"./sse-writer.js\";\nimport { createInterruptionSignal } from \"./interruption.js\";\nimport type { RecordedTimings } from \"./types.js\";\nimport type { Journal } from \"./journal.js\";\nimport { applyChaosAsync } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\n// ─── Responses API request types ────────────────────────────────────────────\n\ninterface ResponsesInputItem {\n role?: string;\n type?: string;\n content?: string | ResponsesContentPart[];\n call_id?: string;\n name?: string;\n arguments?: string;\n output?: string;\n id?: string;\n}\n\ninterface ResponsesContentPart {\n type: string;\n text?: string;\n}\n\ninterface ResponsesRequest {\n model: string;\n input: string | ResponsesInputItem[];\n instructions?: string;\n tools?: ResponsesToolDef[];\n tool_choice?: string | object;\n stream?: boolean;\n temperature?: number;\n max_output_tokens?: number;\n response_format?: { type: string; [key: string]: unknown };\n // Additional output data requested by the caller, e.g.\n // \"reasoning.encrypted_content\" (gates encrypted-reasoning emission).\n include?: string[];\n // Server-side storage flag. `false` (ZDR / stateless replay) is one of the\n // triggers for encrypted reasoning; see `requestWantsEncryptedReasoning`.\n store?: boolean;\n [key: string]: unknown;\n}\n\ninterface ResponsesToolDef {\n type: \"function\";\n name: string;\n description?: string;\n parameters?: object;\n strict?: boolean;\n}\n\n// ─── Input conversion: Responses → ChatCompletions messages ─────────────────\n\nfunction extractTextContent(content: string | ResponsesContentPart[] | undefined): string {\n if (!content) return \"\";\n if (typeof content === \"string\") return content;\n return content\n .filter((p) => p.type === \"input_text\" || p.type === \"output_text\")\n .map((p) => p.text ?? \"\")\n .join(\"\");\n}\n\nexport function responsesInputToMessages(req: ResponsesRequest): ChatMessage[] {\n const messages: ChatMessage[] = [];\n // Track item_reference placeholders so we can upgrade or clean them up\n const itemReferencePlaceholders = new WeakSet<ChatMessage>();\n\n // instructions field → system message\n if (req.instructions) {\n messages.push({ role: \"system\", content: req.instructions });\n }\n\n // The OpenAI Responses API accepts either a plain string or an array of input items.\n // When a string is passed, treat it as a single user message.\n if (typeof req.input === \"string\") {\n messages.push({ role: \"user\", content: req.input });\n return messages;\n }\n\n for (const item of req.input) {\n if (item.role === \"system\" || item.role === \"developer\") {\n messages.push({ role: \"system\", content: extractTextContent(item.content) });\n } else if (item.role === \"user\") {\n messages.push({ role: \"user\", content: extractTextContent(item.content) });\n } else if (item.role === \"assistant\") {\n messages.push({ role: \"assistant\", content: extractTextContent(item.content) });\n } else if (item.type === \"function_call\") {\n // Previous assistant tool call — emit as assistant message with tool_calls\n messages.push({\n role: \"assistant\",\n content: null,\n tool_calls: [\n {\n id: item.call_id ?? generateToolCallId(),\n type: \"function\",\n function: { name: item.name ?? \"\", arguments: item.arguments ?? \"\" },\n },\n ],\n });\n } else if (item.type === \"function_call_output\") {\n // Bug 1 fix: If there's no preceding assistant message with a matching\n // tool_call for this call_id, synthesize one. This happens when the AI SDK\n // sends [user, item_reference, function_call_output] — the item_reference\n // placeholder (see below) has no tool_calls, so we need a real assistant\n // message with the tool_call for turnIndex counting.\n const hasMatchingToolCall = messages.some(\n (m) => m.role === \"assistant\" && m.tool_calls?.some((tc) => tc.id === item.call_id),\n );\n if (!hasMatchingToolCall) {\n // Check if the last message is an item_reference placeholder — if so,\n // upgrade it to carry the tool_call instead of synthesizing a duplicate.\n const lastMsg = messages[messages.length - 1];\n if (\n lastMsg &&\n lastMsg.role === \"assistant\" &&\n itemReferencePlaceholders.has(lastMsg) &&\n !lastMsg.tool_calls\n ) {\n lastMsg.content = null;\n lastMsg.tool_calls = [\n {\n id: item.call_id ?? generateToolCallId(),\n type: \"function\",\n function: { name: \"\", arguments: \"\" },\n },\n ];\n itemReferencePlaceholders.delete(lastMsg);\n } else {\n // Multi-fco case: look for a recent assistant with tool_calls that\n // belongs to the same turn. After the first fco upgrades a placeholder,\n // subsequent fco's see [assistant(call_A), tool(call_A)] — the last\n // assistant with tool_calls (right before the trailing tool messages)\n // is the correct target.\n let appended = false;\n for (let k = messages.length - 1; k >= 0; k--) {\n const m = messages[k];\n if (m.role === \"assistant\" && m.tool_calls) {\n m.tool_calls.push({\n id: item.call_id ?? generateToolCallId(),\n type: \"function\",\n function: { name: \"\", arguments: \"\" },\n });\n appended = true;\n break;\n }\n // Stop scanning if we hit a user message — different turn\n if (m.role === \"user\") break;\n }\n if (!appended) {\n messages.push({\n role: \"assistant\",\n content: null,\n tool_calls: [\n {\n id: item.call_id ?? generateToolCallId(),\n type: \"function\",\n function: { name: \"\", arguments: \"\" },\n },\n ],\n });\n }\n }\n }\n messages.push({\n role: \"tool\",\n content: item.output ?? \"\",\n tool_call_id: item.call_id,\n });\n } else if (item.type === \"item_reference\") {\n // Bug 6 fix: item_reference items represent prior assistant turns (text\n // or function_call). Push a placeholder so they count in assistantCount.\n // If a subsequent function_call_output arrives, the handler above will\n // upgrade this placeholder to carry tool_calls (avoiding double-count).\n const placeholder: ChatMessage = { role: \"assistant\", content: \"\" };\n itemReferencePlaceholders.add(placeholder);\n messages.push(placeholder);\n } else {\n // Skip local_shell_call, mcp_list_tools, etc. — not needed for fixture\n // matching.\n }\n }\n\n return messages;\n}\n\nfunction responsesToolsToCompletionsTools(\n tools?: ResponsesToolDef[],\n): ToolDefinition[] | undefined {\n if (!tools || tools.length === 0) return undefined;\n return tools\n .filter((t) => t.type === \"function\")\n .map((t) => ({\n type: \"function\" as const,\n function: { name: t.name, description: t.description, parameters: t.parameters },\n }));\n}\n\nexport function responsesToCompletionRequest(req: ResponsesRequest): ChatCompletionRequest {\n return {\n model: req.model,\n messages: responsesInputToMessages(req),\n stream: req.stream,\n temperature: req.temperature,\n max_tokens: req.max_output_tokens,\n tools: responsesToolsToCompletionsTools(req.tools),\n tool_choice: req.tool_choice,\n response_format: req.response_format,\n };\n}\n\n// ─── Response building: fixture → Responses API format ──────────────────────\n\nfunction responsesStatus(finishReason: string | undefined, defaultStatus: string): string {\n if (!finishReason) return defaultStatus;\n if (finishReason === \"stop\") return \"completed\";\n if (finishReason === \"tool_calls\") return \"completed\";\n if (finishReason === \"length\") return \"incomplete\";\n if (finishReason === \"content_filter\") return \"failed\";\n return finishReason;\n}\n\nfunction responsesUsage(overrides?: ResponseOverrides): {\n input_tokens: number;\n output_tokens: number;\n total_tokens: number;\n} {\n if (!overrides?.usage) return { input_tokens: 0, output_tokens: 0, total_tokens: 0 };\n const input = overrides.usage.input_tokens ?? overrides.usage.prompt_tokens ?? 0;\n const output = overrides.usage.output_tokens ?? overrides.usage.completion_tokens ?? 0;\n return {\n input_tokens: input,\n output_tokens: output,\n total_tokens: overrides.usage.total_tokens ?? input + output,\n };\n}\n\nfunction responseId(): string {\n return generateId(\"resp\");\n}\n\nfunction itemId(): string {\n return generateId(\"msg\");\n}\n\n// Streaming events for Responses API\n\nexport interface ResponsesSSEEvent {\n type: string;\n [key: string]: unknown;\n}\n\nexport function buildTextStreamEvents(\n content: string,\n model: string,\n chunkSize: number,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n emitEncryptedReasoning = false,\n synthesizeSummarylessReasoning = false,\n): ResponsesSSEEvent[] {\n const { respId, created, events, prefixOutputItems, nextOutputIndex } = buildResponsePreamble(\n model,\n chunkSize,\n reasoning,\n webSearches,\n overrides,\n emitEncryptedReasoning,\n synthesizeSummarylessReasoning,\n );\n\n const { events: msgEvents, msgItem } = buildMessageOutputEvents(\n content,\n chunkSize,\n nextOutputIndex,\n );\n events.push(...msgEvents);\n\n events.push({\n type: \"response.completed\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: overrides?.model ?? model,\n status: responsesStatus(overrides?.finishReason, \"completed\"),\n output: [...prefixOutputItems, msgItem],\n usage: responsesUsage(overrides),\n },\n });\n\n return events;\n}\n\nfunction requireFixtureToolArguments(value: unknown): string {\n if (typeof value !== \"string\") {\n throw new Error('Invalid fixture tool call: \"arguments\" must be a string after normalization');\n }\n return value;\n}\n\nexport function buildToolCallStreamEvents(\n toolCalls: ToolCall[],\n model: string,\n chunkSize: number,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n emitEncryptedReasoning = false,\n synthesizeSummarylessReasoning = false,\n): ResponsesSSEEvent[] {\n const { respId, created, events, prefixOutputItems, nextOutputIndex } = buildResponsePreamble(\n model,\n chunkSize,\n reasoning,\n webSearches,\n overrides,\n emitEncryptedReasoning,\n synthesizeSummarylessReasoning,\n );\n\n const fcOutputItems: object[] = [];\n\n for (let idx = 0; idx < toolCalls.length; idx++) {\n const tc = toolCalls[idx];\n const callId = tc.id || generateToolCallId();\n const fcId = generateId(\"fc\");\n const outputIndex = nextOutputIndex + idx;\n\n // output_item.added (function_call)\n events.push({\n type: \"response.output_item.added\",\n output_index: outputIndex,\n item: {\n type: \"function_call\",\n id: fcId,\n call_id: callId,\n name: tc.name,\n arguments: \"\",\n status: \"in_progress\",\n },\n });\n\n // function_call_arguments.delta\n const args = requireFixtureToolArguments(tc.arguments);\n for (let i = 0; i < args.length; i += chunkSize) {\n const slice = args.slice(i, i + chunkSize);\n events.push({\n type: \"response.function_call_arguments.delta\",\n item_id: fcId,\n output_index: outputIndex,\n delta: slice,\n });\n }\n\n // function_call_arguments.done\n events.push({\n type: \"response.function_call_arguments.done\",\n item_id: fcId,\n output_index: outputIndex,\n arguments: args,\n });\n\n const doneItem = {\n type: \"function_call\",\n id: fcId,\n call_id: callId,\n name: tc.name,\n arguments: args,\n status: \"completed\",\n };\n\n // output_item.done\n events.push({\n type: \"response.output_item.done\",\n output_index: outputIndex,\n item: doneItem,\n });\n\n fcOutputItems.push(doneItem);\n }\n\n // response.completed\n events.push({\n type: \"response.completed\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: overrides?.model ?? model,\n status: responsesStatus(overrides?.finishReason, \"completed\"),\n output: [...prefixOutputItems, ...fcOutputItems],\n usage: responsesUsage(overrides),\n },\n });\n\n return events;\n}\n\n/**\n * Whether the incoming Responses request should receive encrypted reasoning.\n *\n * Two observed triggers, gated on EITHER:\n * - `include: [\"reasoning.encrypted_content\"]` — the explicit opt-in, and what\n * `agent-framework-openai` >= 1.11.0 auto-appends on its stateless-replay path\n * (it never sends `store`), so this is the branch that fires for real clients.\n * - `store: false` — captured responses carry the blob when not server-side\n * stored (ZDR) and omit it when stored; kept as a secondary trigger for\n * clients that go stateless without opting in via `include`.\n *\n * Stored / opted-out replays stay byte-identical. Exported so the WebSocket\n * Responses transport can share one gate.\n */\nexport function requestWantsEncryptedReasoning(req: ResponsesRequest): boolean {\n if (requestIncludesEncryptedReasoning(req)) return true;\n return req.store === false;\n}\n\n/**\n * Whether the request carries the EXPLICIT `include` opt-in — a strictly\n * narrower gate than `requestWantsEncryptedReasoning`, which also fires on\n * `store: false`.\n *\n * This is the gate for SYNTHESIZING a reasoning item that the fixture does not\n * declare (see `shouldSynthesizeBlobOnlyReasoning`), and it is deliberately the\n * narrow one. Attaching a field to an item aimock was already emitting is a much\n * smaller step than conjuring a whole output item that did not previously exist,\n * so the larger behavior change gets the gate that is directly observable in the\n * request rather than the inferred `store: false` one. `agent-framework-openai`\n * >= 1.11.0 auto-appends `include` on its stateless-replay path and never sends\n * `store` at all, so the motivating client is fully served by this branch — the\n * narrowing costs the feature nothing.\n *\n * Exported so the WebSocket Responses transport shares one gate.\n */\nexport function requestIncludesEncryptedReasoning(req: ResponsesRequest): boolean {\n const include = req.include;\n return Array.isArray(include) && include.includes(\"reasoning.encrypted_content\");\n}\n\n/**\n * Synthetic stand-in for OpenAI's opaque `reasoning.encrypted_content`. aimock\n * has no real ciphertext; it emits a base64 placeholder derived from the\n * reasoning id (stable for a given item, opaque like the real field). Consumers\n * store it (e.g. as agent-framework `protected_data`) and replay it verbatim;\n * aimock matches on content and ignores the echoed blob. Without it,\n * agent-framework-openai >= 1.11.0 hard-fails a reasoning + multi-tool chain on\n * the follow-up request. See microsoft/agent-framework#7233.\n *\n * aimock skips inbound reasoning items entirely, so it cannot reproduce\n * OpenAI's `invalid_encrypted_content` rejection of a mismatched blob/id — a\n * known replay-only limitation.\n */\nfunction syntheticEncryptedReasoning(reasoningId: string): string {\n return Buffer.from(`aimock-encrypted-reasoning:${reasoningId}`).toString(\"base64\");\n}\n\n/**\n * Build a Responses `reasoning` output item. `summaryText` controls the summary\n * (present for the terminal `done` / non-streaming item, omitted for the\n * in-progress `added` item); `emitEncrypted` controls the blob INDEPENDENTLY of\n * the summary, so a blob with an empty summary is expressible. aimock emits the\n * blob only on the terminal item and omits it on `added`: real OpenAI populates\n * `added` opportunistically, but the field is `anyOf: [string, null]` and\n * non-required, so consumers should read it at `done` and treat `added` as\n * best-effort — omitting there is legal and harmless.\n */\nfunction buildReasoningOutputItem(\n reasoningId: string,\n opts: { summaryText?: string; emitEncrypted?: boolean } = {},\n): Record<string, unknown> {\n const item: Record<string, unknown> = {\n type: \"reasoning\",\n id: reasoningId,\n summary:\n opts.summaryText === undefined ? [] : [{ type: \"summary_text\", text: opts.summaryText }],\n };\n if (opts.emitEncrypted) {\n item.encrypted_content = syntheticEncryptedReasoning(reasoningId);\n }\n return item;\n}\n\n/**\n * Whether to synthesize a summary-LESS reasoning item that exists purely to\n * carry the encrypted blob.\n *\n * Every reasoning item aimock emits otherwise originates in a fixture's declared\n * `reasoning` summary text. But a fixture RECORDED from the real stateless\n * agent-framework flow typically has NO summary — OpenAI returns `summary: []`\n * unless summaries are explicitly requested — so keying the item on a declared\n * summary starves the exact flow this feature exists to serve: fully opted in,\n * yet no reasoning item and therefore no blob. Real OpenAI, for a\n * reasoning-capable model, still returns a reasoning item (`summary: []`) with\n * the blob populated. So synthesize one, gated on:\n *\n * - the EXPLICIT `include` opt-in ONLY (`requestIncludesEncryptedReasoning`),\n * which is NARROWER than the `requestWantsEncryptedReasoning` gate that\n * controls the blob itself. A `store: false` request whose fixture declares no\n * summary therefore gets NO reasoning item, exactly as before this change.\n * Two reasons: (1) creating an output item that did not previously exist is a\n * bigger behavior change than adding a field to an item already being\n * emitted, so it earns the gate that is directly observable in the request\n * rather than the inferred one; (2) the `store: false` trigger's supporting\n * capture evidence is not verifiable from this repo, and a larger change must\n * not be stacked on an unverifiable premise. `agent-framework-openai` >=\n * 1.11.0 sends `include` and never `store`, so nothing is lost.\n * - the REQUESTED model's reasoning capability (aimock#254) — emitting a\n * reasoning item for gpt-4o would be LESS faithful, not more, since that\n * model has no reasoning channel at all. Unlike `resolveReasoningForModel`,\n * which fails open for a declared summary (a recorded summary is evidence the\n * model did reason), there is nothing to preserve here: a synthesized item on\n * a non-reasoning model would be pure fabrication, so this gate is hard.\n *\n * Note this is INDEPENDENT of `emitEncryptedReasoning`: when a fixture DOES\n * declare a summary, the blob still rides on it under either trigger (including\n * `store: false`), unchanged.\n */\nfunction shouldSynthesizeBlobOnlyReasoning(\n reasoning: string | undefined,\n model: string | undefined,\n synthesizeSummarylessReasoning: boolean,\n): boolean {\n if (reasoning) return false; // a declared summary already produces the item\n if (!synthesizeSummarylessReasoning) return false; // no explicit `include` opt-in\n return isReasoningModel(model);\n}\n\n/**\n * `reasoning` is `undefined` for a synthesized blob-only item (see\n * `shouldSynthesizeBlobOnlyReasoning`). In that case the item's `summary` is\n * `[]`, so the summary-part / summary-text events are SKIPPED entirely — they\n * would describe a part that does not exist on the item — leaving a coherent\n * `output_item.added` → `output_item.done` pair with nothing between.\n */\nfunction buildReasoningStreamEvents(\n reasoning: string | undefined,\n chunkSize: number,\n emitEncryptedReasoning = false,\n): ResponsesSSEEvent[] {\n const reasoningId = generateId(\"rs\");\n const events: ResponsesSSEEvent[] = [];\n\n events.push({\n type: \"response.output_item.added\",\n output_index: 0,\n item: buildReasoningOutputItem(reasoningId),\n });\n\n if (reasoning !== undefined) {\n events.push({\n type: \"response.reasoning_summary_part.added\",\n item_id: reasoningId,\n output_index: 0,\n summary_index: 0,\n part: { type: \"summary_text\", text: \"\" },\n });\n\n for (let i = 0; i < reasoning.length; i += chunkSize) {\n const slice = reasoning.slice(i, i + chunkSize);\n events.push({\n type: \"response.reasoning_summary_text.delta\",\n item_id: reasoningId,\n output_index: 0,\n summary_index: 0,\n delta: slice,\n });\n }\n\n events.push({\n type: \"response.reasoning_summary_text.done\",\n item_id: reasoningId,\n output_index: 0,\n summary_index: 0,\n text: reasoning,\n });\n\n events.push({\n type: \"response.reasoning_summary_part.done\",\n item_id: reasoningId,\n output_index: 0,\n summary_index: 0,\n part: { type: \"summary_text\", text: reasoning },\n });\n }\n\n events.push({\n type: \"response.output_item.done\",\n output_index: 0,\n item: buildReasoningOutputItem(reasoningId, {\n summaryText: reasoning,\n emitEncrypted: emitEncryptedReasoning,\n }),\n });\n\n return events;\n}\n\nfunction buildWebSearchStreamEvents(\n queries: string[],\n startOutputIndex: number,\n): ResponsesSSEEvent[] {\n const events: ResponsesSSEEvent[] = [];\n\n for (let i = 0; i < queries.length; i++) {\n const searchId = generateId(\"ws\");\n const outputIndex = startOutputIndex + i;\n\n events.push({\n type: \"response.output_item.added\",\n output_index: outputIndex,\n item: {\n type: \"web_search_call\",\n id: searchId,\n status: \"in_progress\",\n action: { type: \"search\", query: queries[i] },\n },\n });\n\n events.push({\n type: \"response.output_item.done\",\n output_index: outputIndex,\n item: {\n type: \"web_search_call\",\n id: searchId,\n status: \"completed\",\n action: { type: \"search\", query: queries[i] },\n },\n });\n }\n\n return events;\n}\n\n// ─── Shared streaming helpers ────────────────────────────────────────────────\n\ninterface PreambleResult {\n respId: string;\n created: number;\n events: ResponsesSSEEvent[];\n prefixOutputItems: object[];\n nextOutputIndex: number;\n}\n\nfunction buildResponsePreamble(\n model: string,\n chunkSize: number,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n emitEncryptedReasoning = false,\n synthesizeSummarylessReasoning = false,\n): PreambleResult {\n const respId = overrides?.id ?? responseId();\n const created = overrides?.created ?? Math.floor(Date.now() / 1000);\n const effectiveModel = overrides?.model ?? model;\n const events: ResponsesSSEEvent[] = [];\n const prefixOutputItems: object[] = [];\n let nextOutputIndex = 0;\n\n events.push({\n type: \"response.created\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: effectiveModel,\n status: \"in_progress\",\n output: [],\n },\n });\n events.push({\n type: \"response.in_progress\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: effectiveModel,\n status: \"in_progress\",\n output: [],\n },\n });\n\n if (\n reasoning ||\n shouldSynthesizeBlobOnlyReasoning(reasoning, model, synthesizeSummarylessReasoning)\n ) {\n const reasoningEvents = buildReasoningStreamEvents(\n reasoning,\n chunkSize,\n emitEncryptedReasoning,\n );\n events.push(...reasoningEvents);\n const doneEvent = reasoningEvents.find(\n (e) =>\n e.type === \"response.output_item.done\" &&\n (e.item as { type: string })?.type === \"reasoning\",\n );\n if (doneEvent) prefixOutputItems.push(doneEvent.item as object);\n nextOutputIndex++;\n }\n\n if (webSearches && webSearches.length > 0) {\n const searchEvents = buildWebSearchStreamEvents(webSearches, nextOutputIndex);\n events.push(...searchEvents);\n const doneEvents = searchEvents.filter(\n (e) =>\n e.type === \"response.output_item.done\" &&\n (e.item as { type: string })?.type === \"web_search_call\",\n );\n for (const de of doneEvents) prefixOutputItems.push(de.item as object);\n nextOutputIndex += webSearches.length;\n }\n\n return { respId, created, events, prefixOutputItems, nextOutputIndex };\n}\n\ninterface MessageBlockResult {\n events: ResponsesSSEEvent[];\n msgItem: object;\n}\n\nfunction buildMessageOutputEvents(\n content: string,\n chunkSize: number,\n outputIndex: number,\n): MessageBlockResult {\n const msgId = itemId();\n const events: ResponsesSSEEvent[] = [];\n\n events.push({\n type: \"response.output_item.added\",\n output_index: outputIndex,\n item: { type: \"message\", id: msgId, status: \"in_progress\", role: \"assistant\", content: [] },\n });\n events.push({\n type: \"response.content_part.added\",\n item_id: msgId,\n output_index: outputIndex,\n content_index: 0,\n part: { type: \"output_text\", text: \"\", annotations: [] },\n });\n\n for (let i = 0; i < content.length; i += chunkSize) {\n events.push({\n type: \"response.output_text.delta\",\n item_id: msgId,\n output_index: outputIndex,\n content_index: 0,\n delta: content.slice(i, i + chunkSize),\n });\n }\n\n events.push({\n type: \"response.output_text.done\",\n item_id: msgId,\n output_index: outputIndex,\n content_index: 0,\n text: content,\n });\n events.push({\n type: \"response.content_part.done\",\n item_id: msgId,\n output_index: outputIndex,\n content_index: 0,\n part: { type: \"output_text\", text: content, annotations: [] },\n });\n\n const msgItem = {\n type: \"message\",\n id: msgId,\n status: \"completed\",\n role: \"assistant\",\n content: [{ type: \"output_text\", text: content, annotations: [] }],\n };\n\n events.push({ type: \"response.output_item.done\", output_index: outputIndex, item: msgItem });\n\n return { events, msgItem };\n}\n\ninterface FunctionCallBlockResult {\n events: ResponsesSSEEvent[];\n fcItem: object;\n}\n\n/**\n * Emit the output_item.added → arguments deltas → arguments.done →\n * output_item.done events for a single function_call at `outputIndex`,\n * returning the completed item for the final `output` array. Behavior is\n * identical to the inline per-tool-call loop in the legacy path; both the\n * legacy branch and the ordered-blocks branch share this so wire output stays\n * byte-identical for a given (tool, outputIndex).\n */\nfunction buildFunctionCallOutputEvents(\n toolCall: ToolCall,\n chunkSize: number,\n outputIndex: number,\n): FunctionCallBlockResult {\n const callId = toolCall.id || generateToolCallId();\n const fcId = generateId(\"fc\");\n const args = requireFixtureToolArguments(toolCall.arguments);\n const events: ResponsesSSEEvent[] = [];\n\n events.push({\n type: \"response.output_item.added\",\n output_index: outputIndex,\n item: {\n type: \"function_call\",\n id: fcId,\n call_id: callId,\n name: toolCall.name,\n arguments: \"\",\n status: \"in_progress\",\n },\n });\n\n for (let i = 0; i < args.length; i += chunkSize) {\n events.push({\n type: \"response.function_call_arguments.delta\",\n item_id: fcId,\n output_index: outputIndex,\n delta: args.slice(i, i + chunkSize),\n });\n }\n\n events.push({\n type: \"response.function_call_arguments.done\",\n item_id: fcId,\n output_index: outputIndex,\n arguments: args,\n });\n\n const fcItem = {\n type: \"function_call\",\n id: fcId,\n call_id: callId,\n name: toolCall.name,\n arguments: args,\n status: \"completed\",\n };\n events.push({ type: \"response.output_item.done\", output_index: outputIndex, item: fcItem });\n\n return { events, fcItem };\n}\n\n// ─── Non-streaming response builders ────────────────────────────────────────\n\nfunction buildOutputPrefix(\n content: string,\n model: string,\n reasoning?: string,\n webSearches?: string[],\n emitEncryptedReasoning = false,\n synthesizeSummarylessReasoning = false,\n): object[] {\n const output: object[] = [];\n\n if (\n reasoning ||\n shouldSynthesizeBlobOnlyReasoning(reasoning, model, synthesizeSummarylessReasoning)\n ) {\n output.push(\n buildReasoningOutputItem(generateId(\"rs\"), {\n summaryText: reasoning,\n emitEncrypted: emitEncryptedReasoning,\n }),\n );\n }\n\n if (webSearches && webSearches.length > 0) {\n for (const query of webSearches) {\n output.push({\n type: \"web_search_call\",\n id: generateId(\"ws\"),\n status: \"completed\",\n action: { type: \"search\", query },\n });\n }\n }\n\n output.push({\n type: \"message\",\n id: itemId(),\n status: \"completed\",\n role: \"assistant\",\n content: [{ type: \"output_text\", text: content, annotations: [] }],\n });\n\n return output;\n}\n\nfunction buildResponseEnvelope(\n model: string,\n output: object[],\n overrides?: ResponseOverrides,\n): object {\n return {\n id: overrides?.id ?? responseId(),\n object: \"response\",\n created_at: overrides?.created ?? Math.floor(Date.now() / 1000),\n model: overrides?.model ?? model,\n status: responsesStatus(overrides?.finishReason, \"completed\"),\n output,\n usage: responsesUsage(overrides),\n };\n}\n\nexport function buildTextResponse(\n content: string,\n model: string,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n emitEncryptedReasoning = false,\n synthesizeSummarylessReasoning = false,\n): object {\n return buildResponseEnvelope(\n model,\n buildOutputPrefix(\n content,\n model,\n reasoning,\n webSearches,\n emitEncryptedReasoning,\n synthesizeSummarylessReasoning,\n ),\n overrides,\n );\n}\n\nfunction buildToolCallResponse(\n toolCalls: ToolCall[],\n model: string,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n emitEncryptedReasoning = false,\n synthesizeSummarylessReasoning = false,\n): object {\n const output: object[] = [];\n if (\n reasoning ||\n shouldSynthesizeBlobOnlyReasoning(reasoning, model, synthesizeSummarylessReasoning)\n ) {\n output.push(\n buildReasoningOutputItem(generateId(\"rs\"), {\n summaryText: reasoning,\n emitEncrypted: emitEncryptedReasoning,\n }),\n );\n }\n if (webSearches && webSearches.length > 0) {\n for (const query of webSearches) {\n output.push({\n type: \"web_search_call\",\n id: generateId(\"ws\"),\n status: \"completed\",\n action: { type: \"search\", query },\n });\n }\n }\n for (const tc of toolCalls) {\n output.push({\n type: \"function_call\",\n id: generateId(\"fc\"),\n call_id: tc.id || generateToolCallId(),\n name: tc.name,\n arguments: requireFixtureToolArguments(tc.arguments),\n status: \"completed\",\n });\n }\n return buildResponseEnvelope(model, output, overrides);\n}\n\nexport function buildContentWithToolCallsStreamEvents(\n content: string,\n toolCalls: ToolCall[],\n model: string,\n chunkSize: number,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n blocks?: FixtureBlock[],\n emitEncryptedReasoning = false,\n synthesizeSummarylessReasoning = false,\n): ResponsesSSEEvent[] {\n const { respId, created, events, prefixOutputItems, nextOutputIndex } = buildResponsePreamble(\n model,\n chunkSize,\n reasoning,\n webSearches,\n overrides,\n emitEncryptedReasoning,\n synthesizeSummarylessReasoning,\n );\n\n // The output items assembled in emission order (after any reasoning /\n // web-search prefix items). Each output_index is assigned sequentially as we\n // walk the chosen item order, so the `output_index` on every emitted event\n // matches that item's slot in the final `response.completed.output` array.\n const orderedOutputItems: object[] = [];\n\n if (blocks && blocks.length > 0) {\n // NEW PATH: stream items in the fixture's block ARRAY ORDER. A toolCall\n // block placed before a text block therefore yields a function_call item at\n // a LOWER output_index than the message — it leads the output array.\n const ordered = resolveFixtureBlocks(blocks);\n let outputIndex = nextOutputIndex;\n for (const block of ordered) {\n if (block.type === \"text\") {\n const { events: msgEvents, msgItem } = buildMessageOutputEvents(\n block.text,\n chunkSize,\n outputIndex,\n );\n events.push(...msgEvents);\n orderedOutputItems.push(msgItem);\n } else {\n const { events: fcEvents, fcItem } = buildFunctionCallOutputEvents(\n { name: block.name, arguments: block.arguments, id: block.id },\n chunkSize,\n outputIndex,\n );\n events.push(...fcEvents);\n orderedOutputItems.push(fcItem);\n }\n outputIndex += 1;\n }\n } else {\n // LEGACY PATH: message item first, then function_call items — byte-for-byte\n // unchanged from the pre-blocks behavior (message always leads the output).\n const { events: msgEvents, msgItem } = buildMessageOutputEvents(\n content,\n chunkSize,\n nextOutputIndex,\n );\n events.push(...msgEvents);\n orderedOutputItems.push(msgItem);\n\n for (let idx = 0; idx < toolCalls.length; idx++) {\n const fcOutputIndex = nextOutputIndex + 1 + idx;\n const { events: fcEvents, fcItem } = buildFunctionCallOutputEvents(\n toolCalls[idx],\n chunkSize,\n fcOutputIndex,\n );\n events.push(...fcEvents);\n orderedOutputItems.push(fcItem);\n }\n }\n\n events.push({\n type: \"response.completed\",\n response: {\n id: respId,\n object: \"response\",\n created_at: created,\n model: overrides?.model ?? model,\n status: responsesStatus(overrides?.finishReason, \"completed\"),\n output: [...prefixOutputItems, ...orderedOutputItems],\n usage: responsesUsage(overrides),\n },\n });\n\n return events;\n}\n\nfunction buildFunctionCallOutputItem(tc: { name: string; arguments: string; id?: string }): object {\n return {\n type: \"function_call\",\n id: generateId(\"fc\"),\n call_id: tc.id || generateToolCallId(),\n name: tc.name,\n arguments: requireFixtureToolArguments(tc.arguments),\n status: \"completed\",\n };\n}\n\nfunction buildMessageOutputItem(content: string): object {\n return {\n type: \"message\",\n id: itemId(),\n status: \"completed\",\n role: \"assistant\",\n content: [{ type: \"output_text\", text: content, annotations: [] }],\n };\n}\n\nfunction buildContentWithToolCallsResponse(\n content: string,\n toolCalls: ToolCall[],\n model: string,\n reasoning?: string,\n webSearches?: string[],\n overrides?: ResponseOverrides,\n blocks?: FixtureBlock[],\n emitEncryptedReasoning = false,\n synthesizeSummarylessReasoning = false,\n): object {\n if (blocks && blocks.length > 0) {\n // NEW PATH: the non-streaming `output[]` array is positionally observable,\n // so emit the prefix (reasoning / web_search_call), then the blocks in\n // fixture ARRAY ORDER. A toolCall block before a text block therefore\n // yields a function_call item ahead of the message — matching the streaming\n // path's ordering for the same `blocks` fixture.\n const ordered = resolveFixtureBlocks(blocks);\n const output: object[] = [];\n if (\n reasoning ||\n shouldSynthesizeBlobOnlyReasoning(reasoning, model, synthesizeSummarylessReasoning)\n ) {\n output.push(\n buildReasoningOutputItem(generateId(\"rs\"), {\n summaryText: reasoning,\n emitEncrypted: emitEncryptedReasoning,\n }),\n );\n }\n if (webSearches && webSearches.length > 0) {\n for (const query of webSearches) {\n output.push({\n type: \"web_search_call\",\n id: generateId(\"ws\"),\n status: \"completed\",\n action: { type: \"search\", query },\n });\n }\n }\n for (const block of ordered) {\n if (block.type === \"text\") {\n output.push(buildMessageOutputItem(block.text));\n } else {\n output.push(\n buildFunctionCallOutputItem({\n name: block.name,\n arguments: block.arguments,\n id: block.id,\n }),\n );\n }\n }\n return buildResponseEnvelope(model, output, overrides);\n }\n\n // LEGACY PATH: message item first, then function_call items — unchanged.\n const output = buildOutputPrefix(\n content,\n model,\n reasoning,\n webSearches,\n emitEncryptedReasoning,\n synthesizeSummarylessReasoning,\n );\n for (const tc of toolCalls) {\n output.push(buildFunctionCallOutputItem(tc));\n }\n return buildResponseEnvelope(model, output, overrides);\n}\n\n// ─── SSE writer for Responses API ───────────────────────────────────────────\n\ninterface ResponsesStreamOptions {\n latency?: number;\n streamingProfile?: StreamingProfile;\n recordedTimings?: RecordedTimings;\n replaySpeed?: number;\n signal?: AbortSignal;\n onChunkSent?: () => void;\n}\n\nasync function writeResponsesSSEStream(\n res: http.ServerResponse,\n events: ResponsesSSEEvent[],\n optionsOrLatency?: number | ResponsesStreamOptions,\n): Promise<boolean> {\n const opts: ResponsesStreamOptions =\n typeof optionsOrLatency === \"number\" ? { latency: optionsOrLatency } : (optionsOrLatency ?? {});\n const latency = opts.latency ?? 0;\n const profile = opts.streamingProfile;\n const { recordedTimings, replaySpeed } = opts;\n const signal = opts.signal;\n const onChunkSent = opts.onChunkSent;\n\n if (res.writableEnded) return true;\n res.setHeader(\"Content-Type\", \"text/event-stream\");\n res.setHeader(\"Cache-Control\", \"no-cache\");\n res.setHeader(\"Connection\", \"keep-alive\");\n\n let chunkIndex = 0;\n for (const event of events) {\n const chunkDelay = calculateDelay(chunkIndex, profile, latency, recordedTimings, replaySpeed);\n if (chunkDelay > 0) await delay(chunkDelay, signal);\n if (signal?.aborted) return false;\n if (res.writableEnded) return true;\n res.write(`event: ${event.type}\\ndata: ${JSON.stringify(event)}\\n\\n`);\n onChunkSent?.();\n if (signal?.aborted) return false;\n chunkIndex++;\n }\n\n if (!res.writableEnded) {\n res.end();\n }\n return true;\n}\n\n// ─── Request handler ────────────────────────────────────────────────────────\n\nexport async function handleResponses(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n raw: string,\n fixtures: Fixture[],\n journal: Journal,\n defaults: HandlerDefaults,\n setCorsHeaders: (res: http.ServerResponse) => void,\n): Promise<void> {\n setCorsHeaders(res);\n\n let responsesReq: ResponsesRequest;\n try {\n responsesReq = JSON.parse(raw) as ResponsesRequest;\n } catch (parseErr) {\n const detail = parseErr instanceof Error ? parseErr.message : \"unknown\";\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: `Malformed JSON: ${detail}`,\n type: \"invalid_request_error\",\n code: \"invalid_json\",\n },\n }),\n );\n return;\n }\n\n // Reject bodies that parsed but are not a JSON object (e.g. `null`) before\n // touching fields — otherwise `responsesReq.model` throws a TypeError that\n // surfaces as a 500 instead of a 400.\n if (!isJsonObject(responsesReq)) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Request body must be a JSON object\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n // Guard only shapes consumed by input conversion. Other item fields may be\n // intentionally ignored, and falsy message content normalizes to empty text.\n let inputError: string | undefined;\n if (typeof responsesReq.input !== \"string\" && !Array.isArray(responsesReq.input)) {\n inputError = \"input must be a string or an array\";\n } else if (Array.isArray(responsesReq.input)) {\n for (const [index, item] of responsesReq.input.entries()) {\n if (item === null) {\n inputError = `input[${index}] must not be null`;\n break;\n }\n if (\n (item.role === \"system\" ||\n item.role === \"developer\" ||\n item.role === \"user\" ||\n item.role === \"assistant\") &&\n item.content &&\n typeof item.content !== \"string\" &&\n !Array.isArray(item.content)\n ) {\n inputError = `input[${index}].content must be a string or an array`;\n break;\n }\n }\n }\n // Keep the converter's empty/falsy bypass and ignored non-function entries.\n // Only reject collections that would throw when the converter reads them.\n let toolsError: string | undefined;\n if (responsesReq.tools && responsesReq.tools.length !== 0) {\n if (!Array.isArray(responsesReq.tools)) {\n toolsError = \"tools must be an array\";\n } else if (responsesReq.tools.some((tool) => tool === null)) {\n toolsError = \"tools entries must not be null\";\n }\n }\n const validationError = inputError ?? toolsError;\n if (validationError) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: responsesReq,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({ error: { message: validationError, type: \"invalid_request_error\" } }),\n );\n return;\n }\n\n // Convert to ChatCompletionRequest for fixture matching\n const completionReq = responsesToCompletionRequest(responsesReq);\n completionReq._endpointType = \"chat\";\n completionReq._context = getContext(req);\n\n // Emit a synthetic `reasoning.encrypted_content` only when the request wants it\n // (opted in via `include`, or stateless `store: false` — mirrors real OpenAI).\n // This is what agent-framework-openai >= 1.11.0 sends on stateless-replay\n // requests; without the blob it hard-fails a reasoning + multi-tool chain.\n // See microsoft/agent-framework#7233.\n const emitEncryptedReasoning = requestWantsEncryptedReasoning(responsesReq);\n // Synthesizing a reasoning item the fixture never declared is a bigger step\n // than adding a field to one already being emitted, so it takes the NARROWER\n // explicit-`include` gate: a `store: false` request with a summary-less fixture\n // keeps emitting no reasoning item at all. See\n // `shouldSynthesizeBlobOnlyReasoning`.\n const synthesizeSummarylessReasoning = requestIncludesEncryptedReasoning(responsesReq);\n\n const testId = getTestId(req);\n const { fixture, skippedBySequenceOrTurn } = matchFixtureDiagnostic(\n fixtures,\n completionReq,\n journal.getFixtureMatchCountsForTest(testId),\n defaults.requestTransform,\n // Record mode proxies on a miss to capture a fresh turn (see record gate\n // below), so keep turnIndex strict to prevent an earlier-turn fixture from\n // shadowing a longer request and skipping the new turn's recording.\n recordMatchOptions(!!defaults.record, defaults.logger),\n );\n\n if (fixture) {\n defaults.logger.debug(\n `Responses fixture matched for ${req.method ?? \"POST\"} ${req.url ?? \"/v1/responses\"}`,\n );\n journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n } else {\n defaults.logger.debug(\n `No responses fixture matched for ${req.method ?? \"POST\"} ${req.url ?? \"/v1/responses\"}`,\n );\n }\n\n if (\n await applyChaosAsync(\n res,\n fixture,\n defaults.chaos,\n req.headers,\n req.url,\n journal,\n {\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n },\n fixture ? \"fixture\" : \"proxy\",\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n if (effectiveStrict) {\n const strictStatus = 503;\n const strictMessage = strictNoMatchMessage(skippedBySequenceOrTurn);\n defaults.logger.error(\n strictNoMatchLogLine(\n req.method ?? \"POST\",\n req.url ?? \"/v1/responses\",\n skippedBySequenceOrTurn,\n ),\n );\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: {\n status: strictStatus,\n fixture: null,\n ...strictOverrideField(defaults.strict, req.headers),\n },\n });\n writeErrorResponse(\n res,\n strictStatus,\n JSON.stringify({\n error: {\n message: strictMessage,\n type: \"invalid_request_error\",\n code: \"no_fixture_match\",\n },\n }),\n );\n return;\n }\n if (defaults.record) {\n const outcome = await proxyAndRecord(\n req,\n res,\n completionReq,\n \"openai\",\n req.url ?? \"/v1/responses\",\n fixtures,\n defaults,\n raw,\n );\n if (outcome === \"handled_by_hook\") return;\n if (outcome !== \"not_configured\") {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: res.statusCode ?? 200, fixture: null, source: \"proxy\" },\n });\n return;\n }\n }\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: {\n status: 404,\n fixture: null,\n ...strictOverrideField(defaults.strict, req.headers),\n },\n });\n writeErrorResponse(\n res,\n 404,\n JSON.stringify({\n error: {\n message: \"No fixture matched\",\n type: \"invalid_request_error\",\n code: \"no_fixture_match\",\n },\n }),\n );\n return;\n }\n\n const response = await resolveResponse(fixture, completionReq);\n const latency = fixture.latency ?? defaults.latency;\n const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);\n const fixtureTimings = fixture.recordedTimings;\n const effectiveReplaySpeed = fixture.replaySpeed ?? defaults.replaySpeed;\n\n // Error response\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status, fixture },\n });\n writeErrorResponse(res, status, serializeErrorResponse(response), {\n retryAfter: response.retryAfter,\n });\n return;\n }\n\n // Combined content + tool calls response\n if (isContentWithToolCallsResponse(response)) {\n const overrides = extractOverrides(response);\n // Gate reasoning emission on the requested model's capability (aimock#254).\n const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n const effReasoning = resolveReasoningForModel(\n response.reasoning,\n completionReq.model,\n effectiveStrict,\n defaults.logger,\n );\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (responsesReq.stream !== true) {\n const body = buildContentWithToolCallsResponse(\n response.content ?? \"\",\n response.toolCalls ?? [],\n completionReq.model,\n effReasoning,\n response.webSearches,\n overrides,\n response.blocks,\n emitEncryptedReasoning,\n synthesizeSummarylessReasoning,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildContentWithToolCallsStreamEvents(\n response.content ?? \"\",\n response.toolCalls ?? [],\n completionReq.model,\n chunkSize,\n effReasoning,\n response.webSearches,\n overrides,\n response.blocks,\n emitEncryptedReasoning,\n synthesizeSummarylessReasoning,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeResponsesSSEStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\n recordedTimings: fixtureTimings,\n replaySpeed: effectiveReplaySpeed,\n signal: interruption?.signal,\n onChunkSent: interruption?.tick,\n });\n if (!completed) {\n if (!res.writableEnded) res.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n }\n interruption?.cleanup();\n }\n return;\n }\n\n // Text response\n if (isTextResponse(response)) {\n const overrides = extractOverrides(response);\n // Gate reasoning emission on the requested model's capability (aimock#254).\n const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n const effReasoning = resolveReasoningForModel(\n response.reasoning,\n completionReq.model,\n effectiveStrict,\n defaults.logger,\n );\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (responsesReq.stream !== true) {\n const body = buildTextResponse(\n response.content,\n completionReq.model,\n effReasoning,\n response.webSearches,\n overrides,\n emitEncryptedReasoning,\n synthesizeSummarylessReasoning,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildTextStreamEvents(\n response.content,\n completionReq.model,\n chunkSize,\n effReasoning,\n response.webSearches,\n overrides,\n emitEncryptedReasoning,\n synthesizeSummarylessReasoning,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeResponsesSSEStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\n recordedTimings: fixtureTimings,\n replaySpeed: effectiveReplaySpeed,\n signal: interruption?.signal,\n onChunkSent: interruption?.tick,\n });\n if (!completed) {\n if (!res.writableEnded) res.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n }\n interruption?.cleanup();\n }\n return;\n }\n\n // Tool call response\n if (isToolCallResponse(response)) {\n const overrides = extractOverrides(response);\n // Gate reasoning emission on the requested model's capability (aimock#254).\n const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n const effReasoning = resolveReasoningForModel(\n response.reasoning,\n completionReq.model,\n effectiveStrict,\n defaults.logger,\n );\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n if (responsesReq.stream !== true) {\n const body = buildToolCallResponse(\n response.toolCalls,\n completionReq.model,\n effReasoning,\n response.webSearches,\n overrides,\n emitEncryptedReasoning,\n synthesizeSummarylessReasoning,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n } else {\n const events = buildToolCallStreamEvents(\n response.toolCalls,\n completionReq.model,\n chunkSize,\n effReasoning,\n response.webSearches,\n overrides,\n emitEncryptedReasoning,\n synthesizeSummarylessReasoning,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeResponsesSSEStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\n recordedTimings: fixtureTimings,\n replaySpeed: effectiveReplaySpeed,\n signal: interruption?.signal,\n onChunkSent: interruption?.tick,\n });\n if (!completed) {\n if (!res.writableEnded) res.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n }\n interruption?.cleanup();\n }\n return;\n }\n\n // Unknown response type\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/responses\",\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: { message: \"Fixture response did not match any known type\", type: \"server_error\" },\n }),\n );\n}\n"],"mappings":"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"}
|
package/dist/responses.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"responses.d.cts","names":[],"sources":["../src/responses.ts"],"sourcesContent":[],"mappings":";;;;;;UAkSiB,iBAAA;;;;iBAKD,qBAAA,4GAMF,gGAGX;
|
|
1
|
+
{"version":3,"file":"responses.d.cts","names":[],"sources":["../src/responses.ts"],"sourcesContent":[],"mappings":";;;;;;UAkSiB,iBAAA;;;;iBAKD,qBAAA,4GAMF,gGAGX;iBAyCa,yBAAA,YACH,sGAKC,gGAGX;;;;;;;;;;;;;;;;iBAypBa,qCAAA,6BAEH,sGAKC,4BACH,6FAGR;iBA+NmB,eAAA,MACf,MAAA,CAAK,sBACL,MAAA,CAAK,uCAEA,oBACD,mBACC,uCACY,MAAA,CAAK,0BAC1B"}
|
package/dist/responses.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"responses.d.ts","names":[],"sources":["../src/responses.ts"],"sourcesContent":[],"mappings":";;;;;;UAkSiB,iBAAA;;;;iBAKD,qBAAA,4GAMF,gGAGX;
|
|
1
|
+
{"version":3,"file":"responses.d.ts","names":[],"sources":["../src/responses.ts"],"sourcesContent":[],"mappings":";;;;;;UAkSiB,iBAAA;;;;iBAKD,qBAAA,4GAMF,gGAGX;iBAyCa,yBAAA,YACH,sGAKC,gGAGX;;;;;;;;;;;;;;;;iBAypBa,qCAAA,6BAEH,sGAKC,4BACH,6FAGR;iBA+NmB,eAAA,MACf,MAAA,CAAK,sBACL,MAAA,CAAK,uCAEA,oBACD,mBACC,uCACY,MAAA,CAAK,0BAC1B"}
|
package/dist/responses.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { isReasoningModel } from "./model-utils.js";
|
|
2
2
|
import { extractOverrides, flattenHeaders, generateId, generateToolCallId, getContext, getTestId, isContentWithToolCallsResponse, isErrorResponse, isJsonObject, isTextResponse, isToolCallResponse, resolveFixtureBlocks, resolveReasoningForModel, resolveResponse, resolveStrictMode, serializeErrorResponse, strictNoMatchLogLine, strictNoMatchMessage, strictOverrideField } from "./helpers.js";
|
|
3
|
-
import { matchFixtureDiagnostic, recordMatchOptions } from "./router.js";
|
|
4
3
|
import { calculateDelay, delay, writeErrorResponse } from "./sse-writer.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { applyChaosAsync } from "./chaos.js";
|
|
5
|
+
import { matchFixtureDiagnostic, recordMatchOptions } from "./router.js";
|
|
7
6
|
import { proxyAndRecord } from "./recorder.js";
|
|
7
|
+
import { createInterruptionSignal } from "./interruption.js";
|
|
8
8
|
|
|
9
9
|
//#region src/responses.ts
|
|
10
10
|
function extractTextContent(content) {
|
|
@@ -180,6 +180,10 @@ function buildTextStreamEvents(content, model, chunkSize, reasoning, webSearches
|
|
|
180
180
|
});
|
|
181
181
|
return events;
|
|
182
182
|
}
|
|
183
|
+
function requireFixtureToolArguments(value) {
|
|
184
|
+
if (typeof value !== "string") throw new Error("Invalid fixture tool call: \"arguments\" must be a string after normalization");
|
|
185
|
+
return value;
|
|
186
|
+
}
|
|
183
187
|
function buildToolCallStreamEvents(toolCalls, model, chunkSize, reasoning, webSearches, overrides, emitEncryptedReasoning = false, synthesizeSummarylessReasoning = false) {
|
|
184
188
|
const { respId, created, events, prefixOutputItems, nextOutputIndex } = buildResponsePreamble(model, chunkSize, reasoning, webSearches, overrides, emitEncryptedReasoning, synthesizeSummarylessReasoning);
|
|
185
189
|
const fcOutputItems = [];
|
|
@@ -200,7 +204,7 @@ function buildToolCallStreamEvents(toolCalls, model, chunkSize, reasoning, webSe
|
|
|
200
204
|
status: "in_progress"
|
|
201
205
|
}
|
|
202
206
|
});
|
|
203
|
-
const args = tc.arguments;
|
|
207
|
+
const args = requireFixtureToolArguments(tc.arguments);
|
|
204
208
|
for (let i = 0; i < args.length; i += chunkSize) {
|
|
205
209
|
const slice = args.slice(i, i + chunkSize);
|
|
206
210
|
events.push({
|
|
@@ -593,7 +597,7 @@ function buildMessageOutputEvents(content, chunkSize, outputIndex) {
|
|
|
593
597
|
function buildFunctionCallOutputEvents(toolCall, chunkSize, outputIndex) {
|
|
594
598
|
const callId = toolCall.id || generateToolCallId();
|
|
595
599
|
const fcId = generateId("fc");
|
|
596
|
-
const args = toolCall.arguments;
|
|
600
|
+
const args = requireFixtureToolArguments(toolCall.arguments);
|
|
597
601
|
const events = [];
|
|
598
602
|
events.push({
|
|
599
603
|
type: "response.output_item.added",
|
|
@@ -699,7 +703,7 @@ function buildToolCallResponse(toolCalls, model, reasoning, webSearches, overrid
|
|
|
699
703
|
id: generateId("fc"),
|
|
700
704
|
call_id: tc.id || generateToolCallId(),
|
|
701
705
|
name: tc.name,
|
|
702
|
-
arguments: tc.arguments,
|
|
706
|
+
arguments: requireFixtureToolArguments(tc.arguments),
|
|
703
707
|
status: "completed"
|
|
704
708
|
});
|
|
705
709
|
return buildResponseEnvelope(model, output, overrides);
|
|
@@ -757,7 +761,7 @@ function buildFunctionCallOutputItem(tc) {
|
|
|
757
761
|
id: generateId("fc"),
|
|
758
762
|
call_id: tc.id || generateToolCallId(),
|
|
759
763
|
name: tc.name,
|
|
760
|
-
arguments: tc.arguments,
|
|
764
|
+
arguments: requireFixtureToolArguments(tc.arguments),
|
|
761
765
|
status: "completed"
|
|
762
766
|
};
|
|
763
767
|
}
|
|
@@ -869,6 +873,41 @@ async function handleResponses(req, res, raw, fixtures, journal, defaults, setCo
|
|
|
869
873
|
} }));
|
|
870
874
|
return;
|
|
871
875
|
}
|
|
876
|
+
let inputError;
|
|
877
|
+
if (typeof responsesReq.input !== "string" && !Array.isArray(responsesReq.input)) inputError = "input must be a string or an array";
|
|
878
|
+
else if (Array.isArray(responsesReq.input)) for (const [index, item] of responsesReq.input.entries()) {
|
|
879
|
+
if (item === null) {
|
|
880
|
+
inputError = `input[${index}] must not be null`;
|
|
881
|
+
break;
|
|
882
|
+
}
|
|
883
|
+
if ((item.role === "system" || item.role === "developer" || item.role === "user" || item.role === "assistant") && item.content && typeof item.content !== "string" && !Array.isArray(item.content)) {
|
|
884
|
+
inputError = `input[${index}].content must be a string or an array`;
|
|
885
|
+
break;
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
let toolsError;
|
|
889
|
+
if (responsesReq.tools && responsesReq.tools.length !== 0) {
|
|
890
|
+
if (!Array.isArray(responsesReq.tools)) toolsError = "tools must be an array";
|
|
891
|
+
else if (responsesReq.tools.some((tool) => tool === null)) toolsError = "tools entries must not be null";
|
|
892
|
+
}
|
|
893
|
+
const validationError = inputError ?? toolsError;
|
|
894
|
+
if (validationError) {
|
|
895
|
+
journal.add({
|
|
896
|
+
method: req.method ?? "POST",
|
|
897
|
+
path: req.url ?? "/v1/responses",
|
|
898
|
+
headers: flattenHeaders(req.headers),
|
|
899
|
+
body: responsesReq,
|
|
900
|
+
response: {
|
|
901
|
+
status: 400,
|
|
902
|
+
fixture: null
|
|
903
|
+
}
|
|
904
|
+
});
|
|
905
|
+
writeErrorResponse(res, 400, JSON.stringify({ error: {
|
|
906
|
+
message: validationError,
|
|
907
|
+
type: "invalid_request_error"
|
|
908
|
+
} }));
|
|
909
|
+
return;
|
|
910
|
+
}
|
|
872
911
|
const completionReq = responsesToCompletionRequest(responsesReq);
|
|
873
912
|
completionReq._endpointType = "chat";
|
|
874
913
|
completionReq._context = getContext(req);
|
|
@@ -880,7 +919,7 @@ async function handleResponses(req, res, raw, fixtures, journal, defaults, setCo
|
|
|
880
919
|
defaults.logger.debug(`Responses fixture matched for ${req.method ?? "POST"} ${req.url ?? "/v1/responses"}`);
|
|
881
920
|
journal.incrementFixtureMatchCount(fixture, fixtures, testId);
|
|
882
921
|
} else defaults.logger.debug(`No responses fixture matched for ${req.method ?? "POST"} ${req.url ?? "/v1/responses"}`);
|
|
883
|
-
if (
|
|
922
|
+
if (await applyChaosAsync(res, fixture, defaults.chaos, req.headers, req.url, journal, {
|
|
884
923
|
method: req.method ?? "POST",
|
|
885
924
|
path: req.url ?? "/v1/responses",
|
|
886
925
|
headers: flattenHeaders(req.headers),
|
|
@@ -1093,5 +1132,5 @@ async function handleResponses(req, res, raw, fixtures, journal, defaults, setCo
|
|
|
1093
1132
|
}
|
|
1094
1133
|
|
|
1095
1134
|
//#endregion
|
|
1096
|
-
export { buildContentWithToolCallsStreamEvents, buildTextStreamEvents, buildToolCallStreamEvents, handleResponses, requestIncludesEncryptedReasoning, requestWantsEncryptedReasoning, responsesToCompletionRequest };
|
|
1135
|
+
export { buildContentWithToolCallsStreamEvents, buildTextResponse, buildTextStreamEvents, buildToolCallStreamEvents, handleResponses, requestIncludesEncryptedReasoning, requestWantsEncryptedReasoning, responsesToCompletionRequest };
|
|
1097
1136
|
//# sourceMappingURL=responses.js.map
|