@ai-sdk/google 2.0.102 → 2.0.104

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/dist/index.mjs CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  } from "@ai-sdk/provider-utils";
8
8
 
9
9
  // src/version.ts
10
- var VERSION = true ? "2.0.102" : "0.0.0-test";
10
+ var VERSION = true ? "2.0.104" : "0.0.0-test";
11
11
 
12
12
  // src/google-generative-ai-embedding-model.ts
13
13
  import {
@@ -245,6 +245,100 @@ import {
245
245
  } from "@ai-sdk/provider-utils";
246
246
  import { z as z5 } from "zod/v4";
247
247
 
248
+ // src/add-google-generative-ai-usage-metadata.ts
249
+ function addGoogleGenerativeAIUsageMetadata(a, b) {
250
+ if (a == null || b == null) {
251
+ return b != null ? b : a;
252
+ }
253
+ return {
254
+ ...a,
255
+ ...b,
256
+ promptTokenCount: addCounts(a.promptTokenCount, b.promptTokenCount),
257
+ candidatesTokenCount: addCounts(
258
+ a.candidatesTokenCount,
259
+ b.candidatesTokenCount
260
+ ),
261
+ totalTokenCount: addCounts(a.totalTokenCount, b.totalTokenCount),
262
+ cachedContentTokenCount: addCounts(
263
+ a.cachedContentTokenCount,
264
+ b.cachedContentTokenCount
265
+ ),
266
+ thoughtsTokenCount: addCounts(a.thoughtsTokenCount, b.thoughtsTokenCount),
267
+ promptTokensDetails: addTokenDetails(
268
+ a.promptTokensDetails,
269
+ b.promptTokensDetails
270
+ ),
271
+ candidatesTokensDetails: addTokenDetails(
272
+ a.candidatesTokensDetails,
273
+ b.candidatesTokensDetails
274
+ )
275
+ };
276
+ }
277
+ function addCounts(a, b) {
278
+ return a == null && b == null ? b != null ? b : a : (a != null ? a : 0) + (b != null ? b : 0);
279
+ }
280
+ function addTokenDetails(a, b) {
281
+ var _a;
282
+ if (a == null || b == null) {
283
+ return b != null ? b : a;
284
+ }
285
+ const tokenCounts = /* @__PURE__ */ new Map();
286
+ for (const { modality, tokenCount } of [...a, ...b]) {
287
+ tokenCounts.set(modality, ((_a = tokenCounts.get(modality)) != null ? _a : 0) + tokenCount);
288
+ }
289
+ return Array.from(tokenCounts, ([modality, tokenCount]) => ({
290
+ modality,
291
+ tokenCount
292
+ }));
293
+ }
294
+
295
+ // src/continue-google-stream.ts
296
+ function continueGoogleStream({
297
+ stream,
298
+ getContinuationToken,
299
+ continueStream
300
+ }) {
301
+ let reader = stream.getReader();
302
+ let pendingContinuationToken;
303
+ return new ReadableStream({
304
+ async pull(controller) {
305
+ while (true) {
306
+ const { done, value } = await reader.read();
307
+ if (!done) {
308
+ if (value.success) {
309
+ const token = getContinuationToken(value.value);
310
+ if (token != null) {
311
+ pendingContinuationToken = token;
312
+ }
313
+ }
314
+ controller.enqueue(value);
315
+ return;
316
+ }
317
+ if (pendingContinuationToken == null) {
318
+ controller.close();
319
+ return;
320
+ }
321
+ const continuationToken = pendingContinuationToken;
322
+ pendingContinuationToken = void 0;
323
+ try {
324
+ reader = (await continueStream(continuationToken)).getReader();
325
+ } catch (error) {
326
+ controller.enqueue({
327
+ success: false,
328
+ error,
329
+ rawValue: void 0
330
+ });
331
+ controller.close();
332
+ return;
333
+ }
334
+ }
335
+ },
336
+ async cancel(reason) {
337
+ await reader.cancel(reason);
338
+ }
339
+ });
340
+ }
341
+
248
342
  // src/convert-json-schema-to-openapi-schema.ts
249
343
  import {
250
344
  UnsupportedFunctionalityError
@@ -907,7 +1001,17 @@ var googleGenerativeAIProviderOptions = lazySchema4(
907
1001
  /**
908
1002
  * Optional. The service tier to use for the request.
909
1003
  */
910
- serviceTier: z4.enum(["standard", "flex", "priority"]).optional()
1004
+ serviceTier: z4.enum(["standard", "flex", "priority"]).optional(),
1005
+ /**
1006
+ * Optional. Resumes a response that stopped with `MAX_TOKENS` because it
1007
+ * used up its `maxOutputTokens` budget (Gemini 4 long decode). Pass the
1008
+ * `continuationToken` from the previous response's provider metadata
1009
+ * together with the original prompt and a higher `maxOutputTokens` (the
1010
+ * budget is cumulative across requests). Requests that reach the
1011
+ * per-request cap while budget remains (`CONTINUATION`) are continued
1012
+ * automatically. Sent as the `continuationToken` body field.
1013
+ */
1014
+ continuationToken: z4.string().optional()
911
1015
  })
912
1016
  )
913
1017
  );
@@ -1207,6 +1311,9 @@ function mapGoogleGenerativeAIFinishReason({
1207
1311
  case "STOP":
1208
1312
  return hasToolCalls ? "tool-calls" : "stop";
1209
1313
  case "MAX_TOKENS":
1314
+ // Gemini 4 long decode: the per-request cap was reached while budget
1315
+ // remains. Continued automatically; only surfaced if continuing fails.
1316
+ case "CONTINUATION":
1210
1317
  return "length";
1211
1318
  case "IMAGE_SAFETY":
1212
1319
  case "RECITATION":
@@ -1381,43 +1488,72 @@ var GoogleGenerativeAILanguageModel = class {
1381
1488
  } : googleToolConfig,
1382
1489
  cachedContent: googleOptions == null ? void 0 : googleOptions.cachedContent,
1383
1490
  labels: googleOptions == null ? void 0 : googleOptions.labels,
1384
- serviceTier: sanitizedServiceTier
1491
+ serviceTier: sanitizedServiceTier,
1492
+ ...(googleOptions == null ? void 0 : googleOptions.continuationToken) != null && {
1493
+ continuationToken: googleOptions.continuationToken
1494
+ }
1385
1495
  },
1386
1496
  warnings: [...warnings, ...toolWarnings]
1387
1497
  };
1388
1498
  }
1389
1499
  async doGenerate(options) {
1390
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
1500
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
1391
1501
  const { args, warnings } = await this.getArgs(options);
1392
1502
  const body = JSON.stringify(args);
1393
1503
  const mergedHeaders = combineHeaders2(
1394
1504
  await resolve2(this.config.headers),
1395
1505
  options.headers
1396
1506
  );
1397
- const {
1398
- responseHeaders,
1399
- value: response,
1400
- rawValue: rawResponse
1401
- } = await postJsonToApi2({
1507
+ const generateContent = (body2) => postJsonToApi2({
1402
1508
  url: `${this.config.baseURL}/${getModelPath(
1403
1509
  this.modelId
1404
1510
  )}:generateContent`,
1405
1511
  headers: mergedHeaders,
1406
- body: args,
1512
+ body: body2,
1407
1513
  failedResponseHandler: googleFailedResponseHandler,
1408
1514
  successfulResponseHandler: createJsonResponseHandler2(responseSchema),
1409
1515
  abortSignal: options.abortSignal,
1410
1516
  fetch: this.config.fetch
1411
1517
  });
1412
- const candidate = (_a = response.candidates) == null ? void 0 : _a[0];
1413
- const promptBlockReason = (_b = response.promptFeedback) == null ? void 0 : _b.blockReason;
1518
+ let {
1519
+ responseHeaders,
1520
+ value: response,
1521
+ rawValue: rawResponse
1522
+ } = await generateContent(args);
1523
+ const continuedParts = [];
1524
+ const groundingMetadataPerRequest = [];
1525
+ let continuedUsageMetadata;
1526
+ const firstPromptTokenCount = (_a = response.usageMetadata) == null ? void 0 : _a.promptTokenCount;
1527
+ while (true) {
1528
+ const candidate2 = (_b = response.candidates) == null ? void 0 : _b[0];
1529
+ groundingMetadataPerRequest.push((_c = candidate2 == null ? void 0 : candidate2.groundingMetadata) != null ? _c : null);
1530
+ const continuationToken = (candidate2 == null ? void 0 : candidate2.finishReason) === "CONTINUATION" ? candidate2.continuationToken : void 0;
1531
+ if (continuationToken == null) {
1532
+ break;
1533
+ }
1534
+ continuedParts.push(...(_e = (_d = candidate2 == null ? void 0 : candidate2.content) == null ? void 0 : _d.parts) != null ? _e : []);
1535
+ continuedUsageMetadata = addGoogleGenerativeAIUsageMetadata(
1536
+ continuedUsageMetadata,
1537
+ (_f = response.usageMetadata) != null ? _f : void 0
1538
+ );
1539
+ ({
1540
+ responseHeaders,
1541
+ value: response,
1542
+ rawValue: rawResponse
1543
+ } = await generateContent({ ...args, continuationToken }));
1544
+ }
1545
+ const candidate = (_g = response.candidates) == null ? void 0 : _g[0];
1546
+ const promptBlockReason = (_h = response.promptFeedback) == null ? void 0 : _h.blockReason;
1414
1547
  const isPromptBlocked = (candidate == null ? void 0 : candidate.finishReason) == null && promptBlockReason != null;
1415
1548
  const content = [];
1416
- const parts = (_d = (_c = candidate == null ? void 0 : candidate.content) == null ? void 0 : _c.parts) != null ? _d : [];
1417
- const usageMetadata = response.usageMetadata;
1549
+ const parts = [...continuedParts, ...(_j = (_i = candidate == null ? void 0 : candidate.content) == null ? void 0 : _i.parts) != null ? _j : []];
1550
+ const usageMetadata = addGoogleGenerativeAIUsageMetadata(
1551
+ continuedUsageMetadata,
1552
+ (_k = response.usageMetadata) != null ? _k : void 0
1553
+ );
1418
1554
  let lastCodeExecutionToolCallId;
1419
1555
  for (const part of parts) {
1420
- if ("executableCode" in part && ((_e = part.executableCode) == null ? void 0 : _e.code)) {
1556
+ if ("executableCode" in part && ((_l = part.executableCode) == null ? void 0 : _l.code)) {
1421
1557
  const toolCallId = this.config.generateId();
1422
1558
  lastCodeExecutionToolCallId = toolCallId;
1423
1559
  content.push({
@@ -1458,7 +1594,7 @@ var GoogleGenerativeAILanguageModel = class {
1458
1594
  } else if ("functionCall" in part) {
1459
1595
  content.push({
1460
1596
  type: "tool-call",
1461
- toolCallId: (_f = part.functionCall.id) != null ? _f : this.config.generateId(),
1597
+ toolCallId: (_m = part.functionCall.id) != null ? _m : this.config.generateId(),
1462
1598
  toolName: part.functionCall.name,
1463
1599
  input: JSON.stringify(part.functionCall.args),
1464
1600
  providerMetadata: part.thoughtSignature ? { google: { thoughtSignature: part.thoughtSignature } } : void 0
@@ -1471,10 +1607,10 @@ var GoogleGenerativeAILanguageModel = class {
1471
1607
  });
1472
1608
  }
1473
1609
  }
1474
- const sources = (_g = extractSources({
1610
+ const sources = (_n = extractSources({
1475
1611
  groundingMetadata: candidate == null ? void 0 : candidate.groundingMetadata,
1476
1612
  generateId: this.config.generateId
1477
- })) != null ? _g : [];
1613
+ })) != null ? _n : [];
1478
1614
  for (const source of sources) {
1479
1615
  content.push(source);
1480
1616
  }
@@ -1485,20 +1621,23 @@ var GoogleGenerativeAILanguageModel = class {
1485
1621
  hasToolCalls: content.some((part) => part.type === "tool-call")
1486
1622
  }),
1487
1623
  usage: {
1488
- inputTokens: (_h = usageMetadata == null ? void 0 : usageMetadata.promptTokenCount) != null ? _h : void 0,
1489
- outputTokens: (_i = usageMetadata == null ? void 0 : usageMetadata.candidatesTokenCount) != null ? _i : void 0,
1490
- totalTokens: (_j = usageMetadata == null ? void 0 : usageMetadata.totalTokenCount) != null ? _j : void 0,
1491
- reasoningTokens: (_k = usageMetadata == null ? void 0 : usageMetadata.thoughtsTokenCount) != null ? _k : void 0,
1492
- cachedInputTokens: (_l = usageMetadata == null ? void 0 : usageMetadata.cachedContentTokenCount) != null ? _l : void 0
1624
+ inputTokens: (_o = usageMetadata == null ? void 0 : usageMetadata.promptTokenCount) != null ? _o : void 0,
1625
+ outputTokens: (_p = usageMetadata == null ? void 0 : usageMetadata.candidatesTokenCount) != null ? _p : void 0,
1626
+ totalTokens: (_q = usageMetadata == null ? void 0 : usageMetadata.totalTokenCount) != null ? _q : void 0,
1627
+ reasoningTokens: (_r = usageMetadata == null ? void 0 : usageMetadata.thoughtsTokenCount) != null ? _r : void 0,
1628
+ cachedInputTokens: (_s = usageMetadata == null ? void 0 : usageMetadata.cachedContentTokenCount) != null ? _s : void 0
1493
1629
  },
1494
1630
  warnings,
1495
1631
  providerMetadata: {
1496
1632
  google: {
1497
- promptFeedback: (_m = response.promptFeedback) != null ? _m : null,
1498
- groundingMetadata: (_n = candidate == null ? void 0 : candidate.groundingMetadata) != null ? _n : null,
1499
- urlContextMetadata: (_o = candidate == null ? void 0 : candidate.urlContextMetadata) != null ? _o : null,
1500
- safetyRatings: (_p = candidate == null ? void 0 : candidate.safetyRatings) != null ? _p : null,
1501
- serviceTier: (_q = response.serviceTier) != null ? _q : null,
1633
+ promptFeedback: (_t = response.promptFeedback) != null ? _t : null,
1634
+ groundingMetadata: (_u = candidate == null ? void 0 : candidate.groundingMetadata) != null ? _u : null,
1635
+ ...groundingMetadataPerRequest.length > 1 ? { groundingMetadataPerRequest } : {},
1636
+ urlContextMetadata: (_v = candidate == null ? void 0 : candidate.urlContextMetadata) != null ? _v : null,
1637
+ safetyRatings: (_w = candidate == null ? void 0 : candidate.safetyRatings) != null ? _w : null,
1638
+ serviceTier: (_x = response.serviceTier) != null ? _x : null,
1639
+ ...(candidate == null ? void 0 : candidate.continuationToken) != null && candidate.finishReason === "MAX_TOKENS" ? { continuationToken: candidate.continuationToken } : {},
1640
+ ...continuedUsageMetadata != null && firstPromptTokenCount != null ? { initialPromptTokenCount: firstPromptTokenCount } : {},
1502
1641
  usageMetadata: usageMetadata != null ? usageMetadata : null
1503
1642
  }
1504
1643
  },
@@ -1517,17 +1656,40 @@ var GoogleGenerativeAILanguageModel = class {
1517
1656
  await resolve2(this.config.headers),
1518
1657
  options.headers
1519
1658
  );
1520
- const { responseHeaders, value: response } = await postJsonToApi2({
1659
+ const streamGenerateContent = (body2) => postJsonToApi2({
1521
1660
  url: `${this.config.baseURL}/${getModelPath(
1522
1661
  this.modelId
1523
1662
  )}:streamGenerateContent?alt=sse`,
1524
1663
  headers,
1525
- body: args,
1664
+ body: body2,
1526
1665
  failedResponseHandler: googleFailedResponseHandler,
1527
1666
  successfulResponseHandler: createEventSourceResponseHandler(chunkSchema),
1528
1667
  abortSignal: options.abortSignal,
1529
1668
  fetch: this.config.fetch
1530
1669
  });
1670
+ const { responseHeaders, value: firstResponse } = await streamGenerateContent(args);
1671
+ const groundingMetadataPerRequest = [];
1672
+ let requestGroundingMetadata = null;
1673
+ const response = continueGoogleStream({
1674
+ stream: firstResponse,
1675
+ getContinuationToken: (chunk) => {
1676
+ var _a, _b;
1677
+ const candidate = (_a = chunk.candidates) == null ? void 0 : _a[0];
1678
+ if ((candidate == null ? void 0 : candidate.groundingMetadata) != null) {
1679
+ requestGroundingMetadata = candidate.groundingMetadata;
1680
+ }
1681
+ return (candidate == null ? void 0 : candidate.finishReason) === "CONTINUATION" ? (_b = candidate.continuationToken) != null ? _b : void 0 : void 0;
1682
+ },
1683
+ continueStream: async (continuationToken) => {
1684
+ const { value } = await streamGenerateContent({
1685
+ ...args,
1686
+ continuationToken
1687
+ });
1688
+ groundingMetadataPerRequest.push(requestGroundingMetadata);
1689
+ requestGroundingMetadata = null;
1690
+ return value;
1691
+ }
1692
+ });
1531
1693
  let finishReason = "unknown";
1532
1694
  const usage = {
1533
1695
  inputTokens: void 0,
@@ -1538,6 +1700,10 @@ var GoogleGenerativeAILanguageModel = class {
1538
1700
  let lastGroundingMetadata = null;
1539
1701
  let lastUrlContextMetadata = null;
1540
1702
  let serviceTier = null;
1703
+ let requestUsageMetadata;
1704
+ let continuedUsageMetadata;
1705
+ let lastContinuationToken = null;
1706
+ let initialPromptTokenCount = void 0;
1541
1707
  const generateId3 = this.config.generateId;
1542
1708
  let hasToolCalls = false;
1543
1709
  let currentTextBlockId = null;
@@ -1561,7 +1727,13 @@ var GoogleGenerativeAILanguageModel = class {
1561
1727
  return;
1562
1728
  }
1563
1729
  const value = chunk.value;
1564
- const usageMetadata = value.usageMetadata;
1730
+ if (value.usageMetadata != null) {
1731
+ requestUsageMetadata = value.usageMetadata;
1732
+ }
1733
+ const usageMetadata = value.usageMetadata == null ? void 0 : addGoogleGenerativeAIUsageMetadata(
1734
+ continuedUsageMetadata,
1735
+ requestUsageMetadata
1736
+ );
1565
1737
  if (usageMetadata != null) {
1566
1738
  usage.inputTokens = (_a = usageMetadata.promptTokenCount) != null ? _a : void 0;
1567
1739
  usage.outputTokens = (_b = usageMetadata.candidatesTokenCount) != null ? _b : void 0;
@@ -1573,6 +1745,19 @@ var GoogleGenerativeAILanguageModel = class {
1573
1745
  serviceTier = value.serviceTier;
1574
1746
  }
1575
1747
  const candidate = (_f = value.candidates) == null ? void 0 : _f[0];
1748
+ if ((candidate == null ? void 0 : candidate.continuationToken) != null) {
1749
+ lastContinuationToken = candidate.continuationToken;
1750
+ }
1751
+ if ((candidate == null ? void 0 : candidate.finishReason) === "CONTINUATION") {
1752
+ if (continuedUsageMetadata == null) {
1753
+ initialPromptTokenCount = requestUsageMetadata == null ? void 0 : requestUsageMetadata.promptTokenCount;
1754
+ }
1755
+ continuedUsageMetadata = addGoogleGenerativeAIUsageMetadata(
1756
+ continuedUsageMetadata,
1757
+ requestUsageMetadata
1758
+ );
1759
+ requestUsageMetadata = void 0;
1760
+ }
1576
1761
  if (candidate == null) {
1577
1762
  const promptBlockReason2 = (_g = value.promptFeedback) == null ? void 0 : _g.blockReason;
1578
1763
  if (promptBlockReason2 != null) {
@@ -1755,7 +1940,12 @@ var GoogleGenerativeAILanguageModel = class {
1755
1940
  groundingMetadata: lastGroundingMetadata,
1756
1941
  urlContextMetadata: lastUrlContextMetadata,
1757
1942
  safetyRatings: (_o = candidate.safetyRatings) != null ? _o : null,
1758
- serviceTier
1943
+ serviceTier,
1944
+ // Only surface the token when the response stopped early
1945
+ // (budget used up, or continuing failed), not for the
1946
+ // checkpoint tokens of a stream that finished normally.
1947
+ ...lastContinuationToken != null && (rawFinishReason === "MAX_TOKENS" || rawFinishReason === "CONTINUATION") ? { continuationToken: lastContinuationToken } : {},
1948
+ ...initialPromptTokenCount != null ? { initialPromptTokenCount } : {}
1759
1949
  }
1760
1950
  };
1761
1951
  if (usageMetadata != null) {
@@ -1776,6 +1966,18 @@ var GoogleGenerativeAILanguageModel = class {
1776
1966
  id: currentReasoningBlockId
1777
1967
  });
1778
1968
  }
1969
+ if (groundingMetadataPerRequest.length > 0) {
1970
+ providerMetadata = {
1971
+ ...providerMetadata,
1972
+ google: {
1973
+ ...providerMetadata == null ? void 0 : providerMetadata.google,
1974
+ groundingMetadataPerRequest: [
1975
+ ...groundingMetadataPerRequest,
1976
+ requestGroundingMetadata
1977
+ ]
1978
+ }
1979
+ };
1980
+ }
1779
1981
  controller.enqueue({
1780
1982
  type: "finish",
1781
1983
  finishReason,
@@ -2026,6 +2228,7 @@ var responseSchema = lazySchema5(
2026
2228
  z5.object({
2027
2229
  content: getContentSchema().nullish().or(z5.object({}).strict()),
2028
2230
  finishReason: z5.string().nullish(),
2231
+ continuationToken: z5.string().nullish(),
2029
2232
  safetyRatings: z5.array(getSafetyRatingSchema()).nullish(),
2030
2233
  groundingMetadata: getGroundingMetadataSchema().nullish(),
2031
2234
  urlContextMetadata: getUrlContextMetadataSchema().nullish()
@@ -2047,6 +2250,7 @@ var chunkSchema = lazySchema5(
2047
2250
  z5.object({
2048
2251
  content: getContentSchema().nullish(),
2049
2252
  finishReason: z5.string().nullish(),
2253
+ continuationToken: z5.string().nullish(),
2050
2254
  safetyRatings: z5.array(getSafetyRatingSchema()).nullish(),
2051
2255
  groundingMetadata: getGroundingMetadataSchema().nullish(),
2052
2256
  urlContextMetadata: getUrlContextMetadataSchema().nullish()