@ai-sdk/google 4.0.31 → 4.0.33

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": "4.0.31",
3
+ "version": "4.0.33",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -35,8 +35,8 @@
35
35
  }
36
36
  },
37
37
  "dependencies": {
38
- "@ai-sdk/provider": "4.0.4",
39
- "@ai-sdk/provider-utils": "5.0.18"
38
+ "@ai-sdk/provider": "4.0.5",
39
+ "@ai-sdk/provider-utils": "5.0.20"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/node": "22.19.19",
@@ -1,14 +1,17 @@
1
1
  import {
2
2
  AISDKError,
3
3
  type Experimental_VideoModelV4,
4
+ type Experimental_VideoModelV4CallOptions as VideoModelV4CallOptions,
4
5
  type Experimental_VideoModelV4File,
6
+ type Experimental_VideoModelV4OperationStartResult as VideoModelV4OperationStartResult,
7
+ type Experimental_VideoModelV4OperationStatusResult as VideoModelV4OperationStatusResult,
8
+ type SharedV4ProviderMetadata,
5
9
  type SharedV4Warning,
6
10
  } from '@ai-sdk/provider';
7
11
  import {
8
12
  combineHeaders,
9
13
  convertUint8ArrayToBase64,
10
14
  createJsonResponseHandler,
11
- delay,
12
15
  getFromApi,
13
16
  isSameOrigin,
14
17
  parseProviderOptions,
@@ -25,6 +28,8 @@ import {
25
28
  } from './google-video-model-options';
26
29
  import type { GoogleVideoModelId } from './google-video-settings';
27
30
 
31
+ type VideoModelV4 = Experimental_VideoModelV4;
32
+
28
33
  interface GoogleVideoModelConfig {
29
34
  provider: string;
30
35
  baseURL: string;
@@ -37,27 +42,27 @@ interface GoogleVideoModelConfig {
37
42
  }
38
43
 
39
44
  function getFirstFrameImage(
40
- options: Parameters<Experimental_VideoModelV4['doGenerate']>[0],
45
+ options: VideoModelV4CallOptions,
41
46
  ): Experimental_VideoModelV4File | undefined {
42
47
  return options.frameImages?.find(frame => frame.frameType === 'first_frame')
43
48
  ?.image;
44
49
  }
45
50
 
46
51
  function resolveStartImage(
47
- options: Parameters<Experimental_VideoModelV4['doGenerate']>[0],
52
+ options: VideoModelV4CallOptions,
48
53
  ): Experimental_VideoModelV4File | undefined {
49
54
  return getFirstFrameImage(options) ?? options.image;
50
55
  }
51
56
 
52
57
  function getLastFrameImage(
53
- options: Parameters<Experimental_VideoModelV4['doGenerate']>[0],
58
+ options: VideoModelV4CallOptions,
54
59
  ): Experimental_VideoModelV4File | undefined {
55
60
  return options.frameImages?.find(frame => frame.frameType === 'last_frame')
56
61
  ?.image;
57
62
  }
58
63
 
59
64
  function getInputReferences(
60
- options: Parameters<Experimental_VideoModelV4['doGenerate']>[0],
65
+ options: VideoModelV4CallOptions,
61
66
  ): Array<Experimental_VideoModelV4File> | undefined {
62
67
  if (options.frameImages != null && options.frameImages.length > 0) {
63
68
  return undefined;
@@ -153,10 +158,14 @@ export class GoogleVideoModel implements Experimental_VideoModelV4 {
153
158
  private readonly config: GoogleVideoModelConfig,
154
159
  ) {}
155
160
 
156
- async doGenerate(
157
- options: Parameters<Experimental_VideoModelV4['doGenerate']>[0],
158
- ): Promise<Awaited<ReturnType<Experimental_VideoModelV4['doGenerate']>>> {
159
- const currentDate = this.config._internal?.currentDate?.() ?? new Date();
161
+ private async buildRequest(
162
+ options: Parameters<NonNullable<VideoModelV4['doStart']>>[0],
163
+ ): Promise<{
164
+ instances: Array<Record<string, unknown>>;
165
+ parameters: Record<string, unknown>;
166
+ warnings: SharedV4Warning[];
167
+ googleOptions: GoogleVideoModelOptions | undefined;
168
+ }> {
160
169
  const warnings: SharedV4Warning[] = [];
161
170
 
162
171
  const googleOptions = (await parseProviderOptions({
@@ -254,83 +263,25 @@ export class GoogleVideoModel implements Experimental_VideoModelV4 {
254
263
  }
255
264
  }
256
265
 
257
- const { value: operation } = await postJsonToApi({
258
- url: `${this.config.baseURL}/models/${this.modelId}:predictLongRunning`,
259
- headers: combineHeaders(
260
- await resolve(this.config.headers),
261
- options.headers,
262
- ),
263
- body: {
264
- instances,
265
- parameters,
266
- },
267
- successfulResponseHandler: createJsonResponseHandler(
268
- googleOperationSchema,
269
- ),
270
- failedResponseHandler: googleFailedResponseHandler,
271
- abortSignal: options.abortSignal,
272
- fetch: this.config.fetch,
273
- });
274
-
275
- const operationName = operation.name;
276
- if (!operationName) {
277
- throw new AISDKError({
278
- name: 'GOOGLE_VIDEO_GENERATION_ERROR',
279
- message: 'No operation name returned from API',
280
- });
281
- }
282
-
283
- const pollIntervalMs = googleOptions?.pollIntervalMs ?? 10000; // 10 seconds (per Google docs)
284
- const pollTimeoutMs = googleOptions?.pollTimeoutMs ?? 600000; // 10 minutes
285
-
286
- const startTime = Date.now();
287
- let finalOperation = operation;
288
- let responseHeaders: Record<string, string> | undefined;
289
-
290
- while (!finalOperation.done) {
291
- if (Date.now() - startTime > pollTimeoutMs) {
292
- throw new AISDKError({
293
- name: 'GOOGLE_VIDEO_GENERATION_TIMEOUT',
294
- message: `Video generation timed out after ${pollTimeoutMs}ms`,
295
- });
296
- }
297
-
298
- await delay(pollIntervalMs);
299
-
300
- if (options.abortSignal?.aborted) {
301
- throw new AISDKError({
302
- name: 'GOOGLE_VIDEO_GENERATION_ABORTED',
303
- message: 'Video generation request was aborted',
304
- });
305
- }
306
-
307
- const { value: statusOperation, responseHeaders: pollHeaders } =
308
- await getFromApi({
309
- url: `${this.config.baseURL}/${operationName}`,
310
- validateUrl: false,
311
- headers: combineHeaders(
312
- await resolve(this.config.headers),
313
- options.headers,
314
- ),
315
- successfulResponseHandler: createJsonResponseHandler(
316
- googleOperationSchema,
317
- ),
318
- failedResponseHandler: googleFailedResponseHandler,
319
- abortSignal: options.abortSignal,
320
- fetch: this.config.fetch,
321
- });
322
-
323
- finalOperation = statusOperation;
324
- responseHeaders = pollHeaders;
325
- }
326
-
327
- if (finalOperation.error) {
328
- throw new AISDKError({
329
- name: 'GOOGLE_VIDEO_GENERATION_FAILED',
330
- message: `Video generation failed: ${finalOperation.error.message}`,
331
- });
332
- }
266
+ return { instances, parameters, warnings, googleOptions };
267
+ }
333
268
 
269
+ private async buildCompletedResult(
270
+ finalOperation: z.infer<typeof googleOperationSchema>,
271
+ responseHeaders: Record<string, string> | undefined,
272
+ warnings: SharedV4Warning[],
273
+ currentDate: Date,
274
+ ): Promise<{
275
+ status: 'completed';
276
+ videos: Array<{ type: 'url'; url: string; mediaType: string }>;
277
+ warnings: SharedV4Warning[];
278
+ providerMetadata: SharedV4ProviderMetadata;
279
+ response: {
280
+ timestamp: Date;
281
+ modelId: string;
282
+ headers: Record<string, string> | undefined;
283
+ };
284
+ }> {
334
285
  const response = finalOperation.response;
335
286
  if (
336
287
  !response?.generateVideoResponse?.generatedSamples ||
@@ -379,6 +330,7 @@ export class GoogleVideoModel implements Experimental_VideoModelV4 {
379
330
  }
380
331
 
381
332
  return {
333
+ status: 'completed',
382
334
  videos,
383
335
  warnings,
384
336
  response: {
@@ -393,6 +345,102 @@ export class GoogleVideoModel implements Experimental_VideoModelV4 {
393
345
  },
394
346
  };
395
347
  }
348
+
349
+ async doStart(
350
+ options: Parameters<NonNullable<VideoModelV4['doStart']>>[0],
351
+ ): Promise<VideoModelV4OperationStartResult> {
352
+ const currentDate = this.config._internal?.currentDate?.() ?? new Date();
353
+ const { instances, parameters, warnings } =
354
+ await this.buildRequest(options);
355
+
356
+ const { value: operation, responseHeaders } = await postJsonToApi({
357
+ url: `${this.config.baseURL}/models/${this.modelId}:predictLongRunning`,
358
+ headers: combineHeaders(
359
+ await resolve(this.config.headers),
360
+ options.headers,
361
+ ),
362
+ body: {
363
+ instances,
364
+ parameters,
365
+ },
366
+ successfulResponseHandler: createJsonResponseHandler(
367
+ googleOperationSchema,
368
+ ),
369
+ failedResponseHandler: googleFailedResponseHandler,
370
+ abortSignal: options.abortSignal,
371
+ fetch: this.config.fetch,
372
+ });
373
+
374
+ const operationName = operation.name;
375
+ if (!operationName) {
376
+ throw new AISDKError({
377
+ name: 'GOOGLE_VIDEO_GENERATION_ERROR',
378
+ message: 'No operation name returned from API',
379
+ });
380
+ }
381
+
382
+ return {
383
+ operation: { operationName },
384
+ warnings,
385
+ response: {
386
+ timestamp: currentDate,
387
+ modelId: this.modelId,
388
+ headers: responseHeaders,
389
+ },
390
+ };
391
+ }
392
+
393
+ async doStatus(
394
+ options: Parameters<NonNullable<VideoModelV4['doStatus']>>[0],
395
+ ): Promise<VideoModelV4OperationStatusResult> {
396
+ const currentDate = this.config._internal?.currentDate?.() ?? new Date();
397
+ const { operationName } = options.operation as { operationName: string };
398
+
399
+ const { value: statusOperation, responseHeaders } = await getFromApi({
400
+ url: `${this.config.baseURL}/${operationName}`,
401
+ validateUrl: false,
402
+ headers: combineHeaders(
403
+ await resolve(this.config.headers),
404
+ options.headers,
405
+ ),
406
+ successfulResponseHandler: createJsonResponseHandler(
407
+ googleOperationSchema,
408
+ ),
409
+ failedResponseHandler: googleFailedResponseHandler,
410
+ abortSignal: options.abortSignal,
411
+ fetch: this.config.fetch,
412
+ });
413
+
414
+ if (!statusOperation.done) {
415
+ return {
416
+ status: 'pending',
417
+ response: {
418
+ timestamp: currentDate,
419
+ modelId: this.modelId,
420
+ headers: responseHeaders,
421
+ },
422
+ };
423
+ }
424
+
425
+ if (statusOperation.error) {
426
+ return {
427
+ status: 'error' as const,
428
+ error: `Video generation failed: ${statusOperation.error.message}`,
429
+ response: {
430
+ timestamp: currentDate,
431
+ modelId: this.modelId,
432
+ headers: responseHeaders,
433
+ },
434
+ };
435
+ }
436
+
437
+ return this.buildCompletedResult(
438
+ statusOperation,
439
+ responseHeaders,
440
+ [],
441
+ currentDate,
442
+ );
443
+ }
396
444
  }
397
445
 
398
446
  const googleOperationSchema = z.object({