@copilotkit/aimock 1.43.0 → 1.45.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 +46 -0
- package/README.md +14 -2
- package/dist/agui-handler.d.ts.map +1 -1
- package/dist/aimock-cli.cjs +31 -5
- 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 +31 -5
- package/dist/aimock-cli.js.map +1 -1
- package/dist/bedrock-converse.cjs +344 -43
- 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 +345 -44
- package/dist/bedrock-converse.js.map +1 -1
- package/dist/bedrock.cjs +195 -42
- 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 +196 -43
- package/dist/bedrock.js.map +1 -1
- package/dist/chaos.cjs +9 -5
- 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 +10 -7
- package/dist/chaos.js.map +1 -1
- package/dist/cli.cjs +238 -9
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +242 -13
- package/dist/cli.js.map +1 -1
- package/dist/cohere.cjs +159 -72
- 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 +160 -73
- package/dist/cohere.js.map +1 -1
- package/dist/config-loader.cjs +63 -5
- package/dist/config-loader.cjs.map +1 -1
- package/dist/config-loader.d.cts +37 -4
- package/dist/config-loader.d.cts.map +1 -1
- package/dist/config-loader.d.ts +37 -4
- package/dist/config-loader.d.ts.map +1 -1
- package/dist/config-loader.js +63 -5
- package/dist/config-loader.js.map +1 -1
- package/dist/constants.cjs +8 -0
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +6 -2
- package/dist/constants.d.ts +6 -2
- package/dist/constants.js +8 -1
- package/dist/constants.js.map +1 -1
- package/dist/echo-text.cjs +65 -0
- package/dist/echo-text.cjs.map +1 -0
- package/dist/echo-text.d.cts +22 -0
- package/dist/echo-text.d.cts.map +1 -0
- package/dist/echo-text.d.ts +22 -0
- package/dist/echo-text.d.ts.map +1 -0
- package/dist/echo-text.js +65 -0
- package/dist/echo-text.js.map +1 -0
- package/dist/embeddings.cjs +18 -1
- package/dist/embeddings.cjs.map +1 -1
- package/dist/embeddings.d.cts +1 -1
- package/dist/embeddings.d.cts.map +1 -1
- package/dist/embeddings.d.ts +1 -1
- package/dist/embeddings.d.ts.map +1 -1
- package/dist/embeddings.js +18 -1
- package/dist/embeddings.js.map +1 -1
- package/dist/fakes-plugin.cjs +131 -0
- package/dist/fakes-plugin.cjs.map +1 -0
- package/dist/fakes-plugin.d.cts +23 -0
- package/dist/fakes-plugin.d.cts.map +1 -0
- package/dist/fakes-plugin.d.ts +23 -0
- package/dist/fakes-plugin.d.ts.map +1 -0
- package/dist/fakes-plugin.js +127 -0
- package/dist/fakes-plugin.js.map +1 -0
- package/dist/files.cjs +9 -11
- 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 +10 -13
- package/dist/files.js.map +1 -1
- package/dist/fine-tuning.cjs +1 -19
- 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 -20
- package/dist/fine-tuning.js.map +1 -1
- package/dist/fixture-loader-services.cjs +116 -0
- package/dist/fixture-loader-services.cjs.map +1 -0
- package/dist/fixture-loader-services.d.cts +48 -0
- package/dist/fixture-loader-services.d.cts.map +1 -0
- package/dist/fixture-loader-services.d.ts +48 -0
- package/dist/fixture-loader-services.d.ts.map +1 -0
- package/dist/fixture-loader-services.js +114 -0
- package/dist/fixture-loader-services.js.map +1 -0
- package/dist/fixture-loader.cjs +552 -29
- package/dist/fixture-loader.cjs.map +1 -1
- package/dist/fixture-loader.d.cts +140 -2
- package/dist/fixture-loader.d.cts.map +1 -1
- package/dist/fixture-loader.d.ts +140 -2
- package/dist/fixture-loader.d.ts.map +1 -1
- package/dist/fixture-loader.js +542 -31
- package/dist/fixture-loader.js.map +1 -1
- package/dist/gemini-embeddings.cjs +42 -2
- package/dist/gemini-embeddings.cjs.map +1 -1
- package/dist/gemini-embeddings.js +43 -3
- package/dist/gemini-embeddings.js.map +1 -1
- package/dist/gemini-interactions.cjs +288 -52
- package/dist/gemini-interactions.cjs.map +1 -1
- package/dist/gemini-interactions.d.cts.map +1 -1
- package/dist/gemini-interactions.d.ts.map +1 -1
- package/dist/gemini-interactions.js +289 -53
- package/dist/gemini-interactions.js.map +1 -1
- package/dist/gemini.cjs +234 -38
- 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 +235 -39
- package/dist/gemini.js.map +1 -1
- package/dist/helpers.cjs +1157 -12
- package/dist/helpers.cjs.map +1 -1
- package/dist/helpers.d.cts +85 -4
- package/dist/helpers.d.cts.map +1 -1
- package/dist/helpers.d.ts +85 -4
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +1113 -14
- package/dist/helpers.js.map +1 -1
- package/dist/images.cjs +3 -2
- package/dist/images.cjs.map +1 -1
- package/dist/images.js +3 -2
- package/dist/images.js.map +1 -1
- package/dist/index.cjs +39 -1
- package/dist/index.d.cts +11 -4
- package/dist/index.d.ts +11 -4
- package/dist/index.js +11 -4
- package/dist/jest.cjs +43 -14
- package/dist/jest.cjs.map +1 -1
- package/dist/jest.d.cts +47 -5
- package/dist/jest.d.cts.map +1 -1
- package/dist/jest.d.ts +47 -5
- package/dist/jest.d.ts.map +1 -1
- package/dist/jest.js +45 -16
- package/dist/jest.js.map +1 -1
- package/dist/journal.cjs +155 -13
- package/dist/journal.cjs.map +1 -1
- package/dist/journal.d.cts +54 -4
- package/dist/journal.d.cts.map +1 -1
- package/dist/journal.d.ts +54 -4
- package/dist/journal.d.ts.map +1 -1
- package/dist/journal.js +155 -13
- package/dist/journal.js.map +1 -1
- package/dist/live-sanitize.cjs +4 -32
- package/dist/live-sanitize.cjs.map +1 -1
- package/dist/live-sanitize.js +4 -32
- package/dist/live-sanitize.js.map +1 -1
- package/dist/llmock.cjs +204 -39
- package/dist/llmock.cjs.map +1 -1
- package/dist/llmock.d.cts +51 -1
- package/dist/llmock.d.cts.map +1 -1
- package/dist/llmock.d.ts +51 -1
- package/dist/llmock.d.ts.map +1 -1
- package/dist/llmock.js +206 -41
- package/dist/llmock.js.map +1 -1
- package/dist/mcp-fakes-mount.cjs +217 -0
- package/dist/mcp-fakes-mount.cjs.map +1 -0
- package/dist/mcp-fakes-mount.js +211 -0
- package/dist/mcp-fakes-mount.js.map +1 -0
- package/dist/mcp-fakes-report.cjs +111 -0
- package/dist/mcp-fakes-report.cjs.map +1 -0
- package/dist/mcp-fakes-report.d.cts +40 -0
- package/dist/mcp-fakes-report.d.cts.map +1 -0
- package/dist/mcp-fakes-report.d.ts +40 -0
- package/dist/mcp-fakes-report.d.ts.map +1 -0
- package/dist/mcp-fakes-report.js +107 -0
- package/dist/mcp-fakes-report.js.map +1 -0
- package/dist/mcp-fakes.cjs +1942 -0
- package/dist/mcp-fakes.cjs.map +1 -0
- package/dist/mcp-fakes.d.cts +504 -0
- package/dist/mcp-fakes.d.cts.map +1 -0
- package/dist/mcp-fakes.d.ts +504 -0
- package/dist/mcp-fakes.d.ts.map +1 -0
- package/dist/mcp-fakes.js +1937 -0
- package/dist/mcp-fakes.js.map +1 -0
- package/dist/mcp-handler.cjs +534 -27
- package/dist/mcp-handler.cjs.map +1 -1
- package/dist/mcp-handler.d.cts +49 -0
- package/dist/mcp-handler.d.cts.map +1 -0
- package/dist/mcp-handler.d.ts +49 -0
- package/dist/mcp-handler.d.ts.map +1 -0
- package/dist/mcp-handler.js +530 -28
- package/dist/mcp-handler.js.map +1 -1
- package/dist/mcp-mock.cjs +326 -47
- package/dist/mcp-mock.cjs.map +1 -1
- package/dist/mcp-mock.d.cts +97 -1
- package/dist/mcp-mock.d.cts.map +1 -1
- package/dist/mcp-mock.d.ts +97 -1
- package/dist/mcp-mock.d.ts.map +1 -1
- package/dist/mcp-mock.js +327 -48
- package/dist/mcp-mock.js.map +1 -1
- package/dist/mcp-recorder.cjs +1224 -0
- package/dist/mcp-recorder.cjs.map +1 -0
- package/dist/mcp-recorder.d.cts +108 -0
- package/dist/mcp-recorder.d.cts.map +1 -0
- package/dist/mcp-recorder.d.ts +108 -0
- package/dist/mcp-recorder.d.ts.map +1 -0
- package/dist/mcp-recorder.js +1215 -0
- package/dist/mcp-recorder.js.map +1 -0
- package/dist/mcp-stub.cjs +5 -1
- package/dist/mcp-stub.d.cts +3 -1
- package/dist/mcp-stub.d.ts +3 -1
- package/dist/mcp-stub.js +3 -1
- package/dist/mcp-types.d.cts +6 -0
- package/dist/mcp-types.d.ts +6 -0
- package/dist/message-text.cjs +192 -0
- package/dist/message-text.cjs.map +1 -0
- package/dist/message-text.d.cts +31 -0
- package/dist/message-text.d.cts.map +1 -0
- package/dist/message-text.d.ts +31 -0
- package/dist/message-text.d.ts.map +1 -0
- package/dist/message-text.js +184 -0
- package/dist/message-text.js.map +1 -0
- package/dist/messages.cjs +400 -56
- 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 +401 -58
- package/dist/messages.js.map +1 -1
- package/dist/metrics.cjs +46 -66
- package/dist/metrics.cjs.map +1 -1
- package/dist/metrics.d.cts +14 -6
- package/dist/metrics.d.cts.map +1 -1
- package/dist/metrics.d.ts +14 -6
- package/dist/metrics.d.ts.map +1 -1
- package/dist/metrics.js +32 -40
- package/dist/metrics.js.map +1 -1
- package/dist/misbehavior.cjs +1523 -0
- package/dist/misbehavior.cjs.map +1 -0
- package/dist/misbehavior.d.cts +43 -0
- package/dist/misbehavior.d.cts.map +1 -0
- package/dist/misbehavior.d.ts +43 -0
- package/dist/misbehavior.d.ts.map +1 -0
- package/dist/misbehavior.js +1511 -0
- package/dist/misbehavior.js.map +1 -0
- package/dist/ollama.cjs +315 -113
- 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 +316 -114
- package/dist/ollama.js.map +1 -1
- package/dist/openapi.cjs +3405 -0
- package/dist/openapi.cjs.map +1 -0
- package/dist/openapi.d.cts +30 -0
- package/dist/openapi.d.cts.map +1 -0
- package/dist/openapi.d.ts +30 -0
- package/dist/openapi.d.ts.map +1 -0
- package/dist/openapi.js +3404 -0
- package/dist/openapi.js.map +1 -0
- package/dist/openrouter-video.cjs +4 -4
- 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 +4 -4
- package/dist/openrouter-video.js.map +1 -1
- package/dist/record-sanitize.cjs +231 -0
- package/dist/record-sanitize.cjs.map +1 -0
- package/dist/record-sanitize.js +224 -0
- package/dist/record-sanitize.js.map +1 -0
- package/dist/recorder.cjs +115 -6
- package/dist/recorder.cjs.map +1 -1
- package/dist/recorder.d.cts +2 -1
- package/dist/recorder.d.cts.map +1 -1
- package/dist/recorder.d.ts +2 -1
- package/dist/recorder.d.ts.map +1 -1
- package/dist/recorder.js +116 -8
- package/dist/recorder.js.map +1 -1
- package/dist/responses.cjs +701 -166
- package/dist/responses.cjs.map +1 -1
- package/dist/responses.d.cts +5 -13
- package/dist/responses.d.cts.map +1 -1
- package/dist/responses.d.ts +5 -13
- package/dist/responses.d.ts.map +1 -1
- package/dist/responses.js +699 -169
- package/dist/responses.js.map +1 -1
- package/dist/route-registry.cjs +951 -0
- package/dist/route-registry.cjs.map +1 -0
- package/dist/route-registry.d.cts +33 -0
- package/dist/route-registry.d.cts.map +1 -0
- package/dist/route-registry.d.ts +33 -0
- package/dist/route-registry.d.ts.map +1 -0
- package/dist/route-registry.js +866 -0
- package/dist/route-registry.js.map +1 -0
- package/dist/router.cjs +24 -2
- package/dist/router.cjs.map +1 -1
- package/dist/router.d.cts.map +1 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +25 -4
- package/dist/router.js.map +1 -1
- package/dist/server.cjs +1159 -264
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +4 -1
- package/dist/server.d.cts.map +1 -1
- package/dist/server.d.ts +4 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1067 -172
- package/dist/server.js.map +1 -1
- package/dist/speech.cjs +4 -2
- package/dist/speech.cjs.map +1 -1
- package/dist/speech.js +4 -2
- package/dist/speech.js.map +1 -1
- package/dist/stream-collapse.cjs +236 -34
- package/dist/stream-collapse.cjs.map +1 -1
- package/dist/stream-collapse.d.cts +39 -4
- package/dist/stream-collapse.d.cts.map +1 -1
- package/dist/stream-collapse.d.ts +39 -4
- package/dist/stream-collapse.d.ts.map +1 -1
- package/dist/stream-collapse.js +235 -35
- package/dist/stream-collapse.js.map +1 -1
- package/dist/suite.cjs +1 -1
- package/dist/suite.js +1 -1
- package/dist/transcription.cjs +2 -2
- 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 +2 -2
- package/dist/transcription.js.map +1 -1
- package/dist/types.cjs +18 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +516 -5
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.ts +516 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +17 -0
- package/dist/types.js.map +1 -0
- package/dist/validate-cli.cjs +123 -33
- package/dist/validate-cli.cjs.map +1 -1
- package/dist/validate-cli.js +125 -35
- package/dist/validate-cli.js.map +1 -1
- package/dist/vector-stores.cjs +1180 -0
- package/dist/vector-stores.cjs.map +1 -0
- package/dist/vector-stores.d.cts +106 -0
- package/dist/vector-stores.d.cts.map +1 -0
- package/dist/vector-stores.d.ts +106 -0
- package/dist/vector-stores.d.ts.map +1 -0
- package/dist/vector-stores.js +1164 -0
- package/dist/vector-stores.js.map +1 -0
- package/dist/vector-types.d.cts.map +1 -1
- package/dist/version.cjs +45 -0
- package/dist/version.cjs.map +1 -0
- package/dist/version.js +44 -0
- package/dist/version.js.map +1 -0
- package/dist/video.cjs +19 -0
- 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 +19 -0
- package/dist/video.js.map +1 -1
- package/dist/vitest.cjs +77 -16
- package/dist/vitest.cjs.map +1 -1
- package/dist/vitest.d.cts +38 -5
- package/dist/vitest.d.cts.map +1 -1
- package/dist/vitest.d.ts +38 -5
- package/dist/vitest.d.ts.map +1 -1
- package/dist/vitest.js +78 -17
- package/dist/vitest.js.map +1 -1
- package/dist/watcher.cjs +6 -2
- package/dist/watcher.cjs.map +1 -1
- package/dist/watcher.js +6 -2
- package/dist/watcher.js.map +1 -1
- package/dist/ws-gemini-live.cjs +210 -101
- package/dist/ws-gemini-live.cjs.map +1 -1
- package/dist/ws-gemini-live.d.cts +9 -3
- package/dist/ws-gemini-live.d.cts.map +1 -1
- package/dist/ws-gemini-live.d.ts +9 -3
- package/dist/ws-gemini-live.d.ts.map +1 -1
- package/dist/ws-gemini-live.js +211 -102
- package/dist/ws-gemini-live.js.map +1 -1
- package/dist/ws-realtime.cjs +175 -62
- package/dist/ws-realtime.cjs.map +1 -1
- package/dist/ws-realtime.d.cts +8 -3
- package/dist/ws-realtime.d.cts.map +1 -1
- package/dist/ws-realtime.d.ts +8 -3
- package/dist/ws-realtime.d.ts.map +1 -1
- package/dist/ws-realtime.js +176 -63
- package/dist/ws-realtime.js.map +1 -1
- package/dist/ws-responses.cjs +121 -16
- package/dist/ws-responses.cjs.map +1 -1
- package/dist/ws-responses.d.cts +8 -12
- package/dist/ws-responses.d.cts.map +1 -1
- package/dist/ws-responses.d.ts +8 -12
- package/dist/ws-responses.d.ts.map +1 -1
- package/dist/ws-responses.js +123 -18
- package/dist/ws-responses.js.map +1 -1
- package/package.json +13 -2
- package/skills/write-fixtures/SKILL.md +179 -21
package/dist/fixture-loader.cjs
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
|
|
2
|
+
const require_constants = require('./constants.cjs');
|
|
3
|
+
const require_message_text = require('./message-text.cjs');
|
|
2
4
|
const require_helpers = require('./helpers.cjs');
|
|
3
5
|
const require_live_fixture = require('./live-fixture.cjs');
|
|
4
6
|
const require_chaos = require('./chaos.cjs');
|
|
7
|
+
const require_misbehavior = require('./misbehavior.cjs');
|
|
5
8
|
let node_fs = require("node:fs");
|
|
6
9
|
let node_path = require("node:path");
|
|
7
10
|
|
|
@@ -33,7 +36,35 @@ function normalizeResponse(raw, liveOptions) {
|
|
|
33
36
|
});
|
|
34
37
|
return response;
|
|
35
38
|
}
|
|
36
|
-
|
|
39
|
+
/**
|
|
40
|
+
* @internal Normalize `responsesBlocks` and `customToolCalls` in place, for a
|
|
41
|
+
* server with `responsesTools: "extended"`: stringify object `arguments` on
|
|
42
|
+
* `toolCall` blocks, and give a `customToolCalls` entry with no `type` the
|
|
43
|
+
* type `"custom"`. A custom call's free-text `input` is never stringified.
|
|
44
|
+
* {@link normalizeResponse} leaves both keys as written, as 1.44.0 did.
|
|
45
|
+
*/
|
|
46
|
+
function normalizeResponsesToolsKeys(response) {
|
|
47
|
+
if (Array.isArray(response.responsesBlocks)) response.responsesBlocks = response.responsesBlocks.map((block) => {
|
|
48
|
+
const b = block;
|
|
49
|
+
if (b !== null && typeof b === "object" && b.type === "toolCall" && typeof b.arguments === "object" && b.arguments !== null) return {
|
|
50
|
+
...b,
|
|
51
|
+
arguments: JSON.stringify(b.arguments)
|
|
52
|
+
};
|
|
53
|
+
return block;
|
|
54
|
+
});
|
|
55
|
+
if (Array.isArray(response.customToolCalls)) response.customToolCalls = response.customToolCalls.map((tc) => {
|
|
56
|
+
const entry = tc;
|
|
57
|
+
return entry !== null && typeof entry === "object" && entry.type === void 0 ? {
|
|
58
|
+
...entry,
|
|
59
|
+
type: "custom"
|
|
60
|
+
} : tc;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
var InvalidFixtureMatchError = class extends TypeError {};
|
|
64
|
+
function entryToFixture(entry, logger, liveOptions, source) {
|
|
65
|
+
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) throw new TypeError("Fixture entry must be an object");
|
|
66
|
+
if (entry.match == null) throw new TypeError("Fixture match must be an object");
|
|
67
|
+
if (typeof entry.match !== "object" || Array.isArray(entry.match)) throw new InvalidFixtureMatchError("Fixture match must be an object");
|
|
37
68
|
const fixture = {
|
|
38
69
|
match: {
|
|
39
70
|
userMessage: entry.match.userMessage,
|
|
@@ -62,6 +93,19 @@ function entryToFixture(entry, logger, liveOptions) {
|
|
|
62
93
|
...entry.openRouterProcessing !== void 0 && { openRouterProcessing: entry.openRouterProcessing },
|
|
63
94
|
...entry.metadata !== void 0 && { metadata: entry.metadata }
|
|
64
95
|
};
|
|
96
|
+
if (source) require_misbehavior.setFixtureMisbehaviorPosition(fixture, `${source.file}#${source.index}`);
|
|
97
|
+
const heldToolNamespace = entry.match.toolNamespace !== void 0;
|
|
98
|
+
const response = fixture.response;
|
|
99
|
+
const heldResponseKeys = entry.match.endpoint !== "openai-live" && !require_helpers.isLiveResponse(entry.response) && typeof response === "object" && response !== null && ("customToolCalls" in response || "responsesBlocks" in response);
|
|
100
|
+
if (heldToolNamespace || heldResponseKeys) heldResponsesTools.set(fixture, {
|
|
101
|
+
...heldToolNamespace && { toolNamespace: entry.match.toolNamespace },
|
|
102
|
+
normalize: heldResponseKeys
|
|
103
|
+
});
|
|
104
|
+
if (entry.misbehavior !== void 0) heldFixtureMisbehavior.set(fixture, {
|
|
105
|
+
value: entry.misbehavior,
|
|
106
|
+
path: source ? `fixtures[${source.index}].misbehavior` : "misbehavior",
|
|
107
|
+
file: source?.file ?? null
|
|
108
|
+
});
|
|
65
109
|
if (fixture.recordedTimings) {
|
|
66
110
|
const rt = fixture.recordedTimings;
|
|
67
111
|
if (!Number.isFinite(rt.ttftMs) || rt.ttftMs < 0) rt.ttftMs = 0;
|
|
@@ -92,34 +136,100 @@ function warn(logger, msg, ...rest) {
|
|
|
92
136
|
if (logger) logger.warn(msg, ...rest);
|
|
93
137
|
else console.warn(`[fixture-loader] ${msg}`, ...rest);
|
|
94
138
|
}
|
|
95
|
-
|
|
139
|
+
/**
|
|
140
|
+
* A parsed JSON value, or `null` when the file could not be read or parsed (warned).
|
|
141
|
+
*
|
|
142
|
+
* @internal Shared with fixture-loader-services.ts.
|
|
143
|
+
*/
|
|
144
|
+
function readFixtureJson(filePath, logger) {
|
|
96
145
|
let raw;
|
|
97
146
|
try {
|
|
98
147
|
raw = (0, node_fs.readFileSync)(filePath, "utf-8");
|
|
99
148
|
} catch (err) {
|
|
100
149
|
warn(logger, `Could not read file ${filePath}:`, err);
|
|
101
|
-
return
|
|
150
|
+
return null;
|
|
102
151
|
}
|
|
103
|
-
let parsed;
|
|
104
152
|
try {
|
|
105
|
-
|
|
153
|
+
return { value: JSON.parse(raw) };
|
|
106
154
|
} catch (err) {
|
|
107
155
|
warn(logger, `Invalid JSON in ${filePath}:`, err);
|
|
108
|
-
return
|
|
156
|
+
return null;
|
|
109
157
|
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* `parsed` is a JSON object with an own top-level `mcpFakes` key.
|
|
161
|
+
*
|
|
162
|
+
* @internal Shared with fixture-loader-services.ts.
|
|
163
|
+
*/
|
|
164
|
+
function hasMcpFakesKey(parsed) {
|
|
165
|
+
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) && Object.prototype.hasOwnProperty.call(parsed, "mcpFakes");
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* The LLM fixtures of a parsed file. A missing or non-array `fixtures` is
|
|
169
|
+
* warned and gives none, except that a file with `mcpFakes` may leave
|
|
170
|
+
* `fixtures` out (`fixturesOptional`, spec 5.4). An entry whose `match` is
|
|
171
|
+
* not an object is skipped with a warning; any other bad entry throws.
|
|
172
|
+
*
|
|
173
|
+
* @internal Shared with fixture-loader-services.ts.
|
|
174
|
+
*/
|
|
175
|
+
function fixturesOf(parsed, filePath, logger, liveOptions, fixturesOptional, source = filePath) {
|
|
176
|
+
if (fixturesOptional && typeof parsed === "object" && parsed !== null && !Object.prototype.hasOwnProperty.call(parsed, "fixtures")) return [];
|
|
110
177
|
if (typeof parsed !== "object" || parsed === null || !Array.isArray(parsed.fixtures)) {
|
|
111
178
|
warn(logger, `Missing or invalid "fixtures" array in ${filePath}`);
|
|
112
179
|
return [];
|
|
113
180
|
}
|
|
114
|
-
|
|
181
|
+
const fixtures = [];
|
|
182
|
+
for (const [index, entry] of parsed.fixtures.entries()) try {
|
|
183
|
+
fixtures.push(entryToFixture(entry, logger, liveOptions, {
|
|
184
|
+
file: source,
|
|
185
|
+
index
|
|
186
|
+
}));
|
|
187
|
+
} catch (error) {
|
|
188
|
+
if (!(error instanceof InvalidFixtureMatchError)) throw error;
|
|
189
|
+
warn(logger, `Skipping fixture at index ${index} in ${filePath}: ${error.message}`);
|
|
190
|
+
}
|
|
191
|
+
return fixtures;
|
|
115
192
|
}
|
|
116
|
-
|
|
193
|
+
/**
|
|
194
|
+
* B13: the old loaders return LLM fixtures only, so a file with `mcpFakes`
|
|
195
|
+
* fails loud instead of losing its fakes.
|
|
196
|
+
*/
|
|
197
|
+
function cannotCarryFakes(filePath) {
|
|
198
|
+
return new FixtureLoadError({
|
|
199
|
+
rule: "mcp-fakes/loader-cannot-carry-fakes",
|
|
200
|
+
file: filePath,
|
|
201
|
+
blockId: null,
|
|
202
|
+
entryId: null,
|
|
203
|
+
detail: require_message_text.msg`top-level "mcpFakes" key: loadFixtureFile and loadFixturesFromDir cannot carry MCP fakes; use loadFixtureFileWithServices or loadFixturesFromDirWithServices, or LLMock.loadFixtureFile or LLMock.loadFixtureDir`
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Load the LLM fixtures of one file. Throws a `FixtureLoadError` (rule
|
|
208
|
+
* `mcp-fakes/loader-cannot-carry-fakes`) when the file has a top-level
|
|
209
|
+
* `mcpFakes` key; use `loadFixtureFileWithServices` (fixture-loader-services.ts) for such files.
|
|
210
|
+
*/
|
|
211
|
+
function loadFixtureFile(filePath, logger, liveOptions) {
|
|
212
|
+
return loadLlmFixtureFile(filePath, filePath, logger, liveOptions);
|
|
213
|
+
}
|
|
214
|
+
function loadLlmFixtureFile(filePath, source, logger, liveOptions) {
|
|
215
|
+
const read = readFixtureJson(filePath, logger);
|
|
216
|
+
if (read === null) return [];
|
|
217
|
+
if (hasMcpFakesKey(read.value)) throw cannotCarryFakes(filePath);
|
|
218
|
+
return fixturesOf(read.value, filePath, logger, liveOptions, false, source);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* The `.json` files (sorted) and the subdirectories (sorted) of `dirPath`,
|
|
222
|
+
* or `null` when it cannot be read (warned).
|
|
223
|
+
*
|
|
224
|
+
* @internal Shared with fixture-loader-services.ts.
|
|
225
|
+
*/
|
|
226
|
+
function listFixtureDir(dirPath, logger) {
|
|
117
227
|
let entries;
|
|
118
228
|
try {
|
|
119
229
|
entries = (0, node_fs.readdirSync)(dirPath);
|
|
120
230
|
} catch (err) {
|
|
121
231
|
warn(logger, `Could not read directory ${dirPath}:`, err);
|
|
122
|
-
return
|
|
232
|
+
return null;
|
|
123
233
|
}
|
|
124
234
|
const jsonFiles = [];
|
|
125
235
|
const subdirs = [];
|
|
@@ -137,15 +247,34 @@ function loadFixturesFromDir(dirPath, logger, liveOptions) {
|
|
|
137
247
|
if (name.endsWith(".json")) jsonFiles.push(name);
|
|
138
248
|
}
|
|
139
249
|
jsonFiles.sort();
|
|
250
|
+
subdirs.sort();
|
|
251
|
+
return {
|
|
252
|
+
jsonFiles,
|
|
253
|
+
subdirs
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Load the LLM fixtures of every `.json` file under `dirPath`. Throws a
|
|
258
|
+
* `FixtureLoadError` (rule `mcp-fakes/loader-cannot-carry-fakes`) on the
|
|
259
|
+
* first file with a top-level `mcpFakes` key; use
|
|
260
|
+
* `loadFixturesFromDirWithServices` (fixture-loader-services.ts) for such
|
|
261
|
+
* directories.
|
|
262
|
+
*/
|
|
263
|
+
function loadFixturesFromDir(dirPath, logger, liveOptions) {
|
|
264
|
+
return loadLlmFixtureDir(dirPath, "", logger, liveOptions);
|
|
265
|
+
}
|
|
266
|
+
function loadLlmFixtureDir(dirPath, relDir, logger, liveOptions) {
|
|
267
|
+
const listing = listFixtureDir(dirPath, logger);
|
|
268
|
+
if (listing === null) return [];
|
|
140
269
|
const fixtures = [];
|
|
141
|
-
for (const name of jsonFiles) {
|
|
270
|
+
for (const name of listing.jsonFiles) {
|
|
142
271
|
const filePath = (0, node_path.join)(dirPath, name);
|
|
143
|
-
fixtures.push(...
|
|
272
|
+
fixtures.push(...loadLlmFixtureFile(filePath, relDir + name, logger, liveOptions));
|
|
144
273
|
}
|
|
145
|
-
subdirs.
|
|
146
|
-
for (const sub of subdirs) fixtures.push(...loadFixturesFromDir((0, node_path.join)(dirPath, sub), logger, liveOptions));
|
|
274
|
+
for (const sub of listing.subdirs) fixtures.push(...loadLlmFixtureDir((0, node_path.join)(dirPath, sub), `${relDir}${sub}/`, logger, liveOptions));
|
|
147
275
|
return fixtures;
|
|
148
276
|
}
|
|
277
|
+
const INVALID_ARGUMENTS_HINT = "to send invalid JSON on purpose, use `misbehavior: tool-args-invalid-json`";
|
|
149
278
|
/**
|
|
150
279
|
* Render a ref-carrying finding's message with each named index passed through
|
|
151
280
|
* `renderIndex`. With `String` it reproduces the message `validateFixtures`
|
|
@@ -196,6 +325,98 @@ function validateWebSearches(response, fixtureIndex, results) {
|
|
|
196
325
|
});
|
|
197
326
|
}
|
|
198
327
|
}
|
|
328
|
+
/**
|
|
329
|
+
* Path (`customToolCalls[j]` or `responsesBlocks[j]`) of the first custom
|
|
330
|
+
* tool call a static fixture response carries, or undefined. Factory
|
|
331
|
+
* responses are skipped.
|
|
332
|
+
*/
|
|
333
|
+
function firstCustomToolCallPath(response) {
|
|
334
|
+
if (response === null || typeof response !== "object") return void 0;
|
|
335
|
+
const r = response;
|
|
336
|
+
if (Array.isArray(r.customToolCalls) && r.customToolCalls.length > 0) return "customToolCalls[0]";
|
|
337
|
+
if (Array.isArray(r.responsesBlocks)) {
|
|
338
|
+
const j = r.responsesBlocks.findIndex((b) => b !== null && typeof b === "object" && b.type === "customToolCall");
|
|
339
|
+
if (j >= 0) return `responsesBlocks[${j}]`;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Checks for the OpenAI Responses keys `customToolCalls` and
|
|
344
|
+
* `responsesBlocks`. Both are new, so their findings never touch a fixture an
|
|
345
|
+
* earlier release accepted. A custom tool call takes a non-empty string
|
|
346
|
+
* `name`, a string `input` (empty: warning), no `arguments`, a string `id`
|
|
347
|
+
* when present and a non-empty string `namespace` when present.
|
|
348
|
+
* `responsesBlocks` follows the `blocks` rules plus `customToolCall` blocks,
|
|
349
|
+
* and may not be combined with `blocks`.
|
|
350
|
+
*/
|
|
351
|
+
function validateResponsesToolKeys(response, fixtureIndex, results) {
|
|
352
|
+
if (response === null || typeof response !== "object") return;
|
|
353
|
+
const r = response;
|
|
354
|
+
const error = (message) => results.push({
|
|
355
|
+
severity: "error",
|
|
356
|
+
fixtureIndex,
|
|
357
|
+
message
|
|
358
|
+
});
|
|
359
|
+
const warning = (message) => results.push({
|
|
360
|
+
severity: "warning",
|
|
361
|
+
fixtureIndex,
|
|
362
|
+
message
|
|
363
|
+
});
|
|
364
|
+
const checkCustom = (tc, path) => {
|
|
365
|
+
if (typeof tc.name !== "string" || tc.name === "") error(`${path}.name must be a non-empty string`);
|
|
366
|
+
if (typeof tc.input !== "string") error(`${path}.input must be a string for a custom tool call`);
|
|
367
|
+
else if (tc.input === "") warning(`${path}.input is empty`);
|
|
368
|
+
if (tc.arguments !== void 0) error(`${path}.arguments is not valid on a custom tool call; use input`);
|
|
369
|
+
if (tc.id !== void 0 && typeof tc.id !== "string") error(`${path}.id must be a string, got ${typeof tc.id}`);
|
|
370
|
+
if (tc.namespace !== void 0 && (typeof tc.namespace !== "string" || tc.namespace === "")) error(`${path}.namespace must be a non-empty string`);
|
|
371
|
+
};
|
|
372
|
+
if (r.customToolCalls !== void 0) if (!Array.isArray(r.customToolCalls)) error(`customToolCalls must be an array, got ${typeof r.customToolCalls}`);
|
|
373
|
+
else r.customToolCalls.forEach((entry, j) => {
|
|
374
|
+
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) {
|
|
375
|
+
error(`customToolCalls[${j}] must be an object`);
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
const tc = entry;
|
|
379
|
+
if (tc.type !== void 0 && tc.type !== "custom") error(`customToolCalls[${j}].type must be "custom" when present`);
|
|
380
|
+
checkCustom(tc, `customToolCalls[${j}]`);
|
|
381
|
+
});
|
|
382
|
+
if (r.responsesBlocks === void 0) return;
|
|
383
|
+
if (!Array.isArray(r.responsesBlocks)) {
|
|
384
|
+
error(`responsesBlocks must be an array, got ${typeof r.responsesBlocks}`);
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
if (Array.isArray(r.blocks) && r.blocks.length > 0 && r.responsesBlocks.length > 0) error("blocks and responsesBlocks cannot both be set; use responsesBlocks alone");
|
|
388
|
+
r.responsesBlocks.forEach((entry, j) => {
|
|
389
|
+
const path = `responsesBlocks[${j}]`;
|
|
390
|
+
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) {
|
|
391
|
+
error(`${path} must be an object`);
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
const block = entry;
|
|
395
|
+
if (block.type === "text") {
|
|
396
|
+
if (typeof block.text !== "string") error(`${path}.text must be a string`);
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
if (block.type === "customToolCall") {
|
|
400
|
+
checkCustom(block, path);
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
if (block.type !== "toolCall") {
|
|
404
|
+
error(`${path}.type must be "text", "toolCall" or "customToolCall", got ${JSON.stringify(block.type)}`);
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
if (typeof block.name !== "string" || block.name === "") error(`${path}.name must be a non-empty string`);
|
|
408
|
+
if (block.id !== void 0 && typeof block.id !== "string") error(`${path}.id must be a string, got ${typeof block.id}`);
|
|
409
|
+
if (block.input !== void 0) error(`${path}.input is only valid on a "customToolCall" block`);
|
|
410
|
+
if (block.namespace !== void 0 && (typeof block.namespace !== "string" || block.namespace === "")) error(`${path}.namespace must be a non-empty string`);
|
|
411
|
+
const args = block.arguments;
|
|
412
|
+
if (typeof args === "string") try {
|
|
413
|
+
JSON.parse(args);
|
|
414
|
+
} catch {
|
|
415
|
+
error(`${path}.arguments is not valid JSON: ${args}; ${INVALID_ARGUMENTS_HINT}`);
|
|
416
|
+
}
|
|
417
|
+
else if (args === null || typeof args !== "object") error(`${path}.arguments must be a string or an object`);
|
|
418
|
+
});
|
|
419
|
+
}
|
|
199
420
|
function validateBlocks(response, fixtureIndex, results) {
|
|
200
421
|
if (response.blocks === void 0) return;
|
|
201
422
|
if (!Array.isArray(response.blocks)) {
|
|
@@ -247,7 +468,7 @@ function validateBlocks(response, fixtureIndex, results) {
|
|
|
247
468
|
results.push({
|
|
248
469
|
severity: "error",
|
|
249
470
|
fixtureIndex,
|
|
250
|
-
message: `blocks[${j}].arguments is not valid JSON: ${block.arguments}`
|
|
471
|
+
message: `blocks[${j}].arguments is not valid JSON: ${block.arguments}; ${INVALID_ARGUMENTS_HINT}`
|
|
251
472
|
});
|
|
252
473
|
}
|
|
253
474
|
else if (typeof block.arguments !== "object" || block.arguments === null) results.push({
|
|
@@ -367,13 +588,14 @@ function claimOneShotError(fixtures, fixture) {
|
|
|
367
588
|
* generation means the queue was cleared or reset while the claim was parked
|
|
368
589
|
* (in the chaos-latency await) and the claim is stale — re-arming it would
|
|
369
590
|
* plant the previous test's injection in the next test's freshly reset queue.
|
|
370
|
-
* Keyed by array
|
|
371
|
-
* (`length = 0`), so the counter
|
|
591
|
+
* Keyed by the caller's array (a server's own list resolves to it): every
|
|
592
|
+
* clear path preserves the array reference (`length = 0`), so the counter
|
|
593
|
+
* follows the live queue.
|
|
372
594
|
*/
|
|
373
595
|
const fixtureQueueGeneration = /* @__PURE__ */ new WeakMap();
|
|
374
596
|
const oneShotClaimGeneration = /* @__PURE__ */ new WeakMap();
|
|
375
597
|
function queueGeneration(fixtures) {
|
|
376
|
-
return fixtureQueueGeneration.get(fixtures) ?? 0;
|
|
598
|
+
return fixtureQueueGeneration.get(require_helpers.fixtureListTarget(fixtures)) ?? 0;
|
|
377
599
|
}
|
|
378
600
|
/**
|
|
379
601
|
* Empty a fixture queue in place (array identity preserved — the running
|
|
@@ -385,7 +607,7 @@ function queueGeneration(fixtures) {
|
|
|
385
607
|
*/
|
|
386
608
|
function clearFixtureQueue(fixtures) {
|
|
387
609
|
fixtures.length = 0;
|
|
388
|
-
fixtureQueueGeneration.set(fixtures, queueGeneration(fixtures) + 1);
|
|
610
|
+
fixtureQueueGeneration.set(require_helpers.fixtureListTarget(fixtures), queueGeneration(fixtures) + 1);
|
|
389
611
|
}
|
|
390
612
|
/**
|
|
391
613
|
* Re-arm a one-shot error that was claimed for a request which then ended
|
|
@@ -429,8 +651,25 @@ function validateFixtures(fixtures, liveOptions) {
|
|
|
429
651
|
const results = [];
|
|
430
652
|
const seenUserMessages = /* @__PURE__ */ new Map();
|
|
431
653
|
for (let i = 0; i < fixtures.length; i++) {
|
|
432
|
-
const
|
|
654
|
+
const original = fixtures[i];
|
|
655
|
+
const f = responsesToolsExtendedFixtures.has(original) ? original : withoutResponsesToolsKeys(original);
|
|
433
656
|
const response = f.response;
|
|
657
|
+
const misbehaviorIssue = misbehaviorEnabledFixtures.has(original) ? require_misbehavior.validateFixtureMisbehavior(original, `fixtures[${i}].misbehavior`) : void 0;
|
|
658
|
+
if (misbehaviorIssue) results.push({
|
|
659
|
+
severity: "error",
|
|
660
|
+
fixtureIndex: i,
|
|
661
|
+
message: misbehaviorIssue.message
|
|
662
|
+
});
|
|
663
|
+
else if (misbehaviorEnabledFixtures.has(original) && f.misbehavior !== void 0) {
|
|
664
|
+
const parsed = require_misbehavior.parseMisbehavior(f.misbehavior);
|
|
665
|
+
if (parsed.ok && parsed.config.seed === void 0) {
|
|
666
|
+
for (const fault of parsed.config.faults) if (fault.rate !== void 0 && fault.rate < 1 && fault.times === void 0) results.push({
|
|
667
|
+
severity: "warning",
|
|
668
|
+
fixtureIndex: i,
|
|
669
|
+
message: "probabilistic fault without a seed is reproducible only per test id order; set seed to pin it"
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
}
|
|
434
673
|
if (typeof response !== "function" && (require_helpers.isLiveResponse(response) || f.match.endpoint === "openai-live")) try {
|
|
435
674
|
require_live_fixture.normalizeLiveFixture(response, liveOptions);
|
|
436
675
|
} catch (error) {
|
|
@@ -441,12 +680,13 @@ function validateFixtures(fixtures, liveOptions) {
|
|
|
441
680
|
});
|
|
442
681
|
}
|
|
443
682
|
if (typeof response === "function") {} else {
|
|
444
|
-
if (!require_helpers.
|
|
683
|
+
if (!require_helpers.isCombinedFixtureResponse(response) && !require_helpers.isTextResponse(response) && !require_helpers.isToolCallResponse(response) && !require_helpers.isErrorResponse(response) && !require_helpers.isEmbeddingResponse(response) && !require_helpers.isImageResponse(response) && !require_helpers.isAudioResponse(response) && !require_helpers.isTranscriptionResponse(response) && !require_helpers.isVideoResponse(response) && !require_helpers.isJSONResponse(response) && !require_helpers.isLiveResponse(response)) results.push({
|
|
445
684
|
severity: "error",
|
|
446
685
|
fixtureIndex: i,
|
|
447
686
|
message: "response is not a recognized type (must have content, toolCalls, error, embedding, image, audio, transcription, video, json, or live)"
|
|
448
687
|
});
|
|
449
|
-
const hasNonEmptyBlocks = Array.isArray(response.blocks) && response.blocks.length > 0;
|
|
688
|
+
const hasNonEmptyBlocks = Array.isArray(response.blocks) && response.blocks.length > 0 || Array.isArray(response.responsesBlocks) && response.responsesBlocks.length > 0;
|
|
689
|
+
const hasCustomToolCalls = Array.isArray(response.customToolCalls) && response.customToolCalls.length > 0;
|
|
450
690
|
if (require_helpers.isTextResponse(response)) {
|
|
451
691
|
if (response.content === "" && !hasNonEmptyBlocks) results.push({
|
|
452
692
|
severity: "error",
|
|
@@ -456,7 +696,7 @@ function validateFixtures(fixtures, liveOptions) {
|
|
|
456
696
|
validateReasoning(response, i, results);
|
|
457
697
|
validateWebSearches(response, i, results);
|
|
458
698
|
}
|
|
459
|
-
if (require_helpers.
|
|
699
|
+
if (require_helpers.isCombinedFixtureResponse(response)) {
|
|
460
700
|
if (typeof response.content === "string") {
|
|
461
701
|
if (response.content === "" && !hasNonEmptyBlocks) results.push({
|
|
462
702
|
severity: "error",
|
|
@@ -465,7 +705,7 @@ function validateFixtures(fixtures, liveOptions) {
|
|
|
465
705
|
});
|
|
466
706
|
}
|
|
467
707
|
if (Array.isArray(response.toolCalls)) {
|
|
468
|
-
if (response.toolCalls.length === 0) results.push({
|
|
708
|
+
if (response.toolCalls.length === 0 && !hasCustomToolCalls) results.push({
|
|
469
709
|
severity: "warning",
|
|
470
710
|
fixtureIndex: i,
|
|
471
711
|
message: "toolCalls array is empty — fixture will never produce tool calls"
|
|
@@ -483,7 +723,7 @@ function validateFixtures(fixtures, liveOptions) {
|
|
|
483
723
|
results.push({
|
|
484
724
|
severity: "error",
|
|
485
725
|
fixtureIndex: i,
|
|
486
|
-
message: `toolCalls[${j}].arguments is not valid JSON: ${tc.arguments}`
|
|
726
|
+
message: `toolCalls[${j}].arguments is not valid JSON: ${tc.arguments}; ${INVALID_ARGUMENTS_HINT}`
|
|
487
727
|
});
|
|
488
728
|
}
|
|
489
729
|
}
|
|
@@ -492,8 +732,9 @@ function validateFixtures(fixtures, liveOptions) {
|
|
|
492
732
|
validateWebSearches(response, i, results);
|
|
493
733
|
}
|
|
494
734
|
validateBlocks(response, i, results);
|
|
735
|
+
validateResponsesToolKeys(response, i, results);
|
|
495
736
|
if (require_helpers.isToolCallResponse(response)) {
|
|
496
|
-
if (response.toolCalls.length === 0) results.push({
|
|
737
|
+
if (response.toolCalls.length === 0 && !hasCustomToolCalls) results.push({
|
|
497
738
|
severity: "warning",
|
|
498
739
|
fixtureIndex: i,
|
|
499
740
|
message: "toolCalls array is empty — fixture will never produce tool calls"
|
|
@@ -511,7 +752,7 @@ function validateFixtures(fixtures, liveOptions) {
|
|
|
511
752
|
results.push({
|
|
512
753
|
severity: "error",
|
|
513
754
|
fixtureIndex: i,
|
|
514
|
-
message: `toolCalls[${j}].arguments is not valid JSON: ${tc.arguments}`
|
|
755
|
+
message: `toolCalls[${j}].arguments is not valid JSON: ${tc.arguments}; ${INVALID_ARGUMENTS_HINT}`
|
|
515
756
|
});
|
|
516
757
|
}
|
|
517
758
|
}
|
|
@@ -562,7 +803,7 @@ function validateFixtures(fixtures, liveOptions) {
|
|
|
562
803
|
message: `audio.contentType must be a string, got ${typeof audioObj.contentType}`
|
|
563
804
|
});
|
|
564
805
|
}
|
|
565
|
-
if (require_helpers.isTextResponse(response) || require_helpers.isToolCallResponse(response) || require_helpers.
|
|
806
|
+
if (require_helpers.isTextResponse(response) || require_helpers.isToolCallResponse(response) || require_helpers.isCombinedFixtureResponse(response)) {
|
|
566
807
|
const r = response;
|
|
567
808
|
if (r.id !== void 0 && typeof r.id !== "string") results.push({
|
|
568
809
|
severity: "error",
|
|
@@ -732,6 +973,29 @@ function validateFixtures(fixtures, liveOptions) {
|
|
|
732
973
|
message: "match.toolResultContains must be a non-empty string"
|
|
733
974
|
});
|
|
734
975
|
}
|
|
976
|
+
if (f.match.toolNamespace !== void 0) {
|
|
977
|
+
if (typeof f.match.toolNamespace !== "string") results.push({
|
|
978
|
+
severity: "error",
|
|
979
|
+
fixtureIndex: i,
|
|
980
|
+
message: `match.toolNamespace must be a string, got ${typeof f.match.toolNamespace}`
|
|
981
|
+
});
|
|
982
|
+
else if (f.match.toolNamespace.length === 0) results.push({
|
|
983
|
+
severity: "error",
|
|
984
|
+
fixtureIndex: i,
|
|
985
|
+
message: "match.toolNamespace must be a non-empty string"
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
if (typeof f.match.toolNamespace === "string" && f.match.toolNamespace !== "" && f.match.endpoint !== void 0 && f.match.endpoint !== "chat") results.push({
|
|
989
|
+
severity: "warning",
|
|
990
|
+
fixtureIndex: i,
|
|
991
|
+
message: `match.toolNamespace never matches with endpoint ${JSON.stringify(f.match.endpoint)} — only OpenAI Responses requests (endpoint "chat") carry tool namespaces`
|
|
992
|
+
});
|
|
993
|
+
const customCallPath = f.match.endpoint !== void 0 && f.match.endpoint !== "chat" ? firstCustomToolCallPath(f.response) : void 0;
|
|
994
|
+
if (customCallPath !== void 0) results.push({
|
|
995
|
+
severity: "warning",
|
|
996
|
+
fixtureIndex: i,
|
|
997
|
+
message: `${customCallPath} is a custom tool call, which only OpenAI Responses requests (endpoint "chat") can carry — endpoint ${JSON.stringify(f.match.endpoint)} never serves it, so a request that matches this fixture gets an error instead`
|
|
998
|
+
});
|
|
735
999
|
if (f.match.systemMessage !== void 0) {
|
|
736
1000
|
const sm = f.match.systemMessage;
|
|
737
1001
|
if (typeof sm === "string") {} else if (Array.isArray(sm)) {
|
|
@@ -772,7 +1036,8 @@ function validateFixtures(fixtures, liveOptions) {
|
|
|
772
1036
|
m.context,
|
|
773
1037
|
m.sequenceIndex,
|
|
774
1038
|
m.turnIndex,
|
|
775
|
-
m.hasToolResult
|
|
1039
|
+
m.hasToolResult,
|
|
1040
|
+
...m.toolNamespace !== void 0 ? [`toolNamespace=${m.toolNamespace}`] : []
|
|
776
1041
|
].map((v) => v === void 0 ? "" : String(v)).join("|");
|
|
777
1042
|
const prev = seenUserMessages.get(dedupKey);
|
|
778
1043
|
if (prev !== void 0) {
|
|
@@ -790,7 +1055,7 @@ function validateFixtures(fixtures, liveOptions) {
|
|
|
790
1055
|
} else seenUserMessages.set(dedupKey, i);
|
|
791
1056
|
}
|
|
792
1057
|
const match = f.match;
|
|
793
|
-
if (!(match.endpoint !== void 0 || match.context !== void 0 || match.userMessage !== void 0 || match.systemMessage !== void 0 || match.inputText !== void 0 || match.responseFormat !== void 0 || match.toolCallId !== void 0 || match.toolResultContains !== void 0 || match.toolName !== void 0 || match.model !== void 0 || match.predicate !== void 0 || match.turnIndex !== void 0 || match.sequenceIndex !== void 0 || match.hasToolResult !== void 0) && i < fixtures.length - 1) {
|
|
1058
|
+
if (!(match.endpoint !== void 0 || match.context !== void 0 || match.userMessage !== void 0 || match.systemMessage !== void 0 || match.inputText !== void 0 || match.responseFormat !== void 0 || match.toolCallId !== void 0 || match.toolResultContains !== void 0 || match.toolName !== void 0 || match.toolNamespace !== void 0 || match.model !== void 0 || match.predicate !== void 0 || match.turnIndex !== void 0 || match.sequenceIndex !== void 0 || match.hasToolResult !== void 0) && i < fixtures.length - 1) {
|
|
794
1059
|
const ref = {
|
|
795
1060
|
rule: "catch-all-not-last",
|
|
796
1061
|
shadowsFrom: i + 1,
|
|
@@ -806,19 +1071,277 @@ function validateFixtures(fixtures, liveOptions) {
|
|
|
806
1071
|
}
|
|
807
1072
|
return results;
|
|
808
1073
|
}
|
|
1074
|
+
/**
|
|
1075
|
+
* `text` with every run of line breaks, and the spaces around it, folded to
|
|
1076
|
+
* one space: CR, LF, VT, FF, NEL, and the Unicode line and paragraph
|
|
1077
|
+
* separators.
|
|
1078
|
+
*/
|
|
1079
|
+
function oneLine(text) {
|
|
1080
|
+
return text.replace(/\s*[\r\n\v\f\u0085\u2028\u2029]+\s*/g, " ");
|
|
1081
|
+
}
|
|
1082
|
+
/**
|
|
1083
|
+
* The `detail` as a `FixtureLoadError` message adds it: built in a budget of
|
|
1084
|
+
* its own, cut to at most `MCP_FAKES_ECHO_LIMIT` chars in all, with each of
|
|
1085
|
+
* its user parts cut once. A text detail is folded onto one line, gets the
|
|
1086
|
+
* escaping of every JSON text part (`jsonText`: each control char left, C0,
|
|
1087
|
+
* DEL or C1, and the line and paragraph separators as `\uXXXX`) and is cut
|
|
1088
|
+
* as JSON text (it is
|
|
1089
|
+
* made of fixed text, paths and quoted values, where a backslash only starts
|
|
1090
|
+
* a JSON escape; a stray one only moves the cut back a few chars).
|
|
1091
|
+
*/
|
|
1092
|
+
function capPart(detail) {
|
|
1093
|
+
return require_message_text.within(require_constants.MCP_FAKES_ECHO_LIMIT, typeof detail === "string" ? require_message_text.msg`${require_message_text.jsonText(oneLine(detail))}` : detail);
|
|
1094
|
+
}
|
|
1095
|
+
/**
|
|
1096
|
+
* One `file`, `blockId` or `entryId` as the message names it: JSON-quoted
|
|
1097
|
+
* (control chars escaped, so a name can neither break the line nor pose as
|
|
1098
|
+
* the message layout), and cut once to `MCP_FAKES_ECHO_LIMIT` chars at most.
|
|
1099
|
+
* An empty string is `""`, so the message names every part `toJSON()` keeps.
|
|
1100
|
+
*/
|
|
1101
|
+
function namePart(text) {
|
|
1102
|
+
return require_message_text.msg`${require_message_text.quote(text)}`;
|
|
1103
|
+
}
|
|
1104
|
+
/**
|
|
1105
|
+
* The message of a `FixtureLoadError` or `MisbehaviorConfigError`: the
|
|
1106
|
+
* `file`, every non-null `blockId` and `entryId`, then `[rule] detail`.
|
|
1107
|
+
*/
|
|
1108
|
+
function loadErrorMessage(init) {
|
|
1109
|
+
return oneLine(require_message_text.build(require_message_text.msg`${init.file === null ? require_message_text.msg`<no file>` : namePart(init.file)}${init.blockId == null ? require_message_text.msg`` : require_message_text.msg`, block ${namePart(init.blockId)}`}${init.entryId == null ? require_message_text.msg`` : require_message_text.msg`, entry ${namePart(init.entryId)}`}: [${require_message_text.fixed(init.rule)}] ${capPart(init.detail)}`));
|
|
1110
|
+
}
|
|
1111
|
+
/**
|
|
1112
|
+
* Thrown for a fixture-load case aimock cannot honor (fail-loud rule). Only
|
|
1113
|
+
* MCP fakes use it (misbehavior throws its own `MisbehaviorConfigError`);
|
|
1114
|
+
* other fixture-loader paths log warnings.
|
|
1115
|
+
* `blockId` and `entryId` are own properties only when supplied, so
|
|
1116
|
+
* `toJSON()` (the control API's HTTP 400 `details`) omits them otherwise.
|
|
1117
|
+
* The message names `file` and every non-null `blockId` and `entryId`, an
|
|
1118
|
+
* empty string as `""`, so it agrees with `toJSON()`. `options.cause` (the
|
|
1119
|
+
* standard `ErrorOptions`) keeps the underlying error, such as a JSON parse
|
|
1120
|
+
* failure; `toJSON()` leaves it out.
|
|
1121
|
+
*/
|
|
1122
|
+
var FixtureLoadError = class extends Error {
|
|
1123
|
+
/** Typed `string` so a subclass can set its own name. */
|
|
1124
|
+
name = "FixtureLoadError";
|
|
1125
|
+
rule;
|
|
1126
|
+
file;
|
|
1127
|
+
constructor(init, options) {
|
|
1128
|
+
super(loadErrorMessage(init), options);
|
|
1129
|
+
this.rule = init.rule;
|
|
1130
|
+
this.file = init.file;
|
|
1131
|
+
if (init.blockId !== void 0) Object.defineProperty(this, "blockId", {
|
|
1132
|
+
value: init.blockId,
|
|
1133
|
+
enumerable: true,
|
|
1134
|
+
writable: false
|
|
1135
|
+
});
|
|
1136
|
+
if (init.entryId !== void 0) Object.defineProperty(this, "entryId", {
|
|
1137
|
+
value: init.entryId,
|
|
1138
|
+
enumerable: true,
|
|
1139
|
+
writable: false
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
1142
|
+
toJSON() {
|
|
1143
|
+
const json = {
|
|
1144
|
+
name: this.name,
|
|
1145
|
+
rule: this.rule,
|
|
1146
|
+
file: this.file,
|
|
1147
|
+
message: this.message
|
|
1148
|
+
};
|
|
1149
|
+
if (this.blockId !== void 0) json.blockId = this.blockId;
|
|
1150
|
+
if (this.entryId !== void 0) json.entryId = this.entryId;
|
|
1151
|
+
return json;
|
|
1152
|
+
}
|
|
1153
|
+
};
|
|
1154
|
+
/**
|
|
1155
|
+
* Thrown for an invalid fixture `misbehavior` key, or one that cannot apply
|
|
1156
|
+
* to its fixture, on a server with misbehavior enabled (`enableMisbehavior:
|
|
1157
|
+
* true`, CLI `--misbehavior`). Without that opt-in the key is unused data
|
|
1158
|
+
* and nothing throws. The message has the `FixtureLoadError` layout:
|
|
1159
|
+
* `"<file>": [<rule>] <detail>`.
|
|
1160
|
+
*/
|
|
1161
|
+
var MisbehaviorConfigError = class extends Error {
|
|
1162
|
+
name = "MisbehaviorConfigError";
|
|
1163
|
+
rule;
|
|
1164
|
+
file;
|
|
1165
|
+
constructor(init) {
|
|
1166
|
+
super(loadErrorMessage(init));
|
|
1167
|
+
this.rule = init.rule;
|
|
1168
|
+
this.file = init.file;
|
|
1169
|
+
}
|
|
1170
|
+
toJSON() {
|
|
1171
|
+
return {
|
|
1172
|
+
name: this.name,
|
|
1173
|
+
rule: this.rule,
|
|
1174
|
+
file: this.file,
|
|
1175
|
+
message: this.message
|
|
1176
|
+
};
|
|
1177
|
+
}
|
|
1178
|
+
};
|
|
1179
|
+
const heldFixtureMisbehavior = /* @__PURE__ */ new WeakMap();
|
|
1180
|
+
const responsesToolsExtendedFixtures = /* @__PURE__ */ new WeakSet();
|
|
1181
|
+
const heldResponsesTools = /* @__PURE__ */ new WeakMap();
|
|
1182
|
+
/**
|
|
1183
|
+
* @internal Mark a fixture for a server with `responsesTools: "extended"`,
|
|
1184
|
+
* where that server made the fixture itself (its own load, `--validate`, the
|
|
1185
|
+
* control API): the held `match.toolNamespace` is applied and
|
|
1186
|
+
* `customToolCalls` / `responsesBlocks` are normalized in place, and
|
|
1187
|
+
* `validateFixtures` checks those keys. Idempotent. A fixture the caller
|
|
1188
|
+
* passed in is never marked: an extended server reads it through
|
|
1189
|
+
* {@link responsesToolsExtendedView}, so another server sharing it still sees
|
|
1190
|
+
* it as 1.44.0 loaded it.
|
|
1191
|
+
*/
|
|
1192
|
+
function markFixtureResponsesToolsExtended(fixture) {
|
|
1193
|
+
responsesToolsExtendedFixtures.add(fixture);
|
|
1194
|
+
const held = heldResponsesTools.get(fixture);
|
|
1195
|
+
if (held === void 0) return;
|
|
1196
|
+
heldResponsesTools.delete(fixture);
|
|
1197
|
+
if (held.toolNamespace !== void 0) fixture.match = withHeldToolNamespace(fixture.match, held.toolNamespace);
|
|
1198
|
+
if (held.normalize) normalizeResponsesToolsKeys(fixture.response);
|
|
1199
|
+
}
|
|
1200
|
+
/**
|
|
1201
|
+
* `match` with `toolNamespace` after `toolName`, in the same key order the
|
|
1202
|
+
* listing and journal have always shown in extended mode.
|
|
1203
|
+
*/
|
|
1204
|
+
function withHeldToolNamespace(match, toolNamespace) {
|
|
1205
|
+
const rebuilt = {};
|
|
1206
|
+
for (const [key, value] of Object.entries(match)) {
|
|
1207
|
+
rebuilt[key] = value;
|
|
1208
|
+
if (key === "toolName") rebuilt.toolNamespace = toolNamespace;
|
|
1209
|
+
}
|
|
1210
|
+
if (!("toolNamespace" in rebuilt)) rebuilt.toolNamespace = toolNamespace;
|
|
1211
|
+
return rebuilt;
|
|
1212
|
+
}
|
|
1213
|
+
const extendedViews = /* @__PURE__ */ new WeakMap();
|
|
1214
|
+
/** Each extended view's fixture, so identity bookkeeping can name the caller's object. */
|
|
1215
|
+
const extendedViewSources = /* @__PURE__ */ new WeakMap();
|
|
1216
|
+
/**
|
|
1217
|
+
* @internal The fixture an extended view was made from
|
|
1218
|
+
* ({@link responsesToolsExtendedView}); any other fixture is itself. An
|
|
1219
|
+
* extended server counts and journals the caller's fixture, not its view, so
|
|
1220
|
+
* the identity APIs (`getFixtureMatchCount`, `findByFixture`, the count-map
|
|
1221
|
+
* keys, `JournalEntry.response.fixture`) take the object the caller passed in.
|
|
1222
|
+
*/
|
|
1223
|
+
function responsesToolsViewSource(fixture) {
|
|
1224
|
+
return extendedViewSources.get(fixture) ?? fixture;
|
|
1225
|
+
}
|
|
1226
|
+
/**
|
|
1227
|
+
* @internal The fixture as a server with `responsesTools: "extended"` reads
|
|
1228
|
+
* it. A fixture with held keys gets a separate object, one per fixture, with
|
|
1229
|
+
* `match.toolNamespace` applied and `customToolCalls` / `responsesBlocks`
|
|
1230
|
+
* normalized, as {@link markFixtureResponsesToolsExtended} would leave it.
|
|
1231
|
+
* The fixture itself is not changed, so a legacy server that shares it is
|
|
1232
|
+
* unaffected. Every other property is read from the fixture on each call.
|
|
1233
|
+
* A fixture with nothing held is returned as it is.
|
|
1234
|
+
*/
|
|
1235
|
+
function responsesToolsExtendedView(fixture) {
|
|
1236
|
+
const held = heldResponsesTools.get(fixture);
|
|
1237
|
+
if (held === void 0) return fixture;
|
|
1238
|
+
let cached = extendedViews.get(fixture);
|
|
1239
|
+
if (cached === void 0) {
|
|
1240
|
+
cached = { view: {} };
|
|
1241
|
+
responsesToolsExtendedFixtures.add(cached.view);
|
|
1242
|
+
extendedViewSources.set(cached.view, fixture);
|
|
1243
|
+
extendedViews.set(fixture, cached);
|
|
1244
|
+
}
|
|
1245
|
+
if (cached.viewMatch === void 0 || cached.match !== fixture.match) {
|
|
1246
|
+
cached.match = fixture.match;
|
|
1247
|
+
cached.viewMatch = held.toolNamespace !== void 0 ? withHeldToolNamespace(fixture.match, held.toolNamespace) : fixture.match;
|
|
1248
|
+
}
|
|
1249
|
+
if (!("viewResponse" in cached) || cached.response !== fixture.response) {
|
|
1250
|
+
cached.response = fixture.response;
|
|
1251
|
+
let viewResponse = fixture.response;
|
|
1252
|
+
if (held.normalize && typeof viewResponse === "object" && viewResponse !== null) {
|
|
1253
|
+
const copy = { ...viewResponse };
|
|
1254
|
+
normalizeResponsesToolsKeys(copy);
|
|
1255
|
+
viewResponse = copy;
|
|
1256
|
+
}
|
|
1257
|
+
cached.viewResponse = viewResponse;
|
|
1258
|
+
}
|
|
1259
|
+
const view = cached.view;
|
|
1260
|
+
const source = fixture;
|
|
1261
|
+
for (const key of Object.keys(view)) if (!(key in source)) delete view[key];
|
|
1262
|
+
for (const key of Object.keys(source)) view[key] = key === "match" ? cached.viewMatch : key === "response" ? cached.viewResponse : source[key];
|
|
1263
|
+
require_misbehavior.copyFixtureMisbehaviorPosition(fixture, cached.view);
|
|
1264
|
+
return cached.view;
|
|
1265
|
+
}
|
|
1266
|
+
/**
|
|
1267
|
+
* The fixture as 1.44.0 saw it: without `match.toolNamespace`,
|
|
1268
|
+
* `customToolCalls` and `responsesBlocks`. Returns the same object when none
|
|
1269
|
+
* is set; factory responses are left as they are.
|
|
1270
|
+
*/
|
|
1271
|
+
function withoutResponsesToolsKeys(fixture) {
|
|
1272
|
+
let match = fixture.match;
|
|
1273
|
+
if ("toolNamespace" in match) {
|
|
1274
|
+
const copy = { ...match };
|
|
1275
|
+
delete copy.toolNamespace;
|
|
1276
|
+
match = copy;
|
|
1277
|
+
}
|
|
1278
|
+
let response = fixture.response;
|
|
1279
|
+
if (typeof response !== "function" && response !== null && typeof response === "object" && ("customToolCalls" in response || "responsesBlocks" in response)) {
|
|
1280
|
+
const copy = { ...response };
|
|
1281
|
+
delete copy.customToolCalls;
|
|
1282
|
+
delete copy.responsesBlocks;
|
|
1283
|
+
response = copy;
|
|
1284
|
+
}
|
|
1285
|
+
if (match === fixture.match && response === fixture.response) return fixture;
|
|
1286
|
+
return {
|
|
1287
|
+
...fixture,
|
|
1288
|
+
match,
|
|
1289
|
+
response
|
|
1290
|
+
};
|
|
1291
|
+
}
|
|
1292
|
+
const misbehaviorEnabledFixtures = /* @__PURE__ */ new WeakSet();
|
|
1293
|
+
/**
|
|
1294
|
+
* @internal Recognize the `misbehavior` key a loaded fixture entry carried,
|
|
1295
|
+
* for a server with misbehavior enabled: parse it onto the fixture (in place;
|
|
1296
|
+
* the loader made the object) and check it applies, or throw
|
|
1297
|
+
* `MisbehaviorConfigError`. A fixture with no held key is left unchanged.
|
|
1298
|
+
*/
|
|
1299
|
+
function enableHeldFixtureMisbehavior(fixture) {
|
|
1300
|
+
const held = heldFixtureMisbehavior.get(fixture);
|
|
1301
|
+
if (held === void 0) return;
|
|
1302
|
+
const parsed = require_misbehavior.parseMisbehavior(held.value, held.path);
|
|
1303
|
+
if (parsed.ok) fixture.misbehavior = parsed.config;
|
|
1304
|
+
const issue = parsed.ok ? require_misbehavior.validateFixtureMisbehavior(fixture, held.path) : parsed.issue;
|
|
1305
|
+
if (issue) throw new MisbehaviorConfigError({
|
|
1306
|
+
rule: issue.rule,
|
|
1307
|
+
file: held.file,
|
|
1308
|
+
detail: issue.message
|
|
1309
|
+
});
|
|
1310
|
+
heldFixtureMisbehavior.delete(fixture);
|
|
1311
|
+
misbehaviorEnabledFixtures.add(fixture);
|
|
1312
|
+
}
|
|
1313
|
+
/**
|
|
1314
|
+
* @internal Mark a fixture whose `misbehavior` a server with misbehavior
|
|
1315
|
+
* enabled has recognized, so `validateFixtures` checks it.
|
|
1316
|
+
*/
|
|
1317
|
+
function markFixtureMisbehaviorEnabled(fixture) {
|
|
1318
|
+
misbehaviorEnabledFixtures.add(fixture);
|
|
1319
|
+
}
|
|
809
1320
|
|
|
810
1321
|
//#endregion
|
|
1322
|
+
exports.FixtureLoadError = FixtureLoadError;
|
|
811
1323
|
exports.INJECTED_STATUS_RANGE = INJECTED_STATUS_RANGE;
|
|
1324
|
+
exports.MisbehaviorConfigError = MisbehaviorConfigError;
|
|
812
1325
|
exports.claimOneShotError = claimOneShotError;
|
|
813
1326
|
exports.clearFixtureQueue = clearFixtureQueue;
|
|
1327
|
+
exports.enableHeldFixtureMisbehavior = enableHeldFixtureMisbehavior;
|
|
814
1328
|
exports.entryToFixture = entryToFixture;
|
|
1329
|
+
exports.fixturesOf = fixturesOf;
|
|
1330
|
+
exports.hasMcpFakesKey = hasMcpFakesKey;
|
|
815
1331
|
exports.isInjectableStatus = isInjectableStatus;
|
|
816
1332
|
exports.isOneShotError = isOneShotError;
|
|
1333
|
+
exports.listFixtureDir = listFixtureDir;
|
|
817
1334
|
exports.loadFixtureFile = loadFixtureFile;
|
|
818
1335
|
exports.loadFixturesFromDir = loadFixturesFromDir;
|
|
1336
|
+
exports.markFixtureMisbehaviorEnabled = markFixtureMisbehaviorEnabled;
|
|
1337
|
+
exports.markFixtureResponsesToolsExtended = markFixtureResponsesToolsExtended;
|
|
819
1338
|
exports.normalizeResponse = normalizeResponse;
|
|
1339
|
+
exports.normalizeResponsesToolsKeys = normalizeResponsesToolsKeys;
|
|
820
1340
|
exports.queueOneShotError = queueOneShotError;
|
|
1341
|
+
exports.readFixtureJson = readFixtureJson;
|
|
821
1342
|
exports.releaseOneShotError = releaseOneShotError;
|
|
822
1343
|
exports.renderValidationRef = renderValidationRef;
|
|
1344
|
+
exports.responsesToolsExtendedView = responsesToolsExtendedView;
|
|
1345
|
+
exports.responsesToolsViewSource = responsesToolsViewSource;
|
|
823
1346
|
exports.validateFixtures = validateFixtures;
|
|
824
1347
|
//# sourceMappingURL=fixture-loader.cjs.map
|