@ai-sdk/google 3.0.143 → 3.0.144

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/google",
3
- "version": "3.0.143",
3
+ "version": "3.0.144",
4
4
  "license": "Apache-2.0",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
@@ -37,7 +37,7 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "@ai-sdk/provider": "3.0.19",
40
- "@ai-sdk/provider-utils": "4.0.65"
40
+ "@ai-sdk/provider-utils": "4.0.66"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "20.17.24",
@@ -657,7 +657,10 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
657
657
  safetyRatings: candidate?.safetyRatings ?? null,
658
658
  usageMetadata: usageMetadata ?? null,
659
659
  finishMessage: candidate?.finishMessage ?? null,
660
- serviceTier: usageMetadata?.serviceTier ?? null,
660
+ serviceTier:
661
+ usageMetadata?.serviceTier ??
662
+ responseHeaders?.['x-gemini-service-tier'] ??
663
+ null,
661
664
  ...(candidate?.continuationToken != null &&
662
665
  rawFinishReason === 'MAX_TOKENS'
663
666
  ? { continuationToken: candidate.continuationToken }
@@ -1351,7 +1354,10 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
1351
1354
  safetyRatings: lastSafetyRatings,
1352
1355
  usageMetadata: usage ?? null,
1353
1356
  finishMessage: lastFinishMessage,
1354
- serviceTier: usage?.serviceTier ?? null,
1357
+ serviceTier:
1358
+ usage?.serviceTier ??
1359
+ responseHeaders?.['x-gemini-service-tier'] ??
1360
+ null,
1355
1361
  // Only surface the token when the response stopped early
1356
1362
  // (budget used up, or continuing failed), not for the
1357
1363
  // checkpoint tokens of a stream that finished normally.
@@ -61,7 +61,7 @@ export class GoogleJSONAccumulator {
61
61
  if (!rawPath || rawPath === '$') continue;
62
62
 
63
63
  const segments = parsePath(rawPath);
64
- if (!hasContiguousIndexes(this.accumulatedArgs, segments)) continue;
64
+ if (!normalizeAndCheckIndexes(this.accumulatedArgs, segments)) continue;
65
65
 
66
66
  const existingValue = getNestedValue(this.accumulatedArgs, segments);
67
67
  const isStringContinuation =
@@ -376,20 +376,35 @@ function getNestedValue(
376
376
  }
377
377
 
378
378
  /**
379
- * Checks that every array index on the path is an existing element or the next
380
- * one. Arrays are streamed in order, and a sparse index would make `finalize()`
381
- * serialize one `null` per hole, so a tiny response could allocate without bound.
379
+ * Normalizes dotted array indexes in place and checks that every array index
380
+ * is an existing element or the next one. Arrays are streamed in order, and a
381
+ * sparse index would make `finalize()` serialize one `null` per hole, so a tiny
382
+ * response could allocate without bound.
382
383
  * A missing or `null` parent is replaced with a new array, so it starts at 0.
383
384
  *
384
385
  * Input: ({items:["a"]}, ["items",1]) or ({items:["a"]}, ["items",5])
385
386
  * Output: true or false
386
387
  */
387
- function hasContiguousIndexes(
388
+ function normalizeAndCheckIndexes(
388
389
  obj: Record<string, unknown>,
389
390
  segments: Array<string | number>,
390
391
  ): boolean {
391
392
  let current: unknown = obj;
392
- for (const pathSegment of segments) {
393
+ for (let i = 0; i < segments.length; i++) {
394
+ let pathSegment = segments[i];
395
+ if (Array.isArray(current) && typeof pathSegment === 'string') {
396
+ const index = Number(pathSegment);
397
+ // Only canonical array-index keys affect length. Keep object keys as strings.
398
+ if (
399
+ Number.isInteger(index) &&
400
+ index >= 0 &&
401
+ index < 2 ** 32 - 1 &&
402
+ String(index) === pathSegment
403
+ ) {
404
+ pathSegment = index;
405
+ segments[i] = index;
406
+ }
407
+ }
393
408
  if (typeof pathSegment === 'number') {
394
409
  const length = Array.isArray(current)
395
410
  ? current.length