@copilotkit/aimock 1.44.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 +31 -0
- package/README.md +6 -0
- package/dist/agui-types.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 +312 -39
- 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 +313 -40
- 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 +1 -0
- package/dist/chaos.js +1 -1
- package/dist/cli.cjs +152 -5
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +155 -8
- package/dist/cli.js.map +1 -1
- package/dist/cohere.cjs +132 -71
- 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 +133 -72
- package/dist/cohere.js.map +1 -1
- package/dist/config-loader.cjs +62 -4
- 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 +62 -4
- package/dist/config-loader.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/fixture-loader-services.cjs +1 -1
- package/dist/fixture-loader-services.cjs.map +1 -1
- package/dist/fixture-loader-services.js +1 -1
- package/dist/fixture-loader-services.js.map +1 -1
- package/dist/fixture-loader.cjs +389 -27
- package/dist/fixture-loader.cjs.map +1 -1
- package/dist/fixture-loader.d.cts +47 -3
- package/dist/fixture-loader.d.cts.map +1 -1
- package/dist/fixture-loader.d.ts +47 -3
- package/dist/fixture-loader.d.ts.map +1 -1
- package/dist/fixture-loader.js +384 -29
- package/dist/fixture-loader.js.map +1 -1
- package/dist/gemini-interactions.cjs +250 -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 +251 -53
- package/dist/gemini-interactions.js.map +1 -1
- package/dist/gemini.cjs +226 -37
- 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 +227 -38
- package/dist/gemini.js.map +1 -1
- package/dist/helpers.cjs +881 -7
- 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 +839 -8
- package/dist/helpers.js.map +1 -1
- package/dist/index.cjs +9 -0
- package/dist/index.d.cts +7 -5
- package/dist/index.d.ts +7 -5
- package/dist/index.js +4 -3
- package/dist/jest.cjs +31 -7
- package/dist/jest.cjs.map +1 -1
- package/dist/jest.d.cts +43 -3
- package/dist/jest.d.cts.map +1 -1
- package/dist/jest.d.ts +43 -3
- package/dist/jest.d.ts.map +1 -1
- package/dist/jest.js +33 -9
- package/dist/jest.js.map +1 -1
- package/dist/journal.cjs +135 -13
- package/dist/journal.cjs.map +1 -1
- package/dist/journal.d.cts +38 -4
- package/dist/journal.d.cts.map +1 -1
- package/dist/journal.d.ts +38 -4
- package/dist/journal.d.ts.map +1 -1
- package/dist/journal.js +135 -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 +123 -30
- package/dist/llmock.cjs.map +1 -1
- package/dist/llmock.d.cts +16 -1
- package/dist/llmock.d.cts.map +1 -1
- package/dist/llmock.d.ts +16 -1
- package/dist/llmock.d.ts.map +1 -1
- package/dist/llmock.js +125 -32
- package/dist/llmock.js.map +1 -1
- package/dist/mcp-fakes-mount.cjs +1 -0
- package/dist/mcp-fakes-mount.cjs.map +1 -1
- package/dist/mcp-fakes-mount.js +1 -0
- package/dist/mcp-fakes-mount.js.map +1 -1
- 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 +331 -8
- package/dist/mcp-fakes.cjs.map +1 -1
- package/dist/mcp-fakes.d.cts +406 -3
- package/dist/mcp-fakes.d.cts.map +1 -1
- package/dist/mcp-fakes.d.ts +406 -3
- package/dist/mcp-fakes.d.ts.map +1 -1
- package/dist/mcp-fakes.js +331 -8
- package/dist/mcp-fakes.js.map +1 -1
- package/dist/mcp-handler.cjs +209 -16
- 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 +207 -17
- package/dist/mcp-handler.js.map +1 -1
- package/dist/mcp-mock.cjs +112 -1
- package/dist/mcp-mock.cjs.map +1 -1
- package/dist/mcp-mock.d.cts +33 -2
- package/dist/mcp-mock.d.cts.map +1 -1
- package/dist/mcp-mock.d.ts +33 -2
- package/dist/mcp-mock.d.ts.map +1 -1
- package/dist/mcp-mock.js +112 -1
- 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/messages.cjs +362 -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 +363 -58
- package/dist/messages.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 +310 -112
- 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 +311 -113
- package/dist/ollama.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 +106 -5
- 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 +107 -7
- package/dist/recorder.js.map +1 -1
- package/dist/responses.cjs +667 -171
- 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 +665 -174
- package/dist/responses.js.map +1 -1
- 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 +572 -76
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +574 -78
- package/dist/server.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/types.cjs.map +1 -1
- package/dist/types.d.cts +315 -4
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.ts +315 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/validate-cli.cjs +36 -4
- package/dist/validate-cli.cjs.map +1 -1
- package/dist/validate-cli.js +37 -5
- package/dist/validate-cli.js.map +1 -1
- package/dist/vector-types.d.ts.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/vitest.cjs +66 -10
- package/dist/vitest.cjs.map +1 -1
- package/dist/vitest.d.cts +35 -4
- package/dist/vitest.d.cts.map +1 -1
- package/dist/vitest.d.ts +35 -4
- package/dist/vitest.d.ts.map +1 -1
- package/dist/vitest.js +67 -11
- 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 +109 -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 +111 -18
- package/dist/ws-responses.js.map +1 -1
- package/package.json +10 -2
- package/skills/write-fixtures/SKILL.md +179 -21
package/dist/ws-realtime.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Journal } from "./journal.js";
|
|
2
2
|
import { Logger } from "./logger.js";
|
|
3
|
-
import { ChatCompletionRequest, Fixture } from "./types.js";
|
|
3
|
+
import { ChatCompletionRequest, Fixture, HandlerDefaults } from "./types.js";
|
|
4
4
|
import { WebSocketConnection } from "./ws-framing.js";
|
|
5
|
-
import * as
|
|
5
|
+
import * as node_http2 from "node:http";
|
|
6
6
|
|
|
7
7
|
//#region src/ws-realtime.d.ts
|
|
8
8
|
|
|
@@ -11,12 +11,17 @@ declare function handleWebSocketRealtime(ws: WebSocketConnection, fixtures: Fixt
|
|
|
11
11
|
chunkSize: number;
|
|
12
12
|
replaySpeed?: number;
|
|
13
13
|
model: string;
|
|
14
|
+
misbehavior?: HandlerDefaults["misbehavior"];
|
|
15
|
+
misbehaviorCounters?: HandlerDefaults["misbehaviorCounters"];
|
|
16
|
+
registry?: HandlerDefaults["registry"];
|
|
14
17
|
logger: Logger;
|
|
15
18
|
strict?: boolean;
|
|
16
19
|
requestTransform?: (req: ChatCompletionRequest) => ChatCompletionRequest;
|
|
17
20
|
testId?: string;
|
|
18
|
-
upgradeHeaders?:
|
|
21
|
+
upgradeHeaders?: node_http2.IncomingHttpHeaders;
|
|
19
22
|
transcriptionIntent?: boolean;
|
|
23
|
+
/** @internal Called before each message is processed (the server assigns fixture positions). */
|
|
24
|
+
beforeProcessMessage?: () => void;
|
|
20
25
|
}): void;
|
|
21
26
|
//#endregion
|
|
22
27
|
export { handleWebSocketRealtime };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ws-realtime.d.ts","names":[],"sources":["../src/ws-realtime.ts"],"sourcesContent":[],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"ws-realtime.d.ts","names":[],"sources":["../src/ws-realtime.ts"],"sourcesContent":[],"mappings":";;;;;;;;iBA4hBgB,uBAAA,KACV,+BACM,oBACD;;;;;gBAMO;wBACQ;aACX;UACH;;2BAEiB,0BAA0B;;mBAAqB,UAAA,CAEnC"}
|
package/dist/ws-realtime.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DEFAULT_TEST_ID } from "./constants.js";
|
|
2
|
-
import { flattenHeaders, generateToolCallId,
|
|
2
|
+
import { fixtureToolCallErrorCode, flattenHeaders, generateToolCallId, isCombinedFixtureResponse, isErrorResponse, isFixtureToolCallError, isTextResponse, isToolCallResponse, isTranscriptionResponse, journalFixtureToolCallError, prepareOpenAIChatMisbehavior, rejectResponsesOnlyToolCalls, requireServedFunctionToolCalls, resolveFixtureBlocks, resolveOpenAIChatMisbehaviorUsage, resolveResponse, resolveStrictMode, strictNoMatchLogLine, strictNoMatchMessage, strictOverrideField } from "./helpers.js";
|
|
3
3
|
import { calculateDelay, delay } from "./sse-writer.js";
|
|
4
|
+
import { planMisbehavior, recordMisbehaviorOutcome } from "./misbehavior.js";
|
|
4
5
|
import { matchFixtureDiagnostic } from "./router.js";
|
|
5
6
|
import "./journal.js";
|
|
6
7
|
import { createInterruptionSignal } from "./interruption.js";
|
|
@@ -14,6 +15,11 @@ import { randomBytes } from "node:crypto";
|
|
|
14
15
|
* response.create) over WebSocket and sends back Realtime API events as
|
|
15
16
|
* individual WebSocket text frames.
|
|
16
17
|
*/
|
|
18
|
+
/**
|
|
19
|
+
* Wire label for custom-tool-call rejections on this transport, on both the
|
|
20
|
+
* `toolCalls` and the ordered `blocks` path.
|
|
21
|
+
*/
|
|
22
|
+
const REALTIME_WIRE = "OpenAI Realtime";
|
|
17
23
|
/** Generate a Realtime-API-style ID with underscore separator (e.g. event_xxx, item_xxx). */
|
|
18
24
|
function realtimeId(prefix) {
|
|
19
25
|
return `${prefix}_${randomBytes(12).toString("base64url")}`;
|
|
@@ -135,6 +141,22 @@ function serializeSession(session, sessionId) {
|
|
|
135
141
|
reasoning: session.reasoning
|
|
136
142
|
};
|
|
137
143
|
}
|
|
144
|
+
/** Realtime declares functions directly, rather than under Chat's `function` key. */
|
|
145
|
+
function realtimeToolDefinitions(tools) {
|
|
146
|
+
return tools.flatMap((value) => {
|
|
147
|
+
if (!value || typeof value !== "object") return [];
|
|
148
|
+
const tool = value;
|
|
149
|
+
if (tool.type !== "function" || typeof tool.name !== "string") return [];
|
|
150
|
+
return [{
|
|
151
|
+
type: "function",
|
|
152
|
+
function: {
|
|
153
|
+
name: tool.name,
|
|
154
|
+
...typeof tool.description === "string" ? { description: tool.description } : {},
|
|
155
|
+
...tool.parameters && typeof tool.parameters === "object" && !Array.isArray(tool.parameters) ? { parameters: tool.parameters } : {}
|
|
156
|
+
}
|
|
157
|
+
}];
|
|
158
|
+
});
|
|
159
|
+
}
|
|
138
160
|
function realtimeItemsToMessages(items, instructions, logger) {
|
|
139
161
|
const messages = [];
|
|
140
162
|
if (instructions) messages.push({
|
|
@@ -370,15 +392,20 @@ function handleWebSocketRealtime(ws, fixtures, journal, defaults) {
|
|
|
370
392
|
}, isBeta);
|
|
371
393
|
let pending = Promise.resolve();
|
|
372
394
|
ws.on("message", (raw) => {
|
|
373
|
-
pending = pending.then(
|
|
374
|
-
const msg = err instanceof Error ? err.message : "Internal error";
|
|
375
|
-
logger.error(`WebSocket realtime error: ${msg}`);
|
|
395
|
+
pending = pending.then(async () => {
|
|
376
396
|
try {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
397
|
+
defaults.beforeProcessMessage?.();
|
|
398
|
+
await processMessage(raw, ws, fixtures, journal, defaults, session, conversationItems, isBeta);
|
|
399
|
+
} catch (err) {
|
|
400
|
+
const msg = err instanceof Error ? err.message : "Internal error";
|
|
401
|
+
logger.error(`WebSocket realtime error: ${msg}`);
|
|
402
|
+
try {
|
|
403
|
+
buildErrorRealtimeEvent(ws, msg, isBeta, "server_error");
|
|
404
|
+
} catch (sendErr) {
|
|
405
|
+
defaults.logger.debug(`Failed to send error to client: ${sendErr instanceof Error ? sendErr.message : "unknown"}`);
|
|
406
|
+
}
|
|
380
407
|
}
|
|
381
|
-
})
|
|
408
|
+
});
|
|
382
409
|
});
|
|
383
410
|
}
|
|
384
411
|
async function processMessage(raw, ws, fixtures, journal, defaults, session, conversationItems, isBeta) {
|
|
@@ -694,6 +721,57 @@ function sendLiveTranscriptionFailure(ws, itemId, error, isBeta) {
|
|
|
694
721
|
error
|
|
695
722
|
}, isBeta);
|
|
696
723
|
}
|
|
724
|
+
/**
|
|
725
|
+
* Run a fixture tool-call `check` before any output item is sent. A rejected
|
|
726
|
+
* fixture (a custom tool call, which Realtime cannot carry, or a malformed
|
|
727
|
+
* `toolCalls` entry or tool-call block) marks the journal entry as a 500 and
|
|
728
|
+
* answers with a failed response — `response.created` then
|
|
729
|
+
* `response.done` with `status: "failed"` and the error, including its aimock
|
|
730
|
+
* `code`, in `status_details` — the same pair the error-fixture branch sends.
|
|
731
|
+
* Returns undefined when the response was rejected.
|
|
732
|
+
*/
|
|
733
|
+
function checkRealtimeFixtureToolCalls(ws, journalEntry, responseId, isBeta, logger, check) {
|
|
734
|
+
try {
|
|
735
|
+
return journalFixtureToolCallError(journalEntry, check);
|
|
736
|
+
} catch (err) {
|
|
737
|
+
if (!isFixtureToolCallError(err)) throw err;
|
|
738
|
+
logger.error(`WebSocket realtime error: ${err.message}`);
|
|
739
|
+
sendEvent(ws, {
|
|
740
|
+
type: "response.created",
|
|
741
|
+
response: {
|
|
742
|
+
id: responseId,
|
|
743
|
+
object: "realtime.response",
|
|
744
|
+
status: "failed",
|
|
745
|
+
status_details: null,
|
|
746
|
+
output: [],
|
|
747
|
+
usage: null
|
|
748
|
+
}
|
|
749
|
+
}, isBeta);
|
|
750
|
+
sendEvent(ws, {
|
|
751
|
+
type: "response.done",
|
|
752
|
+
response: {
|
|
753
|
+
id: responseId,
|
|
754
|
+
object: "realtime.response",
|
|
755
|
+
status: "failed",
|
|
756
|
+
output: [],
|
|
757
|
+
status_details: {
|
|
758
|
+
type: "error",
|
|
759
|
+
error: {
|
|
760
|
+
message: err.message,
|
|
761
|
+
type: "server_error",
|
|
762
|
+
code: fixtureToolCallErrorCode(err)
|
|
763
|
+
}
|
|
764
|
+
},
|
|
765
|
+
usage: {
|
|
766
|
+
total_tokens: 0,
|
|
767
|
+
input_tokens: 0,
|
|
768
|
+
output_tokens: 0
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}, isBeta);
|
|
772
|
+
return;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
697
775
|
async function handleResponseCreate(ws, fixtures, journal, defaults, session, conversationItems, isBeta, responseOverrides) {
|
|
698
776
|
const messages = realtimeItemsToMessages(conversationItems, (responseOverrides?.instructions ?? session.instructions) || void 0, defaults.logger);
|
|
699
777
|
const endpointType = {
|
|
@@ -703,10 +781,12 @@ async function handleResponseCreate(ws, fixtures, journal, defaults, session, co
|
|
|
703
781
|
}[session.type] ?? "realtime";
|
|
704
782
|
const realtimeContextHeader = defaults.upgradeHeaders?.["x-aimock-context"];
|
|
705
783
|
const realtimeContext = typeof realtimeContextHeader === "string" ? realtimeContextHeader : Array.isArray(realtimeContextHeader) && realtimeContextHeader.length > 0 ? realtimeContextHeader[0] : void 0;
|
|
784
|
+
const tools = realtimeToolDefinitions(Array.isArray(responseOverrides?.tools) ? responseOverrides.tools : session.tools);
|
|
706
785
|
const completionReq = {
|
|
707
786
|
model: session.model,
|
|
708
787
|
messages,
|
|
709
788
|
_endpointType: endpointType,
|
|
789
|
+
...tools.length > 0 ? { tools } : {},
|
|
710
790
|
_context: realtimeContext
|
|
711
791
|
};
|
|
712
792
|
const testId = defaults.testId ?? DEFAULT_TEST_ID;
|
|
@@ -778,11 +858,24 @@ async function handleResponseCreate(ws, fixtures, journal, defaults, session, co
|
|
|
778
858
|
return;
|
|
779
859
|
}
|
|
780
860
|
const response = await resolveResponse(fixture, completionReq);
|
|
781
|
-
const
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
861
|
+
const plannerDefaults = {
|
|
862
|
+
...defaults,
|
|
863
|
+
replaySpeed: defaults.replaySpeed ?? 1
|
|
864
|
+
};
|
|
865
|
+
let misbehavior = planMisbehavior({
|
|
866
|
+
wire: "openai-realtime",
|
|
867
|
+
emitsToolCallIds: true,
|
|
868
|
+
fixture,
|
|
869
|
+
response,
|
|
870
|
+
request: completionReq,
|
|
871
|
+
stream: true,
|
|
872
|
+
defaults: plannerDefaults,
|
|
873
|
+
rawHeaders: defaults.upgradeHeaders ?? {},
|
|
874
|
+
url: `/v1/realtime?testId=${encodeURIComponent(testId)}`
|
|
875
|
+
});
|
|
876
|
+
if (misbehavior.kind === "applied") misbehavior = prepareOpenAIChatMisbehavior(misbehavior);
|
|
877
|
+
const addResponseEntry = (status) => {
|
|
878
|
+
const entry = journal.add({
|
|
786
879
|
method: "WS",
|
|
787
880
|
path: "/v1/realtime",
|
|
788
881
|
headers: flattenHeaders(defaults.upgradeHeaders ?? {}),
|
|
@@ -792,6 +885,47 @@ async function handleResponseCreate(ws, fixtures, journal, defaults, session, co
|
|
|
792
885
|
fixture
|
|
793
886
|
}
|
|
794
887
|
});
|
|
888
|
+
recordMisbehaviorOutcome({
|
|
889
|
+
entry,
|
|
890
|
+
summary: misbehavior.summary,
|
|
891
|
+
defaults: plannerDefaults,
|
|
892
|
+
testId
|
|
893
|
+
});
|
|
894
|
+
return entry;
|
|
895
|
+
};
|
|
896
|
+
if (misbehavior.kind === "error") {
|
|
897
|
+
addResponseEntry(misbehavior.status);
|
|
898
|
+
if (!misbehavior.summary?.evaluations.length) defaults.logger.error(`[misbehavior] ${misbehavior.message} (testId=${testId})`);
|
|
899
|
+
buildErrorRealtimeEvent(ws, misbehavior.message, isBeta, "invalid_request_error", misbehavior.code);
|
|
900
|
+
return;
|
|
901
|
+
}
|
|
902
|
+
const latency = fixture.latency ?? defaults.latency;
|
|
903
|
+
const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);
|
|
904
|
+
if (misbehavior.kind === "applied") {
|
|
905
|
+
const prepared = misbehavior.response;
|
|
906
|
+
const combined = isCombinedFixtureResponse(prepared);
|
|
907
|
+
const journalEntry = addResponseEntry(200);
|
|
908
|
+
const blocks = checkRealtimeFixtureToolCalls(ws, journalEntry, responseId, isBeta, defaults.logger, () => combined && prepared.blocks?.length ? resolveFixtureBlocks(prepared.blocks) : [...(isTextResponse(prepared) || combined) && prepared.content ? [{
|
|
909
|
+
type: "text",
|
|
910
|
+
text: prepared.content
|
|
911
|
+
}] : [], ...isToolCallResponse(prepared) || combined ? (prepared.toolCalls ?? []).map((call) => ({
|
|
912
|
+
type: "toolCall",
|
|
913
|
+
...call
|
|
914
|
+
})) : []]);
|
|
915
|
+
if (!blocks) return;
|
|
916
|
+
const usage = resolveOpenAIChatMisbehaviorUsage(misbehavior, completionReq, false);
|
|
917
|
+
await streamRealtimeBlocks(ws, blocks, responseId, fixture, defaults, latency, chunkSize, isBeta, conversationItems, journalEntry, {
|
|
918
|
+
stop: misbehavior.stop,
|
|
919
|
+
usage: {
|
|
920
|
+
input_tokens: usage.prompt_tokens,
|
|
921
|
+
output_tokens: usage.completion_tokens,
|
|
922
|
+
total_tokens: usage.total_tokens
|
|
923
|
+
}
|
|
924
|
+
});
|
|
925
|
+
return;
|
|
926
|
+
}
|
|
927
|
+
if (isErrorResponse(response)) {
|
|
928
|
+
addResponseEntry(response.status ?? 500);
|
|
795
929
|
sendEvent(ws, {
|
|
796
930
|
type: "response.created",
|
|
797
931
|
response: {
|
|
@@ -827,21 +961,20 @@ async function handleResponseCreate(ws, fixtures, journal, defaults, session, co
|
|
|
827
961
|
}, isBeta);
|
|
828
962
|
return;
|
|
829
963
|
}
|
|
830
|
-
if (
|
|
831
|
-
const journalEntry =
|
|
832
|
-
method: "WS",
|
|
833
|
-
path: "/v1/realtime",
|
|
834
|
-
headers: flattenHeaders(defaults.upgradeHeaders ?? {}),
|
|
835
|
-
body: completionReq,
|
|
836
|
-
response: {
|
|
837
|
-
status: 200,
|
|
838
|
-
fixture
|
|
839
|
-
}
|
|
840
|
-
});
|
|
964
|
+
if (isCombinedFixtureResponse(response)) {
|
|
965
|
+
const journalEntry = addResponseEntry(200);
|
|
841
966
|
if (response.blocks && response.blocks.length > 0) {
|
|
842
|
-
|
|
967
|
+
const blocks = response.blocks;
|
|
968
|
+
const resolvedBlocks = checkRealtimeFixtureToolCalls(ws, journalEntry, responseId, isBeta, defaults.logger, () => {
|
|
969
|
+
rejectResponsesOnlyToolCalls(response, REALTIME_WIRE);
|
|
970
|
+
return resolveFixtureBlocks(blocks);
|
|
971
|
+
});
|
|
972
|
+
if (!resolvedBlocks) return;
|
|
973
|
+
await streamRealtimeBlocks(ws, resolvedBlocks, responseId, fixture, defaults, latency, chunkSize, isBeta, conversationItems, journalEntry);
|
|
843
974
|
return;
|
|
844
975
|
}
|
|
976
|
+
const functionToolCalls = checkRealtimeFixtureToolCalls(ws, journalEntry, responseId, isBeta, defaults.logger, () => requireServedFunctionToolCalls(response, REALTIME_WIRE));
|
|
977
|
+
if (!functionToolCalls) return;
|
|
845
978
|
sendEvent(ws, {
|
|
846
979
|
type: "response.created",
|
|
847
980
|
response: {
|
|
@@ -991,7 +1124,7 @@ async function handleResponseCreate(ws, fixtures, journal, defaults, session, co
|
|
|
991
1124
|
return;
|
|
992
1125
|
}
|
|
993
1126
|
allOutputItems.push(textOutputItem);
|
|
994
|
-
const toolCalls =
|
|
1127
|
+
const toolCalls = functionToolCalls;
|
|
995
1128
|
for (let tcIdx = 0; tcIdx < toolCalls.length; tcIdx++) {
|
|
996
1129
|
const tc = toolCalls[tcIdx];
|
|
997
1130
|
const callId = tc.id ?? generateToolCallId();
|
|
@@ -1121,16 +1254,7 @@ async function handleResponseCreate(ws, fixtures, journal, defaults, session, co
|
|
|
1121
1254
|
return;
|
|
1122
1255
|
}
|
|
1123
1256
|
if (isTextResponse(response)) {
|
|
1124
|
-
const journalEntry =
|
|
1125
|
-
method: "WS",
|
|
1126
|
-
path: "/v1/realtime",
|
|
1127
|
-
headers: flattenHeaders(defaults.upgradeHeaders ?? {}),
|
|
1128
|
-
body: completionReq,
|
|
1129
|
-
response: {
|
|
1130
|
-
status: 200,
|
|
1131
|
-
fixture
|
|
1132
|
-
}
|
|
1133
|
-
});
|
|
1257
|
+
const journalEntry = addResponseEntry(200);
|
|
1134
1258
|
const itemId = realtimeId("item");
|
|
1135
1259
|
const contentIndex = 0;
|
|
1136
1260
|
const outputIndex = 0;
|
|
@@ -1289,16 +1413,9 @@ async function handleResponseCreate(ws, fixtures, journal, defaults, session, co
|
|
|
1289
1413
|
return;
|
|
1290
1414
|
}
|
|
1291
1415
|
if (isToolCallResponse(response)) {
|
|
1292
|
-
const journalEntry =
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
headers: flattenHeaders(defaults.upgradeHeaders ?? {}),
|
|
1296
|
-
body: completionReq,
|
|
1297
|
-
response: {
|
|
1298
|
-
status: 200,
|
|
1299
|
-
fixture
|
|
1300
|
-
}
|
|
1301
|
-
});
|
|
1416
|
+
const journalEntry = addResponseEntry(200);
|
|
1417
|
+
const toolCalls = checkRealtimeFixtureToolCalls(ws, journalEntry, responseId, isBeta, defaults.logger, () => requireServedFunctionToolCalls(response, REALTIME_WIRE));
|
|
1418
|
+
if (!toolCalls) return;
|
|
1302
1419
|
sendEvent(ws, {
|
|
1303
1420
|
type: "response.created",
|
|
1304
1421
|
response: {
|
|
@@ -1316,8 +1433,8 @@ async function handleResponseCreate(ws, fixtures, journal, defaults, session, co
|
|
|
1316
1433
|
const { recordedTimings } = fixture;
|
|
1317
1434
|
let interrupted = false;
|
|
1318
1435
|
let eventIndex = 0;
|
|
1319
|
-
for (let tcIdx = 0; tcIdx <
|
|
1320
|
-
const tc =
|
|
1436
|
+
for (let tcIdx = 0; tcIdx < toolCalls.length; tcIdx++) {
|
|
1437
|
+
const tc = toolCalls[tcIdx];
|
|
1321
1438
|
const callId = tc.id ?? generateToolCallId();
|
|
1322
1439
|
const itemId = realtimeId("item");
|
|
1323
1440
|
const outputItem = {
|
|
@@ -1432,16 +1549,7 @@ async function handleResponseCreate(ws, fixtures, journal, defaults, session, co
|
|
|
1432
1549
|
for (const item of outputItems) conversationItems.push(item);
|
|
1433
1550
|
return;
|
|
1434
1551
|
}
|
|
1435
|
-
|
|
1436
|
-
method: "WS",
|
|
1437
|
-
path: "/v1/realtime",
|
|
1438
|
-
headers: flattenHeaders(defaults.upgradeHeaders ?? {}),
|
|
1439
|
-
body: completionReq,
|
|
1440
|
-
response: {
|
|
1441
|
-
status: 500,
|
|
1442
|
-
fixture
|
|
1443
|
-
}
|
|
1444
|
-
});
|
|
1552
|
+
addResponseEntry(500);
|
|
1445
1553
|
buildErrorRealtimeEvent(ws, "Fixture response did not match any known type", isBeta, "server_error");
|
|
1446
1554
|
}
|
|
1447
1555
|
/**
|
|
@@ -1453,7 +1561,7 @@ async function handleResponseCreate(ws, fixtures, journal, defaults, session, co
|
|
|
1453
1561
|
* as the legacy text/tool branches; a blocks-only fixture therefore never
|
|
1454
1562
|
* produces an empty payload.
|
|
1455
1563
|
*/
|
|
1456
|
-
async function streamRealtimeBlocks(ws, blocks, responseId, fixture, defaults, latency, chunkSize, isBeta, conversationItems, journalEntry) {
|
|
1564
|
+
async function streamRealtimeBlocks(ws, blocks, responseId, fixture, defaults, latency, chunkSize, isBeta, conversationItems, journalEntry, fault) {
|
|
1457
1565
|
sendEvent(ws, {
|
|
1458
1566
|
type: "response.created",
|
|
1459
1567
|
response: {
|
|
@@ -1592,10 +1700,11 @@ async function streamRealtimeBlocks(ws, blocks, responseId, fixture, defaults, l
|
|
|
1592
1700
|
const callId = block.id ?? generateToolCallId();
|
|
1593
1701
|
const itemId = realtimeId("item");
|
|
1594
1702
|
const args = block.arguments;
|
|
1703
|
+
const itemStatus = fault?.stop === "length" && outputIndex === blocks.length - 1 ? "incomplete" : "completed";
|
|
1595
1704
|
const toolOutputItem = {
|
|
1596
1705
|
id: itemId,
|
|
1597
1706
|
type: "function_call",
|
|
1598
|
-
status:
|
|
1707
|
+
status: itemStatus,
|
|
1599
1708
|
call_id: callId,
|
|
1600
1709
|
name: block.name,
|
|
1601
1710
|
arguments: args
|
|
@@ -1669,7 +1778,7 @@ async function streamRealtimeBlocks(ws, blocks, responseId, fixture, defaults, l
|
|
|
1669
1778
|
id: itemId,
|
|
1670
1779
|
object: "realtime.item",
|
|
1671
1780
|
type: "function_call",
|
|
1672
|
-
status:
|
|
1781
|
+
status: itemStatus,
|
|
1673
1782
|
call_id: callId,
|
|
1674
1783
|
name: block.name,
|
|
1675
1784
|
arguments: args
|
|
@@ -1693,9 +1802,13 @@ async function streamRealtimeBlocks(ws, blocks, responseId, fixture, defaults, l
|
|
|
1693
1802
|
response: {
|
|
1694
1803
|
id: responseId,
|
|
1695
1804
|
object: "realtime.response",
|
|
1696
|
-
status: "completed",
|
|
1805
|
+
status: fault?.stop === "length" || fault?.stop === "content_filter" ? "incomplete" : "completed",
|
|
1806
|
+
...fault?.stop === "length" || fault?.stop === "content_filter" ? { status_details: {
|
|
1807
|
+
type: "incomplete",
|
|
1808
|
+
reason: fault.stop === "length" ? "max_output_tokens" : "content_filter"
|
|
1809
|
+
} } : {},
|
|
1697
1810
|
output: allOutputItems,
|
|
1698
|
-
usage: {
|
|
1811
|
+
usage: fault?.usage ?? {
|
|
1699
1812
|
total_tokens: 0,
|
|
1700
1813
|
input_tokens: 0,
|
|
1701
1814
|
output_tokens: 0
|