@ai-sdk/google 4.0.3 → 4.0.5
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/CHANGELOG.md +13 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +90 -18
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/interactions/build-google-interactions-stream-transform.ts +43 -1
- package/src/interactions/convert-google-interactions-usage.ts +22 -0
- package/src/interactions/google-interactions-api.ts +24 -0
- package/src/interactions/google-interactions-language-model.ts +9 -1
- package/src/interactions/google-interactions-provider-metadata.ts +8 -0
- package/src/interactions/parse-google-interactions-outputs.ts +21 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/google",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@ai-sdk/provider": "4.0.1",
|
|
39
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
39
|
+
"@ai-sdk/provider-utils": "5.0.3"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/node": "22.19.19",
|
|
@@ -11,7 +11,10 @@ import type {
|
|
|
11
11
|
GoogleInteractionsEvent,
|
|
12
12
|
GoogleInteractionsUsage,
|
|
13
13
|
} from './google-interactions-api';
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
convertGoogleInteractionsUsage,
|
|
16
|
+
getGoogleInteractionsOutputTokensByModality,
|
|
17
|
+
} from './convert-google-interactions-usage';
|
|
15
18
|
import {
|
|
16
19
|
annotationsToSources,
|
|
17
20
|
builtinToolResultToSources,
|
|
@@ -478,6 +481,41 @@ export function buildGoogleInteractionsStreamTransform({
|
|
|
478
481
|
break;
|
|
479
482
|
}
|
|
480
483
|
|
|
484
|
+
/*
|
|
485
|
+
* `video` deltas inside `model_output` carry the full payload in a
|
|
486
|
+
* single chunk (no per-byte streaming), mirroring `image`. Emit the
|
|
487
|
+
* `file` part as soon as the delta arrives so it surfaces regardless
|
|
488
|
+
* of whether a text block is currently open at the same index.
|
|
489
|
+
*/
|
|
490
|
+
if (
|
|
491
|
+
dtype === 'video' &&
|
|
492
|
+
(open.kind === 'pending_model_output' || open.kind === 'text')
|
|
493
|
+
) {
|
|
494
|
+
const videoDelta = event.delta as
|
|
495
|
+
| { data?: string; mime_type?: string; uri?: string }
|
|
496
|
+
| undefined;
|
|
497
|
+
const google: Record<string, string> = {};
|
|
498
|
+
if (interactionId != null) google.interactionId = interactionId;
|
|
499
|
+
const providerMetadata =
|
|
500
|
+
Object.keys(google).length > 0 ? { google } : undefined;
|
|
501
|
+
if (videoDelta?.data != null && videoDelta.data.length > 0) {
|
|
502
|
+
controller.enqueue({
|
|
503
|
+
type: 'file',
|
|
504
|
+
mediaType: videoDelta.mime_type ?? 'video/mp4',
|
|
505
|
+
data: { type: 'data', data: videoDelta.data },
|
|
506
|
+
...(providerMetadata ? { providerMetadata } : {}),
|
|
507
|
+
});
|
|
508
|
+
} else if (videoDelta?.uri != null && videoDelta.uri.length > 0) {
|
|
509
|
+
controller.enqueue({
|
|
510
|
+
type: 'file',
|
|
511
|
+
mediaType: videoDelta.mime_type ?? 'video/mp4',
|
|
512
|
+
data: { type: 'url', url: new URL(videoDelta.uri) },
|
|
513
|
+
...(providerMetadata ? { providerMetadata } : {}),
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
break;
|
|
517
|
+
}
|
|
518
|
+
|
|
481
519
|
const delta = event.delta as
|
|
482
520
|
| {
|
|
483
521
|
type?: string;
|
|
@@ -800,10 +838,14 @@ export function buildGoogleInteractionsStreamTransform({
|
|
|
800
838
|
raw: finishStatus,
|
|
801
839
|
};
|
|
802
840
|
|
|
841
|
+
const outputTokensByModality =
|
|
842
|
+
getGoogleInteractionsOutputTokensByModality(usage);
|
|
843
|
+
|
|
803
844
|
const providerMetadata: SharedV4ProviderMetadata = {
|
|
804
845
|
google: {
|
|
805
846
|
...(interactionId != null ? { interactionId } : {}),
|
|
806
847
|
...(serviceTier != null ? { serviceTier } : {}),
|
|
848
|
+
...(outputTokensByModality != null ? { outputTokensByModality } : {}),
|
|
807
849
|
},
|
|
808
850
|
};
|
|
809
851
|
|
|
@@ -45,3 +45,25 @@ export function convertGoogleInteractionsUsage(
|
|
|
45
45
|
raw: usage as unknown as JSONObject,
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Extracts the per-modality output token breakdown from an Interactions usage
|
|
51
|
+
* record (e.g. `{ video: 57920, text: 12 }`).
|
|
52
|
+
*/
|
|
53
|
+
export function getGoogleInteractionsOutputTokensByModality(
|
|
54
|
+
usage: GoogleInteractionsUsage | undefined | null,
|
|
55
|
+
): Record<string, number> | undefined {
|
|
56
|
+
const byModality = usage?.output_tokens_by_modality;
|
|
57
|
+
if (byModality == null) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const result: Record<string, number> = {};
|
|
62
|
+
for (const entry of byModality) {
|
|
63
|
+
if (entry?.modality != null && entry.tokens != null) {
|
|
64
|
+
result[entry.modality] = entry.tokens;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
69
|
+
}
|
|
@@ -140,9 +140,19 @@ const contentBlockSchema = () => {
|
|
|
140
140
|
})
|
|
141
141
|
.loose();
|
|
142
142
|
|
|
143
|
+
const videoContent = z
|
|
144
|
+
.object({
|
|
145
|
+
type: z.literal('video'),
|
|
146
|
+
data: z.string().nullish(),
|
|
147
|
+
mime_type: z.string().nullish(),
|
|
148
|
+
uri: z.string().nullish(),
|
|
149
|
+
})
|
|
150
|
+
.loose();
|
|
151
|
+
|
|
143
152
|
return z.union([
|
|
144
153
|
textContent,
|
|
145
154
|
imageContent,
|
|
155
|
+
videoContent,
|
|
146
156
|
z.object({ type: z.string() }).loose(),
|
|
147
157
|
]);
|
|
148
158
|
};
|
|
@@ -384,6 +394,19 @@ export const googleInteractionsEventSchema = lazySchema(() =>
|
|
|
384
394
|
})
|
|
385
395
|
.loose();
|
|
386
396
|
|
|
397
|
+
/*
|
|
398
|
+
* `video` deltas carry the entire payload per delta (`data` base64 +
|
|
399
|
+
* `mime_type`, or `uri`) — there is no per-byte streaming.
|
|
400
|
+
*/
|
|
401
|
+
const stepDeltaVideo = z
|
|
402
|
+
.object({
|
|
403
|
+
type: z.literal('video'),
|
|
404
|
+
data: z.string().nullish(),
|
|
405
|
+
mime_type: z.string().nullish(),
|
|
406
|
+
uri: z.string().nullish(),
|
|
407
|
+
})
|
|
408
|
+
.loose();
|
|
409
|
+
|
|
387
410
|
/*
|
|
388
411
|
* Built-in tool call/result step deltas mirror the shape of their step
|
|
389
412
|
* counterparts (full payload per delta — there is no per-token
|
|
@@ -419,6 +442,7 @@ export const googleInteractionsEventSchema = lazySchema(() =>
|
|
|
419
442
|
const stepDeltaUnion = z.union([
|
|
420
443
|
stepDeltaText,
|
|
421
444
|
stepDeltaImage,
|
|
445
|
+
stepDeltaVideo,
|
|
422
446
|
stepDeltaThoughtSummary,
|
|
423
447
|
stepDeltaThoughtSignature,
|
|
424
448
|
stepDeltaArgumentsDelta,
|
|
@@ -23,7 +23,10 @@ import {
|
|
|
23
23
|
} from '@ai-sdk/provider-utils';
|
|
24
24
|
import { googleFailedResponseHandler } from '../google-error';
|
|
25
25
|
import { buildGoogleInteractionsStreamTransform } from './build-google-interactions-stream-transform';
|
|
26
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
convertGoogleInteractionsUsage,
|
|
28
|
+
getGoogleInteractionsOutputTokensByModality,
|
|
29
|
+
} from './convert-google-interactions-usage';
|
|
27
30
|
import { convertToGoogleInteractionsInput } from './convert-to-google-interactions-input';
|
|
28
31
|
import {
|
|
29
32
|
googleInteractionsEventSchema,
|
|
@@ -546,10 +549,15 @@ export class GoogleInteractionsLanguageModel implements LanguageModelV4 {
|
|
|
546
549
|
* `response.id` is omitted when `store: false` (fully stateless mode), so
|
|
547
550
|
* `interactionId` is only surfaced when the API actually returned one.
|
|
548
551
|
*/
|
|
552
|
+
const outputTokensByModality = getGoogleInteractionsOutputTokensByModality(
|
|
553
|
+
response.usage,
|
|
554
|
+
);
|
|
555
|
+
|
|
549
556
|
const providerMetadata: SharedV4ProviderMetadata = {
|
|
550
557
|
google: {
|
|
551
558
|
...(interactionId != null ? { interactionId } : {}),
|
|
552
559
|
...(serviceTier != null ? { serviceTier } : {}),
|
|
560
|
+
...(outputTokensByModality != null ? { outputTokensByModality } : {}),
|
|
553
561
|
},
|
|
554
562
|
};
|
|
555
563
|
|
|
@@ -15,6 +15,14 @@ export type GoogleInteractionsProviderMetadata = {
|
|
|
15
15
|
*/
|
|
16
16
|
serviceTier?: string;
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Output token counts keyed by modality (e.g. `{ video: 57920 }`), sourced
|
|
20
|
+
* from the Interactions API `output_tokens_by_modality`. Present only when
|
|
21
|
+
* the response reports a breakdown. Preview surface for per-modality billing;
|
|
22
|
+
* may be promoted to a first-class usage field later.
|
|
23
|
+
*/
|
|
24
|
+
outputTokensByModality?: Record<string, number>;
|
|
25
|
+
|
|
18
26
|
/**
|
|
19
27
|
* Per-block signature hash for backend validation. Set by the SDK on output
|
|
20
28
|
* reasoning / tool-call parts and round-tripped on input parts.
|
|
@@ -151,6 +151,27 @@ export function parseGoogleInteractionsOutputs({
|
|
|
151
151
|
...googleProviderMetadata({ interactionId }),
|
|
152
152
|
});
|
|
153
153
|
}
|
|
154
|
+
} else if (blockType === 'video') {
|
|
155
|
+
const video = block as {
|
|
156
|
+
data?: string;
|
|
157
|
+
mime_type?: string;
|
|
158
|
+
uri?: string;
|
|
159
|
+
};
|
|
160
|
+
if (video.data != null && video.data.length > 0) {
|
|
161
|
+
content.push({
|
|
162
|
+
type: 'file',
|
|
163
|
+
mediaType: video.mime_type ?? 'video/mp4',
|
|
164
|
+
data: { type: 'data', data: video.data },
|
|
165
|
+
...googleProviderMetadata({ interactionId }),
|
|
166
|
+
});
|
|
167
|
+
} else if (video.uri != null && video.uri.length > 0) {
|
|
168
|
+
content.push({
|
|
169
|
+
type: 'file',
|
|
170
|
+
mediaType: video.mime_type ?? 'video/mp4',
|
|
171
|
+
data: { type: 'url', url: new URL(video.uri) },
|
|
172
|
+
...googleProviderMetadata({ interactionId }),
|
|
173
|
+
});
|
|
174
|
+
}
|
|
154
175
|
}
|
|
155
176
|
}
|
|
156
177
|
break;
|