@copilotkit/aimock 1.46.0 → 1.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +12 -1
- package/README.md +4 -1
- package/dist/aws-event-stream.cjs +20 -23
- package/dist/aws-event-stream.cjs.map +1 -1
- package/dist/aws-event-stream.d.cts +0 -1
- package/dist/aws-event-stream.d.ts +0 -1
- package/dist/aws-event-stream.js +20 -24
- package/dist/aws-event-stream.js.map +1 -1
- package/dist/bedrock-converse.cjs +79 -82
- 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 +80 -83
- package/dist/bedrock-converse.js.map +1 -1
- package/dist/bedrock.cjs +112 -121
- 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 +113 -122
- package/dist/bedrock.js.map +1 -1
- package/dist/cohere.cjs +58 -106
- 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 +60 -108
- package/dist/cohere.js.map +1 -1
- package/dist/config-loader.d.cts.map +1 -1
- package/dist/config-loader.d.ts.map +1 -1
- package/dist/fixture-loader.cjs +103 -2
- 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 +104 -4
- package/dist/fixture-loader.js.map +1 -1
- package/dist/gemini-interactions.cjs +63 -121
- 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 +65 -123
- package/dist/gemini-interactions.js.map +1 -1
- package/dist/gemini.cjs +242 -155
- 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 +244 -157
- package/dist/gemini.js.map +1 -1
- package/dist/helpers.cjs +400 -7
- package/dist/helpers.cjs.map +1 -1
- package/dist/helpers.d.cts +51 -1
- package/dist/helpers.d.cts.map +1 -1
- package/dist/helpers.d.ts +51 -1
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +391 -8
- package/dist/helpers.js.map +1 -1
- package/dist/index.cjs +4 -2
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -4
- package/dist/mcp-fakes.d.cts.map +1 -1
- package/dist/messages.cjs +159 -141
- 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 +161 -143
- package/dist/messages.js.map +1 -1
- package/dist/misbehavior.cjs +62 -3
- package/dist/misbehavior.cjs.map +1 -1
- package/dist/misbehavior.d.cts.map +1 -1
- package/dist/misbehavior.d.ts.map +1 -1
- package/dist/misbehavior.js +63 -4
- package/dist/misbehavior.js.map +1 -1
- package/dist/ndjson-writer.cjs +21 -23
- package/dist/ndjson-writer.cjs.map +1 -1
- package/dist/ndjson-writer.d.cts +0 -1
- package/dist/ndjson-writer.d.cts.map +1 -1
- package/dist/ndjson-writer.d.ts +0 -1
- package/dist/ndjson-writer.d.ts.map +1 -1
- package/dist/ndjson-writer.js +21 -24
- package/dist/ndjson-writer.js.map +1 -1
- package/dist/ollama.cjs +153 -147
- 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 +155 -149
- package/dist/ollama.js.map +1 -1
- package/dist/openrouter-chat.cjs +1 -1
- package/dist/openrouter-chat.js +1 -1
- package/dist/raw-validation.cjs +177 -0
- package/dist/raw-validation.cjs.map +1 -0
- package/dist/raw-validation.js +176 -0
- package/dist/raw-validation.js.map +1 -0
- package/dist/response/deliver.cjs +144 -0
- package/dist/response/deliver.cjs.map +1 -0
- package/dist/response/deliver.js +143 -0
- package/dist/response/deliver.js.map +1 -0
- package/dist/response/frame-loop.cjs +102 -0
- package/dist/response/frame-loop.cjs.map +1 -0
- package/dist/response/frame-loop.js +100 -0
- package/dist/response/frame-loop.js.map +1 -0
- package/dist/response/lifecycle.cjs +223 -0
- package/dist/response/lifecycle.cjs.map +1 -0
- package/dist/response/lifecycle.js +211 -0
- package/dist/response/lifecycle.js.map +1 -0
- package/dist/response/proxy.cjs +71 -0
- package/dist/response/proxy.cjs.map +1 -0
- package/dist/response/proxy.js +70 -0
- package/dist/response/proxy.js.map +1 -0
- package/dist/response/raw.cjs +228 -0
- package/dist/response/raw.cjs.map +1 -0
- package/dist/response/raw.js +227 -0
- package/dist/response/raw.js.map +1 -0
- package/dist/response/timing.cjs +157 -0
- package/dist/response/timing.cjs.map +1 -0
- package/dist/response/timing.js +150 -0
- package/dist/response/timing.js.map +1 -0
- package/dist/responses.cjs +269 -148
- 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 +270 -149
- package/dist/responses.js.map +1 -1
- package/dist/router.cjs +20 -4
- package/dist/router.cjs.map +1 -1
- package/dist/router.d.cts +7 -1
- package/dist/router.d.cts.map +1 -1
- package/dist/router.d.ts +7 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +21 -5
- package/dist/router.js.map +1 -1
- package/dist/server.cjs +89 -120
- 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 +91 -122
- package/dist/server.js.map +1 -1
- package/dist/sse-writer.cjs +49 -30
- package/dist/sse-writer.cjs.map +1 -1
- package/dist/sse-writer.d.cts +0 -1
- package/dist/sse-writer.d.cts.map +1 -1
- package/dist/sse-writer.d.ts +0 -1
- package/dist/sse-writer.d.ts.map +1 -1
- package/dist/sse-writer.js +49 -31
- package/dist/sse-writer.js.map +1 -1
- package/dist/transcription.cjs +19 -33
- package/dist/transcription.cjs.map +1 -1
- package/dist/transcription.d.cts.map +1 -1
- package/dist/transcription.d.ts.map +1 -1
- package/dist/transcription.js +20 -34
- package/dist/transcription.js.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +173 -10
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.ts +173 -10
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/ws-framing.cjs +12 -6
- package/dist/ws-framing.cjs.map +1 -1
- package/dist/ws-framing.d.cts +2 -0
- package/dist/ws-framing.d.cts.map +1 -1
- package/dist/ws-framing.d.ts +2 -0
- package/dist/ws-framing.d.ts.map +1 -1
- package/dist/ws-framing.js +12 -6
- package/dist/ws-framing.js.map +1 -1
- package/dist/ws-gemini-live.cjs +120 -93
- package/dist/ws-gemini-live.cjs.map +1 -1
- package/dist/ws-gemini-live.js +120 -93
- package/dist/ws-gemini-live.js.map +1 -1
- package/dist/ws-realtime.cjs +80 -70
- 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 +80 -70
- package/dist/ws-realtime.js.map +1 -1
- package/dist/ws-responses.cjs +72 -53
- package/dist/ws-responses.cjs.map +1 -1
- package/dist/ws-responses.d.cts.map +1 -1
- package/dist/ws-responses.d.ts.map +1 -1
- package/dist/ws-responses.js +73 -54
- package/dist/ws-responses.js.map +1 -1
- package/package.json +1 -1
- package/skills/write-fixtures/SKILL.md +34 -2
package/dist/ws-gemini-live.js
CHANGED
|
@@ -5,7 +5,7 @@ import { calculateDelay, delay } from "./sse-writer.js";
|
|
|
5
5
|
import { planMisbehavior, recordMisbehaviorOutcome } from "./misbehavior.js";
|
|
6
6
|
import { matchFixtureDiagnostic } from "./router.js";
|
|
7
7
|
import "./journal.js";
|
|
8
|
-
import {
|
|
8
|
+
import { markWsTurnStopped, watchWsClose, wsLifecycle } from "./response/lifecycle.js";
|
|
9
9
|
|
|
10
10
|
//#region src/ws-gemini-live.ts
|
|
11
11
|
/**
|
|
@@ -201,6 +201,7 @@ function preflightBlocks(response, journalEntry) {
|
|
|
201
201
|
}
|
|
202
202
|
function handleWebSocketGeminiLive(ws, fixtures, journal, defaults) {
|
|
203
203
|
const { logger } = defaults;
|
|
204
|
+
watchWsClose(ws);
|
|
204
205
|
const session = {
|
|
205
206
|
setupDone: false,
|
|
206
207
|
model: defaults.model,
|
|
@@ -397,40 +398,45 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
397
398
|
const latency = fixture.latency ?? defaults.latency;
|
|
398
399
|
if (misbehavior.kind === "applied" && (misbehavior.summary.fault === "tool-args-invalid-json" || misbehavior.summary.fault === "empty-response")) {
|
|
399
400
|
const journalEntry = addResponseEntry(200);
|
|
400
|
-
const
|
|
401
|
-
const
|
|
402
|
-
journalEntry
|
|
403
|
-
journalEntry.response.interruptReason = interruption?.reason();
|
|
401
|
+
const lifecycle = wsLifecycle(ws, fixture);
|
|
402
|
+
const interruptTurn = () => {
|
|
403
|
+
markWsTurnStopped(journalEntry, ws, lifecycle);
|
|
404
404
|
ws.destroy();
|
|
405
405
|
};
|
|
406
406
|
try {
|
|
407
|
-
if (ws.isClosed)
|
|
407
|
+
if (ws.isClosed) {
|
|
408
|
+
interruptTurn();
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
408
411
|
const chunkDelay = calculateDelay(0, void 0, latency, fixture.recordedTimings, fixture.replaySpeed ?? defaults.replaySpeed);
|
|
409
|
-
if (chunkDelay > 0) await delay(chunkDelay,
|
|
410
|
-
if (
|
|
411
|
-
|
|
412
|
+
if (chunkDelay > 0) await delay(chunkDelay, lifecycle.signal);
|
|
413
|
+
if (lifecycle.signal.aborted || ws.isClosed) {
|
|
414
|
+
interruptTurn();
|
|
412
415
|
return;
|
|
413
416
|
}
|
|
414
|
-
if (ws.isClosed) return;
|
|
415
417
|
const malformed = misbehavior.summary.fault === "tool-args-invalid-json";
|
|
416
418
|
ws.send(JSON.stringify({ serverContent: malformed ? {
|
|
417
419
|
turnComplete: true,
|
|
418
420
|
turnCompleteReason: "MALFORMED_FUNCTION_CALL"
|
|
419
421
|
} : { modelTurn: { parts: [{ text: "" }] } } }));
|
|
420
|
-
|
|
421
|
-
if (
|
|
422
|
-
|
|
422
|
+
lifecycle.tick();
|
|
423
|
+
if (lifecycle.signal.aborted || ws.isClosed) {
|
|
424
|
+
interruptTurn();
|
|
423
425
|
return;
|
|
424
426
|
}
|
|
425
|
-
if (!malformed
|
|
427
|
+
if (!malformed) {
|
|
426
428
|
ws.send(JSON.stringify({ serverContent: { turnComplete: true } }));
|
|
429
|
+
if (ws.isClosed) {
|
|
430
|
+
interruptTurn();
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
427
433
|
session.conversationHistory.push({
|
|
428
434
|
role: "assistant",
|
|
429
435
|
content: ""
|
|
430
436
|
});
|
|
431
437
|
}
|
|
432
438
|
} finally {
|
|
433
|
-
|
|
439
|
+
lifecycle.dispose();
|
|
434
440
|
}
|
|
435
441
|
return;
|
|
436
442
|
}
|
|
@@ -467,25 +473,32 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
467
473
|
...tc,
|
|
468
474
|
resolvedId: tc.id ?? generateToolCallId()
|
|
469
475
|
}));
|
|
476
|
+
const stoppedByClose = () => {
|
|
477
|
+
if (!ws.isClosed) return false;
|
|
478
|
+
markWsTurnStopped(journalEntry, ws);
|
|
479
|
+
return true;
|
|
480
|
+
};
|
|
481
|
+
if (stoppedByClose()) return;
|
|
470
482
|
if (resolvedToolCalls.length === 0) ws.send(JSON.stringify({ serverContent: {
|
|
471
483
|
modelTurn: { parts },
|
|
472
484
|
turnComplete: true
|
|
473
485
|
} }));
|
|
474
486
|
else {
|
|
475
487
|
ws.send(JSON.stringify({ serverContent: { modelTurn: { parts } } }));
|
|
476
|
-
if (
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
+
if (stoppedByClose()) return;
|
|
489
|
+
const functionCalls = resolvedToolCalls.map((tc) => {
|
|
490
|
+
const argsObj = liveToolArguments(tc);
|
|
491
|
+
return {
|
|
492
|
+
name: tc.name,
|
|
493
|
+
args: argsObj,
|
|
494
|
+
id: tc.resolvedId
|
|
495
|
+
};
|
|
496
|
+
});
|
|
497
|
+
ws.send(JSON.stringify({ toolCall: { functionCalls } }));
|
|
498
|
+
if (stoppedByClose()) return;
|
|
499
|
+
ws.send(JSON.stringify({ serverContent: { turnComplete: true } }));
|
|
488
500
|
}
|
|
501
|
+
if (stoppedByClose()) return;
|
|
489
502
|
session.conversationHistory.push({
|
|
490
503
|
role: "assistant",
|
|
491
504
|
content: audioResp.content ?? "[audio]",
|
|
@@ -504,7 +517,7 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
504
517
|
const journalEntry = addResponseEntry(200);
|
|
505
518
|
if (response.blocks && response.blocks.length > 0) {
|
|
506
519
|
const resolvedBlocks = preflightBlocks(response, journalEntry);
|
|
507
|
-
const
|
|
520
|
+
const lifecycle = wsLifecycle(ws, fixture);
|
|
508
521
|
const replaySpeed = fixture.replaySpeed ?? defaults.replaySpeed;
|
|
509
522
|
const { recordedTimings } = fixture;
|
|
510
523
|
let chunkIndex = 0;
|
|
@@ -514,8 +527,8 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
514
527
|
outer: for (const block of resolvedBlocks) if (block.type === "toolCall") {
|
|
515
528
|
if (ws.isClosed) break;
|
|
516
529
|
const tcDelay = calculateDelay(chunkIndex, void 0, latency, recordedTimings, replaySpeed);
|
|
517
|
-
if (tcDelay > 0) await delay(tcDelay,
|
|
518
|
-
if (
|
|
530
|
+
if (tcDelay > 0) await delay(tcDelay, lifecycle.signal);
|
|
531
|
+
if (lifecycle.signal.aborted) {
|
|
519
532
|
interrupted = true;
|
|
520
533
|
break;
|
|
521
534
|
}
|
|
@@ -541,8 +554,8 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
541
554
|
arguments: block.arguments
|
|
542
555
|
}
|
|
543
556
|
});
|
|
544
|
-
|
|
545
|
-
if (
|
|
557
|
+
lifecycle.tick();
|
|
558
|
+
if (lifecycle.signal.aborted) {
|
|
546
559
|
interrupted = true;
|
|
547
560
|
break;
|
|
548
561
|
}
|
|
@@ -553,8 +566,8 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
553
566
|
for (let i = 0; i < text.length; i += chunkSize) {
|
|
554
567
|
if (ws.isClosed) break outer;
|
|
555
568
|
const chunkDelay = calculateDelay(chunkIndex, void 0, latency, recordedTimings, replaySpeed);
|
|
556
|
-
if (chunkDelay > 0) await delay(chunkDelay,
|
|
557
|
-
if (
|
|
569
|
+
if (chunkDelay > 0) await delay(chunkDelay, lifecycle.signal);
|
|
570
|
+
if (lifecycle.signal.aborted) {
|
|
558
571
|
interrupted = true;
|
|
559
572
|
break outer;
|
|
560
573
|
}
|
|
@@ -566,22 +579,25 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
566
579
|
break outer;
|
|
567
580
|
}
|
|
568
581
|
chunkIndex++;
|
|
569
|
-
|
|
570
|
-
if (
|
|
582
|
+
lifecycle.tick();
|
|
583
|
+
if (lifecycle.signal.aborted) {
|
|
571
584
|
interrupted = true;
|
|
572
585
|
break outer;
|
|
573
586
|
}
|
|
574
587
|
}
|
|
575
588
|
}
|
|
576
|
-
if (interrupted) {
|
|
589
|
+
if (interrupted || ws.isClosed) {
|
|
577
590
|
ws.destroy();
|
|
578
|
-
journalEntry
|
|
579
|
-
|
|
580
|
-
|
|
591
|
+
markWsTurnStopped(journalEntry, ws, lifecycle);
|
|
592
|
+
lifecycle.dispose();
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
lifecycle.dispose();
|
|
596
|
+
ws.send(JSON.stringify({ serverContent: { turnComplete: true } }));
|
|
597
|
+
if (ws.isClosed) {
|
|
598
|
+
markWsTurnStopped(journalEntry, ws, lifecycle);
|
|
581
599
|
return;
|
|
582
600
|
}
|
|
583
|
-
interruption?.cleanup();
|
|
584
|
-
if (!ws.isClosed) ws.send(JSON.stringify({ serverContent: { turnComplete: true } }));
|
|
585
601
|
session.conversationHistory.push({
|
|
586
602
|
role: "assistant",
|
|
587
603
|
content: historyContent || null,
|
|
@@ -593,7 +609,7 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
593
609
|
const content = response.content ?? "";
|
|
594
610
|
const chunkList = [];
|
|
595
611
|
for (let i = 0; i < content.length; i += chunkSize) chunkList.push(content.slice(i, i + chunkSize));
|
|
596
|
-
const
|
|
612
|
+
const lifecycle = wsLifecycle(ws, fixture);
|
|
597
613
|
const replaySpeed = fixture.replaySpeed ?? defaults.replaySpeed;
|
|
598
614
|
const { recordedTimings } = fixture;
|
|
599
615
|
let interrupted = false;
|
|
@@ -602,8 +618,8 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
602
618
|
} else for (let i = 0; i < chunkList.length; i++) {
|
|
603
619
|
if (ws.isClosed) break;
|
|
604
620
|
const chunkDelay = calculateDelay(i, void 0, latency, recordedTimings, replaySpeed);
|
|
605
|
-
if (chunkDelay > 0) await delay(chunkDelay,
|
|
606
|
-
if (
|
|
621
|
+
if (chunkDelay > 0) await delay(chunkDelay, lifecycle.signal);
|
|
622
|
+
if (lifecycle.signal.aborted) {
|
|
607
623
|
interrupted = true;
|
|
608
624
|
break;
|
|
609
625
|
}
|
|
@@ -614,17 +630,16 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
614
630
|
defaults.logger.debug("[gemini-live] send failed during text streaming, closing", err);
|
|
615
631
|
break;
|
|
616
632
|
}
|
|
617
|
-
|
|
618
|
-
if (
|
|
633
|
+
lifecycle.tick();
|
|
634
|
+
if (lifecycle.signal.aborted) {
|
|
619
635
|
interrupted = true;
|
|
620
636
|
break;
|
|
621
637
|
}
|
|
622
638
|
}
|
|
623
|
-
if (interrupted) {
|
|
639
|
+
if (interrupted || ws.isClosed) {
|
|
624
640
|
ws.destroy();
|
|
625
|
-
journalEntry
|
|
626
|
-
|
|
627
|
-
interruption?.cleanup();
|
|
641
|
+
markWsTurnStopped(journalEntry, ws, lifecycle);
|
|
642
|
+
lifecycle.dispose();
|
|
628
643
|
return;
|
|
629
644
|
}
|
|
630
645
|
const resolvedToolCalls = functionToolCalls.map((tc) => ({
|
|
@@ -633,12 +648,11 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
633
648
|
}));
|
|
634
649
|
if (!ws.isClosed) {
|
|
635
650
|
const tcDelay = calculateDelay(chunkList.length, void 0, latency, recordedTimings, replaySpeed);
|
|
636
|
-
if (tcDelay > 0) await delay(tcDelay,
|
|
637
|
-
if (
|
|
651
|
+
if (tcDelay > 0) await delay(tcDelay, lifecycle.signal);
|
|
652
|
+
if (lifecycle.signal.aborted || ws.isClosed) {
|
|
638
653
|
ws.destroy();
|
|
639
|
-
journalEntry
|
|
640
|
-
|
|
641
|
-
interruption?.cleanup();
|
|
654
|
+
markWsTurnStopped(journalEntry, ws, lifecycle);
|
|
655
|
+
lifecycle.dispose();
|
|
642
656
|
return;
|
|
643
657
|
}
|
|
644
658
|
const functionCalls = resolvedToolCalls.map((tc) => {
|
|
@@ -650,17 +664,20 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
650
664
|
};
|
|
651
665
|
});
|
|
652
666
|
ws.send(JSON.stringify({ toolCall: { functionCalls } }));
|
|
653
|
-
|
|
667
|
+
lifecycle.tick();
|
|
654
668
|
}
|
|
655
|
-
if (
|
|
669
|
+
if (lifecycle.signal.aborted || ws.isClosed) {
|
|
656
670
|
ws.destroy();
|
|
657
|
-
journalEntry
|
|
658
|
-
|
|
659
|
-
|
|
671
|
+
markWsTurnStopped(journalEntry, ws, lifecycle);
|
|
672
|
+
lifecycle.dispose();
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
lifecycle.dispose();
|
|
676
|
+
ws.send(JSON.stringify({ serverContent: { turnComplete: true } }));
|
|
677
|
+
if (ws.isClosed) {
|
|
678
|
+
markWsTurnStopped(journalEntry, ws, lifecycle);
|
|
660
679
|
return;
|
|
661
680
|
}
|
|
662
|
-
interruption?.cleanup();
|
|
663
|
-
if (!ws.isClosed) ws.send(JSON.stringify({ serverContent: { turnComplete: true } }));
|
|
664
681
|
session.conversationHistory.push({
|
|
665
682
|
role: "assistant",
|
|
666
683
|
content: content || null,
|
|
@@ -679,22 +696,30 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
679
696
|
const journalEntry = addResponseEntry(200);
|
|
680
697
|
const content = response.content;
|
|
681
698
|
if (content.length === 0) {
|
|
682
|
-
if (ws.isClosed)
|
|
699
|
+
if (ws.isClosed) {
|
|
700
|
+
markWsTurnStopped(journalEntry, ws);
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
683
703
|
ws.send(JSON.stringify({ serverContent: { modelTurn: { parts: [{ text: "" }] } } }));
|
|
704
|
+
if (ws.isClosed) {
|
|
705
|
+
markWsTurnStopped(journalEntry, ws);
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
684
708
|
ws.send(JSON.stringify({ serverContent: { turnComplete: true } }));
|
|
709
|
+
if (ws.isClosed) markWsTurnStopped(journalEntry, ws);
|
|
685
710
|
return;
|
|
686
711
|
}
|
|
687
712
|
const chunks = [];
|
|
688
713
|
for (let i = 0; i < content.length; i += chunkSize) chunks.push(content.slice(i, i + chunkSize));
|
|
689
|
-
const
|
|
714
|
+
const lifecycle = wsLifecycle(ws, fixture);
|
|
690
715
|
const replaySpeed = fixture.replaySpeed ?? defaults.replaySpeed;
|
|
691
716
|
const { recordedTimings } = fixture;
|
|
692
717
|
let interrupted = false;
|
|
693
718
|
for (let i = 0; i < chunks.length; i++) {
|
|
694
719
|
if (ws.isClosed) break;
|
|
695
720
|
const chunkDelay = calculateDelay(i, void 0, latency, recordedTimings, replaySpeed);
|
|
696
|
-
if (chunkDelay > 0) await delay(chunkDelay,
|
|
697
|
-
if (
|
|
721
|
+
if (chunkDelay > 0) await delay(chunkDelay, lifecycle.signal);
|
|
722
|
+
if (lifecycle.signal.aborted) {
|
|
698
723
|
interrupted = true;
|
|
699
724
|
break;
|
|
700
725
|
}
|
|
@@ -705,21 +730,24 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
705
730
|
defaults.logger.debug("[gemini-live] send failed during text streaming, closing", err);
|
|
706
731
|
break;
|
|
707
732
|
}
|
|
708
|
-
|
|
709
|
-
if (
|
|
733
|
+
lifecycle.tick();
|
|
734
|
+
if (lifecycle.signal.aborted) {
|
|
710
735
|
interrupted = true;
|
|
711
736
|
break;
|
|
712
737
|
}
|
|
713
738
|
}
|
|
714
|
-
if (interrupted) {
|
|
739
|
+
if (interrupted || ws.isClosed) {
|
|
715
740
|
ws.destroy();
|
|
716
|
-
journalEntry
|
|
717
|
-
|
|
718
|
-
|
|
741
|
+
markWsTurnStopped(journalEntry, ws, lifecycle);
|
|
742
|
+
lifecycle.dispose();
|
|
743
|
+
return;
|
|
744
|
+
}
|
|
745
|
+
lifecycle.dispose();
|
|
746
|
+
ws.send(JSON.stringify({ serverContent: { turnComplete: true } }));
|
|
747
|
+
if (ws.isClosed) {
|
|
748
|
+
markWsTurnStopped(journalEntry, ws, lifecycle);
|
|
719
749
|
return;
|
|
720
750
|
}
|
|
721
|
-
interruption?.cleanup();
|
|
722
|
-
if (!ws.isClosed) ws.send(JSON.stringify({ serverContent: { turnComplete: true } }));
|
|
723
751
|
session.conversationHistory.push({
|
|
724
752
|
role: "assistant",
|
|
725
753
|
content
|
|
@@ -729,24 +757,20 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
729
757
|
if (isToolCallResponse(response)) {
|
|
730
758
|
const journalEntry = addResponseEntry(200);
|
|
731
759
|
const functionToolCalls = preflightToolArguments(response, journalEntry);
|
|
732
|
-
const
|
|
760
|
+
const lifecycle = wsLifecycle(ws, fixture);
|
|
733
761
|
const replaySpeed = fixture.replaySpeed ?? defaults.replaySpeed;
|
|
734
762
|
const { recordedTimings } = fixture;
|
|
735
763
|
if (ws.isClosed) {
|
|
736
|
-
|
|
764
|
+
markWsTurnStopped(journalEntry, ws, lifecycle);
|
|
765
|
+
lifecycle.dispose();
|
|
737
766
|
return;
|
|
738
767
|
}
|
|
739
768
|
const tcDelay = calculateDelay(0, void 0, latency, recordedTimings, replaySpeed);
|
|
740
|
-
if (tcDelay > 0) await delay(tcDelay,
|
|
741
|
-
if (
|
|
769
|
+
if (tcDelay > 0) await delay(tcDelay, lifecycle.signal);
|
|
770
|
+
if (lifecycle.signal.aborted || ws.isClosed) {
|
|
742
771
|
ws.destroy();
|
|
743
|
-
journalEntry
|
|
744
|
-
|
|
745
|
-
interruption?.cleanup();
|
|
746
|
-
return;
|
|
747
|
-
}
|
|
748
|
-
if (ws.isClosed) {
|
|
749
|
-
interruption?.cleanup();
|
|
772
|
+
markWsTurnStopped(journalEntry, ws, lifecycle);
|
|
773
|
+
lifecycle.dispose();
|
|
750
774
|
return;
|
|
751
775
|
}
|
|
752
776
|
const resolvedToolCalls = functionToolCalls.map((tc) => ({
|
|
@@ -762,16 +786,19 @@ async function processMessage(raw, ws, fixtures, journal, defaults, session) {
|
|
|
762
786
|
};
|
|
763
787
|
});
|
|
764
788
|
ws.send(JSON.stringify({ toolCall: { functionCalls } }));
|
|
765
|
-
|
|
766
|
-
if (
|
|
789
|
+
lifecycle.tick();
|
|
790
|
+
if (lifecycle.signal.aborted || ws.isClosed) {
|
|
767
791
|
ws.destroy();
|
|
768
|
-
journalEntry
|
|
769
|
-
|
|
770
|
-
|
|
792
|
+
markWsTurnStopped(journalEntry, ws, lifecycle);
|
|
793
|
+
lifecycle.dispose();
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
lifecycle.dispose();
|
|
797
|
+
ws.send(JSON.stringify({ serverContent: { turnComplete: true } }));
|
|
798
|
+
if (ws.isClosed) {
|
|
799
|
+
markWsTurnStopped(journalEntry, ws, lifecycle);
|
|
771
800
|
return;
|
|
772
801
|
}
|
|
773
|
-
interruption?.cleanup();
|
|
774
|
-
if (!ws.isClosed) ws.send(JSON.stringify({ serverContent: { turnComplete: true } }));
|
|
775
802
|
session.conversationHistory.push({
|
|
776
803
|
role: "assistant",
|
|
777
804
|
content: null,
|