@copilotkit/aimock 1.45.1 → 1.47.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 +25 -1
- package/README.md +11 -2
- package/dist/agui-mock.cjs +25 -25
- 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 +25 -25
- package/dist/agui-mock.js.map +1 -1
- package/dist/agui-types.d.cts.map +1 -1
- package/dist/aimock-cli.cjs +15 -1
- package/dist/aimock-cli.cjs.map +1 -1
- package/dist/aimock-cli.d.cts.map +1 -1
- package/dist/aimock-cli.d.ts.map +1 -1
- package/dist/aimock-cli.js +16 -2
- package/dist/aimock-cli.js.map +1 -1
- package/dist/api-key-auth.cjs +10 -9
- package/dist/api-key-auth.cjs.map +1 -1
- package/dist/api-key-auth.d.cts.map +1 -1
- package/dist/api-key-auth.d.ts.map +1 -1
- package/dist/api-key-auth.js +11 -10
- package/dist/api-key-auth.js.map +1 -1
- package/dist/aws-event-stream.cjs +20 -23
- package/dist/aws-event-stream.cjs.map +1 -1
- package/dist/aws-event-stream.d.cts +0 -1
- package/dist/aws-event-stream.d.ts +0 -1
- package/dist/aws-event-stream.js +20 -24
- package/dist/aws-event-stream.js.map +1 -1
- package/dist/batches.cjs +2 -4
- package/dist/batches.cjs.map +1 -1
- package/dist/batches.d.cts.map +1 -1
- package/dist/batches.d.ts.map +1 -1
- package/dist/batches.js +2 -4
- package/dist/batches.js.map +1 -1
- package/dist/bedrock-converse.cjs +139 -161
- 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 +137 -159
- package/dist/bedrock-converse.js.map +1 -1
- package/dist/bedrock.cjs +175 -216
- 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 +172 -213
- package/dist/bedrock.js.map +1 -1
- package/dist/byteplus-video.cjs +11 -10
- package/dist/byteplus-video.cjs.map +1 -1
- package/dist/byteplus-video.d.cts.map +1 -1
- package/dist/byteplus-video.d.ts.map +1 -1
- package/dist/byteplus-video.js +5 -4
- package/dist/byteplus-video.js.map +1 -1
- package/dist/chaos.cjs +5 -4
- package/dist/chaos.cjs.map +1 -1
- package/dist/chaos.d.cts.map +1 -1
- package/dist/chaos.d.ts.map +1 -1
- package/dist/chaos.js +5 -4
- package/dist/chaos.js.map +1 -1
- package/dist/cli.cjs +15 -0
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +15 -0
- package/dist/cli.js.map +1 -1
- package/dist/cohere.cjs +107 -180
- 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 +106 -179
- package/dist/cohere.js.map +1 -1
- package/dist/config-loader.cjs +29 -1
- package/dist/config-loader.cjs.map +1 -1
- package/dist/config-loader.d.cts +7 -1
- package/dist/config-loader.d.cts.map +1 -1
- package/dist/config-loader.d.ts +7 -1
- package/dist/config-loader.d.ts.map +1 -1
- package/dist/config-loader.js +29 -2
- package/dist/config-loader.js.map +1 -1
- package/dist/count-tokens.cjs +146 -0
- package/dist/count-tokens.cjs.map +1 -0
- package/dist/count-tokens.js +146 -0
- package/dist/count-tokens.js.map +1 -0
- package/dist/elevenlabs-audio.cjs +36 -34
- package/dist/elevenlabs-audio.cjs.map +1 -1
- package/dist/elevenlabs-audio.d.cts.map +1 -1
- package/dist/elevenlabs-audio.d.ts.map +1 -1
- package/dist/elevenlabs-audio.js +33 -31
- package/dist/elevenlabs-audio.js.map +1 -1
- package/dist/elevenlabs-voice.cjs +38 -37
- package/dist/elevenlabs-voice.cjs.map +1 -1
- package/dist/elevenlabs-voice.d.cts.map +1 -1
- package/dist/elevenlabs-voice.d.ts.map +1 -1
- package/dist/elevenlabs-voice.js +33 -32
- package/dist/elevenlabs-voice.js.map +1 -1
- package/dist/embedding-request.cjs +16 -0
- package/dist/embedding-request.cjs.map +1 -0
- package/dist/embedding-request.js +14 -0
- package/dist/embedding-request.js.map +1 -0
- package/dist/embeddings.cjs +30 -20
- package/dist/embeddings.cjs.map +1 -1
- package/dist/embeddings.d.cts.map +1 -1
- package/dist/embeddings.d.ts.map +1 -1
- package/dist/embeddings.js +30 -20
- package/dist/embeddings.js.map +1 -1
- package/dist/fal-audio.cjs +45 -43
- package/dist/fal-audio.cjs.map +1 -1
- package/dist/fal-audio.d.cts.map +1 -1
- package/dist/fal-audio.d.ts.map +1 -1
- package/dist/fal-audio.js +42 -40
- package/dist/fal-audio.js.map +1 -1
- package/dist/fal.cjs +17 -15
- package/dist/fal.cjs.map +1 -1
- package/dist/fal.js +16 -14
- package/dist/fal.js.map +1 -1
- package/dist/files.cjs +2 -4
- package/dist/files.cjs.map +1 -1
- package/dist/files.d.cts.map +1 -1
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +2 -4
- package/dist/files.js.map +1 -1
- package/dist/fine-tuning.cjs +2 -4
- package/dist/fine-tuning.cjs.map +1 -1
- package/dist/fine-tuning.d.cts.map +1 -1
- package/dist/fine-tuning.d.ts.map +1 -1
- package/dist/fine-tuning.js +2 -4
- package/dist/fine-tuning.js.map +1 -1
- package/dist/fixture-loader.cjs +140 -44
- package/dist/fixture-loader.cjs.map +1 -1
- package/dist/fixture-loader.d.cts.map +1 -1
- package/dist/fixture-loader.d.ts.map +1 -1
- package/dist/fixture-loader.js +141 -46
- package/dist/fixture-loader.js.map +1 -1
- package/dist/gemini-embeddings.cjs +26 -24
- package/dist/gemini-embeddings.cjs.map +1 -1
- package/dist/gemini-embeddings.js +26 -24
- package/dist/gemini-embeddings.js.map +1 -1
- package/dist/gemini-interactions.cjs +113 -156
- package/dist/gemini-interactions.cjs.map +1 -1
- package/dist/gemini-interactions.d.cts +0 -1
- package/dist/gemini-interactions.d.cts.map +1 -1
- package/dist/gemini-interactions.d.ts +0 -1
- package/dist/gemini-interactions.d.ts.map +1 -1
- package/dist/gemini-interactions.js +113 -156
- package/dist/gemini-interactions.js.map +1 -1
- package/dist/gemini.cjs +295 -218
- 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 +295 -219
- package/dist/gemini.js.map +1 -1
- package/dist/grok-video.cjs +14 -12
- package/dist/grok-video.cjs.map +1 -1
- package/dist/grok-video.d.cts.map +1 -1
- package/dist/grok-video.d.ts.map +1 -1
- package/dist/grok-video.js +8 -6
- package/dist/grok-video.js.map +1 -1
- package/dist/helpers.cjs +411 -75
- package/dist/helpers.cjs.map +1 -1
- package/dist/helpers.d.cts +51 -1
- package/dist/helpers.d.cts.map +1 -1
- package/dist/helpers.d.ts +51 -1
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +402 -74
- package/dist/helpers.js.map +1 -1
- package/dist/images.cjs +30 -28
- 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 +27 -25
- package/dist/images.js.map +1 -1
- package/dist/index.cjs +4 -2
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -4
- package/dist/journal.cjs +3 -1
- package/dist/journal.cjs.map +1 -1
- package/dist/journal.d.cts.map +1 -1
- package/dist/journal.d.ts.map +1 -1
- package/dist/journal.js +2 -1
- package/dist/journal.js.map +1 -1
- package/dist/llmock.cjs +3 -0
- package/dist/llmock.cjs.map +1 -1
- package/dist/llmock.d.cts.map +1 -1
- package/dist/llmock.d.ts.map +1 -1
- package/dist/llmock.js +3 -0
- package/dist/llmock.js.map +1 -1
- package/dist/mcp-fakes.d.cts.map +1 -1
- package/dist/mcp-handler.cjs +7 -3
- package/dist/mcp-handler.cjs.map +1 -1
- package/dist/mcp-handler.js +7 -3
- package/dist/mcp-handler.js.map +1 -1
- package/dist/mcp-recorder.cjs +2 -1
- package/dist/mcp-recorder.cjs.map +1 -1
- package/dist/mcp-recorder.js +3 -2
- package/dist/mcp-recorder.js.map +1 -1
- package/dist/messages.cjs +235 -202
- 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 +234 -202
- package/dist/messages.js.map +1 -1
- package/dist/metrics.cjs +5 -2
- package/dist/metrics.cjs.map +1 -1
- package/dist/metrics.d.cts.map +1 -1
- package/dist/metrics.d.ts.map +1 -1
- package/dist/metrics.js +6 -3
- package/dist/metrics.js.map +1 -1
- package/dist/misbehavior.cjs +62 -3
- package/dist/misbehavior.cjs.map +1 -1
- package/dist/misbehavior.d.cts.map +1 -1
- package/dist/misbehavior.d.ts.map +1 -1
- package/dist/misbehavior.js +63 -4
- package/dist/misbehavior.js.map +1 -1
- package/dist/model-utils.cjs +1 -0
- package/dist/model-utils.cjs.map +1 -1
- package/dist/model-utils.js +1 -1
- package/dist/model-utils.js.map +1 -1
- package/dist/moderation.cjs +15 -12
- package/dist/moderation.cjs.map +1 -1
- package/dist/moderation.js +14 -11
- package/dist/moderation.js.map +1 -1
- package/dist/ndjson-writer.cjs +21 -23
- package/dist/ndjson-writer.cjs.map +1 -1
- package/dist/ndjson-writer.d.cts +0 -1
- package/dist/ndjson-writer.d.cts.map +1 -1
- package/dist/ndjson-writer.d.ts +0 -1
- package/dist/ndjson-writer.d.ts.map +1 -1
- package/dist/ndjson-writer.js +21 -24
- package/dist/ndjson-writer.js.map +1 -1
- package/dist/ollama.cjs +276 -210
- 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 +273 -207
- package/dist/ollama.js.map +1 -1
- package/dist/openapi.cjs +323 -3
- package/dist/openapi.cjs.map +1 -1
- package/dist/openapi.d.cts.map +1 -1
- package/dist/openapi.d.ts.map +1 -1
- package/dist/openapi.js +324 -4
- package/dist/openapi.js.map +1 -1
- package/dist/openrouter-chat.cjs +11 -155
- package/dist/openrouter-chat.cjs.map +1 -1
- package/dist/openrouter-chat.js +11 -155
- package/dist/openrouter-chat.js.map +1 -1
- package/dist/openrouter-video.cjs +51 -74
- 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 +37 -60
- package/dist/openrouter-video.js.map +1 -1
- package/dist/raw-validation.cjs +177 -0
- package/dist/raw-validation.cjs.map +1 -0
- package/dist/raw-validation.js +176 -0
- package/dist/raw-validation.js.map +1 -0
- package/dist/recorder.cjs +176 -95
- 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 +176 -95
- package/dist/recorder.js.map +1 -1
- package/dist/rerank.cjs +13 -11
- package/dist/rerank.cjs.map +1 -1
- package/dist/rerank.js +12 -10
- package/dist/rerank.js.map +1 -1
- package/dist/response/catalog/anthropic-page.cjs +39 -0
- package/dist/response/catalog/anthropic-page.cjs.map +1 -0
- package/dist/response/catalog/anthropic-page.js +38 -0
- package/dist/response/catalog/anthropic-page.js.map +1 -0
- package/dist/response/catalog/collect.cjs +61 -0
- package/dist/response/catalog/collect.cjs.map +1 -0
- package/dist/response/catalog/collect.js +59 -0
- package/dist/response/catalog/collect.js.map +1 -0
- package/dist/response/catalog/gemini-page.cjs +25 -0
- package/dist/response/catalog/gemini-page.cjs.map +1 -0
- package/dist/response/catalog/gemini-page.js +24 -0
- package/dist/response/catalog/gemini-page.js.map +1 -0
- package/dist/response/catalog/render.cjs +182 -0
- package/dist/response/catalog/render.cjs.map +1 -0
- package/dist/response/catalog/render.js +171 -0
- package/dist/response/catalog/render.js.map +1 -0
- package/dist/response/deliver.cjs +144 -0
- package/dist/response/deliver.cjs.map +1 -0
- package/dist/response/deliver.js +143 -0
- package/dist/response/deliver.js.map +1 -0
- package/dist/response/errors.cjs +225 -0
- package/dist/response/errors.cjs.map +1 -0
- package/dist/response/errors.js +224 -0
- package/dist/response/errors.js.map +1 -0
- package/dist/response/finish.cjs +39 -0
- package/dist/response/finish.cjs.map +1 -0
- package/dist/response/finish.js +35 -0
- package/dist/response/finish.js.map +1 -0
- package/dist/response/frame-loop.cjs +102 -0
- package/dist/response/frame-loop.cjs.map +1 -0
- package/dist/response/frame-loop.js +100 -0
- package/dist/response/frame-loop.js.map +1 -0
- package/dist/response/lifecycle.cjs +223 -0
- package/dist/response/lifecycle.cjs.map +1 -0
- package/dist/response/lifecycle.js +211 -0
- package/dist/response/lifecycle.js.map +1 -0
- package/dist/response/policy.cjs +126 -0
- package/dist/response/policy.cjs.map +1 -0
- package/dist/response/policy.js +120 -0
- package/dist/response/policy.js.map +1 -0
- package/dist/response/profiles.cjs +69 -0
- package/dist/response/profiles.cjs.map +1 -0
- package/dist/response/profiles.js +65 -0
- package/dist/response/profiles.js.map +1 -0
- package/dist/response/proxy.cjs +71 -0
- package/dist/response/proxy.cjs.map +1 -0
- package/dist/response/proxy.js +70 -0
- package/dist/response/proxy.js.map +1 -0
- package/dist/response/raw.cjs +228 -0
- package/dist/response/raw.cjs.map +1 -0
- package/dist/response/raw.js +227 -0
- package/dist/response/raw.js.map +1 -0
- package/dist/response/timing.cjs +157 -0
- package/dist/response/timing.cjs.map +1 -0
- package/dist/response/timing.js +150 -0
- package/dist/response/timing.js.map +1 -0
- package/dist/response/usage/codecs/anthropic.cjs +52 -0
- package/dist/response/usage/codecs/anthropic.cjs.map +1 -0
- package/dist/response/usage/codecs/anthropic.js +50 -0
- package/dist/response/usage/codecs/anthropic.js.map +1 -0
- package/dist/response/usage/codecs/cohere.cjs +36 -0
- package/dist/response/usage/codecs/cohere.cjs.map +1 -0
- package/dist/response/usage/codecs/cohere.js +35 -0
- package/dist/response/usage/codecs/cohere.js.map +1 -0
- package/dist/response/usage/codecs/converse.cjs +16 -0
- package/dist/response/usage/codecs/converse.cjs.map +1 -0
- package/dist/response/usage/codecs/converse.js +15 -0
- package/dist/response/usage/codecs/converse.js.map +1 -0
- package/dist/response/usage/codecs/gemini.cjs +31 -0
- package/dist/response/usage/codecs/gemini.cjs.map +1 -0
- package/dist/response/usage/codecs/gemini.js +31 -0
- package/dist/response/usage/codecs/gemini.js.map +1 -0
- package/dist/response/usage/codecs/interactions.cjs +22 -0
- package/dist/response/usage/codecs/interactions.cjs.map +1 -0
- package/dist/response/usage/codecs/interactions.js +21 -0
- package/dist/response/usage/codecs/interactions.js.map +1 -0
- package/dist/response/usage/codecs/ollama.cjs +17 -0
- package/dist/response/usage/codecs/ollama.cjs.map +1 -0
- package/dist/response/usage/codecs/ollama.js +17 -0
- package/dist/response/usage/codecs/ollama.js.map +1 -0
- package/dist/response/usage/codecs/openai.cjs +52 -0
- package/dist/response/usage/codecs/openai.cjs.map +1 -0
- package/dist/response/usage/codecs/openai.js +50 -0
- package/dist/response/usage/codecs/openai.js.map +1 -0
- package/dist/response/usage/codecs/openrouter.cjs +68 -0
- package/dist/response/usage/codecs/openrouter.cjs.map +1 -0
- package/dist/response/usage/codecs/openrouter.js +67 -0
- package/dist/response/usage/codecs/openrouter.js.map +1 -0
- package/dist/response/usage/codecs/realtime.cjs +19 -0
- package/dist/response/usage/codecs/realtime.cjs.map +1 -0
- package/dist/response/usage/codecs/realtime.js +18 -0
- package/dist/response/usage/codecs/realtime.js.map +1 -0
- package/dist/response/usage/codecs/responses.cjs +21 -0
- package/dist/response/usage/codecs/responses.cjs.map +1 -0
- package/dist/response/usage/codecs/responses.js +20 -0
- package/dist/response/usage/codecs/responses.js.map +1 -0
- package/dist/response/usage/estimate.cjs +23 -0
- package/dist/response/usage/estimate.cjs.map +1 -0
- package/dist/response/usage/estimate.js +21 -0
- package/dist/response/usage/estimate.js.map +1 -0
- package/dist/response/usage/fields.cjs +72 -0
- package/dist/response/usage/fields.cjs.map +1 -0
- package/dist/response/usage/fields.js +70 -0
- package/dist/response/usage/fields.js.map +1 -0
- package/dist/response/usage/recording.cjs +52 -0
- package/dist/response/usage/recording.cjs.map +1 -0
- package/dist/response/usage/recording.js +52 -0
- package/dist/response/usage/recording.js.map +1 -0
- package/dist/responses.cjs +304 -196
- 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 +303 -195
- package/dist/responses.js.map +1 -1
- package/dist/route-registry.cjs +45 -0
- package/dist/route-registry.cjs.map +1 -1
- package/dist/route-registry.d.cts.map +1 -1
- package/dist/route-registry.d.ts.map +1 -1
- package/dist/route-registry.js +41 -1
- package/dist/route-registry.js.map +1 -1
- package/dist/router.cjs +24 -4
- package/dist/router.cjs.map +1 -1
- package/dist/router.d.cts +7 -1
- package/dist/router.d.cts.map +1 -1
- package/dist/router.d.ts +7 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +24 -5
- package/dist/router.js.map +1 -1
- package/dist/search.cjs +13 -11
- package/dist/search.cjs.map +1 -1
- package/dist/search.js +12 -10
- package/dist/search.js.map +1 -1
- package/dist/server.cjs +293 -248
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +294 -249
- package/dist/server.js.map +1 -1
- package/dist/speech.cjs +20 -18
- package/dist/speech.cjs.map +1 -1
- package/dist/speech.d.cts.map +1 -1
- package/dist/speech.d.ts.map +1 -1
- package/dist/speech.js +19 -17
- package/dist/speech.js.map +1 -1
- package/dist/sse-writer.cjs +56 -30
- package/dist/sse-writer.cjs.map +1 -1
- package/dist/sse-writer.d.cts +0 -1
- package/dist/sse-writer.d.cts.map +1 -1
- package/dist/sse-writer.d.ts +0 -1
- package/dist/sse-writer.d.ts.map +1 -1
- package/dist/sse-writer.js +55 -31
- package/dist/sse-writer.js.map +1 -1
- package/dist/stream-collapse.cjs +118 -11
- package/dist/stream-collapse.cjs.map +1 -1
- package/dist/stream-collapse.d.cts +10 -9
- package/dist/stream-collapse.d.cts.map +1 -1
- package/dist/stream-collapse.d.ts +10 -9
- package/dist/stream-collapse.d.ts.map +1 -1
- package/dist/stream-collapse.js +118 -11
- package/dist/stream-collapse.js.map +1 -1
- package/dist/transcription.cjs +31 -43
- 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 +31 -43
- package/dist/transcription.js.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +231 -9
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.ts +231 -9
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/vector-mock.cjs +3 -8
- package/dist/vector-mock.cjs.map +1 -1
- package/dist/vector-mock.d.cts.map +1 -1
- package/dist/vector-mock.d.ts.map +1 -1
- package/dist/vector-mock.js +3 -8
- package/dist/vector-mock.js.map +1 -1
- package/dist/vector-stores.cjs +2 -4
- package/dist/vector-stores.cjs.map +1 -1
- package/dist/vector-stores.d.cts.map +1 -1
- package/dist/vector-stores.d.ts.map +1 -1
- package/dist/vector-stores.js +2 -4
- package/dist/vector-stores.js.map +1 -1
- package/dist/veo-video.cjs +16 -14
- package/dist/veo-video.cjs.map +1 -1
- package/dist/veo-video.js +10 -8
- package/dist/veo-video.js.map +1 -1
- package/dist/video.cjs +21 -19
- package/dist/video.cjs.map +1 -1
- package/dist/video.d.cts.map +1 -1
- package/dist/video.d.ts.map +1 -1
- package/dist/video.js +20 -18
- package/dist/video.js.map +1 -1
- package/dist/ws-framing.cjs +12 -6
- package/dist/ws-framing.cjs.map +1 -1
- package/dist/ws-framing.d.cts +2 -0
- package/dist/ws-framing.d.cts.map +1 -1
- package/dist/ws-framing.d.ts +2 -0
- package/dist/ws-framing.d.ts.map +1 -1
- package/dist/ws-framing.js +12 -6
- package/dist/ws-framing.js.map +1 -1
- package/dist/ws-gemini-live.cjs +131 -96
- package/dist/ws-gemini-live.cjs.map +1 -1
- package/dist/ws-gemini-live.d.cts +0 -1
- package/dist/ws-gemini-live.d.cts.map +1 -1
- package/dist/ws-gemini-live.d.ts +0 -1
- package/dist/ws-gemini-live.d.ts.map +1 -1
- package/dist/ws-gemini-live.js +130 -95
- package/dist/ws-gemini-live.js.map +1 -1
- package/dist/ws-live.cjs +6 -5
- package/dist/ws-live.cjs.map +1 -1
- package/dist/ws-live.js +5 -4
- package/dist/ws-live.js.map +1 -1
- package/dist/ws-realtime.cjs +108 -124
- 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 +105 -121
- package/dist/ws-realtime.js.map +1 -1
- package/dist/ws-responses.cjs +80 -59
- package/dist/ws-responses.cjs.map +1 -1
- package/dist/ws-responses.d.cts.map +1 -1
- package/dist/ws-responses.d.ts.map +1 -1
- package/dist/ws-responses.js +79 -58
- package/dist/ws-responses.js.map +1 -1
- package/package.json +4 -1
- package/skills/write-fixtures/SKILL.md +57 -16
package/dist/journal.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"journal.d.cts","names":[],"sources":["../src/journal.ts"],"sourcesContent":[],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"journal.d.cts","names":[],"sources":["../src/journal.ts"],"sourcesContent":[],"mappings":";;;;;;;AAiEA;;;;;AAqFA;AAuCA;;;;;;AA6Da,iBAzLG,oBAAA,CAyLH,IAAA,EAxLL,WAwLK,GAAA,IAAA,GAAA,SAAA,CAAA,EAAA,IAAA,IAvLF,qBAuLE;AAAyD,UApGrD,cAAA,CAoGqD;;;;;;;;;;;;;YA6JlB,CAAA,EAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;kBA7NlC;;cAGL,OAAA,YAAmB;;;;;;;;;;;;;;;;;;;wBAwBT;;;;;;;;;;;;;;;;;;4BAgCK,IAAI;;aAKnB,KAAK,oDAAoD,UAAU;;;;;;;;;;;;MAuC3C;aASxB;yBAIY,UAAU;;;;;;uBAUZ,eAAe;;;;;;;;gDAWU,IAAI;;;;;;;;;;;sBAwD9B;mBAOH;oBAIC;;;oDAiBgC,YAAY;;;;;;;+CAejB,YAAY;gCAS3B;sCAKnB,gCACc"}
|
package/dist/journal.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"journal.d.ts","names":[],"sources":["../src/journal.ts"],"sourcesContent":[],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"journal.d.ts","names":[],"sources":["../src/journal.ts"],"sourcesContent":[],"mappings":";;;;;;;AAiEA;;;;;AAqFA;AAuCA;;;;;;AA6Da,iBAzLG,oBAAA,CAyLH,IAAA,EAxLL,WAwLK,GAAA,IAAA,GAAA,SAAA,CAAA,EAAA,IAAA,IAvLF,qBAuLE;AAAyD,UApGrD,cAAA,CAoGqD;;;;;;;;;;;;;YA6JlB,CAAA,EAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;kBA7NlC;;cAGL,OAAA,YAAmB;;;;;;;;;;;;;;;;;;;wBAwBT;;;;;;;;;;;;;;;;;;4BAgCK,IAAI;;aAKnB,KAAK,oDAAoD,UAAU;;;;;;;;;;;;MAuC3C;aASxB;yBAIY,UAAU;;;;;;uBAUZ,eAAe;;;;;;;;gDAWU,IAAI;;;;;;;;;;;sBAwD9B;mBAOH;oBAIC;;;oDAiBgC,YAAY;;;;;;;+CAejB,YAAY;gCAS3B;sCAKnB,gCACc"}
|
package/dist/journal.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DEFAULT_TEST_ID } from "./constants.js";
|
|
2
2
|
import { generateId } from "./helpers.js";
|
|
3
|
+
import { isDeepStrictEqual } from "node:util";
|
|
3
4
|
|
|
4
5
|
//#region src/journal.ts
|
|
5
6
|
/**
|
|
@@ -76,7 +77,7 @@ function systemMessageEqual(a, b) {
|
|
|
76
77
|
* (ignoring sequenceIndex). Used to group sequenced fixtures.
|
|
77
78
|
*/
|
|
78
79
|
function matchCriteriaEqual(a, b) {
|
|
79
|
-
return fieldEqual(a.userMessage, b.userMessage) && systemMessageEqual(a.systemMessage, b.systemMessage) && fieldEqual(a.inputText, b.inputText) && fieldEqual(a.toolCallId, b.toolCallId) && fieldEqual(a.toolName, b.toolName) && fieldEqual(a.toolNamespace, b.toolNamespace) && fieldEqual(a.model, b.model) && fieldEqual(a.responseFormat, b.responseFormat) && fieldEqual(a.predicate, b.predicate) && fieldEqual(a.endpoint, b.endpoint) && fieldEqual(a.turnIndex, b.turnIndex) && fieldEqual(a.hasToolResult, b.hasToolResult) && fieldEqual(a.toolResultContains, b.toolResultContains) && fieldEqual(a.context, b.context);
|
|
80
|
+
return fieldEqual(a.userMessage, b.userMessage) && systemMessageEqual(a.systemMessage, b.systemMessage) && fieldEqual(a.inputText, b.inputText) && isDeepStrictEqual(a.embeddingRequest, b.embeddingRequest) && fieldEqual(a.toolCallId, b.toolCallId) && fieldEqual(a.toolName, b.toolName) && fieldEqual(a.toolNamespace, b.toolNamespace) && fieldEqual(a.model, b.model) && fieldEqual(a.responseFormat, b.responseFormat) && fieldEqual(a.predicate, b.predicate) && fieldEqual(a.endpoint, b.endpoint) && fieldEqual(a.turnIndex, b.turnIndex) && fieldEqual(a.hasToolResult, b.hasToolResult) && fieldEqual(a.toolResultContains, b.toolResultContains) && fieldEqual(a.context, b.context);
|
|
80
81
|
}
|
|
81
82
|
/** Count-map keys resolve through `identity`, so every alias of a fixture finds its caller entry. */
|
|
82
83
|
var FixtureCountMap = class extends Map {
|
package/dist/journal.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"journal.js","names":[],"sources":["../src/journal.ts"],"sourcesContent":["import { generateId } from \"./helpers.js\";\nimport type {\n ChatCompletionRequest,\n Fixture,\n FixtureMatch,\n JournalBody,\n JournalEntry,\n MisbehaviorCounterKey,\n MisbehaviorCounters,\n} from \"./types.js\";\nimport { DEFAULT_TEST_ID } from \"./constants.js\";\nexport { DEFAULT_TEST_ID } from \"./constants.js\";\n\n/**\n * Maximum UTF-8 byte length of a serialized request body retained in a\n * journal entry. Bodies whose JSON serialization exceeds this byte size are\n * replaced with a truncation marker.\n *\n * Only the request `body` field is capped here. `headers` and `path` are\n * retained uncapped, but they are naturally bounded by Node's default ~16 KB\n * maximum HTTP header size, so the per-entry overhead beyond the body cap\n * remains small. Combined with the journal's maxEntries limit (default 1000),\n * the total `JSON.stringify(journal.getAll())` output stays well under V8's\n * ~512 MB string limit even at maximum capacity.\n */\nconst JOURNAL_BODY_CAP_BYTES = 64 * 1024; // 64 KB\n\n/**\n * If `body` serializes to more than JOURNAL_BODY_CAP_BYTES (in UTF-8 bytes),\n * replace it with a truncation marker. Returns the original body when within\n * the cap, or null when `body` is null.\n *\n * The gate uses Buffer.byteLength (UTF-8 bytes) rather than .length (UTF-16\n * code units) to match the constant name and to correctly cap multibyte\n * content (e.g. CJK/emoji) whose code-unit count falls under the threshold\n * but whose byte size does not.\n */\nfunction capBody(body: JournalBody | null): JournalBody | null {\n if (body === null) return null;\n const serialized = JSON.stringify(body);\n if (Buffer.byteLength(serialized, \"utf8\") <= JOURNAL_BODY_CAP_BYTES) return body;\n // The marker is not a chat request, and `JournalBody` no longer claims it is\n // — downstream consumers (e.g. GET /journal) treat the body as opaque JSON.\n return {\n __aimock_truncated: true,\n originalByteSize: Buffer.byteLength(serialized, \"utf8\"),\n note: \"body truncated by aimock journal cap (64 KB limit)\",\n };\n}\n\n/**\n * Narrow a journaled body to a chat-completion request.\n *\n * `JournalEntry.body` is a union (see {@link JournalBody}): most entries hold a\n * chat request, but the fine-tuning create payload and this module's own\n * truncation marker do not. Anything reading `messages`, `model` or the rest of\n * the chat shape off a journal entry — inside aimock or in a consumer's test\n * — goes through here, so an entry that is not a chat request fails as a\n * `false` it can assert on rather than as an undefined property three accesses\n * later.\n *\n * `messages` is the discriminator because it is the one required field no\n * other journaled shape carries.\n */\nexport function isChatCompletionBody(\n body: JournalBody | null | undefined,\n): body is ChatCompletionRequest {\n return (\n body !== null &&\n body !== undefined &&\n Array.isArray((body as { messages?: unknown }).messages) &&\n typeof (body as { model?: unknown }).model === \"string\"\n );\n}\n\n/**\n * Compare two field values, handling RegExp by source+flags rather than reference.\n */\nfunction fieldEqual(a: unknown, b: unknown): boolean {\n if (a instanceof RegExp && b instanceof RegExp)\n return a.source === b.source && a.flags === b.flags;\n return a === b;\n}\n\n/**\n * Compare two systemMessage values. Handles string, string[], and RegExp.\n * Both-undefined is treated as equal.\n */\nfunction systemMessageEqual(\n a: string | string[] | RegExp | undefined,\n b: string | string[] | RegExp | undefined,\n): boolean {\n if (a === undefined && b === undefined) return true;\n if (a === undefined || b === undefined) return false;\n if (typeof a === \"string\" && typeof b === \"string\") return a === b;\n if (Array.isArray(a) && Array.isArray(b))\n return a.length === b.length && a.every((v, i) => v === b[i]);\n if (a instanceof RegExp && b instanceof RegExp)\n return a.source === b.source && a.flags === b.flags;\n return false;\n}\n\n/**\n * Check whether two fixture match objects have the same criteria\n * (ignoring sequenceIndex). Used to group sequenced fixtures.\n */\nfunction matchCriteriaEqual(a: FixtureMatch, b: FixtureMatch): boolean {\n return (\n fieldEqual(a.userMessage, b.userMessage) &&\n systemMessageEqual(a.systemMessage, b.systemMessage) &&\n fieldEqual(a.inputText, b.inputText) &&\n fieldEqual(a.toolCallId, b.toolCallId) &&\n fieldEqual(a.toolName, b.toolName) &&\n fieldEqual(a.toolNamespace, b.toolNamespace) &&\n fieldEqual(a.model, b.model) &&\n fieldEqual(a.responseFormat, b.responseFormat) &&\n fieldEqual(a.predicate, b.predicate) &&\n fieldEqual(a.endpoint, b.endpoint) &&\n fieldEqual(a.turnIndex, b.turnIndex) &&\n fieldEqual(a.hasToolResult, b.hasToolResult) &&\n fieldEqual(a.toolResultContains, b.toolResultContains) &&\n fieldEqual(a.context, b.context)\n );\n}\n\n/** Count-map keys resolve through `identity`, so every alias of a fixture finds its caller entry. */\nclass FixtureCountMap extends Map<Fixture, number> {\n constructor(private readonly identity: (fixture: Fixture) => Fixture) {\n super();\n }\n\n override get(key: Fixture): number | undefined {\n return super.get(this.identity(key));\n }\n\n override has(key: Fixture): boolean {\n return super.has(this.identity(key));\n }\n\n override set(key: Fixture, value: number): this {\n return super.set(this.identity(key), value);\n }\n\n override delete(key: Fixture): boolean {\n return super.delete(this.identity(key));\n }\n}\n\nexport interface JournalOptions {\n /**\n * Maximum number of entries to retain. When exceeded, oldest entries are\n * dropped FIFO. Set to 0 (or omit) for unbounded retention (the historical\n * default — suitable for short-lived test runs only). Negative values are\n * rejected at the CLI parse layer; programmatically they are treated as 0\n * (unbounded) for back-compat.\n *\n * Long-running servers (e.g. mock proxies in CI/demo environments) should\n * always set a finite cap: every request appends an entry holding the\n * request body + headers + fixture reference, and without a cap the\n * journal grows until the process OOMs.\n */\n maxEntries?: number;\n /**\n * Maximum number of unique testIds retained across fixture match-count\n * and misbehavior counters. When exceeded, the oldest testId\n * (by first-insertion order) is evicted FIFO. Set to 0 (or omit) for\n * unbounded retention. Negative values are rejected at the CLI parse\n * layer; programmatically they are treated as 0 (unbounded) for\n * back-compat. Without a cap this map can grow over time in long-running\n * servers that see many unique testIds.\n */\n fixtureCountsMaxTestIds?: number;\n /**\n * Called with every entry {@link Journal.add} creates, right after it is\n * recorded. The hook exists so an embedder can attribute an entry to the\n * request that produced it WITHOUT touching each of the ~100 `journal.add`\n * call sites spread across the handler modules: the server binds the entry\n * to the in-flight `IncomingMessage` here, and its error arm then amends\n * that exact object rather than guessing from a caller-supplied header.\n *\n * The entry is already recorded when the hook runs, so a hook that throws\n * does not lose the write — but it does propagate out of `add` into the\n * caller's error path, so a hook must not throw.\n */\n onAdd?: (entry: JournalEntry) => void;\n}\n\nexport class Journal implements MisbehaviorCounters {\n private entries: JournalEntry[] = [];\n private readonly matchedFixtures = new WeakMap<JournalEntry, Fixture>();\n /** The fixture a request was served from, where the entry names its caller fixture instead. */\n private readonly servedFixtures = new WeakMap<JournalEntry, Fixture>();\n private readonly fixtureMatchCountsByTestId: Map<string, Map<Fixture, number>> = new Map();\n /** An extended server's view of a fixture to the caller's fixture (configureFixtureViewSource). */\n private fixtureViewSource = (fixture: Fixture): Fixture => fixture;\n private fixtureCountIdentity = (fixture: Fixture): Fixture => fixture;\n /** The key a fixture is counted under: the caller's object behind any view or copy. */\n private readonly fixtureCountKey = (fixture: Fixture): Fixture =>\n this.fixtureCountIdentity(this.fixtureViewSource(fixture));\n private createFixtureCountMap = (): Map<Fixture, number> => new Map();\n private fixtureCountIdentityConfigured = false;\n private fixtureViewSourceConfigured = false;\n private readonly counterTestIds = new Set<string>();\n private readonly misbehaviorCountersByTestId = new Map<\n string,\n Map<string, Map<number, { ordinal: number; firings: number }>>\n >();\n private readonly maxEntries: number;\n private readonly fixtureCountsMaxTestIds: number;\n private readonly onAdd?: (entry: JournalEntry) => void;\n\n constructor(options: JournalOptions = {}) {\n this.onAdd = options.onAdd;\n // Treat 0 or negative as \"unbounded\" to preserve prior behavior when\n // the option is omitted or explicitly disabled.\n const cap = options.maxEntries;\n this.maxEntries = cap !== undefined && cap > 0 ? cap : 0;\n const testIdCap = options.fixtureCountsMaxTestIds;\n this.fixtureCountsMaxTestIds = testIdCap !== undefined && testIdCap > 0 ? testIdCap : 0;\n }\n\n /**\n * The per-test-id cap on fixture match-count maps, for an MCP mount to pass\n * to `McpFakeStore.setMaxTestIds`. Always a non-negative safe integer, `0`\n * meaning unbounded, and never throws, whatever option was passed:\n * omitted, zero, negative or `NaN` is `0`; `Infinity` or a value above\n * `Number.MAX_SAFE_INTEGER` (never reached) is `0`; a fraction of 1 or more\n * is rounded down (`1.5` evicts at 2 ids, so it keeps 1). For these values\n * it is the number of test ids the journal keeps.\n *\n * An option between 0 and 1 is the exception. The journal keeps no test id\n * (each new count map is evicted as soon as it is made, so counts never\n * advance), and a store cap cannot say \"keep none\" because `0` is\n * unbounded. The getter returns `1`, the smallest bounded cap, so a store\n * given it keeps 1 test id where the journal keeps 0.\n */\n get fixtureCountsMaxTestIdsCap(): number {\n const cap = this.fixtureCountsMaxTestIds;\n if (!(cap > 0) || cap > Number.MAX_SAFE_INTEGER) return 0;\n return Math.max(1, Math.floor(cap));\n }\n\n /** Backwards-compatible accessor — returns the default (no testId) count map. */\n get fixtureMatchCounts(): Map<Fixture, number> {\n return this.getFixtureMatchCountsForTest(DEFAULT_TEST_ID);\n }\n\n /** @internal matchedFixture preserves identity when Live supplies safe diagnostics. */\n add(entry: Omit<JournalEntry, \"id\" | \"timestamp\">, matchedFixture?: Fixture): JournalEntry {\n const full: JournalEntry = {\n id: generateId(\"req\"),\n timestamp: Date.now(),\n ...entry,\n body: capBody(entry.body),\n };\n // A request is served from an extended server's view of a fixture, or\n // from LLMock's per-addition copy with misbehavior enabled; the entry\n // names the caller's fixture behind it, as in 1.44.0.\n const fixture = full.response.fixture;\n const source = fixture ? this.fixtureCountKey(fixture) : fixture;\n if (fixture && source !== fixture) {\n full.response = { ...full.response, fixture: source };\n this.servedFixtures.set(full, fixture);\n }\n if (matchedFixture) this.matchedFixtures.set(full, this.fixtureCountKey(matchedFixture));\n this.entries.push(full);\n // FIFO eviction when over capacity. Array.prototype.shift() is O(n)\n // regardless of how many we drop per add; we accept it at small caps\n // (default 1000) because the constant factor is tiny and this runs once\n // per request. For much larger caps, switch to a ring buffer for true\n // O(1) eviction.\n if (this.maxEntries > 0 && this.entries.length > this.maxEntries) {\n this.entries.shift();\n }\n this.onAdd?.(full);\n return full;\n }\n\n /**\n * Return every entry, or with `limit` the most recent `limit` entries.\n * `0` returns `[]` — exactly what `GET /__aimock/journal?limit=0` answers.\n * `slice(-0)` is `slice(0)`, so a `0` used to return the ENTIRE journal; it\n * is special-cased so the library and the HTTP route agree. This is a public\n * library API, so odd limits are tolerated rather than thrown on: a\n * non-finite limit (`NaN`, `Infinity`) means \"no limit\", a fractional limit\n * floors, and any limit at or below `0` asks for nothing.\n */\n getAll(opts?: { limit?: number }): JournalEntry[] {\n if (opts?.limit !== undefined && Number.isFinite(opts.limit)) {\n const limit = Math.floor(opts.limit);\n if (limit <= 0) return [];\n return this.entries.slice(-limit);\n }\n return this.entries.slice();\n }\n\n getLast(): JournalEntry | null {\n return this.entries.length > 0 ? this.entries[this.entries.length - 1] : null;\n }\n\n findByFixture(fixture: Fixture): JournalEntry[] {\n const key = this.fixtureCountKey(fixture);\n return this.entries.filter((e) => (this.matchedFixtures.get(e) ?? e.response.fixture) === key);\n }\n\n /**\n * @internal The fixture `entry`'s request was served from: the extended\n * view or the per-addition copy when the entry names the caller's fixture\n * behind it, otherwise `entry.response.fixture`. The journal JSON shows it.\n */\n servedFixture(entry: JournalEntry): Fixture | null {\n return this.servedFixtures.get(entry) ?? entry.response.fixture;\n }\n\n /**\n * READ-ONLY accessor. Returns the existing count map for `testId`, or an\n * empty transient Map if none exists. Does NOT insert into the cache and\n * does NOT trigger FIFO eviction — callers may read freely without\n * perturbing cache state. For the write path, see\n * `getOrCreateFixtureMatchCountsForTest`.\n */\n getFixtureMatchCountsForTest(testId: string): Map<Fixture, number> {\n return this.fixtureMatchCountsByTestId.get(testId) ?? this.createFixtureCountMap();\n }\n\n /**\n * WRITE path: get the count map for `testId`, inserting a fresh empty Map\n * if missing and running FIFO eviction when the testId cap is exceeded.\n * Only callers that intend to mutate the map (e.g. incrementing a count)\n * should use this.\n */\n private getOrCreateFixtureMatchCountsForTest(testId: string): Map<Fixture, number> {\n let counts = this.fixtureMatchCountsByTestId.get(testId);\n if (!counts) {\n counts = this.createFixtureCountMap();\n this.fixtureMatchCountsByTestId.set(testId, counts);\n this.admitCounterTestId(testId);\n }\n return counts;\n }\n\n /** Match and fault mutations share one admission order and capacity. */\n private admitCounterTestId(testId: string): void {\n this.counterTestIds.add(testId);\n if (\n this.fixtureCountsMaxTestIds > 0 &&\n this.counterTestIds.size > this.fixtureCountsMaxTestIds\n ) {\n const oldest = this.counterTestIds.values().next().value;\n if (oldest !== undefined) {\n this.counterTestIds.delete(oldest);\n this.fixtureMatchCountsByTestId.delete(oldest);\n this.misbehaviorCountersByTestId.delete(oldest);\n }\n }\n }\n\n private getOrCreateMisbehaviorCounter(key: MisbehaviorCounterKey) {\n let sources = this.misbehaviorCountersByTestId.get(key.testId);\n if (!sources) {\n sources = new Map();\n this.misbehaviorCountersByTestId.set(key.testId, sources);\n this.admitCounterTestId(key.testId);\n }\n let entries = sources.get(key.sourceKey);\n if (!entries) {\n entries = new Map();\n sources.set(key.sourceKey, entries);\n }\n let counter = entries.get(key.entryIndex);\n if (!counter) {\n counter = { ordinal: 0, firings: 0 };\n entries.set(key.entryIndex, counter);\n }\n return counter;\n }\n\n getFiringCount(key: MisbehaviorCounterKey): number {\n return (\n this.misbehaviorCountersByTestId.get(key.testId)?.get(key.sourceKey)?.get(key.entryIndex)\n ?.firings ?? 0\n );\n }\n\n nextOrdinal(key: MisbehaviorCounterKey): number {\n return this.getOrCreateMisbehaviorCounter(key).ordinal++;\n }\n\n recordFiring(key: MisbehaviorCounterKey): void {\n this.getOrCreateMisbehaviorCounter(key).firings++;\n }\n\n clearMisbehaviorCounters(testId?: string): void {\n if (testId !== undefined) {\n this.misbehaviorCountersByTestId.delete(testId);\n if (!this.fixtureMatchCountsByTestId.has(testId)) this.counterTestIds.delete(testId);\n } else {\n this.misbehaviorCountersByTestId.clear();\n for (const id of this.counterTestIds) {\n if (!this.fixtureMatchCountsByTestId.has(id)) this.counterTestIds.delete(id);\n }\n }\n }\n\n /** @internal LLMock configures caller count identity before serving requests. */\n configureFixtureCountIdentity(identity: (fixture: Fixture) => Fixture): void {\n if (this.fixtureCountIdentityConfigured || this.fixtureMatchCountsByTestId.size > 0) {\n throw new Error(\"Fixture count identity must be configured once before counting\");\n }\n this.fixtureCountIdentity = identity;\n this.createFixtureCountMap = () => new FixtureCountMap(this.fixtureCountKey);\n this.fixtureCountIdentityConfigured = true;\n }\n\n /**\n * @internal A server with `responsesTools: \"extended\"` matches each fixture\n * through its extended view. `source` maps a view back to the caller's\n * fixture, so counts, `findByFixture` and `JournalEntry.response.fixture`\n * keep the caller's object. Configured once, before counting.\n */\n configureFixtureViewSource(source: (fixture: Fixture) => Fixture): void {\n if (this.fixtureViewSourceConfigured || this.fixtureMatchCountsByTestId.size > 0) {\n throw new Error(\"Fixture view source must be configured once before counting\");\n }\n this.fixtureViewSource = source;\n this.createFixtureCountMap = () => new FixtureCountMap(this.fixtureCountKey);\n this.fixtureViewSourceConfigured = true;\n }\n\n getFixtureMatchCount(fixture: Fixture, testId = DEFAULT_TEST_ID): number {\n return this.getFixtureMatchCountsForTest(testId).get(fixture) ?? 0;\n }\n\n incrementFixtureMatchCount(\n fixture: Fixture,\n allFixtures?: readonly Fixture[],\n testId = DEFAULT_TEST_ID,\n ): void {\n const counts = this.getOrCreateFixtureMatchCountsForTest(testId);\n counts.set(fixture, (counts.get(fixture) ?? 0) + 1);\n // When a sequenced fixture matches, also increment all siblings with matching criteria\n if (fixture.match.sequenceIndex !== undefined && allFixtures) {\n for (const sibling of allFixtures) {\n if (this.fixtureCountKey(sibling) === this.fixtureCountKey(fixture)) continue;\n if (sibling.match.sequenceIndex === undefined) continue;\n if (matchCriteriaEqual(fixture.match, sibling.match)) {\n counts.set(sibling, (counts.get(sibling) ?? 0) + 1);\n }\n }\n }\n }\n\n clearMatchCounts(testId?: string): void {\n if (testId !== undefined) {\n this.fixtureMatchCountsByTestId.delete(testId);\n this.clearMisbehaviorCounters(testId);\n } else {\n this.fixtureMatchCountsByTestId.clear();\n this.clearMisbehaviorCounters();\n }\n }\n\n /**\n * Clear ONLY the request journal entries, preserving fixture match-counts.\n * Match-counts are fixture-matching/sequencing state, not journal data, so\n * clearing the journal must not silently rewind sequenced fixtures. Used by\n * `POST /__aimock/reset/journal`. For a full reset (entries + match-counts),\n * use `clear()` instead.\n */\n clearEntries(): void {\n this.entries = [];\n }\n\n clear(): void {\n this.entries = [];\n this.clearMatchCounts();\n }\n\n get size(): number {\n return this.entries.length;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"journal.js","names":[],"sources":["../src/journal.ts"],"sourcesContent":["import { generateId } from \"./helpers.js\";\nimport { isDeepStrictEqual } from \"node:util\";\nimport type {\n ChatCompletionRequest,\n Fixture,\n FixtureMatch,\n JournalBody,\n JournalEntry,\n MisbehaviorCounterKey,\n MisbehaviorCounters,\n} from \"./types.js\";\nimport { DEFAULT_TEST_ID } from \"./constants.js\";\nexport { DEFAULT_TEST_ID } from \"./constants.js\";\n\n/**\n * Maximum UTF-8 byte length of a serialized request body retained in a\n * journal entry. Bodies whose JSON serialization exceeds this byte size are\n * replaced with a truncation marker.\n *\n * Only the request `body` field is capped here. `headers` and `path` are\n * retained uncapped, but they are naturally bounded by Node's default ~16 KB\n * maximum HTTP header size, so the per-entry overhead beyond the body cap\n * remains small. Combined with the journal's maxEntries limit (default 1000),\n * the total `JSON.stringify(journal.getAll())` output stays well under V8's\n * ~512 MB string limit even at maximum capacity.\n */\nconst JOURNAL_BODY_CAP_BYTES = 64 * 1024; // 64 KB\n\n/**\n * If `body` serializes to more than JOURNAL_BODY_CAP_BYTES (in UTF-8 bytes),\n * replace it with a truncation marker. Returns the original body when within\n * the cap, or null when `body` is null.\n *\n * The gate uses Buffer.byteLength (UTF-8 bytes) rather than .length (UTF-16\n * code units) to match the constant name and to correctly cap multibyte\n * content (e.g. CJK/emoji) whose code-unit count falls under the threshold\n * but whose byte size does not.\n */\nfunction capBody(body: JournalBody | null): JournalBody | null {\n if (body === null) return null;\n const serialized = JSON.stringify(body);\n if (Buffer.byteLength(serialized, \"utf8\") <= JOURNAL_BODY_CAP_BYTES) return body;\n // The marker is not a chat request, and `JournalBody` no longer claims it is\n // — downstream consumers (e.g. GET /journal) treat the body as opaque JSON.\n return {\n __aimock_truncated: true,\n originalByteSize: Buffer.byteLength(serialized, \"utf8\"),\n note: \"body truncated by aimock journal cap (64 KB limit)\",\n };\n}\n\n/**\n * Narrow a journaled body to a chat-completion request.\n *\n * `JournalEntry.body` is a union (see {@link JournalBody}): most entries hold a\n * chat request, but the fine-tuning create payload and this module's own\n * truncation marker do not. Anything reading `messages`, `model` or the rest of\n * the chat shape off a journal entry — inside aimock or in a consumer's test\n * — goes through here, so an entry that is not a chat request fails as a\n * `false` it can assert on rather than as an undefined property three accesses\n * later.\n *\n * `messages` is the discriminator because it is the one required field no\n * other journaled shape carries.\n */\nexport function isChatCompletionBody(\n body: JournalBody | null | undefined,\n): body is ChatCompletionRequest {\n return (\n body !== null &&\n body !== undefined &&\n Array.isArray((body as { messages?: unknown }).messages) &&\n typeof (body as { model?: unknown }).model === \"string\"\n );\n}\n\n/**\n * Compare two field values, handling RegExp by source+flags rather than reference.\n */\nfunction fieldEqual(a: unknown, b: unknown): boolean {\n if (a instanceof RegExp && b instanceof RegExp)\n return a.source === b.source && a.flags === b.flags;\n return a === b;\n}\n\n/**\n * Compare two systemMessage values. Handles string, string[], and RegExp.\n * Both-undefined is treated as equal.\n */\nfunction systemMessageEqual(\n a: string | string[] | RegExp | undefined,\n b: string | string[] | RegExp | undefined,\n): boolean {\n if (a === undefined && b === undefined) return true;\n if (a === undefined || b === undefined) return false;\n if (typeof a === \"string\" && typeof b === \"string\") return a === b;\n if (Array.isArray(a) && Array.isArray(b))\n return a.length === b.length && a.every((v, i) => v === b[i]);\n if (a instanceof RegExp && b instanceof RegExp)\n return a.source === b.source && a.flags === b.flags;\n return false;\n}\n\n/**\n * Check whether two fixture match objects have the same criteria\n * (ignoring sequenceIndex). Used to group sequenced fixtures.\n */\nfunction matchCriteriaEqual(a: FixtureMatch, b: FixtureMatch): boolean {\n return (\n fieldEqual(a.userMessage, b.userMessage) &&\n systemMessageEqual(a.systemMessage, b.systemMessage) &&\n fieldEqual(a.inputText, b.inputText) &&\n isDeepStrictEqual(a.embeddingRequest, b.embeddingRequest) &&\n fieldEqual(a.toolCallId, b.toolCallId) &&\n fieldEqual(a.toolName, b.toolName) &&\n fieldEqual(a.toolNamespace, b.toolNamespace) &&\n fieldEqual(a.model, b.model) &&\n fieldEqual(a.responseFormat, b.responseFormat) &&\n fieldEqual(a.predicate, b.predicate) &&\n fieldEqual(a.endpoint, b.endpoint) &&\n fieldEqual(a.turnIndex, b.turnIndex) &&\n fieldEqual(a.hasToolResult, b.hasToolResult) &&\n fieldEqual(a.toolResultContains, b.toolResultContains) &&\n fieldEqual(a.context, b.context)\n );\n}\n\n/** Count-map keys resolve through `identity`, so every alias of a fixture finds its caller entry. */\nclass FixtureCountMap extends Map<Fixture, number> {\n constructor(private readonly identity: (fixture: Fixture) => Fixture) {\n super();\n }\n\n override get(key: Fixture): number | undefined {\n return super.get(this.identity(key));\n }\n\n override has(key: Fixture): boolean {\n return super.has(this.identity(key));\n }\n\n override set(key: Fixture, value: number): this {\n return super.set(this.identity(key), value);\n }\n\n override delete(key: Fixture): boolean {\n return super.delete(this.identity(key));\n }\n}\n\nexport interface JournalOptions {\n /**\n * Maximum number of entries to retain. When exceeded, oldest entries are\n * dropped FIFO. Set to 0 (or omit) for unbounded retention (the historical\n * default — suitable for short-lived test runs only). Negative values are\n * rejected at the CLI parse layer; programmatically they are treated as 0\n * (unbounded) for back-compat.\n *\n * Long-running servers (e.g. mock proxies in CI/demo environments) should\n * always set a finite cap: every request appends an entry holding the\n * request body + headers + fixture reference, and without a cap the\n * journal grows until the process OOMs.\n */\n maxEntries?: number;\n /**\n * Maximum number of unique testIds retained across fixture match-count\n * and misbehavior counters. When exceeded, the oldest testId\n * (by first-insertion order) is evicted FIFO. Set to 0 (or omit) for\n * unbounded retention. Negative values are rejected at the CLI parse\n * layer; programmatically they are treated as 0 (unbounded) for\n * back-compat. Without a cap this map can grow over time in long-running\n * servers that see many unique testIds.\n */\n fixtureCountsMaxTestIds?: number;\n /**\n * Called with every entry {@link Journal.add} creates, right after it is\n * recorded. The hook exists so an embedder can attribute an entry to the\n * request that produced it WITHOUT touching each of the ~100 `journal.add`\n * call sites spread across the handler modules: the server binds the entry\n * to the in-flight `IncomingMessage` here, and its error arm then amends\n * that exact object rather than guessing from a caller-supplied header.\n *\n * The entry is already recorded when the hook runs, so a hook that throws\n * does not lose the write — but it does propagate out of `add` into the\n * caller's error path, so a hook must not throw.\n */\n onAdd?: (entry: JournalEntry) => void;\n}\n\nexport class Journal implements MisbehaviorCounters {\n private entries: JournalEntry[] = [];\n private readonly matchedFixtures = new WeakMap<JournalEntry, Fixture>();\n /** The fixture a request was served from, where the entry names its caller fixture instead. */\n private readonly servedFixtures = new WeakMap<JournalEntry, Fixture>();\n private readonly fixtureMatchCountsByTestId: Map<string, Map<Fixture, number>> = new Map();\n /** An extended server's view of a fixture to the caller's fixture (configureFixtureViewSource). */\n private fixtureViewSource = (fixture: Fixture): Fixture => fixture;\n private fixtureCountIdentity = (fixture: Fixture): Fixture => fixture;\n /** The key a fixture is counted under: the caller's object behind any view or copy. */\n private readonly fixtureCountKey = (fixture: Fixture): Fixture =>\n this.fixtureCountIdentity(this.fixtureViewSource(fixture));\n private createFixtureCountMap = (): Map<Fixture, number> => new Map();\n private fixtureCountIdentityConfigured = false;\n private fixtureViewSourceConfigured = false;\n private readonly counterTestIds = new Set<string>();\n private readonly misbehaviorCountersByTestId = new Map<\n string,\n Map<string, Map<number, { ordinal: number; firings: number }>>\n >();\n private readonly maxEntries: number;\n private readonly fixtureCountsMaxTestIds: number;\n private readonly onAdd?: (entry: JournalEntry) => void;\n\n constructor(options: JournalOptions = {}) {\n this.onAdd = options.onAdd;\n // Treat 0 or negative as \"unbounded\" to preserve prior behavior when\n // the option is omitted or explicitly disabled.\n const cap = options.maxEntries;\n this.maxEntries = cap !== undefined && cap > 0 ? cap : 0;\n const testIdCap = options.fixtureCountsMaxTestIds;\n this.fixtureCountsMaxTestIds = testIdCap !== undefined && testIdCap > 0 ? testIdCap : 0;\n }\n\n /**\n * The per-test-id cap on fixture match-count maps, for an MCP mount to pass\n * to `McpFakeStore.setMaxTestIds`. Always a non-negative safe integer, `0`\n * meaning unbounded, and never throws, whatever option was passed:\n * omitted, zero, negative or `NaN` is `0`; `Infinity` or a value above\n * `Number.MAX_SAFE_INTEGER` (never reached) is `0`; a fraction of 1 or more\n * is rounded down (`1.5` evicts at 2 ids, so it keeps 1). For these values\n * it is the number of test ids the journal keeps.\n *\n * An option between 0 and 1 is the exception. The journal keeps no test id\n * (each new count map is evicted as soon as it is made, so counts never\n * advance), and a store cap cannot say \"keep none\" because `0` is\n * unbounded. The getter returns `1`, the smallest bounded cap, so a store\n * given it keeps 1 test id where the journal keeps 0.\n */\n get fixtureCountsMaxTestIdsCap(): number {\n const cap = this.fixtureCountsMaxTestIds;\n if (!(cap > 0) || cap > Number.MAX_SAFE_INTEGER) return 0;\n return Math.max(1, Math.floor(cap));\n }\n\n /** Backwards-compatible accessor — returns the default (no testId) count map. */\n get fixtureMatchCounts(): Map<Fixture, number> {\n return this.getFixtureMatchCountsForTest(DEFAULT_TEST_ID);\n }\n\n /** @internal matchedFixture preserves identity when Live supplies safe diagnostics. */\n add(entry: Omit<JournalEntry, \"id\" | \"timestamp\">, matchedFixture?: Fixture): JournalEntry {\n const full: JournalEntry = {\n id: generateId(\"req\"),\n timestamp: Date.now(),\n ...entry,\n body: capBody(entry.body),\n };\n // A request is served from an extended server's view of a fixture, or\n // from LLMock's per-addition copy with misbehavior enabled; the entry\n // names the caller's fixture behind it, as in 1.44.0.\n const fixture = full.response.fixture;\n const source = fixture ? this.fixtureCountKey(fixture) : fixture;\n if (fixture && source !== fixture) {\n full.response = { ...full.response, fixture: source };\n this.servedFixtures.set(full, fixture);\n }\n if (matchedFixture) this.matchedFixtures.set(full, this.fixtureCountKey(matchedFixture));\n this.entries.push(full);\n // FIFO eviction when over capacity. Array.prototype.shift() is O(n)\n // regardless of how many we drop per add; we accept it at small caps\n // (default 1000) because the constant factor is tiny and this runs once\n // per request. For much larger caps, switch to a ring buffer for true\n // O(1) eviction.\n if (this.maxEntries > 0 && this.entries.length > this.maxEntries) {\n this.entries.shift();\n }\n this.onAdd?.(full);\n return full;\n }\n\n /**\n * Return every entry, or with `limit` the most recent `limit` entries.\n * `0` returns `[]` — exactly what `GET /__aimock/journal?limit=0` answers.\n * `slice(-0)` is `slice(0)`, so a `0` used to return the ENTIRE journal; it\n * is special-cased so the library and the HTTP route agree. This is a public\n * library API, so odd limits are tolerated rather than thrown on: a\n * non-finite limit (`NaN`, `Infinity`) means \"no limit\", a fractional limit\n * floors, and any limit at or below `0` asks for nothing.\n */\n getAll(opts?: { limit?: number }): JournalEntry[] {\n if (opts?.limit !== undefined && Number.isFinite(opts.limit)) {\n const limit = Math.floor(opts.limit);\n if (limit <= 0) return [];\n return this.entries.slice(-limit);\n }\n return this.entries.slice();\n }\n\n getLast(): JournalEntry | null {\n return this.entries.length > 0 ? this.entries[this.entries.length - 1] : null;\n }\n\n findByFixture(fixture: Fixture): JournalEntry[] {\n const key = this.fixtureCountKey(fixture);\n return this.entries.filter((e) => (this.matchedFixtures.get(e) ?? e.response.fixture) === key);\n }\n\n /**\n * @internal The fixture `entry`'s request was served from: the extended\n * view or the per-addition copy when the entry names the caller's fixture\n * behind it, otherwise `entry.response.fixture`. The journal JSON shows it.\n */\n servedFixture(entry: JournalEntry): Fixture | null {\n return this.servedFixtures.get(entry) ?? entry.response.fixture;\n }\n\n /**\n * READ-ONLY accessor. Returns the existing count map for `testId`, or an\n * empty transient Map if none exists. Does NOT insert into the cache and\n * does NOT trigger FIFO eviction — callers may read freely without\n * perturbing cache state. For the write path, see\n * `getOrCreateFixtureMatchCountsForTest`.\n */\n getFixtureMatchCountsForTest(testId: string): Map<Fixture, number> {\n return this.fixtureMatchCountsByTestId.get(testId) ?? this.createFixtureCountMap();\n }\n\n /**\n * WRITE path: get the count map for `testId`, inserting a fresh empty Map\n * if missing and running FIFO eviction when the testId cap is exceeded.\n * Only callers that intend to mutate the map (e.g. incrementing a count)\n * should use this.\n */\n private getOrCreateFixtureMatchCountsForTest(testId: string): Map<Fixture, number> {\n let counts = this.fixtureMatchCountsByTestId.get(testId);\n if (!counts) {\n counts = this.createFixtureCountMap();\n this.fixtureMatchCountsByTestId.set(testId, counts);\n this.admitCounterTestId(testId);\n }\n return counts;\n }\n\n /** Match and fault mutations share one admission order and capacity. */\n private admitCounterTestId(testId: string): void {\n this.counterTestIds.add(testId);\n if (\n this.fixtureCountsMaxTestIds > 0 &&\n this.counterTestIds.size > this.fixtureCountsMaxTestIds\n ) {\n const oldest = this.counterTestIds.values().next().value;\n if (oldest !== undefined) {\n this.counterTestIds.delete(oldest);\n this.fixtureMatchCountsByTestId.delete(oldest);\n this.misbehaviorCountersByTestId.delete(oldest);\n }\n }\n }\n\n private getOrCreateMisbehaviorCounter(key: MisbehaviorCounterKey) {\n let sources = this.misbehaviorCountersByTestId.get(key.testId);\n if (!sources) {\n sources = new Map();\n this.misbehaviorCountersByTestId.set(key.testId, sources);\n this.admitCounterTestId(key.testId);\n }\n let entries = sources.get(key.sourceKey);\n if (!entries) {\n entries = new Map();\n sources.set(key.sourceKey, entries);\n }\n let counter = entries.get(key.entryIndex);\n if (!counter) {\n counter = { ordinal: 0, firings: 0 };\n entries.set(key.entryIndex, counter);\n }\n return counter;\n }\n\n getFiringCount(key: MisbehaviorCounterKey): number {\n return (\n this.misbehaviorCountersByTestId.get(key.testId)?.get(key.sourceKey)?.get(key.entryIndex)\n ?.firings ?? 0\n );\n }\n\n nextOrdinal(key: MisbehaviorCounterKey): number {\n return this.getOrCreateMisbehaviorCounter(key).ordinal++;\n }\n\n recordFiring(key: MisbehaviorCounterKey): void {\n this.getOrCreateMisbehaviorCounter(key).firings++;\n }\n\n clearMisbehaviorCounters(testId?: string): void {\n if (testId !== undefined) {\n this.misbehaviorCountersByTestId.delete(testId);\n if (!this.fixtureMatchCountsByTestId.has(testId)) this.counterTestIds.delete(testId);\n } else {\n this.misbehaviorCountersByTestId.clear();\n for (const id of this.counterTestIds) {\n if (!this.fixtureMatchCountsByTestId.has(id)) this.counterTestIds.delete(id);\n }\n }\n }\n\n /** @internal LLMock configures caller count identity before serving requests. */\n configureFixtureCountIdentity(identity: (fixture: Fixture) => Fixture): void {\n if (this.fixtureCountIdentityConfigured || this.fixtureMatchCountsByTestId.size > 0) {\n throw new Error(\"Fixture count identity must be configured once before counting\");\n }\n this.fixtureCountIdentity = identity;\n this.createFixtureCountMap = () => new FixtureCountMap(this.fixtureCountKey);\n this.fixtureCountIdentityConfigured = true;\n }\n\n /**\n * @internal A server with `responsesTools: \"extended\"` matches each fixture\n * through its extended view. `source` maps a view back to the caller's\n * fixture, so counts, `findByFixture` and `JournalEntry.response.fixture`\n * keep the caller's object. Configured once, before counting.\n */\n configureFixtureViewSource(source: (fixture: Fixture) => Fixture): void {\n if (this.fixtureViewSourceConfigured || this.fixtureMatchCountsByTestId.size > 0) {\n throw new Error(\"Fixture view source must be configured once before counting\");\n }\n this.fixtureViewSource = source;\n this.createFixtureCountMap = () => new FixtureCountMap(this.fixtureCountKey);\n this.fixtureViewSourceConfigured = true;\n }\n\n getFixtureMatchCount(fixture: Fixture, testId = DEFAULT_TEST_ID): number {\n return this.getFixtureMatchCountsForTest(testId).get(fixture) ?? 0;\n }\n\n incrementFixtureMatchCount(\n fixture: Fixture,\n allFixtures?: readonly Fixture[],\n testId = DEFAULT_TEST_ID,\n ): void {\n const counts = this.getOrCreateFixtureMatchCountsForTest(testId);\n counts.set(fixture, (counts.get(fixture) ?? 0) + 1);\n // When a sequenced fixture matches, also increment all siblings with matching criteria\n if (fixture.match.sequenceIndex !== undefined && allFixtures) {\n for (const sibling of allFixtures) {\n if (this.fixtureCountKey(sibling) === this.fixtureCountKey(fixture)) continue;\n if (sibling.match.sequenceIndex === undefined) continue;\n if (matchCriteriaEqual(fixture.match, sibling.match)) {\n counts.set(sibling, (counts.get(sibling) ?? 0) + 1);\n }\n }\n }\n }\n\n clearMatchCounts(testId?: string): void {\n if (testId !== undefined) {\n this.fixtureMatchCountsByTestId.delete(testId);\n this.clearMisbehaviorCounters(testId);\n } else {\n this.fixtureMatchCountsByTestId.clear();\n this.clearMisbehaviorCounters();\n }\n }\n\n /**\n * Clear ONLY the request journal entries, preserving fixture match-counts.\n * Match-counts are fixture-matching/sequencing state, not journal data, so\n * clearing the journal must not silently rewind sequenced fixtures. Used by\n * `POST /__aimock/reset/journal`. For a full reset (entries + match-counts),\n * use `clear()` instead.\n */\n clearEntries(): void {\n this.entries = [];\n }\n\n clear(): void {\n this.entries = [];\n this.clearMatchCounts();\n }\n\n get size(): number {\n return this.entries.length;\n }\n}\n"],"mappings":"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"}
|
package/dist/llmock.cjs
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
const require_constants = require('./constants.cjs');
|
|
2
2
|
const require_message_text = require('./message-text.cjs');
|
|
3
|
+
const require_policy = require('./response/policy.cjs');
|
|
3
4
|
const require_helpers = require('./helpers.cjs');
|
|
4
5
|
const require_live_fixture = require('./live-fixture.cjs');
|
|
5
6
|
const require_misbehavior = require('./misbehavior.cjs');
|
|
6
7
|
const require_fixture_loader = require('./fixture-loader.cjs');
|
|
8
|
+
const require_logger = require('./logger.cjs');
|
|
7
9
|
const require_fal = require('./fal.cjs');
|
|
8
10
|
const require_elevenlabs_voice = require('./elevenlabs-voice.cjs');
|
|
9
11
|
const require_mcp_mock = require('./mcp-mock.cjs');
|
|
@@ -34,6 +36,7 @@ var LLMock = class LLMock {
|
|
|
34
36
|
constructor(options, resolvedInboundAuth) {
|
|
35
37
|
require_helpers.markServerOwnedFixtures(this.fixtures);
|
|
36
38
|
this.options = options ?? {};
|
|
39
|
+
require_policy.parsePolicy(this.options.policy, (message) => new require_logger.Logger("warn").warn(message));
|
|
37
40
|
if (this.options.live !== void 0) require_live_fixture.normalizeLiveOptions(this.options.live);
|
|
38
41
|
if (this.misbehaviorEnabled && this.options.misbehavior !== void 0) this.setMisbehavior(this.options.misbehavior);
|
|
39
42
|
this.resolvedInboundAuth = resolvedInboundAuth;
|
package/dist/llmock.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llmock.cjs","names":["getFixtureMisbehaviorPosition","parseMisbehavior","validateFixtureMisbehavior","MisbehaviorConfigError","isLiveResponse","normalizeLiveFixture","loadFixtureFileWithServices","loadFixturesFromDirWithServices","enableHeldFixtureMisbehavior","markFixtureResponsesToolsExtended","planFileFakes","ensureFakeMount","entryToFixture","validateFixtures","normalizeResponse","voiceDesignToJson","imageResponseToFalJson","videoResponseToFalJson","isInjectableStatus","INJECTED_STATUS_RANGE","isAutoMount","MCPMock","build","quote","resolveMisbehaviorSeed","DEFAULT_TEST_ID","createServerWithResolvedAuth","createServer"],"sources":["../src/llmock.ts"],"sourcesContent":["import type { LiveTranscript } from \"./live-types.js\";\nimport { normalizeLiveFixture, normalizeLiveOptions } from \"./live-fixture.js\";\nimport { isLiveResponse, markServerOwnedFixtures } from \"./helpers.js\";\nimport type {\n AudioResponse,\n ChaosConfig,\n EmbeddingFixtureOpts,\n FalQueueOpts,\n Fixture,\n FixtureFileEntry,\n FixtureFileResponse,\n FixtureMatch,\n FixtureOpts,\n FixtureResponse,\n ImageResponse,\n McpFakeSource,\n MockServerOptions,\n MisbehaviorConfig,\n MisbehaviorFaultId,\n Mountable,\n RecordConfig,\n ResponseFactory,\n TranscriptionResponse,\n VideoResponse,\n VoiceDesignResponse,\n} from \"./types.js\";\nimport {\n createServer,\n createServerWithResolvedAuth,\n performFullReset,\n type ServerInstance,\n} from \"./server.js\";\nimport type { ResolvedInboundAuth } from \"./api-key-auth.js\";\nimport {\n isInjectableStatus,\n INJECTED_STATUS_RANGE,\n queueOneShotError,\n clearFixtureQueue,\n entryToFixture,\n normalizeResponse,\n normalizeResponsesToolsKeys,\n validateFixtures,\n enableHeldFixtureMisbehavior,\n markFixtureResponsesToolsExtended,\n markFixtureMisbehaviorEnabled,\n MisbehaviorConfigError,\n} from \"./fixture-loader.js\";\nimport {\n loadFixtureFileWithServices,\n loadFixturesFromDirWithServices,\n type FixturesWithServices,\n} from \"./fixture-loader-services.js\";\nimport { ensureFakeMount, isAutoMount, planFileFakes } from \"./mcp-fakes-mount.js\";\nimport { MCPMock } from \"./mcp-mock.js\";\nimport { build, msg, quote } from \"./message-text.js\";\nimport { DEFAULT_TEST_ID } from \"./constants.js\";\nimport { Journal } from \"./journal.js\";\nimport type { SearchFixture, SearchResult } from \"./search.js\";\nimport type { RerankFixture, RerankResult } from \"./rerank.js\";\nimport type { ModerationFixture, ModerationResult } from \"./moderation.js\";\nimport { imageResponseToFalJson, videoResponseToFalJson } from \"./fal.js\";\nimport { voiceDesignToJson } from \"./elevenlabs-voice.js\";\n\nimport {\n getFixtureMisbehaviorPosition,\n parseMisbehavior,\n resolveMisbehaviorSeed,\n setFixtureMisbehaviorPosition,\n validateFixtureMisbehavior,\n} from \"./misbehavior.js\";\n\nexport class LLMock {\n private fixtures: Fixture[] = [];\n private fixtureAddition = 0;\n private readonly fixtureCountOrigins = new WeakMap<Fixture, Fixture>();\n /**\n * Fixtures this LLMock built itself (on() and the other helpers), so the\n * caller never held them: the stored object is their identity.\n */\n private readonly ownFixtures = new WeakSet<Fixture>();\n private searchFixtures: SearchFixture[] = [];\n private rerankFixtures: RerankFixture[] = [];\n private moderationFixtures: ModerationFixture[] = [];\n private mounts: Array<{ path: string; handler: Mountable }> = [];\n /** `mcpFakes` blocks loaded before `start()`, handed to the server at start (W2). */\n private mcpFakeBuffer: McpFakeSource[] = [];\n /** MCPMocks the server or a load auto-mounted (W3, W6), for the L6 check. */\n private serverInstance: ServerInstance | null = null;\n private options: MockServerOptions;\n private readonly resolvedInboundAuth?: ResolvedInboundAuth;\n\n constructor(options?: MockServerOptions, resolvedInboundAuth?: ResolvedInboundAuth) {\n // Only this LLMock's server reads its array, so fixtures it makes may be marked in place.\n markServerOwnedFixtures(this.fixtures);\n this.options = options ?? {};\n if (this.options.live !== undefined) normalizeLiveOptions(this.options.live);\n // The `misbehavior` option is read only with `enableMisbehavior: true`;\n // otherwise it is unused data, as in 1.44.0.\n if (this.misbehaviorEnabled && this.options.misbehavior !== undefined) {\n this.setMisbehavior(this.options.misbehavior);\n }\n this.resolvedInboundAuth = resolvedInboundAuth;\n }\n\n /** Misbehavior (fixture keys, header, `misbehavior` option) needs `enableMisbehavior: true`. */\n private get misbehaviorEnabled(): boolean {\n return this.options.enableMisbehavior === true;\n }\n\n // ---- Fixture management ----\n\n private normalizeFixture(fixture: Fixture): Fixture {\n const misbehaviorEnabled = this.misbehaviorEnabled;\n // A fixture loaded from a file holds its `misbehavior` key until enabled.\n if (misbehaviorEnabled) enableHeldFixtureMisbehavior(fixture);\n // A fixture this LLMock built (on() and the helpers) is new to it, so it\n // needs no per-addition copy, and the object stored is its identity.\n const own = this.ownFixtures.delete(fixture);\n const countIdentity = own ? undefined : (this.fixtureCountOrigins.get(fixture) ?? fixture);\n const previousPosition = getFixtureMisbehaviorPosition(fixture);\n const isNewAddition = previousPosition === undefined || /^code#\\d+$/.test(previousPosition);\n const position = isNewAddition ? `code#${this.fixtureAddition++}` : previousPosition;\n // With misbehavior enabled, re-adding a code fixture creates a new fault\n // source without changing the old entry, so each addition is its own copy.\n // The journal counts and records every copy under the caller's object\n // (fixtureCountOrigins), so the identity APIs read as they do without\n // misbehavior: an object added twice is one caller fixture, as in 1.44.0.\n // Without misbehavior the position is never read, and the caller's object\n // is stored as in 1.44.0.\n if (isNewAddition && misbehaviorEnabled && !own) fixture = { ...fixture };\n if (misbehaviorEnabled && fixture.misbehavior !== undefined) {\n const parsed = parseMisbehavior(fixture.misbehavior);\n if (parsed.ok) fixture = { ...fixture, misbehavior: parsed.config };\n const issue = parsed.ok ? validateFixtureMisbehavior(fixture) : parsed.issue;\n if (issue) {\n throw new MisbehaviorConfigError({\n rule: issue.rule,\n file: position,\n detail: issue.message,\n });\n }\n }\n\n if (\n isLiveResponse(fixture.response) ||\n (fixture.match.endpoint === \"openai-live\" && typeof fixture.response !== \"function\")\n ) {\n fixture = {\n ...fixture,\n match: { ...fixture.match },\n response: normalizeLiveFixture(fixture.response, this.options.live),\n };\n } else if (countIdentity !== undefined && fixture !== countIdentity) {\n this.fixtureCountOrigins.set(fixture, countIdentity);\n }\n setFixtureMisbehaviorPosition(fixture, position);\n if (misbehaviorEnabled && fixture.misbehavior !== undefined) {\n markFixtureMisbehaviorEnabled(fixture);\n }\n // A fixture passed in is not marked for responsesTools \"extended\": the\n // server reads it through its extended view, so the caller's object (which\n // another server may share) is left as it was loaded.\n return fixture;\n }\n\n addFixture(fixture: Fixture): this {\n this.fixtures.push(this.normalizeFixture(fixture));\n return this;\n }\n\n addFixtures(fixtures: Fixture[]): this {\n this.fixtures.push(...fixtures.map((fixture) => this.normalizeFixture(fixture)));\n return this;\n }\n\n prependFixture(fixture: Fixture): this {\n this.fixtures.unshift(this.normalizeFixture(fixture));\n return this;\n }\n\n /** Mark a fixture this LLMock built, for {@link normalizeFixture}. */\n private own(fixture: Fixture): Fixture {\n this.ownFixtures.add(fixture);\n return fixture;\n }\n\n getFixtures(): readonly Fixture[] {\n return this.fixtures;\n }\n\n /**\n * Load a fixture file: its LLM fixtures and its `mcpFakes` blocks (F4).\n * Before `start()` the blocks are buffered and handed to the server at\n * start (W2); after it they go to the MCPMock serving each block's `mount`\n * path, auto-mounted when none does (W6). A block that cannot be honored\n * throws a `FixtureLoadError` and nothing from the file is added.\n */\n loadFixtureFile(filePath: string): this {\n return this.acceptLoaded(loadFixtureFileWithServices(filePath, undefined, this.options.live));\n }\n\n /** As {@link loadFixtureFile}, for every fixture file under `dirPath`. */\n loadFixtureDir(dirPath: string): this {\n return this.acceptLoaded(\n loadFixturesFromDirWithServices(dirPath, undefined, this.options.live),\n );\n }\n\n /**\n * Add a load's fakes (all or nothing), then its LLM fixtures. Before start\n * the fakes are checked as the start-time hand-off will check them, with\n * the blocks already buffered and the mounts added so far, so a file whose\n * fakes would be rejected adds nothing. A mount added after the load can\n * still make `start()` reject.\n */\n private acceptLoaded(loaded: FixturesWithServices): this {\n // With misbehavior enabled, a bad `misbehavior` key throws before anything is added.\n if (this.misbehaviorEnabled) loaded.fixtures.forEach(enableHeldFixtureMisbehavior);\n if (this.options.responsesTools === \"extended\") {\n loaded.fixtures.forEach(markFixtureResponsesToolsExtended);\n }\n if (loaded.mcpFakes.length > 0) {\n if (this.serverInstance) {\n this.addFakesAfterStart(this.serverInstance, loaded.mcpFakes);\n } else {\n planFileFakes(\n this.mounts,\n [...this.mcpFakeBuffer, ...loaded.mcpFakes],\n new Set(loaded.mcpFakes),\n );\n this.mcpFakeBuffer.push(...loaded.mcpFakes);\n }\n }\n this.fixtures.push(...loaded.fixtures);\n return this;\n }\n\n /**\n * W6 for a load after start. Every group of blocks (by `mount` path) is\n * checked before any mount is touched: a path held by a mount that is not\n * an MCPMock is a mount conflict, and each group is first added to a\n * throwaway store. Groups for an existing MCPMock are then added to it (its\n * own add is all or nothing and finds collisions with its loaded ids);\n * groups for a free path are added last, to a new auto-mounted MCPMock,\n * wired as W4. The add warnings (L8) are logged at `warn`.\n */\n private addFakesAfterStart(server: ServerInstance, sources: McpFakeSource[]): void {\n const { onExisting, onNew } = planFileFakes(this.mounts, sources);\n\n const logger = server.defaults.logger;\n for (const { handler, group } of onExisting) {\n const result = handler.addMcpFakes?.(group, { kind: \"file\" });\n for (const warning of result?.warnings ?? []) logger.warn(warning.message);\n }\n const registry = server.defaults.registry;\n for (const { path, group } of onNew) {\n const target = ensureFakeMount(\n this.mounts,\n path,\n {\n journal: server.journal,\n ...(registry ? { registry } : {}),\n logger,\n replaySpeed: server.defaults.replaySpeed,\n },\n logger,\n );\n // The check above found no mount at this path, and nothing ran since.\n if (\"conflict\" in target) continue;\n const result = target.handler.addMcpFakes?.(group, { kind: \"file\" });\n for (const warning of result?.warnings ?? []) logger.warn(warning.message);\n }\n }\n\n /** R4, R5: unload the fakes of every mount and the pre-start buffer. */\n private unloadMcpFakes(): void {\n this.mcpFakeBuffer.length = 0;\n for (const { handler } of this.mounts) handler.clearMcpFakes?.();\n }\n\n /**\n * Add fixtures from a JSON string or pre-parsed array of fixture entries.\n * Validates all fixtures and throws if any have severity \"error\".\n */\n addFixturesFromJSON(input: string | FixtureFileEntry[]): this {\n let entries: FixtureFileEntry[];\n if (typeof input === \"string\") {\n try {\n entries = JSON.parse(input);\n } catch (err) {\n throw new Error(\n `addFixturesFromJSON: invalid JSON — ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n } else {\n entries = input;\n }\n if (!Array.isArray(entries)) {\n throw new TypeError(\n \"addFixturesFromJSON: expected an array of fixture entries; use loadFixtureFile for a {fixtures:[...]} file\",\n );\n }\n const converted = entries.map((entry) => {\n const position = `code#${this.fixtureAddition++}`;\n const fixture = entryToFixture(entry, undefined, this.options.live, {\n file: position,\n index: 0,\n });\n setFixtureMisbehaviorPosition(fixture, position);\n if (this.misbehaviorEnabled) enableHeldFixtureMisbehavior(fixture);\n if (this.options.responsesTools === \"extended\") markFixtureResponsesToolsExtended(fixture);\n return fixture;\n });\n\n const issues = validateFixtures(converted, this.options.live);\n const errors = issues.filter((i) => i.severity === \"error\");\n if (errors.length > 0) {\n throw new Error(`Fixture validation failed: ${JSON.stringify(errors)}`);\n }\n this.fixtures.push(...converted);\n return this;\n }\n\n // Clears in place to preserve array reference identity — the running\n // server reads this same array on every request — and invalidates any\n // one-shot claim parked in flight so it cannot re-arm into the cleared queue.\n clearFixtures(): this {\n clearFixtureQueue(this.fixtures);\n this.serverInstance?.journal.clearMisbehaviorCounters();\n this.unloadMcpFakes();\n return this;\n }\n\n // ---- Convenience ----\n\n on(\n match: FixtureMatch,\n response: FixtureFileResponse | ResponseFactory,\n opts?: FixtureOpts,\n ): this {\n let normalized: FixtureResponse | ResponseFactory = response as ResponseFactory;\n if (typeof response !== \"function\") {\n normalized = normalizeResponse(response, this.options.live);\n // `customToolCalls` / `responsesBlocks` are normalized only where they are\n // read; otherwise they stay as written, as in 1.44.0.\n if (this.options.responsesTools === \"extended\" && !isLiveResponse(normalized)) {\n normalizeResponsesToolsKeys(normalized as unknown as Record<string, unknown>);\n }\n }\n return this.addFixture(this.own({ match, response: normalized, ...opts }));\n }\n\n onLive(\n match: Omit<FixtureMatch, \"endpoint\">,\n transcript: LiveTranscript,\n opts?: FixtureOpts,\n ): this {\n return this.on({ ...match, endpoint: \"openai-live\" }, { live: transcript }, opts);\n }\n\n onMessage(\n pattern: string | RegExp,\n response: FixtureFileResponse | ResponseFactory,\n opts?: FixtureOpts,\n ): this {\n return this.on({ userMessage: pattern }, response, opts);\n }\n\n onEmbedding(\n pattern: string | RegExp,\n response: FixtureFileResponse | ResponseFactory,\n opts?: EmbeddingFixtureOpts,\n ): this {\n return this.on({ inputText: pattern }, response, opts);\n }\n\n onJsonOutput(pattern: string | RegExp, jsonContent: object | string, opts?: FixtureOpts): this {\n const content = typeof jsonContent === \"string\" ? jsonContent : JSON.stringify(jsonContent);\n return this.on({ userMessage: pattern, responseFormat: \"json_object\" }, { content }, opts);\n }\n\n onToolCall(\n name: string,\n response: FixtureFileResponse | ResponseFactory,\n opts?: FixtureOpts,\n ): this {\n return this.on({ toolName: name }, response, opts);\n }\n\n onToolResult(\n id: string,\n response: FixtureFileResponse | ResponseFactory,\n opts?: FixtureOpts,\n ): this {\n return this.on({ toolCallId: id }, response, opts);\n }\n\n onTurn(\n turn: number,\n pattern: string | RegExp,\n response: FixtureFileResponse | ResponseFactory,\n opts?: FixtureOpts,\n ): this {\n return this.on({ userMessage: pattern, turnIndex: turn }, response, opts);\n }\n\n onImage(prompt: string | RegExp, response: ImageResponse): this {\n return this.addFixture(\n this.own({\n match: { userMessage: prompt, endpoint: \"image\" },\n response,\n }),\n );\n }\n\n onSpeech(input: string | RegExp, response: AudioResponse): this {\n return this.addFixture(\n this.own({\n match: { userMessage: input, endpoint: \"speech\" },\n response,\n }),\n );\n }\n\n onTranscription(response: TranscriptionResponse): this {\n return this.addFixture(\n this.own({\n match: { endpoint: \"transcription\" },\n response,\n }),\n );\n }\n\n onTranslation(response: TranscriptionResponse): this {\n return this.addFixture(\n this.own({\n match: { endpoint: \"translation\" },\n response,\n }),\n );\n }\n\n onVideo(prompt: string | RegExp, response: VideoResponse): this {\n return this.addFixture(\n this.own({\n match: { userMessage: prompt, endpoint: \"video\" },\n response,\n }),\n );\n }\n\n onAudio(input: string | RegExp, response: AudioResponse): this {\n return this.addFixture(this.own({ match: { userMessage: input }, response }));\n }\n\n onSoundEffect(text: string | RegExp, response: AudioResponse): this {\n return this.addFixture(\n this.own({\n match: { userMessage: text, endpoint: \"audio-gen\" },\n response,\n }),\n );\n }\n\n onMusic(prompt: string | RegExp, response: AudioResponse): this {\n return this.addFixture(\n this.own({\n match: { userMessage: prompt, endpoint: \"audio-gen\" },\n response,\n }),\n );\n }\n\n onElevenLabsTTS(text: string | RegExp, response: AudioResponse): this {\n return this.addFixture(\n this.own({\n match: { userMessage: text, endpoint: \"elevenlabs-tts\" },\n response,\n }),\n );\n }\n\n onElevenLabsVoiceDesign(description: string | RegExp, response: VoiceDesignResponse): this {\n return this.addFixture(\n this.own({\n match: { userMessage: description, endpoint: \"elevenlabs-voice-design\" },\n response: voiceDesignToJson(response),\n }),\n );\n }\n\n onFalAudio(prompt: string | RegExp, response: AudioResponse, model?: string): this {\n return this.addFixture(\n this.own({\n match: { userMessage: prompt, endpoint: \"fal-audio\", ...(model ? { model } : {}) },\n response,\n }),\n );\n }\n\n // fal.queue.* is the dominant client API; onFalRun is a sync alias.\n //\n // `opts.billableUnits` rides through to the completed `queue-result`\n // response's `x-fal-billable-units` header (emitted alongside\n // `x-fal-request-id`), letting consumers like `@tanstack/ai-fal` surface a\n // billed-units value on replay. Omit it to preserve the header-less default.\n onFalQueue(modelOrPrompt: string | RegExp, response: unknown, opts?: FalQueueOpts): this {\n const { billableUnits, ...fixtureOpts } = opts ?? {};\n return this.addFixture(\n this.own({\n match: { model: modelOrPrompt, endpoint: \"fal\" },\n response: { json: response, ...(billableUnits != null ? { billableUnits } : {}) },\n ...fixtureOpts,\n }),\n );\n }\n\n onFalRun(modelOrPrompt: string | RegExp, response: unknown, opts?: FalQueueOpts): this {\n return this.onFalQueue(modelOrPrompt, response, opts);\n }\n\n /**\n * Register a fal.ai image fixture. Wraps an `ImageResponse` (the shape used\n * by `onImage` and OpenAI/Azure image fixtures) into fal's image envelope\n * before storing it as a `RawJSONResponse`. Defaults `width`/`height` to\n * 1024 when the fixture's `ImageItem` doesn't carry them.\n */\n onFalImage(modelOrPrompt: string | RegExp, response: ImageResponse, opts?: FalQueueOpts): this {\n return this.onFalQueue(modelOrPrompt, imageResponseToFalJson(response), opts);\n }\n\n /**\n * Register a fal.ai video fixture. Wraps a `VideoResponse` into fal's video\n * envelope (`{ video: { url, content_type, file_name, file_size }, seed }`)\n * before storing it as a `RawJSONResponse`.\n */\n onFalVideo(modelOrPrompt: string | RegExp, response: VideoResponse, opts?: FalQueueOpts): this {\n return this.onFalQueue(modelOrPrompt, videoResponseToFalJson(response), opts);\n }\n\n // ---- Service mock convenience methods ----\n\n onSearch(pattern: string | RegExp, results: SearchResult[]): this {\n this.searchFixtures.push({ match: pattern, results });\n return this;\n }\n\n onRerank(pattern: string | RegExp, results: RerankResult[]): this {\n this.rerankFixtures.push({ match: pattern, results });\n return this;\n }\n\n onModerate(pattern: string | RegExp, result: ModerationResult): this {\n this.moderationFixtures.push({ match: pattern, result });\n return this;\n }\n\n /**\n * Queue a one-shot error that will be returned for the next matching\n * request, then automatically removed. Implemented as an internal fixture\n * inserted at the front of the fixture list; see `queueOneShotError` for\n * the endpoint gate and the served-not-evaluated consumption rule.\n */\n nextRequestError(\n status: number,\n errorBody?: { message?: string; type?: string; code?: string },\n ): this {\n // Same gate as `POST /__aimock/error` and fixture validation — this is the\n // form the docs use, and an unchecked status reaches `res.writeHead` on\n // the next matched request: 99/1000 throw there (the injected error is\n // lost and the caller sees a generic 500), and 1xx hangs the request until\n // the client times out. Throwing HERE names the offending call instead.\n if (!isInjectableStatus(status)) {\n throw new RangeError(\n `nextRequestError: invalid status ${String(status)} — must be ${INJECTED_STATUS_RANGE}`,\n );\n }\n queueOneShotError(this.fixtures, status, errorBody);\n return this;\n }\n\n // ---- Mounts ----\n\n mount(path: string, handler: Mountable): this {\n // W4: an auto-mounted MCPMock at `path` takes its requests first (dispatch\n // takes the first match), so the new mount is shadowed; so is one at\n // `path` plus \"/\", whose root request the auto-mount answers as its own.\n // An auto-mount lets any other sub-path fall through: that is no shadow.\n const shadowedBy = this.serverInstance\n ? this.mounts.find(\n (m) => isAutoMount(m.handler) && (path === m.path || path === m.path + \"/\"),\n )\n : undefined;\n this.mounts.push({ path, handler });\n\n // If server is already running, wire up journal, registry, logger and baseUrl\n // immediately so late mounts behave identically to pre-start mounts.\n if (this.serverInstance) {\n if (handler.setJournal) handler.setJournal(this.serverInstance.journal);\n if (handler.setBaseUrl) handler.setBaseUrl(this.serverInstance.url + path);\n const registry = this.serverInstance.defaults.registry;\n if (registry && handler.setRegistry) handler.setRegistry(registry);\n const logger = this.serverInstance.defaults.logger;\n if (handler.setLogger) handler.setLogger(logger);\n // B11/R12: only aimock's own MCPMock takes the replay speed; a custom\n // Mountable is never called (1.44.0 had no such hook).\n if (handler instanceof MCPMock) {\n handler.setReplaySpeed(this.serverInstance.defaults.replaySpeed);\n }\n if (shadowedBy) {\n logger.warn(\n build(\n msg`MCP fakes: the mount at ${quote(path)} is shadowed by the MCP mock auto-mounted at ${quote(shadowedBy.path)}; its requests reach the auto-mount`,\n ),\n );\n }\n }\n\n return this;\n }\n\n // ---- Journal proxies ----\n\n getRequests(): import(\"./types.js\").JournalEntry[] {\n return this.journal.getAll();\n }\n\n getLastRequest(): import(\"./types.js\").JournalEntry | null {\n return this.journal.getLast();\n }\n\n /**\n * Clear the request journal. Fixture match-counts (sequencing state) are\n * left intact — use `resetMatchCounts()` for those.\n */\n clearRequests(): void {\n this.journal.clearEntries();\n }\n\n /**\n * Reset fixture match counts, and the MCP fakes consumption state of every\n * mount (R6), for `testId` or for all test ids. Fakes stay loaded.\n */\n resetMatchCounts(testId?: string): this {\n if (this.serverInstance) {\n this.serverInstance.journal.clearMatchCounts(testId);\n }\n for (const { handler } of this.mounts) handler.resetScenarioState?.(testId);\n return this;\n }\n\n // ---- Chaos ----\n\n /**\n * Set the server-wide chaos baseline. Writes through to a RUNNING server as\n * well as the construction options: an untagged `POST /__aimock/chaos`\n * installs a baseline override that shadows `options.chaos`, and without this\n * the call would silently do nothing until the next `reset()`. Per-testId\n * overrides still win over the baseline.\n */\n setChaos(config: ChaosConfig): this {\n this.options.chaos = config;\n if (this.serverInstance) this.serverInstance.defaults.chaos = config;\n return this;\n }\n\n /**\n * Turn chaos off everywhere: the construction config, the runtime baseline,\n * and every per-testId override (assigning `undefined` is the full-clear\n * signal the `defaults.chaos` setter defines).\n */\n clearChaos(): this {\n delete this.options.chaos;\n if (this.serverInstance) this.serverInstance.defaults.chaos = undefined;\n return this;\n }\n\n // ---- Semantic misbehavior ----\n\n /** Replace construction/runtime baselines without changing named test overrides. */\n setMisbehavior(config: MisbehaviorConfig | MisbehaviorFaultId): this {\n if (!this.misbehaviorEnabled) {\n throw new TypeError(\n \"setMisbehavior: misbehavior is not enabled; construct with enableMisbehavior: true\",\n );\n }\n const parsed = parseMisbehavior(config);\n if (!parsed.ok) throw new TypeError(`${parsed.issue.rule}: ${parsed.issue.message}`);\n this.options.misbehavior = parsed.config;\n const defaults = this.serverInstance?.defaults;\n if (defaults?.misbehavior) {\n defaults.misbehavior.baseline =\n parsed.config.seed === \"random\"\n ? { ...parsed.config, seed: resolveMisbehaviorSeed(parsed.config.seed, defaults.logger) }\n : parsed.config;\n if (defaults.misbehavior.byTestId.has(DEFAULT_TEST_ID)) {\n defaults.misbehavior.byTestId.set(DEFAULT_TEST_ID, defaults.misbehavior.baseline);\n }\n }\n return this;\n }\n\n /** Clear the baseline and all runtime overrides, before or after start. */\n clearMisbehavior(): this {\n delete this.options.misbehavior;\n const scope = this.serverInstance?.defaults.misbehavior;\n if (scope) {\n scope.baseline = undefined;\n scope.byTestId.clear();\n }\n return this;\n }\n\n // ---- Recording ----\n\n enableRecording(config: RecordConfig): this {\n this.options.record = config;\n return this;\n }\n\n disableRecording(): this {\n delete this.options.record;\n return this;\n }\n\n // ---- Reset ----\n\n /**\n * Full reset — the in-process equivalent of `POST /__aimock/reset`. Shares\n * one implementation with the control-API route so the two cannot drift.\n *\n * The one deliberate difference: search / rerank / moderation fixtures are\n * also cleared here. Those are registered through this class only — the\n * control API has no route that creates them, so the HTTP reset can neither\n * reach nor observe them.\n *\n * NOT ALL OF THIS IS PER-INSTANCE. `performFullReset` clears module-global\n * state as well: the Gemini interaction and event-id counters\n * (`resetInteractionCounter` / `resetEventIdCounter` in\n * `./gemini-interactions.js`), the fal.ai job/queue maps (`falJobs`,\n * `falQueueStates`), the fine-tuning job store (`clearFineTuningStore`),\n * and the ElevenLabs Voice Design store (`clearElevenLabsVoices`). With two\n * `LLMock` instances live in one process,\n * `a.reset()` rewinds the Gemini id sequence that `b` is mid-way through —\n * `b` then re-emits `aimock-int-0` / `evt_1`, ids it has already handed\n * out — and drops `b`'s in-flight fal jobs. Give each instance its own\n * process (or its own vitest worker) if that matters.\n *\n * The global stores are cleared even before `start()`, when there is no\n * server instance to reset.\n */\n reset(): this {\n this.searchFixtures.length = 0;\n this.rerankFixtures.length = 0;\n this.moderationFixtures.length = 0;\n // `ServerInstance` carries no mounts, so the fakes are unloaded here (R4).\n this.unloadMcpFakes();\n performFullReset(this.fixtures, this.serverInstance);\n return this;\n }\n\n // ---- Server lifecycle ----\n\n async start(): Promise<string> {\n if (this.serverInstance) {\n throw new Error(\"Server already started\");\n }\n const serviceFixtures = {\n search: this.searchFixtures,\n rerank: this.rerankFixtures,\n moderation: this.moderationFixtures,\n mcpFakes: [...this.mcpFakeBuffer],\n };\n this.serverInstance = await (this.resolvedInboundAuth\n ? createServerWithResolvedAuth(\n this.fixtures,\n this.options,\n this.resolvedInboundAuth,\n this.mounts,\n serviceFixtures,\n )\n : createServer(this.fixtures, this.options, this.mounts, serviceFixtures));\n const countIdentity = (fixture: Fixture) => this.fixtureCountOrigins.get(fixture) ?? fixture;\n this.serverInstance.journal.configureFixtureCountIdentity(countIdentity);\n // The server holds the buffered fakes now (W2). A start that rejects took\n // its hand-off back, so the buffer is kept for a retry.\n this.mcpFakeBuffer.length = 0;\n return this.serverInstance.url;\n }\n\n closeLiveSessions(testId?: string): this {\n this.serverInstance?.closeLiveSessions(testId);\n return this;\n }\n\n async stop(): Promise<void> {\n if (!this.serverInstance) {\n throw new Error(\"Server not started\");\n }\n const { server } = this.serverInstance;\n await new Promise<void>((resolve, reject) => {\n server.close((err: Error | undefined) => (err ? reject(err) : resolve()));\n });\n this.serverInstance = null;\n }\n\n // ---- Accessors ----\n\n get journal(): Journal {\n if (!this.serverInstance) {\n throw new Error(\"Server not started\");\n }\n return this.serverInstance.journal;\n }\n\n get url(): string {\n if (!this.serverInstance) {\n throw new Error(\"Server not started\");\n }\n return this.serverInstance.url;\n }\n\n get baseUrl(): string {\n return this.url;\n }\n\n get port(): number {\n const parsed = new URL(this.url); // this.url throws if not started\n if (!parsed.port) {\n throw new Error(`Server URL has no explicit port: ${this.url}`);\n }\n return parseInt(parsed.port, 10);\n }\n\n // ---- Static factory ----\n\n static async create(options?: MockServerOptions): Promise<LLMock> {\n const instance = new LLMock(options);\n await instance.start();\n return instance;\n }\n}\n\n/** @internal Configuration startup preserves a policy resolved from the selected source. */\nexport function createLLMockWithResolvedAuth(\n options: MockServerOptions,\n resolvedAuth: ResolvedInboundAuth,\n): LLMock {\n return new LLMock(options, resolvedAuth);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"llmock.cjs","names":["Logger","getFixtureMisbehaviorPosition","parseMisbehavior","validateFixtureMisbehavior","MisbehaviorConfigError","isLiveResponse","normalizeLiveFixture","loadFixtureFileWithServices","loadFixturesFromDirWithServices","enableHeldFixtureMisbehavior","markFixtureResponsesToolsExtended","planFileFakes","ensureFakeMount","entryToFixture","validateFixtures","normalizeResponse","voiceDesignToJson","imageResponseToFalJson","videoResponseToFalJson","isInjectableStatus","INJECTED_STATUS_RANGE","isAutoMount","MCPMock","build","quote","resolveMisbehaviorSeed","DEFAULT_TEST_ID","createServerWithResolvedAuth","createServer"],"sources":["../src/llmock.ts"],"sourcesContent":["import type { LiveTranscript } from \"./live-types.js\";\nimport { normalizeLiveFixture, normalizeLiveOptions } from \"./live-fixture.js\";\nimport { isLiveResponse, markServerOwnedFixtures } from \"./helpers.js\";\nimport type {\n AudioResponse,\n ChaosConfig,\n EmbeddingFixtureOpts,\n FalQueueOpts,\n Fixture,\n FixtureFileEntry,\n FixtureFileResponse,\n FixtureMatch,\n FixtureOpts,\n FixtureResponse,\n ImageResponse,\n McpFakeSource,\n MockServerOptions,\n MisbehaviorConfig,\n MisbehaviorFaultId,\n Mountable,\n RecordConfig,\n ResponseFactory,\n TranscriptionResponse,\n VideoResponse,\n VoiceDesignResponse,\n} from \"./types.js\";\nimport {\n createServer,\n createServerWithResolvedAuth,\n performFullReset,\n type ServerInstance,\n} from \"./server.js\";\nimport type { ResolvedInboundAuth } from \"./api-key-auth.js\";\nimport {\n isInjectableStatus,\n INJECTED_STATUS_RANGE,\n queueOneShotError,\n clearFixtureQueue,\n entryToFixture,\n normalizeResponse,\n normalizeResponsesToolsKeys,\n validateFixtures,\n enableHeldFixtureMisbehavior,\n markFixtureResponsesToolsExtended,\n markFixtureMisbehaviorEnabled,\n MisbehaviorConfigError,\n} from \"./fixture-loader.js\";\nimport {\n loadFixtureFileWithServices,\n loadFixturesFromDirWithServices,\n type FixturesWithServices,\n} from \"./fixture-loader-services.js\";\nimport { ensureFakeMount, isAutoMount, planFileFakes } from \"./mcp-fakes-mount.js\";\nimport { MCPMock } from \"./mcp-mock.js\";\nimport { build, msg, quote } from \"./message-text.js\";\nimport { DEFAULT_TEST_ID } from \"./constants.js\";\nimport { Journal } from \"./journal.js\";\nimport type { SearchFixture, SearchResult } from \"./search.js\";\nimport type { RerankFixture, RerankResult } from \"./rerank.js\";\nimport type { ModerationFixture, ModerationResult } from \"./moderation.js\";\nimport { imageResponseToFalJson, videoResponseToFalJson } from \"./fal.js\";\nimport { voiceDesignToJson } from \"./elevenlabs-voice.js\";\nimport { Logger } from \"./logger.js\";\nimport { parsePolicy } from \"./response/policy.js\";\n\nimport {\n getFixtureMisbehaviorPosition,\n parseMisbehavior,\n resolveMisbehaviorSeed,\n setFixtureMisbehaviorPosition,\n validateFixtureMisbehavior,\n} from \"./misbehavior.js\";\n\nexport class LLMock {\n private fixtures: Fixture[] = [];\n private fixtureAddition = 0;\n private readonly fixtureCountOrigins = new WeakMap<Fixture, Fixture>();\n /**\n * Fixtures this LLMock built itself (on() and the other helpers), so the\n * caller never held them: the stored object is their identity.\n */\n private readonly ownFixtures = new WeakSet<Fixture>();\n private searchFixtures: SearchFixture[] = [];\n private rerankFixtures: RerankFixture[] = [];\n private moderationFixtures: ModerationFixture[] = [];\n private mounts: Array<{ path: string; handler: Mountable }> = [];\n /** `mcpFakes` blocks loaded before `start()`, handed to the server at start (W2). */\n private mcpFakeBuffer: McpFakeSource[] = [];\n /** MCPMocks the server or a load auto-mounted (W3, W6), for the L6 check. */\n private serverInstance: ServerInstance | null = null;\n private options: MockServerOptions;\n private readonly resolvedInboundAuth?: ResolvedInboundAuth;\n\n constructor(options?: MockServerOptions, resolvedInboundAuth?: ResolvedInboundAuth) {\n // Only this LLMock's server reads its array, so fixtures it makes may be marked in place.\n markServerOwnedFixtures(this.fixtures);\n this.options = options ?? {};\n // Validate this public entry point without copying or changing caller options.\n parsePolicy(this.options.policy, (message) => new Logger(\"warn\").warn(message));\n if (this.options.live !== undefined) normalizeLiveOptions(this.options.live);\n // The `misbehavior` option is read only with `enableMisbehavior: true`;\n // otherwise it is unused data, as in 1.44.0.\n if (this.misbehaviorEnabled && this.options.misbehavior !== undefined) {\n this.setMisbehavior(this.options.misbehavior);\n }\n this.resolvedInboundAuth = resolvedInboundAuth;\n }\n\n /** Misbehavior (fixture keys, header, `misbehavior` option) needs `enableMisbehavior: true`. */\n private get misbehaviorEnabled(): boolean {\n return this.options.enableMisbehavior === true;\n }\n\n // ---- Fixture management ----\n\n private normalizeFixture(fixture: Fixture): Fixture {\n const misbehaviorEnabled = this.misbehaviorEnabled;\n // A fixture loaded from a file holds its `misbehavior` key until enabled.\n if (misbehaviorEnabled) enableHeldFixtureMisbehavior(fixture);\n // A fixture this LLMock built (on() and the helpers) is new to it, so it\n // needs no per-addition copy, and the object stored is its identity.\n const own = this.ownFixtures.delete(fixture);\n const countIdentity = own ? undefined : (this.fixtureCountOrigins.get(fixture) ?? fixture);\n const previousPosition = getFixtureMisbehaviorPosition(fixture);\n const isNewAddition = previousPosition === undefined || /^code#\\d+$/.test(previousPosition);\n const position = isNewAddition ? `code#${this.fixtureAddition++}` : previousPosition;\n // With misbehavior enabled, re-adding a code fixture creates a new fault\n // source without changing the old entry, so each addition is its own copy.\n // The journal counts and records every copy under the caller's object\n // (fixtureCountOrigins), so the identity APIs read as they do without\n // misbehavior: an object added twice is one caller fixture, as in 1.44.0.\n // Without misbehavior the position is never read, and the caller's object\n // is stored as in 1.44.0.\n if (isNewAddition && misbehaviorEnabled && !own) fixture = { ...fixture };\n if (misbehaviorEnabled && fixture.misbehavior !== undefined) {\n const parsed = parseMisbehavior(fixture.misbehavior);\n if (parsed.ok) fixture = { ...fixture, misbehavior: parsed.config };\n const issue = parsed.ok ? validateFixtureMisbehavior(fixture) : parsed.issue;\n if (issue) {\n throw new MisbehaviorConfigError({\n rule: issue.rule,\n file: position,\n detail: issue.message,\n });\n }\n }\n\n if (\n isLiveResponse(fixture.response) ||\n (fixture.match.endpoint === \"openai-live\" && typeof fixture.response !== \"function\")\n ) {\n fixture = {\n ...fixture,\n match: { ...fixture.match },\n response: normalizeLiveFixture(fixture.response, this.options.live),\n };\n } else if (countIdentity !== undefined && fixture !== countIdentity) {\n this.fixtureCountOrigins.set(fixture, countIdentity);\n }\n setFixtureMisbehaviorPosition(fixture, position);\n if (misbehaviorEnabled && fixture.misbehavior !== undefined) {\n markFixtureMisbehaviorEnabled(fixture);\n }\n // A fixture passed in is not marked for responsesTools \"extended\": the\n // server reads it through its extended view, so the caller's object (which\n // another server may share) is left as it was loaded.\n return fixture;\n }\n\n addFixture(fixture: Fixture): this {\n this.fixtures.push(this.normalizeFixture(fixture));\n return this;\n }\n\n addFixtures(fixtures: Fixture[]): this {\n this.fixtures.push(...fixtures.map((fixture) => this.normalizeFixture(fixture)));\n return this;\n }\n\n prependFixture(fixture: Fixture): this {\n this.fixtures.unshift(this.normalizeFixture(fixture));\n return this;\n }\n\n /** Mark a fixture this LLMock built, for {@link normalizeFixture}. */\n private own(fixture: Fixture): Fixture {\n this.ownFixtures.add(fixture);\n return fixture;\n }\n\n getFixtures(): readonly Fixture[] {\n return this.fixtures;\n }\n\n /**\n * Load a fixture file: its LLM fixtures and its `mcpFakes` blocks (F4).\n * Before `start()` the blocks are buffered and handed to the server at\n * start (W2); after it they go to the MCPMock serving each block's `mount`\n * path, auto-mounted when none does (W6). A block that cannot be honored\n * throws a `FixtureLoadError` and nothing from the file is added.\n */\n loadFixtureFile(filePath: string): this {\n return this.acceptLoaded(loadFixtureFileWithServices(filePath, undefined, this.options.live));\n }\n\n /** As {@link loadFixtureFile}, for every fixture file under `dirPath`. */\n loadFixtureDir(dirPath: string): this {\n return this.acceptLoaded(\n loadFixturesFromDirWithServices(dirPath, undefined, this.options.live),\n );\n }\n\n /**\n * Add a load's fakes (all or nothing), then its LLM fixtures. Before start\n * the fakes are checked as the start-time hand-off will check them, with\n * the blocks already buffered and the mounts added so far, so a file whose\n * fakes would be rejected adds nothing. A mount added after the load can\n * still make `start()` reject.\n */\n private acceptLoaded(loaded: FixturesWithServices): this {\n // With misbehavior enabled, a bad `misbehavior` key throws before anything is added.\n if (this.misbehaviorEnabled) loaded.fixtures.forEach(enableHeldFixtureMisbehavior);\n if (this.options.responsesTools === \"extended\") {\n loaded.fixtures.forEach(markFixtureResponsesToolsExtended);\n }\n if (loaded.mcpFakes.length > 0) {\n if (this.serverInstance) {\n this.addFakesAfterStart(this.serverInstance, loaded.mcpFakes);\n } else {\n planFileFakes(\n this.mounts,\n [...this.mcpFakeBuffer, ...loaded.mcpFakes],\n new Set(loaded.mcpFakes),\n );\n this.mcpFakeBuffer.push(...loaded.mcpFakes);\n }\n }\n this.fixtures.push(...loaded.fixtures);\n return this;\n }\n\n /**\n * W6 for a load after start. Every group of blocks (by `mount` path) is\n * checked before any mount is touched: a path held by a mount that is not\n * an MCPMock is a mount conflict, and each group is first added to a\n * throwaway store. Groups for an existing MCPMock are then added to it (its\n * own add is all or nothing and finds collisions with its loaded ids);\n * groups for a free path are added last, to a new auto-mounted MCPMock,\n * wired as W4. The add warnings (L8) are logged at `warn`.\n */\n private addFakesAfterStart(server: ServerInstance, sources: McpFakeSource[]): void {\n const { onExisting, onNew } = planFileFakes(this.mounts, sources);\n\n const logger = server.defaults.logger;\n for (const { handler, group } of onExisting) {\n const result = handler.addMcpFakes?.(group, { kind: \"file\" });\n for (const warning of result?.warnings ?? []) logger.warn(warning.message);\n }\n const registry = server.defaults.registry;\n for (const { path, group } of onNew) {\n const target = ensureFakeMount(\n this.mounts,\n path,\n {\n journal: server.journal,\n ...(registry ? { registry } : {}),\n logger,\n replaySpeed: server.defaults.replaySpeed,\n },\n logger,\n );\n // The check above found no mount at this path, and nothing ran since.\n if (\"conflict\" in target) continue;\n const result = target.handler.addMcpFakes?.(group, { kind: \"file\" });\n for (const warning of result?.warnings ?? []) logger.warn(warning.message);\n }\n }\n\n /** R4, R5: unload the fakes of every mount and the pre-start buffer. */\n private unloadMcpFakes(): void {\n this.mcpFakeBuffer.length = 0;\n for (const { handler } of this.mounts) handler.clearMcpFakes?.();\n }\n\n /**\n * Add fixtures from a JSON string or pre-parsed array of fixture entries.\n * Validates all fixtures and throws if any have severity \"error\".\n */\n addFixturesFromJSON(input: string | FixtureFileEntry[]): this {\n let entries: FixtureFileEntry[];\n if (typeof input === \"string\") {\n try {\n entries = JSON.parse(input);\n } catch (err) {\n throw new Error(\n `addFixturesFromJSON: invalid JSON — ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n } else {\n entries = input;\n }\n if (!Array.isArray(entries)) {\n throw new TypeError(\n \"addFixturesFromJSON: expected an array of fixture entries; use loadFixtureFile for a {fixtures:[...]} file\",\n );\n }\n const converted = entries.map((entry) => {\n const position = `code#${this.fixtureAddition++}`;\n const fixture = entryToFixture(entry, undefined, this.options.live, {\n file: position,\n index: 0,\n });\n setFixtureMisbehaviorPosition(fixture, position);\n if (this.misbehaviorEnabled) enableHeldFixtureMisbehavior(fixture);\n if (this.options.responsesTools === \"extended\") markFixtureResponsesToolsExtended(fixture);\n return fixture;\n });\n\n const issues = validateFixtures(converted, this.options.live);\n const errors = issues.filter((i) => i.severity === \"error\");\n if (errors.length > 0) {\n throw new Error(`Fixture validation failed: ${JSON.stringify(errors)}`);\n }\n this.fixtures.push(...converted);\n return this;\n }\n\n // Clears in place to preserve array reference identity — the running\n // server reads this same array on every request — and invalidates any\n // one-shot claim parked in flight so it cannot re-arm into the cleared queue.\n clearFixtures(): this {\n clearFixtureQueue(this.fixtures);\n this.serverInstance?.journal.clearMisbehaviorCounters();\n this.unloadMcpFakes();\n return this;\n }\n\n // ---- Convenience ----\n\n on(\n match: FixtureMatch,\n response: FixtureFileResponse | ResponseFactory,\n opts?: FixtureOpts,\n ): this {\n let normalized: FixtureResponse | ResponseFactory = response as ResponseFactory;\n if (typeof response !== \"function\") {\n normalized = normalizeResponse(response, this.options.live);\n // `customToolCalls` / `responsesBlocks` are normalized only where they are\n // read; otherwise they stay as written, as in 1.44.0.\n if (this.options.responsesTools === \"extended\" && !isLiveResponse(normalized)) {\n normalizeResponsesToolsKeys(normalized as unknown as Record<string, unknown>);\n }\n }\n return this.addFixture(this.own({ match, response: normalized, ...opts }));\n }\n\n onLive(\n match: Omit<FixtureMatch, \"endpoint\">,\n transcript: LiveTranscript,\n opts?: FixtureOpts,\n ): this {\n return this.on({ ...match, endpoint: \"openai-live\" }, { live: transcript }, opts);\n }\n\n onMessage(\n pattern: string | RegExp,\n response: FixtureFileResponse | ResponseFactory,\n opts?: FixtureOpts,\n ): this {\n return this.on({ userMessage: pattern }, response, opts);\n }\n\n onEmbedding(\n pattern: string | RegExp,\n response: FixtureFileResponse | ResponseFactory,\n opts?: EmbeddingFixtureOpts,\n ): this {\n return this.on({ inputText: pattern }, response, opts);\n }\n\n onJsonOutput(pattern: string | RegExp, jsonContent: object | string, opts?: FixtureOpts): this {\n const content = typeof jsonContent === \"string\" ? jsonContent : JSON.stringify(jsonContent);\n return this.on({ userMessage: pattern, responseFormat: \"json_object\" }, { content }, opts);\n }\n\n onToolCall(\n name: string,\n response: FixtureFileResponse | ResponseFactory,\n opts?: FixtureOpts,\n ): this {\n return this.on({ toolName: name }, response, opts);\n }\n\n onToolResult(\n id: string,\n response: FixtureFileResponse | ResponseFactory,\n opts?: FixtureOpts,\n ): this {\n return this.on({ toolCallId: id }, response, opts);\n }\n\n onTurn(\n turn: number,\n pattern: string | RegExp,\n response: FixtureFileResponse | ResponseFactory,\n opts?: FixtureOpts,\n ): this {\n return this.on({ userMessage: pattern, turnIndex: turn }, response, opts);\n }\n\n onImage(prompt: string | RegExp, response: ImageResponse): this {\n return this.addFixture(\n this.own({\n match: { userMessage: prompt, endpoint: \"image\" },\n response,\n }),\n );\n }\n\n onSpeech(input: string | RegExp, response: AudioResponse): this {\n return this.addFixture(\n this.own({\n match: { userMessage: input, endpoint: \"speech\" },\n response,\n }),\n );\n }\n\n onTranscription(response: TranscriptionResponse): this {\n return this.addFixture(\n this.own({\n match: { endpoint: \"transcription\" },\n response,\n }),\n );\n }\n\n onTranslation(response: TranscriptionResponse): this {\n return this.addFixture(\n this.own({\n match: { endpoint: \"translation\" },\n response,\n }),\n );\n }\n\n onVideo(prompt: string | RegExp, response: VideoResponse): this {\n return this.addFixture(\n this.own({\n match: { userMessage: prompt, endpoint: \"video\" },\n response,\n }),\n );\n }\n\n onAudio(input: string | RegExp, response: AudioResponse): this {\n return this.addFixture(this.own({ match: { userMessage: input }, response }));\n }\n\n onSoundEffect(text: string | RegExp, response: AudioResponse): this {\n return this.addFixture(\n this.own({\n match: { userMessage: text, endpoint: \"audio-gen\" },\n response,\n }),\n );\n }\n\n onMusic(prompt: string | RegExp, response: AudioResponse): this {\n return this.addFixture(\n this.own({\n match: { userMessage: prompt, endpoint: \"audio-gen\" },\n response,\n }),\n );\n }\n\n onElevenLabsTTS(text: string | RegExp, response: AudioResponse): this {\n return this.addFixture(\n this.own({\n match: { userMessage: text, endpoint: \"elevenlabs-tts\" },\n response,\n }),\n );\n }\n\n onElevenLabsVoiceDesign(description: string | RegExp, response: VoiceDesignResponse): this {\n return this.addFixture(\n this.own({\n match: { userMessage: description, endpoint: \"elevenlabs-voice-design\" },\n response: voiceDesignToJson(response),\n }),\n );\n }\n\n onFalAudio(prompt: string | RegExp, response: AudioResponse, model?: string): this {\n return this.addFixture(\n this.own({\n match: { userMessage: prompt, endpoint: \"fal-audio\", ...(model ? { model } : {}) },\n response,\n }),\n );\n }\n\n // fal.queue.* is the dominant client API; onFalRun is a sync alias.\n //\n // `opts.billableUnits` rides through to the completed `queue-result`\n // response's `x-fal-billable-units` header (emitted alongside\n // `x-fal-request-id`), letting consumers like `@tanstack/ai-fal` surface a\n // billed-units value on replay. Omit it to preserve the header-less default.\n onFalQueue(modelOrPrompt: string | RegExp, response: unknown, opts?: FalQueueOpts): this {\n const { billableUnits, ...fixtureOpts } = opts ?? {};\n return this.addFixture(\n this.own({\n match: { model: modelOrPrompt, endpoint: \"fal\" },\n response: { json: response, ...(billableUnits != null ? { billableUnits } : {}) },\n ...fixtureOpts,\n }),\n );\n }\n\n onFalRun(modelOrPrompt: string | RegExp, response: unknown, opts?: FalQueueOpts): this {\n return this.onFalQueue(modelOrPrompt, response, opts);\n }\n\n /**\n * Register a fal.ai image fixture. Wraps an `ImageResponse` (the shape used\n * by `onImage` and OpenAI/Azure image fixtures) into fal's image envelope\n * before storing it as a `RawJSONResponse`. Defaults `width`/`height` to\n * 1024 when the fixture's `ImageItem` doesn't carry them.\n */\n onFalImage(modelOrPrompt: string | RegExp, response: ImageResponse, opts?: FalQueueOpts): this {\n return this.onFalQueue(modelOrPrompt, imageResponseToFalJson(response), opts);\n }\n\n /**\n * Register a fal.ai video fixture. Wraps a `VideoResponse` into fal's video\n * envelope (`{ video: { url, content_type, file_name, file_size }, seed }`)\n * before storing it as a `RawJSONResponse`.\n */\n onFalVideo(modelOrPrompt: string | RegExp, response: VideoResponse, opts?: FalQueueOpts): this {\n return this.onFalQueue(modelOrPrompt, videoResponseToFalJson(response), opts);\n }\n\n // ---- Service mock convenience methods ----\n\n onSearch(pattern: string | RegExp, results: SearchResult[]): this {\n this.searchFixtures.push({ match: pattern, results });\n return this;\n }\n\n onRerank(pattern: string | RegExp, results: RerankResult[]): this {\n this.rerankFixtures.push({ match: pattern, results });\n return this;\n }\n\n onModerate(pattern: string | RegExp, result: ModerationResult): this {\n this.moderationFixtures.push({ match: pattern, result });\n return this;\n }\n\n /**\n * Queue a one-shot error that will be returned for the next matching\n * request, then automatically removed. Implemented as an internal fixture\n * inserted at the front of the fixture list; see `queueOneShotError` for\n * the endpoint gate and the served-not-evaluated consumption rule.\n */\n nextRequestError(\n status: number,\n errorBody?: { message?: string; type?: string; code?: string },\n ): this {\n // Same gate as `POST /__aimock/error` and fixture validation — this is the\n // form the docs use, and an unchecked status reaches `res.writeHead` on\n // the next matched request: 99/1000 throw there (the injected error is\n // lost and the caller sees a generic 500), and 1xx hangs the request until\n // the client times out. Throwing HERE names the offending call instead.\n if (!isInjectableStatus(status)) {\n throw new RangeError(\n `nextRequestError: invalid status ${String(status)} — must be ${INJECTED_STATUS_RANGE}`,\n );\n }\n queueOneShotError(this.fixtures, status, errorBody);\n return this;\n }\n\n // ---- Mounts ----\n\n mount(path: string, handler: Mountable): this {\n // W4: an auto-mounted MCPMock at `path` takes its requests first (dispatch\n // takes the first match), so the new mount is shadowed; so is one at\n // `path` plus \"/\", whose root request the auto-mount answers as its own.\n // An auto-mount lets any other sub-path fall through: that is no shadow.\n const shadowedBy = this.serverInstance\n ? this.mounts.find(\n (m) => isAutoMount(m.handler) && (path === m.path || path === m.path + \"/\"),\n )\n : undefined;\n this.mounts.push({ path, handler });\n\n // If server is already running, wire up journal, registry, logger and baseUrl\n // immediately so late mounts behave identically to pre-start mounts.\n if (this.serverInstance) {\n if (handler.setJournal) handler.setJournal(this.serverInstance.journal);\n if (handler.setBaseUrl) handler.setBaseUrl(this.serverInstance.url + path);\n const registry = this.serverInstance.defaults.registry;\n if (registry && handler.setRegistry) handler.setRegistry(registry);\n const logger = this.serverInstance.defaults.logger;\n if (handler.setLogger) handler.setLogger(logger);\n // B11/R12: only aimock's own MCPMock takes the replay speed; a custom\n // Mountable is never called (1.44.0 had no such hook).\n if (handler instanceof MCPMock) {\n handler.setReplaySpeed(this.serverInstance.defaults.replaySpeed);\n }\n if (shadowedBy) {\n logger.warn(\n build(\n msg`MCP fakes: the mount at ${quote(path)} is shadowed by the MCP mock auto-mounted at ${quote(shadowedBy.path)}; its requests reach the auto-mount`,\n ),\n );\n }\n }\n\n return this;\n }\n\n // ---- Journal proxies ----\n\n getRequests(): import(\"./types.js\").JournalEntry[] {\n return this.journal.getAll();\n }\n\n getLastRequest(): import(\"./types.js\").JournalEntry | null {\n return this.journal.getLast();\n }\n\n /**\n * Clear the request journal. Fixture match-counts (sequencing state) are\n * left intact — use `resetMatchCounts()` for those.\n */\n clearRequests(): void {\n this.journal.clearEntries();\n }\n\n /**\n * Reset fixture match counts, and the MCP fakes consumption state of every\n * mount (R6), for `testId` or for all test ids. Fakes stay loaded.\n */\n resetMatchCounts(testId?: string): this {\n if (this.serverInstance) {\n this.serverInstance.journal.clearMatchCounts(testId);\n }\n for (const { handler } of this.mounts) handler.resetScenarioState?.(testId);\n return this;\n }\n\n // ---- Chaos ----\n\n /**\n * Set the server-wide chaos baseline. Writes through to a RUNNING server as\n * well as the construction options: an untagged `POST /__aimock/chaos`\n * installs a baseline override that shadows `options.chaos`, and without this\n * the call would silently do nothing until the next `reset()`. Per-testId\n * overrides still win over the baseline.\n */\n setChaos(config: ChaosConfig): this {\n this.options.chaos = config;\n if (this.serverInstance) this.serverInstance.defaults.chaos = config;\n return this;\n }\n\n /**\n * Turn chaos off everywhere: the construction config, the runtime baseline,\n * and every per-testId override (assigning `undefined` is the full-clear\n * signal the `defaults.chaos` setter defines).\n */\n clearChaos(): this {\n delete this.options.chaos;\n if (this.serverInstance) this.serverInstance.defaults.chaos = undefined;\n return this;\n }\n\n // ---- Semantic misbehavior ----\n\n /** Replace construction/runtime baselines without changing named test overrides. */\n setMisbehavior(config: MisbehaviorConfig | MisbehaviorFaultId): this {\n if (!this.misbehaviorEnabled) {\n throw new TypeError(\n \"setMisbehavior: misbehavior is not enabled; construct with enableMisbehavior: true\",\n );\n }\n const parsed = parseMisbehavior(config);\n if (!parsed.ok) throw new TypeError(`${parsed.issue.rule}: ${parsed.issue.message}`);\n this.options.misbehavior = parsed.config;\n const defaults = this.serverInstance?.defaults;\n if (defaults?.misbehavior) {\n defaults.misbehavior.baseline =\n parsed.config.seed === \"random\"\n ? { ...parsed.config, seed: resolveMisbehaviorSeed(parsed.config.seed, defaults.logger) }\n : parsed.config;\n if (defaults.misbehavior.byTestId.has(DEFAULT_TEST_ID)) {\n defaults.misbehavior.byTestId.set(DEFAULT_TEST_ID, defaults.misbehavior.baseline);\n }\n }\n return this;\n }\n\n /** Clear the baseline and all runtime overrides, before or after start. */\n clearMisbehavior(): this {\n delete this.options.misbehavior;\n const scope = this.serverInstance?.defaults.misbehavior;\n if (scope) {\n scope.baseline = undefined;\n scope.byTestId.clear();\n }\n return this;\n }\n\n // ---- Recording ----\n\n enableRecording(config: RecordConfig): this {\n this.options.record = config;\n return this;\n }\n\n disableRecording(): this {\n delete this.options.record;\n return this;\n }\n\n // ---- Reset ----\n\n /**\n * Full reset — the in-process equivalent of `POST /__aimock/reset`. Shares\n * one implementation with the control-API route so the two cannot drift.\n *\n * The one deliberate difference: search / rerank / moderation fixtures are\n * also cleared here. Those are registered through this class only — the\n * control API has no route that creates them, so the HTTP reset can neither\n * reach nor observe them.\n *\n * NOT ALL OF THIS IS PER-INSTANCE. `performFullReset` clears module-global\n * state as well: the Gemini interaction and event-id counters\n * (`resetInteractionCounter` / `resetEventIdCounter` in\n * `./gemini-interactions.js`), the fal.ai job/queue maps (`falJobs`,\n * `falQueueStates`), the fine-tuning job store (`clearFineTuningStore`),\n * and the ElevenLabs Voice Design store (`clearElevenLabsVoices`). With two\n * `LLMock` instances live in one process,\n * `a.reset()` rewinds the Gemini id sequence that `b` is mid-way through —\n * `b` then re-emits `aimock-int-0` / `evt_1`, ids it has already handed\n * out — and drops `b`'s in-flight fal jobs. Give each instance its own\n * process (or its own vitest worker) if that matters.\n *\n * The global stores are cleared even before `start()`, when there is no\n * server instance to reset.\n */\n reset(): this {\n this.searchFixtures.length = 0;\n this.rerankFixtures.length = 0;\n this.moderationFixtures.length = 0;\n // `ServerInstance` carries no mounts, so the fakes are unloaded here (R4).\n this.unloadMcpFakes();\n performFullReset(this.fixtures, this.serverInstance);\n return this;\n }\n\n // ---- Server lifecycle ----\n\n async start(): Promise<string> {\n if (this.serverInstance) {\n throw new Error(\"Server already started\");\n }\n const serviceFixtures = {\n search: this.searchFixtures,\n rerank: this.rerankFixtures,\n moderation: this.moderationFixtures,\n mcpFakes: [...this.mcpFakeBuffer],\n };\n this.serverInstance = await (this.resolvedInboundAuth\n ? createServerWithResolvedAuth(\n this.fixtures,\n this.options,\n this.resolvedInboundAuth,\n this.mounts,\n serviceFixtures,\n )\n : createServer(this.fixtures, this.options, this.mounts, serviceFixtures));\n const countIdentity = (fixture: Fixture) => this.fixtureCountOrigins.get(fixture) ?? fixture;\n this.serverInstance.journal.configureFixtureCountIdentity(countIdentity);\n // The server holds the buffered fakes now (W2). A start that rejects took\n // its hand-off back, so the buffer is kept for a retry.\n this.mcpFakeBuffer.length = 0;\n return this.serverInstance.url;\n }\n\n closeLiveSessions(testId?: string): this {\n this.serverInstance?.closeLiveSessions(testId);\n return this;\n }\n\n async stop(): Promise<void> {\n if (!this.serverInstance) {\n throw new Error(\"Server not started\");\n }\n const { server } = this.serverInstance;\n await new Promise<void>((resolve, reject) => {\n server.close((err: Error | undefined) => (err ? reject(err) : resolve()));\n });\n this.serverInstance = null;\n }\n\n // ---- Accessors ----\n\n get journal(): Journal {\n if (!this.serverInstance) {\n throw new Error(\"Server not started\");\n }\n return this.serverInstance.journal;\n }\n\n get url(): string {\n if (!this.serverInstance) {\n throw new Error(\"Server not started\");\n }\n return this.serverInstance.url;\n }\n\n get baseUrl(): string {\n return this.url;\n }\n\n get port(): number {\n const parsed = new URL(this.url); // this.url throws if not started\n if (!parsed.port) {\n throw new Error(`Server URL has no explicit port: ${this.url}`);\n }\n return parseInt(parsed.port, 10);\n }\n\n // ---- Static factory ----\n\n static async create(options?: MockServerOptions): Promise<LLMock> {\n const instance = new LLMock(options);\n await instance.start();\n return instance;\n }\n}\n\n/** @internal Configuration startup preserves a policy resolved from the selected source. */\nexport function createLLMockWithResolvedAuth(\n options: MockServerOptions,\n resolvedAuth: ResolvedInboundAuth,\n): LLMock {\n return new LLMock(options, resolvedAuth);\n}\n"],"mappings":"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"}
|
package/dist/llmock.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llmock.d.cts","names":[],"sources":["../src/llmock.ts"],"sourcesContent":[],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"llmock.d.cts","names":[],"sources":["../src/llmock.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/llmock.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llmock.d.ts","names":[],"sources":["../src/llmock.ts"],"sourcesContent":[],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"llmock.d.ts","names":[],"sources":["../src/llmock.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/llmock.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { DEFAULT_TEST_ID } from "./constants.js";
|
|
2
2
|
import { build, msg, quote } from "./message-text.js";
|
|
3
|
+
import { parsePolicy } from "./response/policy.js";
|
|
3
4
|
import { isLiveResponse, markServerOwnedFixtures } from "./helpers.js";
|
|
4
5
|
import { normalizeLiveFixture, normalizeLiveOptions } from "./live-fixture.js";
|
|
5
6
|
import { getFixtureMisbehaviorPosition, parseMisbehavior, resolveMisbehaviorSeed, setFixtureMisbehaviorPosition, validateFixtureMisbehavior } from "./misbehavior.js";
|
|
6
7
|
import { INJECTED_STATUS_RANGE, MisbehaviorConfigError, clearFixtureQueue, enableHeldFixtureMisbehavior, entryToFixture, isInjectableStatus, markFixtureMisbehaviorEnabled, markFixtureResponsesToolsExtended, normalizeResponse, normalizeResponsesToolsKeys, queueOneShotError, validateFixtures } from "./fixture-loader.js";
|
|
8
|
+
import { Logger } from "./logger.js";
|
|
7
9
|
import { imageResponseToFalJson, videoResponseToFalJson } from "./fal.js";
|
|
8
10
|
import { voiceDesignToJson } from "./elevenlabs-voice.js";
|
|
9
11
|
import { MCPMock } from "./mcp-mock.js";
|
|
@@ -34,6 +36,7 @@ var LLMock = class LLMock {
|
|
|
34
36
|
constructor(options, resolvedInboundAuth) {
|
|
35
37
|
markServerOwnedFixtures(this.fixtures);
|
|
36
38
|
this.options = options ?? {};
|
|
39
|
+
parsePolicy(this.options.policy, (message) => new Logger("warn").warn(message));
|
|
37
40
|
if (this.options.live !== void 0) normalizeLiveOptions(this.options.live);
|
|
38
41
|
if (this.misbehaviorEnabled && this.options.misbehavior !== void 0) this.setMisbehavior(this.options.misbehavior);
|
|
39
42
|
this.resolvedInboundAuth = resolvedInboundAuth;
|