@ai-sdk/google 4.0.25 → 4.0.26
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 +9 -0
- package/dist/index.d.ts +50 -3
- package/dist/index.js +482 -15
- package/dist/index.js.map +1 -1
- package/docs/15-google.mdx +51 -0
- package/package.json +2 -2
- package/src/get-realtime-base-url.ts +31 -0
- package/src/google-provider.ts +32 -0
- package/src/index.ts +6 -0
- package/src/realtime/google-realtime-model.ts +5 -17
- package/src/translation/google-translation-model-options.ts +26 -0
- package/src/translation/google-translation-model.ts +612 -0
package/docs/15-google.mdx
CHANGED
|
@@ -1133,6 +1133,57 @@ Gemini Live Translation accepts audio input and produces translated audio
|
|
|
1133
1133
|
output. Text input, tools, and custom instructions are not supported by this
|
|
1134
1134
|
model.
|
|
1135
1135
|
|
|
1136
|
+
## Translation Models
|
|
1137
|
+
|
|
1138
|
+
<Note type="warning">Speech translation is an experimental feature.</Note>
|
|
1139
|
+
|
|
1140
|
+
For server-side streaming translation, you can create models that call the
|
|
1141
|
+
[Gemini Live API](https://ai.google.dev/gemini-api/docs/live) using the
|
|
1142
|
+
`.translation()` factory method. Translation models are streaming-only and are
|
|
1143
|
+
used with
|
|
1144
|
+
[`experimental_streamTranslate`](/docs/reference/ai-sdk-core/stream-translate).
|
|
1145
|
+
|
|
1146
|
+
The first argument is the model id e.g. `gemini-3.5-live-translate-preview`.
|
|
1147
|
+
|
|
1148
|
+
```ts
|
|
1149
|
+
const model = google.translation('gemini-3.5-live-translate-preview');
|
|
1150
|
+
```
|
|
1151
|
+
|
|
1152
|
+
```ts
|
|
1153
|
+
import { experimental_streamTranslate as streamTranslate } from 'ai';
|
|
1154
|
+
import { google } from '@ai-sdk/google';
|
|
1155
|
+
|
|
1156
|
+
const result = streamTranslate({
|
|
1157
|
+
model: google.translation('gemini-3.5-live-translate-preview'),
|
|
1158
|
+
audio: audioStream, // ReadableStream<Uint8Array | string>
|
|
1159
|
+
inputAudioFormat: { type: 'audio/pcm', rate: 16000 },
|
|
1160
|
+
targetLanguage: 'es',
|
|
1161
|
+
});
|
|
1162
|
+
|
|
1163
|
+
for await (const part of result.fullStream) {
|
|
1164
|
+
if (part.type === 'output-text-delta') {
|
|
1165
|
+
process.stdout.write(part.delta);
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
```
|
|
1169
|
+
|
|
1170
|
+
The Gemini Live API auto-detects the source language (`sourceLanguage` is not
|
|
1171
|
+
supported) and always outputs 24kHz 16-bit PCM audio (`outputAudioFormat` is
|
|
1172
|
+
not supported). Unsupported settings surface as call warnings.
|
|
1173
|
+
|
|
1174
|
+
The following provider options are available:
|
|
1175
|
+
|
|
1176
|
+
- **echoTargetLanguage** _boolean_
|
|
1177
|
+
Whether input audio already in the target language should be echoed instead
|
|
1178
|
+
of producing silence.
|
|
1179
|
+
Optional.
|
|
1180
|
+
|
|
1181
|
+
### Model Capabilities
|
|
1182
|
+
|
|
1183
|
+
| Model | Translated Audio | Translated Text | Source Transcript |
|
|
1184
|
+
| ----------------------------------- | ---------------- | --------------- | ----------------- |
|
|
1185
|
+
| `gemini-3.5-live-translate-preview` | <Check /> | <Check /> | <Check /> |
|
|
1186
|
+
|
|
1136
1187
|
## Interactions API
|
|
1137
1188
|
|
|
1138
1189
|
The [Gemini Interactions API](https://ai.google.dev/gemini-api/docs/interactions)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/google",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.26",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@ai-sdk/provider": "4.0.4",
|
|
39
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
39
|
+
"@ai-sdk/provider-utils": "5.0.14"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/node": "22.19.19",
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the base URL for Live API (WebSocket) endpoints, stripping a
|
|
3
|
+
* trailing `/v1beta` or `/v1alpha` API version segment: Live API paths carry
|
|
4
|
+
* their own version and are not nested under it.
|
|
5
|
+
*/
|
|
6
|
+
export function getRealtimeBaseURL(baseURL: string): URL {
|
|
7
|
+
const url = new URL(baseURL);
|
|
8
|
+
const pathSegments = url.pathname.split('/');
|
|
9
|
+
const version = pathSegments.at(-1);
|
|
10
|
+
|
|
11
|
+
if (version === 'v1beta' || version === 'v1alpha') {
|
|
12
|
+
pathSegments.pop();
|
|
13
|
+
url.pathname = pathSegments.join('/') || '/';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return url;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Builds a `wss://` Live API WebSocket URL for the given bidi service path
|
|
21
|
+
* (e.g. `google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent`).
|
|
22
|
+
*/
|
|
23
|
+
export function getRealtimeWebSocketURL(
|
|
24
|
+
baseURL: string,
|
|
25
|
+
webSocketPath: string,
|
|
26
|
+
): URL {
|
|
27
|
+
const url = getRealtimeBaseURL(baseURL);
|
|
28
|
+
url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
29
|
+
url.pathname = `${url.pathname.replace(/\/$/, '')}/ws/${webSocketPath}`;
|
|
30
|
+
return url;
|
|
31
|
+
}
|
package/src/google-provider.ts
CHANGED
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
Experimental_RealtimeFactoryV4 as RealtimeFactoryV4,
|
|
9
9
|
Experimental_RealtimeFactoryV4GetTokenOptions as RealtimeFactoryV4GetTokenOptions,
|
|
10
10
|
SpeechModelV4,
|
|
11
|
+
Experimental_SpeechTranslationModelV4 as SpeechTranslationModelV4,
|
|
11
12
|
} from '@ai-sdk/provider';
|
|
12
13
|
import {
|
|
13
14
|
generateId,
|
|
@@ -15,6 +16,7 @@ import {
|
|
|
15
16
|
withoutTrailingSlash,
|
|
16
17
|
withUserAgentSuffix,
|
|
17
18
|
type FetchFunction,
|
|
19
|
+
type WebSocketConstructor,
|
|
18
20
|
} from '@ai-sdk/provider-utils';
|
|
19
21
|
import { VERSION } from './version';
|
|
20
22
|
import { GoogleEmbeddingModel } from './google-embedding-model';
|
|
@@ -40,6 +42,8 @@ import {
|
|
|
40
42
|
import type { GoogleInteractionsModelId } from './interactions/google-interactions-language-model-options';
|
|
41
43
|
import type { GoogleInteractionsAgentName } from './interactions/google-interactions-agent';
|
|
42
44
|
import { GoogleRealtimeModel } from './realtime/google-realtime-model';
|
|
45
|
+
import { GoogleTranslationModel } from './translation/google-translation-model';
|
|
46
|
+
import type { GoogleTranslationModelId } from './translation/google-translation-model-options';
|
|
43
47
|
|
|
44
48
|
export interface GoogleProvider extends ProviderV4 {
|
|
45
49
|
(modelId: GoogleModelId): LanguageModelV4;
|
|
@@ -91,6 +95,18 @@ export interface GoogleProvider extends ProviderV4 {
|
|
|
91
95
|
*/
|
|
92
96
|
videoModel(modelId: GoogleVideoModelId): Experimental_VideoModelV4;
|
|
93
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Creates an experimental model for streaming speech translation.
|
|
100
|
+
*/
|
|
101
|
+
translation(modelId: GoogleTranslationModelId): SpeechTranslationModelV4;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Creates an experimental model for streaming speech translation.
|
|
105
|
+
*/
|
|
106
|
+
speechTranslationModel(
|
|
107
|
+
modelId: GoogleTranslationModelId,
|
|
108
|
+
): SpeechTranslationModelV4;
|
|
109
|
+
|
|
94
110
|
/**
|
|
95
111
|
* Creates a model for speech generation (text-to-speech).
|
|
96
112
|
*/
|
|
@@ -152,6 +168,12 @@ export interface GoogleProviderSettings {
|
|
|
152
168
|
*/
|
|
153
169
|
generateId?: () => string;
|
|
154
170
|
|
|
171
|
+
/**
|
|
172
|
+
* Custom WebSocket implementation. This is useful for testing or for
|
|
173
|
+
* runtimes that need a WebSocket constructor with header support.
|
|
174
|
+
*/
|
|
175
|
+
webSocket?: WebSocketConstructor;
|
|
176
|
+
|
|
155
177
|
/**
|
|
156
178
|
* Custom provider name
|
|
157
179
|
* Defaults to 'google.generative-ai'.
|
|
@@ -288,6 +310,14 @@ export function createGoogle(
|
|
|
288
310
|
fetch: options.fetch,
|
|
289
311
|
});
|
|
290
312
|
|
|
313
|
+
const createTranslationModel = (modelId: GoogleTranslationModelId) =>
|
|
314
|
+
new GoogleTranslationModel(modelId, {
|
|
315
|
+
provider: `${providerName}.translation`,
|
|
316
|
+
baseURL,
|
|
317
|
+
headers: getHeaders,
|
|
318
|
+
webSocket: options.webSocket,
|
|
319
|
+
});
|
|
320
|
+
|
|
291
321
|
const createSpeechModel = (modelId: GoogleSpeechModelId) =>
|
|
292
322
|
new GoogleSpeechModel(modelId, {
|
|
293
323
|
provider: `${providerName}.speech`,
|
|
@@ -358,6 +388,8 @@ export function createGoogle(
|
|
|
358
388
|
provider.files = createFiles;
|
|
359
389
|
provider.speech = createSpeechModel;
|
|
360
390
|
provider.speechModel = createSpeechModel;
|
|
391
|
+
provider.translation = createTranslationModel;
|
|
392
|
+
provider.speechTranslationModel = createTranslationModel;
|
|
361
393
|
provider.interactions = createInteractionsModel;
|
|
362
394
|
provider.tools = googleTools;
|
|
363
395
|
|
package/src/index.ts
CHANGED
|
@@ -60,5 +60,11 @@ export type {
|
|
|
60
60
|
GoogleRealtimeModelId as Experimental_GoogleRealtimeModelId,
|
|
61
61
|
GoogleRealtimeModelOptions as Experimental_GoogleRealtimeModelOptions,
|
|
62
62
|
} from './realtime/google-realtime-model-options';
|
|
63
|
+
export { GoogleTranslationModel as Experimental_GoogleTranslationModel } from './translation/google-translation-model';
|
|
64
|
+
export type { GoogleTranslationModelConfig as Experimental_GoogleTranslationModelConfig } from './translation/google-translation-model';
|
|
65
|
+
export type {
|
|
66
|
+
GoogleTranslationModelId as Experimental_GoogleTranslationModelId,
|
|
67
|
+
GoogleTranslationModelOptions as Experimental_GoogleTranslationModelOptions,
|
|
68
|
+
} from './translation/google-translation-model-options';
|
|
63
69
|
|
|
64
70
|
export { VERSION } from './version';
|
|
@@ -7,6 +7,10 @@ import type {
|
|
|
7
7
|
Experimental_RealtimeModelV4SessionConfig as RealtimeModelV4SessionConfig,
|
|
8
8
|
} from '@ai-sdk/provider';
|
|
9
9
|
import type { FetchFunction } from '@ai-sdk/provider-utils';
|
|
10
|
+
import {
|
|
11
|
+
getRealtimeBaseURL,
|
|
12
|
+
getRealtimeWebSocketURL,
|
|
13
|
+
} from '../get-realtime-base-url';
|
|
10
14
|
import {
|
|
11
15
|
GoogleRealtimeEventMapper,
|
|
12
16
|
buildGoogleSessionConfig,
|
|
@@ -15,19 +19,6 @@ import {
|
|
|
15
19
|
const realtimeWebSocketPath =
|
|
16
20
|
'google.ai.generativelanguage.v1alpha.GenerativeService.BidiGenerateContentConstrained';
|
|
17
21
|
|
|
18
|
-
function getRealtimeBaseURL(baseURL: string): URL {
|
|
19
|
-
const url = new URL(baseURL);
|
|
20
|
-
const pathSegments = url.pathname.split('/');
|
|
21
|
-
const version = pathSegments.at(-1);
|
|
22
|
-
|
|
23
|
-
if (version === 'v1beta' || version === 'v1alpha') {
|
|
24
|
-
pathSegments.pop();
|
|
25
|
-
url.pathname = pathSegments.join('/') || '/';
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return url;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
22
|
function getAuthTokensURL(baseURL: string): string {
|
|
32
23
|
const url = getRealtimeBaseURL(baseURL);
|
|
33
24
|
url.pathname = `${url.pathname.replace(/\/$/, '')}/v1alpha/auth_tokens`;
|
|
@@ -35,10 +26,7 @@ function getAuthTokensURL(baseURL: string): string {
|
|
|
35
26
|
}
|
|
36
27
|
|
|
37
28
|
function getWebSocketURL(baseURL: string): string {
|
|
38
|
-
|
|
39
|
-
url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
40
|
-
url.pathname = `${url.pathname.replace(/\/$/, '')}/ws/${realtimeWebSocketPath}`;
|
|
41
|
-
return url.toString();
|
|
29
|
+
return getRealtimeWebSocketURL(baseURL, realtimeWebSocketPath).toString();
|
|
42
30
|
}
|
|
43
31
|
|
|
44
32
|
export type GoogleRealtimeModelConfig = {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {
|
|
2
|
+
lazySchema,
|
|
3
|
+
zodSchema,
|
|
4
|
+
type InferSchema,
|
|
5
|
+
} from '@ai-sdk/provider-utils';
|
|
6
|
+
import { z } from 'zod/v4';
|
|
7
|
+
|
|
8
|
+
export type GoogleTranslationModelId =
|
|
9
|
+
| 'gemini-3.5-live-translate-preview'
|
|
10
|
+
| (string & {});
|
|
11
|
+
|
|
12
|
+
export const googleTranslationModelOptions = lazySchema(() =>
|
|
13
|
+
zodSchema(
|
|
14
|
+
z.object({
|
|
15
|
+
/**
|
|
16
|
+
* Whether input audio already in the target language should be echoed
|
|
17
|
+
* instead of producing silence.
|
|
18
|
+
*/
|
|
19
|
+
echoTargetLanguage: z.boolean().optional(),
|
|
20
|
+
}),
|
|
21
|
+
),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
export type GoogleTranslationModelOptions = InferSchema<
|
|
25
|
+
typeof googleTranslationModelOptions
|
|
26
|
+
>;
|