@memberjunction/ai-realtime-client 6.2.0-edge.2 → 6.2.0-edge.4
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/README.md +156 -29
- package/dist/audio/audioMeter.d.ts +71 -0
- package/dist/audio/audioMeter.d.ts.map +1 -1
- package/dist/audio/audioMeter.js +83 -0
- package/dist/audio/audioMeter.js.map +1 -1
- package/dist/audio/mediaElementAudioRouter.d.ts +41 -0
- package/dist/audio/mediaElementAudioRouter.d.ts.map +1 -0
- package/dist/audio/mediaElementAudioRouter.js +82 -0
- package/dist/audio/mediaElementAudioRouter.js.map +1 -0
- package/dist/audio/micCapture.d.ts +12 -3
- package/dist/audio/micCapture.d.ts.map +1 -1
- package/dist/audio/micCapture.js +15 -1
- package/dist/audio/micCapture.js.map +1 -1
- package/dist/audio/pcmPlayback.d.ts +72 -4
- package/dist/audio/pcmPlayback.d.ts.map +1 -1
- package/dist/audio/pcmPlayback.js +101 -1
- package/dist/audio/pcmPlayback.js.map +1 -1
- package/dist/drivers/assemblyAIRealtimeClient.d.ts +2 -0
- package/dist/drivers/assemblyAIRealtimeClient.d.ts.map +1 -1
- package/dist/drivers/assemblyAIRealtimeClient.js +14 -0
- package/dist/drivers/assemblyAIRealtimeClient.js.map +1 -1
- package/dist/drivers/elevenLabsRealtimeClient.d.ts +2 -0
- package/dist/drivers/elevenLabsRealtimeClient.d.ts.map +1 -1
- package/dist/drivers/elevenLabsRealtimeClient.js +14 -0
- package/dist/drivers/elevenLabsRealtimeClient.js.map +1 -1
- package/dist/drivers/geminiAvatarOutput.d.ts +132 -0
- package/dist/drivers/geminiAvatarOutput.d.ts.map +1 -0
- package/dist/drivers/geminiAvatarOutput.js +310 -0
- package/dist/drivers/geminiAvatarOutput.js.map +1 -0
- package/dist/drivers/geminiEnterpriseRealtimeClient.d.ts +38 -0
- package/dist/drivers/geminiEnterpriseRealtimeClient.d.ts.map +1 -0
- package/dist/drivers/geminiEnterpriseRealtimeClient.js +107 -0
- package/dist/drivers/geminiEnterpriseRealtimeClient.js.map +1 -0
- package/dist/drivers/geminiRealtimeClient.d.ts +314 -48
- package/dist/drivers/geminiRealtimeClient.d.ts.map +1 -1
- package/dist/drivers/geminiRealtimeClient.js +759 -176
- package/dist/drivers/geminiRealtimeClient.js.map +1 -1
- package/dist/drivers/openAILiveClient.d.ts +5 -8
- package/dist/drivers/openAILiveClient.d.ts.map +1 -1
- package/dist/drivers/openAILiveClient.js +19 -32
- package/dist/drivers/openAILiveClient.js.map +1 -1
- package/dist/drivers/openAIRealtimeClient.d.ts +23 -26
- package/dist/drivers/openAIRealtimeClient.d.ts.map +1 -1
- package/dist/drivers/openAIRealtimeClient.js +42 -57
- package/dist/drivers/openAIRealtimeClient.js.map +1 -1
- package/dist/generic/baseRealtimeClient.d.ts +188 -30
- package/dist/generic/baseRealtimeClient.d.ts.map +1 -1
- package/dist/generic/baseRealtimeClient.js +250 -14
- package/dist/generic/baseRealtimeClient.js.map +1 -1
- package/dist/generic/openAIProtocolClient.d.ts +57 -1
- package/dist/generic/openAIProtocolClient.d.ts.map +1 -1
- package/dist/generic/openAIProtocolClient.js +89 -4
- package/dist/generic/openAIProtocolClient.js.map +1 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/media/attachVideoSource.d.ts +23 -0
- package/dist/media/attachVideoSource.d.ts.map +1 -0
- package/dist/media/attachVideoSource.js +49 -0
- package/dist/media/attachVideoSource.js.map +1 -0
- package/dist/media/channelVideoSource.d.ts +110 -14
- package/dist/media/channelVideoSource.d.ts.map +1 -1
- package/dist/media/channelVideoSource.js +183 -18
- package/dist/media/channelVideoSource.js.map +1 -1
- package/dist/media/decoders/frameScheduler.d.ts +119 -0
- package/dist/media/decoders/frameScheduler.d.ts.map +1 -0
- package/dist/media/decoders/frameScheduler.js +238 -0
- package/dist/media/decoders/frameScheduler.js.map +1 -0
- package/dist/media/decoders/imageFrameDecoder.d.ts +58 -0
- package/dist/media/decoders/imageFrameDecoder.d.ts.map +1 -0
- package/dist/media/decoders/imageFrameDecoder.js +110 -0
- package/dist/media/decoders/imageFrameDecoder.js.map +1 -0
- package/dist/media/decoders/mseFmp4Decoder.d.ts +130 -0
- package/dist/media/decoders/mseFmp4Decoder.d.ts.map +1 -0
- package/dist/media/decoders/mseFmp4Decoder.js +402 -0
- package/dist/media/decoders/mseFmp4Decoder.js.map +1 -0
- package/dist/media/decoders/streamCanvas.d.ts +46 -0
- package/dist/media/decoders/streamCanvas.d.ts.map +1 -0
- package/dist/media/decoders/streamCanvas.js +163 -0
- package/dist/media/decoders/streamCanvas.js.map +1 -0
- package/dist/media/decoders/videoMimeTypes.d.ts +29 -0
- package/dist/media/decoders/videoMimeTypes.d.ts.map +1 -0
- package/dist/media/decoders/videoMimeTypes.js +50 -0
- package/dist/media/decoders/videoMimeTypes.js.map +1 -0
- package/dist/media/decoders/webCodecsChunkDecoder.d.ts +99 -0
- package/dist/media/decoders/webCodecsChunkDecoder.d.ts.map +1 -0
- package/dist/media/decoders/webCodecsChunkDecoder.js +265 -0
- package/dist/media/decoders/webCodecsChunkDecoder.js.map +1 -0
- package/dist/media/displayCapture.d.ts +128 -0
- package/dist/media/displayCapture.d.ts.map +1 -0
- package/dist/media/displayCapture.js +245 -0
- package/dist/media/displayCapture.js.map +1 -0
- package/dist/media/frameCapture.d.ts +25 -8
- package/dist/media/frameCapture.d.ts.map +1 -1
- package/dist/media/frameCapture.js +42 -72
- package/dist/media/frameCapture.js.map +1 -1
- package/dist/media/frameSampler.d.ts +94 -0
- package/dist/media/frameSampler.d.ts.map +1 -0
- package/dist/media/frameSampler.js +134 -0
- package/dist/media/frameSampler.js.map +1 -0
- package/dist/media/index.d.ts +32 -0
- package/dist/media/index.d.ts.map +1 -0
- package/dist/media/index.js +32 -0
- package/dist/media/index.js.map +1 -0
- package/dist/media/localMediaController.d.ts +116 -0
- package/dist/media/localMediaController.d.ts.map +1 -0
- package/dist/media/localMediaController.js +281 -0
- package/dist/media/localMediaController.js.map +1 -0
- package/dist/media/mediaLayout.d.ts +93 -0
- package/dist/media/mediaLayout.d.ts.map +1 -0
- package/dist/media/mediaLayout.js +187 -0
- package/dist/media/mediaLayout.js.map +1 -0
- package/dist/media/mediaPreview.d.ts +94 -0
- package/dist/media/mediaPreview.d.ts.map +1 -0
- package/dist/media/mediaPreview.js +154 -0
- package/dist/media/mediaPreview.js.map +1 -0
- package/dist/media/mediaStage.d.ts +99 -0
- package/dist/media/mediaStage.d.ts.map +1 -0
- package/dist/media/mediaStage.js +171 -0
- package/dist/media/mediaStage.js.map +1 -0
- package/dist/media/model.d.ts +154 -0
- package/dist/media/model.d.ts.map +1 -0
- package/dist/media/model.js +9 -0
- package/dist/media/model.js.map +1 -0
- package/dist/media/playbackClock.d.ts +20 -0
- package/dist/media/playbackClock.d.ts.map +1 -0
- package/dist/media/playbackClock.js +13 -0
- package/dist/media/playbackClock.js.map +1 -0
- package/dist/media/videoFrameDecoder.d.ts +86 -0
- package/dist/media/videoFrameDecoder.d.ts.map +1 -0
- package/dist/media/videoFrameDecoder.js +2 -0
- package/dist/media/videoFrameDecoder.js.map +1 -0
- package/dist/media/videoFrameDecoderRegistry.d.ts +40 -0
- package/dist/media/videoFrameDecoderRegistry.d.ts.map +1 -0
- package/dist/media/videoFrameDecoderRegistry.js +69 -0
- package/dist/media/videoFrameDecoderRegistry.js.map +1 -0
- package/dist/media/videoPacing.d.ts +32 -0
- package/dist/media/videoPacing.d.ts.map +1 -0
- package/dist/media/videoPacing.js +37 -0
- package/dist/media/videoPacing.js.map +1 -0
- package/dist/media/videoPlayout.d.ts +168 -0
- package/dist/media/videoPlayout.d.ts.map +1 -0
- package/dist/media/videoPlayout.js +217 -0
- package/dist/media/videoPlayout.js.map +1 -0
- package/dist/media/videoSourceArbiter.d.ts +250 -0
- package/dist/media/videoSourceArbiter.d.ts.map +1 -0
- package/dist/media/videoSourceArbiter.js +423 -0
- package/dist/media/videoSourceArbiter.js.map +1 -0
- package/dist/testing/conformanceAssertions.d.ts +25 -0
- package/dist/testing/conformanceAssertions.d.ts.map +1 -0
- package/dist/testing/conformanceAssertions.js +64 -0
- package/dist/testing/conformanceAssertions.js.map +1 -0
- package/dist/testing/conformanceFixtures.d.ts +76 -0
- package/dist/testing/conformanceFixtures.d.ts.map +1 -0
- package/dist/testing/conformanceFixtures.js +169 -0
- package/dist/testing/conformanceFixtures.js.map +1 -0
- package/dist/testing/conformanceGates.d.ts +32 -0
- package/dist/testing/conformanceGates.d.ts.map +1 -0
- package/dist/testing/conformanceGates.js +35 -0
- package/dist/testing/conformanceGates.js.map +1 -0
- package/dist/testing/conformanceMicrophone.d.ts +10 -0
- package/dist/testing/conformanceMicrophone.d.ts.map +1 -0
- package/dist/testing/conformanceMicrophone.js +71 -0
- package/dist/testing/conformanceMicrophone.js.map +1 -0
- package/dist/testing/conformanceTimeline.d.ts +128 -0
- package/dist/testing/conformanceTimeline.d.ts.map +1 -0
- package/dist/testing/conformanceTimeline.js +32 -0
- package/dist/testing/conformanceTimeline.js.map +1 -0
- package/dist/testing/conformanceVideoStream.d.ts +29 -0
- package/dist/testing/conformanceVideoStream.d.ts.map +1 -0
- package/dist/testing/conformanceVideoStream.js +39 -0
- package/dist/testing/conformanceVideoStream.js.map +1 -0
- package/dist/testing/index.d.ts +29 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +28 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/realtimeVideoConformance.d.ts +23 -0
- package/dist/testing/realtimeVideoConformance.d.ts.map +1 -0
- package/dist/testing/realtimeVideoConformance.js +139 -0
- package/dist/testing/realtimeVideoConformance.js.map +1 -0
- package/dist/testing/realtimeVideoConformanceChecks.d.ts +4 -0
- package/dist/testing/realtimeVideoConformanceChecks.d.ts.map +1 -0
- package/dist/testing/realtimeVideoConformanceChecks.js +164 -0
- package/dist/testing/realtimeVideoConformanceChecks.js.map +1 -0
- package/dist/testing/realtimeVideoConformanceFrameChecks.d.ts +4 -0
- package/dist/testing/realtimeVideoConformanceFrameChecks.d.ts.map +1 -0
- package/dist/testing/realtimeVideoConformanceFrameChecks.js +63 -0
- package/dist/testing/realtimeVideoConformanceFrameChecks.js.map +1 -0
- package/dist/testing/realtimeVideoConformanceSession.d.ts +108 -0
- package/dist/testing/realtimeVideoConformanceSession.d.ts.map +1 -0
- package/dist/testing/realtimeVideoConformanceSession.js +270 -0
- package/dist/testing/realtimeVideoConformanceSession.js.map +1 -0
- package/dist/testing/realtimeVideoConformanceTurnChecks.d.ts +4 -0
- package/dist/testing/realtimeVideoConformanceTurnChecks.d.ts.map +1 -0
- package/dist/testing/realtimeVideoConformanceTurnChecks.js +248 -0
- package/dist/testing/realtimeVideoConformanceTurnChecks.js.map +1 -0
- package/dist/testing/realtimeVideoConformanceTypes.d.ts +155 -0
- package/dist/testing/realtimeVideoConformanceTypes.d.ts.map +1 -0
- package/dist/testing/realtimeVideoConformanceTypes.js +2 -0
- package/dist/testing/realtimeVideoConformanceTypes.js.map +1 -0
- package/dist/testing/recordingPlayout.d.ts +84 -0
- package/dist/testing/recordingPlayout.d.ts.map +1 -0
- package/dist/testing/recordingPlayout.js +120 -0
- package/dist/testing/recordingPlayout.js.map +1 -0
- package/package.json +29 -4
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { ClientRealtimeSessionConfig } from '@memberjunction/ai';
|
|
1
|
+
import { ClientRealtimeSessionConfig, type RealtimeClientTransport, type RealtimeResumeAttempt } from '@memberjunction/ai';
|
|
2
2
|
import { type Blob as GeminiBlob, type Content, type FunctionResponse, type LiveConnectConfig, type LiveServerMessage } from '@google/genai';
|
|
3
3
|
import { BaseRealtimeClient } from '../generic/baseRealtimeClient.js';
|
|
4
4
|
import { IRealtimePcmPlayback, RealtimePcmPlayback } from '../audio/pcmPlayback.js';
|
|
5
5
|
import { IPcmMicCapture } from '../audio/micCapture.js';
|
|
6
|
+
import { type IAvatarVideoPlayout, type VideoPlayoutOptions } from '../media/videoPlayout.js';
|
|
6
7
|
/**
|
|
7
8
|
* The minimal subset of `@google/genai`'s `Session` this client depends on. Declaring the seam
|
|
8
9
|
* as an interface (rather than the concrete SDK `Session`) lets unit tests inject a fully
|
|
@@ -35,17 +36,24 @@ export interface GeminiLiveClientSession {
|
|
|
35
36
|
}
|
|
36
37
|
/**
|
|
37
38
|
* Arguments handed to {@link GeminiRealtimeClient.connectLiveSession}. Bundles the resolved
|
|
38
|
-
* model + connect config (from the server-minted `SessionConfig`), the ephemeral token
|
|
39
|
-
* lifecycle callbacks so the seam owns the entire
|
|
40
|
-
* it wholesale.
|
|
39
|
+
* model + connect config (from the server-minted `SessionConfig`), the ephemeral token (or a relay
|
|
40
|
+
* session's transport and relay URL), and the lifecycle callbacks so the seam owns the entire
|
|
41
|
+
* `live.connect` call and tests can substitute it wholesale.
|
|
41
42
|
*/
|
|
42
43
|
export interface GeminiClientConnectArgs {
|
|
43
44
|
/** The Gemini Live model id to open the session against. */
|
|
44
45
|
Model: string;
|
|
45
46
|
/** The server-built connect config (system instruction, tools, modalities, transcription). */
|
|
46
47
|
Config: LiveConnectConfig;
|
|
47
|
-
/** The server-minted ephemeral auth token (used as the API key on a `v1alpha` client). */
|
|
48
|
+
/** The server-minted ephemeral auth token (used as the API key on a `v1alpha` client). Empty on a relay session. */
|
|
48
49
|
EphemeralToken: string;
|
|
50
|
+
/** How the browser reaches the provider, as minted (`ClientRealtimeSessionConfig.Transport`); absent means direct. */
|
|
51
|
+
Transport?: RealtimeClientTransport;
|
|
52
|
+
/**
|
|
53
|
+
* A relay session's relay URL, as minted (`ClientRealtimeSessionConfig.RelayUrl`). It carries the relay's ticket:
|
|
54
|
+
* never log it or put it in an error message.
|
|
55
|
+
*/
|
|
56
|
+
RelayUrl?: string;
|
|
49
57
|
/** Invoked for every {@link LiveServerMessage} the server emits over the session. */
|
|
50
58
|
OnMessage: (message: LiveServerMessage) => void;
|
|
51
59
|
/** Invoked on a websocket-level error (fatal). */
|
|
@@ -95,21 +103,36 @@ export declare class GeminiPcmPlayback extends RealtimePcmPlayback {
|
|
|
95
103
|
* ({@link createMicCapture} seam) and streamed with `sendRealtimeInput`.
|
|
96
104
|
* - **Audio out**: model PCM16 @ 24 kHz chunks scheduled through {@link GeminiPcmPlayback}
|
|
97
105
|
* ({@link createPlayback} seam); {@link IsAudioPlaying} is computed from the playout clock.
|
|
106
|
+
* - **Avatar out**: when the minted config grants an avatar and the host shows it (the outbound
|
|
107
|
+
* video track is live), fragmented MP4 parts play through a {@link VideoPlayout}
|
|
108
|
+
* ({@link CreateVideoPlayout} seam) handed to the host at connect, whose audio routes into the
|
|
109
|
+
* PCM playback's graph; PCM follows the avatar's voice rule (see `GeminiAvatarOutput`). A host
|
|
110
|
+
* that shows no avatar gets an audio-only session.
|
|
98
111
|
* - **Event translation** (Gemini → contract): `inputTranscription` → User deltas/finals,
|
|
99
112
|
* `outputTranscription` → Assistant deltas/finals (accumulated like the OpenAI driver),
|
|
100
113
|
* `toolCall.functionCalls` → {@link OnToolCall} (callID→name cached for
|
|
101
114
|
* {@link SendToolResult}), `interrupted` → playback flush + `'listening'`,
|
|
102
115
|
* `turnComplete` → busy cleared + queued sends flushed, `usageMetadata` → {@link OnUsage}
|
|
103
|
-
* (per-turn prompt/response token deltas — see {@link handleUsageMetadata}).
|
|
116
|
+
* (per-turn prompt/response token deltas with their modality split — see {@link handleUsageMetadata}).
|
|
117
|
+
* An avatar's generated video seconds go to {@link OnUsage} in updates of their own
|
|
118
|
+
* (`OutputTokenDetails.VideoSeconds`) at each turn boundary.
|
|
104
119
|
* - **Busy mapping**: Gemini has no `response.created` frame, so `IsBusy` is set EAGERLY when
|
|
105
120
|
* this client triggers a response (text / narration / tool result) and on the first model
|
|
106
121
|
* output of a turn (audio part or output-transcription delta); cleared on `turnComplete`,
|
|
107
122
|
* and on a `toolCall` frame (the model has yielded the floor pending the tool result — so a
|
|
108
|
-
* slow `turnComplete` can never deadlock the queued result).
|
|
123
|
+
* slow `turnComplete` can never deadlock the queued result). In an avatar session, video sets
|
|
124
|
+
* it only while the model's answer is under way: Vertex AI streams the avatar's video between
|
|
125
|
+
* answers too, and that idle video plays without marking the agent speaking or busy.
|
|
109
126
|
* - **Collision safety**: ANY `sendClientContent` interrupts in-flight Gemini generation (per
|
|
110
127
|
* the Live API contract), so text / narration / context-note / tool-result sends issued
|
|
111
128
|
* while a turn is in flight are queued and flushed in order on `turnComplete` (the flush
|
|
112
129
|
* stops at the first send that starts a new response).
|
|
130
|
+
* - **Moving to a new connection**: Google ends a connection after about 10 minutes, announcing
|
|
131
|
+
* it with `goAway`, and the session resumes on a new one with Google's handle
|
|
132
|
+
* ({@link RealtimeSessionResumption}). A planned move waits until no turn is in progress
|
|
133
|
+
* ({@link IsTurnOpen}). A connection is put to use only once Google confirms its setup
|
|
134
|
+
* (`setupComplete`): input that reaches it earlier is dropped. During a move, sends queue and
|
|
135
|
+
* the latest 2 s of mic audio are held; both go out on the new connection once it is ready.
|
|
113
136
|
* - **Open-turn commit**: context notes ride as `turnComplete: false` client content, which
|
|
114
137
|
* tells the Live API MORE INPUT IS COMING — the server holds ALL generation (including the
|
|
115
138
|
* normally-automatic continuation after a tool response) until a `turnComplete: true`
|
|
@@ -136,15 +159,61 @@ export declare class GeminiRealtimeClient extends BaseRealtimeClient {
|
|
|
136
159
|
private micStream;
|
|
137
160
|
private cameraStream;
|
|
138
161
|
private micCapture;
|
|
139
|
-
private
|
|
162
|
+
private cameraSampler;
|
|
140
163
|
private playback;
|
|
164
|
+
/**
|
|
165
|
+
* The avatar half of the session: created at connect when the server granted an avatar and the host shows it (the
|
|
166
|
+
* outbound video track is live). `null` otherwise, and the session then plays model output as it always has.
|
|
167
|
+
*/
|
|
168
|
+
private avatarOutput;
|
|
141
169
|
private firstVideoSendTimestamp;
|
|
142
170
|
private lastVideoSendTimestamp;
|
|
143
171
|
protected videoFramesSent: number;
|
|
144
|
-
|
|
145
|
-
|
|
172
|
+
/**
|
|
173
|
+
* Moves the session to a new connection with Google's resumption handle: when Google
|
|
174
|
+
* announces the connection is ending (`goAway`, with the time left; on Vertex AI it came about
|
|
175
|
+
* 9 minutes into a connection, with 30 s left) and after an unexpected drop. A planned move
|
|
176
|
+
* waits until no turn is in progress ({@link IsTurnOpen}). Created per {@link Connect}.
|
|
177
|
+
*/
|
|
178
|
+
private resumption;
|
|
179
|
+
/**
|
|
180
|
+
* Whether input can go out: the connection in use has confirmed its setup (`setupComplete`) and
|
|
181
|
+
* no move to a new connection is in progress. Google drops input that reaches a connection
|
|
182
|
+
* before its setup completes, and a connection being replaced resumes from a handle issued
|
|
183
|
+
* before the move, so what it receives never reaches the new one. While `false`, sends wait in
|
|
184
|
+
* {@link queuedSends} and microphone audio in {@link heldMicAudio}.
|
|
185
|
+
*/
|
|
186
|
+
private connectionReady;
|
|
187
|
+
/** Microphone audio captured during a move, sent on the new connection once it is ready. */
|
|
188
|
+
private heldMicAudio;
|
|
189
|
+
/** Base64 characters in {@link heldMicAudio}, kept under {@link MAX_HELD_MIC_AUDIO_BASE64_CHARS}. */
|
|
190
|
+
private heldMicAudioChars;
|
|
191
|
+
/** See {@link IsTurnOpen}. */
|
|
192
|
+
private turnOpen;
|
|
193
|
+
/** A turn's `turnComplete` came while a tool call was pending: the turn ends once the last pending call's result goes out. */
|
|
194
|
+
private turnEndAwaitsToolResults;
|
|
195
|
+
/** Model, config and token of the current connection; a resume reuses them with the new handle. */
|
|
196
|
+
private connectTarget;
|
|
197
|
+
/** Last connection number handed out by {@link openConnection}. */
|
|
198
|
+
private issuedConnections;
|
|
199
|
+
/**
|
|
200
|
+
* Number of the connection in use. Callbacks from any other connection (one that was
|
|
201
|
+
* replaced, closed, or is still opening) are ignored, so a replaced socket's close can't end
|
|
202
|
+
* the session that replaced it. `0` while no connection is in use.
|
|
203
|
+
*/
|
|
204
|
+
private currentConnection;
|
|
146
205
|
/** Returns the latest session resumption handle reported by the server, if any. */
|
|
147
206
|
get ResumptionHandle(): string | null;
|
|
207
|
+
/**
|
|
208
|
+
* Whether a turn is in progress. A turn opens at its first sign: the user's first transcribed words, a turn this
|
|
209
|
+
* client sends (typed text, a spoken update), or the model's output (a transcription delta, a thought, a tool call,
|
|
210
|
+
* an audio part, which in an avatar session must play as the voice, or, on an `interactionStatus` model, the
|
|
211
|
+
* `IN_PROGRESS` status; the video an avatar streams between turns never opens one). It closes at the turn's
|
|
212
|
+
* `turnComplete` (the true idle signal on an `interactionStatus` model) once no tool call is pending, or when the last
|
|
213
|
+
* pending call's result goes out after that; and at a resume. The session moves to a new connection only between
|
|
214
|
+
* turns.
|
|
215
|
+
*/
|
|
216
|
+
get IsTurnOpen(): boolean;
|
|
148
217
|
/** Returns the count of video frames successfully sent over the established video track. */
|
|
149
218
|
get VideoFramesSent(): number;
|
|
150
219
|
/**
|
|
@@ -170,6 +239,8 @@ export declare class GeminiRealtimeClient extends BaseRealtimeClient {
|
|
|
170
239
|
private pendingUserText;
|
|
171
240
|
/** Accumulates in-flight thought text deltas until finalized on turn completion. */
|
|
172
241
|
private pendingThoughtText;
|
|
242
|
+
/** MIME types of model output this session dropped, so each is reported once. */
|
|
243
|
+
private droppedOutputTypes;
|
|
173
244
|
/** True while a model turn is in flight; gates (queues) client-triggered sends. */
|
|
174
245
|
private responseActive;
|
|
175
246
|
/** The kind of the turn currently in flight; stamped at send time, reset on turnComplete. */
|
|
@@ -198,20 +269,74 @@ export declare class GeminiRealtimeClient extends BaseRealtimeClient {
|
|
|
198
269
|
* leaves `'speaking'` (no emission) until the result reply's first output re-asserts it.
|
|
199
270
|
*/
|
|
200
271
|
private currentState;
|
|
201
|
-
/**
|
|
202
|
-
* Opens the client-direct Gemini Live session: creates the playout engine, connects with
|
|
203
|
-
* the ephemeral token + the server-built `SessionConfig` (`{ model, config }` — the same
|
|
204
|
-
* values the server LOCKED into the token, so tampering is ignored by the API), then wires
|
|
205
|
-
* the mic-capture worklet. Reports `'listening'` once audio is flowing.
|
|
206
|
-
*/
|
|
207
272
|
/**
|
|
208
273
|
* Opens the client-direct Gemini Live session: creates the playout engine, connects with
|
|
209
274
|
* the ephemeral token + the server-built `SessionConfig` (`{ model, config }` — the same
|
|
210
275
|
* values the server LOCKED into the token, so tampering is ignored by the API), negotiates
|
|
211
276
|
* tracks, then wires the mic-capture worklet and optional video capture.
|
|
212
|
-
* Reports `'
|
|
277
|
+
* Reports `'connected'` once Google confirms the session's setup (`setupComplete`): input
|
|
278
|
+
* sent before that is dropped, so nothing goes out on the connection, and the microphone
|
|
279
|
+
* does not start, until then. Reports `'listening'` once audio is flowing.
|
|
280
|
+
*
|
|
281
|
+
* When the server granted an avatar (the minted `avatar` block) and the host shows it (the
|
|
282
|
+
* outbound video track is live), the avatar's video goes to the host once the connection is
|
|
283
|
+
* open. When the host doesn't show it, the session connects audio only.
|
|
284
|
+
*
|
|
285
|
+
* @throws When the connection closes or fails before Google confirms its setup, or no
|
|
286
|
+
* confirmation comes in time (see `RealtimeConnectionSetup`).
|
|
213
287
|
*/
|
|
214
288
|
Connect(config: ClientRealtimeSessionConfig, micStream: MediaStream, cameraStream?: MediaStream): Promise<void>;
|
|
289
|
+
/** Takes the streams for a new connect and clears what an earlier one left behind. */
|
|
290
|
+
private resetForConnect;
|
|
291
|
+
/** No connection ready, no audio held, no turn open: the state of a session before its first connection. */
|
|
292
|
+
private resetConnectionState;
|
|
293
|
+
/**
|
|
294
|
+
* Opens the session's first connection and puts it to use once Google confirms its setup.
|
|
295
|
+
*
|
|
296
|
+
* @returns `false` when the consumer disconnected while the setup was in flight; the connection is then closed, and a
|
|
297
|
+
* setup failure after the disconnect is not reported.
|
|
298
|
+
*/
|
|
299
|
+
private openFirstConnection;
|
|
300
|
+
/**
|
|
301
|
+
* Negotiates tracks. Video capability and its frame-rate ceiling are PER-MODEL DATA, minted
|
|
302
|
+
* from the provider's profile table (GeminiLiveModelProfile.SupportsInboundVideo /
|
|
303
|
+
* .MaxInboundVideoRate) and carried in the session config. Deriving either from the model
|
|
304
|
+
* id would put a second answer to the same question in a second place: the two agreed only
|
|
305
|
+
* because the model names happened to line up, and the next model to break that pattern
|
|
306
|
+
* would diverge silently. A granted avatar adds an outbound video track when this browser
|
|
307
|
+
* can play it.
|
|
308
|
+
*/
|
|
309
|
+
private negotiateSessionTracks;
|
|
310
|
+
/** The outbound video track a granted avatar offers, or `null` when this browser can't play its type through MSE. */
|
|
311
|
+
private static avatarTrackFor;
|
|
312
|
+
/**
|
|
313
|
+
* Sets up the avatar the server granted, when the host shows it (the outbound video track is
|
|
314
|
+
* live). Otherwise the session runs audio only: the config sent at connect asks for audio and
|
|
315
|
+
* no avatar, and one line says why. Returns the config to connect with.
|
|
316
|
+
*/
|
|
317
|
+
private prepareAvatar;
|
|
318
|
+
/**
|
|
319
|
+
* The one line for a granted avatar this session won't show, in the server driver's format: `browser` when the host
|
|
320
|
+
* asked for the agent's video and this browser can't play it, `host` when the host asked for none.
|
|
321
|
+
*/
|
|
322
|
+
private avatarDowngradeMessage;
|
|
323
|
+
/** The connect config of a session whose avatar won't show: audio out, and no avatar. */
|
|
324
|
+
private static withoutAvatar;
|
|
325
|
+
/** Starts the microphone capture, the camera passed to `Connect` when inbound video is live, and both audio meters. */
|
|
326
|
+
private startLocalCapture;
|
|
327
|
+
/**
|
|
328
|
+
* Stops the avatar's video and releases its element; the session then has no avatar. The video it generated and
|
|
329
|
+
* did not yet report is emitted first.
|
|
330
|
+
*/
|
|
331
|
+
private disposeAvatarOutput;
|
|
332
|
+
/**
|
|
333
|
+
* Samples the camera passed to {@link Connect} at the rate the video track negotiated and feeds it to
|
|
334
|
+
* the session's {@link VideoSourceArbiter} as a `'camera'` source. The arbiter stays the only writer of
|
|
335
|
+
* inbound video, and it tells the model when it switches to the camera.
|
|
336
|
+
*/
|
|
337
|
+
private startConnectCamera;
|
|
338
|
+
/** Stops sampling the `Connect` camera and removes it from the arbiter. Does not stop its tracks. */
|
|
339
|
+
private stopConnectCamera;
|
|
215
340
|
/**
|
|
216
341
|
* Tears down the session, mic capture, mic tracks, camera capture, and playout engine,
|
|
217
342
|
* resets the response state machine, and emits a final `'closed'` (unless already `'error'`).
|
|
@@ -236,19 +361,26 @@ export declare class GeminiRealtimeClient extends BaseRealtimeClient {
|
|
|
236
361
|
/**
|
|
237
362
|
* Streams one base64 image frame over the established inbound video track.
|
|
238
363
|
*
|
|
239
|
-
* Enforces a
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
364
|
+
* Enforces a minimum inter-frame spacing as a backstop with deliberate jitter headroom for the
|
|
365
|
+
* upstream pacers (the source arbiter, `ChannelInboundVideoBridge`, `frameCapture`, channel-level
|
|
366
|
+
* gates such as `OnScreencastFrame`). The spacing is derived from the rate the track NEGOTIATED
|
|
367
|
+
* ({@link MinVideoFrameSpacingMs} of {@link BaseRealtimeClient.InboundVideoRate}), so it follows the
|
|
368
|
+
* model's profile rather than a constant: at the 1 fps every Live model accepts today it is the
|
|
369
|
+
* 750 ms gate this driver has always applied, and a faster model needs no change here. Upstream
|
|
370
|
+
* generators are the primary enforcers of the nominal rate; this gate absorbs event-loop and async
|
|
371
|
+
* dispatch jitter without dropping intended frames, while preventing an unpaced caller from bursting.
|
|
372
|
+
*
|
|
373
|
+
* Gemini accepts ONE inbound video stream, so `sourceId` is ignored: choosing which source feeds that
|
|
374
|
+
* stream is the arbiter's job, and by the time a frame arrives here the choice is made.
|
|
245
375
|
*
|
|
246
376
|
* If inbound video is not established, returns `false` without error or frame sends (fallback).
|
|
377
|
+
* A frame that comes while no connection is ready (before Google confirms the setup, or while
|
|
378
|
+
* the session moves to a new connection) is dropped too: the source sends the next one at the track's rate.
|
|
247
379
|
*
|
|
248
|
-
* @returns `true` if the frame was dispatched to the session; `false` if dropped (throttled
|
|
249
|
-
* or
|
|
380
|
+
* @returns `true` if the frame was dispatched to the session; `false` if dropped (throttled,
|
|
381
|
+
* track unestablished, or no connection ready).
|
|
250
382
|
*/
|
|
251
|
-
SendVideoFrame(base64Image: string, mimeType?: string): boolean;
|
|
383
|
+
SendVideoFrame(base64Image: string, mimeType?: string, _sourceId?: string): boolean;
|
|
252
384
|
/**
|
|
253
385
|
* @inheritdoc
|
|
254
386
|
*
|
|
@@ -259,7 +391,7 @@ export declare class GeminiRealtimeClient extends BaseRealtimeClient {
|
|
|
259
391
|
* by a cancel). Server-side, the next client content sent naturally interrupts any
|
|
260
392
|
* residual generation per the Live API contract. The interrupted turn's accumulated
|
|
261
393
|
* transcript is kept — the provider's trailing frames finalize what WAS spoken. No-op
|
|
262
|
-
* when nothing is active.
|
|
394
|
+
* when nothing is active. An avatar's video stops with the voice.
|
|
263
395
|
*/
|
|
264
396
|
CancelActiveResponse(): void;
|
|
265
397
|
/**
|
|
@@ -304,6 +436,8 @@ export declare class GeminiRealtimeClient extends BaseRealtimeClient {
|
|
|
304
436
|
* client driver).
|
|
305
437
|
*/
|
|
306
438
|
SetMuted(muted: boolean): void;
|
|
439
|
+
/** Rebinds the PCM capture and the input meter to the stream's current track (obligation #10); the socket stays open. */
|
|
440
|
+
ReplaceMicrophone(micStream: MediaStream): Promise<void>;
|
|
307
441
|
/** @inheritdoc */
|
|
308
442
|
get IsBusy(): boolean;
|
|
309
443
|
/**
|
|
@@ -311,7 +445,10 @@ export declare class GeminiRealtimeClient extends BaseRealtimeClient {
|
|
|
311
445
|
*
|
|
312
446
|
* Computed directly from the playout engine's playhead clock — this client OWNS the output
|
|
313
447
|
* buffer (no WebRTC playback events exist on Gemini), so "audibly playing" is precisely
|
|
314
|
-
* "scheduled audio extends beyond the audio context's current time".
|
|
448
|
+
* "scheduled audio extends beyond the audio context's current time". In an avatar session
|
|
449
|
+
* the avatar's video counts too, while some of an answer's media is still ahead of its
|
|
450
|
+
* playhead: its MP4 usually carries the voice. The idle video that follows an answer does
|
|
451
|
+
* not count.
|
|
315
452
|
*/
|
|
316
453
|
get IsAudioPlaying(): boolean;
|
|
317
454
|
/**
|
|
@@ -331,6 +468,15 @@ export declare class GeminiRealtimeClient extends BaseRealtimeClient {
|
|
|
331
468
|
protected createMicCapture(micStream: MediaStream, onPcmChunk: (base64Pcm16: string) => void): Promise<IGeminiMicCapture>;
|
|
332
469
|
/** Creation seam for the playout engine. Production returns {@link GeminiPcmPlayback}. */
|
|
333
470
|
protected createPlayback(): IGeminiAudioPlayback;
|
|
471
|
+
/**
|
|
472
|
+
* Creation seam for the avatar's video player, called at connect when the server granted an
|
|
473
|
+
* avatar and the host shows it. Production returns {@link VideoPlayout} (Media Source
|
|
474
|
+
* Extensions); unit tests return a fake.
|
|
475
|
+
*
|
|
476
|
+
* @param options The type the grant names, whether the video carries the voice, and the hook
|
|
477
|
+
* that routes the element's audio into the PCM playback's Web Audio graph.
|
|
478
|
+
*/
|
|
479
|
+
protected CreateVideoPlayout(options: VideoPlayoutOptions): IAvatarVideoPlayout;
|
|
334
480
|
/**
|
|
335
481
|
* Extracts the model + Live connect config from the server-minted `SessionConfig`
|
|
336
482
|
* (shaped `{ model, config }` by the server's `GeminiRealtime.CreateClientSession`).
|
|
@@ -338,11 +484,36 @@ export declare class GeminiRealtimeClient extends BaseRealtimeClient {
|
|
|
338
484
|
* server locked the real config into the token, so the session still behaves correctly.
|
|
339
485
|
*/
|
|
340
486
|
private parseSessionConfig;
|
|
341
|
-
/**
|
|
487
|
+
/** The tracks the runtime asks the session for (`requestedTracks`); `undefined` when it sent no list. */
|
|
488
|
+
private static readRequestedTracks;
|
|
489
|
+
/**
|
|
490
|
+
* The avatar the server granted: the minted `avatar` block (`{ output: true, encoding, audioMuxed }`), which the
|
|
491
|
+
* server writes only when the session renders one. `audioMuxed` defaults to true, as the server's profile does.
|
|
492
|
+
*/
|
|
493
|
+
private static readAvatarGrant;
|
|
494
|
+
/**
|
|
495
|
+
* Streams one base64 PCM16 mic chunk to the model (no-op once the session is gone, closed, or in error). During a
|
|
496
|
+
* move to a new connection the chunk is held instead, and goes out on the new connection once it is ready.
|
|
497
|
+
*/
|
|
342
498
|
private sendMicChunk;
|
|
343
|
-
/**
|
|
499
|
+
/** Sends one base64 PCM16 mic chunk on `session`; a failed send is logged, not thrown. */
|
|
500
|
+
private sendAudio;
|
|
501
|
+
/** Holds a mic chunk during a move, keeping the latest {@link HELD_MIC_AUDIO_SECONDS} seconds; older audio goes first. */
|
|
502
|
+
private holdMicChunk;
|
|
503
|
+
/** Sends the mic audio held during a move on the connection now in use, oldest first. */
|
|
504
|
+
private sendHeldMicAudio;
|
|
505
|
+
/**
|
|
506
|
+
* Surfaces a fatal websocket error and marks the session unusable. When the session can be
|
|
507
|
+
* resumed, the error is only logged: a websocket `error` is always followed by a `close`,
|
|
508
|
+
* and {@link handleTransportClose} resumes from there.
|
|
509
|
+
*/
|
|
344
510
|
private handleTransportError;
|
|
345
|
-
/**
|
|
511
|
+
/**
|
|
512
|
+
* Handles a close of the current connection that the consumer did not ask for. MJAPI's relay
|
|
513
|
+
* closing at the session's time limit ends the call with a `time-limit` error. Otherwise, when
|
|
514
|
+
* Google issued a resumption handle, the session reconnects with it; else the close ends the
|
|
515
|
+
* session, as an error when it was abnormal.
|
|
516
|
+
*/
|
|
346
517
|
private handleTransportClose;
|
|
347
518
|
/**
|
|
348
519
|
* Entry point for every inbound {@link LiveServerMessage}; fans out to per-concern
|
|
@@ -350,9 +521,52 @@ export declare class GeminiRealtimeClient extends BaseRealtimeClient {
|
|
|
350
521
|
*/
|
|
351
522
|
private handleServerMessage;
|
|
352
523
|
/**
|
|
353
|
-
*
|
|
354
|
-
|
|
355
|
-
|
|
524
|
+
* Opens a replacement connection that resumes the session from `handle`, switches to it once
|
|
525
|
+
* Google confirms its setup, and closes the old one. Until then the old connection stays in
|
|
526
|
+
* use, so what it still sends (the rest of a turn the deadline cut, its usage) is handled.
|
|
527
|
+
* Mic capture and playout carry over untouched. Rejects when the connection can't be opened or
|
|
528
|
+
* its setup fails, so {@link RealtimeSessionResumption} can retry.
|
|
529
|
+
*
|
|
530
|
+
* The resume reuses the session's ephemeral token, which Google accepts until the token's
|
|
531
|
+
* `expireTime` (the server driver mints 30 minutes). After that every attempt fails and the
|
|
532
|
+
* session ends with a fatal error.
|
|
533
|
+
*
|
|
534
|
+
* @param handle The resumption handle Google issued.
|
|
535
|
+
* @param attempt Marks the attempt abandoned after a timeout or a consumer close; a
|
|
536
|
+
* connection that opens after that is closed instead of used.
|
|
537
|
+
*/
|
|
538
|
+
protected resumeSession(handle: string, attempt: RealtimeResumeAttempt): Promise<void>;
|
|
539
|
+
/**
|
|
540
|
+
* Opens a connection through {@link connectLiveSession}. Its callbacks act only while it is the
|
|
541
|
+
* connection in use, so events from one that was replaced, closed, or is still opening are
|
|
542
|
+
* dropped; its `setupComplete`, and a close or error before it, settle its {@link GeminiOpenedConnection.Setup}
|
|
543
|
+
* whether or not it is in use yet. It becomes the connection in use through {@link useConnection},
|
|
544
|
+
* which lets the old connection keep delivering events while a planned move is in progress.
|
|
545
|
+
*/
|
|
546
|
+
private openConnection;
|
|
547
|
+
/** Waits for Google to confirm a new connection's setup. On failure the connection is closed and the error rethrown. */
|
|
548
|
+
private static awaitSetup;
|
|
549
|
+
/** What a websocket error event says went wrong. */
|
|
550
|
+
private static transportErrorDetail;
|
|
551
|
+
/** Makes an opened connection the one in use. */
|
|
552
|
+
private useConnection;
|
|
553
|
+
/**
|
|
554
|
+
* Builds the resumption helper for a newly connected session; see {@link resumption}. From the
|
|
555
|
+
* moment a move starts, input waits for the new connection ({@link connectionReady}).
|
|
556
|
+
*/
|
|
557
|
+
private createResumption;
|
|
558
|
+
/**
|
|
559
|
+
* The session continues on a new connection, whose setup Google has confirmed. A turn cut off
|
|
560
|
+
* by a drop or the deadline never completes there, so the turn state is reset (its partial
|
|
561
|
+
* transcripts are emitted as final). The mic audio held during the move goes out, then the
|
|
562
|
+
* sends queued behind it. An avatar's video plays out what arrived of that turn and holds its
|
|
563
|
+
* last frame.
|
|
564
|
+
*/
|
|
565
|
+
private handleResumed;
|
|
566
|
+
/** Every resume attempt failed: the session ends with a fatal error. */
|
|
567
|
+
private handleResumeFailed;
|
|
568
|
+
/** Closes a socket the session no longer uses; it may already be closed. */
|
|
569
|
+
private static closeQuietly;
|
|
356
570
|
/**
|
|
357
571
|
* Inspects inbound frames for the untyped `interaction_status` / `interactionStatus` wire field
|
|
358
572
|
* documented for Gemini Live Extended Thinking (V3). Narrowed via null-safe object/string helpers.
|
|
@@ -369,7 +583,22 @@ export declare class GeminiRealtimeClient extends BaseRealtimeClient {
|
|
|
369
583
|
* the server-bridged `GeminiRealtime` driver forwards the same payload to `IRealtimeSession.OnUsage`.
|
|
370
584
|
*/
|
|
371
585
|
private handleUsageMetadata;
|
|
372
|
-
/**
|
|
586
|
+
/**
|
|
587
|
+
* Gemini's per-modality token counts (`promptTokensDetails` or `responseTokensDetails`) as a detail block: TEXT,
|
|
588
|
+
* AUDIO, IMAGE and VIDEO. `undefined` when Gemini sent no count for a modality it names.
|
|
589
|
+
*/
|
|
590
|
+
private static modalityTokens;
|
|
591
|
+
/**
|
|
592
|
+
* Emits the avatar video generated since the last emission as an update of its own
|
|
593
|
+
* (`OutputTokenDetails.VideoSeconds`, an amount): called where a turn's counting ends (generation complete,
|
|
594
|
+
* turn complete, resumed; an interrupted turn ends at its turn complete) and before the avatar output is
|
|
595
|
+
* disposed, so every second is emitted once, whenever Google's `usageMetadata` arrives.
|
|
596
|
+
*/
|
|
597
|
+
private emitAvatarVideoSeconds;
|
|
598
|
+
/**
|
|
599
|
+
* Translates one {@link LiveServerContent} frame in provider-documented signal order. What the frame carries opens
|
|
600
|
+
* the turn before its `turnComplete` ends it.
|
|
601
|
+
*/
|
|
373
602
|
private handleServerContent;
|
|
374
603
|
/**
|
|
375
604
|
* generationComplete: indicates the model has finished generating all tokens for the turn.
|
|
@@ -377,6 +606,8 @@ export declare class GeminiRealtimeClient extends BaseRealtimeClient {
|
|
|
377
606
|
*
|
|
378
607
|
* Per Reviewer Item 20: Draining the queue happens on turnComplete or true IDLE, not prematurely
|
|
379
608
|
* on generationComplete. We set responseActive = false so busy state reflects token completion.
|
|
609
|
+
* An avatar's video gets its end of turn here: playback runs to the true end and holds the
|
|
610
|
+
* last frame.
|
|
380
611
|
*/
|
|
381
612
|
private handleGenerationComplete;
|
|
382
613
|
/**
|
|
@@ -385,11 +616,19 @@ export declare class GeminiRealtimeClient extends BaseRealtimeClient {
|
|
|
385
616
|
* client's audio queue), surface the TRUE barge-in to the host (Gemini only emits
|
|
386
617
|
* `interrupted` when user input actually cut off in-flight generation — no extra gating
|
|
387
618
|
* needed), and give the floor back. The interrupted turn's accumulated transcript is
|
|
388
|
-
* kept — the following `turnComplete` finalizes what WAS spoken.
|
|
619
|
+
* kept — the following `turnComplete` finalizes what WAS spoken. In an avatar session the
|
|
620
|
+
* video stops too, and the turn's late parts are dropped until its `turnComplete`.
|
|
389
621
|
*/
|
|
390
622
|
private handleInterruption;
|
|
391
|
-
/**
|
|
392
|
-
|
|
623
|
+
/**
|
|
624
|
+
* Plays inline model parts. In an avatar session the avatar output routes each part to the
|
|
625
|
+
* video, to the PCM playback or nowhere; only the answer's parts mark generation started
|
|
626
|
+
* (and the turn open): the idle video between answers plays without making the agent
|
|
627
|
+
* speaking or busy. Otherwise base64 PCM16 @ 24 kHz parts go to the playout queue.
|
|
628
|
+
*/
|
|
629
|
+
private handleModelMedia;
|
|
630
|
+
/** Reports each MIME type of dropped model output once per session, not once per part. */
|
|
631
|
+
private reportDroppedOutput;
|
|
393
632
|
/**
|
|
394
633
|
* Extracts thought parts (`part.thought === true`) from model turns and emits them
|
|
395
634
|
* as narration transcript deltas (`Kind: 'narration'`). Thought summaries are reasoning
|
|
@@ -424,23 +663,23 @@ export declare class GeminiRealtimeClient extends BaseRealtimeClient {
|
|
|
424
663
|
private handleToolCallFrame;
|
|
425
664
|
/**
|
|
426
665
|
* Turn boundary: finalize any un-finished assistant transcript.
|
|
427
|
-
* Under 'turnComplete' idle signal,
|
|
428
|
-
* drain queued sends, and return the floor to the user.
|
|
666
|
+
* Under 'turnComplete' idle signal, end the turn (see {@link IsTurnOpen}), release the busy
|
|
667
|
+
* lock, reset response kind, drain queued sends, and return the floor to the user.
|
|
429
668
|
* Under 'interactionStatus' (Extended Thinking), turnComplete does NOT indicate idle:
|
|
430
|
-
* background reasoning or async tool calls may still be in flight, so the busy lock
|
|
669
|
+
* background reasoning or async tool calls may still be in flight, so the turn, the busy lock
|
|
431
670
|
* and queued sends remain held until the true IDLE signal lands.
|
|
432
671
|
*/
|
|
433
672
|
private handleTurnComplete;
|
|
434
673
|
/**
|
|
435
674
|
* Reached when the server emits true IDLE (interactionStatus) or the safety backstop fires.
|
|
436
|
-
*
|
|
437
|
-
* drains queued sends, and returns the floor.
|
|
675
|
+
* Ends the turn (see {@link IsTurnOpen}), releases busy state, commits any deferred open client
|
|
676
|
+
* turns without cutting off generation, drains queued sends, and returns the floor.
|
|
438
677
|
*/
|
|
439
678
|
private handleIdleTerminal;
|
|
440
679
|
/**
|
|
441
|
-
* First model output of a turn (audio part
|
|
442
|
-
* over (finalize their pending transcript), the model is busy,
|
|
443
|
-
* imminently `'speaking'`.
|
|
680
|
+
* First model output of a turn (audio part, transcription delta, or a part of an avatar's
|
|
681
|
+
* answer): the user's turn is over (finalize their pending transcript), the model is busy,
|
|
682
|
+
* and the client is audibly / imminently `'speaking'`.
|
|
444
683
|
*/
|
|
445
684
|
private markGenerationStarted;
|
|
446
685
|
/** Emits the accumulated user turn as final (if non-empty) and clears the accumulator. */
|
|
@@ -449,16 +688,43 @@ export declare class GeminiRealtimeClient extends BaseRealtimeClient {
|
|
|
449
688
|
private finalizeAssistantTranscript;
|
|
450
689
|
/** Emits the accumulated thought turn as final (if non-empty) with Kind: 'narration' and IsThought: true. */
|
|
451
690
|
private finalizeThoughtTranscript;
|
|
691
|
+
/**
|
|
692
|
+
* Whether a server content message is a sign of a turn: the user's or the model's transcribed
|
|
693
|
+
* words, a thought, or (in a session without an avatar) the model's audio. An avatar's video
|
|
694
|
+
* never is: Vertex AI streams it between turns too.
|
|
695
|
+
*/
|
|
696
|
+
private contentOpensTurn;
|
|
697
|
+
/**
|
|
698
|
+
* Whether a model part is a sign of a turn: a thought, or audio (as this client plays it) in a session without an
|
|
699
|
+
* avatar. In an avatar session, a voice part opens the turn once it plays ({@link handleModelMedia}).
|
|
700
|
+
*/
|
|
701
|
+
private partOpensTurn;
|
|
702
|
+
/** Whether a transcription frame carries words (whitespace alone does not count). */
|
|
703
|
+
private static hasText;
|
|
704
|
+
/** A turn started or continued: a planned move waits until it ends. */
|
|
705
|
+
private markTurnOpen;
|
|
706
|
+
/** The turn's `turnComplete` (or true idle): it ends now, or once the results of the tool calls still pending go out. */
|
|
707
|
+
private endTurnUnlessToolCallPending;
|
|
708
|
+
/** A tool result went out: a turn whose `turnComplete` waited on the pending calls ends once none is left. */
|
|
709
|
+
private endTurnIfToolResultsIn;
|
|
710
|
+
/** The turn is over: a planned move happens at the next resumable handle Google issues. */
|
|
711
|
+
private endTurn;
|
|
452
712
|
/**
|
|
453
713
|
* Runs a send immediately when no turn is in flight; otherwise queues it for the next
|
|
454
714
|
* `turnComplete`. This is Gemini's equivalent of the OpenAI driver's
|
|
455
715
|
* queue-behind-active-response rule — stricter here because ANY client content interrupts
|
|
456
|
-
* in-flight generation on the Live API.
|
|
716
|
+
* in-flight generation on the Live API. Every send also waits while no connection is ready
|
|
717
|
+
* ({@link connectionReady}): during a move it goes out on the new connection.
|
|
718
|
+
*
|
|
719
|
+
* @param send The send.
|
|
720
|
+
* @param waitsForTurn Whether the send waits for a turn in flight (`false` for a non-blocking
|
|
721
|
+
* tool result, which goes out while the model talks).
|
|
457
722
|
*/
|
|
458
723
|
private enqueueOrRun;
|
|
459
724
|
/**
|
|
460
725
|
* Drains queued sends in order on a turn boundary, stopping as soon as one starts a new
|
|
461
|
-
* turn (sets {@link responseActive}) — the rest wait for that turn's completion.
|
|
726
|
+
* turn (sets {@link responseActive}) — the rest wait for that turn's completion. Nothing
|
|
727
|
+
* drains while no connection is ready: {@link handleResumed} drains onto the new one.
|
|
462
728
|
*/
|
|
463
729
|
private flushQueuedSends;
|
|
464
730
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"geminiRealtimeClient.d.ts","sourceRoot":"","sources":["../../src/drivers/geminiRealtimeClient.ts"],"names":[],"mappings":"AACA,OAAO,EACH,2BAA2B,
|
|
1
|
+
{"version":3,"file":"geminiRealtimeClient.d.ts","sourceRoot":"","sources":["../../src/drivers/geminiRealtimeClient.ts"],"names":[],"mappings":"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"}
|