@ai-sdk/google 2.0.101 → 2.0.103

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.101" : "0.0.0-test";
10
+ var VERSION = true ? "2.0.103" : "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,70 @@ 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;
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
+ let continuedUsageMetadata;
1525
+ const firstPromptTokenCount = (_a = response.usageMetadata) == null ? void 0 : _a.promptTokenCount;
1526
+ while (true) {
1527
+ const candidate2 = (_b = response.candidates) == null ? void 0 : _b[0];
1528
+ const continuationToken = (candidate2 == null ? void 0 : candidate2.finishReason) === "CONTINUATION" ? candidate2.continuationToken : void 0;
1529
+ if (continuationToken == null) {
1530
+ break;
1531
+ }
1532
+ continuedParts.push(...(_d = (_c = candidate2 == null ? void 0 : candidate2.content) == null ? void 0 : _c.parts) != null ? _d : []);
1533
+ continuedUsageMetadata = addGoogleGenerativeAIUsageMetadata(
1534
+ continuedUsageMetadata,
1535
+ (_e = response.usageMetadata) != null ? _e : void 0
1536
+ );
1537
+ ({
1538
+ responseHeaders,
1539
+ value: response,
1540
+ rawValue: rawResponse
1541
+ } = await generateContent({ ...args, continuationToken }));
1542
+ }
1543
+ const candidate = (_f = response.candidates) == null ? void 0 : _f[0];
1544
+ const promptBlockReason = (_g = response.promptFeedback) == null ? void 0 : _g.blockReason;
1414
1545
  const isPromptBlocked = (candidate == null ? void 0 : candidate.finishReason) == null && promptBlockReason != null;
1415
1546
  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;
1547
+ const parts = [...continuedParts, ...(_i = (_h = candidate == null ? void 0 : candidate.content) == null ? void 0 : _h.parts) != null ? _i : []];
1548
+ const usageMetadata = addGoogleGenerativeAIUsageMetadata(
1549
+ continuedUsageMetadata,
1550
+ (_j = response.usageMetadata) != null ? _j : void 0
1551
+ );
1418
1552
  let lastCodeExecutionToolCallId;
1419
1553
  for (const part of parts) {
1420
- if ("executableCode" in part && ((_e = part.executableCode) == null ? void 0 : _e.code)) {
1554
+ if ("executableCode" in part && ((_k = part.executableCode) == null ? void 0 : _k.code)) {
1421
1555
  const toolCallId = this.config.generateId();
1422
1556
  lastCodeExecutionToolCallId = toolCallId;
1423
1557
  content.push({
@@ -1458,7 +1592,7 @@ var GoogleGenerativeAILanguageModel = class {
1458
1592
  } else if ("functionCall" in part) {
1459
1593
  content.push({
1460
1594
  type: "tool-call",
1461
- toolCallId: (_f = part.functionCall.id) != null ? _f : this.config.generateId(),
1595
+ toolCallId: (_l = part.functionCall.id) != null ? _l : this.config.generateId(),
1462
1596
  toolName: part.functionCall.name,
1463
1597
  input: JSON.stringify(part.functionCall.args),
1464
1598
  providerMetadata: part.thoughtSignature ? { google: { thoughtSignature: part.thoughtSignature } } : void 0
@@ -1471,10 +1605,10 @@ var GoogleGenerativeAILanguageModel = class {
1471
1605
  });
1472
1606
  }
1473
1607
  }
1474
- const sources = (_g = extractSources({
1608
+ const sources = (_m = extractSources({
1475
1609
  groundingMetadata: candidate == null ? void 0 : candidate.groundingMetadata,
1476
1610
  generateId: this.config.generateId
1477
- })) != null ? _g : [];
1611
+ })) != null ? _m : [];
1478
1612
  for (const source of sources) {
1479
1613
  content.push(source);
1480
1614
  }
@@ -1485,20 +1619,22 @@ var GoogleGenerativeAILanguageModel = class {
1485
1619
  hasToolCalls: content.some((part) => part.type === "tool-call")
1486
1620
  }),
1487
1621
  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
1622
+ inputTokens: (_n = usageMetadata == null ? void 0 : usageMetadata.promptTokenCount) != null ? _n : void 0,
1623
+ outputTokens: (_o = usageMetadata == null ? void 0 : usageMetadata.candidatesTokenCount) != null ? _o : void 0,
1624
+ totalTokens: (_p = usageMetadata == null ? void 0 : usageMetadata.totalTokenCount) != null ? _p : void 0,
1625
+ reasoningTokens: (_q = usageMetadata == null ? void 0 : usageMetadata.thoughtsTokenCount) != null ? _q : void 0,
1626
+ cachedInputTokens: (_r = usageMetadata == null ? void 0 : usageMetadata.cachedContentTokenCount) != null ? _r : void 0
1493
1627
  },
1494
1628
  warnings,
1495
1629
  providerMetadata: {
1496
1630
  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,
1631
+ promptFeedback: (_s = response.promptFeedback) != null ? _s : null,
1632
+ groundingMetadata: (_t = candidate == null ? void 0 : candidate.groundingMetadata) != null ? _t : null,
1633
+ urlContextMetadata: (_u = candidate == null ? void 0 : candidate.urlContextMetadata) != null ? _u : null,
1634
+ safetyRatings: (_v = candidate == null ? void 0 : candidate.safetyRatings) != null ? _v : null,
1635
+ serviceTier: (_w = response.serviceTier) != null ? _w : null,
1636
+ ...(candidate == null ? void 0 : candidate.continuationToken) != null ? { continuationToken: candidate.continuationToken } : {},
1637
+ ...continuedUsageMetadata != null && firstPromptTokenCount != null ? { initialPromptTokenCount: firstPromptTokenCount } : {},
1502
1638
  usageMetadata: usageMetadata != null ? usageMetadata : null
1503
1639
  }
1504
1640
  },
@@ -1517,17 +1653,27 @@ var GoogleGenerativeAILanguageModel = class {
1517
1653
  await resolve2(this.config.headers),
1518
1654
  options.headers
1519
1655
  );
1520
- const { responseHeaders, value: response } = await postJsonToApi2({
1656
+ const streamGenerateContent = (body2) => postJsonToApi2({
1521
1657
  url: `${this.config.baseURL}/${getModelPath(
1522
1658
  this.modelId
1523
1659
  )}:streamGenerateContent?alt=sse`,
1524
1660
  headers,
1525
- body: args,
1661
+ body: body2,
1526
1662
  failedResponseHandler: googleFailedResponseHandler,
1527
1663
  successfulResponseHandler: createEventSourceResponseHandler(chunkSchema),
1528
1664
  abortSignal: options.abortSignal,
1529
1665
  fetch: this.config.fetch
1530
1666
  });
1667
+ const { responseHeaders, value: firstResponse } = await streamGenerateContent(args);
1668
+ const response = continueGoogleStream({
1669
+ stream: firstResponse,
1670
+ getContinuationToken: (chunk) => {
1671
+ var _a, _b;
1672
+ const candidate = (_a = chunk.candidates) == null ? void 0 : _a[0];
1673
+ return (candidate == null ? void 0 : candidate.finishReason) === "CONTINUATION" ? (_b = candidate.continuationToken) != null ? _b : void 0 : void 0;
1674
+ },
1675
+ continueStream: async (continuationToken) => (await streamGenerateContent({ ...args, continuationToken })).value
1676
+ });
1531
1677
  let finishReason = "unknown";
1532
1678
  const usage = {
1533
1679
  inputTokens: void 0,
@@ -1538,6 +1684,10 @@ var GoogleGenerativeAILanguageModel = class {
1538
1684
  let lastGroundingMetadata = null;
1539
1685
  let lastUrlContextMetadata = null;
1540
1686
  let serviceTier = null;
1687
+ let requestUsageMetadata;
1688
+ let continuedUsageMetadata;
1689
+ let lastContinuationToken = null;
1690
+ let initialPromptTokenCount = void 0;
1541
1691
  const generateId3 = this.config.generateId;
1542
1692
  let hasToolCalls = false;
1543
1693
  let currentTextBlockId = null;
@@ -1561,7 +1711,13 @@ var GoogleGenerativeAILanguageModel = class {
1561
1711
  return;
1562
1712
  }
1563
1713
  const value = chunk.value;
1564
- const usageMetadata = value.usageMetadata;
1714
+ if (value.usageMetadata != null) {
1715
+ requestUsageMetadata = value.usageMetadata;
1716
+ }
1717
+ const usageMetadata = value.usageMetadata == null ? void 0 : addGoogleGenerativeAIUsageMetadata(
1718
+ continuedUsageMetadata,
1719
+ requestUsageMetadata
1720
+ );
1565
1721
  if (usageMetadata != null) {
1566
1722
  usage.inputTokens = (_a = usageMetadata.promptTokenCount) != null ? _a : void 0;
1567
1723
  usage.outputTokens = (_b = usageMetadata.candidatesTokenCount) != null ? _b : void 0;
@@ -1573,6 +1729,19 @@ var GoogleGenerativeAILanguageModel = class {
1573
1729
  serviceTier = value.serviceTier;
1574
1730
  }
1575
1731
  const candidate = (_f = value.candidates) == null ? void 0 : _f[0];
1732
+ if ((candidate == null ? void 0 : candidate.continuationToken) != null) {
1733
+ lastContinuationToken = candidate.continuationToken;
1734
+ }
1735
+ if ((candidate == null ? void 0 : candidate.finishReason) === "CONTINUATION") {
1736
+ if (continuedUsageMetadata == null) {
1737
+ initialPromptTokenCount = requestUsageMetadata == null ? void 0 : requestUsageMetadata.promptTokenCount;
1738
+ }
1739
+ continuedUsageMetadata = addGoogleGenerativeAIUsageMetadata(
1740
+ continuedUsageMetadata,
1741
+ requestUsageMetadata
1742
+ );
1743
+ requestUsageMetadata = void 0;
1744
+ }
1576
1745
  if (candidate == null) {
1577
1746
  const promptBlockReason2 = (_g = value.promptFeedback) == null ? void 0 : _g.blockReason;
1578
1747
  if (promptBlockReason2 != null) {
@@ -1755,7 +1924,12 @@ var GoogleGenerativeAILanguageModel = class {
1755
1924
  groundingMetadata: lastGroundingMetadata,
1756
1925
  urlContextMetadata: lastUrlContextMetadata,
1757
1926
  safetyRatings: (_o = candidate.safetyRatings) != null ? _o : null,
1758
- serviceTier
1927
+ serviceTier,
1928
+ // Only surface the token when the response stopped early
1929
+ // (budget used up, or continuing failed), not for the
1930
+ // checkpoint tokens of a stream that finished normally.
1931
+ ...lastContinuationToken != null && (rawFinishReason === "MAX_TOKENS" || rawFinishReason === "CONTINUATION") ? { continuationToken: lastContinuationToken } : {},
1932
+ ...initialPromptTokenCount != null ? { initialPromptTokenCount } : {}
1759
1933
  }
1760
1934
  };
1761
1935
  if (usageMetadata != null) {
@@ -2026,6 +2200,7 @@ var responseSchema = lazySchema5(
2026
2200
  z5.object({
2027
2201
  content: getContentSchema().nullish().or(z5.object({}).strict()),
2028
2202
  finishReason: z5.string().nullish(),
2203
+ continuationToken: z5.string().nullish(),
2029
2204
  safetyRatings: z5.array(getSafetyRatingSchema()).nullish(),
2030
2205
  groundingMetadata: getGroundingMetadataSchema().nullish(),
2031
2206
  urlContextMetadata: getUrlContextMetadataSchema().nullish()
@@ -2047,6 +2222,7 @@ var chunkSchema = lazySchema5(
2047
2222
  z5.object({
2048
2223
  content: getContentSchema().nullish(),
2049
2224
  finishReason: z5.string().nullish(),
2225
+ continuationToken: z5.string().nullish(),
2050
2226
  safetyRatings: z5.array(getSafetyRatingSchema()).nullish(),
2051
2227
  groundingMetadata: getGroundingMetadataSchema().nullish(),
2052
2228
  urlContextMetadata: getUrlContextMetadataSchema().nullish()