@ai-sdk/google 4.0.61 → 4.0.63

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.
@@ -20,6 +20,7 @@ import type {
20
20
  GoogleInteractionsInput,
21
21
  GoogleInteractionsStep,
22
22
  GoogleInteractionsTextContent,
23
+ GoogleInteractionsVideoProcessing,
23
24
  } from './google-interactions-prompt';
24
25
 
25
26
  export type GoogleInteractionsMediaResolution =
@@ -163,6 +164,44 @@ export function convertToGoogleInteractionsInput({
163
164
  if (fileBlock != null) {
164
165
  pendingModelOutput.push(fileBlock);
165
166
  }
167
+ } else if (part.type === 'custom') {
168
+ flushModelOutput();
169
+ const google = part.providerOptions?.google as
170
+ | {
171
+ processingId?: unknown;
172
+ processingCallId?: unknown;
173
+ signature?: unknown;
174
+ }
175
+ | undefined;
176
+ const signature =
177
+ typeof google?.signature === 'string'
178
+ ? google.signature
179
+ : undefined;
180
+
181
+ if (
182
+ part.kind === 'google.processing_call' &&
183
+ typeof google?.processingId === 'string'
184
+ ) {
185
+ steps.push({
186
+ type: 'processing_call',
187
+ id: google.processingId,
188
+ ...(signature != null ? { signature } : {}),
189
+ });
190
+ } else if (
191
+ part.kind === 'google.processing_result' &&
192
+ typeof google?.processingCallId === 'string'
193
+ ) {
194
+ steps.push({
195
+ type: 'processing_result',
196
+ call_id: google.processingCallId,
197
+ ...(signature != null ? { signature } : {}),
198
+ });
199
+ } else {
200
+ warnings.push({
201
+ type: 'other',
202
+ message: `google.interactions: unsupported or invalid custom assistant content part "${part.kind}"; part dropped.`,
203
+ });
204
+ }
166
205
  } else if (part.type === 'tool-call') {
167
206
  flushModelOutput();
168
207
  const signature = part.providerOptions?.google?.signature as
@@ -282,6 +321,8 @@ function convertFilePartToContent({
282
321
  mediaResolution != null && (kind === 'image' || kind === 'video')
283
322
  ? { resolution: mediaResolution }
284
323
  : {};
324
+ const processingField =
325
+ kind === 'video' ? getVideoProcessingField({ part, warnings }) : {};
285
326
 
286
327
  switch (part.data.type) {
287
328
  case 'data': {
@@ -291,6 +332,7 @@ function convertFilePartToContent({
291
332
  data: convertToBase64(part.data.data),
292
333
  mime_type: mimeType,
293
334
  ...resolutionField,
335
+ ...processingField,
294
336
  };
295
337
  }
296
338
  case 'url': {
@@ -301,6 +343,7 @@ function convertFilePartToContent({
301
343
  ? { mime_type: part.mediaType }
302
344
  : {}),
303
345
  ...resolutionField,
346
+ ...processingField,
304
347
  };
305
348
  }
306
349
  case 'reference': {
@@ -315,11 +358,67 @@ function convertFilePartToContent({
315
358
  ? { mime_type: part.mediaType }
316
359
  : {}),
317
360
  ...resolutionField,
361
+ ...processingField,
318
362
  };
319
363
  }
320
364
  }
321
365
  }
322
366
 
367
+ function getVideoProcessingField({
368
+ part,
369
+ warnings,
370
+ }: {
371
+ part: LanguageModelV4FilePart;
372
+ warnings: Array<SharedV4Warning>;
373
+ }): { processing?: GoogleInteractionsVideoProcessing } {
374
+ const processing = (
375
+ part.providerOptions?.google as
376
+ | {
377
+ processing?: unknown;
378
+ }
379
+ | undefined
380
+ )?.processing;
381
+
382
+ if (processing == null) {
383
+ return {};
384
+ }
385
+
386
+ if (processing === 'agentic' || processing === 'static') {
387
+ return { processing };
388
+ }
389
+
390
+ if (
391
+ typeof processing === 'object' &&
392
+ !Array.isArray(processing) &&
393
+ (processing as { type?: unknown }).type === 'static'
394
+ ) {
395
+ const config = processing as {
396
+ startOffset?: unknown;
397
+ endOffset?: unknown;
398
+ fps?: unknown;
399
+ };
400
+ return {
401
+ processing: {
402
+ type: 'static',
403
+ ...(typeof config.startOffset === 'number'
404
+ ? { start_offset: config.startOffset }
405
+ : {}),
406
+ ...(typeof config.endOffset === 'number'
407
+ ? { end_offset: config.endOffset }
408
+ : {}),
409
+ ...(typeof config.fps === 'number' ? { fps: config.fps } : {}),
410
+ },
411
+ };
412
+ }
413
+
414
+ warnings.push({
415
+ type: 'other',
416
+ message:
417
+ 'google.interactions: invalid providerOptions.google.processing on video file part; expected "agentic", "static", or a static processing configuration. Option dropped.',
418
+ });
419
+ return {};
420
+ }
421
+
323
422
  /*
324
423
  * Drops assistant messages that were part of the linked interaction
325
424
  * (`previousInteractionId`). Tool-result turns whose tool-call counterpart
@@ -222,6 +222,22 @@ const stepSchema = () => {
222
222
  })
223
223
  .loose();
224
224
 
225
+ const processingCallStep = z
226
+ .object({
227
+ type: z.literal('processing_call'),
228
+ id: z.string(),
229
+ signature: z.string().nullish(),
230
+ })
231
+ .loose();
232
+
233
+ const processingResultStep = z
234
+ .object({
235
+ type: z.literal('processing_result'),
236
+ call_id: z.string(),
237
+ signature: z.string().nullish(),
238
+ })
239
+ .loose();
240
+
225
241
  const builtinToolCallStep = z
226
242
  .object({
227
243
  type: z.enum(BUILTIN_TOOL_CALL_STEP_TYPES),
@@ -251,6 +267,8 @@ const stepSchema = () => {
251
267
  modelOutputStep,
252
268
  functionCallStep,
253
269
  thoughtStep,
270
+ processingCallStep,
271
+ processingResultStep,
254
272
  builtinToolCallStep,
255
273
  builtinToolResultStep,
256
274
  z.object({ type: z.string() }).loose(),
@@ -36,10 +36,34 @@ export type GoogleInteractionsModelId =
36
36
  | 'gemini-3.5-flash-lite'
37
37
  | 'gemini-3.6-flash'
38
38
  | 'gemini-3.7-flash'
39
+ | 'gemini-3.8-flash'
39
40
  | 'lyria-3-clip-preview'
40
41
  | 'lyria-3-pro-preview'
41
42
  | (string & {});
42
43
 
44
+ /**
45
+ * Provider options for an individual video file part sent to the Gemini
46
+ * Interactions API.
47
+ */
48
+ export type GoogleInteractionsVideoOptions = {
49
+ /**
50
+ * Controls how Gemini processes this video.
51
+ *
52
+ * Agentic processing dynamically explores the video timeline. Static
53
+ * processing samples frames at a fixed rate and optionally supports clipping
54
+ * and custom frame rates.
55
+ */
56
+ processing?:
57
+ | 'agentic'
58
+ | 'static'
59
+ | {
60
+ type: 'static';
61
+ startOffset?: number;
62
+ endOffset?: number;
63
+ fps?: number;
64
+ };
65
+ };
66
+
43
67
  /**
44
68
  * Provider-options schema for `google.interactions(...)` calls. Read from the
45
69
  * shared `providerOptions.google.*` namespace (per PRD); per-call options that
@@ -35,12 +35,23 @@ export type GoogleInteractionsDocumentContent = {
35
35
  uri?: string;
36
36
  };
37
37
 
38
+ export type GoogleInteractionsVideoProcessing =
39
+ | 'agentic'
40
+ | 'static'
41
+ | {
42
+ type: 'static';
43
+ start_offset?: number;
44
+ end_offset?: number;
45
+ fps?: number;
46
+ };
47
+
38
48
  export type GoogleInteractionsVideoContent = {
39
49
  type: 'video';
40
50
  data?: string;
41
51
  mime_type?: string;
42
52
  uri?: string;
43
53
  resolution?: 'low' | 'medium' | 'high' | 'ultra_high';
54
+ processing?: GoogleInteractionsVideoProcessing;
44
55
  };
45
56
 
46
57
  export type GoogleInteractionsThoughtSummaryItem =
@@ -127,6 +138,16 @@ export type GoogleInteractionsThoughtStepPayload = {
127
138
  summary?: Array<GoogleInteractionsThoughtSummaryItem>;
128
139
  };
129
140
 
141
+ export type GoogleInteractionsProcessingCallStepPayload = {
142
+ id: string;
143
+ signature?: string;
144
+ };
145
+
146
+ export type GoogleInteractionsProcessingResultStepPayload = {
147
+ call_id: string;
148
+ signature?: string;
149
+ };
150
+
130
151
  export type GoogleInteractionsCodeExecutionCallStepPayload = {
131
152
  id: string;
132
153
  arguments?: { code?: string; language?: string };
@@ -255,6 +276,14 @@ export type GoogleInteractionsThoughtStep = {
255
276
  type: 'thought';
256
277
  } & GoogleInteractionsThoughtStepPayload;
257
278
 
279
+ export type GoogleInteractionsProcessingCallStep = {
280
+ type: 'processing_call';
281
+ } & GoogleInteractionsProcessingCallStepPayload;
282
+
283
+ export type GoogleInteractionsProcessingResultStep = {
284
+ type: 'processing_result';
285
+ } & GoogleInteractionsProcessingResultStepPayload;
286
+
258
287
  export type GoogleInteractionsBuiltinToolCallStep =
259
288
  | ({
260
289
  type: 'google_search_call';
@@ -294,6 +323,8 @@ export type GoogleInteractionsStep =
294
323
  | GoogleInteractionsModelOutputStep
295
324
  | GoogleInteractionsFunctionCallStep
296
325
  | GoogleInteractionsThoughtStep
326
+ | GoogleInteractionsProcessingCallStep
327
+ | GoogleInteractionsProcessingResultStep
297
328
  | GoogleInteractionsBuiltinToolCallStep
298
329
  | GoogleInteractionsBuiltinToolResultStep
299
330
  | { type: string; [k: string]: unknown };
@@ -28,4 +28,16 @@ export type GoogleInteractionsProviderMetadata = {
28
28
  * reasoning / tool-call parts and round-tripped on input parts.
29
29
  */
30
30
  signature?: string;
31
+
32
+ /**
33
+ * ID of an agentic video `processing_call` step. Present on
34
+ * `google.processing_call` custom parts.
35
+ */
36
+ processingId?: string;
37
+
38
+ /**
39
+ * ID of the corresponding agentic video processing call. Present on
40
+ * `google.processing_result` custom parts.
41
+ */
42
+ processingCallId?: string;
31
43
  };
@@ -23,9 +23,13 @@ export type ParseGoogleInteractionsOutputsResult = {
23
23
  function googleProviderMetadata({
24
24
  signature,
25
25
  interactionId,
26
+ processingId,
27
+ processingCallId,
26
28
  }: {
27
29
  signature?: string | null;
28
30
  interactionId?: string;
31
+ processingId?: string;
32
+ processingCallId?: string;
29
33
  }): { providerMetadata: { google: Record<string, string> } } | object {
30
34
  const google: Record<string, string> = {};
31
35
  if (signature != null) {
@@ -34,6 +38,12 @@ function googleProviderMetadata({
34
38
  if (interactionId != null) {
35
39
  google.interactionId = interactionId;
36
40
  }
41
+ if (processingId != null) {
42
+ google.processingId = processingId;
43
+ }
44
+ if (processingCallId != null) {
45
+ google.processingCallId = processingCallId;
46
+ }
37
47
  return Object.keys(google).length > 0 ? { providerMetadata: { google } } : {};
38
48
  }
39
49
 
@@ -198,6 +208,40 @@ export function parseGoogleInteractionsOutputs({
198
208
  });
199
209
  break;
200
210
  }
211
+ case 'processing_call': {
212
+ const call = step as {
213
+ id?: string;
214
+ signature?: string | null;
215
+ };
216
+ const processingId = call.id || generateId();
217
+ content.push({
218
+ type: 'custom',
219
+ kind: 'google.processing_call',
220
+ ...googleProviderMetadata({
221
+ signature: call.signature,
222
+ interactionId,
223
+ processingId,
224
+ }),
225
+ });
226
+ break;
227
+ }
228
+ case 'processing_result': {
229
+ const result = step as {
230
+ call_id?: string;
231
+ signature?: string | null;
232
+ };
233
+ const processingCallId = result.call_id || generateId();
234
+ content.push({
235
+ type: 'custom',
236
+ kind: 'google.processing_result',
237
+ ...googleProviderMetadata({
238
+ signature: result.signature,
239
+ interactionId,
240
+ processingCallId,
241
+ }),
242
+ });
243
+ break;
244
+ }
201
245
  case 'function_call': {
202
246
  hasFunctionCall = true;
203
247
  const call = step as {