@ai-sdk/google 4.0.98 → 4.0.100

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.
@@ -395,6 +395,14 @@ and long coding or agentic tasks.
395
395
  - Complex requests can run for several minutes. Make sure your HTTP client
396
396
  allows read timeouts of at least 15 to 20 minutes.
397
397
 
398
+ **Grounding across requests.** When a response is continued automatically,
399
+ `providerMetadata.google.groundingMetadataPerRequest` contains the grounding
400
+ metadata from each request, in order. An entry is `null` if that request did
401
+ not return grounding metadata. This preserves earlier Search results even if
402
+ the final request returns none, and keeps citation indices scoped to their
403
+ original request. The existing `groundingMetadata` field keeps its current
404
+ behavior; use the per-request array when inspecting a continued response.
405
+
398
406
  **Usage across requests.** Each continued request re-sends the prompt plus all
399
407
  output so far as input, so its prompt token count includes everything
400
408
  generated before it. `usage` is the sum of all requests, which matches what
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/google",
3
- "version": "4.0.98",
3
+ "version": "4.0.100",
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.28",
39
- "@ai-sdk/provider-utils": "5.0.61"
38
+ "@ai-sdk/provider": "4.0.30",
39
+ "@ai-sdk/provider-utils": "5.0.63"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@ai-sdk/test-server": "2.0.4",
@@ -6,15 +6,18 @@ import {
6
6
  } from '@ai-sdk/provider-utils';
7
7
  import { z } from 'zod/v4';
8
8
 
9
+ export const getGoogleErrorSchema = () =>
10
+ z.object({
11
+ code: z.number().nullable(),
12
+ message: z.string(),
13
+ status: z.string(),
14
+ details: z.array(z.unknown()).nullish(),
15
+ });
16
+
9
17
  const googleErrorDataSchema = lazySchema(() =>
10
18
  zodSchema(
11
19
  z.object({
12
- error: z.object({
13
- code: z.number().nullable(),
14
- message: z.string(),
15
- status: z.string(),
16
- details: z.array(z.unknown()).nullish(),
17
- }),
20
+ error: getGoogleErrorSchema(),
18
21
  }),
19
22
  ),
20
23
  );
@@ -18,6 +18,7 @@ import {
18
18
  createToolNameMapping,
19
19
  createEventSourceResponseHandler,
20
20
  createJsonResponseHandler,
21
+ createProviderStreamError,
21
22
  generateId,
22
23
  isCustomReasoning,
23
24
  lazySchema,
@@ -45,7 +46,10 @@ import {
45
46
  import { convertToGoogleMessages } from './convert-to-google-messages';
46
47
  import { downloadToolResultFiles } from './download-tool-result-files';
47
48
  import { getModelPath } from './get-model-path';
48
- import { googleFailedResponseHandler } from './google-error';
49
+ import {
50
+ getGoogleErrorSchema,
51
+ googleFailedResponseHandler,
52
+ } from './google-error';
49
53
  import { sanitizeResponseJsonSchema } from './sanitize-response-json-schema';
50
54
  import {
51
55
  googleLanguageModelOptions,
@@ -516,6 +520,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
516
520
  toolNameMapping,
517
521
  jsonResponseToolName,
518
522
  initialPromptTokenCount,
523
+ groundingMetadataPerRequest,
519
524
  }: {
520
525
  config: GoogleLanguageModelConfig;
521
526
  response: InferSchema<typeof responseSchema>;
@@ -524,6 +529,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
524
529
  toolNameMapping?: ReturnType<typeof createToolNameMapping>;
525
530
  jsonResponseToolName?: string;
526
531
  initialPromptTokenCount?: number | null;
532
+ groundingMetadataPerRequest?: Array<GroundingMetadataSchema | null>;
527
533
  }): LanguageModelV4GenerateResult {
528
534
  const wrapProviderMetadata = (payload: Record<string, unknown>) =>
529
535
  Object.fromEntries(
@@ -714,6 +720,9 @@ export class GoogleLanguageModel implements LanguageModelV4 {
714
720
  providerMetadata: wrapProviderMetadata({
715
721
  promptFeedback: response.promptFeedback ?? null,
716
722
  groundingMetadata: candidate?.groundingMetadata ?? null,
723
+ ...(groundingMetadataPerRequest != null
724
+ ? { groundingMetadataPerRequest }
725
+ : {}),
717
726
  urlContextMetadata: candidate?.urlContextMetadata ?? null,
718
727
  safetyRatings: candidate?.safetyRatings ?? null,
719
728
  usageMetadata: usageMetadata ?? null,
@@ -777,12 +786,15 @@ export class GoogleLanguageModel implements LanguageModelV4 {
777
786
  // the prompt plus all output so far as input, so the first request's
778
787
  // prompt token count is kept separately for context window checks.
779
788
  const content: LanguageModelV4Content[] = [];
789
+ const groundingMetadataPerRequest: Array<GroundingMetadataSchema | null> =
790
+ [];
780
791
  let usageMetadata: GoogleUsageMetadata | undefined;
781
792
  const firstPromptTokenCount = response.usageMetadata?.promptTokenCount;
782
793
  let isContinued = false;
783
794
 
784
795
  while (true) {
785
796
  const candidate = response.candidates?.[0];
797
+ groundingMetadataPerRequest.push(candidate?.groundingMetadata ?? null);
786
798
  const continuationToken =
787
799
  candidate?.finishReason === 'CONTINUATION'
788
800
  ? candidate.continuationToken
@@ -824,6 +836,9 @@ export class GoogleLanguageModel implements LanguageModelV4 {
824
836
  toolNameMapping,
825
837
  jsonResponseToolName,
826
838
  initialPromptTokenCount: isContinued ? firstPromptTokenCount : undefined,
839
+ groundingMetadataPerRequest: isContinued
840
+ ? groundingMetadataPerRequest
841
+ : undefined,
827
842
  });
828
843
 
829
844
  const result = {
@@ -881,6 +896,10 @@ export class GoogleLanguageModel implements LanguageModelV4 {
881
896
  const { responseHeaders, value: firstResponse } =
882
897
  await streamGenerateContent(args);
883
898
 
899
+ const groundingMetadataPerRequest: Array<GroundingMetadataSchema | null> =
900
+ [];
901
+ let requestGroundingMetadata: GroundingMetadataSchema | null = null;
902
+
884
903
  // Gemini 4 long decode: when a stream reaches the per-request cap while
885
904
  // `maxOutputTokens` budget remains, its last chunk finishes with
886
905
  // `CONTINUATION`. Resend the same request with the continuation token and
@@ -889,12 +908,22 @@ export class GoogleLanguageModel implements LanguageModelV4 {
889
908
  stream: firstResponse,
890
909
  getContinuationToken: chunk => {
891
910
  const candidate = chunk.candidates?.[0];
911
+ if (candidate?.groundingMetadata != null) {
912
+ requestGroundingMetadata = candidate.groundingMetadata;
913
+ }
892
914
  return candidate?.finishReason === 'CONTINUATION'
893
915
  ? (candidate.continuationToken ?? undefined)
894
916
  : undefined;
895
917
  },
896
- continueStream: async continuationToken =>
897
- (await streamGenerateContent({ ...args, continuationToken })).value,
918
+ continueStream: async continuationToken => {
919
+ const { value } = await streamGenerateContent({
920
+ ...args,
921
+ continuationToken,
922
+ });
923
+ groundingMetadataPerRequest.push(requestGroundingMetadata);
924
+ requestGroundingMetadata = null;
925
+ return value;
926
+ },
898
927
  });
899
928
 
900
929
  let finishReason: LanguageModelV4FinishReason = {
@@ -995,6 +1024,28 @@ export class GoogleLanguageModel implements LanguageModelV4 {
995
1024
 
996
1025
  const value = chunk.value;
997
1026
 
1027
+ if (value.error != null) {
1028
+ finishReason = { unified: 'error', raw: undefined };
1029
+ const error = value.error;
1030
+ controller.enqueue({
1031
+ type: 'error',
1032
+ error: createProviderStreamError({
1033
+ message: error.message,
1034
+ type: error.status,
1035
+ code: error.code ?? undefined,
1036
+ statusCode: error.code ?? undefined,
1037
+ isRetryable:
1038
+ error.code != null &&
1039
+ (error.code === 408 ||
1040
+ error.code === 409 ||
1041
+ error.code === 429 ||
1042
+ error.code >= 500),
1043
+ data: error,
1044
+ }),
1045
+ });
1046
+ return;
1047
+ }
1048
+
998
1049
  if (!hasEmittedResponseMetadata && value.responseId != null) {
999
1050
  hasEmittedResponseMetadata = true;
1000
1051
  controller.enqueue({
@@ -1463,6 +1514,14 @@ export class GoogleLanguageModel implements LanguageModelV4 {
1463
1514
  providerMetadata: wrapProviderMetadata({
1464
1515
  promptFeedback,
1465
1516
  groundingMetadata: lastGroundingMetadata,
1517
+ ...(groundingMetadataPerRequest.length > 0
1518
+ ? {
1519
+ groundingMetadataPerRequest: [
1520
+ ...groundingMetadataPerRequest,
1521
+ requestGroundingMetadata,
1522
+ ],
1523
+ }
1524
+ : {}),
1466
1525
  urlContextMetadata: lastUrlContextMetadata,
1467
1526
  safetyRatings: lastSafetyRatings,
1468
1527
  usageMetadata: usage ?? null,
@@ -2012,6 +2071,7 @@ export type UsageMetadataSchema = NonNullable<
2012
2071
  const chunkSchema = lazySchema(() =>
2013
2072
  zodSchema(
2014
2073
  z.object({
2074
+ error: getGoogleErrorSchema().nullish(),
2015
2075
  responseId: z.string().nullish(),
2016
2076
  candidates: z
2017
2077
  .array(
@@ -94,6 +94,8 @@ export type GoogleUsageMetadata = UsageMetadataSchema;
94
94
  export interface GoogleProviderMetadata {
95
95
  promptFeedback: GooglePromptFeedback | null;
96
96
  groundingMetadata: GoogleGroundingMetadata | null;
97
+ /** Grounding from each automatically continued request, in request order. */
98
+ groundingMetadataPerRequest?: Array<GoogleGroundingMetadata | null>;
97
99
  urlContextMetadata: GoogleUrlContextMetadata | null;
98
100
  safetyRatings: GoogleSafetyRating[] | null;
99
101
  usageMetadata: GoogleUsageMetadata | null;