@ai-sdk/google 4.0.111 → 4.0.112
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/CHANGELOG.md +28 -0
- package/dist/index.d.ts +17 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +176 -22
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +75 -17
- package/dist/internal/index.js.map +1 -1
- package/docs/15-google.mdx +9 -3
- package/package.json +3 -3
- package/src/convert-to-google-messages.ts +2 -2
- package/src/google-language-model.ts +197 -145
- package/src/google-speech-model.ts +9 -12
- package/src/google-video-model.ts +1 -1
- package/src/realtime/google-realtime-event-mapper.ts +123 -0
- package/src/realtime/google-realtime-model.ts +58 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# @ai-sdk/google
|
|
2
2
|
|
|
3
|
+
## 4.0.112
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- fd7e8a7: Preserve the order of text and complete function calls in streamed Google responses, including standalone thought signatures on empty text or reasoning parts.
|
|
8
|
+
|
|
9
|
+
Keep provider metadata on empty text parts when converting results to response messages so it can be passed back in subsequent requests.
|
|
10
|
+
|
|
11
|
+
Omit foreign-provider empty signature text when replaying history through Anthropic or Bedrock, preserving Bedrock’s existing native reasoning-history handling.
|
|
12
|
+
|
|
13
|
+
- ef2dfb5: fix: pass through `seed: 0` instead of dropping it in image and video models. KlingAI now reports `seed: 0` as an unsupported setting like any other seed.
|
|
14
|
+
- 892af4d: feat (provider/google): implement server-side realtime extensions
|
|
15
|
+
|
|
16
|
+
`GoogleRealtimeModel` supports the existing `getServerWebSocketConfig()` contract, returning the unconstrained Gemini Live endpoint with resolved credential headers. Each server connection can create its own event parser. Reported gross token totals include thinking and tool-use counts, with cached input portions and available modality counts normalized without guessing missing values. Usage in a completion frame is attached to `response-done`; other snapshots use `custom` events with `rawType: 'usageMetadata'` and typed `usage`, preserving lifecycle ordering without inferring response associations.
|
|
17
|
+
|
|
18
|
+
- 3c6fb43: Forward explicit speech language codes to Gemini TTS for single- and multi-speaker requests, including the shared Vertex Gemini adapter. Omitted languages and `language: 'auto'` retain automatic detection without an unsupported-language warning.
|
|
19
|
+
- Updated dependencies [36802d4]
|
|
20
|
+
- Updated dependencies [e0143b0]
|
|
21
|
+
- Updated dependencies [934100c]
|
|
22
|
+
- Updated dependencies [892af4d]
|
|
23
|
+
- Updated dependencies [89aff56]
|
|
24
|
+
- Updated dependencies [41465fd]
|
|
25
|
+
- Updated dependencies [9754014]
|
|
26
|
+
- Updated dependencies [4bb73b0]
|
|
27
|
+
- Updated dependencies [2e44144]
|
|
28
|
+
- @ai-sdk/provider@4.0.36
|
|
29
|
+
- @ai-sdk/provider-utils@5.0.75
|
|
30
|
+
|
|
3
31
|
## 4.0.111
|
|
4
32
|
|
|
5
33
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FetchFunction, InferSchema, Resolvable, WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE, WebSocketConstructor, createToolNameMapping } from "@ai-sdk/provider-utils";
|
|
2
|
-
import { EmbeddingModelV4, Experimental_BatchV4, Experimental_DecisionModelV4, Experimental_RealtimeFactoryV4, Experimental_RealtimeModelV4, Experimental_RealtimeModelV4ClientEvent, Experimental_RealtimeModelV4ClientSecretOptions, Experimental_RealtimeModelV4ClientSecretResult, Experimental_RealtimeModelV4ServerEvent, Experimental_RealtimeModelV4SessionConfig, Experimental_SpeechTranslationModelV4, Experimental_SpeechTranslationModelV4StreamOptions, Experimental_TranscriptionModelV4StreamOptions, Experimental_VideoModelV4, FilesV4, ImageModelV4, JSONObject, LanguageModelV4, ProviderV4, SpeechModelV4, TranscriptionModelV4 } from "@ai-sdk/provider";
|
|
2
|
+
import { EmbeddingModelV4, Experimental_BatchV4, Experimental_DecisionModelV4, Experimental_RealtimeFactoryV4, Experimental_RealtimeModelV4, Experimental_RealtimeModelV4ClientEvent, Experimental_RealtimeModelV4ClientSecretOptions, Experimental_RealtimeModelV4ClientSecretResult, Experimental_RealtimeModelV4ServerConnection, Experimental_RealtimeModelV4ServerEvent, Experimental_RealtimeModelV4SessionConfig, Experimental_RealtimeModelV4SessionIntent, Experimental_SpeechTranslationModelV4, Experimental_SpeechTranslationModelV4StreamOptions, Experimental_TranscriptionModelV4StreamOptions, Experimental_VideoModelV4, FilesV4, ImageModelV4, JSONObject, LanguageModelV4, ProviderV4, SpeechModelV4, TranscriptionModelV4 } from "@ai-sdk/provider";
|
|
3
3
|
import { z } from "zod/v4";
|
|
4
4
|
//#region src/google-error.d.ts
|
|
5
5
|
declare const googleErrorDataSchema: import("@ai-sdk/provider-utils").LazySchema<{
|
|
@@ -797,6 +797,11 @@ type GoogleRealtimeModelConfig = {
|
|
|
797
797
|
};
|
|
798
798
|
declare class GoogleRealtimeModel implements Experimental_RealtimeModelV4 {
|
|
799
799
|
readonly specificationVersion: "v4";
|
|
800
|
+
readonly capabilities: {
|
|
801
|
+
readonly conversation: "turn-based";
|
|
802
|
+
readonly transports: readonly ["websocket"];
|
|
803
|
+
readonly connections: readonly ["client-secret-websocket", "server-websocket"];
|
|
804
|
+
};
|
|
800
805
|
readonly provider: string;
|
|
801
806
|
readonly modelId: string;
|
|
802
807
|
private readonly config;
|
|
@@ -810,9 +815,18 @@ declare class GoogleRealtimeModel implements Experimental_RealtimeModelV4 {
|
|
|
810
815
|
url: string;
|
|
811
816
|
protocols?: string[];
|
|
812
817
|
};
|
|
818
|
+
getServerWebSocketConfig(options?: {
|
|
819
|
+
intent?: Experimental_RealtimeModelV4SessionIntent;
|
|
820
|
+
}): Experimental_RealtimeModelV4ServerConnection | PromiseLike<Experimental_RealtimeModelV4ServerConnection>;
|
|
821
|
+
private assertConversationIntent;
|
|
813
822
|
parseServerEvent(raw: unknown): Experimental_RealtimeModelV4ServerEvent | Experimental_RealtimeModelV4ServerEvent[];
|
|
814
|
-
|
|
815
|
-
|
|
823
|
+
createServerEventParser(): ReturnType<NonNullable<Experimental_RealtimeModelV4['createServerEventParser']>>;
|
|
824
|
+
serializeClientEvent(event: Experimental_RealtimeModelV4ClientEvent, options?: {
|
|
825
|
+
intent?: Experimental_RealtimeModelV4SessionIntent;
|
|
826
|
+
}): ReturnType<Experimental_RealtimeModelV4['serializeClientEvent']>;
|
|
827
|
+
buildSessionConfig(config: Experimental_RealtimeModelV4SessionConfig, options?: {
|
|
828
|
+
intent?: Experimental_RealtimeModelV4SessionIntent;
|
|
829
|
+
}): Record<string, unknown>;
|
|
816
830
|
}
|
|
817
831
|
//#endregion
|
|
818
832
|
//#region src/realtime/google-realtime-model-options.d.ts
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":["DecisionModelV4","BatchV4","SpeechTranslationModelV4","RealtimeFactoryV4","RealtimeModelV4ClientSecretOptions","RealtimeModelV4ClientSecretResult","
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":["DecisionModelV4","BatchV4","SpeechTranslationModelV4","RealtimeFactoryV4","RealtimeModelV4ClientSecretOptions","RealtimeModelV4ClientSecretResult","RealtimeModelV4SessionIntent","RealtimeModelV4ServerConnection","RealtimeModelV4ServerEvent","RealtimeModelV4","RealtimeModelV4ClientEvent","RealtimeModelV4SessionConfig","TranscriptionModelV4StreamOptions","SpeechTranslationModelV4StreamOptions","SpeechTranslationModelV4"],"sources":["../src/google-error.ts","../src/google-language-model-options.ts","../src/google-language-model.ts","../src/google-prompt.ts","../src/tool/google-search.ts","../src/google-image-model-options.ts","../src/google-embedding-model-options.ts","../src/google-video-model-options.ts","../src/google-video-settings.ts","../src/google-speech-model-options.ts","../src/google-files.ts","../src/interactions/google-interactions-language-model-options.ts","../src/interactions/google-interactions-provider-metadata.ts","../src/interactions/google-interactions-agent.ts","../src/google-tools.ts","../src/google-image-settings.ts","../src/transcription/google-transcription-model-options.ts","../src/speech-translation/google-speech-translation-model-options.ts","../src/google-provider.ts","../src/realtime/google-realtime-model.ts","../src/realtime/google-realtime-model-options.ts","../src/transcription/google-transcription-model.ts","../src/speech-translation/google-speech-translation-model.ts","../src/version.ts"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { EXPERIMENTAL_EMBEDDING_MODEL_PROVIDER_OPTIONS_TRANSFORMER, WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE, combineHeaders, connectToWebSocket, convertAsyncIteratorToReadableStream, convertBase64ToUint8Array, convertInlineFileDataToUint8Array, convertJsonResponseToolStream, convertToBase64, convertUint8ArrayToBase64, createEventSourceResponseHandler, createJsonErrorResponseHandler, createJsonLinesResponseHandler, createJsonResponseHandler, createNullLanguageModelUsage, createProviderExecutedToolFactory, createProviderStreamError, createToolNameMapping, delay, detectMediaType, downloadBlob, encodePathSegment, generateId, getFromApi, getRuntimeEnvironmentUserAgent, getTopLevelMediaType, isAbortError, isCustomReasoning, isFullMediaType, isRecord, isSameOrigin, isUrlSupported, lazySchema, loadApiKey, mapReasoningToProviderBudget, mapReasoningToProviderEffort, normalizeBatchRequestCounts, parseProviderOptions, postJsonToApi, postToApi, resolve, resolveFullMediaType, resolveProviderReference, resolveWith, safeParseJSON, safeValidateTypes, secureJsonParse, serializeModelOptions, stringifyWithBigIntAndCycles, waitForWebSocketBufferDrain, withUserAgentSuffix, withoutTrailingSlash, zodSchema } from "@ai-sdk/provider-utils";
|
|
1
|
+
import { EXPERIMENTAL_EMBEDDING_MODEL_PROVIDER_OPTIONS_TRANSFORMER, WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE, combineHeaders, connectToWebSocket, convertAsyncIteratorToReadableStream, convertBase64ToUint8Array, convertInlineFileDataToUint8Array, convertJsonResponseToolStream, convertToBase64, convertUint8ArrayToBase64, createEventSourceResponseHandler, createJsonErrorResponseHandler, createJsonLinesResponseHandler, createJsonResponseHandler, createNullLanguageModelUsage, createProviderExecutedToolFactory, createProviderStreamError, createToolNameMapping, delay, detectMediaType, downloadBlob, encodePathSegment, generateId, getFromApi, getRuntimeEnvironmentUserAgent, getTopLevelMediaType, isAbortError, isCustomReasoning, isFullMediaType, isRecord, isSameOrigin, isUrlSupported, lazySchema, loadApiKey, mapReasoningToProviderBudget, mapReasoningToProviderEffort, normalizeBatchRequestCounts, parseProviderOptions, postJsonToApi, postToApi, removeUndefinedEntries, resolve, resolveFullMediaType, resolveProviderReference, resolveWith, safeParseJSON, safeValidateTypes, secureJsonParse, serializeModelOptions, stringifyWithBigIntAndCycles, waitForWebSocketBufferDrain, withUserAgentSuffix, withoutTrailingSlash, zodSchema } from "@ai-sdk/provider-utils";
|
|
2
2
|
import { Experimental_DecisionLanguageModel } from "@ai-sdk/provider-utils/experimental-decision";
|
|
3
3
|
import { AISDKError, InvalidArgumentError, InvalidResponseDataError, TooManyEmbeddingValuesForCallError, UnsupportedFunctionalityError } from "@ai-sdk/provider";
|
|
4
4
|
import { z } from "zod/v4";
|
|
5
5
|
//#region src/version.ts
|
|
6
|
-
const VERSION = "4.0.
|
|
6
|
+
const VERSION = "4.0.112";
|
|
7
7
|
//#endregion
|
|
8
8
|
//#region src/google-error.ts
|
|
9
9
|
const getGoogleErrorSchema = () => z.object({
|
|
@@ -577,11 +577,11 @@ function convertToGoogleMessages(prompt, options) {
|
|
|
577
577
|
const providerOpts = readProviderOpts(part);
|
|
578
578
|
const thoughtSignature = providerOpts?.thoughtSignature != null ? String(providerOpts.thoughtSignature) : void 0;
|
|
579
579
|
switch (part.type) {
|
|
580
|
-
case "text": return part.text.length === 0 ? void 0 : {
|
|
580
|
+
case "text": return part.text.length === 0 && thoughtSignature == null ? void 0 : {
|
|
581
581
|
text: part.text,
|
|
582
582
|
thoughtSignature
|
|
583
583
|
};
|
|
584
|
-
case "reasoning": return part.text.length === 0 ? void 0 : {
|
|
584
|
+
case "reasoning": return part.text.length === 0 && thoughtSignature == null ? void 0 : {
|
|
585
585
|
text: part.text,
|
|
586
586
|
thought: true,
|
|
587
587
|
thoughtSignature
|
|
@@ -2195,6 +2195,20 @@ var GoogleLanguageModel = class GoogleLanguageModel {
|
|
|
2195
2195
|
const finishActiveStreamingToolCall = (controller) => {
|
|
2196
2196
|
const active = activeStreamingToolCalls.pop();
|
|
2197
2197
|
if (active == null) return;
|
|
2198
|
+
if (currentTextBlockId !== null) {
|
|
2199
|
+
controller.enqueue({
|
|
2200
|
+
type: "text-end",
|
|
2201
|
+
id: currentTextBlockId
|
|
2202
|
+
});
|
|
2203
|
+
currentTextBlockId = null;
|
|
2204
|
+
}
|
|
2205
|
+
if (currentReasoningBlockId !== null) {
|
|
2206
|
+
controller.enqueue({
|
|
2207
|
+
type: "reasoning-end",
|
|
2208
|
+
id: currentReasoningBlockId
|
|
2209
|
+
});
|
|
2210
|
+
currentReasoningBlockId = null;
|
|
2211
|
+
}
|
|
2198
2212
|
const { finalJSON, closingDelta } = active.accumulator.finalize();
|
|
2199
2213
|
if (closingDelta.length > 0) controller.enqueue({
|
|
2200
2214
|
type: "tool-input-delta",
|
|
@@ -2333,12 +2347,40 @@ var GoogleLanguageModel = class GoogleLanguageModel {
|
|
|
2333
2347
|
} else if ("text" in part && part.text != null) {
|
|
2334
2348
|
const thoughtSignatureMetadata = part.thoughtSignature ? wrapProviderMetadata({ thoughtSignature: part.thoughtSignature }) : void 0;
|
|
2335
2349
|
if (part.text.length === 0) {
|
|
2336
|
-
if (thoughtSignatureMetadata != null
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2350
|
+
if (thoughtSignatureMetadata != null) {
|
|
2351
|
+
if (currentTextBlockId !== null) controller.enqueue({
|
|
2352
|
+
type: "text-delta",
|
|
2353
|
+
id: currentTextBlockId,
|
|
2354
|
+
delta: "",
|
|
2355
|
+
providerMetadata: thoughtSignatureMetadata
|
|
2356
|
+
});
|
|
2357
|
+
else {
|
|
2358
|
+
if (currentReasoningBlockId !== null) {
|
|
2359
|
+
controller.enqueue({
|
|
2360
|
+
type: "reasoning-end",
|
|
2361
|
+
id: currentReasoningBlockId
|
|
2362
|
+
});
|
|
2363
|
+
currentReasoningBlockId = null;
|
|
2364
|
+
}
|
|
2365
|
+
const id = String(blockCounter++);
|
|
2366
|
+
const type = part.thought === true ? "reasoning" : "text";
|
|
2367
|
+
controller.enqueue({
|
|
2368
|
+
type: `${type}-start`,
|
|
2369
|
+
id,
|
|
2370
|
+
providerMetadata: thoughtSignatureMetadata
|
|
2371
|
+
});
|
|
2372
|
+
controller.enqueue({
|
|
2373
|
+
type: `${type}-delta`,
|
|
2374
|
+
id,
|
|
2375
|
+
delta: "",
|
|
2376
|
+
providerMetadata: thoughtSignatureMetadata
|
|
2377
|
+
});
|
|
2378
|
+
controller.enqueue({
|
|
2379
|
+
type: `${type}-end`,
|
|
2380
|
+
id
|
|
2381
|
+
});
|
|
2382
|
+
}
|
|
2383
|
+
}
|
|
2342
2384
|
} else if (part.thought === true) {
|
|
2343
2385
|
if (currentTextBlockId !== null) {
|
|
2344
2386
|
controller.enqueue({
|
|
@@ -2442,14 +2484,28 @@ var GoogleLanguageModel = class GoogleLanguageModel {
|
|
|
2442
2484
|
providerMetadata: serverMeta
|
|
2443
2485
|
});
|
|
2444
2486
|
lastServerToolCallId = void 0;
|
|
2445
|
-
}
|
|
2446
|
-
for (const part of parts) {
|
|
2447
|
-
if (!("functionCall" in part)) continue;
|
|
2487
|
+
} else if ("functionCall" in part) {
|
|
2448
2488
|
const providerMeta = part.thoughtSignature ? wrapProviderMetadata({ thoughtSignature: part.thoughtSignature }) : void 0;
|
|
2449
2489
|
const isStreamingChunk = part.functionCall.partialArgs != null || part.functionCall.name != null && part.functionCall.willContinue === true;
|
|
2450
2490
|
const isTerminalChunk = part.functionCall.name == null && part.functionCall.args == null && part.functionCall.partialArgs == null && part.functionCall.willContinue == null;
|
|
2451
2491
|
const isCompleteCall = part.functionCall.name != null && part.functionCall.args != null && part.functionCall.partialArgs == null;
|
|
2452
2492
|
const isNoArgsCompleteCall = part.functionCall.name != null && part.functionCall.args == null && part.functionCall.partialArgs == null && part.functionCall.willContinue !== true;
|
|
2493
|
+
if (!isStreamingChunk && (isCompleteCall || isNoArgsCompleteCall)) {
|
|
2494
|
+
if (currentTextBlockId !== null) {
|
|
2495
|
+
controller.enqueue({
|
|
2496
|
+
type: "text-end",
|
|
2497
|
+
id: currentTextBlockId
|
|
2498
|
+
});
|
|
2499
|
+
currentTextBlockId = null;
|
|
2500
|
+
}
|
|
2501
|
+
if (currentReasoningBlockId !== null) {
|
|
2502
|
+
controller.enqueue({
|
|
2503
|
+
type: "reasoning-end",
|
|
2504
|
+
id: currentReasoningBlockId
|
|
2505
|
+
});
|
|
2506
|
+
currentReasoningBlockId = null;
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2453
2509
|
if (isStreamingChunk) {
|
|
2454
2510
|
if (part.functionCall.name != null) {
|
|
2455
2511
|
const toolCallId = part.functionCall.id || generateId();
|
|
@@ -3963,7 +4019,7 @@ var GoogleVideoModel = class {
|
|
|
3963
4019
|
"3840x2160": "4k"
|
|
3964
4020
|
}[options.resolution] || options.resolution;
|
|
3965
4021
|
if (options.duration) parameters.durationSeconds = options.duration;
|
|
3966
|
-
if (options.seed) parameters.seed = options.seed;
|
|
4022
|
+
if (options.seed != null) parameters.seed = options.seed;
|
|
3967
4023
|
if (googleOptions != null) {
|
|
3968
4024
|
const opts = googleOptions;
|
|
3969
4025
|
if (opts.personGeneration !== void 0 && opts.personGeneration !== null) parameters.personGeneration = opts.personGeneration;
|
|
@@ -4216,7 +4272,14 @@ var GoogleSpeechModel = class GoogleSpeechModel {
|
|
|
4216
4272
|
message: "Custom voices are not supported. Use a prebuilt voice instead."
|
|
4217
4273
|
});
|
|
4218
4274
|
const multiSpeakerVoiceConfig = googleOptions?.multiSpeakerVoiceConfig;
|
|
4219
|
-
const
|
|
4275
|
+
const languageCode = language === "auto" ? void 0 : language;
|
|
4276
|
+
const speechConfig = multiSpeakerVoiceConfig ? {
|
|
4277
|
+
multiSpeakerVoiceConfig,
|
|
4278
|
+
...languageCode != null && { languageCode }
|
|
4279
|
+
} : {
|
|
4280
|
+
voiceConfig: { prebuiltVoiceConfig: { voiceName: voice } },
|
|
4281
|
+
...languageCode != null && { languageCode }
|
|
4282
|
+
};
|
|
4220
4283
|
let promptText = text;
|
|
4221
4284
|
if (instructions != null && !usesStructuredSpeech) {
|
|
4222
4285
|
if (multiSpeakerVoiceConfig) warnings.push({
|
|
@@ -4268,11 +4331,6 @@ var GoogleSpeechModel = class GoogleSpeechModel {
|
|
|
4268
4331
|
feature: "speed",
|
|
4269
4332
|
details: "Google Gemini TTS models do not support the `speed` option. It was ignored."
|
|
4270
4333
|
});
|
|
4271
|
-
if (language != null) warnings.push({
|
|
4272
|
-
type: "unsupported",
|
|
4273
|
-
feature: "language",
|
|
4274
|
-
details: "Google Gemini TTS models do not support the `language` option. Language is detected automatically from the input text."
|
|
4275
|
-
});
|
|
4276
4334
|
const formats = usesStructuredSpeech ? {
|
|
4277
4335
|
wav: "AUDIO_WAV",
|
|
4278
4336
|
"audio/wav": "AUDIO_WAV",
|
|
@@ -7296,6 +7354,27 @@ var GoogleRealtimeEventMapper = class {
|
|
|
7296
7354
|
this.inputTranscriptionBuffer = "";
|
|
7297
7355
|
}
|
|
7298
7356
|
parseServerEvent(raw) {
|
|
7357
|
+
const events = this.parseEvent(raw);
|
|
7358
|
+
const usage = mapGoogleUsage(raw.usageMetadata);
|
|
7359
|
+
if (usage == null) return events;
|
|
7360
|
+
const list = Array.isArray(events) ? events : [events];
|
|
7361
|
+
if (list.some((event) => event.type === "response-done")) {
|
|
7362
|
+
const mapped = list.map((event) => event.type === "response-done" ? {
|
|
7363
|
+
...event,
|
|
7364
|
+
usage
|
|
7365
|
+
} : event);
|
|
7366
|
+
return Array.isArray(events) ? mapped : mapped[0];
|
|
7367
|
+
}
|
|
7368
|
+
const update = {
|
|
7369
|
+
type: "custom",
|
|
7370
|
+
rawType: "usageMetadata",
|
|
7371
|
+
usage,
|
|
7372
|
+
raw
|
|
7373
|
+
};
|
|
7374
|
+
if (list.length === 1 && list[0].type === "custom" && list[0].rawType === "usageMetadata") return update;
|
|
7375
|
+
return [...list, update];
|
|
7376
|
+
}
|
|
7377
|
+
parseEvent(raw) {
|
|
7299
7378
|
const data = raw;
|
|
7300
7379
|
if (data.setupComplete != null) return {
|
|
7301
7380
|
type: "session-created",
|
|
@@ -7486,6 +7565,53 @@ var GoogleRealtimeEventMapper = class {
|
|
|
7486
7565
|
}
|
|
7487
7566
|
};
|
|
7488
7567
|
/**
|
|
7568
|
+
* Maps Gemini Live `usageMetadata` to normalized usage. Google reports usage
|
|
7569
|
+
* per modality in `promptTokensDetails` / `responseTokensDetails`.
|
|
7570
|
+
*
|
|
7571
|
+
* Field names are Live-API-specific: the Live `UsageMetadata` uses
|
|
7572
|
+
* `responseTokenCount` / `responseTokensDetails` for output, NOT the
|
|
7573
|
+
* `candidatesTokenCount` / `candidatesTokensDetails` of the regular
|
|
7574
|
+
* `generateContent` response (see google-language-model.ts). Do not "align"
|
|
7575
|
+
* these to `candidates*` — they are different wire shapes.
|
|
7576
|
+
*
|
|
7577
|
+
* Gross totals preserve provider counts even when modality details are absent
|
|
7578
|
+
* or contain modalities without a dedicated normalized bucket. Never guess a
|
|
7579
|
+
* text/audio split from those totals.
|
|
7580
|
+
*/
|
|
7581
|
+
function mapGoogleUsage(usageMetadata) {
|
|
7582
|
+
if (usageMetadata == null) return void 0;
|
|
7583
|
+
const input = sumByModality(usageMetadata.promptTokensDetails);
|
|
7584
|
+
const output = sumByModality(usageMetadata.responseTokensDetails);
|
|
7585
|
+
return compactUsage({
|
|
7586
|
+
inputTokens: usageMetadata.promptTokenCount != null ? usageMetadata.promptTokenCount + (usageMetadata.toolUsePromptTokenCount ?? 0) : void 0,
|
|
7587
|
+
outputTokens: usageMetadata.responseTokenCount != null ? usageMetadata.responseTokenCount + (usageMetadata.thoughtsTokenCount ?? 0) : void 0,
|
|
7588
|
+
cachedInputTokens: usageMetadata.cachedContentTokenCount,
|
|
7589
|
+
inputTextTokens: input.text,
|
|
7590
|
+
inputAudioTokens: input.audio,
|
|
7591
|
+
outputTextTokens: output.text,
|
|
7592
|
+
outputAudioTokens: output.audio
|
|
7593
|
+
});
|
|
7594
|
+
}
|
|
7595
|
+
/** Aggregate Gemini per-modality token details into text/audio buckets. */
|
|
7596
|
+
function sumByModality(details) {
|
|
7597
|
+
if (details == null) return {};
|
|
7598
|
+
const totals = {};
|
|
7599
|
+
for (const detail of details) {
|
|
7600
|
+
const count = detail.tokenCount;
|
|
7601
|
+
if (count == null) continue;
|
|
7602
|
+
const modality = detail.modality?.toUpperCase();
|
|
7603
|
+
if (modality === "AUDIO") totals.audio = (totals.audio ?? 0) + count;
|
|
7604
|
+
else if (modality === "TEXT") totals.text = (totals.text ?? 0) + count;
|
|
7605
|
+
}
|
|
7606
|
+
return totals;
|
|
7607
|
+
}
|
|
7608
|
+
/** Drop `undefined` fields; return `undefined` when nothing is observable. */
|
|
7609
|
+
function compactUsage(usage) {
|
|
7610
|
+
const result = {};
|
|
7611
|
+
for (const [key, value] of Object.entries(usage)) if (value != null) result[key] = value;
|
|
7612
|
+
return Object.keys(result).length > 0 ? result : void 0;
|
|
7613
|
+
}
|
|
7614
|
+
/**
|
|
7489
7615
|
* The value Gemini accepts for `functionResponse.response`.
|
|
7490
7616
|
*
|
|
7491
7617
|
* The field is typed `google.protobuf.Struct`, which is an object and nothing else, so
|
|
@@ -7570,6 +7696,7 @@ function buildGoogleSessionConfig(config, modelId) {
|
|
|
7570
7696
|
//#endregion
|
|
7571
7697
|
//#region src/realtime/google-realtime-model.ts
|
|
7572
7698
|
const realtimeWebSocketPath = "google.ai.generativelanguage.v1alpha.GenerativeService.BidiGenerateContentConstrained";
|
|
7699
|
+
const realtimeServerWebSocketPath = "google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent";
|
|
7573
7700
|
function getAuthTokensURL(baseURL) {
|
|
7574
7701
|
const url = getRealtimeBaseURL(baseURL);
|
|
7575
7702
|
url.pathname = `${url.pathname.replace(/\/$/, "")}/v1alpha/auth_tokens`;
|
|
@@ -7578,9 +7705,20 @@ function getAuthTokensURL(baseURL) {
|
|
|
7578
7705
|
function getWebSocketURL(baseURL) {
|
|
7579
7706
|
return getRealtimeWebSocketURL(baseURL, realtimeWebSocketPath).toString();
|
|
7580
7707
|
}
|
|
7708
|
+
function getServerWebSocketURL(baseURL) {
|
|
7709
|
+
const url = getRealtimeBaseURL(baseURL);
|
|
7710
|
+
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
7711
|
+
url.pathname = `${url.pathname.replace(/\/$/, "")}/ws/${realtimeServerWebSocketPath}`;
|
|
7712
|
+
return url.toString();
|
|
7713
|
+
}
|
|
7581
7714
|
var GoogleRealtimeModel = class {
|
|
7582
7715
|
constructor(modelId, config) {
|
|
7583
7716
|
this.specificationVersion = "v4";
|
|
7717
|
+
this.capabilities = {
|
|
7718
|
+
conversation: "turn-based",
|
|
7719
|
+
transports: ["websocket"],
|
|
7720
|
+
connections: ["client-secret-websocket", "server-websocket"]
|
|
7721
|
+
};
|
|
7584
7722
|
this.mapper = new GoogleRealtimeEventMapper();
|
|
7585
7723
|
this.modelId = modelId;
|
|
7586
7724
|
this.provider = config.provider;
|
|
@@ -7619,13 +7757,29 @@ var GoogleRealtimeModel = class {
|
|
|
7619
7757
|
getWebSocketConfig(options) {
|
|
7620
7758
|
return { url: `${options.url}?access_token=${encodeURIComponent(options.token)}` };
|
|
7621
7759
|
}
|
|
7760
|
+
getServerWebSocketConfig(options) {
|
|
7761
|
+
this.assertConversationIntent(options);
|
|
7762
|
+
return resolveWith(this.config.headers, (headers) => ({
|
|
7763
|
+
url: getServerWebSocketURL(this.config.baseURL),
|
|
7764
|
+
headers: removeUndefinedEntries(headers)
|
|
7765
|
+
}));
|
|
7766
|
+
}
|
|
7767
|
+
assertConversationIntent(options) {
|
|
7768
|
+
if (options?.intent != null && options.intent !== "conversation") throw new Error(`Google realtime does not support the '${options.intent}' session intent.`);
|
|
7769
|
+
}
|
|
7622
7770
|
parseServerEvent(raw) {
|
|
7623
7771
|
return this.mapper.parseServerEvent(raw);
|
|
7624
7772
|
}
|
|
7625
|
-
|
|
7773
|
+
createServerEventParser() {
|
|
7774
|
+
const mapper = new GoogleRealtimeEventMapper();
|
|
7775
|
+
return (raw) => mapper.parseServerEvent(raw);
|
|
7776
|
+
}
|
|
7777
|
+
serializeClientEvent(event, options) {
|
|
7778
|
+
this.assertConversationIntent(options);
|
|
7626
7779
|
return this.mapper.serializeClientEvent(event, this.modelId);
|
|
7627
7780
|
}
|
|
7628
|
-
buildSessionConfig(config) {
|
|
7781
|
+
buildSessionConfig(config, options) {
|
|
7782
|
+
this.assertConversationIntent(options);
|
|
7629
7783
|
return buildGoogleSessionConfig(config, this.modelId);
|
|
7630
7784
|
}
|
|
7631
7785
|
};
|