@ai-sdk/google 3.0.122 → 3.0.123

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/google",
3
- "version": "3.0.122",
3
+ "version": "3.0.123",
4
4
  "license": "Apache-2.0",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
@@ -615,9 +615,12 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
615
615
  raw: undefined,
616
616
  };
617
617
  let usage: GoogleGenerativeAIUsageMetadata | undefined = undefined;
618
- let providerMetadata: SharedV3ProviderMetadata | undefined = undefined;
618
+ let promptFeedback: PromptFeedbackSchema | null = null;
619
619
  let lastGroundingMetadata: GroundingMetadataSchema | null = null;
620
620
  let lastUrlContextMetadata: UrlContextMetadataSchema | null = null;
621
+ let lastSafetyRatings: SafetyRatingSchema[] | null = null;
622
+ let lastFinishMessage: string | null = null;
623
+ let confirmedPromptBlockReason: string | undefined;
621
624
 
622
625
  const generateId = this.config.generateId;
623
626
  let hasToolCalls = false;
@@ -714,40 +717,48 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
714
717
  usage = usageMetadata;
715
718
  }
716
719
 
717
- const candidate = value.candidates?.[0];
720
+ if (
721
+ value.promptFeedback != null &&
722
+ confirmedPromptBlockReason == null
723
+ ) {
724
+ promptFeedback = value.promptFeedback;
718
725
 
719
- // sometimes the API returns an empty candidates array
720
- if (candidate == null) {
721
- const promptBlockReason = value.promptFeedback?.blockReason;
722
- if (promptBlockReason != null) {
726
+ if (
727
+ isConfirmedPromptBlockReason(value.promptFeedback.blockReason)
728
+ ) {
729
+ confirmedPromptBlockReason = value.promptFeedback.blockReason;
723
730
  finishReason = {
724
731
  unified: 'content-filter',
725
- raw: promptBlockReason,
726
- };
727
- providerMetadata = {
728
- [providerOptionsName]: {
729
- promptFeedback: value.promptFeedback ?? null,
730
- groundingMetadata: lastGroundingMetadata,
731
- urlContextMetadata: lastUrlContextMetadata,
732
- safetyRatings: null,
733
- usageMetadata: usageMetadata ?? null,
734
- finishMessage: null,
735
- serviceTier: usage?.serviceTier ?? null,
736
- } satisfies GoogleGenerativeAIProviderMetadata,
732
+ raw: confirmedPromptBlockReason,
737
733
  };
738
734
  }
739
- return;
740
735
  }
741
736
 
742
- const content = candidate.content;
737
+ const candidate = value.candidates?.[0];
743
738
 
744
- if (candidate.groundingMetadata != null) {
745
- lastGroundingMetadata = candidate.groundingMetadata;
739
+ if (candidate != null) {
740
+ if (candidate.groundingMetadata != null) {
741
+ lastGroundingMetadata = candidate.groundingMetadata;
742
+ }
743
+ if (candidate.urlContextMetadata != null) {
744
+ lastUrlContextMetadata = candidate.urlContextMetadata;
745
+ }
746
+ if (candidate.safetyRatings != null) {
747
+ lastSafetyRatings = candidate.safetyRatings;
748
+ }
749
+ if (candidate.finishMessage != null) {
750
+ lastFinishMessage = candidate.finishMessage;
751
+ }
746
752
  }
747
- if (candidate.urlContextMetadata != null) {
748
- lastUrlContextMetadata = candidate.urlContextMetadata;
753
+
754
+ // A confirmed prompt block is terminal for generated content, but
755
+ // later chunks can still contribute usage and provider metadata.
756
+ if (confirmedPromptBlockReason != null || candidate == null) {
757
+ return;
749
758
  }
750
759
 
760
+ const content = candidate.content;
761
+
751
762
  const sources = extractSources({
752
763
  groundingMetadata: candidate.groundingMetadata,
753
764
  generateId,
@@ -1125,33 +1136,13 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
1125
1136
  }
1126
1137
  }
1127
1138
 
1128
- const promptBlockReason = value.promptFeedback?.blockReason;
1129
- const isPromptBlocked =
1130
- candidate.finishReason == null && promptBlockReason != null;
1131
- const rawFinishReason =
1132
- candidate.finishReason ?? promptBlockReason ?? undefined;
1133
-
1134
- if (rawFinishReason != null) {
1139
+ if (candidate.finishReason != null) {
1135
1140
  finishReason = {
1136
- unified: isPromptBlocked
1137
- ? 'content-filter'
1138
- : mapGoogleGenerativeAIFinishReason({
1139
- finishReason: rawFinishReason,
1140
- hasToolCalls,
1141
- }),
1142
- raw: rawFinishReason,
1143
- };
1144
-
1145
- providerMetadata = {
1146
- [providerOptionsName]: {
1147
- promptFeedback: value.promptFeedback ?? null,
1148
- groundingMetadata: lastGroundingMetadata,
1149
- urlContextMetadata: lastUrlContextMetadata,
1150
- safetyRatings: candidate.safetyRatings ?? null,
1151
- usageMetadata: usageMetadata ?? null,
1152
- finishMessage: candidate.finishMessage ?? null,
1153
- serviceTier: usage?.serviceTier ?? null,
1154
- } satisfies GoogleGenerativeAIProviderMetadata,
1141
+ unified: mapGoogleGenerativeAIFinishReason({
1142
+ finishReason: candidate.finishReason,
1143
+ hasToolCalls,
1144
+ }),
1145
+ raw: candidate.finishReason,
1155
1146
  };
1156
1147
  }
1157
1148
  },
@@ -1174,7 +1165,17 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
1174
1165
  type: 'finish',
1175
1166
  finishReason,
1176
1167
  usage: convertGoogleGenerativeAIUsage(usage),
1177
- providerMetadata,
1168
+ providerMetadata: {
1169
+ [providerOptionsName]: {
1170
+ promptFeedback,
1171
+ groundingMetadata: lastGroundingMetadata,
1172
+ urlContextMetadata: lastUrlContextMetadata,
1173
+ safetyRatings: lastSafetyRatings,
1174
+ usageMetadata: usage ?? null,
1175
+ finishMessage: lastFinishMessage,
1176
+ serviceTier: usage?.serviceTier ?? null,
1177
+ } satisfies GoogleGenerativeAIProviderMetadata,
1178
+ },
1178
1179
  });
1179
1180
  },
1180
1181
  }),
@@ -1609,3 +1610,14 @@ const chunkSchema = lazySchema(() =>
1609
1610
  );
1610
1611
 
1611
1612
  type ChunkSchema = InferSchema<typeof chunkSchema>;
1613
+
1614
+ function isConfirmedPromptBlockReason(
1615
+ blockReason: string | null | undefined,
1616
+ ): blockReason is string {
1617
+ return (
1618
+ blockReason != null &&
1619
+ blockReason !== '' &&
1620
+ blockReason !== 'BLOCK_REASON_UNSPECIFIED' &&
1621
+ blockReason !== 'BLOCKED_REASON_UNSPECIFIED'
1622
+ );
1623
+ }