@ai-sdk/google 4.0.2 → 4.0.3
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 +9 -0
- package/dist/index.js +83 -31
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/src/google-video-model.ts +120 -36
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/google",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -35,16 +35,16 @@
|
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@ai-sdk/provider": "4.0.
|
|
39
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
38
|
+
"@ai-sdk/provider": "4.0.1",
|
|
39
|
+
"@ai-sdk/provider-utils": "5.0.2"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/node": "22.19.19",
|
|
43
43
|
"tsup": "^8.5.1",
|
|
44
44
|
"typescript": "5.8.3",
|
|
45
45
|
"zod": "3.25.76",
|
|
46
|
-
"@
|
|
47
|
-
"@ai-
|
|
46
|
+
"@ai-sdk/test-server": "2.0.0",
|
|
47
|
+
"@vercel/ai-tsconfig": "0.0.0"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"zod": "^3.25.76 || ^4.1.8"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AISDKError,
|
|
3
3
|
type Experimental_VideoModelV4,
|
|
4
|
+
type Experimental_VideoModelV4File,
|
|
4
5
|
type SharedV4Warning,
|
|
5
6
|
} from '@ai-sdk/provider';
|
|
6
7
|
import {
|
|
@@ -35,6 +36,103 @@ interface GoogleVideoModelConfig {
|
|
|
35
36
|
};
|
|
36
37
|
}
|
|
37
38
|
|
|
39
|
+
function getFirstFrameImage(
|
|
40
|
+
options: Parameters<Experimental_VideoModelV4['doGenerate']>[0],
|
|
41
|
+
): Experimental_VideoModelV4File | undefined {
|
|
42
|
+
return options.frameImages?.find(frame => frame.frameType === 'first_frame')
|
|
43
|
+
?.image;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function resolveStartImage(
|
|
47
|
+
options: Parameters<Experimental_VideoModelV4['doGenerate']>[0],
|
|
48
|
+
): Experimental_VideoModelV4File | undefined {
|
|
49
|
+
return getFirstFrameImage(options) ?? options.image;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function getLastFrameImage(
|
|
53
|
+
options: Parameters<Experimental_VideoModelV4['doGenerate']>[0],
|
|
54
|
+
): Experimental_VideoModelV4File | undefined {
|
|
55
|
+
return options.frameImages?.find(frame => frame.frameType === 'last_frame')
|
|
56
|
+
?.image;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function getInputReferences(
|
|
60
|
+
options: Parameters<Experimental_VideoModelV4['doGenerate']>[0],
|
|
61
|
+
): Array<Experimental_VideoModelV4File> | undefined {
|
|
62
|
+
if (options.frameImages != null && options.frameImages.length > 0) {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return options.inputReferences != null && options.inputReferences.length > 0
|
|
67
|
+
? options.inputReferences
|
|
68
|
+
: undefined;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function convertFileToGoogleImage(
|
|
72
|
+
file: Experimental_VideoModelV4File,
|
|
73
|
+
warnings: SharedV4Warning[],
|
|
74
|
+
): Record<string, unknown> | undefined {
|
|
75
|
+
if (file.type === 'url') {
|
|
76
|
+
if (file.url.startsWith('gs://')) {
|
|
77
|
+
return {
|
|
78
|
+
gcsUri: file.url,
|
|
79
|
+
mimeType: 'image/png',
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
warnings.push({
|
|
84
|
+
type: 'unsupported',
|
|
85
|
+
feature: 'URL-based image input',
|
|
86
|
+
details:
|
|
87
|
+
'Google Generative AI video models require base64-encoded images or GCS URIs. URL will be ignored.',
|
|
88
|
+
});
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const base64Data =
|
|
93
|
+
typeof file.data === 'string'
|
|
94
|
+
? file.data
|
|
95
|
+
: convertUint8ArrayToBase64(file.data);
|
|
96
|
+
|
|
97
|
+
// The Gemini Developer API (generativelanguage.googleapis.com) requires
|
|
98
|
+
// inline image bytes wrapped as `inlineData`.
|
|
99
|
+
return {
|
|
100
|
+
inlineData: {
|
|
101
|
+
mimeType: file.mediaType || 'image/png',
|
|
102
|
+
data: base64Data,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function convertProviderReferenceImage(
|
|
108
|
+
refImg: NonNullable<GoogleVideoModelOptions['referenceImages']>[number],
|
|
109
|
+
): Record<string, unknown> {
|
|
110
|
+
if (refImg.bytesBase64Encoded) {
|
|
111
|
+
return {
|
|
112
|
+
inlineData: {
|
|
113
|
+
mimeType: 'image/png',
|
|
114
|
+
data: refImg.bytesBase64Encoded,
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (refImg.gcsUri) {
|
|
120
|
+
return {
|
|
121
|
+
gcsUri: refImg.gcsUri,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return refImg;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function convertInputReferenceImage(
|
|
129
|
+
file: Experimental_VideoModelV4File,
|
|
130
|
+
warnings: SharedV4Warning[],
|
|
131
|
+
): Record<string, unknown> | undefined {
|
|
132
|
+
const image = convertFileToGoogleImage(file, warnings);
|
|
133
|
+
return image != null ? { image, referenceType: 'asset' } : undefined;
|
|
134
|
+
}
|
|
135
|
+
|
|
38
136
|
export class GoogleVideoModel implements Experimental_VideoModelV4 {
|
|
39
137
|
readonly specificationVersion = 'v4';
|
|
40
138
|
|
|
@@ -71,46 +169,32 @@ export class GoogleVideoModel implements Experimental_VideoModelV4 {
|
|
|
71
169
|
instance.prompt = options.prompt;
|
|
72
170
|
}
|
|
73
171
|
|
|
74
|
-
|
|
75
|
-
if (
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
feature: 'URL-based image input',
|
|
80
|
-
details:
|
|
81
|
-
'Google Generative AI video models require base64-encoded images. URL will be ignored.',
|
|
82
|
-
});
|
|
83
|
-
} else {
|
|
84
|
-
const base64Data =
|
|
85
|
-
typeof options.image.data === 'string'
|
|
86
|
-
? options.image.data
|
|
87
|
-
: convertUint8ArrayToBase64(options.image.data);
|
|
88
|
-
|
|
89
|
-
instance.image = {
|
|
90
|
-
inlineData: {
|
|
91
|
-
mimeType: options.image.mediaType || 'image/png',
|
|
92
|
-
data: base64Data,
|
|
93
|
-
},
|
|
94
|
-
};
|
|
172
|
+
const startImage = resolveStartImage(options);
|
|
173
|
+
if (startImage != null) {
|
|
174
|
+
const image = convertFileToGoogleImage(startImage, warnings);
|
|
175
|
+
if (image != null) {
|
|
176
|
+
instance.image = image;
|
|
95
177
|
}
|
|
96
178
|
}
|
|
97
179
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
return refImg;
|
|
180
|
+
const lastFrameImage = getLastFrameImage(options);
|
|
181
|
+
if (lastFrameImage != null) {
|
|
182
|
+
const lastFrame = convertFileToGoogleImage(lastFrameImage, warnings);
|
|
183
|
+
if (lastFrame != null) {
|
|
184
|
+
instance.lastFrame = lastFrame;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const inputReferences = getInputReferences(options);
|
|
189
|
+
if (inputReferences != null) {
|
|
190
|
+
instance.referenceImages = inputReferences.flatMap(reference => {
|
|
191
|
+
const converted = convertInputReferenceImage(reference, warnings);
|
|
192
|
+
return converted != null ? [converted] : [];
|
|
113
193
|
});
|
|
194
|
+
} else if (googleOptions?.referenceImages != null) {
|
|
195
|
+
instance.referenceImages = googleOptions.referenceImages.map(refImg =>
|
|
196
|
+
convertProviderReferenceImage(refImg),
|
|
197
|
+
);
|
|
114
198
|
}
|
|
115
199
|
|
|
116
200
|
const parameters: Record<string, unknown> = {
|