@copilotkit/aimock 1.19.4 → 1.20.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/plugin.json +1 -1
- package/CHANGELOG.md +35 -0
- package/README.md +1 -1
- package/dist/agui-recorder.cjs +4 -4
- package/dist/agui-recorder.cjs.map +1 -1
- package/dist/agui-recorder.js +4 -4
- package/dist/agui-recorder.js.map +1 -1
- package/dist/agui-types.d.ts.map +1 -1
- package/dist/bedrock.cjs +28 -3
- 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 +28 -3
- package/dist/bedrock.js.map +1 -1
- package/dist/cohere.cjs +59 -35
- package/dist/cohere.cjs.map +1 -1
- package/dist/cohere.d.cts +14 -2
- package/dist/cohere.d.cts.map +1 -1
- package/dist/cohere.d.ts +14 -2
- package/dist/cohere.d.ts.map +1 -1
- package/dist/cohere.js +59 -35
- package/dist/cohere.js.map +1 -1
- package/dist/config-loader.d.ts.map +1 -1
- package/dist/fixture-loader.cjs +7 -1
- package/dist/fixture-loader.cjs.map +1 -1
- package/dist/fixture-loader.d.cts.map +1 -1
- package/dist/fixture-loader.d.ts.map +1 -1
- package/dist/fixture-loader.js +7 -1
- package/dist/fixture-loader.js.map +1 -1
- package/dist/gemini.cjs +4 -2
- 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 +5 -3
- package/dist/gemini.js.map +1 -1
- package/dist/messages.cjs +24 -4
- 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 +24 -4
- package/dist/messages.js.map +1 -1
- package/dist/moderation.cjs +6 -2
- package/dist/moderation.cjs.map +1 -1
- package/dist/moderation.d.cts.map +1 -1
- package/dist/moderation.d.ts.map +1 -1
- package/dist/moderation.js +6 -2
- package/dist/moderation.js.map +1 -1
- package/dist/ollama.cjs +25 -8
- package/dist/ollama.cjs.map +1 -1
- package/dist/ollama.d.cts +7 -0
- package/dist/ollama.d.cts.map +1 -1
- package/dist/ollama.d.ts +7 -0
- package/dist/ollama.d.ts.map +1 -1
- package/dist/ollama.js +25 -8
- package/dist/ollama.js.map +1 -1
- package/dist/recorder.cjs +5 -2
- package/dist/recorder.cjs.map +1 -1
- package/dist/recorder.js +5 -2
- package/dist/recorder.js.map +1 -1
- package/dist/rerank.cjs +4 -10
- package/dist/rerank.cjs.map +1 -1
- package/dist/rerank.js +4 -10
- package/dist/rerank.js.map +1 -1
- package/dist/responses.cjs +3 -1
- package/dist/responses.cjs.map +1 -1
- package/dist/responses.d.cts.map +1 -1
- package/dist/responses.d.ts.map +1 -1
- package/dist/responses.js +3 -1
- package/dist/responses.js.map +1 -1
- package/dist/router.cjs +28 -0
- package/dist/router.cjs.map +1 -1
- package/dist/router.d.cts +0 -1
- package/dist/router.d.cts.map +1 -1
- package/dist/router.d.ts +0 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +28 -0
- package/dist/router.js.map +1 -1
- package/dist/search.cjs +7 -1
- package/dist/search.cjs.map +1 -1
- package/dist/search.js +7 -1
- package/dist/search.js.map +1 -1
- package/dist/server.cjs +12 -2
- 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 +12 -2
- package/dist/server.js.map +1 -1
- package/dist/transcription.cjs +7 -6
- package/dist/transcription.cjs.map +1 -1
- package/dist/transcription.js +7 -6
- package/dist/transcription.js.map +1 -1
- package/dist/types.d.cts +11 -0
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/vector-types.d.cts.map +1 -1
- package/dist/vector-types.d.ts.map +1 -1
- package/dist/ws-gemini-live.cjs +37 -29
- package/dist/ws-gemini-live.cjs.map +1 -1
- package/dist/ws-gemini-live.d.cts.map +1 -1
- package/dist/ws-gemini-live.d.ts.map +1 -1
- package/dist/ws-gemini-live.js +37 -29
- package/dist/ws-gemini-live.js.map +1 -1
- package/dist/ws-realtime.cjs +84 -15
- package/dist/ws-realtime.cjs.map +1 -1
- package/dist/ws-realtime.d.cts.map +1 -1
- package/dist/ws-realtime.d.ts.map +1 -1
- package/dist/ws-realtime.js +84 -16
- package/dist/ws-realtime.js.map +1 -1
- package/package.json +1 -1
- package/skills/write-fixtures/SKILL.md +2 -0
package/dist/transcription.js
CHANGED
|
@@ -121,15 +121,16 @@ async function handleTranscription(req, res, raw, fixtures, journal, defaults, s
|
|
|
121
121
|
});
|
|
122
122
|
const t = response.transcription;
|
|
123
123
|
if (responseFormat === "verbose_json" || t.words != null || t.segments != null) {
|
|
124
|
-
|
|
125
|
-
res.end(JSON.stringify({
|
|
124
|
+
const verboseBody = {
|
|
126
125
|
task: "transcribe",
|
|
127
126
|
language: t.language ?? "english",
|
|
128
127
|
duration: t.duration ?? 0,
|
|
129
|
-
text: t.text
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
128
|
+
text: t.text
|
|
129
|
+
};
|
|
130
|
+
if (t.words && t.words.length > 0) verboseBody.words = t.words;
|
|
131
|
+
if (t.segments && t.segments.length > 0) verboseBody.segments = t.segments;
|
|
132
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
133
|
+
res.end(JSON.stringify(verboseBody));
|
|
133
134
|
} else {
|
|
134
135
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
135
136
|
res.end(JSON.stringify({ text: t.text }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transcription.js","names":[],"sources":["../src/transcription.ts"],"sourcesContent":["import type * as http from \"node:http\";\nimport type { ChatCompletionRequest, Fixture, HandlerDefaults } from \"./types.js\";\nimport {\n isTranscriptionResponse,\n isErrorResponse,\n flattenHeaders,\n getTestId,\n resolveResponse,\n} from \"./helpers.js\";\nimport { matchFixture } from \"./router.js\";\nimport { writeErrorResponse } from \"./sse-writer.js\";\nimport type { Journal } from \"./journal.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\n/**\n * Extract a text field from multipart form data using regex.\n * NOTE: This runs against the full body including binary audio data.\n * It works because text metadata fields (model, response_format, etc.)\n * appear before the binary audio part in standard multipart encoding.\n * A proper multipart parser would be more robust but is overkill for\n * the small set of fields we extract.\n */\nfunction extractFormField(raw: string, fieldName: string): string | undefined {\n const pattern = new RegExp(\n `Content-Disposition:\\\\s*form-data;[^\\\\r\\\\n]*name=\"${fieldName}\"[^\\\\r\\\\n]*\\\\r\\\\n\\\\r\\\\n([^\\\\r\\\\n]*)`,\n \"i\",\n );\n const match = raw.match(pattern);\n return match?.[1];\n}\n\nexport async function handleTranscription(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n raw: string,\n fixtures: Fixture[],\n journal: Journal,\n defaults: HandlerDefaults,\n setCorsHeaders: (res: http.ServerResponse) => void,\n): Promise<void> {\n setCorsHeaders(res);\n const path = req.url ?? \"/v1/audio/transcriptions\";\n const method = req.method ?? \"POST\";\n\n const model = extractFormField(raw, \"model\") ?? \"whisper-1\";\n const responseFormat = extractFormField(raw, \"response_format\") ?? \"json\";\n\n const syntheticReq: ChatCompletionRequest = {\n model,\n messages: [],\n _endpointType: \"transcription\",\n };\n\n const testId = getTestId(req);\n const fixture = matchFixture(\n fixtures,\n syntheticReq,\n journal.getFixtureMatchCountsForTest(testId),\n defaults.requestTransform,\n );\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n defaults.logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);\n } else {\n defaults.logger.debug(`No fixture matched for request`);\n }\n\n if (\n applyChaos(\n res,\n fixture,\n defaults.chaos,\n req.headers,\n journal,\n { method, path, headers: flattenHeaders(req.headers), body: syntheticReq },\n fixture ? \"fixture\" : \"proxy\",\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n if (defaults.record) {\n const outcome = await proxyAndRecord(\n req,\n res,\n syntheticReq,\n \"openai\",\n req.url ?? \"/v1/audio/transcriptions\",\n fixtures,\n defaults,\n raw,\n );\n if (outcome !== \"not_configured\") {\n journal.add({\n method,\n path,\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: res.statusCode ?? 200, fixture: null, source: \"proxy\" },\n });\n return;\n }\n }\n\n const strictStatus = defaults.strict ? 503 : 404;\n const strictMessage = defaults.strict\n ? \"Strict mode: no fixture matched\"\n : \"No fixture matched\";\n journal.add({\n method,\n path,\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: strictStatus, fixture: null },\n });\n writeErrorResponse(\n res,\n strictStatus,\n JSON.stringify({\n error: {\n message: strictMessage,\n type: \"invalid_request_error\",\n code: \"no_fixture_match\",\n },\n }),\n );\n return;\n }\n\n const response = await resolveResponse(fixture, syntheticReq);\n\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method,\n path,\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status, fixture },\n });\n writeErrorResponse(res, status, JSON.stringify(response));\n return;\n }\n\n if (!isTranscriptionResponse(response)) {\n journal.add({\n method,\n path,\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: {\n message: \"Fixture response is not a transcription type\",\n type: \"server_error\",\n },\n }),\n );\n return;\n }\n\n journal.add({\n method,\n path,\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 200, fixture },\n });\n\n const t = response.transcription;\n const useVerbose = responseFormat === \"verbose_json\" || t.words != null || t.segments != null;\n\n if (useVerbose) {\n
|
|
1
|
+
{"version":3,"file":"transcription.js","names":[],"sources":["../src/transcription.ts"],"sourcesContent":["import type * as http from \"node:http\";\nimport type { ChatCompletionRequest, Fixture, HandlerDefaults } from \"./types.js\";\nimport {\n isTranscriptionResponse,\n isErrorResponse,\n flattenHeaders,\n getTestId,\n resolveResponse,\n} from \"./helpers.js\";\nimport { matchFixture } from \"./router.js\";\nimport { writeErrorResponse } from \"./sse-writer.js\";\nimport type { Journal } from \"./journal.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\n/**\n * Extract a text field from multipart form data using regex.\n * NOTE: This runs against the full body including binary audio data.\n * It works because text metadata fields (model, response_format, etc.)\n * appear before the binary audio part in standard multipart encoding.\n * A proper multipart parser would be more robust but is overkill for\n * the small set of fields we extract.\n */\nfunction extractFormField(raw: string, fieldName: string): string | undefined {\n const pattern = new RegExp(\n `Content-Disposition:\\\\s*form-data;[^\\\\r\\\\n]*name=\"${fieldName}\"[^\\\\r\\\\n]*\\\\r\\\\n\\\\r\\\\n([^\\\\r\\\\n]*)`,\n \"i\",\n );\n const match = raw.match(pattern);\n return match?.[1];\n}\n\nexport async function handleTranscription(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n raw: string,\n fixtures: Fixture[],\n journal: Journal,\n defaults: HandlerDefaults,\n setCorsHeaders: (res: http.ServerResponse) => void,\n): Promise<void> {\n setCorsHeaders(res);\n const path = req.url ?? \"/v1/audio/transcriptions\";\n const method = req.method ?? \"POST\";\n\n const model = extractFormField(raw, \"model\") ?? \"whisper-1\";\n const responseFormat = extractFormField(raw, \"response_format\") ?? \"json\";\n\n const syntheticReq: ChatCompletionRequest = {\n model,\n messages: [],\n _endpointType: \"transcription\",\n };\n\n const testId = getTestId(req);\n const fixture = matchFixture(\n fixtures,\n syntheticReq,\n journal.getFixtureMatchCountsForTest(testId),\n defaults.requestTransform,\n );\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n defaults.logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);\n } else {\n defaults.logger.debug(`No fixture matched for request`);\n }\n\n if (\n applyChaos(\n res,\n fixture,\n defaults.chaos,\n req.headers,\n journal,\n { method, path, headers: flattenHeaders(req.headers), body: syntheticReq },\n fixture ? \"fixture\" : \"proxy\",\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n if (defaults.record) {\n const outcome = await proxyAndRecord(\n req,\n res,\n syntheticReq,\n \"openai\",\n req.url ?? \"/v1/audio/transcriptions\",\n fixtures,\n defaults,\n raw,\n );\n if (outcome !== \"not_configured\") {\n journal.add({\n method,\n path,\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: res.statusCode ?? 200, fixture: null, source: \"proxy\" },\n });\n return;\n }\n }\n\n const strictStatus = defaults.strict ? 503 : 404;\n const strictMessage = defaults.strict\n ? \"Strict mode: no fixture matched\"\n : \"No fixture matched\";\n journal.add({\n method,\n path,\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: strictStatus, fixture: null },\n });\n writeErrorResponse(\n res,\n strictStatus,\n JSON.stringify({\n error: {\n message: strictMessage,\n type: \"invalid_request_error\",\n code: \"no_fixture_match\",\n },\n }),\n );\n return;\n }\n\n const response = await resolveResponse(fixture, syntheticReq);\n\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method,\n path,\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status, fixture },\n });\n writeErrorResponse(res, status, JSON.stringify(response));\n return;\n }\n\n if (!isTranscriptionResponse(response)) {\n journal.add({\n method,\n path,\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: {\n message: \"Fixture response is not a transcription type\",\n type: \"server_error\",\n },\n }),\n );\n return;\n }\n\n journal.add({\n method,\n path,\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 200, fixture },\n });\n\n const t = response.transcription;\n const useVerbose = responseFormat === \"verbose_json\" || t.words != null || t.segments != null;\n\n if (useVerbose) {\n const verboseBody: Record<string, unknown> = {\n task: \"transcribe\",\n language: t.language ?? \"english\",\n duration: t.duration ?? 0,\n text: t.text,\n };\n if (t.words && t.words.length > 0) {\n verboseBody.words = t.words;\n }\n if (t.segments && t.segments.length > 0) {\n verboseBody.segments = t.segments;\n }\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(verboseBody));\n } else {\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ text: t.text }));\n }\n}\n"],"mappings":"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"}
|
package/dist/types.d.cts
CHANGED
|
@@ -64,6 +64,16 @@ interface ToolDefinition {
|
|
|
64
64
|
}
|
|
65
65
|
interface FixtureMatch {
|
|
66
66
|
userMessage?: string | RegExp;
|
|
67
|
+
/**
|
|
68
|
+
* Substring or regexp matched against the concatenated text content of every
|
|
69
|
+
* `system` role message in the request. Gates fixture activation on values
|
|
70
|
+
* the host plumbs in via system messages (agent context, persona, dynamic
|
|
71
|
+
* config) instead of the user-typed prompt — so changing context state in
|
|
72
|
+
* the calling app causes stale fixtures to fall through to a real upstream
|
|
73
|
+
* instead of silently returning a baked response that no longer reflects
|
|
74
|
+
* reality.
|
|
75
|
+
*/
|
|
76
|
+
systemMessage?: string | RegExp;
|
|
67
77
|
inputText?: string | RegExp;
|
|
68
78
|
toolCallId?: string;
|
|
69
79
|
toolName?: string;
|
|
@@ -252,6 +262,7 @@ interface FixtureFile {
|
|
|
252
262
|
interface FixtureFileEntry {
|
|
253
263
|
match: {
|
|
254
264
|
userMessage?: string;
|
|
265
|
+
systemMessage?: string;
|
|
255
266
|
inputText?: string;
|
|
256
267
|
toolCallId?: string;
|
|
257
268
|
toolName?: string;
|
package/dist/types.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.cts","names":[],"sources":["../src/types.ts"],"sourcesContent":[],"mappings":";;;;;;;UAQiB,SAAA;qBAER,MAAA,CAAK,sBACL,MAAA,CAAK,mCAET;EALY,aAAS,EAAA,MAAA,EAMD,GAAA,CAAI,MANH,EAAA,IAAA,EAMiB,MANjB,EAAA,QAAA,EAAA,MAAA,CAAA,EAM4C,OAN5C,CAAA,OAAA,CAAA;EAAA,MAAA,GAAA,EAAA;IAEjB,MAAK,EAAA,MAAA;IACL,CAAA,GAAA,EAAK,MAAA,CAAA,EAAA,OAAA;;YAGe,EAAA,OAAA,EAEN,OAFM,CAAA,EAAA,IAAA;YAAc,EAAA,GAAA,EAAA,MAAA,CAAA,EAAA,IAAA;aAA2B,EAAA,QAAA,EAI7C,eAJ6C,CAAA,EAAA,IAAA;;AAI7C,UAGR,WAAA,CAHQ;EAAe,IAAA,EAAA,MAAA;EAGvB,IAAA,CAAA,EAAA,MAAA;EAMA,CAAA,GAAA,EAAA,MAAA,CAAA,EAAW,OAAA;;AAER,UAFH,WAAA,CAEG;MAEL,EAAA,QAAA,GAAA,MAAA,GAAA,WAAA,GAAA,MAAA;EAAe,OAAA,EAAA,MAAA,GAFV,WAEU,EAAA,GAAA,IAAA;EAIb,IAAA,CAAA,EAAA,MAAA;EAMA,UAAA,CAAA,EAVF,eAUuB,EAAA;EAAA,YAAA,CAAA,EAAA,MAAA;;AAM5B,UAZO,eAAA,CAYP;EAAc,EAAA,EAAA,MAAA;EAUP,IAAA,EAAA,UAAA;EAOA,QAAA,EAAA;IAAY,IAAA,EAAA,MAAA;IACJ,SAAA,EAAA,MAAA;;;
|
|
1
|
+
{"version":3,"file":"types.d.cts","names":[],"sources":["../src/types.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -64,6 +64,16 @@ interface ToolDefinition {
|
|
|
64
64
|
}
|
|
65
65
|
interface FixtureMatch {
|
|
66
66
|
userMessage?: string | RegExp;
|
|
67
|
+
/**
|
|
68
|
+
* Substring or regexp matched against the concatenated text content of every
|
|
69
|
+
* `system` role message in the request. Gates fixture activation on values
|
|
70
|
+
* the host plumbs in via system messages (agent context, persona, dynamic
|
|
71
|
+
* config) instead of the user-typed prompt — so changing context state in
|
|
72
|
+
* the calling app causes stale fixtures to fall through to a real upstream
|
|
73
|
+
* instead of silently returning a baked response that no longer reflects
|
|
74
|
+
* reality.
|
|
75
|
+
*/
|
|
76
|
+
systemMessage?: string | RegExp;
|
|
67
77
|
inputText?: string | RegExp;
|
|
68
78
|
toolCallId?: string;
|
|
69
79
|
toolName?: string;
|
|
@@ -252,6 +262,7 @@ interface FixtureFile {
|
|
|
252
262
|
interface FixtureFileEntry {
|
|
253
263
|
match: {
|
|
254
264
|
userMessage?: string;
|
|
265
|
+
systemMessage?: string;
|
|
255
266
|
inputText?: string;
|
|
256
267
|
toolCallId?: string;
|
|
257
268
|
toolName?: string;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"sourcesContent":[],"mappings":";;;;;;;UAQiB,SAAA;qBAER,MAAA,CAAK,sBACL,MAAA,CAAK,mCAET;EALY,aAAS,EAAA,MAAA,EAMD,GAAA,CAAI,MANH,EAAA,IAAA,EAMiB,MANjB,EAAA,QAAA,EAAA,MAAA,CAAA,EAM4C,OAN5C,CAAA,OAAA,CAAA;EAAA,MAAA,GAAA,EAAA;IAEjB,MAAK,EAAA,MAAA;IACL,CAAA,GAAA,EAAK,MAAA,CAAA,EAAA,OAAA;;YAGe,EAAA,OAAA,EAEN,OAFM,CAAA,EAAA,IAAA;YAAc,EAAA,GAAA,EAAA,MAAA,CAAA,EAAA,IAAA;aAA2B,EAAA,QAAA,EAI7C,eAJ6C,CAAA,EAAA,IAAA;;AAI7C,UAGR,WAAA,CAHQ;EAAe,IAAA,EAAA,MAAA;EAGvB,IAAA,CAAA,EAAA,MAAA;EAMA,CAAA,GAAA,EAAA,MAAA,CAAA,EAAW,OAAA;;AAER,UAFH,WAAA,CAEG;MAEL,EAAA,QAAA,GAAA,MAAA,GAAA,WAAA,GAAA,MAAA;EAAe,OAAA,EAAA,MAAA,GAFV,WAEU,EAAA,GAAA,IAAA;EAIb,IAAA,CAAA,EAAA,MAAA;EAMA,UAAA,CAAA,EAVF,eAUuB,EAAA;EAAA,YAAA,CAAA,EAAA,MAAA;;AAM5B,UAZO,eAAA,CAYP;EAAc,EAAA,EAAA,MAAA;EAUP,IAAA,EAAA,UAAA;EAOA,QAAA,EAAA;IAAY,IAAA,EAAA,MAAA;IACJ,SAAA,EAAA,MAAA;;;
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"sourcesContent":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vector-types.d.cts","names":[],"sources":["../src/vector-types.ts"],"sourcesContent":[],"mappings":";UAAiB,iBAAA;EAAA,IAAA,CAAA,EAAA,MAAA;EAKA,IAAA,CAAA,EAAA,MAAA;;AAGM,UAHN,gBAAA,CAGM;MAAZ,EAAA,MAAA;EAAG,SAAA,EAAA,MAAA;EAGG,OAAA,EAHN,GAGM,CAAA,MAAW,EAHL,
|
|
1
|
+
{"version":3,"file":"vector-types.d.cts","names":[],"sources":["../src/vector-types.ts"],"sourcesContent":[],"mappings":";UAAiB,iBAAA;EAAA,IAAA,CAAA,EAAA,MAAA;EAKA,IAAA,CAAA,EAAA,MAAA;;AAGM,UAHN,gBAAA,CAGM;MAAZ,EAAA,MAAA;EAAG,SAAA,EAAA,MAAA;EAGG,OAAA,EAHN,GAGM,CAAA,MAAW,EAHL,WAMV,CAAM;AAGnB;AAOiB,UAbA,WAAA,CAaW;EAOhB,EAAA,EAAA,MAAA;EAAY,MAAA,EAAA,MAAA,EAAA;UAAG,CAAA,EAjBd,MAiBc,CAAA,MAAA,EAAA,OAAA,CAAA;;AAAyC,UAdnD,WAAA,CAcmD;EAAW,EAAA,EAAA,MAAA;;aAXlE;;;UAII,WAAA;;;;;;KAOL,YAAA,GAAe,yBAAyB,gBAAgB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vector-types.d.ts","names":[],"sources":["../src/vector-types.ts"],"sourcesContent":[],"mappings":";UAAiB,iBAAA;EAAA,IAAA,CAAA,EAAA,MAAA;EAKA,IAAA,CAAA,EAAA,MAAA;;AAGM,UAHN,gBAAA,CAGM;MAAZ,EAAA,MAAA;EAAG,SAAA,EAAA,MAAA;EAGG,OAAA,EAHN,GAGM,CAAA,MAAW,EAHL,
|
|
1
|
+
{"version":3,"file":"vector-types.d.ts","names":[],"sources":["../src/vector-types.ts"],"sourcesContent":[],"mappings":";UAAiB,iBAAA;EAAA,IAAA,CAAA,EAAA,MAAA;EAKA,IAAA,CAAA,EAAA,MAAA;;AAGM,UAHN,gBAAA,CAGM;MAAZ,EAAA,MAAA;EAAG,SAAA,EAAA,MAAA;EAGG,OAAA,EAHN,GAGM,CAAA,MAAW,EAHL,WAMJ,CAAA;AAGnB;AAOiB,UAbA,WAAA,CAaW;EAOhB,EAAA,EAAA,MAAA;EAAY,MAAA,EAAA,MAAA,EAAA;UAAG,CAAA,EAjBd,MAiBc,CAAA,MAAA,EAAA,OAAA,CAAA;;AAAyC,UAdnD,WAAA,CAcmD;EAAW,EAAA,EAAA,MAAA;;aAXlE;;;UAII,WAAA;;;;;;KAOL,YAAA,GAAe,yBAAyB,gBAAgB"}
|
package/dist/ws-gemini-live.cjs
CHANGED
|
@@ -7,6 +7,23 @@ const require_interruption = require('./interruption.cjs');
|
|
|
7
7
|
//#region src/ws-gemini-live.ts
|
|
8
8
|
const WS_PATH = "/ws/google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent";
|
|
9
9
|
/**
|
|
10
|
+
* Map HTTP status codes to gRPC error codes.
|
|
11
|
+
* Gemini Live uses gRPC codes, not HTTP status codes.
|
|
12
|
+
*/
|
|
13
|
+
function httpToGrpc(httpCode) {
|
|
14
|
+
switch (httpCode) {
|
|
15
|
+
case 400: return 3;
|
|
16
|
+
case 401: return 16;
|
|
17
|
+
case 403: return 7;
|
|
18
|
+
case 404: return 5;
|
|
19
|
+
case 409: return 10;
|
|
20
|
+
case 429: return 8;
|
|
21
|
+
case 501: return 12;
|
|
22
|
+
case 503: return 14;
|
|
23
|
+
default: return 13;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
10
27
|
* Convert Gemini Live turns into ChatMessage[] for fixture matching.
|
|
11
28
|
*/
|
|
12
29
|
function geminiTurnsToMessages(turns) {
|
|
@@ -101,7 +118,7 @@ function handleWebSocketGeminiLive(ws, fixtures, journal, defaults) {
|
|
|
101
118
|
logger.error(`WebSocket Gemini Live error: ${msg}`);
|
|
102
119
|
try {
|
|
103
120
|
ws.send(JSON.stringify({ error: {
|
|
104
|
-
code:
|
|
121
|
+
code: 13,
|
|
105
122
|
message: msg,
|
|
106
123
|
status: "INTERNAL"
|
|
107
124
|
} }));
|
|
@@ -115,22 +132,23 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
115
132
|
parsed = JSON.parse(raw);
|
|
116
133
|
} catch {
|
|
117
134
|
ws.send(JSON.stringify({ error: {
|
|
118
|
-
code:
|
|
135
|
+
code: 3,
|
|
119
136
|
message: "Malformed JSON",
|
|
120
137
|
status: "INVALID_ARGUMENT"
|
|
121
138
|
} }));
|
|
122
139
|
return;
|
|
123
140
|
}
|
|
124
|
-
|
|
141
|
+
const setupMsg = parsed.setup ?? parsed.config;
|
|
142
|
+
if (setupMsg) {
|
|
125
143
|
session.setupDone = true;
|
|
126
|
-
session.model =
|
|
127
|
-
session.tools = convertTools(
|
|
144
|
+
session.model = setupMsg.model ?? defaults.model;
|
|
145
|
+
session.tools = convertTools(setupMsg.tools);
|
|
128
146
|
ws.send(JSON.stringify({ setupComplete: {} }));
|
|
129
147
|
return;
|
|
130
148
|
}
|
|
131
149
|
if (!session.setupDone) {
|
|
132
150
|
ws.send(JSON.stringify({ error: {
|
|
133
|
-
code:
|
|
151
|
+
code: 9,
|
|
134
152
|
message: "Setup required",
|
|
135
153
|
status: "FAILED_PRECONDITION"
|
|
136
154
|
} }));
|
|
@@ -140,7 +158,7 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
140
158
|
if (parsed.clientContent) {
|
|
141
159
|
if (!parsed.clientContent.turns || !Array.isArray(parsed.clientContent.turns)) {
|
|
142
160
|
ws.send(JSON.stringify({ error: {
|
|
143
|
-
code:
|
|
161
|
+
code: 3,
|
|
144
162
|
message: "Missing 'turns' in clientContent",
|
|
145
163
|
status: "INVALID_ARGUMENT"
|
|
146
164
|
} }));
|
|
@@ -150,7 +168,7 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
150
168
|
} else if (parsed.toolResponse) {
|
|
151
169
|
if (!parsed.toolResponse.functionResponses || !Array.isArray(parsed.toolResponse.functionResponses)) {
|
|
152
170
|
ws.send(JSON.stringify({ error: {
|
|
153
|
-
code:
|
|
171
|
+
code: 3,
|
|
154
172
|
message: "Missing 'functionResponses' in toolResponse",
|
|
155
173
|
status: "INVALID_ARGUMENT"
|
|
156
174
|
} }));
|
|
@@ -159,7 +177,7 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
159
177
|
newMessages = toolResponseToMessages(parsed.toolResponse);
|
|
160
178
|
} else {
|
|
161
179
|
ws.send(JSON.stringify({ error: {
|
|
162
|
-
code:
|
|
180
|
+
code: 3,
|
|
163
181
|
message: "Expected clientContent or toolResponse",
|
|
164
182
|
status: "INVALID_ARGUMENT"
|
|
165
183
|
} }));
|
|
@@ -202,7 +220,7 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
202
220
|
}
|
|
203
221
|
});
|
|
204
222
|
ws.send(JSON.stringify({ error: {
|
|
205
|
-
code:
|
|
223
|
+
code: 5,
|
|
206
224
|
message: "No fixture matched",
|
|
207
225
|
status: "NOT_FOUND"
|
|
208
226
|
} }));
|
|
@@ -225,7 +243,7 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
225
243
|
}
|
|
226
244
|
});
|
|
227
245
|
ws.send(JSON.stringify({ error: {
|
|
228
|
-
code: status,
|
|
246
|
+
code: httpToGrpc(status),
|
|
229
247
|
message: response.error.message,
|
|
230
248
|
status: response.error.type ?? "INTERNAL"
|
|
231
249
|
} }));
|
|
@@ -282,10 +300,7 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
282
300
|
const interruption = require_interruption.createInterruptionSignal(fixture);
|
|
283
301
|
let interrupted = false;
|
|
284
302
|
if (content.length === 0) {
|
|
285
|
-
if (!ws.isClosed) ws.send(JSON.stringify({ serverContent: {
|
|
286
|
-
modelTurn: { parts: [{ text: "" }] },
|
|
287
|
-
turnComplete: false
|
|
288
|
-
} }));
|
|
303
|
+
if (!ws.isClosed) ws.send(JSON.stringify({ serverContent: { modelTurn: { parts: [{ text: "" }] } } }));
|
|
289
304
|
} else for (let i = 0; i < chunkList.length; i++) {
|
|
290
305
|
if (ws.isClosed) break;
|
|
291
306
|
if (latency > 0) await require_sse_writer.delay(latency, interruption?.signal);
|
|
@@ -294,10 +309,7 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
294
309
|
break;
|
|
295
310
|
}
|
|
296
311
|
if (ws.isClosed) break;
|
|
297
|
-
ws.send(JSON.stringify({ serverContent: {
|
|
298
|
-
modelTurn: { parts: [{ text: chunkList[i] }] },
|
|
299
|
-
turnComplete: false
|
|
300
|
-
} }));
|
|
312
|
+
ws.send(JSON.stringify({ serverContent: { modelTurn: { parts: [{ text: chunkList[i] }] } } }));
|
|
301
313
|
interruption?.tick();
|
|
302
314
|
if (interruption?.signal.aborted) {
|
|
303
315
|
interrupted = true;
|
|
@@ -378,10 +390,8 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
378
390
|
const content = response.content;
|
|
379
391
|
if (content.length === 0) {
|
|
380
392
|
if (ws.isClosed) return;
|
|
381
|
-
ws.send(JSON.stringify({ serverContent: {
|
|
382
|
-
|
|
383
|
-
turnComplete: true
|
|
384
|
-
} }));
|
|
393
|
+
ws.send(JSON.stringify({ serverContent: { modelTurn: { parts: [{ text: "" }] } } }));
|
|
394
|
+
ws.send(JSON.stringify({ serverContent: { turnComplete: true } }));
|
|
385
395
|
return;
|
|
386
396
|
}
|
|
387
397
|
const chunks = [];
|
|
@@ -396,11 +406,7 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
396
406
|
break;
|
|
397
407
|
}
|
|
398
408
|
if (ws.isClosed) break;
|
|
399
|
-
|
|
400
|
-
ws.send(JSON.stringify({ serverContent: {
|
|
401
|
-
modelTurn: { parts: [{ text: chunks[i] }] },
|
|
402
|
-
turnComplete: isLast
|
|
403
|
-
} }));
|
|
409
|
+
ws.send(JSON.stringify({ serverContent: { modelTurn: { parts: [{ text: chunks[i] }] } } }));
|
|
404
410
|
interruption?.tick();
|
|
405
411
|
if (interruption?.signal.aborted) {
|
|
406
412
|
interrupted = true;
|
|
@@ -415,6 +421,7 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
415
421
|
return;
|
|
416
422
|
}
|
|
417
423
|
interruption?.cleanup();
|
|
424
|
+
if (!ws.isClosed) ws.send(JSON.stringify({ serverContent: { turnComplete: true } }));
|
|
418
425
|
session.conversationHistory.push({
|
|
419
426
|
role: "assistant",
|
|
420
427
|
content
|
|
@@ -473,6 +480,7 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
473
480
|
return;
|
|
474
481
|
}
|
|
475
482
|
interruption?.cleanup();
|
|
483
|
+
if (!ws.isClosed) ws.send(JSON.stringify({ serverContent: { turnComplete: true } }));
|
|
476
484
|
session.conversationHistory.push({
|
|
477
485
|
role: "assistant",
|
|
478
486
|
content: null,
|
|
@@ -498,7 +506,7 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
498
506
|
}
|
|
499
507
|
});
|
|
500
508
|
ws.send(JSON.stringify({ error: {
|
|
501
|
-
code:
|
|
509
|
+
code: 13,
|
|
502
510
|
message: "Fixture response did not match any known type",
|
|
503
511
|
status: "INTERNAL"
|
|
504
512
|
} }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ws-gemini-live.cjs","names":["DEFAULT_TEST_ID","matchFixture","resolveResponse","isErrorResponse","isAudioResponse","formatToMime","isContentWithToolCallsResponse","createInterruptionSignal","delay","generateToolCallId","isTextResponse","isToolCallResponse"],"sources":["../src/ws-gemini-live.ts"],"sourcesContent":["/**\n * WebSocket handler for Gemini Live BidiGenerateContent API.\n *\n * Accepts setup, clientContent, and toolResponse messages over WebSocket\n * and responds with setupComplete, serverContent, toolCall, and error\n * messages in the Gemini Live streaming format.\n */\n\nimport type {\n Fixture,\n ChatMessage,\n ChatCompletionRequest,\n ToolDefinition,\n AudioResponse,\n} from \"./types.js\";\nimport { matchFixture } from \"./router.js\";\nimport {\n isTextResponse,\n isToolCallResponse,\n isContentWithToolCallsResponse,\n isErrorResponse,\n isAudioResponse,\n formatToMime,\n generateToolCallId,\n resolveResponse,\n} from \"./helpers.js\";\nimport { createInterruptionSignal } from \"./interruption.js\";\nimport { delay } from \"./sse-writer.js\";\nimport { DEFAULT_TEST_ID, type Journal } from \"./journal.js\";\nimport type { Logger } from \"./logger.js\";\nimport type { WebSocketConnection } from \"./ws-framing.js\";\n\n// ─── Gemini Live protocol types ─────────────────────────────────────────────\n\ninterface GeminiLivePart {\n text?: string;\n thought?: boolean;\n functionCall?: { name: string; args: Record<string, unknown> };\n functionResponse?: { name: string; response: unknown; id?: string };\n inlineData?: { mimeType: string; data: string };\n}\n\ninterface GeminiLiveTurn {\n role: string;\n parts: GeminiLivePart[];\n}\n\ninterface GeminiLiveFunctionDeclaration {\n name: string;\n description?: string;\n parameters?: object;\n}\n\ninterface GeminiLiveToolDef {\n functionDeclarations?: GeminiLiveFunctionDeclaration[];\n}\n\ninterface GeminiLiveSetup {\n model?: string;\n generationConfig?: Record<string, unknown>;\n tools?: GeminiLiveToolDef[];\n}\n\ninterface GeminiLiveClientContent {\n turns: GeminiLiveTurn[];\n turnComplete?: boolean;\n}\n\ninterface GeminiLiveFunctionResponse {\n id?: string;\n name: string;\n response: unknown;\n}\n\ninterface GeminiLiveToolResponse {\n functionResponses: GeminiLiveFunctionResponse[];\n}\n\ninterface GeminiLiveMessage {\n setup?: GeminiLiveSetup;\n clientContent?: GeminiLiveClientContent;\n toolResponse?: GeminiLiveToolResponse;\n}\n\n// ─── Session state ──────────────────────────────────────────────────────────\n\ninterface SessionState {\n setupDone: boolean;\n model: string;\n tools: ToolDefinition[];\n conversationHistory: ChatMessage[];\n}\n\n// ─── Helpers ────────────────────────────────────────────────────────────────\n\nconst WS_PATH = \"/ws/google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent\";\n\n/**\n * Convert Gemini Live turns into ChatMessage[] for fixture matching.\n */\nfunction geminiTurnsToMessages(turns: GeminiLiveTurn[]): ChatMessage[] {\n const messages: ChatMessage[] = [];\n\n for (const turn of turns) {\n const role = turn.role ?? \"user\";\n\n if (role === \"user\") {\n const funcResponses = turn.parts.filter((p) => p.functionResponse);\n // inlineData parts (e.g. client audio input) are silently skipped —\n // only text and functionResponse parts are relevant for fixture matching.\n const textParts = turn.parts.filter((p) => p.text !== undefined && !p.thought);\n\n if (funcResponses.length > 0) {\n for (let i = 0; i < funcResponses.length; i++) {\n const part = funcResponses[i];\n const fr = part.functionResponse!;\n messages.push({\n role: \"tool\",\n content: typeof fr.response === \"string\" ? fr.response : JSON.stringify(fr.response),\n tool_call_id: fr.id ?? `call_gemini_${fr.name}_${i}`,\n });\n }\n if (textParts.length > 0) {\n messages.push({\n role: \"user\",\n content: textParts.map((p) => p.text!).join(\"\"),\n });\n }\n } else {\n const text = textParts.map((p) => p.text!).join(\"\");\n messages.push({ role: \"user\", content: text });\n }\n } else if (role === \"model\") {\n const funcCalls = turn.parts.filter((p) => p.functionCall);\n const textParts = turn.parts.filter((p) => p.text !== undefined && !p.thought);\n\n if (funcCalls.length > 0) {\n messages.push({\n role: \"assistant\",\n content: null,\n tool_calls: funcCalls.map((p, i) => ({\n id: `call_gemini_${p.functionCall!.name}_${i}`,\n type: \"function\" as const,\n function: {\n name: p.functionCall!.name,\n arguments: JSON.stringify(p.functionCall!.args),\n },\n })),\n });\n } else {\n const text = textParts.map((p) => p.text!).join(\"\");\n messages.push({ role: \"assistant\", content: text });\n }\n }\n }\n\n return messages;\n}\n\n/**\n * Convert toolResponse messages into ChatMessage[] for fixture matching.\n */\nfunction toolResponseToMessages(toolResponse: GeminiLiveToolResponse): ChatMessage[] {\n return toolResponse.functionResponses.map((fr, i) => ({\n role: \"tool\" as const,\n content: typeof fr.response === \"string\" ? fr.response : JSON.stringify(fr.response),\n tool_call_id: fr.id ?? `call_gemini_${fr.name}_${i}`,\n }));\n}\n\n/**\n * Convert Gemini tool definitions to ChatCompletion ToolDefinition[].\n */\nfunction convertTools(geminiTools?: GeminiLiveToolDef[]): ToolDefinition[] {\n if (!geminiTools || geminiTools.length === 0) return [];\n const decls = geminiTools.flatMap((t) => t.functionDeclarations ?? []);\n return decls.map((d) => ({\n type: \"function\" as const,\n function: {\n name: d.name,\n description: d.description,\n parameters: d.parameters,\n },\n }));\n}\n\n// ─── Main handler ───────────────────────────────────────────────────────────\n\nexport function handleWebSocketGeminiLive(\n ws: WebSocketConnection,\n fixtures: Fixture[],\n journal: Journal,\n defaults: {\n latency: number;\n chunkSize: number;\n model: string;\n logger: Logger;\n strict?: boolean;\n requestTransform?: (req: ChatCompletionRequest) => ChatCompletionRequest;\n testId?: string;\n },\n): void {\n const { logger } = defaults;\n const session: SessionState = {\n setupDone: false,\n model: defaults.model,\n tools: [],\n conversationHistory: [],\n };\n\n let pending = Promise.resolve();\n ws.on(\"message\", (raw: string) => {\n pending = pending.then(() =>\n processMessage(raw, ws, fixtures, journal, defaults, session).catch((err: unknown) => {\n const msg = err instanceof Error ? err.message : \"Internal error\";\n logger.error(`WebSocket Gemini Live error: ${msg}`);\n try {\n ws.send(\n JSON.stringify({\n error: { code: 500, message: msg, status: \"INTERNAL\" },\n }),\n );\n } catch {\n // Connection already gone — original error already logged above\n }\n }),\n );\n });\n}\n\nasync function processMessage(\n raw: string,\n ws: WebSocketConnection,\n fixtures: Fixture[],\n journal: Journal,\n defaults: {\n latency: number;\n chunkSize: number;\n model: string;\n logger: Logger;\n strict?: boolean;\n requestTransform?: (req: ChatCompletionRequest) => ChatCompletionRequest;\n testId?: string;\n },\n session: SessionState,\n): Promise<void> {\n let parsed: GeminiLiveMessage;\n try {\n parsed = JSON.parse(raw) as GeminiLiveMessage;\n } catch {\n ws.send(\n JSON.stringify({\n error: { code: 400, message: \"Malformed JSON\", status: \"INVALID_ARGUMENT\" },\n }),\n );\n return;\n }\n\n // Handle setup message\n if (parsed.setup) {\n session.setupDone = true;\n session.model = parsed.setup.model ?? defaults.model;\n session.tools = convertTools(parsed.setup.tools);\n ws.send(JSON.stringify({ setupComplete: {} }));\n return;\n }\n\n // Reject messages before setup\n if (!session.setupDone) {\n ws.send(\n JSON.stringify({\n error: { code: 400, message: \"Setup required\", status: \"FAILED_PRECONDITION\" },\n }),\n );\n return;\n }\n\n // Build messages from this interaction\n let newMessages: ChatMessage[];\n\n if (parsed.clientContent) {\n if (!parsed.clientContent.turns || !Array.isArray(parsed.clientContent.turns)) {\n ws.send(\n JSON.stringify({\n error: {\n code: 400,\n message: \"Missing 'turns' in clientContent\",\n status: \"INVALID_ARGUMENT\",\n },\n }),\n );\n return;\n }\n newMessages = geminiTurnsToMessages(parsed.clientContent.turns);\n } else if (parsed.toolResponse) {\n if (\n !parsed.toolResponse.functionResponses ||\n !Array.isArray(parsed.toolResponse.functionResponses)\n ) {\n ws.send(\n JSON.stringify({\n error: {\n code: 400,\n message: \"Missing 'functionResponses' in toolResponse\",\n status: \"INVALID_ARGUMENT\",\n },\n }),\n );\n return;\n }\n newMessages = toolResponseToMessages(parsed.toolResponse);\n } else {\n ws.send(\n JSON.stringify({\n error: {\n code: 400,\n message: \"Expected clientContent or toolResponse\",\n status: \"INVALID_ARGUMENT\",\n },\n }),\n );\n return;\n }\n\n // Build completion request for fixture matching (include new messages speculatively)\n const completionReq: ChatCompletionRequest = {\n model: session.model,\n messages: [...session.conversationHistory, ...newMessages],\n stream: true,\n tools: session.tools.length > 0 ? session.tools : undefined,\n };\n\n const testId = defaults.testId ?? DEFAULT_TEST_ID;\n const fixture = matchFixture(\n fixtures,\n completionReq,\n journal.getFixtureMatchCountsForTest(testId),\n defaults.requestTransform,\n );\n const path = WS_PATH;\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n }\n\n if (!fixture) {\n if (defaults.strict) {\n defaults.logger.warn(`STRICT: No fixture matched for WebSocket message`);\n journal.add({\n method: \"WS\",\n path,\n headers: {},\n body: completionReq,\n response: { status: 404, fixture: null },\n });\n ws.close(1008, \"Strict mode: no fixture matched\");\n return;\n }\n journal.add({\n method: \"WS\",\n path,\n headers: {},\n body: completionReq,\n response: { status: 404, fixture: null },\n });\n ws.send(\n JSON.stringify({\n error: { code: 404, message: \"No fixture matched\", status: \"NOT_FOUND\" },\n }),\n );\n return;\n }\n\n // Commit messages to conversation history only after successful fixture match\n session.conversationHistory.push(...newMessages);\n\n const response = await resolveResponse(fixture, completionReq);\n const latency = fixture.latency ?? defaults.latency;\n const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);\n\n // Error response\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method: \"WS\",\n path,\n headers: {},\n body: completionReq,\n response: { status, fixture },\n });\n ws.send(\n JSON.stringify({\n error: {\n code: status,\n message: response.error.message,\n status: response.error.type ?? \"INTERNAL\",\n },\n }),\n );\n return;\n }\n\n // Audio response — single frame with inlineData and turnComplete: true\n if (isAudioResponse(response)) {\n journal.add({\n method: \"WS\",\n path,\n headers: {},\n body: completionReq,\n response: { status: 200, fixture },\n });\n\n const audioResp = response as AudioResponse;\n let mimeType: string;\n let data: string;\n\n if (typeof audioResp.audio === \"string\") {\n mimeType = formatToMime(audioResp.format ?? \"mp3\");\n data = audioResp.audio;\n } else {\n mimeType = audioResp.audio.contentType ?? \"audio/mpeg\";\n data = audioResp.audio.b64Json;\n }\n\n ws.send(\n JSON.stringify({\n serverContent: {\n modelTurn: {\n parts: [{ inlineData: { mimeType, data } }],\n },\n turnComplete: true,\n },\n }),\n );\n\n session.conversationHistory.push({\n role: \"assistant\",\n content: \"[audio]\",\n });\n return;\n }\n\n // Content + tool calls response (must be checked before isTextResponse / isToolCallResponse)\n if (isContentWithToolCallsResponse(response)) {\n const journalEntry = journal.add({\n method: \"WS\",\n path,\n headers: {},\n body: completionReq,\n response: { status: 200, fixture },\n });\n\n const content = response.content;\n const chunkList: string[] = [];\n for (let i = 0; i < content.length; i += chunkSize) {\n chunkList.push(content.slice(i, i + chunkSize));\n }\n\n const interruption = createInterruptionSignal(fixture);\n let interrupted = false;\n\n // Stream text content chunks\n if (content.length === 0) {\n if (!ws.isClosed) {\n ws.send(\n JSON.stringify({\n serverContent: {\n modelTurn: { parts: [{ text: \"\" }] },\n turnComplete: false,\n },\n }),\n );\n }\n } else {\n for (let i = 0; i < chunkList.length; i++) {\n if (ws.isClosed) break;\n if (latency > 0) await delay(latency, interruption?.signal);\n if (interruption?.signal.aborted) {\n interrupted = true;\n break;\n }\n if (ws.isClosed) break;\n\n ws.send(\n JSON.stringify({\n serverContent: {\n modelTurn: { parts: [{ text: chunkList[i] }] },\n turnComplete: false,\n },\n }),\n );\n interruption?.tick();\n if (interruption?.signal.aborted) {\n interrupted = true;\n break;\n }\n }\n }\n\n if (interrupted) {\n ws.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n interruption?.cleanup();\n return;\n }\n\n // Pre-compute tool calls with stable IDs so wire message and history match\n const resolvedToolCalls = response.toolCalls.map((tc) => ({\n ...tc,\n resolvedId: tc.id ?? generateToolCallId(),\n }));\n\n // Send tool calls\n if (!ws.isClosed) {\n if (latency > 0) await delay(latency, interruption?.signal);\n if (interruption?.signal.aborted) {\n ws.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n interruption?.cleanup();\n return;\n }\n\n const functionCalls = resolvedToolCalls.map((tc) => {\n let argsObj: Record<string, unknown>;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\") as Record<string, unknown>;\n } catch {\n defaults.logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n return {\n name: tc.name,\n args: argsObj,\n id: tc.resolvedId,\n };\n });\n\n ws.send(JSON.stringify({ toolCall: { functionCalls } }));\n interruption?.tick();\n }\n\n if (interruption?.signal.aborted) {\n ws.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n interruption?.cleanup();\n return;\n }\n\n interruption?.cleanup();\n\n // Send turnComplete\n if (!ws.isClosed) {\n ws.send(\n JSON.stringify({\n serverContent: { turnComplete: true },\n }),\n );\n }\n\n // Add to conversation history using the same resolved IDs from the wire message\n session.conversationHistory.push({\n role: \"assistant\",\n content: content || null,\n tool_calls: resolvedToolCalls.map((tc) => ({\n id: tc.resolvedId,\n type: \"function\" as const,\n function: {\n name: tc.name,\n arguments: tc.arguments,\n },\n })),\n });\n return;\n }\n\n // Text response — stream chunks with serverContent\n if (isTextResponse(response)) {\n const journalEntry = journal.add({\n method: \"WS\",\n path,\n headers: {},\n body: completionReq,\n response: { status: 200, fixture },\n });\n\n const content = response.content;\n\n if (content.length === 0) {\n if (ws.isClosed) return;\n ws.send(\n JSON.stringify({\n serverContent: {\n modelTurn: { parts: [{ text: \"\" }] },\n turnComplete: true,\n },\n }),\n );\n return;\n }\n\n // Chunk the content\n const chunks: string[] = [];\n for (let i = 0; i < content.length; i += chunkSize) {\n chunks.push(content.slice(i, i + chunkSize));\n }\n\n const interruption = createInterruptionSignal(fixture);\n let interrupted = false;\n\n for (let i = 0; i < chunks.length; i++) {\n if (ws.isClosed) break;\n if (latency > 0) await delay(latency, interruption?.signal);\n if (interruption?.signal.aborted) {\n interrupted = true;\n break;\n }\n if (ws.isClosed) break;\n\n const isLast = i === chunks.length - 1;\n ws.send(\n JSON.stringify({\n serverContent: {\n modelTurn: { parts: [{ text: chunks[i] }] },\n turnComplete: isLast,\n },\n }),\n );\n interruption?.tick();\n if (interruption?.signal.aborted) {\n interrupted = true;\n break;\n }\n }\n\n if (interrupted) {\n ws.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n interruption?.cleanup();\n return;\n }\n\n interruption?.cleanup();\n\n // Add assistant response to conversation history\n session.conversationHistory.push({ role: \"assistant\", content });\n return;\n }\n\n // Tool call response\n if (isToolCallResponse(response)) {\n const journalEntry = journal.add({\n method: \"WS\",\n path,\n headers: {},\n body: completionReq,\n response: { status: 200, fixture },\n });\n\n const interruption = createInterruptionSignal(fixture);\n\n if (ws.isClosed) {\n interruption?.cleanup();\n return;\n }\n if (latency > 0) await delay(latency, interruption?.signal);\n if (interruption?.signal.aborted) {\n ws.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n interruption?.cleanup();\n return;\n }\n if (ws.isClosed) {\n interruption?.cleanup();\n return;\n }\n\n const functionCalls = response.toolCalls.map((tc, i) => {\n let argsObj: Record<string, unknown>;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\") as Record<string, unknown>;\n } catch {\n defaults.logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n return {\n name: tc.name,\n args: argsObj,\n id: tc.id ?? `call_gemini_${tc.name}_${i}`,\n };\n });\n\n ws.send(JSON.stringify({ toolCall: { functionCalls } }));\n interruption?.tick();\n\n if (interruption?.signal.aborted) {\n ws.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n interruption?.cleanup();\n return;\n }\n\n interruption?.cleanup();\n\n // Add assistant tool_calls to conversation history\n session.conversationHistory.push({\n role: \"assistant\",\n content: null,\n tool_calls: response.toolCalls.map((tc, i) => ({\n id: tc.id ?? `call_gemini_${tc.name}_${i}`,\n type: \"function\" as const,\n function: {\n name: tc.name,\n arguments: tc.arguments,\n },\n })),\n });\n return;\n }\n\n // Unknown response type\n journal.add({\n method: \"WS\",\n path,\n headers: {},\n body: completionReq,\n response: { status: 500, fixture },\n });\n ws.send(\n JSON.stringify({\n error: {\n code: 500,\n message: \"Fixture response did not match any known type\",\n status: \"INTERNAL\",\n },\n }),\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ws-gemini-live.cjs","names":["DEFAULT_TEST_ID","matchFixture","resolveResponse","isErrorResponse","isAudioResponse","formatToMime","isContentWithToolCallsResponse","createInterruptionSignal","delay","generateToolCallId","isTextResponse","isToolCallResponse"],"sources":["../src/ws-gemini-live.ts"],"sourcesContent":["/**\n * WebSocket handler for Gemini Live BidiGenerateContent API.\n *\n * Accepts setup, clientContent, and toolResponse messages over WebSocket\n * and responds with setupComplete, serverContent, toolCall, and error\n * messages in the Gemini Live streaming format.\n */\n\nimport type {\n Fixture,\n ChatMessage,\n ChatCompletionRequest,\n ToolDefinition,\n AudioResponse,\n} from \"./types.js\";\nimport { matchFixture } from \"./router.js\";\nimport {\n isTextResponse,\n isToolCallResponse,\n isContentWithToolCallsResponse,\n isErrorResponse,\n isAudioResponse,\n formatToMime,\n generateToolCallId,\n resolveResponse,\n} from \"./helpers.js\";\nimport { createInterruptionSignal } from \"./interruption.js\";\nimport { delay } from \"./sse-writer.js\";\nimport { DEFAULT_TEST_ID, type Journal } from \"./journal.js\";\nimport type { Logger } from \"./logger.js\";\nimport type { WebSocketConnection } from \"./ws-framing.js\";\n\n// ─── Gemini Live protocol types ─────────────────────────────────────────────\n\ninterface GeminiLivePart {\n text?: string;\n thought?: boolean;\n functionCall?: { name: string; args: Record<string, unknown> };\n functionResponse?: { name: string; response: unknown; id?: string };\n inlineData?: { mimeType: string; data: string };\n}\n\ninterface GeminiLiveTurn {\n role: string;\n parts: GeminiLivePart[];\n}\n\ninterface GeminiLiveFunctionDeclaration {\n name: string;\n description?: string;\n parameters?: object;\n}\n\ninterface GeminiLiveToolDef {\n functionDeclarations?: GeminiLiveFunctionDeclaration[];\n}\n\ninterface GeminiLiveSetup {\n model?: string;\n generationConfig?: Record<string, unknown>;\n tools?: GeminiLiveToolDef[];\n}\n\ninterface GeminiLiveClientContent {\n turns: GeminiLiveTurn[];\n turnComplete?: boolean;\n}\n\ninterface GeminiLiveFunctionResponse {\n id?: string;\n name: string;\n response: unknown;\n}\n\ninterface GeminiLiveToolResponse {\n functionResponses: GeminiLiveFunctionResponse[];\n}\n\ninterface GeminiLiveMessage {\n setup?: GeminiLiveSetup;\n config?: GeminiLiveSetup;\n clientContent?: GeminiLiveClientContent;\n toolResponse?: GeminiLiveToolResponse;\n}\n\n// ─── Session state ──────────────────────────────────────────────────────────\n\ninterface SessionState {\n setupDone: boolean;\n model: string;\n tools: ToolDefinition[];\n conversationHistory: ChatMessage[];\n}\n\n// ─── Helpers ────────────────────────────────────────────────────────────────\n\nconst WS_PATH = \"/ws/google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent\";\n\n/**\n * Map HTTP status codes to gRPC error codes.\n * Gemini Live uses gRPC codes, not HTTP status codes.\n */\nfunction httpToGrpc(httpCode: number): number {\n switch (httpCode) {\n case 400:\n return 3; // INVALID_ARGUMENT\n case 401:\n return 16; // UNAUTHENTICATED\n case 403:\n return 7; // PERMISSION_DENIED\n case 404:\n return 5; // NOT_FOUND\n case 409:\n return 10; // ABORTED\n case 429:\n return 8; // RESOURCE_EXHAUSTED\n case 501:\n return 12; // UNIMPLEMENTED\n case 503:\n return 14; // UNAVAILABLE\n default:\n return 13; // INTERNAL\n }\n}\n\n/**\n * Convert Gemini Live turns into ChatMessage[] for fixture matching.\n */\nfunction geminiTurnsToMessages(turns: GeminiLiveTurn[]): ChatMessage[] {\n const messages: ChatMessage[] = [];\n\n for (const turn of turns) {\n const role = turn.role ?? \"user\";\n\n if (role === \"user\") {\n const funcResponses = turn.parts.filter((p) => p.functionResponse);\n // inlineData parts (e.g. client audio input) are silently skipped —\n // only text and functionResponse parts are relevant for fixture matching.\n const textParts = turn.parts.filter((p) => p.text !== undefined && !p.thought);\n\n if (funcResponses.length > 0) {\n for (let i = 0; i < funcResponses.length; i++) {\n const part = funcResponses[i];\n const fr = part.functionResponse!;\n messages.push({\n role: \"tool\",\n content: typeof fr.response === \"string\" ? fr.response : JSON.stringify(fr.response),\n tool_call_id: fr.id ?? `call_gemini_${fr.name}_${i}`,\n });\n }\n if (textParts.length > 0) {\n messages.push({\n role: \"user\",\n content: textParts.map((p) => p.text!).join(\"\"),\n });\n }\n } else {\n const text = textParts.map((p) => p.text!).join(\"\");\n messages.push({ role: \"user\", content: text });\n }\n } else if (role === \"model\") {\n const funcCalls = turn.parts.filter((p) => p.functionCall);\n const textParts = turn.parts.filter((p) => p.text !== undefined && !p.thought);\n\n if (funcCalls.length > 0) {\n messages.push({\n role: \"assistant\",\n content: null,\n tool_calls: funcCalls.map((p, i) => ({\n id: `call_gemini_${p.functionCall!.name}_${i}`,\n type: \"function\" as const,\n function: {\n name: p.functionCall!.name,\n arguments: JSON.stringify(p.functionCall!.args),\n },\n })),\n });\n } else {\n const text = textParts.map((p) => p.text!).join(\"\");\n messages.push({ role: \"assistant\", content: text });\n }\n }\n }\n\n return messages;\n}\n\n/**\n * Convert toolResponse messages into ChatMessage[] for fixture matching.\n */\nfunction toolResponseToMessages(toolResponse: GeminiLiveToolResponse): ChatMessage[] {\n return toolResponse.functionResponses.map((fr, i) => ({\n role: \"tool\" as const,\n content: typeof fr.response === \"string\" ? fr.response : JSON.stringify(fr.response),\n tool_call_id: fr.id ?? `call_gemini_${fr.name}_${i}`,\n }));\n}\n\n/**\n * Convert Gemini tool definitions to ChatCompletion ToolDefinition[].\n */\nfunction convertTools(geminiTools?: GeminiLiveToolDef[]): ToolDefinition[] {\n if (!geminiTools || geminiTools.length === 0) return [];\n const decls = geminiTools.flatMap((t) => t.functionDeclarations ?? []);\n return decls.map((d) => ({\n type: \"function\" as const,\n function: {\n name: d.name,\n description: d.description,\n parameters: d.parameters,\n },\n }));\n}\n\n// ─── Main handler ───────────────────────────────────────────────────────────\n\nexport function handleWebSocketGeminiLive(\n ws: WebSocketConnection,\n fixtures: Fixture[],\n journal: Journal,\n defaults: {\n latency: number;\n chunkSize: number;\n model: string;\n logger: Logger;\n strict?: boolean;\n requestTransform?: (req: ChatCompletionRequest) => ChatCompletionRequest;\n testId?: string;\n },\n): void {\n const { logger } = defaults;\n const session: SessionState = {\n setupDone: false,\n model: defaults.model,\n tools: [],\n conversationHistory: [],\n };\n\n let pending = Promise.resolve();\n ws.on(\"message\", (raw: string) => {\n pending = pending.then(() =>\n processMessage(raw, ws, fixtures, journal, defaults, session).catch((err: unknown) => {\n const msg = err instanceof Error ? err.message : \"Internal error\";\n logger.error(`WebSocket Gemini Live error: ${msg}`);\n try {\n ws.send(\n JSON.stringify({\n error: { code: 13, message: msg, status: \"INTERNAL\" },\n }),\n );\n } catch {\n // Connection already gone — original error already logged above\n }\n }),\n );\n });\n}\n\nasync function processMessage(\n raw: string,\n ws: WebSocketConnection,\n fixtures: Fixture[],\n journal: Journal,\n defaults: {\n latency: number;\n chunkSize: number;\n model: string;\n logger: Logger;\n strict?: boolean;\n requestTransform?: (req: ChatCompletionRequest) => ChatCompletionRequest;\n testId?: string;\n },\n session: SessionState,\n): Promise<void> {\n let parsed: GeminiLiveMessage;\n try {\n parsed = JSON.parse(raw) as GeminiLiveMessage;\n } catch {\n ws.send(\n JSON.stringify({\n error: { code: 3, message: \"Malformed JSON\", status: \"INVALID_ARGUMENT\" },\n }),\n );\n return;\n }\n\n // Handle setup message (accept both `setup` and `config` as aliases)\n const setupMsg = parsed.setup ?? parsed.config;\n if (setupMsg) {\n session.setupDone = true;\n session.model = setupMsg.model ?? defaults.model;\n session.tools = convertTools(setupMsg.tools);\n ws.send(JSON.stringify({ setupComplete: {} }));\n return;\n }\n\n // Reject messages before setup\n if (!session.setupDone) {\n ws.send(\n JSON.stringify({\n error: { code: 9, message: \"Setup required\", status: \"FAILED_PRECONDITION\" },\n }),\n );\n return;\n }\n\n // Build messages from this interaction\n let newMessages: ChatMessage[];\n\n if (parsed.clientContent) {\n if (!parsed.clientContent.turns || !Array.isArray(parsed.clientContent.turns)) {\n ws.send(\n JSON.stringify({\n error: {\n code: 3,\n message: \"Missing 'turns' in clientContent\",\n status: \"INVALID_ARGUMENT\",\n },\n }),\n );\n return;\n }\n newMessages = geminiTurnsToMessages(parsed.clientContent.turns);\n } else if (parsed.toolResponse) {\n if (\n !parsed.toolResponse.functionResponses ||\n !Array.isArray(parsed.toolResponse.functionResponses)\n ) {\n ws.send(\n JSON.stringify({\n error: {\n code: 3,\n message: \"Missing 'functionResponses' in toolResponse\",\n status: \"INVALID_ARGUMENT\",\n },\n }),\n );\n return;\n }\n newMessages = toolResponseToMessages(parsed.toolResponse);\n } else {\n ws.send(\n JSON.stringify({\n error: {\n code: 3,\n message: \"Expected clientContent or toolResponse\",\n status: \"INVALID_ARGUMENT\",\n },\n }),\n );\n return;\n }\n\n // Build completion request for fixture matching (include new messages speculatively)\n const completionReq: ChatCompletionRequest = {\n model: session.model,\n messages: [...session.conversationHistory, ...newMessages],\n stream: true,\n tools: session.tools.length > 0 ? session.tools : undefined,\n };\n\n const testId = defaults.testId ?? DEFAULT_TEST_ID;\n const fixture = matchFixture(\n fixtures,\n completionReq,\n journal.getFixtureMatchCountsForTest(testId),\n defaults.requestTransform,\n );\n const path = WS_PATH;\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n }\n\n if (!fixture) {\n if (defaults.strict) {\n defaults.logger.warn(`STRICT: No fixture matched for WebSocket message`);\n journal.add({\n method: \"WS\",\n path,\n headers: {},\n body: completionReq,\n response: { status: 404, fixture: null },\n });\n ws.close(1008, \"Strict mode: no fixture matched\");\n return;\n }\n journal.add({\n method: \"WS\",\n path,\n headers: {},\n body: completionReq,\n response: { status: 404, fixture: null },\n });\n ws.send(\n JSON.stringify({\n error: { code: 5, message: \"No fixture matched\", status: \"NOT_FOUND\" },\n }),\n );\n return;\n }\n\n // Commit messages to conversation history only after successful fixture match\n session.conversationHistory.push(...newMessages);\n\n const response = await resolveResponse(fixture, completionReq);\n const latency = fixture.latency ?? defaults.latency;\n const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);\n\n // Error response\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method: \"WS\",\n path,\n headers: {},\n body: completionReq,\n response: { status, fixture },\n });\n ws.send(\n JSON.stringify({\n error: {\n code: httpToGrpc(status),\n message: response.error.message,\n status: response.error.type ?? \"INTERNAL\",\n },\n }),\n );\n return;\n }\n\n // Audio response — single frame with inlineData and turnComplete: true\n if (isAudioResponse(response)) {\n journal.add({\n method: \"WS\",\n path,\n headers: {},\n body: completionReq,\n response: { status: 200, fixture },\n });\n\n const audioResp = response as AudioResponse;\n let mimeType: string;\n let data: string;\n\n if (typeof audioResp.audio === \"string\") {\n mimeType = formatToMime(audioResp.format ?? \"mp3\");\n data = audioResp.audio;\n } else {\n mimeType = audioResp.audio.contentType ?? \"audio/mpeg\";\n data = audioResp.audio.b64Json;\n }\n\n ws.send(\n JSON.stringify({\n serverContent: {\n modelTurn: {\n parts: [{ inlineData: { mimeType, data } }],\n },\n turnComplete: true,\n },\n }),\n );\n\n session.conversationHistory.push({\n role: \"assistant\",\n content: \"[audio]\",\n });\n return;\n }\n\n // Content + tool calls response (must be checked before isTextResponse / isToolCallResponse)\n if (isContentWithToolCallsResponse(response)) {\n const journalEntry = journal.add({\n method: \"WS\",\n path,\n headers: {},\n body: completionReq,\n response: { status: 200, fixture },\n });\n\n const content = response.content;\n const chunkList: string[] = [];\n for (let i = 0; i < content.length; i += chunkSize) {\n chunkList.push(content.slice(i, i + chunkSize));\n }\n\n const interruption = createInterruptionSignal(fixture);\n let interrupted = false;\n\n // Stream text content chunks (turnComplete omitted — sent as a separate message later)\n if (content.length === 0) {\n if (!ws.isClosed) {\n ws.send(\n JSON.stringify({\n serverContent: {\n modelTurn: { parts: [{ text: \"\" }] },\n },\n }),\n );\n }\n } else {\n for (let i = 0; i < chunkList.length; i++) {\n if (ws.isClosed) break;\n if (latency > 0) await delay(latency, interruption?.signal);\n if (interruption?.signal.aborted) {\n interrupted = true;\n break;\n }\n if (ws.isClosed) break;\n\n ws.send(\n JSON.stringify({\n serverContent: {\n modelTurn: { parts: [{ text: chunkList[i] }] },\n },\n }),\n );\n interruption?.tick();\n if (interruption?.signal.aborted) {\n interrupted = true;\n break;\n }\n }\n }\n\n if (interrupted) {\n ws.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n interruption?.cleanup();\n return;\n }\n\n // Pre-compute tool calls with stable IDs so wire message and history match\n const resolvedToolCalls = response.toolCalls.map((tc) => ({\n ...tc,\n resolvedId: tc.id ?? generateToolCallId(),\n }));\n\n // Send tool calls\n if (!ws.isClosed) {\n if (latency > 0) await delay(latency, interruption?.signal);\n if (interruption?.signal.aborted) {\n ws.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n interruption?.cleanup();\n return;\n }\n\n const functionCalls = resolvedToolCalls.map((tc) => {\n let argsObj: Record<string, unknown>;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\") as Record<string, unknown>;\n } catch {\n defaults.logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n return {\n name: tc.name,\n args: argsObj,\n id: tc.resolvedId,\n };\n });\n\n ws.send(JSON.stringify({ toolCall: { functionCalls } }));\n interruption?.tick();\n }\n\n if (interruption?.signal.aborted) {\n ws.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n interruption?.cleanup();\n return;\n }\n\n interruption?.cleanup();\n\n // Send turnComplete\n if (!ws.isClosed) {\n ws.send(\n JSON.stringify({\n serverContent: { turnComplete: true },\n }),\n );\n }\n\n // Add to conversation history using the same resolved IDs from the wire message\n session.conversationHistory.push({\n role: \"assistant\",\n content: content || null,\n tool_calls: resolvedToolCalls.map((tc) => ({\n id: tc.resolvedId,\n type: \"function\" as const,\n function: {\n name: tc.name,\n arguments: tc.arguments,\n },\n })),\n });\n return;\n }\n\n // Text response — stream chunks with serverContent\n if (isTextResponse(response)) {\n const journalEntry = journal.add({\n method: \"WS\",\n path,\n headers: {},\n body: completionReq,\n response: { status: 200, fixture },\n });\n\n const content = response.content;\n\n if (content.length === 0) {\n if (ws.isClosed) return;\n // Empty content: send empty modelTurn, then separate turnComplete\n ws.send(\n JSON.stringify({\n serverContent: {\n modelTurn: { parts: [{ text: \"\" }] },\n },\n }),\n );\n ws.send(\n JSON.stringify({\n serverContent: { turnComplete: true },\n }),\n );\n return;\n }\n\n // Chunk the content\n const chunks: string[] = [];\n for (let i = 0; i < content.length; i += chunkSize) {\n chunks.push(content.slice(i, i + chunkSize));\n }\n\n const interruption = createInterruptionSignal(fixture);\n let interrupted = false;\n\n // Stream content chunks without turnComplete (sent separately after)\n for (let i = 0; i < chunks.length; i++) {\n if (ws.isClosed) break;\n if (latency > 0) await delay(latency, interruption?.signal);\n if (interruption?.signal.aborted) {\n interrupted = true;\n break;\n }\n if (ws.isClosed) break;\n\n ws.send(\n JSON.stringify({\n serverContent: {\n modelTurn: { parts: [{ text: chunks[i] }] },\n },\n }),\n );\n interruption?.tick();\n if (interruption?.signal.aborted) {\n interrupted = true;\n break;\n }\n }\n\n if (interrupted) {\n ws.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n interruption?.cleanup();\n return;\n }\n\n interruption?.cleanup();\n\n // Send separate turnComplete message\n if (!ws.isClosed) {\n ws.send(\n JSON.stringify({\n serverContent: { turnComplete: true },\n }),\n );\n }\n\n // Add assistant response to conversation history\n session.conversationHistory.push({ role: \"assistant\", content });\n return;\n }\n\n // Tool call response\n if (isToolCallResponse(response)) {\n const journalEntry = journal.add({\n method: \"WS\",\n path,\n headers: {},\n body: completionReq,\n response: { status: 200, fixture },\n });\n\n const interruption = createInterruptionSignal(fixture);\n\n if (ws.isClosed) {\n interruption?.cleanup();\n return;\n }\n if (latency > 0) await delay(latency, interruption?.signal);\n if (interruption?.signal.aborted) {\n ws.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n interruption?.cleanup();\n return;\n }\n if (ws.isClosed) {\n interruption?.cleanup();\n return;\n }\n\n const functionCalls = response.toolCalls.map((tc, i) => {\n let argsObj: Record<string, unknown>;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\") as Record<string, unknown>;\n } catch {\n defaults.logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n return {\n name: tc.name,\n args: argsObj,\n id: tc.id ?? `call_gemini_${tc.name}_${i}`,\n };\n });\n\n ws.send(JSON.stringify({ toolCall: { functionCalls } }));\n interruption?.tick();\n\n if (interruption?.signal.aborted) {\n ws.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n interruption?.cleanup();\n return;\n }\n\n interruption?.cleanup();\n\n // Send turnComplete after tool call\n if (!ws.isClosed) {\n ws.send(\n JSON.stringify({\n serverContent: { turnComplete: true },\n }),\n );\n }\n\n // Add assistant tool_calls to conversation history\n session.conversationHistory.push({\n role: \"assistant\",\n content: null,\n tool_calls: response.toolCalls.map((tc, i) => ({\n id: tc.id ?? `call_gemini_${tc.name}_${i}`,\n type: \"function\" as const,\n function: {\n name: tc.name,\n arguments: tc.arguments,\n },\n })),\n });\n return;\n }\n\n // Unknown response type\n journal.add({\n method: \"WS\",\n path,\n headers: {},\n body: completionReq,\n response: { status: 500, fixture },\n });\n ws.send(\n JSON.stringify({\n error: {\n code: 13,\n message: \"Fixture response did not match any known type\",\n status: \"INTERNAL\",\n },\n }),\n );\n}\n"],"mappings":";;;;;;;AAgGA,MAAM,UAAU;;;;;AAMhB,SAAS,WAAW,UAA0B;AAC5C,SAAQ,UAAR;EACE,KAAK,IACH,QAAO;EACT,KAAK,IACH,QAAO;EACT,KAAK,IACH,QAAO;EACT,KAAK,IACH,QAAO;EACT,KAAK,IACH,QAAO;EACT,KAAK,IACH,QAAO;EACT,KAAK,IACH,QAAO;EACT,KAAK,IACH,QAAO;EACT,QACE,QAAO;;;;;;AAOb,SAAS,sBAAsB,OAAwC;CACrE,MAAM,WAA0B,EAAE;AAElC,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,OAAO,KAAK,QAAQ;AAE1B,MAAI,SAAS,QAAQ;GACnB,MAAM,gBAAgB,KAAK,MAAM,QAAQ,MAAM,EAAE,iBAAiB;GAGlE,MAAM,YAAY,KAAK,MAAM,QAAQ,MAAM,EAAE,SAAS,UAAa,CAAC,EAAE,QAAQ;AAE9E,OAAI,cAAc,SAAS,GAAG;AAC5B,SAAK,IAAI,IAAI,GAAG,IAAI,cAAc,QAAQ,KAAK;KAE7C,MAAM,KADO,cAAc,GACX;AAChB,cAAS,KAAK;MACZ,MAAM;MACN,SAAS,OAAO,GAAG,aAAa,WAAW,GAAG,WAAW,KAAK,UAAU,GAAG,SAAS;MACpF,cAAc,GAAG,MAAM,eAAe,GAAG,KAAK,GAAG;MAClD,CAAC;;AAEJ,QAAI,UAAU,SAAS,EACrB,UAAS,KAAK;KACZ,MAAM;KACN,SAAS,UAAU,KAAK,MAAM,EAAE,KAAM,CAAC,KAAK,GAAG;KAChD,CAAC;UAEC;IACL,MAAM,OAAO,UAAU,KAAK,MAAM,EAAE,KAAM,CAAC,KAAK,GAAG;AACnD,aAAS,KAAK;KAAE,MAAM;KAAQ,SAAS;KAAM,CAAC;;aAEvC,SAAS,SAAS;GAC3B,MAAM,YAAY,KAAK,MAAM,QAAQ,MAAM,EAAE,aAAa;GAC1D,MAAM,YAAY,KAAK,MAAM,QAAQ,MAAM,EAAE,SAAS,UAAa,CAAC,EAAE,QAAQ;AAE9E,OAAI,UAAU,SAAS,EACrB,UAAS,KAAK;IACZ,MAAM;IACN,SAAS;IACT,YAAY,UAAU,KAAK,GAAG,OAAO;KACnC,IAAI,eAAe,EAAE,aAAc,KAAK,GAAG;KAC3C,MAAM;KACN,UAAU;MACR,MAAM,EAAE,aAAc;MACtB,WAAW,KAAK,UAAU,EAAE,aAAc,KAAK;MAChD;KACF,EAAE;IACJ,CAAC;QACG;IACL,MAAM,OAAO,UAAU,KAAK,MAAM,EAAE,KAAM,CAAC,KAAK,GAAG;AACnD,aAAS,KAAK;KAAE,MAAM;KAAa,SAAS;KAAM,CAAC;;;;AAKzD,QAAO;;;;;AAMT,SAAS,uBAAuB,cAAqD;AACnF,QAAO,aAAa,kBAAkB,KAAK,IAAI,OAAO;EACpD,MAAM;EACN,SAAS,OAAO,GAAG,aAAa,WAAW,GAAG,WAAW,KAAK,UAAU,GAAG,SAAS;EACpF,cAAc,GAAG,MAAM,eAAe,GAAG,KAAK,GAAG;EAClD,EAAE;;;;;AAML,SAAS,aAAa,aAAqD;AACzE,KAAI,CAAC,eAAe,YAAY,WAAW,EAAG,QAAO,EAAE;AAEvD,QADc,YAAY,SAAS,MAAM,EAAE,wBAAwB,EAAE,CAAC,CACzD,KAAK,OAAO;EACvB,MAAM;EACN,UAAU;GACR,MAAM,EAAE;GACR,aAAa,EAAE;GACf,YAAY,EAAE;GACf;EACF,EAAE;;AAKL,SAAgB,0BACd,IACA,UACA,SACA,UASM;CACN,MAAM,EAAE,WAAW;CACnB,MAAM,UAAwB;EAC5B,WAAW;EACX,OAAO,SAAS;EAChB,OAAO,EAAE;EACT,qBAAqB,EAAE;EACxB;CAED,IAAI,UAAU,QAAQ,SAAS;AAC/B,IAAG,GAAG,YAAY,QAAgB;AAChC,YAAU,QAAQ,WAChB,eAAe,KAAK,IAAI,UAAU,SAAS,UAAU,QAAQ,CAAC,OAAO,QAAiB;GACpF,MAAM,MAAM,eAAe,QAAQ,IAAI,UAAU;AACjD,UAAO,MAAM,gCAAgC,MAAM;AACnD,OAAI;AACF,OAAG,KACD,KAAK,UAAU,EACb,OAAO;KAAE,MAAM;KAAI,SAAS;KAAK,QAAQ;KAAY,EACtD,CAAC,CACH;WACK;IAGR,CACH;GACD;;AAGJ,eAAe,eACb,KACA,IACA,UACA,SACA,UASA,SACe;CACf,IAAI;AACJ,KAAI;AACF,WAAS,KAAK,MAAM,IAAI;SAClB;AACN,KAAG,KACD,KAAK,UAAU,EACb,OAAO;GAAE,MAAM;GAAG,SAAS;GAAkB,QAAQ;GAAoB,EAC1E,CAAC,CACH;AACD;;CAIF,MAAM,WAAW,OAAO,SAAS,OAAO;AACxC,KAAI,UAAU;AACZ,UAAQ,YAAY;AACpB,UAAQ,QAAQ,SAAS,SAAS,SAAS;AAC3C,UAAQ,QAAQ,aAAa,SAAS,MAAM;AAC5C,KAAG,KAAK,KAAK,UAAU,EAAE,eAAe,EAAE,EAAE,CAAC,CAAC;AAC9C;;AAIF,KAAI,CAAC,QAAQ,WAAW;AACtB,KAAG,KACD,KAAK,UAAU,EACb,OAAO;GAAE,MAAM;GAAG,SAAS;GAAkB,QAAQ;GAAuB,EAC7E,CAAC,CACH;AACD;;CAIF,IAAI;AAEJ,KAAI,OAAO,eAAe;AACxB,MAAI,CAAC,OAAO,cAAc,SAAS,CAAC,MAAM,QAAQ,OAAO,cAAc,MAAM,EAAE;AAC7E,MAAG,KACD,KAAK,UAAU,EACb,OAAO;IACL,MAAM;IACN,SAAS;IACT,QAAQ;IACT,EACF,CAAC,CACH;AACD;;AAEF,gBAAc,sBAAsB,OAAO,cAAc,MAAM;YACtD,OAAO,cAAc;AAC9B,MACE,CAAC,OAAO,aAAa,qBACrB,CAAC,MAAM,QAAQ,OAAO,aAAa,kBAAkB,EACrD;AACA,MAAG,KACD,KAAK,UAAU,EACb,OAAO;IACL,MAAM;IACN,SAAS;IACT,QAAQ;IACT,EACF,CAAC,CACH;AACD;;AAEF,gBAAc,uBAAuB,OAAO,aAAa;QACpD;AACL,KAAG,KACD,KAAK,UAAU,EACb,OAAO;GACL,MAAM;GACN,SAAS;GACT,QAAQ;GACT,EACF,CAAC,CACH;AACD;;CAIF,MAAM,gBAAuC;EAC3C,OAAO,QAAQ;EACf,UAAU,CAAC,GAAG,QAAQ,qBAAqB,GAAG,YAAY;EAC1D,QAAQ;EACR,OAAO,QAAQ,MAAM,SAAS,IAAI,QAAQ,QAAQ;EACnD;CAED,MAAM,SAAS,SAAS,UAAUA;CAClC,MAAM,UAAUC,4BACd,UACA,eACA,QAAQ,6BAA6B,OAAO,EAC5C,SAAS,iBACV;CACD,MAAM,OAAO;AAEb,KAAI,QACF,SAAQ,2BAA2B,SAAS,UAAU,OAAO;AAG/D,KAAI,CAAC,SAAS;AACZ,MAAI,SAAS,QAAQ;AACnB,YAAS,OAAO,KAAK,mDAAmD;AACxE,WAAQ,IAAI;IACV,QAAQ;IACR;IACA,SAAS,EAAE;IACX,MAAM;IACN,UAAU;KAAE,QAAQ;KAAK,SAAS;KAAM;IACzC,CAAC;AACF,MAAG,MAAM,MAAM,kCAAkC;AACjD;;AAEF,UAAQ,IAAI;GACV,QAAQ;GACR;GACA,SAAS,EAAE;GACX,MAAM;GACN,UAAU;IAAE,QAAQ;IAAK,SAAS;IAAM;GACzC,CAAC;AACF,KAAG,KACD,KAAK,UAAU,EACb,OAAO;GAAE,MAAM;GAAG,SAAS;GAAsB,QAAQ;GAAa,EACvE,CAAC,CACH;AACD;;AAIF,SAAQ,oBAAoB,KAAK,GAAG,YAAY;CAEhD,MAAM,WAAW,MAAMC,gCAAgB,SAAS,cAAc;CAC9D,MAAM,UAAU,QAAQ,WAAW,SAAS;CAC5C,MAAM,YAAY,KAAK,IAAI,GAAG,QAAQ,aAAa,SAAS,UAAU;AAGtE,KAAIC,gCAAgB,SAAS,EAAE;EAC7B,MAAM,SAAS,SAAS,UAAU;AAClC,UAAQ,IAAI;GACV,QAAQ;GACR;GACA,SAAS,EAAE;GACX,MAAM;GACN,UAAU;IAAE;IAAQ;IAAS;GAC9B,CAAC;AACF,KAAG,KACD,KAAK,UAAU,EACb,OAAO;GACL,MAAM,WAAW,OAAO;GACxB,SAAS,SAAS,MAAM;GACxB,QAAQ,SAAS,MAAM,QAAQ;GAChC,EACF,CAAC,CACH;AACD;;AAIF,KAAIC,gCAAgB,SAAS,EAAE;AAC7B,UAAQ,IAAI;GACV,QAAQ;GACR;GACA,SAAS,EAAE;GACX,MAAM;GACN,UAAU;IAAE,QAAQ;IAAK;IAAS;GACnC,CAAC;EAEF,MAAM,YAAY;EAClB,IAAI;EACJ,IAAI;AAEJ,MAAI,OAAO,UAAU,UAAU,UAAU;AACvC,cAAWC,6BAAa,UAAU,UAAU,MAAM;AAClD,UAAO,UAAU;SACZ;AACL,cAAW,UAAU,MAAM,eAAe;AAC1C,UAAO,UAAU,MAAM;;AAGzB,KAAG,KACD,KAAK,UAAU,EACb,eAAe;GACb,WAAW,EACT,OAAO,CAAC,EAAE,YAAY;IAAE;IAAU;IAAM,EAAE,CAAC,EAC5C;GACD,cAAc;GACf,EACF,CAAC,CACH;AAED,UAAQ,oBAAoB,KAAK;GAC/B,MAAM;GACN,SAAS;GACV,CAAC;AACF;;AAIF,KAAIC,+CAA+B,SAAS,EAAE;EAC5C,MAAM,eAAe,QAAQ,IAAI;GAC/B,QAAQ;GACR;GACA,SAAS,EAAE;GACX,MAAM;GACN,UAAU;IAAE,QAAQ;IAAK;IAAS;GACnC,CAAC;EAEF,MAAM,UAAU,SAAS;EACzB,MAAM,YAAsB,EAAE;AAC9B,OAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK,UACvC,WAAU,KAAK,QAAQ,MAAM,GAAG,IAAI,UAAU,CAAC;EAGjD,MAAM,eAAeC,8CAAyB,QAAQ;EACtD,IAAI,cAAc;AAGlB,MAAI,QAAQ,WAAW,GACrB;OAAI,CAAC,GAAG,SACN,IAAG,KACD,KAAK,UAAU,EACb,eAAe,EACb,WAAW,EAAE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC,EAAE,EACrC,EACF,CAAC,CACH;QAGH,MAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,OAAI,GAAG,SAAU;AACjB,OAAI,UAAU,EAAG,OAAMC,yBAAM,SAAS,cAAc,OAAO;AAC3D,OAAI,cAAc,OAAO,SAAS;AAChC,kBAAc;AACd;;AAEF,OAAI,GAAG,SAAU;AAEjB,MAAG,KACD,KAAK,UAAU,EACb,eAAe,EACb,WAAW,EAAE,OAAO,CAAC,EAAE,MAAM,UAAU,IAAI,CAAC,EAAE,EAC/C,EACF,CAAC,CACH;AACD,iBAAc,MAAM;AACpB,OAAI,cAAc,OAAO,SAAS;AAChC,kBAAc;AACd;;;AAKN,MAAI,aAAa;AACf,MAAG,SAAS;AACZ,gBAAa,SAAS,cAAc;AACpC,gBAAa,SAAS,kBAAkB,cAAc,QAAQ;AAC9D,iBAAc,SAAS;AACvB;;EAIF,MAAM,oBAAoB,SAAS,UAAU,KAAK,QAAQ;GACxD,GAAG;GACH,YAAY,GAAG,MAAMC,oCAAoB;GAC1C,EAAE;AAGH,MAAI,CAAC,GAAG,UAAU;AAChB,OAAI,UAAU,EAAG,OAAMD,yBAAM,SAAS,cAAc,OAAO;AAC3D,OAAI,cAAc,OAAO,SAAS;AAChC,OAAG,SAAS;AACZ,iBAAa,SAAS,cAAc;AACpC,iBAAa,SAAS,kBAAkB,cAAc,QAAQ;AAC9D,kBAAc,SAAS;AACvB;;GAGF,MAAM,gBAAgB,kBAAkB,KAAK,OAAO;IAClD,IAAI;AACJ,QAAI;AACF,eAAU,KAAK,MAAM,GAAG,aAAa,KAAK;YACpC;AACN,cAAS,OAAO,KACd,sDAAsD,GAAG,KAAK,KAAK,GAAG,YACvE;AACD,eAAU,EAAE;;AAEd,WAAO;KACL,MAAM,GAAG;KACT,MAAM;KACN,IAAI,GAAG;KACR;KACD;AAEF,MAAG,KAAK,KAAK,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,CAAC,CAAC;AACxD,iBAAc,MAAM;;AAGtB,MAAI,cAAc,OAAO,SAAS;AAChC,MAAG,SAAS;AACZ,gBAAa,SAAS,cAAc;AACpC,gBAAa,SAAS,kBAAkB,cAAc,QAAQ;AAC9D,iBAAc,SAAS;AACvB;;AAGF,gBAAc,SAAS;AAGvB,MAAI,CAAC,GAAG,SACN,IAAG,KACD,KAAK,UAAU,EACb,eAAe,EAAE,cAAc,MAAM,EACtC,CAAC,CACH;AAIH,UAAQ,oBAAoB,KAAK;GAC/B,MAAM;GACN,SAAS,WAAW;GACpB,YAAY,kBAAkB,KAAK,QAAQ;IACzC,IAAI,GAAG;IACP,MAAM;IACN,UAAU;KACR,MAAM,GAAG;KACT,WAAW,GAAG;KACf;IACF,EAAE;GACJ,CAAC;AACF;;AAIF,KAAIE,+BAAe,SAAS,EAAE;EAC5B,MAAM,eAAe,QAAQ,IAAI;GAC/B,QAAQ;GACR;GACA,SAAS,EAAE;GACX,MAAM;GACN,UAAU;IAAE,QAAQ;IAAK;IAAS;GACnC,CAAC;EAEF,MAAM,UAAU,SAAS;AAEzB,MAAI,QAAQ,WAAW,GAAG;AACxB,OAAI,GAAG,SAAU;AAEjB,MAAG,KACD,KAAK,UAAU,EACb,eAAe,EACb,WAAW,EAAE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC,EAAE,EACrC,EACF,CAAC,CACH;AACD,MAAG,KACD,KAAK,UAAU,EACb,eAAe,EAAE,cAAc,MAAM,EACtC,CAAC,CACH;AACD;;EAIF,MAAM,SAAmB,EAAE;AAC3B,OAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK,UACvC,QAAO,KAAK,QAAQ,MAAM,GAAG,IAAI,UAAU,CAAC;EAG9C,MAAM,eAAeH,8CAAyB,QAAQ;EACtD,IAAI,cAAc;AAGlB,OAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,OAAI,GAAG,SAAU;AACjB,OAAI,UAAU,EAAG,OAAMC,yBAAM,SAAS,cAAc,OAAO;AAC3D,OAAI,cAAc,OAAO,SAAS;AAChC,kBAAc;AACd;;AAEF,OAAI,GAAG,SAAU;AAEjB,MAAG,KACD,KAAK,UAAU,EACb,eAAe,EACb,WAAW,EAAE,OAAO,CAAC,EAAE,MAAM,OAAO,IAAI,CAAC,EAAE,EAC5C,EACF,CAAC,CACH;AACD,iBAAc,MAAM;AACpB,OAAI,cAAc,OAAO,SAAS;AAChC,kBAAc;AACd;;;AAIJ,MAAI,aAAa;AACf,MAAG,SAAS;AACZ,gBAAa,SAAS,cAAc;AACpC,gBAAa,SAAS,kBAAkB,cAAc,QAAQ;AAC9D,iBAAc,SAAS;AACvB;;AAGF,gBAAc,SAAS;AAGvB,MAAI,CAAC,GAAG,SACN,IAAG,KACD,KAAK,UAAU,EACb,eAAe,EAAE,cAAc,MAAM,EACtC,CAAC,CACH;AAIH,UAAQ,oBAAoB,KAAK;GAAE,MAAM;GAAa;GAAS,CAAC;AAChE;;AAIF,KAAIG,mCAAmB,SAAS,EAAE;EAChC,MAAM,eAAe,QAAQ,IAAI;GAC/B,QAAQ;GACR;GACA,SAAS,EAAE;GACX,MAAM;GACN,UAAU;IAAE,QAAQ;IAAK;IAAS;GACnC,CAAC;EAEF,MAAM,eAAeJ,8CAAyB,QAAQ;AAEtD,MAAI,GAAG,UAAU;AACf,iBAAc,SAAS;AACvB;;AAEF,MAAI,UAAU,EAAG,OAAMC,yBAAM,SAAS,cAAc,OAAO;AAC3D,MAAI,cAAc,OAAO,SAAS;AAChC,MAAG,SAAS;AACZ,gBAAa,SAAS,cAAc;AACpC,gBAAa,SAAS,kBAAkB,cAAc,QAAQ;AAC9D,iBAAc,SAAS;AACvB;;AAEF,MAAI,GAAG,UAAU;AACf,iBAAc,SAAS;AACvB;;EAGF,MAAM,gBAAgB,SAAS,UAAU,KAAK,IAAI,MAAM;GACtD,IAAI;AACJ,OAAI;AACF,cAAU,KAAK,MAAM,GAAG,aAAa,KAAK;WACpC;AACN,aAAS,OAAO,KACd,sDAAsD,GAAG,KAAK,KAAK,GAAG,YACvE;AACD,cAAU,EAAE;;AAEd,UAAO;IACL,MAAM,GAAG;IACT,MAAM;IACN,IAAI,GAAG,MAAM,eAAe,GAAG,KAAK,GAAG;IACxC;IACD;AAEF,KAAG,KAAK,KAAK,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,CAAC,CAAC;AACxD,gBAAc,MAAM;AAEpB,MAAI,cAAc,OAAO,SAAS;AAChC,MAAG,SAAS;AACZ,gBAAa,SAAS,cAAc;AACpC,gBAAa,SAAS,kBAAkB,cAAc,QAAQ;AAC9D,iBAAc,SAAS;AACvB;;AAGF,gBAAc,SAAS;AAGvB,MAAI,CAAC,GAAG,SACN,IAAG,KACD,KAAK,UAAU,EACb,eAAe,EAAE,cAAc,MAAM,EACtC,CAAC,CACH;AAIH,UAAQ,oBAAoB,KAAK;GAC/B,MAAM;GACN,SAAS;GACT,YAAY,SAAS,UAAU,KAAK,IAAI,OAAO;IAC7C,IAAI,GAAG,MAAM,eAAe,GAAG,KAAK,GAAG;IACvC,MAAM;IACN,UAAU;KACR,MAAM,GAAG;KACT,WAAW,GAAG;KACf;IACF,EAAE;GACJ,CAAC;AACF;;AAIF,SAAQ,IAAI;EACV,QAAQ;EACR;EACA,SAAS,EAAE;EACX,MAAM;EACN,UAAU;GAAE,QAAQ;GAAK;GAAS;EACnC,CAAC;AACF,IAAG,KACD,KAAK,UAAU,EACb,OAAO;EACL,MAAM;EACN,SAAS;EACT,QAAQ;EACT,EACF,CAAC,CACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ws-gemini-live.d.cts","names":[],"sources":["../src/ws-gemini-live.ts"],"sourcesContent":[],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"ws-gemini-live.d.cts","names":[],"sources":["../src/ws-gemini-live.ts"],"sourcesContent":[],"mappings":";;;;;;;AAgOY,iBARI,yBAAA,CAQJ,EAAA,EAPN,mBAOM,EAAA,QAAA,EANA,OAMA,EAAA,EAAA,OAAA,EALD,OAKC,EAAA,QAAA,EAAA;SAEiB,EAAA,MAAA;WAA0B,EAAA,MAAA;EAAqB,KAAA,EAAA,MAAA;UAFhE;;2BAEiB,0BAA0B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ws-gemini-live.d.ts","names":[],"sources":["../src/ws-gemini-live.ts"],"sourcesContent":[],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"ws-gemini-live.d.ts","names":[],"sources":["../src/ws-gemini-live.ts"],"sourcesContent":[],"mappings":";;;;;;;AAgOY,iBARI,yBAAA,CAQJ,EAAA,EAPN,mBAOM,EAAA,QAAA,EANA,OAMA,EAAA,EAAA,OAAA,EALD,OAKC,EAAA,QAAA,EAAA;SAEiB,EAAA,MAAA;WAA0B,EAAA,MAAA;EAAqB,KAAA,EAAA,MAAA;UAFhE;;2BAEiB,0BAA0B"}
|