@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.
@@ -12,6 +12,100 @@ import {
12
12
  } from "@ai-sdk/provider-utils";
13
13
  import { z as z3 } from "zod/v4";
14
14
 
15
+ // src/add-google-generative-ai-usage-metadata.ts
16
+ function addGoogleGenerativeAIUsageMetadata(a, b) {
17
+ if (a == null || b == null) {
18
+ return b != null ? b : a;
19
+ }
20
+ return {
21
+ ...a,
22
+ ...b,
23
+ promptTokenCount: addCounts(a.promptTokenCount, b.promptTokenCount),
24
+ candidatesTokenCount: addCounts(
25
+ a.candidatesTokenCount,
26
+ b.candidatesTokenCount
27
+ ),
28
+ totalTokenCount: addCounts(a.totalTokenCount, b.totalTokenCount),
29
+ cachedContentTokenCount: addCounts(
30
+ a.cachedContentTokenCount,
31
+ b.cachedContentTokenCount
32
+ ),
33
+ thoughtsTokenCount: addCounts(a.thoughtsTokenCount, b.thoughtsTokenCount),
34
+ promptTokensDetails: addTokenDetails(
35
+ a.promptTokensDetails,
36
+ b.promptTokensDetails
37
+ ),
38
+ candidatesTokensDetails: addTokenDetails(
39
+ a.candidatesTokensDetails,
40
+ b.candidatesTokensDetails
41
+ )
42
+ };
43
+ }
44
+ function addCounts(a, b) {
45
+ return a == null && b == null ? b != null ? b : a : (a != null ? a : 0) + (b != null ? b : 0);
46
+ }
47
+ function addTokenDetails(a, b) {
48
+ var _a;
49
+ if (a == null || b == null) {
50
+ return b != null ? b : a;
51
+ }
52
+ const tokenCounts = /* @__PURE__ */ new Map();
53
+ for (const { modality, tokenCount } of [...a, ...b]) {
54
+ tokenCounts.set(modality, ((_a = tokenCounts.get(modality)) != null ? _a : 0) + tokenCount);
55
+ }
56
+ return Array.from(tokenCounts, ([modality, tokenCount]) => ({
57
+ modality,
58
+ tokenCount
59
+ }));
60
+ }
61
+
62
+ // src/continue-google-stream.ts
63
+ function continueGoogleStream({
64
+ stream,
65
+ getContinuationToken,
66
+ continueStream
67
+ }) {
68
+ let reader = stream.getReader();
69
+ let pendingContinuationToken;
70
+ return new ReadableStream({
71
+ async pull(controller) {
72
+ while (true) {
73
+ const { done, value } = await reader.read();
74
+ if (!done) {
75
+ if (value.success) {
76
+ const token = getContinuationToken(value.value);
77
+ if (token != null) {
78
+ pendingContinuationToken = token;
79
+ }
80
+ }
81
+ controller.enqueue(value);
82
+ return;
83
+ }
84
+ if (pendingContinuationToken == null) {
85
+ controller.close();
86
+ return;
87
+ }
88
+ const continuationToken = pendingContinuationToken;
89
+ pendingContinuationToken = void 0;
90
+ try {
91
+ reader = (await continueStream(continuationToken)).getReader();
92
+ } catch (error) {
93
+ controller.enqueue({
94
+ success: false,
95
+ error,
96
+ rawValue: void 0
97
+ });
98
+ controller.close();
99
+ return;
100
+ }
101
+ }
102
+ },
103
+ async cancel(reason) {
104
+ await reader.cancel(reason);
105
+ }
106
+ });
107
+ }
108
+
15
109
  // src/convert-json-schema-to-openapi-schema.ts
16
110
  import {
17
111
  UnsupportedFunctionalityError
@@ -698,7 +792,17 @@ var googleGenerativeAIProviderOptions = lazySchema2(
698
792
  /**
699
793
  * Optional. The service tier to use for the request.
700
794
  */
701
- serviceTier: z2.enum(["standard", "flex", "priority"]).optional()
795
+ serviceTier: z2.enum(["standard", "flex", "priority"]).optional(),
796
+ /**
797
+ * Optional. Resumes a response that stopped with `MAX_TOKENS` because it
798
+ * used up its `maxOutputTokens` budget (Gemini 4 long decode). Pass the
799
+ * `continuationToken` from the previous response's provider metadata
800
+ * together with the original prompt and a higher `maxOutputTokens` (the
801
+ * budget is cumulative across requests). Requests that reach the
802
+ * per-request cap while budget remains (`CONTINUATION`) are continued
803
+ * automatically. Sent as the `continuationToken` body field.
804
+ */
805
+ continuationToken: z2.string().optional()
702
806
  })
703
807
  )
704
808
  );
@@ -998,6 +1102,9 @@ function mapGoogleGenerativeAIFinishReason({
998
1102
  case "STOP":
999
1103
  return hasToolCalls ? "tool-calls" : "stop";
1000
1104
  case "MAX_TOKENS":
1105
+ // Gemini 4 long decode: the per-request cap was reached while budget
1106
+ // remains. Continued automatically; only surfaced if continuing fails.
1107
+ case "CONTINUATION":
1001
1108
  return "length";
1002
1109
  case "IMAGE_SAFETY":
1003
1110
  case "RECITATION":
@@ -1172,43 +1279,72 @@ var GoogleGenerativeAILanguageModel = class {
1172
1279
  } : googleToolConfig,
1173
1280
  cachedContent: googleOptions == null ? void 0 : googleOptions.cachedContent,
1174
1281
  labels: googleOptions == null ? void 0 : googleOptions.labels,
1175
- serviceTier: sanitizedServiceTier
1282
+ serviceTier: sanitizedServiceTier,
1283
+ ...(googleOptions == null ? void 0 : googleOptions.continuationToken) != null && {
1284
+ continuationToken: googleOptions.continuationToken
1285
+ }
1176
1286
  },
1177
1287
  warnings: [...warnings, ...toolWarnings]
1178
1288
  };
1179
1289
  }
1180
1290
  async doGenerate(options) {
1181
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
1291
+ 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;
1182
1292
  const { args, warnings } = await this.getArgs(options);
1183
1293
  const body = JSON.stringify(args);
1184
1294
  const mergedHeaders = combineHeaders(
1185
1295
  await resolve(this.config.headers),
1186
1296
  options.headers
1187
1297
  );
1188
- const {
1189
- responseHeaders,
1190
- value: response,
1191
- rawValue: rawResponse
1192
- } = await postJsonToApi({
1298
+ const generateContent = (body2) => postJsonToApi({
1193
1299
  url: `${this.config.baseURL}/${getModelPath(
1194
1300
  this.modelId
1195
1301
  )}:generateContent`,
1196
1302
  headers: mergedHeaders,
1197
- body: args,
1303
+ body: body2,
1198
1304
  failedResponseHandler: googleFailedResponseHandler,
1199
1305
  successfulResponseHandler: createJsonResponseHandler(responseSchema),
1200
1306
  abortSignal: options.abortSignal,
1201
1307
  fetch: this.config.fetch
1202
1308
  });
1203
- const candidate = (_a = response.candidates) == null ? void 0 : _a[0];
1204
- const promptBlockReason = (_b = response.promptFeedback) == null ? void 0 : _b.blockReason;
1309
+ let {
1310
+ responseHeaders,
1311
+ value: response,
1312
+ rawValue: rawResponse
1313
+ } = await generateContent(args);
1314
+ const continuedParts = [];
1315
+ const groundingMetadataPerRequest = [];
1316
+ let continuedUsageMetadata;
1317
+ const firstPromptTokenCount = (_a = response.usageMetadata) == null ? void 0 : _a.promptTokenCount;
1318
+ while (true) {
1319
+ const candidate2 = (_b = response.candidates) == null ? void 0 : _b[0];
1320
+ groundingMetadataPerRequest.push((_c = candidate2 == null ? void 0 : candidate2.groundingMetadata) != null ? _c : null);
1321
+ const continuationToken = (candidate2 == null ? void 0 : candidate2.finishReason) === "CONTINUATION" ? candidate2.continuationToken : void 0;
1322
+ if (continuationToken == null) {
1323
+ break;
1324
+ }
1325
+ continuedParts.push(...(_e = (_d = candidate2 == null ? void 0 : candidate2.content) == null ? void 0 : _d.parts) != null ? _e : []);
1326
+ continuedUsageMetadata = addGoogleGenerativeAIUsageMetadata(
1327
+ continuedUsageMetadata,
1328
+ (_f = response.usageMetadata) != null ? _f : void 0
1329
+ );
1330
+ ({
1331
+ responseHeaders,
1332
+ value: response,
1333
+ rawValue: rawResponse
1334
+ } = await generateContent({ ...args, continuationToken }));
1335
+ }
1336
+ const candidate = (_g = response.candidates) == null ? void 0 : _g[0];
1337
+ const promptBlockReason = (_h = response.promptFeedback) == null ? void 0 : _h.blockReason;
1205
1338
  const isPromptBlocked = (candidate == null ? void 0 : candidate.finishReason) == null && promptBlockReason != null;
1206
1339
  const content = [];
1207
- const parts = (_d = (_c = candidate == null ? void 0 : candidate.content) == null ? void 0 : _c.parts) != null ? _d : [];
1208
- const usageMetadata = response.usageMetadata;
1340
+ const parts = [...continuedParts, ...(_j = (_i = candidate == null ? void 0 : candidate.content) == null ? void 0 : _i.parts) != null ? _j : []];
1341
+ const usageMetadata = addGoogleGenerativeAIUsageMetadata(
1342
+ continuedUsageMetadata,
1343
+ (_k = response.usageMetadata) != null ? _k : void 0
1344
+ );
1209
1345
  let lastCodeExecutionToolCallId;
1210
1346
  for (const part of parts) {
1211
- if ("executableCode" in part && ((_e = part.executableCode) == null ? void 0 : _e.code)) {
1347
+ if ("executableCode" in part && ((_l = part.executableCode) == null ? void 0 : _l.code)) {
1212
1348
  const toolCallId = this.config.generateId();
1213
1349
  lastCodeExecutionToolCallId = toolCallId;
1214
1350
  content.push({
@@ -1249,7 +1385,7 @@ var GoogleGenerativeAILanguageModel = class {
1249
1385
  } else if ("functionCall" in part) {
1250
1386
  content.push({
1251
1387
  type: "tool-call",
1252
- toolCallId: (_f = part.functionCall.id) != null ? _f : this.config.generateId(),
1388
+ toolCallId: (_m = part.functionCall.id) != null ? _m : this.config.generateId(),
1253
1389
  toolName: part.functionCall.name,
1254
1390
  input: JSON.stringify(part.functionCall.args),
1255
1391
  providerMetadata: part.thoughtSignature ? { google: { thoughtSignature: part.thoughtSignature } } : void 0
@@ -1262,10 +1398,10 @@ var GoogleGenerativeAILanguageModel = class {
1262
1398
  });
1263
1399
  }
1264
1400
  }
1265
- const sources = (_g = extractSources({
1401
+ const sources = (_n = extractSources({
1266
1402
  groundingMetadata: candidate == null ? void 0 : candidate.groundingMetadata,
1267
1403
  generateId: this.config.generateId
1268
- })) != null ? _g : [];
1404
+ })) != null ? _n : [];
1269
1405
  for (const source of sources) {
1270
1406
  content.push(source);
1271
1407
  }
@@ -1276,20 +1412,23 @@ var GoogleGenerativeAILanguageModel = class {
1276
1412
  hasToolCalls: content.some((part) => part.type === "tool-call")
1277
1413
  }),
1278
1414
  usage: {
1279
- inputTokens: (_h = usageMetadata == null ? void 0 : usageMetadata.promptTokenCount) != null ? _h : void 0,
1280
- outputTokens: (_i = usageMetadata == null ? void 0 : usageMetadata.candidatesTokenCount) != null ? _i : void 0,
1281
- totalTokens: (_j = usageMetadata == null ? void 0 : usageMetadata.totalTokenCount) != null ? _j : void 0,
1282
- reasoningTokens: (_k = usageMetadata == null ? void 0 : usageMetadata.thoughtsTokenCount) != null ? _k : void 0,
1283
- cachedInputTokens: (_l = usageMetadata == null ? void 0 : usageMetadata.cachedContentTokenCount) != null ? _l : void 0
1415
+ inputTokens: (_o = usageMetadata == null ? void 0 : usageMetadata.promptTokenCount) != null ? _o : void 0,
1416
+ outputTokens: (_p = usageMetadata == null ? void 0 : usageMetadata.candidatesTokenCount) != null ? _p : void 0,
1417
+ totalTokens: (_q = usageMetadata == null ? void 0 : usageMetadata.totalTokenCount) != null ? _q : void 0,
1418
+ reasoningTokens: (_r = usageMetadata == null ? void 0 : usageMetadata.thoughtsTokenCount) != null ? _r : void 0,
1419
+ cachedInputTokens: (_s = usageMetadata == null ? void 0 : usageMetadata.cachedContentTokenCount) != null ? _s : void 0
1284
1420
  },
1285
1421
  warnings,
1286
1422
  providerMetadata: {
1287
1423
  google: {
1288
- promptFeedback: (_m = response.promptFeedback) != null ? _m : null,
1289
- groundingMetadata: (_n = candidate == null ? void 0 : candidate.groundingMetadata) != null ? _n : null,
1290
- urlContextMetadata: (_o = candidate == null ? void 0 : candidate.urlContextMetadata) != null ? _o : null,
1291
- safetyRatings: (_p = candidate == null ? void 0 : candidate.safetyRatings) != null ? _p : null,
1292
- serviceTier: (_q = response.serviceTier) != null ? _q : null,
1424
+ promptFeedback: (_t = response.promptFeedback) != null ? _t : null,
1425
+ groundingMetadata: (_u = candidate == null ? void 0 : candidate.groundingMetadata) != null ? _u : null,
1426
+ ...groundingMetadataPerRequest.length > 1 ? { groundingMetadataPerRequest } : {},
1427
+ urlContextMetadata: (_v = candidate == null ? void 0 : candidate.urlContextMetadata) != null ? _v : null,
1428
+ safetyRatings: (_w = candidate == null ? void 0 : candidate.safetyRatings) != null ? _w : null,
1429
+ serviceTier: (_x = response.serviceTier) != null ? _x : null,
1430
+ ...(candidate == null ? void 0 : candidate.continuationToken) != null && candidate.finishReason === "MAX_TOKENS" ? { continuationToken: candidate.continuationToken } : {},
1431
+ ...continuedUsageMetadata != null && firstPromptTokenCount != null ? { initialPromptTokenCount: firstPromptTokenCount } : {},
1293
1432
  usageMetadata: usageMetadata != null ? usageMetadata : null
1294
1433
  }
1295
1434
  },
@@ -1308,17 +1447,40 @@ var GoogleGenerativeAILanguageModel = class {
1308
1447
  await resolve(this.config.headers),
1309
1448
  options.headers
1310
1449
  );
1311
- const { responseHeaders, value: response } = await postJsonToApi({
1450
+ const streamGenerateContent = (body2) => postJsonToApi({
1312
1451
  url: `${this.config.baseURL}/${getModelPath(
1313
1452
  this.modelId
1314
1453
  )}:streamGenerateContent?alt=sse`,
1315
1454
  headers,
1316
- body: args,
1455
+ body: body2,
1317
1456
  failedResponseHandler: googleFailedResponseHandler,
1318
1457
  successfulResponseHandler: createEventSourceResponseHandler(chunkSchema),
1319
1458
  abortSignal: options.abortSignal,
1320
1459
  fetch: this.config.fetch
1321
1460
  });
1461
+ const { responseHeaders, value: firstResponse } = await streamGenerateContent(args);
1462
+ const groundingMetadataPerRequest = [];
1463
+ let requestGroundingMetadata = null;
1464
+ const response = continueGoogleStream({
1465
+ stream: firstResponse,
1466
+ getContinuationToken: (chunk) => {
1467
+ var _a, _b;
1468
+ const candidate = (_a = chunk.candidates) == null ? void 0 : _a[0];
1469
+ if ((candidate == null ? void 0 : candidate.groundingMetadata) != null) {
1470
+ requestGroundingMetadata = candidate.groundingMetadata;
1471
+ }
1472
+ return (candidate == null ? void 0 : candidate.finishReason) === "CONTINUATION" ? (_b = candidate.continuationToken) != null ? _b : void 0 : void 0;
1473
+ },
1474
+ continueStream: async (continuationToken) => {
1475
+ const { value } = await streamGenerateContent({
1476
+ ...args,
1477
+ continuationToken
1478
+ });
1479
+ groundingMetadataPerRequest.push(requestGroundingMetadata);
1480
+ requestGroundingMetadata = null;
1481
+ return value;
1482
+ }
1483
+ });
1322
1484
  let finishReason = "unknown";
1323
1485
  const usage = {
1324
1486
  inputTokens: void 0,
@@ -1329,6 +1491,10 @@ var GoogleGenerativeAILanguageModel = class {
1329
1491
  let lastGroundingMetadata = null;
1330
1492
  let lastUrlContextMetadata = null;
1331
1493
  let serviceTier = null;
1494
+ let requestUsageMetadata;
1495
+ let continuedUsageMetadata;
1496
+ let lastContinuationToken = null;
1497
+ let initialPromptTokenCount = void 0;
1332
1498
  const generateId2 = this.config.generateId;
1333
1499
  let hasToolCalls = false;
1334
1500
  let currentTextBlockId = null;
@@ -1352,7 +1518,13 @@ var GoogleGenerativeAILanguageModel = class {
1352
1518
  return;
1353
1519
  }
1354
1520
  const value = chunk.value;
1355
- const usageMetadata = value.usageMetadata;
1521
+ if (value.usageMetadata != null) {
1522
+ requestUsageMetadata = value.usageMetadata;
1523
+ }
1524
+ const usageMetadata = value.usageMetadata == null ? void 0 : addGoogleGenerativeAIUsageMetadata(
1525
+ continuedUsageMetadata,
1526
+ requestUsageMetadata
1527
+ );
1356
1528
  if (usageMetadata != null) {
1357
1529
  usage.inputTokens = (_a = usageMetadata.promptTokenCount) != null ? _a : void 0;
1358
1530
  usage.outputTokens = (_b = usageMetadata.candidatesTokenCount) != null ? _b : void 0;
@@ -1364,6 +1536,19 @@ var GoogleGenerativeAILanguageModel = class {
1364
1536
  serviceTier = value.serviceTier;
1365
1537
  }
1366
1538
  const candidate = (_f = value.candidates) == null ? void 0 : _f[0];
1539
+ if ((candidate == null ? void 0 : candidate.continuationToken) != null) {
1540
+ lastContinuationToken = candidate.continuationToken;
1541
+ }
1542
+ if ((candidate == null ? void 0 : candidate.finishReason) === "CONTINUATION") {
1543
+ if (continuedUsageMetadata == null) {
1544
+ initialPromptTokenCount = requestUsageMetadata == null ? void 0 : requestUsageMetadata.promptTokenCount;
1545
+ }
1546
+ continuedUsageMetadata = addGoogleGenerativeAIUsageMetadata(
1547
+ continuedUsageMetadata,
1548
+ requestUsageMetadata
1549
+ );
1550
+ requestUsageMetadata = void 0;
1551
+ }
1367
1552
  if (candidate == null) {
1368
1553
  const promptBlockReason2 = (_g = value.promptFeedback) == null ? void 0 : _g.blockReason;
1369
1554
  if (promptBlockReason2 != null) {
@@ -1546,7 +1731,12 @@ var GoogleGenerativeAILanguageModel = class {
1546
1731
  groundingMetadata: lastGroundingMetadata,
1547
1732
  urlContextMetadata: lastUrlContextMetadata,
1548
1733
  safetyRatings: (_o = candidate.safetyRatings) != null ? _o : null,
1549
- serviceTier
1734
+ serviceTier,
1735
+ // Only surface the token when the response stopped early
1736
+ // (budget used up, or continuing failed), not for the
1737
+ // checkpoint tokens of a stream that finished normally.
1738
+ ...lastContinuationToken != null && (rawFinishReason === "MAX_TOKENS" || rawFinishReason === "CONTINUATION") ? { continuationToken: lastContinuationToken } : {},
1739
+ ...initialPromptTokenCount != null ? { initialPromptTokenCount } : {}
1550
1740
  }
1551
1741
  };
1552
1742
  if (usageMetadata != null) {
@@ -1567,6 +1757,18 @@ var GoogleGenerativeAILanguageModel = class {
1567
1757
  id: currentReasoningBlockId
1568
1758
  });
1569
1759
  }
1760
+ if (groundingMetadataPerRequest.length > 0) {
1761
+ providerMetadata = {
1762
+ ...providerMetadata,
1763
+ google: {
1764
+ ...providerMetadata == null ? void 0 : providerMetadata.google,
1765
+ groundingMetadataPerRequest: [
1766
+ ...groundingMetadataPerRequest,
1767
+ requestGroundingMetadata
1768
+ ]
1769
+ }
1770
+ };
1771
+ }
1570
1772
  controller.enqueue({
1571
1773
  type: "finish",
1572
1774
  finishReason,
@@ -1817,6 +2019,7 @@ var responseSchema = lazySchema3(
1817
2019
  z3.object({
1818
2020
  content: getContentSchema().nullish().or(z3.object({}).strict()),
1819
2021
  finishReason: z3.string().nullish(),
2022
+ continuationToken: z3.string().nullish(),
1820
2023
  safetyRatings: z3.array(getSafetyRatingSchema()).nullish(),
1821
2024
  groundingMetadata: getGroundingMetadataSchema().nullish(),
1822
2025
  urlContextMetadata: getUrlContextMetadataSchema().nullish()
@@ -1838,6 +2041,7 @@ var chunkSchema = lazySchema3(
1838
2041
  z3.object({
1839
2042
  content: getContentSchema().nullish(),
1840
2043
  finishReason: z3.string().nullish(),
2044
+ continuationToken: z3.string().nullish(),
1841
2045
  safetyRatings: z3.array(getSafetyRatingSchema()).nullish(),
1842
2046
  groundingMetadata: getGroundingMetadataSchema().nullish(),
1843
2047
  urlContextMetadata: getUrlContextMetadataSchema().nullish()