@ai-sdk/google 4.0.83 → 4.0.85
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 +14 -0
- package/dist/index.js +85 -22
- package/dist/index.js.map +1 -1
- package/docs/15-google.mdx +30 -13
- package/package.json +2 -2
- package/src/google-provider.ts +1 -1
- package/src/realtime/google-realtime-event-mapper.ts +109 -23
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @ai-sdk/google
|
|
2
2
|
|
|
3
|
+
## 4.0.85
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- c2511c1: fix: use standards-compliant User-Agent header
|
|
8
|
+
- Updated dependencies [c2511c1]
|
|
9
|
+
- @ai-sdk/provider-utils@5.0.51
|
|
10
|
+
|
|
11
|
+
## 4.0.84
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- d0290cf: fix(google): preserve realtime user utterances with independent IDs and cumulative transcripts, honor text-free transcription completion markers, and advance response IDs after interruption
|
|
16
|
+
|
|
3
17
|
## 4.0.83
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import { Experimental_EvaluationLanguageModel as EvaluationLanguageModel } from "@ai-sdk/provider-utils/experimental-evaluation";
|
|
9
9
|
|
|
10
10
|
// src/version.ts
|
|
11
|
-
var VERSION = true ? "4.0.
|
|
11
|
+
var VERSION = true ? "4.0.85" : "0.0.0-test";
|
|
12
12
|
|
|
13
13
|
// src/google-embedding-model.ts
|
|
14
14
|
import {
|
|
@@ -8091,6 +8091,10 @@ import { isRecord, safeParseJSON } from "@ai-sdk/provider-utils";
|
|
|
8091
8091
|
var GoogleRealtimeEventMapper = class {
|
|
8092
8092
|
constructor() {
|
|
8093
8093
|
this.turnCounter = 0;
|
|
8094
|
+
this.inputTranscriptionCounter = 0;
|
|
8095
|
+
this.inputTranscriptionBuffer = "";
|
|
8096
|
+
this.inputTranscriptionBoundary = "none";
|
|
8097
|
+
this.preserveInputTranscriptionAcrossTurnComplete = false;
|
|
8094
8098
|
this.hasAudio = false;
|
|
8095
8099
|
this.hasText = false;
|
|
8096
8100
|
this.hasTranscript = false;
|
|
@@ -8104,12 +8108,11 @@ var GoogleRealtimeEventMapper = class {
|
|
|
8104
8108
|
return `google-item-${this.turnCounter}`;
|
|
8105
8109
|
}
|
|
8106
8110
|
/**
|
|
8107
|
-
* Rolls over to the next turn lazily,
|
|
8108
|
-
* arrives. `turnComplete` merely marks the current turn closed
|
|
8109
|
-
*
|
|
8110
|
-
*
|
|
8111
|
-
*
|
|
8112
|
-
* ordering relative to `turnComplete`.
|
|
8111
|
+
* Rolls over to the next turn lazily, once model content for the next turn
|
|
8112
|
+
* arrives. `turnComplete` merely marks the current turn closed.
|
|
8113
|
+
* This keeps an output transcript that arrives shortly after `turnComplete`
|
|
8114
|
+
* attached to the turn it belongs to, since Google delivers transcription
|
|
8115
|
+
* independently with no guaranteed ordering relative to `turnComplete`.
|
|
8113
8116
|
*/
|
|
8114
8117
|
beginTurnIfClosed() {
|
|
8115
8118
|
if (!this.turnClosed) return;
|
|
@@ -8118,6 +8121,48 @@ var GoogleRealtimeEventMapper = class {
|
|
|
8118
8121
|
this.hasText = false;
|
|
8119
8122
|
this.hasTranscript = false;
|
|
8120
8123
|
this.turnClosed = false;
|
|
8124
|
+
this.preserveInputTranscriptionAcrossTurnComplete = false;
|
|
8125
|
+
}
|
|
8126
|
+
// Google streams input transcription as a sequence of non-accumulating
|
|
8127
|
+
// fragments for a single user utterance (e.g. "The quick brown fox",
|
|
8128
|
+
// " jumps over the", " lazy dog."). Concatenate consecutive fragments into
|
|
8129
|
+
// one running transcript under a stable synthetic id so the realtime reducer
|
|
8130
|
+
// (which overwrites the message for a given id) surfaces them as a single
|
|
8131
|
+
// coherent user message rather than one message per fragment. Google's
|
|
8132
|
+
// `finished` signal is the authoritative utterance boundary. For older
|
|
8133
|
+
// payloads without that signal, response boundaries remain a fallback.
|
|
8134
|
+
//
|
|
8135
|
+
// Input transcriptions can arrive independently of response turn events, so
|
|
8136
|
+
// their synthetic IDs use a sequence independent of `turnCounter`.
|
|
8137
|
+
accumulateInputTranscription({
|
|
8138
|
+
text,
|
|
8139
|
+
finished
|
|
8140
|
+
}) {
|
|
8141
|
+
if (!text) {
|
|
8142
|
+
if (finished === true) {
|
|
8143
|
+
this.finishInputTranscription();
|
|
8144
|
+
}
|
|
8145
|
+
return void 0;
|
|
8146
|
+
}
|
|
8147
|
+
const hasFinishedSignal = finished != null;
|
|
8148
|
+
if (this.inputTranscriptionBuffer !== "" && (this.inputTranscriptionBoundary === "interrupted" || this.inputTranscriptionBoundary === "turn-complete" && !hasFinishedSignal)) {
|
|
8149
|
+
this.finishInputTranscription();
|
|
8150
|
+
}
|
|
8151
|
+
this.inputTranscriptionBoundary = "none";
|
|
8152
|
+
this.inputTranscriptionBuffer += text;
|
|
8153
|
+
const result = {
|
|
8154
|
+
itemId: `google-input-${this.inputTranscriptionCounter}`,
|
|
8155
|
+
transcript: this.inputTranscriptionBuffer
|
|
8156
|
+
};
|
|
8157
|
+
if (finished === true) {
|
|
8158
|
+
this.finishInputTranscription();
|
|
8159
|
+
}
|
|
8160
|
+
return result;
|
|
8161
|
+
}
|
|
8162
|
+
finishInputTranscription() {
|
|
8163
|
+
if (this.inputTranscriptionBuffer === "") return;
|
|
8164
|
+
this.inputTranscriptionCounter++;
|
|
8165
|
+
this.inputTranscriptionBuffer = "";
|
|
8121
8166
|
}
|
|
8122
8167
|
parseServerEvent(raw) {
|
|
8123
8168
|
const data = raw;
|
|
@@ -8174,19 +8219,26 @@ var GoogleRealtimeEventMapper = class {
|
|
|
8174
8219
|
if (data.serverContent != null) {
|
|
8175
8220
|
return this.parseServerContent(data.serverContent, raw);
|
|
8176
8221
|
}
|
|
8177
|
-
if (data.inputTranscription
|
|
8178
|
-
|
|
8179
|
-
|
|
8180
|
-
|
|
8181
|
-
|
|
8182
|
-
|
|
8183
|
-
|
|
8222
|
+
if (data.inputTranscription != null) {
|
|
8223
|
+
const transcription = this.accumulateInputTranscription(
|
|
8224
|
+
data.inputTranscription
|
|
8225
|
+
);
|
|
8226
|
+
if (transcription != null) {
|
|
8227
|
+
return {
|
|
8228
|
+
type: "input-transcription-completed",
|
|
8229
|
+
...transcription,
|
|
8230
|
+
raw
|
|
8231
|
+
};
|
|
8232
|
+
}
|
|
8184
8233
|
}
|
|
8185
8234
|
return { type: "custom", rawType: String(Object.keys(data)[0]), raw };
|
|
8186
8235
|
}
|
|
8187
8236
|
parseServerContent(serverContent, raw) {
|
|
8188
8237
|
const events = [];
|
|
8189
8238
|
if (serverContent.interrupted) {
|
|
8239
|
+
this.inputTranscriptionBoundary = "interrupted";
|
|
8240
|
+
this.preserveInputTranscriptionAcrossTurnComplete = true;
|
|
8241
|
+
this.turnClosed = true;
|
|
8190
8242
|
events.push({
|
|
8191
8243
|
type: "speech-started",
|
|
8192
8244
|
raw
|
|
@@ -8227,13 +8279,17 @@ var GoogleRealtimeEventMapper = class {
|
|
|
8227
8279
|
raw
|
|
8228
8280
|
});
|
|
8229
8281
|
}
|
|
8230
|
-
if (serverContent.inputTranscription
|
|
8231
|
-
|
|
8232
|
-
|
|
8233
|
-
|
|
8234
|
-
|
|
8235
|
-
|
|
8236
|
-
|
|
8282
|
+
if (serverContent.inputTranscription != null) {
|
|
8283
|
+
const transcription = this.accumulateInputTranscription(
|
|
8284
|
+
serverContent.inputTranscription
|
|
8285
|
+
);
|
|
8286
|
+
if (transcription != null) {
|
|
8287
|
+
events.push({
|
|
8288
|
+
type: "input-transcription-completed",
|
|
8289
|
+
...transcription,
|
|
8290
|
+
raw
|
|
8291
|
+
});
|
|
8292
|
+
}
|
|
8237
8293
|
}
|
|
8238
8294
|
if (serverContent.generationComplete) {
|
|
8239
8295
|
events.push({
|
|
@@ -8288,6 +8344,13 @@ var GoogleRealtimeEventMapper = class {
|
|
|
8288
8344
|
raw
|
|
8289
8345
|
});
|
|
8290
8346
|
this.turnClosed = true;
|
|
8347
|
+
if (this.preserveInputTranscriptionAcrossTurnComplete) {
|
|
8348
|
+
this.preserveInputTranscriptionAcrossTurnComplete = false;
|
|
8349
|
+
} else {
|
|
8350
|
+
if (this.inputTranscriptionBoundary !== "interrupted") {
|
|
8351
|
+
this.inputTranscriptionBoundary = "turn-complete";
|
|
8352
|
+
}
|
|
8353
|
+
}
|
|
8291
8354
|
}
|
|
8292
8355
|
if (events.length === 0) {
|
|
8293
8356
|
return { type: "custom", rawType: "serverContent", raw };
|
|
@@ -9528,7 +9591,7 @@ function createGoogle(options = {}) {
|
|
|
9528
9591
|
}),
|
|
9529
9592
|
...options.headers
|
|
9530
9593
|
},
|
|
9531
|
-
`ai-sdk
|
|
9594
|
+
`ai-sdk-google/${VERSION}`
|
|
9532
9595
|
);
|
|
9533
9596
|
const getSupportedUrls = (modelId, includeExternalUrls = modelId == null || supportsExternalFileUrls(modelId)) => ({
|
|
9534
9597
|
"*": [
|