@ai-sdk/google 4.0.101 → 4.0.103
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 +26 -0
- package/dist/index.d.ts +10 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +64 -50
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +41 -33
- package/dist/internal/index.js.map +1 -1
- package/docs/15-google.mdx +1 -1
- package/package.json +3 -3
- package/src/continue-google-stream.ts +11 -3
- package/src/google-batch.ts +37 -34
- package/src/google-embedding-model-options.ts +15 -14
- package/src/google-files.ts +1 -11
- package/src/google-image-model-options.ts +1 -1
- package/src/google-language-model.ts +60 -44
- package/src/google-speech-model-options.ts +17 -14
- package/src/google-video-model.ts +34 -27
- package/src/interactions/build-google-interactions-stream-transform.ts +12 -5
- package/src/tool/file-search.ts +34 -27
- package/src/tool/google-search.ts +16 -15
- package/src/transcription/google-transcription-model-options.ts +40 -31
- package/src/transcription/google-transcription-model.ts +37 -30
package/docs/15-google.mdx
CHANGED
|
@@ -878,7 +878,7 @@ import { generateText } from 'ai';
|
|
|
878
878
|
const { text, sources, providerMetadata } = await generateText({
|
|
879
879
|
model: google('gemini-4-argon'),
|
|
880
880
|
prompt: `Based on the document: https://ai.google.dev/gemini-api/docs/url-context.
|
|
881
|
-
Answer this question: How many links we
|
|
881
|
+
Answer this question: How many links can we consume in one request?`,
|
|
882
882
|
tools: {
|
|
883
883
|
url_context: google.tools.urlContext({}),
|
|
884
884
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/google",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.103",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@ai-sdk/provider": "4.0.
|
|
39
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
38
|
+
"@ai-sdk/provider": "4.0.32",
|
|
39
|
+
"@ai-sdk/provider-utils": "5.0.66"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@ai-sdk/test-server": "2.0.4",
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import type { ParseResult } from '@ai-sdk/provider-utils';
|
|
2
2
|
|
|
3
|
+
export type GoogleStreamPart<T> =
|
|
4
|
+
| ParseResult<T>
|
|
5
|
+
| { type: 'continuation-start' };
|
|
6
|
+
|
|
3
7
|
/**
|
|
4
8
|
* Concatenates the event streams of a long decode response that spans several
|
|
5
9
|
* requests (Gemini 4 long decode).
|
|
@@ -7,7 +11,9 @@ import type { ParseResult } from '@ai-sdk/provider-utils';
|
|
|
7
11
|
* Events of the current stream are passed through unchanged. When an event
|
|
8
12
|
* signals that the per-request cap was reached while budget remains
|
|
9
13
|
* (`getContinuationToken` returns a token), the next request is sent with that
|
|
10
|
-
* token once the current stream ends, and its events are appended
|
|
14
|
+
* token once the current stream ends, and its events are appended after a
|
|
15
|
+
* `continuation-start` marker. The marker orders per-response state changes
|
|
16
|
+
* with buffered events, including when the new stream is empty. If the
|
|
11
17
|
* continuation request fails, the error is emitted as a failed parse result
|
|
12
18
|
* and the stream ends.
|
|
13
19
|
*/
|
|
@@ -21,11 +27,11 @@ export function continueGoogleStream<T>({
|
|
|
21
27
|
continueStream: (
|
|
22
28
|
continuationToken: string,
|
|
23
29
|
) => Promise<ReadableStream<ParseResult<T>>>;
|
|
24
|
-
}): ReadableStream<
|
|
30
|
+
}): ReadableStream<GoogleStreamPart<T>> {
|
|
25
31
|
let reader = stream.getReader();
|
|
26
32
|
let pendingContinuationToken: string | undefined;
|
|
27
33
|
|
|
28
|
-
return new ReadableStream<
|
|
34
|
+
return new ReadableStream<GoogleStreamPart<T>>({
|
|
29
35
|
async pull(controller) {
|
|
30
36
|
while (true) {
|
|
31
37
|
const { done, value } = await reader.read();
|
|
@@ -51,6 +57,8 @@ export function continueGoogleStream<T>({
|
|
|
51
57
|
|
|
52
58
|
try {
|
|
53
59
|
reader = (await continueStream(continuationToken)).getReader();
|
|
60
|
+
controller.enqueue({ type: 'continuation-start' });
|
|
61
|
+
return;
|
|
54
62
|
} catch (error) {
|
|
55
63
|
// Surfaced as an `error` stream part, followed by the `finish` part
|
|
56
64
|
// with the last continuation token so the caller can resume.
|
package/src/google-batch.ts
CHANGED
|
@@ -78,35 +78,38 @@ function assertSupportedBatchRequests(
|
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
const googleRpcStatusSchema =
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
81
|
+
const googleRpcStatusSchema = () =>
|
|
82
|
+
z.object({
|
|
83
|
+
code: z.union([z.number(), z.string()]).nullish(),
|
|
84
|
+
message: z.string().nullish(),
|
|
85
|
+
status: z.string().nullish(),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const googleBatchStatsSchema = () =>
|
|
89
|
+
z.object({
|
|
90
|
+
requestCount: z.union([z.string(), z.number()]).nullish(),
|
|
91
|
+
successfulRequestCount: z.union([z.string(), z.number()]).nullish(),
|
|
92
|
+
failedRequestCount: z.union([z.string(), z.number()]).nullish(),
|
|
93
|
+
pendingRequestCount: z.union([z.string(), z.number()]).nullish(),
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const googleBatchOutputSchema = () =>
|
|
97
|
+
z.object({
|
|
98
|
+
responsesFile: z.string().nullish(),
|
|
99
|
+
inlinedResponses: z
|
|
100
|
+
.object({
|
|
101
|
+
inlinedResponses: z.array(
|
|
102
|
+
z.object({
|
|
103
|
+
metadata: z.object({
|
|
104
|
+
key: z.string(),
|
|
105
|
+
}),
|
|
106
|
+
response: z.unknown().nullish(),
|
|
107
|
+
error: googleRpcStatusSchema().nullish(),
|
|
102
108
|
}),
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
})
|
|
108
|
-
.nullish(),
|
|
109
|
-
});
|
|
109
|
+
),
|
|
110
|
+
})
|
|
111
|
+
.nullish(),
|
|
112
|
+
});
|
|
110
113
|
|
|
111
114
|
const googleBatchOperationZodSchema = () =>
|
|
112
115
|
z.object({
|
|
@@ -115,13 +118,13 @@ const googleBatchOperationZodSchema = () =>
|
|
|
115
118
|
.object({
|
|
116
119
|
state: z.string().nullish(),
|
|
117
120
|
createTime: z.string().nullish(),
|
|
118
|
-
batchStats: googleBatchStatsSchema.nullish(),
|
|
119
|
-
output: googleBatchOutputSchema.nullish(),
|
|
121
|
+
batchStats: googleBatchStatsSchema().nullish(),
|
|
122
|
+
output: googleBatchOutputSchema().nullish(),
|
|
120
123
|
})
|
|
121
124
|
.nullish(),
|
|
122
125
|
done: z.boolean().nullish(),
|
|
123
|
-
error: googleRpcStatusSchema.nullish(),
|
|
124
|
-
response: googleBatchOutputSchema.nullish(),
|
|
126
|
+
error: googleRpcStatusSchema().nullish(),
|
|
127
|
+
response: googleBatchOutputSchema().nullish(),
|
|
125
128
|
});
|
|
126
129
|
|
|
127
130
|
const googleBatchOperationSchema = lazySchema(() =>
|
|
@@ -159,7 +162,7 @@ const googleBatchResultLineSchema = lazySchema(() =>
|
|
|
159
162
|
z.object({
|
|
160
163
|
key: z.string(),
|
|
161
164
|
response: z.unknown().nullish(),
|
|
162
|
-
error: googleRpcStatusSchema.nullish(),
|
|
165
|
+
error: googleRpcStatusSchema().nullish(),
|
|
163
166
|
}),
|
|
164
167
|
),
|
|
165
168
|
);
|
|
@@ -872,7 +875,7 @@ function parseCount(value: string | number | null | undefined) {
|
|
|
872
875
|
}
|
|
873
876
|
|
|
874
877
|
function convertGoogleRpcError(
|
|
875
|
-
error: InferSchema<typeof googleRpcStatusSchema
|
|
878
|
+
error: InferSchema<ReturnType<typeof googleRpcStatusSchema>>,
|
|
876
879
|
fallbackMessage: string,
|
|
877
880
|
): BatchV4Error {
|
|
878
881
|
return {
|
|
@@ -11,21 +11,22 @@ export type GoogleEmbeddingModelId =
|
|
|
11
11
|
| 'gemini-embedding-2-preview'
|
|
12
12
|
| (string & {});
|
|
13
13
|
|
|
14
|
-
const googleEmbeddingContentPartSchema =
|
|
15
|
-
z.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
const googleEmbeddingContentPartSchema = () =>
|
|
15
|
+
z.union([
|
|
16
|
+
z.object({ text: z.string() }),
|
|
17
|
+
z.object({
|
|
18
|
+
inlineData: z.object({
|
|
19
|
+
mimeType: z.string(),
|
|
20
|
+
data: z.string(),
|
|
21
|
+
}),
|
|
20
22
|
}),
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
z.object({
|
|
24
|
+
fileData: z.object({
|
|
25
|
+
fileUri: z.string(),
|
|
26
|
+
mimeType: z.string(),
|
|
27
|
+
}),
|
|
26
28
|
}),
|
|
27
|
-
|
|
28
|
-
]);
|
|
29
|
+
]);
|
|
29
30
|
|
|
30
31
|
export const googleEmbeddingModelOptions = lazySchema(() =>
|
|
31
32
|
zodSchema(
|
|
@@ -71,7 +72,7 @@ export const googleEmbeddingModelOptions = lazySchema(() =>
|
|
|
71
72
|
* the case of a single embedding, the array length must be 1.
|
|
72
73
|
*/
|
|
73
74
|
content: z
|
|
74
|
-
.array(z.array(googleEmbeddingContentPartSchema).min(1).nullable())
|
|
75
|
+
.array(z.array(googleEmbeddingContentPartSchema()).min(1).nullable())
|
|
75
76
|
.optional(),
|
|
76
77
|
}),
|
|
77
78
|
),
|
package/src/google-files.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
lazySchema,
|
|
14
14
|
parseProviderOptions,
|
|
15
15
|
zodSchema,
|
|
16
|
+
encodePathSegment,
|
|
16
17
|
getFromApi,
|
|
17
18
|
type FetchFunction,
|
|
18
19
|
} from '@ai-sdk/provider-utils';
|
|
@@ -34,17 +35,6 @@ interface GoogleFilesConfig {
|
|
|
34
35
|
fetch?: FetchFunction;
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
function encodePathSegment(value: string): string {
|
|
38
|
-
const encodedValue = encodeURIComponent(value);
|
|
39
|
-
|
|
40
|
-
// URL parsing normalizes both literal and percent-encoded dot segments.
|
|
41
|
-
return encodedValue === '.'
|
|
42
|
-
? '%252E'
|
|
43
|
-
: encodedValue === '..'
|
|
44
|
-
? '%252E%252E'
|
|
45
|
-
: encodedValue;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
38
|
export class GoogleFiles implements FilesV4 {
|
|
49
39
|
readonly specificationVersion = 'v4';
|
|
50
40
|
|
|
@@ -18,7 +18,7 @@ export const googleImageModelOptionsSchema = lazySchema(() =>
|
|
|
18
18
|
* dedicated escape hatch for grounding image generation the same way
|
|
19
19
|
* `generateText` does.
|
|
20
20
|
*/
|
|
21
|
-
googleSearch: googleSearchToolArgsBaseSchema.optional(),
|
|
21
|
+
googleSearch: googleSearchToolArgsBaseSchema().optional(),
|
|
22
22
|
}),
|
|
23
23
|
),
|
|
24
24
|
);
|
|
@@ -33,11 +33,13 @@ import {
|
|
|
33
33
|
zodSchema,
|
|
34
34
|
type FetchFunction,
|
|
35
35
|
type InferSchema,
|
|
36
|
-
type ParseResult,
|
|
37
36
|
type Resolvable,
|
|
38
37
|
} from '@ai-sdk/provider-utils';
|
|
39
38
|
import { z } from 'zod/v4';
|
|
40
|
-
import {
|
|
39
|
+
import {
|
|
40
|
+
continueGoogleStream,
|
|
41
|
+
type GoogleStreamPart,
|
|
42
|
+
} from './continue-google-stream';
|
|
41
43
|
import {
|
|
42
44
|
addGoogleUsageMetadata,
|
|
43
45
|
convertGoogleUsage,
|
|
@@ -926,8 +928,9 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
926
928
|
},
|
|
927
929
|
});
|
|
928
930
|
|
|
931
|
+
// A clean end without the provider's completion signal is interrupted.
|
|
929
932
|
let finishReason: LanguageModelV4FinishReason = {
|
|
930
|
-
unified: '
|
|
933
|
+
unified: 'interrupted',
|
|
931
934
|
raw: undefined,
|
|
932
935
|
};
|
|
933
936
|
let usage: GoogleUsageMetadata | undefined = undefined;
|
|
@@ -1005,7 +1008,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
1005
1008
|
const result = {
|
|
1006
1009
|
stream: response.pipeThrough(
|
|
1007
1010
|
new TransformStream<
|
|
1008
|
-
|
|
1011
|
+
GoogleStreamPart<ChunkSchema>,
|
|
1009
1012
|
LanguageModelV4StreamPart
|
|
1010
1013
|
>({
|
|
1011
1014
|
start(controller) {
|
|
@@ -1013,11 +1016,21 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
1013
1016
|
},
|
|
1014
1017
|
|
|
1015
1018
|
transform(chunk, controller) {
|
|
1019
|
+
if ('type' in chunk) {
|
|
1020
|
+
// Reset in stream order, after the prior response's buffered
|
|
1021
|
+
// CONTINUATION chunk, rather than when the request starts.
|
|
1022
|
+
finishReason = { unified: 'interrupted', raw: undefined };
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1016
1026
|
if (options.includeRawChunks) {
|
|
1017
1027
|
controller.enqueue({ type: 'raw', rawValue: chunk.rawValue });
|
|
1018
1028
|
}
|
|
1019
1029
|
|
|
1020
1030
|
if (!chunk.success) {
|
|
1031
|
+
if (finishReason.unified === 'interrupted') {
|
|
1032
|
+
finishReason = { unified: 'error', raw: undefined };
|
|
1033
|
+
}
|
|
1021
1034
|
controller.enqueue({ type: 'error', error: chunk.error });
|
|
1022
1035
|
return;
|
|
1023
1036
|
}
|
|
@@ -1889,14 +1902,15 @@ export const getGroundingMetadataSchema = () =>
|
|
|
1889
1902
|
.nullish(),
|
|
1890
1903
|
});
|
|
1891
1904
|
|
|
1892
|
-
const partialArgSchema =
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1905
|
+
const partialArgSchema = () =>
|
|
1906
|
+
z.object({
|
|
1907
|
+
jsonPath: z.string(),
|
|
1908
|
+
stringValue: z.string().nullish(),
|
|
1909
|
+
numberValue: z.number().nullish(),
|
|
1910
|
+
boolValue: z.boolean().nullish(),
|
|
1911
|
+
nullValue: z.unknown().nullish(),
|
|
1912
|
+
willContinue: z.boolean().nullish(),
|
|
1913
|
+
});
|
|
1900
1914
|
|
|
1901
1915
|
const getContentSchema = () =>
|
|
1902
1916
|
z.object({
|
|
@@ -1909,7 +1923,7 @@ const getContentSchema = () =>
|
|
|
1909
1923
|
id: z.string().nullish(),
|
|
1910
1924
|
name: z.string().nullish(),
|
|
1911
1925
|
args: z.unknown().nullish(),
|
|
1912
|
-
partialArgs: z.array(partialArgSchema).nullish(),
|
|
1926
|
+
partialArgs: z.array(partialArgSchema()).nullish(),
|
|
1913
1927
|
willContinue: z.boolean().nullish(),
|
|
1914
1928
|
}),
|
|
1915
1929
|
thoughtSignature: z.string().nullish(),
|
|
@@ -1971,35 +1985,37 @@ const getSafetyRatingSchema = () =>
|
|
|
1971
1985
|
blocked: z.boolean().nullish(),
|
|
1972
1986
|
});
|
|
1973
1987
|
|
|
1974
|
-
const tokenDetailsSchema =
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
1988
|
+
const tokenDetailsSchema = () =>
|
|
1989
|
+
z
|
|
1990
|
+
.array(
|
|
1991
|
+
z
|
|
1992
|
+
.object({
|
|
1993
|
+
modality: z.string(),
|
|
1994
|
+
tokenCount: z.number(),
|
|
1995
|
+
})
|
|
1996
|
+
.loose(),
|
|
1997
|
+
)
|
|
1998
|
+
.nullish();
|
|
1999
|
+
|
|
2000
|
+
const usageSchema = () =>
|
|
2001
|
+
z
|
|
2002
|
+
.object({
|
|
2003
|
+
cachedContentTokenCount: z.number().nullish(),
|
|
2004
|
+
thoughtsTokenCount: z.number().nullish(),
|
|
2005
|
+
promptTokenCount: z.number().nullish(),
|
|
2006
|
+
candidatesTokenCount: z.number().nullish(),
|
|
2007
|
+
toolUsePromptTokenCount: z.number().nullish(),
|
|
2008
|
+
totalTokenCount: z.number().nullish(),
|
|
2009
|
+
// https://cloud.google.com/vertex-ai/generative-ai/docs/reference/rest/v1/GenerateContentResponse#TrafficType
|
|
2010
|
+
trafficType: z.string().nullish(),
|
|
2011
|
+
serviceTier: z.string().nullish(),
|
|
2012
|
+
// https://ai.google.dev/api/generate-content#Modality
|
|
2013
|
+
promptTokensDetails: tokenDetailsSchema(),
|
|
2014
|
+
cacheTokensDetails: tokenDetailsSchema(),
|
|
2015
|
+
candidatesTokensDetails: tokenDetailsSchema(),
|
|
2016
|
+
toolUsePromptTokensDetails: tokenDetailsSchema(),
|
|
2017
|
+
})
|
|
2018
|
+
.loose();
|
|
2003
2019
|
|
|
2004
2020
|
// https://ai.google.dev/api/generate-content#UrlRetrievalMetadata
|
|
2005
2021
|
export const getUrlContextMetadataSchema = () =>
|
|
@@ -2031,7 +2047,7 @@ export const responseSchema = lazySchema(() =>
|
|
|
2031
2047
|
}),
|
|
2032
2048
|
)
|
|
2033
2049
|
.nullish(),
|
|
2034
|
-
usageMetadata: usageSchema.nullish(),
|
|
2050
|
+
usageMetadata: usageSchema().nullish(),
|
|
2035
2051
|
promptFeedback: z
|
|
2036
2052
|
.object({
|
|
2037
2053
|
blockReason: z.string().nullish(),
|
|
@@ -2086,7 +2102,7 @@ const chunkSchema = lazySchema(() =>
|
|
|
2086
2102
|
}),
|
|
2087
2103
|
)
|
|
2088
2104
|
.nullish(),
|
|
2089
|
-
usageMetadata: usageSchema.nullish(),
|
|
2105
|
+
usageMetadata: usageSchema().nullish(),
|
|
2090
2106
|
promptFeedback: z
|
|
2091
2107
|
.object({
|
|
2092
2108
|
blockReason: z.string().nullish(),
|
|
@@ -13,25 +13,28 @@ export type GoogleSpeechModelId =
|
|
|
13
13
|
| 'gemini-3.8-flash-lite-tts'
|
|
14
14
|
| (string & {});
|
|
15
15
|
|
|
16
|
-
const prebuiltVoiceConfigSchema =
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
const prebuiltVoiceConfigSchema = () =>
|
|
17
|
+
z.object({
|
|
18
|
+
voiceName: z.string(),
|
|
19
|
+
});
|
|
19
20
|
|
|
20
|
-
const voiceConfigSchema =
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
const voiceConfigSchema = () =>
|
|
22
|
+
z.object({
|
|
23
|
+
prebuiltVoiceConfig: prebuiltVoiceConfigSchema(),
|
|
24
|
+
voice: z.never().optional(),
|
|
25
|
+
});
|
|
24
26
|
|
|
25
|
-
const speechMetadataSchema =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
const speechMetadataSchema = () =>
|
|
28
|
+
z.object({
|
|
29
|
+
speaker: z.string().min(1).optional(),
|
|
30
|
+
style: z.string().optional(),
|
|
31
|
+
});
|
|
29
32
|
|
|
30
33
|
export const googleSpeechProviderOptionsSchema = lazySchema(() =>
|
|
31
34
|
zodSchema(
|
|
32
35
|
z.object({
|
|
33
36
|
/** Turn-level directions for the top-level text, for Gemini 3.8 TTS. */
|
|
34
|
-
speechMetadata: speechMetadataSchema.optional(),
|
|
37
|
+
speechMetadata: speechMetadataSchema().optional(),
|
|
35
38
|
|
|
36
39
|
/**
|
|
37
40
|
* Structured transcript for Gemini 3.8 TTS. Replaces the top-level text;
|
|
@@ -42,7 +45,7 @@ export const googleSpeechProviderOptionsSchema = lazySchema(() =>
|
|
|
42
45
|
.array(
|
|
43
46
|
z.object({
|
|
44
47
|
text: z.string(),
|
|
45
|
-
speechMetadata: speechMetadataSchema.optional(),
|
|
48
|
+
speechMetadata: speechMetadataSchema().optional(),
|
|
46
49
|
}),
|
|
47
50
|
)
|
|
48
51
|
.min(1)
|
|
@@ -61,7 +64,7 @@ export const googleSpeechProviderOptionsSchema = lazySchema(() =>
|
|
|
61
64
|
speakerVoiceConfigs: z.array(
|
|
62
65
|
z.object({
|
|
63
66
|
speaker: z.string(),
|
|
64
|
-
voiceConfig: voiceConfigSchema,
|
|
67
|
+
voiceConfig: voiceConfigSchema(),
|
|
65
68
|
}),
|
|
66
69
|
),
|
|
67
70
|
})
|
|
@@ -9,6 +9,9 @@ import {
|
|
|
9
9
|
type SharedV4Warning,
|
|
10
10
|
} from '@ai-sdk/provider';
|
|
11
11
|
import {
|
|
12
|
+
lazySchema,
|
|
13
|
+
zodSchema,
|
|
14
|
+
type InferSchema,
|
|
12
15
|
combineHeaders,
|
|
13
16
|
convertUint8ArrayToBase64,
|
|
14
17
|
createJsonResponseHandler,
|
|
@@ -265,7 +268,7 @@ export class GoogleVideoModel implements VideoModelV4 {
|
|
|
265
268
|
}
|
|
266
269
|
|
|
267
270
|
private async buildCompletedResult(
|
|
268
|
-
finalOperation:
|
|
271
|
+
finalOperation: InferSchema<typeof googleOperationSchema>,
|
|
269
272
|
responseHeaders: Record<string, string> | undefined,
|
|
270
273
|
warnings: SharedV4Warning[],
|
|
271
274
|
currentDate: Date,
|
|
@@ -441,33 +444,37 @@ export class GoogleVideoModel implements VideoModelV4 {
|
|
|
441
444
|
}
|
|
442
445
|
}
|
|
443
446
|
|
|
444
|
-
const googleOperationSchema =
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
message: z.string(),
|
|
451
|
-
status: z.string().nullish(),
|
|
452
|
-
})
|
|
453
|
-
.nullish(),
|
|
454
|
-
response: z
|
|
455
|
-
.object({
|
|
456
|
-
generateVideoResponse: z
|
|
447
|
+
const googleOperationSchema = lazySchema(() =>
|
|
448
|
+
zodSchema(
|
|
449
|
+
z.object({
|
|
450
|
+
name: z.string().nullish(),
|
|
451
|
+
done: z.boolean().nullish(),
|
|
452
|
+
error: z
|
|
457
453
|
.object({
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
454
|
+
code: z.number().nullish(),
|
|
455
|
+
message: z.string(),
|
|
456
|
+
status: z.string().nullish(),
|
|
457
|
+
})
|
|
458
|
+
.nullish(),
|
|
459
|
+
response: z
|
|
460
|
+
.object({
|
|
461
|
+
generateVideoResponse: z
|
|
462
|
+
.object({
|
|
463
|
+
generatedSamples: z
|
|
464
|
+
.array(
|
|
465
|
+
z.object({
|
|
466
|
+
video: z
|
|
467
|
+
.object({
|
|
468
|
+
uri: z.string().nullish(),
|
|
469
|
+
})
|
|
470
|
+
.nullish(),
|
|
471
|
+
}),
|
|
472
|
+
)
|
|
473
|
+
.nullish(),
|
|
474
|
+
})
|
|
468
475
|
.nullish(),
|
|
469
476
|
})
|
|
470
477
|
.nullish(),
|
|
471
|
-
})
|
|
472
|
-
|
|
473
|
-
|
|
478
|
+
}),
|
|
479
|
+
),
|
|
480
|
+
);
|
|
@@ -152,6 +152,7 @@ export function buildGoogleInteractionsStreamTransform({
|
|
|
152
152
|
let serviceTier: string | undefined = headerServiceTier;
|
|
153
153
|
let finishStatus: GoogleInteractionsStatus | string | undefined;
|
|
154
154
|
let hasFunctionCall = false;
|
|
155
|
+
let hasCompletionEvent = false;
|
|
155
156
|
|
|
156
157
|
/*
|
|
157
158
|
* Per-index open step slots. The Interactions API frames concurrent steps
|
|
@@ -838,6 +839,7 @@ export function buildGoogleInteractionsStreamTransform({
|
|
|
838
839
|
}
|
|
839
840
|
|
|
840
841
|
case 'interaction.completed': {
|
|
842
|
+
hasCompletionEvent = true;
|
|
841
843
|
const event = value as Extract<
|
|
842
844
|
GoogleInteractionsEvent,
|
|
843
845
|
{ event_type: 'interaction.completed' }
|
|
@@ -893,12 +895,17 @@ export function buildGoogleInteractionsStreamTransform({
|
|
|
893
895
|
},
|
|
894
896
|
|
|
895
897
|
flush(controller) {
|
|
898
|
+
const isInterrupted =
|
|
899
|
+
!hasCompletionEvent &&
|
|
900
|
+
(finishStatus == null || finishStatus === 'in_progress');
|
|
896
901
|
const finishReason: LanguageModelV4FinishReason = {
|
|
897
|
-
unified:
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
+
unified: isInterrupted
|
|
903
|
+
? 'interrupted'
|
|
904
|
+
: mapGoogleInteractionsFinishReason({
|
|
905
|
+
status: finishStatus,
|
|
906
|
+
hasFunctionCall,
|
|
907
|
+
}),
|
|
908
|
+
raw: isInterrupted ? undefined : finishStatus,
|
|
902
909
|
};
|
|
903
910
|
|
|
904
911
|
const outputTokensByModality =
|