@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
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { extractOverrides, flattenHeaders, generateToolCallId, getContext, getTestId,
|
|
1
|
+
import { extractOverrides, flattenHeaders, generateToolCallId, getContext, getTestId, isCombinedFixtureResponse, isErrorResponse, isJsonObject, isTextResponse, isToolCallResponse, prepareOpenAIChatMisbehavior, requireEmittedFunctionToolCalls, resolveFixtureBlockOutcome, resolveOpenAIChatMisbehaviorUsage, resolveResponse, resolveStrictMode, servedToolArgs, strictNoMatchLogLine, strictNoMatchMessage, strictOverrideField } from "./helpers.js";
|
|
2
2
|
import { calculateDelay, delay, writeErrorResponse } from "./sse-writer.js";
|
|
3
3
|
import { applyChaosAsync } from "./chaos.js";
|
|
4
|
+
import { planMisbehavior, recordMisbehaviorOutcome } from "./misbehavior.js";
|
|
4
5
|
import { matchFixtureDiagnostic } from "./router.js";
|
|
5
6
|
import { proxyAndRecord } from "./recorder.js";
|
|
6
7
|
import { createInterruptionSignal } from "./interruption.js";
|
|
@@ -22,6 +23,29 @@ const STEP_TYPES = new Set([
|
|
|
22
23
|
"model_output",
|
|
23
24
|
...STEP_RESULT_TYPES
|
|
24
25
|
]);
|
|
26
|
+
function validateInteractionsInput(input) {
|
|
27
|
+
if (typeof input === "number") return "input must not be a number";
|
|
28
|
+
if (!Array.isArray(input)) return null;
|
|
29
|
+
const first = input[0];
|
|
30
|
+
if (isJsonObject(first) && "role" in first) for (const [index, turn] of input.entries()) {
|
|
31
|
+
if (!isJsonObject(turn)) continue;
|
|
32
|
+
const blocks = turn.content ?? turn.parts;
|
|
33
|
+
if (typeof blocks === "string" && blocks.length > 0) return `input[${index}].${turn.content != null ? "content" : "parts"} must be an array`;
|
|
34
|
+
}
|
|
35
|
+
else if (!(isJsonObject(first) && typeof first.type === "string" && STEP_TYPES.has(first.type))) {
|
|
36
|
+
const nullIndex = input.findIndex((part) => part === null);
|
|
37
|
+
if (nullIndex !== -1) return `input[${nullIndex}] must be an object`;
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
function validateInteractionsTools(tools) {
|
|
42
|
+
if (typeof tools === "string" && tools.length > 0) return "tools must be an array";
|
|
43
|
+
if (Array.isArray(tools)) {
|
|
44
|
+
const nullIndex = tools.findIndex((tool) => tool === null);
|
|
45
|
+
if (nullIndex !== -1) return `tools[${nullIndex}] must be an object`;
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
25
49
|
function geminiInteractionsToCompletionRequest(req) {
|
|
26
50
|
const messages = [];
|
|
27
51
|
const model = req.model ?? "gemini-2.5-flash";
|
|
@@ -192,18 +216,12 @@ function buildInteractionsTextResponse(content, model, interactionId, overrides)
|
|
|
192
216
|
};
|
|
193
217
|
}
|
|
194
218
|
function buildFunctionCallStep(tc, logger) {
|
|
195
|
-
|
|
196
|
-
try {
|
|
197
|
-
argsObj = JSON.parse(tc.arguments || "{}");
|
|
198
|
-
} catch {
|
|
199
|
-
logger.warn(`Malformed JSON in fixture tool call arguments for "${tc.name}": ${tc.arguments}`);
|
|
200
|
-
argsObj = {};
|
|
201
|
-
}
|
|
219
|
+
const args = servedToolArgs(tc, "object", logger);
|
|
202
220
|
return {
|
|
203
221
|
type: "function_call",
|
|
204
222
|
id: tc.id || generateToolCallId(),
|
|
205
223
|
name: tc.name,
|
|
206
|
-
arguments:
|
|
224
|
+
arguments: args.value
|
|
207
225
|
};
|
|
208
226
|
}
|
|
209
227
|
function buildInteractionsToolCallResponse(toolCalls, model, interactionId, logger, overrides) {
|
|
@@ -337,13 +355,7 @@ function buildInteractionsToolCallSSEEvents(toolCalls, interactionId, logger, ov
|
|
|
337
355
|
});
|
|
338
356
|
for (let idx = 0; idx < toolCalls.length; idx++) {
|
|
339
357
|
const tc = toolCalls[idx];
|
|
340
|
-
|
|
341
|
-
try {
|
|
342
|
-
argsObj = JSON.parse(tc.arguments || "{}");
|
|
343
|
-
} catch {
|
|
344
|
-
logger.warn(`Malformed JSON in fixture tool call arguments for "${tc.name}": ${tc.arguments}`);
|
|
345
|
-
argsObj = {};
|
|
346
|
-
}
|
|
358
|
+
const args = servedToolArgs(tc, "string", logger);
|
|
347
359
|
events.push({
|
|
348
360
|
event_type: "step.start",
|
|
349
361
|
index: idx,
|
|
@@ -360,7 +372,7 @@ function buildInteractionsToolCallSSEEvents(toolCalls, interactionId, logger, ov
|
|
|
360
372
|
index: idx,
|
|
361
373
|
delta: {
|
|
362
374
|
type: "arguments_delta",
|
|
363
|
-
arguments:
|
|
375
|
+
arguments: args.text
|
|
364
376
|
},
|
|
365
377
|
event_id: nextEventId()
|
|
366
378
|
});
|
|
@@ -416,13 +428,7 @@ function pushTextStepEvents(events, index, content, chunkSize) {
|
|
|
416
428
|
});
|
|
417
429
|
}
|
|
418
430
|
function pushFunctionCallStepEvents(events, index, tc, logger) {
|
|
419
|
-
|
|
420
|
-
try {
|
|
421
|
-
argsObj = JSON.parse(tc.arguments || "{}");
|
|
422
|
-
} catch {
|
|
423
|
-
logger.warn(`Malformed JSON in fixture tool call arguments for "${tc.name}": ${tc.arguments}`);
|
|
424
|
-
argsObj = {};
|
|
425
|
-
}
|
|
431
|
+
const args = servedToolArgs(tc, "string", logger);
|
|
426
432
|
events.push({
|
|
427
433
|
event_type: "step.start",
|
|
428
434
|
index,
|
|
@@ -439,7 +445,7 @@ function pushFunctionCallStepEvents(events, index, tc, logger) {
|
|
|
439
445
|
index,
|
|
440
446
|
delta: {
|
|
441
447
|
type: "arguments_delta",
|
|
442
|
-
arguments:
|
|
448
|
+
arguments: args.text
|
|
443
449
|
},
|
|
444
450
|
event_id: nextEventId()
|
|
445
451
|
});
|
|
@@ -516,6 +522,35 @@ async function writeGeminiInteractionsSSEStream(res, events, optionsOrLatency) {
|
|
|
516
522
|
if (!res.writableEnded) res.end();
|
|
517
523
|
return true;
|
|
518
524
|
}
|
|
525
|
+
function prepareInteractionsMisbehavior(plan, streaming) {
|
|
526
|
+
if (!streaming && plan.summary.fault === "stop-length-mid-tool") {
|
|
527
|
+
const response = plan.response;
|
|
528
|
+
const combined = isCombinedFixtureResponse(response);
|
|
529
|
+
const outcome = combined && response.blocks?.length ? resolveFixtureBlockOutcome(response.blocks) : void 0;
|
|
530
|
+
const toolCalls = (outcome?.toolCalls ?? (combined || isToolCallResponse(response) ? response.toolCalls ?? [] : [])).filter((_, index) => index !== plan.target?.index);
|
|
531
|
+
let callIndex = 0;
|
|
532
|
+
const blocks = outcome?.ordered.filter((block) => block.type === "text" || callIndex++ !== plan.target?.index);
|
|
533
|
+
plan = {
|
|
534
|
+
...plan,
|
|
535
|
+
response: {
|
|
536
|
+
...response,
|
|
537
|
+
toolCalls,
|
|
538
|
+
...blocks ? { blocks } : {}
|
|
539
|
+
}
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
return prepareOpenAIChatMisbehavior(plan);
|
|
543
|
+
}
|
|
544
|
+
function finalizeInteractionsMisbehavior(events, plan) {
|
|
545
|
+
if (plan.kind !== "applied" || plan.summary.fault !== "stop-length-mid-tool") return events;
|
|
546
|
+
return events.map((event) => event.event_type === "interaction.completed" && isJsonObject(event.interaction) ? {
|
|
547
|
+
...event,
|
|
548
|
+
interaction: {
|
|
549
|
+
...event.interaction,
|
|
550
|
+
status: "incomplete"
|
|
551
|
+
}
|
|
552
|
+
} : event);
|
|
553
|
+
}
|
|
519
554
|
async function handleGeminiInteractions(req, res, raw, fixtures, journal, defaults, setCorsHeaders) {
|
|
520
555
|
const { logger } = defaults;
|
|
521
556
|
setCorsHeaders(res);
|
|
@@ -552,6 +587,21 @@ async function handleGeminiInteractions(req, res, raw, fixtures, journal, defaul
|
|
|
552
587
|
writeErrorResponse(res, 400, JSON.stringify(buildInteractionsErrorResponse("Request body must be a JSON object", "INVALID_ARGUMENT")));
|
|
553
588
|
return;
|
|
554
589
|
}
|
|
590
|
+
const validationError = validateInteractionsInput(interactionsReq.input) ?? validateInteractionsTools(interactionsReq.tools);
|
|
591
|
+
if (validationError) {
|
|
592
|
+
journal.add({
|
|
593
|
+
method: req.method ?? "POST",
|
|
594
|
+
path: urlPath,
|
|
595
|
+
headers: flattenHeaders(req.headers),
|
|
596
|
+
body: null,
|
|
597
|
+
response: {
|
|
598
|
+
status: 400,
|
|
599
|
+
fixture: null
|
|
600
|
+
}
|
|
601
|
+
});
|
|
602
|
+
writeErrorResponse(res, 400, JSON.stringify(buildInteractionsErrorResponse(validationError, "INVALID_ARGUMENT")));
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
555
605
|
const completionReq = geminiInteractionsToCompletionRequest(interactionsReq);
|
|
556
606
|
completionReq._endpointType = "chat";
|
|
557
607
|
completionReq._context = getContext(req);
|
|
@@ -617,29 +667,172 @@ async function handleGeminiInteractions(req, res, raw, fixtures, journal, defaul
|
|
|
617
667
|
writeErrorResponse(res, 404, JSON.stringify(buildInteractionsErrorResponse("No fixture matched", "NOT_FOUND")));
|
|
618
668
|
return;
|
|
619
669
|
}
|
|
620
|
-
|
|
670
|
+
let response = await resolveResponse(fixture, completionReq);
|
|
671
|
+
let misbehavior = planMisbehavior({
|
|
672
|
+
wire: "gemini-interactions",
|
|
673
|
+
fixture,
|
|
674
|
+
response,
|
|
675
|
+
request: completionReq,
|
|
676
|
+
stream: streaming,
|
|
677
|
+
emitsToolCallIds: true,
|
|
678
|
+
defaults,
|
|
679
|
+
rawHeaders: req.headers,
|
|
680
|
+
url: req.url
|
|
681
|
+
});
|
|
682
|
+
if (misbehavior.kind === "error") {
|
|
683
|
+
recordMisbehaviorOutcome({
|
|
684
|
+
entry: journal.add({
|
|
685
|
+
method: req.method ?? "POST",
|
|
686
|
+
path: urlPath,
|
|
687
|
+
headers: flattenHeaders(req.headers),
|
|
688
|
+
body: completionReq,
|
|
689
|
+
response: {
|
|
690
|
+
status: misbehavior.status,
|
|
691
|
+
fixture
|
|
692
|
+
}
|
|
693
|
+
}),
|
|
694
|
+
summary: misbehavior.summary,
|
|
695
|
+
defaults,
|
|
696
|
+
testId
|
|
697
|
+
});
|
|
698
|
+
if (!misbehavior.summary?.evaluations.some((evaluation) => evaluation.outcome === "error")) logger.error(`${req.method ?? "POST"} ${urlPath}: ${misbehavior.message}`);
|
|
699
|
+
writeErrorResponse(res, misbehavior.status, JSON.stringify(buildInteractionsErrorResponse(misbehavior.message, misbehavior.code)));
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
if (misbehavior.kind === "applied") {
|
|
703
|
+
misbehavior = prepareInteractionsMisbehavior(misbehavior, streaming);
|
|
704
|
+
response = misbehavior.response;
|
|
705
|
+
}
|
|
706
|
+
const appliedUsage = misbehavior.kind === "applied" ? resolveOpenAIChatMisbehaviorUsage(misbehavior, completionReq) : void 0;
|
|
621
707
|
const latency = fixture.latency ?? defaults.latency;
|
|
622
708
|
const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);
|
|
623
709
|
const replaySpeed = fixture.replaySpeed ?? defaults.replaySpeed;
|
|
624
710
|
if (isErrorResponse(response)) {
|
|
625
711
|
const status = response.status ?? 500;
|
|
626
|
-
|
|
712
|
+
recordMisbehaviorOutcome({
|
|
713
|
+
entry: journal.add({
|
|
714
|
+
method: req.method ?? "POST",
|
|
715
|
+
path: urlPath,
|
|
716
|
+
headers: flattenHeaders(req.headers),
|
|
717
|
+
body: completionReq,
|
|
718
|
+
response: {
|
|
719
|
+
status,
|
|
720
|
+
fixture
|
|
721
|
+
}
|
|
722
|
+
}),
|
|
723
|
+
summary: misbehavior.summary,
|
|
724
|
+
defaults,
|
|
725
|
+
testId
|
|
726
|
+
});
|
|
727
|
+
writeErrorResponse(res, status, JSON.stringify(buildInteractionsErrorResponse(response.error.message, response.error.type ?? "ERROR")), { retryAfter: response.retryAfter });
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
if (misbehavior.kind === "applied" && misbehavior.summary.fault === "reasoning-only") {
|
|
731
|
+
const journalEntry = journal.add({
|
|
627
732
|
method: req.method ?? "POST",
|
|
628
733
|
path: urlPath,
|
|
629
734
|
headers: flattenHeaders(req.headers),
|
|
630
735
|
body: completionReq,
|
|
631
736
|
response: {
|
|
632
|
-
status,
|
|
737
|
+
status: 200,
|
|
633
738
|
fixture
|
|
634
739
|
}
|
|
635
740
|
});
|
|
636
|
-
|
|
741
|
+
recordMisbehaviorOutcome({
|
|
742
|
+
entry: journalEntry,
|
|
743
|
+
summary: misbehavior.summary,
|
|
744
|
+
defaults,
|
|
745
|
+
testId
|
|
746
|
+
});
|
|
747
|
+
const interactionId = nextInteractionId();
|
|
748
|
+
const usage = {
|
|
749
|
+
...interactionsUsage({ usage: appliedUsage }),
|
|
750
|
+
total_output_tokens: 0,
|
|
751
|
+
total_thought_tokens: appliedUsage?.completion_tokens ?? 0
|
|
752
|
+
};
|
|
753
|
+
if (!streaming) {
|
|
754
|
+
const overrides = isTextResponse(response) || isToolCallResponse(response) || isCombinedFixtureResponse(response) ? extractOverrides(response) : void 0;
|
|
755
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
756
|
+
res.end(JSON.stringify({
|
|
757
|
+
id: interactionId,
|
|
758
|
+
model: overrides?.model ?? model,
|
|
759
|
+
status: "incomplete",
|
|
760
|
+
steps: [{
|
|
761
|
+
type: "thought",
|
|
762
|
+
signature: "",
|
|
763
|
+
summary: [{
|
|
764
|
+
type: "text",
|
|
765
|
+
text: misbehavior.reasoning ?? ""
|
|
766
|
+
}]
|
|
767
|
+
}],
|
|
768
|
+
usage
|
|
769
|
+
}));
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
const events = [
|
|
773
|
+
{
|
|
774
|
+
event_type: "interaction.created",
|
|
775
|
+
interaction: {
|
|
776
|
+
id: interactionId,
|
|
777
|
+
status: "in_progress"
|
|
778
|
+
},
|
|
779
|
+
event_id: nextEventId()
|
|
780
|
+
},
|
|
781
|
+
{
|
|
782
|
+
event_type: "step.start",
|
|
783
|
+
index: 0,
|
|
784
|
+
step: { type: "thought" },
|
|
785
|
+
event_id: nextEventId()
|
|
786
|
+
},
|
|
787
|
+
{
|
|
788
|
+
event_type: "step.delta",
|
|
789
|
+
index: 0,
|
|
790
|
+
delta: {
|
|
791
|
+
type: "thought_summary",
|
|
792
|
+
content: {
|
|
793
|
+
type: "text",
|
|
794
|
+
text: misbehavior.reasoning ?? ""
|
|
795
|
+
}
|
|
796
|
+
},
|
|
797
|
+
event_id: nextEventId()
|
|
798
|
+
},
|
|
799
|
+
{
|
|
800
|
+
event_type: "step.stop",
|
|
801
|
+
index: 0,
|
|
802
|
+
event_id: nextEventId()
|
|
803
|
+
},
|
|
804
|
+
{
|
|
805
|
+
event_type: "interaction.completed",
|
|
806
|
+
interaction: {
|
|
807
|
+
id: interactionId,
|
|
808
|
+
status: "incomplete",
|
|
809
|
+
usage
|
|
810
|
+
},
|
|
811
|
+
event_id: nextEventId()
|
|
812
|
+
}
|
|
813
|
+
];
|
|
814
|
+
const interruption = createInterruptionSignal(fixture);
|
|
815
|
+
if (!await writeGeminiInteractionsSSEStream(res, events, {
|
|
816
|
+
latency,
|
|
817
|
+
streamingProfile: fixture.streamingProfile,
|
|
818
|
+
recordedTimings: fixture.recordedTimings,
|
|
819
|
+
replaySpeed,
|
|
820
|
+
signal: interruption?.signal,
|
|
821
|
+
onChunkSent: interruption?.tick
|
|
822
|
+
})) {
|
|
823
|
+
if (!res.writableEnded) res.destroy();
|
|
824
|
+
journalEntry.response.interrupted = true;
|
|
825
|
+
journalEntry.response.interruptReason = interruption?.reason();
|
|
826
|
+
}
|
|
827
|
+
interruption?.cleanup();
|
|
637
828
|
return;
|
|
638
829
|
}
|
|
639
|
-
|
|
640
|
-
if (isContentWithToolCallsResponse(response)) {
|
|
830
|
+
if (isCombinedFixtureResponse(response)) {
|
|
641
831
|
if (response.webSearches?.length) logger.warn("webSearches in fixture response are not supported for Gemini Interactions API — ignoring");
|
|
642
|
-
const overrides =
|
|
832
|
+
const overrides = {
|
|
833
|
+
...extractOverrides(response),
|
|
834
|
+
...appliedUsage ? { usage: appliedUsage } : {}
|
|
835
|
+
};
|
|
643
836
|
const journalEntry = journal.add({
|
|
644
837
|
method: req.method ?? "POST",
|
|
645
838
|
path: urlPath,
|
|
@@ -650,14 +843,25 @@ async function handleGeminiInteractions(req, res, raw, fixtures, journal, defaul
|
|
|
650
843
|
fixture
|
|
651
844
|
}
|
|
652
845
|
});
|
|
846
|
+
recordMisbehaviorOutcome({
|
|
847
|
+
entry: journalEntry,
|
|
848
|
+
summary: misbehavior.summary,
|
|
849
|
+
defaults,
|
|
850
|
+
testId
|
|
851
|
+
});
|
|
852
|
+
const functionToolCalls = requireEmittedFunctionToolCalls(response, "Gemini Interactions");
|
|
853
|
+
const interactionId = nextInteractionId();
|
|
653
854
|
if (!streaming) {
|
|
654
|
-
const body = buildInteractionsContentWithToolCallsResponse(response.content ?? "",
|
|
855
|
+
const body = buildInteractionsContentWithToolCallsResponse(response.content ?? "", functionToolCalls, model, interactionId, logger, overrides, response.blocks);
|
|
655
856
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
656
|
-
res.end(JSON.stringify(
|
|
857
|
+
res.end(JSON.stringify(misbehavior.kind === "applied" && misbehavior.summary.fault === "stop-length-mid-tool" ? {
|
|
858
|
+
...body,
|
|
859
|
+
status: "incomplete"
|
|
860
|
+
} : body));
|
|
657
861
|
} else {
|
|
658
|
-
const events = buildInteractionsContentWithToolCallsSSEEvents(response.content ?? "",
|
|
862
|
+
const events = buildInteractionsContentWithToolCallsSSEEvents(response.content ?? "", functionToolCalls, interactionId, chunkSize, logger, overrides, response.blocks);
|
|
659
863
|
const interruption = createInterruptionSignal(fixture);
|
|
660
|
-
if (!await writeGeminiInteractionsSSEStream(res, events, {
|
|
864
|
+
if (!await writeGeminiInteractionsSSEStream(res, finalizeInteractionsMisbehavior(events, misbehavior), {
|
|
661
865
|
latency,
|
|
662
866
|
streamingProfile: fixture.streamingProfile,
|
|
663
867
|
recordedTimings: fixture.recordedTimings,
|
|
@@ -675,7 +879,10 @@ async function handleGeminiInteractions(req, res, raw, fixtures, journal, defaul
|
|
|
675
879
|
}
|
|
676
880
|
if (isTextResponse(response)) {
|
|
677
881
|
if (response.webSearches?.length) logger.warn("webSearches in fixture response are not supported for Gemini Interactions API — ignoring");
|
|
678
|
-
const overrides =
|
|
882
|
+
const overrides = {
|
|
883
|
+
...extractOverrides(response),
|
|
884
|
+
...appliedUsage ? { usage: appliedUsage } : {}
|
|
885
|
+
};
|
|
679
886
|
const journalEntry = journal.add({
|
|
680
887
|
method: req.method ?? "POST",
|
|
681
888
|
path: urlPath,
|
|
@@ -686,14 +893,24 @@ async function handleGeminiInteractions(req, res, raw, fixtures, journal, defaul
|
|
|
686
893
|
fixture
|
|
687
894
|
}
|
|
688
895
|
});
|
|
896
|
+
recordMisbehaviorOutcome({
|
|
897
|
+
entry: journalEntry,
|
|
898
|
+
summary: misbehavior.summary,
|
|
899
|
+
defaults,
|
|
900
|
+
testId
|
|
901
|
+
});
|
|
902
|
+
const interactionId = nextInteractionId();
|
|
689
903
|
if (!streaming) {
|
|
690
904
|
const body = buildInteractionsTextResponse(response.content, model, interactionId, overrides);
|
|
691
905
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
692
|
-
res.end(JSON.stringify(
|
|
906
|
+
res.end(JSON.stringify(misbehavior.kind === "applied" && misbehavior.summary.fault === "stop-length-mid-tool" ? {
|
|
907
|
+
...body,
|
|
908
|
+
status: "incomplete"
|
|
909
|
+
} : body));
|
|
693
910
|
} else {
|
|
694
911
|
const events = buildInteractionsTextSSEEvents(response.content, interactionId, chunkSize, overrides);
|
|
695
912
|
const interruption = createInterruptionSignal(fixture);
|
|
696
|
-
if (!await writeGeminiInteractionsSSEStream(res, events, {
|
|
913
|
+
if (!await writeGeminiInteractionsSSEStream(res, finalizeInteractionsMisbehavior(events, misbehavior), {
|
|
697
914
|
latency,
|
|
698
915
|
streamingProfile: fixture.streamingProfile,
|
|
699
916
|
recordedTimings: fixture.recordedTimings,
|
|
@@ -711,7 +928,10 @@ async function handleGeminiInteractions(req, res, raw, fixtures, journal, defaul
|
|
|
711
928
|
}
|
|
712
929
|
if (isToolCallResponse(response)) {
|
|
713
930
|
if (response.webSearches?.length) logger.warn("webSearches in fixture response are not supported for Gemini Interactions API — ignoring");
|
|
714
|
-
const overrides =
|
|
931
|
+
const overrides = {
|
|
932
|
+
...extractOverrides(response),
|
|
933
|
+
...appliedUsage ? { usage: appliedUsage } : {}
|
|
934
|
+
};
|
|
715
935
|
const journalEntry = journal.add({
|
|
716
936
|
method: req.method ?? "POST",
|
|
717
937
|
path: urlPath,
|
|
@@ -722,14 +942,25 @@ async function handleGeminiInteractions(req, res, raw, fixtures, journal, defaul
|
|
|
722
942
|
fixture
|
|
723
943
|
}
|
|
724
944
|
});
|
|
945
|
+
recordMisbehaviorOutcome({
|
|
946
|
+
entry: journalEntry,
|
|
947
|
+
summary: misbehavior.summary,
|
|
948
|
+
defaults,
|
|
949
|
+
testId
|
|
950
|
+
});
|
|
951
|
+
const functionToolCalls = requireEmittedFunctionToolCalls(response, "Gemini Interactions");
|
|
952
|
+
const interactionId = nextInteractionId();
|
|
725
953
|
if (!streaming) {
|
|
726
|
-
const body = buildInteractionsToolCallResponse(
|
|
954
|
+
const body = buildInteractionsToolCallResponse(functionToolCalls, model, interactionId, logger, overrides);
|
|
727
955
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
728
|
-
res.end(JSON.stringify(
|
|
956
|
+
res.end(JSON.stringify(misbehavior.kind === "applied" && misbehavior.summary.fault === "stop-length-mid-tool" ? {
|
|
957
|
+
...body,
|
|
958
|
+
status: "incomplete"
|
|
959
|
+
} : body));
|
|
729
960
|
} else {
|
|
730
|
-
const events = buildInteractionsToolCallSSEEvents(
|
|
961
|
+
const events = buildInteractionsToolCallSSEEvents(functionToolCalls, interactionId, logger, overrides);
|
|
731
962
|
const interruption = createInterruptionSignal(fixture);
|
|
732
|
-
if (!await writeGeminiInteractionsSSEStream(res, events, {
|
|
963
|
+
if (!await writeGeminiInteractionsSSEStream(res, finalizeInteractionsMisbehavior(events, misbehavior), {
|
|
733
964
|
latency,
|
|
734
965
|
streamingProfile: fixture.streamingProfile,
|
|
735
966
|
recordedTimings: fixture.recordedTimings,
|
|
@@ -745,15 +976,20 @@ async function handleGeminiInteractions(req, res, raw, fixtures, journal, defaul
|
|
|
745
976
|
}
|
|
746
977
|
return;
|
|
747
978
|
}
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
979
|
+
recordMisbehaviorOutcome({
|
|
980
|
+
entry: journal.add({
|
|
981
|
+
method: req.method ?? "POST",
|
|
982
|
+
path: urlPath,
|
|
983
|
+
headers: flattenHeaders(req.headers),
|
|
984
|
+
body: completionReq,
|
|
985
|
+
response: {
|
|
986
|
+
status: 500,
|
|
987
|
+
fixture
|
|
988
|
+
}
|
|
989
|
+
}),
|
|
990
|
+
summary: misbehavior.summary,
|
|
991
|
+
defaults,
|
|
992
|
+
testId
|
|
757
993
|
});
|
|
758
994
|
writeErrorResponse(res, 500, JSON.stringify(buildInteractionsErrorResponse("Fixture response did not match any known type", "INTERNAL")));
|
|
759
995
|
}
|