@ai-sdk/google 2.0.102 → 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.
@@ -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,70 @@ 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;
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
+ let continuedUsageMetadata;
1316
+ const firstPromptTokenCount = (_a = response.usageMetadata) == null ? void 0 : _a.promptTokenCount;
1317
+ while (true) {
1318
+ const candidate2 = (_b = response.candidates) == null ? void 0 : _b[0];
1319
+ const continuationToken = (candidate2 == null ? void 0 : candidate2.finishReason) === "CONTINUATION" ? candidate2.continuationToken : void 0;
1320
+ if (continuationToken == null) {
1321
+ break;
1322
+ }
1323
+ continuedParts.push(...(_d = (_c = candidate2 == null ? void 0 : candidate2.content) == null ? void 0 : _c.parts) != null ? _d : []);
1324
+ continuedUsageMetadata = addGoogleGenerativeAIUsageMetadata(
1325
+ continuedUsageMetadata,
1326
+ (_e = response.usageMetadata) != null ? _e : void 0
1327
+ );
1328
+ ({
1329
+ responseHeaders,
1330
+ value: response,
1331
+ rawValue: rawResponse
1332
+ } = await generateContent({ ...args, continuationToken }));
1333
+ }
1334
+ const candidate = (_f = response.candidates) == null ? void 0 : _f[0];
1335
+ const promptBlockReason = (_g = response.promptFeedback) == null ? void 0 : _g.blockReason;
1205
1336
  const isPromptBlocked = (candidate == null ? void 0 : candidate.finishReason) == null && promptBlockReason != null;
1206
1337
  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;
1338
+ const parts = [...continuedParts, ...(_i = (_h = candidate == null ? void 0 : candidate.content) == null ? void 0 : _h.parts) != null ? _i : []];
1339
+ const usageMetadata = addGoogleGenerativeAIUsageMetadata(
1340
+ continuedUsageMetadata,
1341
+ (_j = response.usageMetadata) != null ? _j : void 0
1342
+ );
1209
1343
  let lastCodeExecutionToolCallId;
1210
1344
  for (const part of parts) {
1211
- if ("executableCode" in part && ((_e = part.executableCode) == null ? void 0 : _e.code)) {
1345
+ if ("executableCode" in part && ((_k = part.executableCode) == null ? void 0 : _k.code)) {
1212
1346
  const toolCallId = this.config.generateId();
1213
1347
  lastCodeExecutionToolCallId = toolCallId;
1214
1348
  content.push({
@@ -1249,7 +1383,7 @@ var GoogleGenerativeAILanguageModel = class {
1249
1383
  } else if ("functionCall" in part) {
1250
1384
  content.push({
1251
1385
  type: "tool-call",
1252
- toolCallId: (_f = part.functionCall.id) != null ? _f : this.config.generateId(),
1386
+ toolCallId: (_l = part.functionCall.id) != null ? _l : this.config.generateId(),
1253
1387
  toolName: part.functionCall.name,
1254
1388
  input: JSON.stringify(part.functionCall.args),
1255
1389
  providerMetadata: part.thoughtSignature ? { google: { thoughtSignature: part.thoughtSignature } } : void 0
@@ -1262,10 +1396,10 @@ var GoogleGenerativeAILanguageModel = class {
1262
1396
  });
1263
1397
  }
1264
1398
  }
1265
- const sources = (_g = extractSources({
1399
+ const sources = (_m = extractSources({
1266
1400
  groundingMetadata: candidate == null ? void 0 : candidate.groundingMetadata,
1267
1401
  generateId: this.config.generateId
1268
- })) != null ? _g : [];
1402
+ })) != null ? _m : [];
1269
1403
  for (const source of sources) {
1270
1404
  content.push(source);
1271
1405
  }
@@ -1276,20 +1410,22 @@ var GoogleGenerativeAILanguageModel = class {
1276
1410
  hasToolCalls: content.some((part) => part.type === "tool-call")
1277
1411
  }),
1278
1412
  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
1413
+ inputTokens: (_n = usageMetadata == null ? void 0 : usageMetadata.promptTokenCount) != null ? _n : void 0,
1414
+ outputTokens: (_o = usageMetadata == null ? void 0 : usageMetadata.candidatesTokenCount) != null ? _o : void 0,
1415
+ totalTokens: (_p = usageMetadata == null ? void 0 : usageMetadata.totalTokenCount) != null ? _p : void 0,
1416
+ reasoningTokens: (_q = usageMetadata == null ? void 0 : usageMetadata.thoughtsTokenCount) != null ? _q : void 0,
1417
+ cachedInputTokens: (_r = usageMetadata == null ? void 0 : usageMetadata.cachedContentTokenCount) != null ? _r : void 0
1284
1418
  },
1285
1419
  warnings,
1286
1420
  providerMetadata: {
1287
1421
  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,
1422
+ promptFeedback: (_s = response.promptFeedback) != null ? _s : null,
1423
+ groundingMetadata: (_t = candidate == null ? void 0 : candidate.groundingMetadata) != null ? _t : null,
1424
+ urlContextMetadata: (_u = candidate == null ? void 0 : candidate.urlContextMetadata) != null ? _u : null,
1425
+ safetyRatings: (_v = candidate == null ? void 0 : candidate.safetyRatings) != null ? _v : null,
1426
+ serviceTier: (_w = response.serviceTier) != null ? _w : null,
1427
+ ...(candidate == null ? void 0 : candidate.continuationToken) != null ? { continuationToken: candidate.continuationToken } : {},
1428
+ ...continuedUsageMetadata != null && firstPromptTokenCount != null ? { initialPromptTokenCount: firstPromptTokenCount } : {},
1293
1429
  usageMetadata: usageMetadata != null ? usageMetadata : null
1294
1430
  }
1295
1431
  },
@@ -1308,17 +1444,27 @@ var GoogleGenerativeAILanguageModel = class {
1308
1444
  await resolve(this.config.headers),
1309
1445
  options.headers
1310
1446
  );
1311
- const { responseHeaders, value: response } = await postJsonToApi({
1447
+ const streamGenerateContent = (body2) => postJsonToApi({
1312
1448
  url: `${this.config.baseURL}/${getModelPath(
1313
1449
  this.modelId
1314
1450
  )}:streamGenerateContent?alt=sse`,
1315
1451
  headers,
1316
- body: args,
1452
+ body: body2,
1317
1453
  failedResponseHandler: googleFailedResponseHandler,
1318
1454
  successfulResponseHandler: createEventSourceResponseHandler(chunkSchema),
1319
1455
  abortSignal: options.abortSignal,
1320
1456
  fetch: this.config.fetch
1321
1457
  });
1458
+ const { responseHeaders, value: firstResponse } = await streamGenerateContent(args);
1459
+ const response = continueGoogleStream({
1460
+ stream: firstResponse,
1461
+ getContinuationToken: (chunk) => {
1462
+ var _a, _b;
1463
+ const candidate = (_a = chunk.candidates) == null ? void 0 : _a[0];
1464
+ return (candidate == null ? void 0 : candidate.finishReason) === "CONTINUATION" ? (_b = candidate.continuationToken) != null ? _b : void 0 : void 0;
1465
+ },
1466
+ continueStream: async (continuationToken) => (await streamGenerateContent({ ...args, continuationToken })).value
1467
+ });
1322
1468
  let finishReason = "unknown";
1323
1469
  const usage = {
1324
1470
  inputTokens: void 0,
@@ -1329,6 +1475,10 @@ var GoogleGenerativeAILanguageModel = class {
1329
1475
  let lastGroundingMetadata = null;
1330
1476
  let lastUrlContextMetadata = null;
1331
1477
  let serviceTier = null;
1478
+ let requestUsageMetadata;
1479
+ let continuedUsageMetadata;
1480
+ let lastContinuationToken = null;
1481
+ let initialPromptTokenCount = void 0;
1332
1482
  const generateId2 = this.config.generateId;
1333
1483
  let hasToolCalls = false;
1334
1484
  let currentTextBlockId = null;
@@ -1352,7 +1502,13 @@ var GoogleGenerativeAILanguageModel = class {
1352
1502
  return;
1353
1503
  }
1354
1504
  const value = chunk.value;
1355
- const usageMetadata = value.usageMetadata;
1505
+ if (value.usageMetadata != null) {
1506
+ requestUsageMetadata = value.usageMetadata;
1507
+ }
1508
+ const usageMetadata = value.usageMetadata == null ? void 0 : addGoogleGenerativeAIUsageMetadata(
1509
+ continuedUsageMetadata,
1510
+ requestUsageMetadata
1511
+ );
1356
1512
  if (usageMetadata != null) {
1357
1513
  usage.inputTokens = (_a = usageMetadata.promptTokenCount) != null ? _a : void 0;
1358
1514
  usage.outputTokens = (_b = usageMetadata.candidatesTokenCount) != null ? _b : void 0;
@@ -1364,6 +1520,19 @@ var GoogleGenerativeAILanguageModel = class {
1364
1520
  serviceTier = value.serviceTier;
1365
1521
  }
1366
1522
  const candidate = (_f = value.candidates) == null ? void 0 : _f[0];
1523
+ if ((candidate == null ? void 0 : candidate.continuationToken) != null) {
1524
+ lastContinuationToken = candidate.continuationToken;
1525
+ }
1526
+ if ((candidate == null ? void 0 : candidate.finishReason) === "CONTINUATION") {
1527
+ if (continuedUsageMetadata == null) {
1528
+ initialPromptTokenCount = requestUsageMetadata == null ? void 0 : requestUsageMetadata.promptTokenCount;
1529
+ }
1530
+ continuedUsageMetadata = addGoogleGenerativeAIUsageMetadata(
1531
+ continuedUsageMetadata,
1532
+ requestUsageMetadata
1533
+ );
1534
+ requestUsageMetadata = void 0;
1535
+ }
1367
1536
  if (candidate == null) {
1368
1537
  const promptBlockReason2 = (_g = value.promptFeedback) == null ? void 0 : _g.blockReason;
1369
1538
  if (promptBlockReason2 != null) {
@@ -1546,7 +1715,12 @@ var GoogleGenerativeAILanguageModel = class {
1546
1715
  groundingMetadata: lastGroundingMetadata,
1547
1716
  urlContextMetadata: lastUrlContextMetadata,
1548
1717
  safetyRatings: (_o = candidate.safetyRatings) != null ? _o : null,
1549
- serviceTier
1718
+ serviceTier,
1719
+ // Only surface the token when the response stopped early
1720
+ // (budget used up, or continuing failed), not for the
1721
+ // checkpoint tokens of a stream that finished normally.
1722
+ ...lastContinuationToken != null && (rawFinishReason === "MAX_TOKENS" || rawFinishReason === "CONTINUATION") ? { continuationToken: lastContinuationToken } : {},
1723
+ ...initialPromptTokenCount != null ? { initialPromptTokenCount } : {}
1550
1724
  }
1551
1725
  };
1552
1726
  if (usageMetadata != null) {
@@ -1817,6 +1991,7 @@ var responseSchema = lazySchema3(
1817
1991
  z3.object({
1818
1992
  content: getContentSchema().nullish().or(z3.object({}).strict()),
1819
1993
  finishReason: z3.string().nullish(),
1994
+ continuationToken: z3.string().nullish(),
1820
1995
  safetyRatings: z3.array(getSafetyRatingSchema()).nullish(),
1821
1996
  groundingMetadata: getGroundingMetadataSchema().nullish(),
1822
1997
  urlContextMetadata: getUrlContextMetadataSchema().nullish()
@@ -1838,6 +2013,7 @@ var chunkSchema = lazySchema3(
1838
2013
  z3.object({
1839
2014
  content: getContentSchema().nullish(),
1840
2015
  finishReason: z3.string().nullish(),
2016
+ continuationToken: z3.string().nullish(),
1841
2017
  safetyRatings: z3.array(getSafetyRatingSchema()).nullish(),
1842
2018
  groundingMetadata: getGroundingMetadataSchema().nullish(),
1843
2019
  urlContextMetadata: getUrlContextMetadataSchema().nullish()