@ai-sdk/google 4.0.108 → 4.0.110
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 +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +238 -81
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +226 -68
- package/dist/internal/index.js.map +1 -1
- package/docs/15-google.mdx +23 -11
- package/package.json +3 -3
- package/src/convert-to-google-messages.ts +61 -7
- package/src/google-batch.ts +3 -4
- package/src/google-embedding-model.ts +2 -1
- package/src/google-error.ts +37 -0
- package/src/google-files.ts +7 -7
- package/src/google-language-model.ts +43 -92
- package/src/google-model-capabilities.ts +7 -40
- package/src/google-model-catalog.ts +319 -0
- package/src/google-provider.ts +15 -11
- package/src/interactions/cancel-google-interaction.ts +7 -2
- package/src/interactions/google-interactions-language-model.ts +8 -12
- package/src/interactions/poll-google-interactions.ts +4 -2
- package/src/interactions/stream-google-interactions.ts +4 -7
- package/src/realtime/google-realtime-model.ts +7 -3
- package/src/speech-translation/google-speech-translation-model.ts +7 -2
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ModelCapabilities,
|
|
3
|
+
ModelCapability,
|
|
4
|
+
ModelEntry,
|
|
5
|
+
ProviderOptionDefinition,
|
|
6
|
+
ProviderOptionDefinitions,
|
|
7
|
+
} from '@ai-sdk/provider';
|
|
8
|
+
import type { GoogleLanguageModelOptions } from './google-language-model-options';
|
|
9
|
+
|
|
10
|
+
const gemini1ModelPattern = /(^|[/.])gemini-1(?:[.-]|$)/i;
|
|
11
|
+
const gemini2ModelPattern = /(^|[/.])gemini-2(?:[.-]|$)/i;
|
|
12
|
+
const gemini25ModelPattern = /(^|[/.])gemini-2\.5(?:[.-]|$)/i;
|
|
13
|
+
const geminiModelPattern = /(^|[/.])gemini-/i;
|
|
14
|
+
|
|
15
|
+
type GoogleLanguageProviderOption = keyof GoogleLanguageModelOptions;
|
|
16
|
+
|
|
17
|
+
/** Options accepted under providerOptions.google (or googleVertex on Vertex). */
|
|
18
|
+
export const googleProviderOptions = {
|
|
19
|
+
language: {
|
|
20
|
+
responseModalities: { description: 'Response modalities to generate.' },
|
|
21
|
+
thinkingConfig: {
|
|
22
|
+
description: 'Thinking budget, level, and thought output.',
|
|
23
|
+
},
|
|
24
|
+
cachedContent: { description: 'Cached content to use as request context.' },
|
|
25
|
+
structuredOutputs: {
|
|
26
|
+
description: 'Whether to send the JSON response schema.',
|
|
27
|
+
},
|
|
28
|
+
safetySettings: { description: 'Safety settings for the request.' },
|
|
29
|
+
threshold: {
|
|
30
|
+
description: 'Default threshold for configurable safety categories.',
|
|
31
|
+
},
|
|
32
|
+
audioTimestamp: {
|
|
33
|
+
description: 'Enable timestamp understanding for audio.',
|
|
34
|
+
},
|
|
35
|
+
labels: { description: 'Billing labels. Vertex AI only.' },
|
|
36
|
+
mediaResolution: {
|
|
37
|
+
description: 'Resolution used to process media inputs.',
|
|
38
|
+
},
|
|
39
|
+
imageConfig: { description: 'Image generation configuration.' },
|
|
40
|
+
retrievalConfig: { description: 'Retrieval configuration for tools.' },
|
|
41
|
+
streamFunctionCallArguments: {
|
|
42
|
+
description: 'Stream function arguments. Vertex AI only.',
|
|
43
|
+
},
|
|
44
|
+
serviceTier: { description: 'Service tier. Gemini API only.' },
|
|
45
|
+
continuationToken: {
|
|
46
|
+
description: 'Resume a response using its continuation token.',
|
|
47
|
+
},
|
|
48
|
+
sharedRequestType: { description: 'Shared PayGo tier. Vertex AI only.' },
|
|
49
|
+
requestType: { description: 'Request routing type. Vertex AI only.' },
|
|
50
|
+
} satisfies Record<GoogleLanguageProviderOption, ProviderOptionDefinition>,
|
|
51
|
+
} as const satisfies ProviderOptionDefinitions;
|
|
52
|
+
|
|
53
|
+
type GoogleLanguageCapabilities = NonNullable<ModelCapabilities['language']> & {
|
|
54
|
+
tools: NonNullable<ModelCapabilities['language']>['tools'] & {
|
|
55
|
+
/** Existing request gate for Gemini 2 provider-defined tools. */
|
|
56
|
+
gemini2: boolean;
|
|
57
|
+
googleSearch: ModelCapability;
|
|
58
|
+
urlContext: ModelCapability;
|
|
59
|
+
fileSearch: boolean;
|
|
60
|
+
mixed: boolean;
|
|
61
|
+
functionResponseParts: boolean;
|
|
62
|
+
};
|
|
63
|
+
reasoning: NonNullable<ModelCapabilities['language']>['reasoning'] & {
|
|
64
|
+
minBudget: number;
|
|
65
|
+
maxBudget: number;
|
|
66
|
+
};
|
|
67
|
+
sampling: NonNullable<ModelCapabilities['language']>['sampling'] & {
|
|
68
|
+
topK: ModelCapability;
|
|
69
|
+
penalties: ModelCapability;
|
|
70
|
+
};
|
|
71
|
+
structuredOutput: {
|
|
72
|
+
withFunctionTools: boolean;
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
type GoogleLanguageRequestConfig = {
|
|
77
|
+
systemInstruction: 'system' | 'user';
|
|
78
|
+
thinkingFormat: 'level' | 'budget';
|
|
79
|
+
reasoningMaxOutputTokens: number;
|
|
80
|
+
jsonResponseTool: boolean;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export type GoogleLanguageModelEntry = ModelEntry<{
|
|
84
|
+
language: GoogleLanguageRequestConfig;
|
|
85
|
+
}> & {
|
|
86
|
+
capabilities: { language: GoogleLanguageCapabilities };
|
|
87
|
+
providerOptions: {
|
|
88
|
+
language: Record<GoogleLanguageProviderOption, ModelCapability>;
|
|
89
|
+
};
|
|
90
|
+
requestConfig: { language: GoogleLanguageRequestConfig };
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
type DocumentedCapabilities = {
|
|
94
|
+
image: boolean;
|
|
95
|
+
objectGeneration: boolean;
|
|
96
|
+
tools: boolean;
|
|
97
|
+
streaming: boolean;
|
|
98
|
+
googleSearch: boolean;
|
|
99
|
+
urlContext: boolean;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// Preserve the existing documentation's model set and per-model exceptions.
|
|
103
|
+
const standard = {
|
|
104
|
+
image: true,
|
|
105
|
+
objectGeneration: true,
|
|
106
|
+
tools: true,
|
|
107
|
+
streaming: true,
|
|
108
|
+
googleSearch: true,
|
|
109
|
+
urlContext: true,
|
|
110
|
+
} as const;
|
|
111
|
+
|
|
112
|
+
const documentedModels: Record<string, DocumentedCapabilities> = {
|
|
113
|
+
'gemini-nano-banana-2.1': {
|
|
114
|
+
image: true,
|
|
115
|
+
objectGeneration: false,
|
|
116
|
+
tools: false,
|
|
117
|
+
streaming: false,
|
|
118
|
+
googleSearch: true,
|
|
119
|
+
urlContext: false,
|
|
120
|
+
},
|
|
121
|
+
'gemini-4-argon': standard,
|
|
122
|
+
'gemini-3.8-flash': standard,
|
|
123
|
+
'gemini-3.7-flash': standard,
|
|
124
|
+
'gemini-3.6-flash': standard,
|
|
125
|
+
'gemini-3.5-flash': standard,
|
|
126
|
+
'gemini-3.5-flash-lite': standard,
|
|
127
|
+
'gemini-3.1-pro-preview': standard,
|
|
128
|
+
'gemini-3.1-flash-image-preview': standard,
|
|
129
|
+
'gemini-3.1-flash-lite-preview': standard,
|
|
130
|
+
'gemini-3-pro-preview': standard,
|
|
131
|
+
'gemini-3-pro-image-preview': standard,
|
|
132
|
+
'gemini-3-flash-preview': standard,
|
|
133
|
+
'gemini-2.5-pro': standard,
|
|
134
|
+
'gemini-2.5-flash': standard,
|
|
135
|
+
'gemini-2.5-flash-lite': standard,
|
|
136
|
+
'gemini-2.5-flash-lite-preview-06-17': standard,
|
|
137
|
+
'gemini-2.0-flash': standard,
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export const googleModelCatalog: Readonly<
|
|
141
|
+
Record<string, GoogleLanguageModelEntry>
|
|
142
|
+
> = Object.fromEntries(
|
|
143
|
+
Object.entries(documentedModels).map(([modelId, documented]) => [
|
|
144
|
+
modelId,
|
|
145
|
+
createGoogleLanguageModelEntry(modelId, documented),
|
|
146
|
+
]),
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
export function getGoogleLanguageModelEntry(
|
|
150
|
+
modelId: string,
|
|
151
|
+
): GoogleLanguageModelEntry {
|
|
152
|
+
return Object.prototype.hasOwnProperty.call(googleModelCatalog, modelId)
|
|
153
|
+
? googleModelCatalog[modelId]
|
|
154
|
+
: createGoogleLanguageModelEntry(modelId);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function createGoogleLanguageModelEntry(
|
|
158
|
+
modelId: string,
|
|
159
|
+
documented?: DocumentedCapabilities,
|
|
160
|
+
): GoogleLanguageModelEntry {
|
|
161
|
+
const runtime = resolveRuntimeDefinition(modelId);
|
|
162
|
+
const declared = documented != null;
|
|
163
|
+
const id = modelId.toLowerCase();
|
|
164
|
+
// Preserve the original case-sensitive exception in the thinking resolver.
|
|
165
|
+
const thinkingFormat =
|
|
166
|
+
runtime.usesGemini3Features && !modelId.includes('gemini-3-pro-image')
|
|
167
|
+
? 'level'
|
|
168
|
+
: 'budget';
|
|
169
|
+
const minLevel = getMinimumThinkingLevelForGemini3Model(modelId);
|
|
170
|
+
const language: GoogleLanguageCapabilities = {
|
|
171
|
+
inputs: { image: documented?.image ?? 'unknown', audio: 'unknown' },
|
|
172
|
+
objectGeneration: documented?.objectGeneration ?? 'unknown',
|
|
173
|
+
tools: {
|
|
174
|
+
usage: documented?.tools ?? 'unknown',
|
|
175
|
+
streaming: documented?.streaming ?? 'unknown',
|
|
176
|
+
gemini2: runtime.supportsGemini2Tools,
|
|
177
|
+
googleSearch: documented?.googleSearch ?? 'unknown',
|
|
178
|
+
urlContext: documented?.urlContext ?? 'unknown',
|
|
179
|
+
fileSearch: runtime.supportsFileSearch,
|
|
180
|
+
mixed: runtime.usesGemini3Features,
|
|
181
|
+
functionResponseParts: runtime.usesGemini3Features,
|
|
182
|
+
},
|
|
183
|
+
reasoning: {
|
|
184
|
+
support: 'unknown',
|
|
185
|
+
efforts:
|
|
186
|
+
thinkingFormat === 'level'
|
|
187
|
+
? [
|
|
188
|
+
...(minLevel === 'minimal' ? ['minimal'] : []),
|
|
189
|
+
'low',
|
|
190
|
+
'medium',
|
|
191
|
+
'high',
|
|
192
|
+
]
|
|
193
|
+
: undefined,
|
|
194
|
+
minBudget: id.includes('2.5-pro') ? 128 : 0,
|
|
195
|
+
maxBudget:
|
|
196
|
+
id.includes('2.5-pro') || id.includes('gemini-3-pro-image')
|
|
197
|
+
? 32768
|
|
198
|
+
: 24576,
|
|
199
|
+
},
|
|
200
|
+
sampling: {
|
|
201
|
+
temperature: 'unknown',
|
|
202
|
+
topP: 'unknown',
|
|
203
|
+
topK: 'unknown',
|
|
204
|
+
logprobs: false,
|
|
205
|
+
penalties: gemini25ModelPattern.test(modelId)
|
|
206
|
+
? { condition: 'Only supported on the Vertex AI API.' }
|
|
207
|
+
: true,
|
|
208
|
+
},
|
|
209
|
+
structuredOutput: {
|
|
210
|
+
withFunctionTools: runtime.usesGemini3Features,
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
return {
|
|
215
|
+
capabilities: { language },
|
|
216
|
+
providerOptions: {
|
|
217
|
+
language: declareProviderOptions(declared ? true : 'unknown', {
|
|
218
|
+
labels: { condition: 'Only supported on the Vertex AI API.' },
|
|
219
|
+
sharedRequestType: {
|
|
220
|
+
condition: 'Only supported on the Vertex AI API.',
|
|
221
|
+
},
|
|
222
|
+
requestType: { condition: 'Only supported on the Vertex AI API.' },
|
|
223
|
+
serviceTier: { condition: 'Only supported on the Gemini API.' },
|
|
224
|
+
streamFunctionCallArguments: {
|
|
225
|
+
condition:
|
|
226
|
+
'Only supported for streaming requests on the Vertex AI API with Gemini 3 or newer.',
|
|
227
|
+
},
|
|
228
|
+
}),
|
|
229
|
+
},
|
|
230
|
+
requestConfig: {
|
|
231
|
+
language: {
|
|
232
|
+
systemInstruction: id.startsWith('gemma-') ? 'user' : 'system',
|
|
233
|
+
thinkingFormat,
|
|
234
|
+
reasoningMaxOutputTokens: 65536,
|
|
235
|
+
jsonResponseTool: /(^|\/)gemini-/i.test(modelId),
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function declareProviderOptions(
|
|
242
|
+
support: ModelCapability,
|
|
243
|
+
exceptions: Partial<Record<GoogleLanguageProviderOption, ModelCapability>>,
|
|
244
|
+
): Record<GoogleLanguageProviderOption, ModelCapability> {
|
|
245
|
+
return Object.fromEntries(
|
|
246
|
+
(
|
|
247
|
+
Object.keys(
|
|
248
|
+
googleProviderOptions.language,
|
|
249
|
+
) as GoogleLanguageProviderOption[]
|
|
250
|
+
).map(option => [option, exceptions[option] ?? support]),
|
|
251
|
+
) as Record<GoogleLanguageProviderOption, ModelCapability>;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function isKnownPreGemini2Model(modelId: string): boolean {
|
|
255
|
+
return (
|
|
256
|
+
gemini1ModelPattern.test(modelId) ||
|
|
257
|
+
/(^|[/.])gemini-pro(?:-vision)?$/i.test(modelId) ||
|
|
258
|
+
/(^|[/.])gemini-robotics-er-1\.5(?:[.-]|$)/i.test(modelId)
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Classifies Gemini capabilities by excluding known older generations.
|
|
264
|
+
*
|
|
265
|
+
* Google model IDs are open-ended, so unrecognized Gemini IDs and aliases
|
|
266
|
+
* intentionally inherit the newest supported behavior. Add exceptions here
|
|
267
|
+
* only when a model is known to require a legacy request shape.
|
|
268
|
+
*/
|
|
269
|
+
function resolveRuntimeDefinition(modelId: string) {
|
|
270
|
+
const isGeminiModel = geminiModelPattern.test(modelId);
|
|
271
|
+
const isGemini2Model = gemini2ModelPattern.test(modelId);
|
|
272
|
+
const isKnownPreGemini2 = isKnownPreGemini2Model(modelId);
|
|
273
|
+
const isKnownOlderModel = isKnownPreGemini2 || isGemini2Model;
|
|
274
|
+
const usesGemini3Features = isGeminiModel && !isKnownOlderModel;
|
|
275
|
+
|
|
276
|
+
return {
|
|
277
|
+
supportsGemini2Tools:
|
|
278
|
+
(isGeminiModel && !isKnownPreGemini2) ||
|
|
279
|
+
modelId.toLowerCase().includes('nano-banana'),
|
|
280
|
+
supportsFileSearch:
|
|
281
|
+
gemini25ModelPattern.test(modelId) || usesGemini3Features,
|
|
282
|
+
usesGemini3Features,
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function getMinimumThinkingLevelForGemini3Model(
|
|
287
|
+
modelId: string,
|
|
288
|
+
): 'minimal' | 'low' {
|
|
289
|
+
const modelName = /(?:^|[/.])(gemini-[^/]*)$/i
|
|
290
|
+
.exec(modelId)?.[1]
|
|
291
|
+
.toLowerCase();
|
|
292
|
+
|
|
293
|
+
if (modelName === 'gemini-flash-latest') {
|
|
294
|
+
return 'low';
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const proVersionMatch = /^gemini-(\d+)(?:\.\d+)?-pro(?:$|-)/.exec(
|
|
298
|
+
modelName ?? '',
|
|
299
|
+
);
|
|
300
|
+
|
|
301
|
+
if (Number(proVersionMatch?.[1]) >= 3) {
|
|
302
|
+
return 'low';
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const versionMatch = /^gemini-(\d+)\.(\d+)-flash(?:$|-(?!lite(?:-|$)))/.exec(
|
|
306
|
+
modelName ?? '',
|
|
307
|
+
);
|
|
308
|
+
|
|
309
|
+
if (versionMatch == null) {
|
|
310
|
+
return 'minimal';
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const majorVersion = Number(versionMatch[1]);
|
|
314
|
+
const minorVersion = Number(versionMatch[2]);
|
|
315
|
+
|
|
316
|
+
return majorVersion > 3 || (majorVersion === 3 && minorVersion >= 7)
|
|
317
|
+
? 'low'
|
|
318
|
+
: 'minimal';
|
|
319
|
+
}
|
package/src/google-provider.ts
CHANGED
|
@@ -14,6 +14,8 @@ import type {
|
|
|
14
14
|
TranscriptionModelV4,
|
|
15
15
|
} from '@ai-sdk/provider';
|
|
16
16
|
import {
|
|
17
|
+
resolveWith,
|
|
18
|
+
type Resolvable,
|
|
17
19
|
generateId,
|
|
18
20
|
loadApiKey,
|
|
19
21
|
withoutTrailingSlash,
|
|
@@ -194,7 +196,7 @@ export interface GoogleProviderSettings {
|
|
|
194
196
|
* API key that is being send using the `x-goog-api-key` header.
|
|
195
197
|
* It defaults to the `GOOGLE_GENERATIVE_AI_API_KEY` environment variable.
|
|
196
198
|
*/
|
|
197
|
-
apiKey?: string
|
|
199
|
+
apiKey?: Resolvable<string>;
|
|
198
200
|
|
|
199
201
|
/**
|
|
200
202
|
* Custom headers to include in the requests.
|
|
@@ -267,16 +269,18 @@ export function createGoogle(
|
|
|
267
269
|
const providerName = options.name ?? 'google.generative-ai';
|
|
268
270
|
|
|
269
271
|
const getHeaders = () =>
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
272
|
+
resolveWith(options.apiKey, apiKey =>
|
|
273
|
+
withUserAgentSuffix(
|
|
274
|
+
{
|
|
275
|
+
'x-goog-api-key': loadApiKey({
|
|
276
|
+
apiKey,
|
|
277
|
+
environmentVariableName: 'GOOGLE_GENERATIVE_AI_API_KEY',
|
|
278
|
+
description: 'Google Generative AI',
|
|
279
|
+
}),
|
|
280
|
+
...options.headers,
|
|
281
|
+
},
|
|
282
|
+
`ai-sdk-google/${VERSION}`,
|
|
283
|
+
),
|
|
280
284
|
);
|
|
281
285
|
|
|
282
286
|
const getSupportedUrls = (
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
+
resolve,
|
|
3
|
+
type Resolvable,
|
|
2
4
|
combineHeaders,
|
|
3
5
|
getRuntimeEnvironmentUserAgent,
|
|
4
6
|
withUserAgentSuffix,
|
|
@@ -24,7 +26,7 @@ export async function cancelGoogleInteraction({
|
|
|
24
26
|
}: {
|
|
25
27
|
baseURL: string;
|
|
26
28
|
interactionId: string | null | undefined;
|
|
27
|
-
headers: Record<string, string | undefined
|
|
29
|
+
headers: Resolvable<Record<string, string | undefined>>;
|
|
28
30
|
fetch?: FetchFunction;
|
|
29
31
|
}): Promise<void> {
|
|
30
32
|
if (interactionId == null || interactionId.length === 0) {
|
|
@@ -37,7 +39,10 @@ export async function cancelGoogleInteraction({
|
|
|
37
39
|
const response = await fetch(url, {
|
|
38
40
|
method: 'POST',
|
|
39
41
|
headers: withUserAgentSuffix(
|
|
40
|
-
combineHeaders(
|
|
42
|
+
combineHeaders(
|
|
43
|
+
{ 'Content-Type': 'application/json' },
|
|
44
|
+
await resolve(headers),
|
|
45
|
+
),
|
|
41
46
|
getRuntimeEnvironmentUserAgent(),
|
|
42
47
|
),
|
|
43
48
|
body: '{}',
|
|
@@ -487,14 +487,12 @@ export class GoogleInteractionsLanguageModel implements LanguageModelV4 {
|
|
|
487
487
|
|
|
488
488
|
const url = `${this.config.baseURL}/interactions`;
|
|
489
489
|
|
|
490
|
-
const mergedHeaders =
|
|
491
|
-
|
|
492
|
-
options.headers,
|
|
493
|
-
);
|
|
490
|
+
const mergedHeaders = async () =>
|
|
491
|
+
combineHeaders(await resolve(this.config.headers), options.headers);
|
|
494
492
|
|
|
495
493
|
const postResult = await postJsonToApi({
|
|
496
494
|
url,
|
|
497
|
-
headers: mergedHeaders,
|
|
495
|
+
headers: await resolve(mergedHeaders),
|
|
498
496
|
body: args,
|
|
499
497
|
failedResponseHandler: googleFailedResponseHandler,
|
|
500
498
|
successfulResponseHandler: createJsonResponseHandler(
|
|
@@ -620,10 +618,8 @@ export class GoogleInteractionsLanguageModel implements LanguageModelV4 {
|
|
|
620
618
|
|
|
621
619
|
const url = `${this.config.baseURL}/interactions`;
|
|
622
620
|
|
|
623
|
-
const mergedHeaders =
|
|
624
|
-
|
|
625
|
-
options.headers,
|
|
626
|
-
);
|
|
621
|
+
const mergedHeaders = async () =>
|
|
622
|
+
combineHeaders(await resolve(this.config.headers), options.headers);
|
|
627
623
|
|
|
628
624
|
/*
|
|
629
625
|
* `background: true` is incompatible with `stream: true` on POST. Drive
|
|
@@ -647,7 +643,7 @@ export class GoogleInteractionsLanguageModel implements LanguageModelV4 {
|
|
|
647
643
|
|
|
648
644
|
const { responseHeaders, value: response } = await postJsonToApi({
|
|
649
645
|
url,
|
|
650
|
-
headers: mergedHeaders,
|
|
646
|
+
headers: await resolve(mergedHeaders),
|
|
651
647
|
body,
|
|
652
648
|
failedResponseHandler: googleFailedResponseHandler,
|
|
653
649
|
successfulResponseHandler: createEventSourceResponseHandler(
|
|
@@ -709,13 +705,13 @@ export class GoogleInteractionsLanguageModel implements LanguageModelV4 {
|
|
|
709
705
|
args: GoogleInteractionsRequestBody;
|
|
710
706
|
warnings: Array<SharedV4Warning>;
|
|
711
707
|
url: string;
|
|
712
|
-
mergedHeaders: Record<string, string | undefined
|
|
708
|
+
mergedHeaders: Resolvable<Record<string, string | undefined>>;
|
|
713
709
|
options: LanguageModelV4CallOptions;
|
|
714
710
|
pollingTimeoutMs: number | undefined;
|
|
715
711
|
}): Promise<LanguageModelV4StreamResult> {
|
|
716
712
|
const postResult = await postJsonToApi({
|
|
717
713
|
url,
|
|
718
|
-
headers: mergedHeaders,
|
|
714
|
+
headers: await resolve(mergedHeaders),
|
|
719
715
|
body: args,
|
|
720
716
|
failedResponseHandler: googleFailedResponseHandler,
|
|
721
717
|
successfulResponseHandler: createJsonResponseHandler(
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
+
resolve,
|
|
3
|
+
type Resolvable,
|
|
2
4
|
createJsonResponseHandler,
|
|
3
5
|
delay,
|
|
4
6
|
getFromApi,
|
|
@@ -57,7 +59,7 @@ export async function pollGoogleInteractionUntilTerminal({
|
|
|
57
59
|
}: {
|
|
58
60
|
baseURL: string;
|
|
59
61
|
interactionId: string | null | undefined;
|
|
60
|
-
headers: Record<string, string | undefined
|
|
62
|
+
headers: Resolvable<Record<string, string | undefined>>;
|
|
61
63
|
fetch?: FetchFunction;
|
|
62
64
|
abortSignal?: AbortSignal;
|
|
63
65
|
initialDelayMs?: number;
|
|
@@ -106,7 +108,7 @@ export async function pollGoogleInteractionUntilTerminal({
|
|
|
106
108
|
} = await getFromApi({
|
|
107
109
|
url,
|
|
108
110
|
validateUrl: false,
|
|
109
|
-
headers,
|
|
111
|
+
headers: await resolve(headers),
|
|
110
112
|
failedResponseHandler: googleFailedResponseHandler,
|
|
111
113
|
successfulResponseHandler: createJsonResponseHandler(
|
|
112
114
|
googleInteractionsResponseSchema,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
+
resolve,
|
|
3
|
+
type Resolvable,
|
|
2
4
|
createEventSourceResponseHandler,
|
|
3
5
|
delay,
|
|
4
6
|
getFromApi,
|
|
@@ -43,7 +45,7 @@ export function streamGoogleInteractionEvents({
|
|
|
43
45
|
}: {
|
|
44
46
|
baseURL: string;
|
|
45
47
|
interactionId: string;
|
|
46
|
-
headers: Record<string, string | undefined
|
|
48
|
+
headers: Resolvable<Record<string, string | undefined>>;
|
|
47
49
|
fetch?: FetchFunction;
|
|
48
50
|
abortSignal?: AbortSignal;
|
|
49
51
|
maxRetries?: number;
|
|
@@ -55,11 +57,6 @@ export function streamGoogleInteractionEvents({
|
|
|
55
57
|
);
|
|
56
58
|
}
|
|
57
59
|
|
|
58
|
-
const eventSourceHeaders = {
|
|
59
|
-
...headers,
|
|
60
|
-
accept: 'text/event-stream',
|
|
61
|
-
};
|
|
62
|
-
|
|
63
60
|
let lastEventId: string | undefined;
|
|
64
61
|
let complete = false;
|
|
65
62
|
let attempt = 0;
|
|
@@ -99,7 +96,7 @@ export function streamGoogleInteractionEvents({
|
|
|
99
96
|
const { value: stream } = await getFromApi({
|
|
100
97
|
url: buildUrl(),
|
|
101
98
|
validateUrl: false,
|
|
102
|
-
headers:
|
|
99
|
+
headers: { ...(await resolve(headers)), accept: 'text/event-stream' },
|
|
103
100
|
failedResponseHandler: googleFailedResponseHandler,
|
|
104
101
|
successfulResponseHandler: createEventSourceResponseHandler(
|
|
105
102
|
googleInteractionsEventSchema,
|
|
@@ -6,7 +6,11 @@ import type {
|
|
|
6
6
|
Experimental_RealtimeModelV4ServerEvent as RealtimeModelV4ServerEvent,
|
|
7
7
|
Experimental_RealtimeModelV4SessionConfig as RealtimeModelV4SessionConfig,
|
|
8
8
|
} from '@ai-sdk/provider';
|
|
9
|
-
import
|
|
9
|
+
import {
|
|
10
|
+
resolve,
|
|
11
|
+
type Resolvable,
|
|
12
|
+
type FetchFunction,
|
|
13
|
+
} from '@ai-sdk/provider-utils';
|
|
10
14
|
import {
|
|
11
15
|
getRealtimeBaseURL,
|
|
12
16
|
getRealtimeWebSocketURL,
|
|
@@ -32,7 +36,7 @@ function getWebSocketURL(baseURL: string): string {
|
|
|
32
36
|
export type GoogleRealtimeModelConfig = {
|
|
33
37
|
provider: string;
|
|
34
38
|
baseURL: string;
|
|
35
|
-
headers:
|
|
39
|
+
headers: Resolvable<Record<string, string | undefined>>;
|
|
36
40
|
fetch?: FetchFunction;
|
|
37
41
|
};
|
|
38
42
|
|
|
@@ -54,7 +58,7 @@ export class GoogleRealtimeModel implements RealtimeModelV4 {
|
|
|
54
58
|
options: RealtimeModelV4ClientSecretOptions,
|
|
55
59
|
): Promise<RealtimeModelV4ClientSecretResult> {
|
|
56
60
|
const fetchFn = this.config.fetch ?? fetch;
|
|
57
|
-
const headers = this.config.headers
|
|
61
|
+
const headers = await resolve(this.config.headers);
|
|
58
62
|
const apiKey = headers['x-goog-api-key'];
|
|
59
63
|
|
|
60
64
|
if (!apiKey) {
|
|
@@ -7,6 +7,8 @@ import {
|
|
|
7
7
|
type SharedV4Warning,
|
|
8
8
|
} from '@ai-sdk/provider';
|
|
9
9
|
import {
|
|
10
|
+
resolve,
|
|
11
|
+
type Resolvable,
|
|
10
12
|
connectToWebSocket,
|
|
11
13
|
combineHeaders,
|
|
12
14
|
convertBase64ToUint8Array,
|
|
@@ -74,7 +76,7 @@ type GoogleLiveServerMessage = {
|
|
|
74
76
|
export type GoogleSpeechTranslationModelConfig = {
|
|
75
77
|
provider: string;
|
|
76
78
|
baseURL: string;
|
|
77
|
-
headers:
|
|
79
|
+
headers: Resolvable<Record<string, string | undefined>>;
|
|
78
80
|
webSocket?: WebSocketConstructor;
|
|
79
81
|
_internal?: {
|
|
80
82
|
currentDate?: () => Date;
|
|
@@ -152,7 +154,10 @@ export class GoogleSpeechTranslationModel implements SpeechTranslationModelV4 {
|
|
|
152
154
|
});
|
|
153
155
|
}
|
|
154
156
|
|
|
155
|
-
const headers = combineHeaders(
|
|
157
|
+
const headers = combineHeaders(
|
|
158
|
+
await resolve(this.config.headers),
|
|
159
|
+
options.headers,
|
|
160
|
+
);
|
|
156
161
|
// last case-variant wins: combineHeaders keeps case-distinct keys and
|
|
157
162
|
// spreads per-call headers after configuration headers
|
|
158
163
|
let apiKey: string | undefined;
|