@ai-sdk/google 3.0.98 → 3.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.
@@ -359,6 +359,7 @@ function convertToGoogleGenerativeAIMessages(prompt, options) {
359
359
  }
360
360
  case "assistant": {
361
361
  systemMessagesAllowed = false;
362
+ let modelResponseHasSignedFunctionCall = false;
362
363
  contents.push({
363
364
  role: "model",
364
365
  parts: content.map((part) => {
@@ -399,8 +400,19 @@ function convertToGoogleGenerativeAIMessages(prompt, options) {
399
400
  case "tool-call": {
400
401
  const serverToolCallId = (providerOpts == null ? void 0 : providerOpts.serverToolCallId) != null ? String(providerOpts.serverToolCallId) : void 0;
401
402
  const serverToolType = (providerOpts == null ? void 0 : providerOpts.serverToolType) != null ? String(providerOpts.serverToolType) : void 0;
402
- const effectiveThoughtSignature = thoughtSignature != null ? thoughtSignature : isGemini3Model ? injectSkipSignature(part.toolName) : void 0;
403
- if (serverToolCallId && serverToolType) {
403
+ const isServerToolCall = serverToolCallId != null && serverToolType != null;
404
+ const shouldSkipMissingSignatureMitigation = (
405
+ // Gemini 3 returns a single signature for a parallel
406
+ // function-call response on the first standard function
407
+ // call. Subsequent standard function calls in the same
408
+ // model response legitimately have no signature.
409
+ !isServerToolCall && thoughtSignature == null && modelResponseHasSignedFunctionCall
410
+ );
411
+ const effectiveThoughtSignature = thoughtSignature != null ? thoughtSignature : isGemini3Model && !shouldSkipMissingSignatureMitigation ? injectSkipSignature(part.toolName) : void 0;
412
+ if (!isServerToolCall && thoughtSignature != null) {
413
+ modelResponseHasSignedFunctionCall = true;
414
+ }
415
+ if (isServerToolCall) {
404
416
  return {
405
417
  toolCall: {
406
418
  toolType: serverToolType,
@@ -743,6 +755,27 @@ var googleLanguageModelOptions = lazySchema2(
743
755
  )
744
756
  );
745
757
 
758
+ // src/google-model-capabilities.ts
759
+ var gemini1ModelPattern = /(^|\/)gemini-1(?:[.-]|$)/i;
760
+ var gemini2ModelPattern = /(^|\/)gemini-2(?:[.-]|$)/i;
761
+ var gemini25ModelPattern = /(^|\/)gemini-2\.5(?:[.-]|$)/i;
762
+ var geminiModelPattern = /(^|\/)gemini-/i;
763
+ function isKnownPreGemini2Model(modelId) {
764
+ return gemini1ModelPattern.test(modelId) || /(^|\/)gemini-pro(?:-vision)?$/i.test(modelId) || /(^|\/)gemini-robotics-er-1\.5(?:[.-]|$)/i.test(modelId);
765
+ }
766
+ function getGoogleModelCapabilities(modelId) {
767
+ const isGeminiModel = geminiModelPattern.test(modelId);
768
+ const isGemini2Model = gemini2ModelPattern.test(modelId);
769
+ const isKnownPreGemini2 = isKnownPreGemini2Model(modelId);
770
+ const isKnownOlderModel = isKnownPreGemini2 || isGemini2Model;
771
+ const usesGemini3Features = isGeminiModel && !isKnownOlderModel;
772
+ return {
773
+ supportsGemini2Tools: isGeminiModel && !isKnownPreGemini2 || modelId.toLowerCase().includes("nano-banana"),
774
+ supportsFileSearch: gemini25ModelPattern.test(modelId) || usesGemini3Features,
775
+ usesGemini3Features
776
+ };
777
+ }
778
+
746
779
  // src/google-prepare-tools.ts
747
780
  import {
748
781
  UnsupportedFunctionalityError as UnsupportedFunctionalityError2
@@ -756,20 +789,13 @@ function prepareTools({
756
789
  var _a, _b;
757
790
  tools = (tools == null ? void 0 : tools.length) ? tools : void 0;
758
791
  const toolWarnings = [];
759
- const isLatest = [
760
- "gemini-flash-latest",
761
- "gemini-flash-lite-latest",
762
- "gemini-pro-latest"
763
- ].some((id) => id === modelId);
764
- const isGemini2orNewer = modelId.includes("gemini-2") || modelId.includes("gemini-3") || modelId.includes("nano-banana") || isLatest;
765
- const isGemini3orNewer = modelId.includes("gemini-3");
766
- const supportsFileSearch = modelId.includes("gemini-2.5") || modelId.includes("gemini-3");
792
+ const { supportsGemini2Tools, supportsFileSearch, usesGemini3Features } = getGoogleModelCapabilities(modelId);
767
793
  if (tools == null) {
768
794
  return { tools: void 0, toolConfig: void 0, toolWarnings };
769
795
  }
770
796
  const hasFunctionTools = tools.some((tool) => tool.type === "function");
771
797
  const hasProviderTools = tools.some((tool) => tool.type === "provider");
772
- if (hasFunctionTools && hasProviderTools && !isGemini3orNewer) {
798
+ if (hasFunctionTools && hasProviderTools && !usesGemini3Features) {
773
799
  toolWarnings.push({
774
800
  type: "unsupported",
775
801
  feature: `combination of function and provider-defined tools`
@@ -781,7 +807,7 @@ function prepareTools({
781
807
  ProviderTools.forEach((tool) => {
782
808
  switch (tool.id) {
783
809
  case "google.google_search":
784
- if (isGemini2orNewer) {
810
+ if (supportsGemini2Tools) {
785
811
  googleTools2.push({ googleSearch: { ...tool.args } });
786
812
  } else {
787
813
  toolWarnings.push({
@@ -792,7 +818,7 @@ function prepareTools({
792
818
  }
793
819
  break;
794
820
  case "google.enterprise_web_search":
795
- if (isGemini2orNewer) {
821
+ if (supportsGemini2Tools) {
796
822
  googleTools2.push({ enterpriseWebSearch: {} });
797
823
  } else {
798
824
  toolWarnings.push({
@@ -803,7 +829,7 @@ function prepareTools({
803
829
  }
804
830
  break;
805
831
  case "google.url_context":
806
- if (isGemini2orNewer) {
832
+ if (supportsGemini2Tools) {
807
833
  googleTools2.push({ urlContext: {} });
808
834
  } else {
809
835
  toolWarnings.push({
@@ -814,7 +840,7 @@ function prepareTools({
814
840
  }
815
841
  break;
816
842
  case "google.code_execution":
817
- if (isGemini2orNewer) {
843
+ if (supportsGemini2Tools) {
818
844
  googleTools2.push({ codeExecution: {} });
819
845
  } else {
820
846
  toolWarnings.push({
@@ -836,7 +862,7 @@ function prepareTools({
836
862
  }
837
863
  break;
838
864
  case "google.vertex_rag_store":
839
- if (isGemini2orNewer) {
865
+ if (supportsGemini2Tools) {
840
866
  googleTools2.push({
841
867
  retrieval: {
842
868
  vertex_rag_store: {
@@ -856,7 +882,7 @@ function prepareTools({
856
882
  }
857
883
  break;
858
884
  case "google.google_maps":
859
- if (isGemini2orNewer) {
885
+ if (supportsGemini2Tools) {
860
886
  googleTools2.push({ googleMaps: {} });
861
887
  } else {
862
888
  toolWarnings.push({
@@ -874,7 +900,7 @@ function prepareTools({
874
900
  break;
875
901
  }
876
902
  });
877
- if (hasFunctionTools && isGemini3orNewer && googleTools2.length > 0) {
903
+ if (hasFunctionTools && usesGemini3Features && googleTools2.length > 0) {
878
904
  const functionDeclarations2 = [];
879
905
  for (const tool of tools) {
880
906
  if (tool.type === "function") {
@@ -1371,15 +1397,14 @@ var GoogleGenerativeAILanguageModel = class {
1371
1397
  }
1372
1398
  }
1373
1399
  const isGemmaModel = this.modelId.toLowerCase().startsWith("gemma-");
1374
- const isGemini3Model = /^gemini-3[.-]/.test(this.modelId);
1375
- const supportsFunctionResponseParts = isGemini3Model;
1400
+ const { usesGemini3Features } = getGoogleModelCapabilities(this.modelId);
1376
1401
  const { contents, systemInstruction } = convertToGoogleGenerativeAIMessages(
1377
1402
  prompt,
1378
1403
  {
1379
1404
  isGemmaModel,
1380
- isGemini3Model,
1405
+ isGemini3Model: usesGemini3Features,
1381
1406
  providerOptionsName,
1382
- supportsFunctionResponseParts,
1407
+ supportsFunctionResponseParts: usesGemini3Features,
1383
1408
  onWarning: (warning) => warnings.push(warning)
1384
1409
  }
1385
1410
  );