@ai-sdk/google 4.0.0-beta.13 → 4.0.0-beta.15

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 CHANGED
@@ -1,5 +1,25 @@
1
1
  # @ai-sdk/google
2
2
 
3
+ ## 4.0.0-beta.15
4
+
5
+ ### Patch Changes
6
+
7
+ - 18c1970: feat(provider/google): Add multimodal tool-result support for Google function responses.
8
+
9
+ Tool results with `output.type = 'content'` now map media parts into
10
+ `functionResponse.parts` for Google models, including `image-data`,
11
+ `file-data`, and base64 `data:` URLs in URL-style content parts.
12
+ Remote HTTP(S) URLs in URL-style tool-result parts are not supported.
13
+
14
+ ## 4.0.0-beta.14
15
+
16
+ ### Patch Changes
17
+
18
+ - 3887c70: feat(provider): add new top-level reasoning parameter to spec and support it in `generateText` and `streamText`
19
+ - Updated dependencies [3887c70]
20
+ - @ai-sdk/provider-utils@5.0.0-beta.6
21
+ - @ai-sdk/provider@4.0.0-beta.4
22
+
3
23
  ## 4.0.0-beta.13
4
24
 
5
25
  ### Patch Changes
@@ -413,13 +433,13 @@
413
433
  Before
414
434
 
415
435
  ```ts
416
- model.textEmbeddingModel('my-model-id');
436
+ model.textEmbeddingModel("my-model-id");
417
437
  ```
418
438
 
419
439
  After
420
440
 
421
441
  ```ts
422
- model.embeddingModel('my-model-id');
442
+ model.embeddingModel("my-model-id");
423
443
  ```
424
444
 
425
445
  - 2625a04: feat(openai); update spec for mcp approval
@@ -728,13 +748,13 @@
728
748
  Before
729
749
 
730
750
  ```ts
731
- model.textEmbeddingModel('my-model-id');
751
+ model.textEmbeddingModel("my-model-id");
732
752
  ```
733
753
 
734
754
  After
735
755
 
736
756
  ```ts
737
- model.embeddingModel('my-model-id');
757
+ model.embeddingModel("my-model-id");
738
758
  ```
739
759
 
740
760
  - Updated dependencies [8d9e8ad]
package/dist/index.js CHANGED
@@ -30,7 +30,7 @@ module.exports = __toCommonJS(index_exports);
30
30
  var import_provider_utils16 = require("@ai-sdk/provider-utils");
31
31
 
32
32
  // src/version.ts
33
- var VERSION = true ? "4.0.0-beta.13" : "0.0.0-test";
33
+ var VERSION = true ? "4.0.0-beta.15" : "0.0.0-test";
34
34
 
35
35
  // src/google-generative-ai-embedding-model.ts
36
36
  var import_provider = require("@ai-sdk/provider");
@@ -400,13 +400,118 @@ function isEmptyObjectSchema(jsonSchema) {
400
400
  // src/convert-to-google-generative-ai-messages.ts
401
401
  var import_provider2 = require("@ai-sdk/provider");
402
402
  var import_provider_utils4 = require("@ai-sdk/provider-utils");
403
+ var dataUrlRegex = /^data:([^;,]+);base64,(.+)$/s;
404
+ function parseBase64DataUrl(value) {
405
+ const match = dataUrlRegex.exec(value);
406
+ if (match == null) {
407
+ return void 0;
408
+ }
409
+ return {
410
+ mediaType: match[1],
411
+ data: match[2]
412
+ };
413
+ }
414
+ function convertUrlToolResultPart(url) {
415
+ const parsedDataUrl = parseBase64DataUrl(url);
416
+ if (parsedDataUrl == null) {
417
+ return void 0;
418
+ }
419
+ return {
420
+ inlineData: {
421
+ mimeType: parsedDataUrl.mediaType,
422
+ data: parsedDataUrl.data
423
+ }
424
+ };
425
+ }
426
+ function appendToolResultParts(parts, toolName, outputValue) {
427
+ const functionResponseParts = [];
428
+ const responseTextParts = [];
429
+ for (const contentPart of outputValue) {
430
+ switch (contentPart.type) {
431
+ case "text": {
432
+ responseTextParts.push(contentPart.text);
433
+ break;
434
+ }
435
+ case "image-data":
436
+ case "file-data": {
437
+ functionResponseParts.push({
438
+ inlineData: {
439
+ mimeType: contentPart.mediaType,
440
+ data: contentPart.data
441
+ }
442
+ });
443
+ break;
444
+ }
445
+ case "image-url":
446
+ case "file-url": {
447
+ const functionResponsePart = convertUrlToolResultPart(
448
+ contentPart.url
449
+ );
450
+ if (functionResponsePart != null) {
451
+ functionResponseParts.push(functionResponsePart);
452
+ } else {
453
+ responseTextParts.push(JSON.stringify(contentPart));
454
+ }
455
+ break;
456
+ }
457
+ default: {
458
+ responseTextParts.push(JSON.stringify(contentPart));
459
+ break;
460
+ }
461
+ }
462
+ }
463
+ parts.push({
464
+ functionResponse: {
465
+ name: toolName,
466
+ response: {
467
+ name: toolName,
468
+ content: responseTextParts.length > 0 ? responseTextParts.join("\n") : "Tool executed successfully."
469
+ },
470
+ ...functionResponseParts.length > 0 ? { parts: functionResponseParts } : {}
471
+ }
472
+ });
473
+ }
474
+ function appendLegacyToolResultParts(parts, toolName, outputValue) {
475
+ for (const contentPart of outputValue) {
476
+ switch (contentPart.type) {
477
+ case "text":
478
+ parts.push({
479
+ functionResponse: {
480
+ name: toolName,
481
+ response: {
482
+ name: toolName,
483
+ content: contentPart.text
484
+ }
485
+ }
486
+ });
487
+ break;
488
+ case "image-data":
489
+ parts.push(
490
+ {
491
+ inlineData: {
492
+ mimeType: String(contentPart.mediaType),
493
+ data: String(contentPart.data)
494
+ }
495
+ },
496
+ {
497
+ text: "Tool executed successfully and returned this image as a response"
498
+ }
499
+ );
500
+ break;
501
+ default:
502
+ parts.push({ text: JSON.stringify(contentPart) });
503
+ break;
504
+ }
505
+ }
506
+ }
403
507
  function convertToGoogleGenerativeAIMessages(prompt, options) {
404
- var _a, _b, _c;
508
+ var _a, _b, _c, _d;
405
509
  const systemInstructionParts = [];
406
510
  const contents = [];
407
511
  let systemMessagesAllowed = true;
408
512
  const isGemmaModel = (_a = options == null ? void 0 : options.isGemmaModel) != null ? _a : false;
409
513
  const providerOptionsName = (_b = options == null ? void 0 : options.providerOptionsName) != null ? _b : "google";
514
+ const supportsFunctionResponseParts = (_c = options == null ? void 0 : options.supportsFunctionResponseParts) != null ? _c : true;
410
515
  for (const { role, content } of prompt) {
411
516
  switch (role) {
412
517
  case "system": {
@@ -454,8 +559,8 @@ function convertToGoogleGenerativeAIMessages(prompt, options) {
454
559
  contents.push({
455
560
  role: "model",
456
561
  parts: content.map((part) => {
457
- var _a2, _b2, _c2, _d;
458
- const providerOpts = (_d = (_a2 = part.providerOptions) == null ? void 0 : _a2[providerOptionsName]) != null ? _d : providerOptionsName !== "google" ? (_b2 = part.providerOptions) == null ? void 0 : _b2.google : (_c2 = part.providerOptions) == null ? void 0 : _c2.vertex;
562
+ var _a2, _b2, _c2, _d2;
563
+ const providerOpts = (_d2 = (_a2 = part.providerOptions) == null ? void 0 : _a2[providerOptionsName]) != null ? _d2 : providerOptionsName !== "google" ? (_b2 = part.providerOptions) == null ? void 0 : _b2.google : (_c2 = part.providerOptions) == null ? void 0 : _c2.vertex;
459
564
  const thoughtSignature = (providerOpts == null ? void 0 : providerOpts.thoughtSignature) != null ? String(providerOpts.thoughtSignature) : void 0;
460
565
  switch (part.type) {
461
566
  case "text": {
@@ -524,36 +629,10 @@ function convertToGoogleGenerativeAIMessages(prompt, options) {
524
629
  }
525
630
  const output = part.output;
526
631
  if (output.type === "content") {
527
- for (const contentPart of output.value) {
528
- switch (contentPart.type) {
529
- case "text":
530
- parts.push({
531
- functionResponse: {
532
- name: part.toolName,
533
- response: {
534
- name: part.toolName,
535
- content: contentPart.text
536
- }
537
- }
538
- });
539
- break;
540
- case "image-data":
541
- parts.push(
542
- {
543
- inlineData: {
544
- mimeType: contentPart.mediaType,
545
- data: contentPart.data
546
- }
547
- },
548
- {
549
- text: "Tool executed successfully and returned this image as a response"
550
- }
551
- );
552
- break;
553
- default:
554
- parts.push({ text: JSON.stringify(contentPart) });
555
- break;
556
- }
632
+ if (supportsFunctionResponseParts) {
633
+ appendToolResultParts(parts, part.toolName, output.value);
634
+ } else {
635
+ appendLegacyToolResultParts(parts, part.toolName, output.value);
557
636
  }
558
637
  } else {
559
638
  parts.push({
@@ -561,7 +640,7 @@ function convertToGoogleGenerativeAIMessages(prompt, options) {
561
640
  name: part.toolName,
562
641
  response: {
563
642
  name: part.toolName,
564
- content: output.type === "execution-denied" ? (_c = output.reason) != null ? _c : "Tool execution denied." : output.value
643
+ content: output.type === "execution-denied" ? (_d = output.reason) != null ? _d : "Tool execution denied." : output.value
565
644
  }
566
645
  }
567
646
  });
@@ -977,6 +1056,7 @@ var GoogleGenerativeAILanguageModel = class {
977
1056
  seed,
978
1057
  tools,
979
1058
  toolChoice,
1059
+ reasoning,
980
1060
  providerOptions
981
1061
  }) {
982
1062
  var _a;
@@ -1003,9 +1083,14 @@ var GoogleGenerativeAILanguageModel = class {
1003
1083
  });
1004
1084
  }
1005
1085
  const isGemmaModel = this.modelId.toLowerCase().startsWith("gemma-");
1086
+ const supportsFunctionResponseParts = this.modelId.startsWith("gemini-3");
1006
1087
  const { contents, systemInstruction } = convertToGoogleGenerativeAIMessages(
1007
1088
  prompt,
1008
- { isGemmaModel, providerOptionsName }
1089
+ {
1090
+ isGemmaModel,
1091
+ providerOptionsName,
1092
+ supportsFunctionResponseParts
1093
+ }
1009
1094
  );
1010
1095
  const {
1011
1096
  tools: googleTools2,
@@ -1016,6 +1101,12 @@ var GoogleGenerativeAILanguageModel = class {
1016
1101
  toolChoice,
1017
1102
  modelId: this.modelId
1018
1103
  });
1104
+ const resolvedThinking = resolveThinkingConfig({
1105
+ reasoning,
1106
+ modelId: this.modelId,
1107
+ warnings
1108
+ });
1109
+ const thinkingConfig = (googleOptions == null ? void 0 : googleOptions.thinkingConfig) || resolvedThinking ? { ...resolvedThinking, ...googleOptions == null ? void 0 : googleOptions.thinkingConfig } : void 0;
1019
1110
  return {
1020
1111
  args: {
1021
1112
  generationConfig: {
@@ -1039,7 +1130,7 @@ var GoogleGenerativeAILanguageModel = class {
1039
1130
  },
1040
1131
  // provider options:
1041
1132
  responseModalities: googleOptions == null ? void 0 : googleOptions.responseModalities,
1042
- thinkingConfig: googleOptions == null ? void 0 : googleOptions.thinkingConfig,
1133
+ thinkingConfig,
1043
1134
  ...(googleOptions == null ? void 0 : googleOptions.mediaResolution) && {
1044
1135
  mediaResolution: googleOptions.mediaResolution
1045
1136
  },
@@ -1470,6 +1561,75 @@ var GoogleGenerativeAILanguageModel = class {
1470
1561
  };
1471
1562
  }
1472
1563
  };
1564
+ function isGemini3Model(modelId) {
1565
+ return /gemini-3[\.\-]/i.test(modelId) || /gemini-3$/i.test(modelId);
1566
+ }
1567
+ function getMaxOutputTokensForGemini25Model() {
1568
+ return 65536;
1569
+ }
1570
+ function getMaxThinkingTokensForGemini25Model(modelId) {
1571
+ const id = modelId.toLowerCase();
1572
+ if (id.includes("2.5-pro") || id.includes("gemini-3-pro-image")) {
1573
+ return 32768;
1574
+ }
1575
+ return 24576;
1576
+ }
1577
+ function resolveThinkingConfig({
1578
+ reasoning,
1579
+ modelId,
1580
+ warnings
1581
+ }) {
1582
+ if (!(0, import_provider_utils6.isCustomReasoning)(reasoning)) {
1583
+ return void 0;
1584
+ }
1585
+ if (isGemini3Model(modelId) && !modelId.includes("gemini-3-pro-image")) {
1586
+ return resolveGemini3ThinkingConfig({ reasoning, warnings });
1587
+ }
1588
+ return resolveGemini25ThinkingConfig({ reasoning, modelId, warnings });
1589
+ }
1590
+ function resolveGemini3ThinkingConfig({
1591
+ reasoning,
1592
+ warnings
1593
+ }) {
1594
+ if (reasoning === "none") {
1595
+ return { thinkingLevel: "minimal" };
1596
+ }
1597
+ const thinkingLevel = (0, import_provider_utils6.mapReasoningToProviderEffort)({
1598
+ reasoning,
1599
+ effortMap: {
1600
+ minimal: "minimal",
1601
+ low: "low",
1602
+ medium: "medium",
1603
+ high: "high",
1604
+ xhigh: "high"
1605
+ },
1606
+ warnings
1607
+ });
1608
+ if (thinkingLevel == null) {
1609
+ return void 0;
1610
+ }
1611
+ return { thinkingLevel };
1612
+ }
1613
+ function resolveGemini25ThinkingConfig({
1614
+ reasoning,
1615
+ modelId,
1616
+ warnings
1617
+ }) {
1618
+ if (reasoning === "none") {
1619
+ return { thinkingBudget: 0 };
1620
+ }
1621
+ const thinkingBudget = (0, import_provider_utils6.mapReasoningToProviderBudget)({
1622
+ reasoning,
1623
+ maxOutputTokens: getMaxOutputTokensForGemini25Model(),
1624
+ maxReasoningBudget: getMaxThinkingTokensForGemini25Model(modelId),
1625
+ minReasoningBudget: 0,
1626
+ warnings
1627
+ });
1628
+ if (thinkingBudget == null) {
1629
+ return void 0;
1630
+ }
1631
+ return { thinkingBudget };
1632
+ }
1473
1633
  function getToolCallsFromParts({
1474
1634
  parts,
1475
1635
  generateId: generateId3,