@ai-sdk/google 4.0.113 → 4.0.116
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 +31 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +45 -17
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +2 -1
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +44 -16
- package/dist/internal/index.js.map +1 -1
- package/docs/15-google.mdx +8 -0
- package/package.json +3 -3
- package/src/google-json-accumulator.ts +49 -0
- package/src/google-language-model.ts +25 -20
- package/src/google-prepare-tools.ts +7 -0
- package/src/interactions/google-interactions-language-model-options.ts +2 -0
- package/src/interactions/google-interactions-language-model.ts +1 -0
- package/src/interactions/google-interactions-prompt.ts +1 -0
package/docs/15-google.mdx
CHANGED
|
@@ -1594,6 +1594,14 @@ await generateText({
|
|
|
1594
1594
|
|
|
1595
1595
|
The following optional provider options are available:
|
|
1596
1596
|
|
|
1597
|
+
- **labels** _Record<string, string>_
|
|
1598
|
+
|
|
1599
|
+
User-defined metadata sent in the top-level `labels` field of the Interactions
|
|
1600
|
+
request. For example, set `{ safety_identifier: 'opaque_user_123' }` to attach
|
|
1601
|
+
an opaque end-user identifier. Other labels are preserved unchanged.
|
|
1602
|
+
Vertex AI Interactions models also read labels from `providerOptions.google`,
|
|
1603
|
+
not `providerOptions.googleVertex` or `providerOptions.vertex`.
|
|
1604
|
+
|
|
1597
1605
|
- **previousInteractionId** _string_
|
|
1598
1606
|
|
|
1599
1607
|
Server-side interaction id from a prior turn. When set, the server pulls
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/google",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.116",
|
|
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.37",
|
|
39
|
+
"@ai-sdk/provider-utils": "5.0.78"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@ai-sdk/test-server": "2.0.4",
|
|
@@ -61,6 +61,7 @@ export class GoogleJSONAccumulator {
|
|
|
61
61
|
if (!rawPath || rawPath === '$') continue;
|
|
62
62
|
|
|
63
63
|
const segments = parsePath(rawPath);
|
|
64
|
+
if (!normalizeAndCheckIndexes(this.accumulatedArgs, segments)) continue;
|
|
64
65
|
|
|
65
66
|
const existingValue = getNestedValue(this.accumulatedArgs, segments);
|
|
66
67
|
const isStringContinuation =
|
|
@@ -386,6 +387,54 @@ function getNestedValue(
|
|
|
386
387
|
return current;
|
|
387
388
|
}
|
|
388
389
|
|
|
390
|
+
/**
|
|
391
|
+
* Normalizes dotted array indexes in place and checks that every array index
|
|
392
|
+
* is an existing element or the next one. Arrays are streamed in order, and a
|
|
393
|
+
* sparse index would make `finalize()` serialize one `null` per hole, so a tiny
|
|
394
|
+
* response could allocate without bound.
|
|
395
|
+
* A missing or `null` parent is replaced with a new array, so it starts at 0.
|
|
396
|
+
*
|
|
397
|
+
* Input: ({items:["a"]}, ["items",1]) or ({items:["a"]}, ["items",5])
|
|
398
|
+
* Output: true or false
|
|
399
|
+
*/
|
|
400
|
+
function normalizeAndCheckIndexes(
|
|
401
|
+
obj: Record<string, unknown>,
|
|
402
|
+
segments: Array<string | number>,
|
|
403
|
+
): boolean {
|
|
404
|
+
let current: unknown = obj;
|
|
405
|
+
for (let i = 0; i < segments.length; i++) {
|
|
406
|
+
let pathSegment = segments[i];
|
|
407
|
+
if (Array.isArray(current) && typeof pathSegment === 'string') {
|
|
408
|
+
const index = Number(pathSegment);
|
|
409
|
+
// Only canonical array-index keys affect length. Keep object keys as strings.
|
|
410
|
+
if (
|
|
411
|
+
Number.isInteger(index) &&
|
|
412
|
+
index >= 0 &&
|
|
413
|
+
index < 2 ** 32 - 1 &&
|
|
414
|
+
String(index) === pathSegment
|
|
415
|
+
) {
|
|
416
|
+
pathSegment = index;
|
|
417
|
+
segments[i] = index;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
if (typeof pathSegment === 'number') {
|
|
421
|
+
const length = Array.isArray(current)
|
|
422
|
+
? current.length
|
|
423
|
+
: current == null
|
|
424
|
+
? 0
|
|
425
|
+
: undefined;
|
|
426
|
+
if (length !== undefined && pathSegment > length) return false;
|
|
427
|
+
}
|
|
428
|
+
current =
|
|
429
|
+
current != null &&
|
|
430
|
+
typeof current === 'object' &&
|
|
431
|
+
hasOwnProperty(current as Record<string | number, unknown>, pathSegment)
|
|
432
|
+
? (current as Record<string | number, unknown>)[pathSegment]
|
|
433
|
+
: undefined;
|
|
434
|
+
}
|
|
435
|
+
return true;
|
|
436
|
+
}
|
|
437
|
+
|
|
389
438
|
/**
|
|
390
439
|
* Sets a value at a nested path, creating intermediate objects or arrays as needed.
|
|
391
440
|
*
|
|
@@ -24,9 +24,9 @@ import {
|
|
|
24
24
|
lazySchema,
|
|
25
25
|
mapReasoningToProviderBudget,
|
|
26
26
|
mapReasoningToProviderEffort,
|
|
27
|
-
parseProviderOptions,
|
|
28
27
|
postJsonToApi,
|
|
29
28
|
resolve,
|
|
29
|
+
resolveProviderOptions,
|
|
30
30
|
serializeModelOptions,
|
|
31
31
|
WORKFLOW_SERIALIZE,
|
|
32
32
|
WORKFLOW_DESERIALIZE,
|
|
@@ -179,25 +179,15 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
179
179
|
? (['googleVertex', 'vertex'] as const)
|
|
180
180
|
: (['google'] as const);
|
|
181
181
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
182
|
+
// The first present namespace wins as a whole. A Vertex provider also
|
|
183
|
+
// falls back to the `google` key (e.g. via the AI Gateway).
|
|
184
|
+
const { options: googleOptions } =
|
|
185
|
+
await resolveProviderOptions<GoogleLanguageModelOptions>({
|
|
186
186
|
providerOptions,
|
|
187
|
+
namespaces: [...providerOptionsNames, 'google'],
|
|
188
|
+
resolution: 'first',
|
|
187
189
|
schema: googleLanguageModelOptions,
|
|
188
190
|
});
|
|
189
|
-
if (googleOptions != null) break;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// Cross-namespace fallback: a Vertex provider may receive options under
|
|
193
|
-
// the `google` key (e.g. via the AI Gateway).
|
|
194
|
-
if (googleOptions == null && !providerOptionsNames.includes('google')) {
|
|
195
|
-
googleOptions = await parseProviderOptions({
|
|
196
|
-
provider: 'google',
|
|
197
|
-
providerOptions,
|
|
198
|
-
schema: googleLanguageModelOptions,
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
191
|
|
|
202
192
|
// Add warning if Vertex rag tools are used with a non-Vertex Google provider
|
|
203
193
|
const isVertexProvider = config.provider.startsWith('google.vertex.');
|
|
@@ -468,7 +458,13 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
468
458
|
options: LanguageModelV4CallOptions,
|
|
469
459
|
{ isStreaming = false }: { isStreaming?: boolean } = {},
|
|
470
460
|
) {
|
|
471
|
-
const { responseFormat,
|
|
461
|
+
const { responseFormat, toolChoice } = options;
|
|
462
|
+
// Enforce the caller's tool choice before the JSON response fallback can
|
|
463
|
+
// replace it with a forced call to the synthetic response tool.
|
|
464
|
+
const tools =
|
|
465
|
+
toolChoice?.type === 'none'
|
|
466
|
+
? options.tools?.filter(tool => tool.type === 'function')
|
|
467
|
+
: options.tools;
|
|
472
468
|
const entry = getGoogleLanguageModelEntry(this.modelId);
|
|
473
469
|
const { structuredOutput } = entry.capabilities.language;
|
|
474
470
|
let jsonResponseTool: LanguageModelV4FunctionTool | undefined;
|
|
@@ -522,6 +518,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
522
518
|
static convertGenerateContentResponse({
|
|
523
519
|
config,
|
|
524
520
|
response,
|
|
521
|
+
responseHeaders,
|
|
525
522
|
warnings,
|
|
526
523
|
providerOptionsNames,
|
|
527
524
|
toolNameMapping,
|
|
@@ -531,6 +528,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
531
528
|
}: {
|
|
532
529
|
config: GoogleLanguageModelConfig;
|
|
533
530
|
response: InferSchema<typeof responseSchema>;
|
|
531
|
+
responseHeaders?: Record<string, string>;
|
|
534
532
|
warnings: SharedV4Warning[];
|
|
535
533
|
providerOptionsNames: readonly string[];
|
|
536
534
|
toolNameMapping?: ReturnType<typeof createToolNameMapping>;
|
|
@@ -734,7 +732,10 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
734
732
|
safetyRatings: candidate?.safetyRatings ?? null,
|
|
735
733
|
usageMetadata: usageMetadata ?? null,
|
|
736
734
|
finishMessage: candidate?.finishMessage ?? null,
|
|
737
|
-
serviceTier:
|
|
735
|
+
serviceTier:
|
|
736
|
+
usageMetadata?.serviceTier ??
|
|
737
|
+
responseHeaders?.['x-gemini-service-tier'] ??
|
|
738
|
+
null,
|
|
738
739
|
...(candidate?.continuationToken != null
|
|
739
740
|
? { continuationToken: candidate.continuationToken }
|
|
740
741
|
: {}),
|
|
@@ -836,6 +837,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
836
837
|
const lastResult = GoogleLanguageModel.convertGenerateContentResponse({
|
|
837
838
|
config: this.config,
|
|
838
839
|
response: { ...response, usageMetadata },
|
|
840
|
+
responseHeaders,
|
|
839
841
|
warnings,
|
|
840
842
|
providerOptionsNames,
|
|
841
843
|
toolNameMapping,
|
|
@@ -1595,7 +1597,10 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
1595
1597
|
safetyRatings: lastSafetyRatings,
|
|
1596
1598
|
usageMetadata: usage ?? null,
|
|
1597
1599
|
finishMessage: lastFinishMessage,
|
|
1598
|
-
serviceTier:
|
|
1600
|
+
serviceTier:
|
|
1601
|
+
usage?.serviceTier ??
|
|
1602
|
+
responseHeaders?.['x-gemini-service-tier'] ??
|
|
1603
|
+
null,
|
|
1599
1604
|
// Only surface the token when the response stopped early
|
|
1600
1605
|
// (budget used up, or continuing failed), not for the
|
|
1601
1606
|
// checkpoint tokens of a stream that finished normally.
|
|
@@ -48,6 +48,13 @@ export function prepareTools({
|
|
|
48
48
|
};
|
|
49
49
|
toolWarnings: SharedV4Warning[];
|
|
50
50
|
} {
|
|
51
|
+
// NONE only disables function calling in the Google API. Provider tools
|
|
52
|
+
// must be omitted so they cannot execute server-side. Keep function
|
|
53
|
+
// declarations for conversation history containing function calls.
|
|
54
|
+
if (toolChoice?.type === 'none') {
|
|
55
|
+
tools = tools?.filter(tool => tool.type === 'function');
|
|
56
|
+
}
|
|
57
|
+
|
|
51
58
|
// when the tools array is empty, change it to undefined to prevent errors:
|
|
52
59
|
tools = tools?.length ? tools : undefined;
|
|
53
60
|
|
|
@@ -76,6 +76,8 @@ export type GoogleInteractionsVideoOptions = {
|
|
|
76
76
|
export const googleInteractionsLanguageModelOptions = lazySchema(() =>
|
|
77
77
|
zodSchema(
|
|
78
78
|
z.object({
|
|
79
|
+
/** User-defined request metadata, including `safety_identifier`. */
|
|
80
|
+
labels: z.record(z.string(), z.string()).nullish(),
|
|
79
81
|
previousInteractionId: z.string().nullish(),
|
|
80
82
|
store: z.boolean().nullish(),
|
|
81
83
|
|
|
@@ -447,6 +447,7 @@ export class GoogleInteractionsLanguageModel implements LanguageModelV4 {
|
|
|
447
447
|
const args: GoogleInteractionsRequestBody = pruneUndefined({
|
|
448
448
|
...(isAgent ? { agent: this.agent } : { model: this.modelId }),
|
|
449
449
|
input,
|
|
450
|
+
labels: googleOptions?.labels ?? undefined,
|
|
450
451
|
system_instruction: systemInstruction,
|
|
451
452
|
tools: toolsForBody,
|
|
452
453
|
response_format:
|
|
@@ -577,6 +577,7 @@ export type GoogleInteractionsRequestBody = {
|
|
|
577
577
|
model?: string;
|
|
578
578
|
agent?: string;
|
|
579
579
|
input: GoogleInteractionsInput;
|
|
580
|
+
labels?: Record<string, string>;
|
|
580
581
|
system_instruction?: string;
|
|
581
582
|
tools?: Array<GoogleInteractionsTool>;
|
|
582
583
|
response_format?: Array<GoogleInteractionsResponseFormatEntry>;
|