@ai-sdk/google 3.0.86 → 3.0.88

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.86",
3
+ "version": "3.0.88",
4
4
  "license": "Apache-2.0",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
@@ -36,16 +36,16 @@
36
36
  }
37
37
  },
38
38
  "dependencies": {
39
- "@ai-sdk/provider": "3.0.12",
40
- "@ai-sdk/provider-utils": "4.0.33"
39
+ "@ai-sdk/provider": "3.0.13",
40
+ "@ai-sdk/provider-utils": "4.0.35"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "20.17.24",
44
44
  "tsup": "^8",
45
45
  "typescript": "5.8.3",
46
46
  "zod": "3.25.76",
47
- "@ai-sdk/test-server": "1.0.6",
48
- "@vercel/ai-tsconfig": "0.0.0"
47
+ "@vercel/ai-tsconfig": "0.0.0",
48
+ "@ai-sdk/test-server": "1.0.6"
49
49
  },
50
50
  "peerDependencies": {
51
51
  "zod": "^3.25.76 || ^4.1.8"
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  AISDKError,
3
3
  type Experimental_VideoModelV3,
4
+ type Experimental_VideoModelV3File,
4
5
  type SharedV3Warning,
5
6
  } from '@ai-sdk/provider';
6
7
  import {
@@ -51,6 +52,103 @@ interface GoogleGenerativeAIVideoModelConfig {
51
52
  };
52
53
  }
53
54
 
55
+ function getFirstFrameImage(
56
+ options: Parameters<Experimental_VideoModelV3['doGenerate']>[0],
57
+ ): Experimental_VideoModelV3File | undefined {
58
+ return options.frameImages?.find(frame => frame.frameType === 'first_frame')
59
+ ?.image;
60
+ }
61
+
62
+ function resolveStartImage(
63
+ options: Parameters<Experimental_VideoModelV3['doGenerate']>[0],
64
+ ): Experimental_VideoModelV3File | undefined {
65
+ return getFirstFrameImage(options) ?? options.image;
66
+ }
67
+
68
+ function getLastFrameImage(
69
+ options: Parameters<Experimental_VideoModelV3['doGenerate']>[0],
70
+ ): Experimental_VideoModelV3File | undefined {
71
+ return options.frameImages?.find(frame => frame.frameType === 'last_frame')
72
+ ?.image;
73
+ }
74
+
75
+ function getInputReferences(
76
+ options: Parameters<Experimental_VideoModelV3['doGenerate']>[0],
77
+ ): Array<Experimental_VideoModelV3File> | undefined {
78
+ if (options.frameImages != null && options.frameImages.length > 0) {
79
+ return undefined;
80
+ }
81
+
82
+ return options.inputReferences != null && options.inputReferences.length > 0
83
+ ? options.inputReferences
84
+ : undefined;
85
+ }
86
+
87
+ function convertFileToGoogleImage(
88
+ file: Experimental_VideoModelV3File,
89
+ warnings: SharedV3Warning[],
90
+ ): Record<string, unknown> | undefined {
91
+ if (file.type === 'url') {
92
+ if (file.url.startsWith('gs://')) {
93
+ return {
94
+ gcsUri: file.url,
95
+ mimeType: 'image/png',
96
+ };
97
+ }
98
+
99
+ warnings.push({
100
+ type: 'unsupported',
101
+ feature: 'URL-based image input',
102
+ details:
103
+ 'Google Generative AI video models require base64-encoded images or GCS URIs. URL will be ignored.',
104
+ });
105
+ return undefined;
106
+ }
107
+
108
+ const base64Data =
109
+ typeof file.data === 'string'
110
+ ? file.data
111
+ : convertUint8ArrayToBase64(file.data);
112
+
113
+ // The Gemini Developer API (generativelanguage.googleapis.com) requires
114
+ // inline image bytes wrapped as `inlineData`.
115
+ return {
116
+ inlineData: {
117
+ mimeType: file.mediaType || 'image/png',
118
+ data: base64Data,
119
+ },
120
+ };
121
+ }
122
+
123
+ function convertProviderReferenceImage(
124
+ refImg: NonNullable<GoogleVideoModelOptions['referenceImages']>[number],
125
+ ): Record<string, unknown> {
126
+ if (refImg.bytesBase64Encoded) {
127
+ return {
128
+ inlineData: {
129
+ mimeType: 'image/png',
130
+ data: refImg.bytesBase64Encoded,
131
+ },
132
+ };
133
+ }
134
+
135
+ if (refImg.gcsUri) {
136
+ return {
137
+ gcsUri: refImg.gcsUri,
138
+ };
139
+ }
140
+
141
+ return refImg;
142
+ }
143
+
144
+ function convertInputReferenceImage(
145
+ file: Experimental_VideoModelV3File,
146
+ warnings: SharedV3Warning[],
147
+ ): Record<string, unknown> | undefined {
148
+ const image = convertFileToGoogleImage(file, warnings);
149
+ return image != null ? { image, referenceType: 'asset' } : undefined;
150
+ }
151
+
54
152
  export class GoogleGenerativeAIVideoModel implements Experimental_VideoModelV3 {
55
153
  readonly specificationVersion = 'v3';
56
154
 
@@ -87,46 +185,32 @@ export class GoogleGenerativeAIVideoModel implements Experimental_VideoModelV3 {
87
185
  instance.prompt = options.prompt;
88
186
  }
89
187
 
90
- // Handle image-to-video: convert image to base64
91
- if (options.image != null) {
92
- if (options.image.type === 'url') {
93
- warnings.push({
94
- type: 'unsupported',
95
- feature: 'URL-based image input',
96
- details:
97
- 'Google Generative AI video models require base64-encoded images. URL will be ignored.',
98
- });
99
- } else {
100
- const base64Data =
101
- typeof options.image.data === 'string'
102
- ? options.image.data
103
- : convertUint8ArrayToBase64(options.image.data);
104
-
105
- instance.image = {
106
- inlineData: {
107
- mimeType: options.image.mediaType || 'image/png',
108
- data: base64Data,
109
- },
110
- };
188
+ const startImage = resolveStartImage(options);
189
+ if (startImage != null) {
190
+ const image = convertFileToGoogleImage(startImage, warnings);
191
+ if (image != null) {
192
+ instance.image = image;
111
193
  }
112
194
  }
113
195
 
114
- if (googleOptions?.referenceImages != null) {
115
- instance.referenceImages = googleOptions.referenceImages.map(refImg => {
116
- if (refImg.bytesBase64Encoded) {
117
- return {
118
- inlineData: {
119
- mimeType: 'image/png',
120
- data: refImg.bytesBase64Encoded,
121
- },
122
- };
123
- } else if (refImg.gcsUri) {
124
- return {
125
- gcsUri: refImg.gcsUri,
126
- };
127
- }
128
- return refImg;
196
+ const lastFrameImage = getLastFrameImage(options);
197
+ if (lastFrameImage != null) {
198
+ const lastFrame = convertFileToGoogleImage(lastFrameImage, warnings);
199
+ if (lastFrame != null) {
200
+ instance.lastFrame = lastFrame;
201
+ }
202
+ }
203
+
204
+ const inputReferences = getInputReferences(options);
205
+ if (inputReferences != null) {
206
+ instance.referenceImages = inputReferences.flatMap(reference => {
207
+ const converted = convertInputReferenceImage(reference, warnings);
208
+ return converted != null ? [converted] : [];
129
209
  });
210
+ } else if (googleOptions?.referenceImages != null) {
211
+ instance.referenceImages = googleOptions.referenceImages.map(refImg =>
212
+ convertProviderReferenceImage(refImg),
213
+ );
130
214
  }
131
215
 
132
216
  const parameters: Record<string, unknown> = {