@tanstack/ai 0.31.0 → 0.32.0

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.
Files changed (37) hide show
  1. package/dist/esm/activities/generateImage/adapter.d.ts +8 -4
  2. package/dist/esm/activities/generateImage/adapter.js.map +1 -1
  3. package/dist/esm/activities/generateImage/index.d.ts +19 -3
  4. package/dist/esm/activities/generateImage/index.js +12 -1
  5. package/dist/esm/activities/generateImage/index.js.map +1 -1
  6. package/dist/esm/activities/generateVideo/adapter.d.ts +65 -6
  7. package/dist/esm/activities/generateVideo/adapter.js +14 -0
  8. package/dist/esm/activities/generateVideo/adapter.js.map +1 -1
  9. package/dist/esm/activities/generateVideo/index.d.ts +31 -5
  10. package/dist/esm/activities/generateVideo/index.js.map +1 -1
  11. package/dist/esm/activities/generateVideo/snap.d.ts +14 -0
  12. package/dist/esm/activities/generateVideo/snap.js +54 -0
  13. package/dist/esm/activities/generateVideo/snap.js.map +1 -0
  14. package/dist/esm/activities/index.d.ts +3 -2
  15. package/dist/esm/activities/index.js +2 -0
  16. package/dist/esm/activities/index.js.map +1 -1
  17. package/dist/esm/client.d.ts +1 -1
  18. package/dist/esm/client.js.map +1 -1
  19. package/dist/esm/index.d.ts +2 -0
  20. package/dist/esm/index.js +2 -0
  21. package/dist/esm/index.js.map +1 -1
  22. package/dist/esm/types.d.ts +96 -7
  23. package/dist/esm/utilities/media-prompt.d.ts +35 -0
  24. package/dist/esm/utilities/media-prompt.js +43 -0
  25. package/dist/esm/utilities/media-prompt.js.map +1 -0
  26. package/package.json +2 -2
  27. package/skills/ai-core/media-generation/SKILL.md +173 -3
  28. package/src/activities/generateImage/adapter.ts +16 -3
  29. package/src/activities/generateImage/index.ts +48 -4
  30. package/src/activities/generateVideo/adapter.ts +80 -4
  31. package/src/activities/generateVideo/index.ts +53 -4
  32. package/src/activities/generateVideo/snap.ts +100 -0
  33. package/src/activities/index.ts +4 -0
  34. package/src/client.ts +4 -0
  35. package/src/index.ts +4 -0
  36. package/src/types.ts +119 -6
  37. package/src/utilities/media-prompt.ts +86 -0
@@ -1,4 +1,8 @@
1
- import type { ImageGenerationOptions, ImageGenerationResult } from '../../types'
1
+ import type {
2
+ ImageGenerationOptions,
3
+ ImageGenerationResult,
4
+ ModelInputModalitiesByName,
5
+ } from '../../types'
2
6
 
3
7
  /**
4
8
  * Resolve the size type for a model from the model-size map.
@@ -29,6 +33,8 @@ export interface ImageAdapterConfig {
29
33
  * - TProviderOptions: Base provider-specific options (already resolved)
30
34
  * - TModelProviderOptionsByName: Map from model name to its specific provider options
31
35
  * - TModelSizeByName: Map from model name to its supported sizes
36
+ * - TModelInputModalitiesByName: Map from model name to the non-text prompt
37
+ * modalities it accepts (constrains the `prompt` part types at compile time)
32
38
  */
33
39
  export interface ImageAdapter<
34
40
  TModel extends string = string,
@@ -38,6 +44,8 @@ export interface ImageAdapter<
38
44
  string,
39
45
  string
40
46
  >,
47
+ TModelInputModalitiesByName extends ModelInputModalitiesByName =
48
+ ModelInputModalitiesByName,
41
49
  > {
42
50
  /** Discriminator for adapter kind - used by generate() to determine API shape */
43
51
  readonly kind: 'image'
@@ -53,6 +61,7 @@ export interface ImageAdapter<
53
61
  providerOptions: TProviderOptions
54
62
  modelProviderOptionsByName: TModelProviderOptionsByName
55
63
  modelSizeByName: TModelSizeByName
64
+ modelInputModalitiesByName: TModelInputModalitiesByName
56
65
  }
57
66
 
58
67
  /**
@@ -67,7 +76,7 @@ export interface ImageAdapter<
67
76
  * An ImageAdapter with any/unknown type parameters.
68
77
  * Useful as a constraint in generic functions and interfaces.
69
78
  */
70
- export type AnyImageAdapter = ImageAdapter<any, any, any, any>
79
+ export type AnyImageAdapter = ImageAdapter<any, any, any, any, any>
71
80
 
72
81
  /**
73
82
  * Abstract base class for image generation adapters.
@@ -83,11 +92,14 @@ export abstract class BaseImageAdapter<
83
92
  string,
84
93
  string
85
94
  >,
95
+ TModelInputModalitiesByName extends ModelInputModalitiesByName =
96
+ ModelInputModalitiesByName,
86
97
  > implements ImageAdapter<
87
98
  TModel,
88
99
  TProviderOptions,
89
100
  TModelProviderOptionsByName,
90
- TModelSizeByName
101
+ TModelSizeByName,
102
+ TModelInputModalitiesByName
91
103
  > {
92
104
  readonly kind = 'image' as const
93
105
  abstract readonly name: string
@@ -98,6 +110,7 @@ export abstract class BaseImageAdapter<
98
110
  providerOptions: TProviderOptions
99
111
  modelProviderOptionsByName: TModelProviderOptionsByName
100
112
  modelSizeByName: TModelSizeByName
113
+ modelInputModalitiesByName: TModelInputModalitiesByName
101
114
  }
102
115
 
103
116
  protected config: ImageAdapterConfig
@@ -8,10 +8,16 @@
8
8
  import { aiEventClient } from '@tanstack/ai-event-client'
9
9
  import { streamGenerationResult } from '../stream-generation-result.js'
10
10
  import { resolveDebugOption } from '../../logger/resolve'
11
+ import { resolveMediaPrompt } from '../../utilities/media-prompt'
11
12
  import type { InternalLogger } from '../../logger/internal-logger'
12
13
  import type { DebugOption } from '../../logger/types'
13
14
  import type { ImageAdapter } from './adapter'
14
- import type { ImageGenerationResult, StreamChunk } from '../../types'
15
+ import type {
16
+ ImageGenerationResult,
17
+ MediaPrompt,
18
+ MediaPromptFor,
19
+ StreamChunk,
20
+ } from '../../types'
15
21
 
16
22
  // ===========================
17
23
  // Activity Kind
@@ -55,6 +61,23 @@ export type ImageSizeForModel<TAdapter, TModel extends string> =
55
61
  : string
56
62
  : string
57
63
 
64
+ /**
65
+ * Extract the prompt type a model accepts from an ImageAdapter via ~types.
66
+ * Adapters declare a per-model input-modality map; models in the map get a
67
+ * `prompt` narrowed to text + their supported part types (text-only models
68
+ * accept `string | Array<TextPart>`), so unsupported media parts fail at
69
+ * compile time. Adapters without a map fall back to the full MediaPrompt.
70
+ */
71
+ export type ImagePromptForModel<TAdapter, TModel extends string> =
72
+ TAdapter extends ImageAdapter<any, any, any, any, infer ModsByName>
73
+ ? string extends keyof ModsByName
74
+ ? // No explicit map - accept the full union
75
+ MediaPrompt
76
+ : TModel extends keyof ModsByName
77
+ ? MediaPromptFor<ModsByName[TModel][number]>
78
+ : MediaPrompt
79
+ : MediaPrompt
80
+
58
81
  // ===========================
59
82
  // Activity Options Type
60
83
  // ===========================
@@ -72,8 +95,16 @@ export type ImageActivityOptions<
72
95
  > = {
73
96
  /** The image adapter to use (must be created with a model) */
74
97
  adapter: TAdapter & { kind: typeof kind }
75
- /** Text description of the desired image(s) */
76
- prompt: string
98
+ /**
99
+ * Description of the desired image(s). Either a plain string, or — for
100
+ * models that support image-conditioned generation — an ordered array of
101
+ * content parts interleaving text with image inputs (image-to-image,
102
+ * reference-guided, edit, multi-reference). Media parts may carry
103
+ * `metadata.role` (`'reference' | 'mask' | 'control' | 'character'`) to
104
+ * disambiguate intent. The accepted part types are narrowed per model via
105
+ * the adapter's input-modality map.
106
+ */
107
+ prompt: ImagePromptForModel<TAdapter, TAdapter['model']>
77
108
  /** Number of images to generate (default: 1) */
78
109
  numberOfImages?: number
79
110
  /** Image size in WIDTHxHEIGHT format (e.g., "1024x1024") */
@@ -203,13 +234,26 @@ async function runGenerateImage<
203
234
  const startTime = Date.now()
204
235
  const logger: InternalLogger = resolveDebugOption(options.debug)
205
236
 
237
+ // Devtools events carry the flattened prompt text plus media-part counts —
238
+ // the wire payload stays `prompt: string` regardless of the prompt shape.
239
+ const resolved = resolveMediaPrompt(rest.prompt)
240
+
206
241
  aiEventClient.emit('image:request:started', {
207
242
  requestId,
208
243
  provider: adapter.name,
209
244
  model,
210
- prompt: rest.prompt,
245
+ prompt: resolved.text,
211
246
  numberOfImages: rest.numberOfImages,
212
247
  size: rest.size,
248
+ ...(resolved.images.length > 0 && {
249
+ imageInputCount: resolved.images.length,
250
+ }),
251
+ ...(resolved.videos.length > 0 && {
252
+ videoInputCount: resolved.videos.length,
253
+ }),
254
+ ...(resolved.audios.length > 0 && {
255
+ audioInputCount: resolved.audios.length,
256
+ }),
213
257
  modelOptions: rest.modelOptions,
214
258
  timestamp: startTime,
215
259
  })
@@ -1,10 +1,30 @@
1
1
  import type {
2
+ ModelInputModalitiesByName,
2
3
  VideoGenerationOptions,
3
4
  VideoJobResult,
4
5
  VideoStatusResult,
5
6
  VideoUrlResult,
6
7
  } from '../../types'
7
8
 
9
+ /**
10
+ * Structured description of the durations a video model accepts.
11
+ *
12
+ * Tagged union so the same shape can express discrete enums (OpenAI Sora,
13
+ * Veo), continuous ranges, mixed shapes, and models with no duration field.
14
+ * Consumed by `VideoAdapter.availableDurations()`.
15
+ *
16
+ * @experimental Video generation is an experimental feature and may change.
17
+ */
18
+ export type DurationOptions<T extends string | number | undefined> =
19
+ | { kind: 'discrete'; values: ReadonlyArray<NonNullable<T>> }
20
+ | { kind: 'range'; min: number; max: number; step?: number; unit: 'seconds' }
21
+ | {
22
+ kind: 'mixed'
23
+ values: ReadonlyArray<NonNullable<T>>
24
+ range?: { min: number; max: number; step?: number }
25
+ }
26
+ | { kind: 'none' }
27
+
8
28
  /**
9
29
  * Configuration for video adapter instances
10
30
  *
@@ -31,6 +51,11 @@ export interface VideoAdapterConfig {
31
51
  * - TProviderOptions: Provider-specific options (already resolved)
32
52
  * - TModelProviderOptionsByName: Map from model name to its specific provider options
33
53
  * - TModelSizeByName: Map from model name to its supported sizes
54
+ * - TModelInputModalitiesByName: Map from model name to the non-text prompt
55
+ * modalities it accepts (constrains the `prompt` part types at compile time)
56
+ * - TModelDurationByName: Map from model name to its supported duration
57
+ * union. Defaults to `Record<string, number>` so adapters that haven't
58
+ * declared a map keep today's `duration?: number` typing.
34
59
  */
35
60
  export interface VideoAdapter<
36
61
  TModel extends string = string,
@@ -40,6 +65,10 @@ export interface VideoAdapter<
40
65
  string,
41
66
  string
42
67
  >,
68
+ TModelInputModalitiesByName extends ModelInputModalitiesByName =
69
+ ModelInputModalitiesByName,
70
+ TModelDurationByName extends Record<string, string | number | undefined> =
71
+ Record<string, number>,
43
72
  > {
44
73
  /** Discriminator for adapter kind - used to determine API shape */
45
74
  readonly kind: 'video'
@@ -55,6 +84,8 @@ export interface VideoAdapter<
55
84
  providerOptions: TProviderOptions
56
85
  modelProviderOptionsByName: TModelProviderOptionsByName
57
86
  modelSizeByName: TModelSizeByName
87
+ modelInputModalitiesByName: TModelInputModalitiesByName
88
+ modelDurationByName: TModelDurationByName
58
89
  }
59
90
 
60
91
  /**
@@ -62,7 +93,11 @@ export interface VideoAdapter<
62
93
  * Returns a job ID that can be used to poll for status and retrieve the video.
63
94
  */
64
95
  createVideoJob: (
65
- options: VideoGenerationOptions<TProviderOptions, TModelSizeByName[TModel]>,
96
+ options: VideoGenerationOptions<
97
+ TProviderOptions,
98
+ TModelSizeByName[TModel],
99
+ TModelDurationByName[TModel]
100
+ >,
66
101
  ) => Promise<VideoJobResult>
67
102
 
68
103
  /**
@@ -75,13 +110,26 @@ export interface VideoAdapter<
75
110
  * Should only be called after status is 'completed'.
76
111
  */
77
112
  getVideoUrl: (jobId: string) => Promise<VideoUrlResult>
113
+
114
+ /**
115
+ * Describe the durations this adapter's model accepts. Returns a tagged
116
+ * union so consumers can render UI / coerce input without provider-specific
117
+ * knowledge.
118
+ */
119
+ availableDurations: () => DurationOptions<TModelDurationByName[TModel]>
120
+
121
+ /**
122
+ * Coerce a raw seconds value to the closest valid duration for this model.
123
+ * Returns `undefined` for models with no duration field.
124
+ */
125
+ snapDuration: (seconds: number) => TModelDurationByName[TModel] | undefined
78
126
  }
79
127
 
80
128
  /**
81
129
  * A VideoAdapter with any/unknown type parameters.
82
130
  * Useful as a constraint in generic functions and interfaces.
83
131
  */
84
- export type AnyVideoAdapter = VideoAdapter<any, any, any, any>
132
+ export type AnyVideoAdapter = VideoAdapter<any, any, any, any, any, any>
85
133
 
86
134
  /**
87
135
  * Abstract base class for video generation adapters.
@@ -99,11 +147,17 @@ export abstract class BaseVideoAdapter<
99
147
  string,
100
148
  string
101
149
  >,
150
+ TModelInputModalitiesByName extends ModelInputModalitiesByName =
151
+ ModelInputModalitiesByName,
152
+ TModelDurationByName extends Record<string, string | number | undefined> =
153
+ Record<string, number>,
102
154
  > implements VideoAdapter<
103
155
  TModel,
104
156
  TProviderOptions,
105
157
  TModelProviderOptionsByName,
106
- TModelSizeByName
158
+ TModelSizeByName,
159
+ TModelInputModalitiesByName,
160
+ TModelDurationByName
107
161
  > {
108
162
  readonly kind = 'video' as const
109
163
  abstract readonly name: string
@@ -114,6 +168,8 @@ export abstract class BaseVideoAdapter<
114
168
  providerOptions: TProviderOptions
115
169
  modelProviderOptionsByName: TModelProviderOptionsByName
116
170
  modelSizeByName: TModelSizeByName
171
+ modelInputModalitiesByName: TModelInputModalitiesByName
172
+ modelDurationByName: TModelDurationByName
117
173
  }
118
174
 
119
175
  protected config: VideoAdapterConfig
@@ -124,13 +180,33 @@ export abstract class BaseVideoAdapter<
124
180
  }
125
181
 
126
182
  abstract createVideoJob(
127
- options: VideoGenerationOptions<TProviderOptions, TModelSizeByName[TModel]>,
183
+ options: VideoGenerationOptions<
184
+ TProviderOptions,
185
+ TModelSizeByName[TModel],
186
+ TModelDurationByName[TModel]
187
+ >,
128
188
  ): Promise<VideoJobResult>
129
189
 
130
190
  abstract getVideoStatus(jobId: string): Promise<VideoStatusResult>
131
191
 
132
192
  abstract getVideoUrl(jobId: string): Promise<VideoUrlResult>
133
193
 
194
+ /**
195
+ * Default implementation returns `{ kind: 'none' }`. Adapters that have
196
+ * declared their per-model duration map should override this.
197
+ */
198
+ availableDurations(): DurationOptions<TModelDurationByName[TModel]> {
199
+ return { kind: 'none' }
200
+ }
201
+
202
+ /**
203
+ * Default implementation returns `undefined`. Adapters that have declared
204
+ * their per-model duration map should override.
205
+ */
206
+ snapDuration(_seconds: number): TModelDurationByName[TModel] | undefined {
207
+ return undefined
208
+ }
209
+
134
210
  protected generateId(): string {
135
211
  return `${this.name}-${Date.now()}-${Math.random().toString(36).substring(7)}`
136
212
  }
@@ -14,6 +14,8 @@ import type { InternalLogger } from '../../logger/internal-logger'
14
14
  import type { DebugOption } from '../../logger/types'
15
15
  import type { VideoAdapter } from './adapter'
16
16
  import type {
17
+ MediaPrompt,
18
+ MediaPromptFor,
17
19
  StreamChunk,
18
20
  TokenUsage,
19
21
  VideoJobResult,
@@ -50,6 +52,40 @@ export type VideoSizeForAdapter<TAdapter> =
50
52
  : string
51
53
  : string
52
54
 
55
+ /**
56
+ * Extract the prompt type a model accepts from a VideoAdapter via ~types.
57
+ * Mirrors `ImagePromptForModel`: models in the adapter's input-modality map
58
+ * get a `prompt` narrowed to text + their supported part types; adapters
59
+ * without a map fall back to the full MediaPrompt.
60
+ */
61
+ export type VideoPromptForAdapter<TAdapter> =
62
+ TAdapter extends VideoAdapter<infer TModel, any, any, any, infer ModsByName>
63
+ ? string extends keyof ModsByName
64
+ ? MediaPrompt
65
+ : TModel extends keyof ModsByName
66
+ ? MediaPromptFor<ModsByName[TModel][number]>
67
+ : MediaPrompt
68
+ : MediaPrompt
69
+
70
+ /**
71
+ * Extract the duration type for a VideoAdapter's model via ~types.
72
+ * Mirrors `VideoSizeForAdapter`. Falls back to `number` for adapters that
73
+ * haven't declared per-model duration constraints.
74
+ */
75
+ export type VideoDurationForAdapter<TAdapter> =
76
+ TAdapter extends VideoAdapter<
77
+ infer TModel,
78
+ any,
79
+ any,
80
+ any,
81
+ any,
82
+ infer TDurationMap
83
+ >
84
+ ? TModel extends keyof TDurationMap
85
+ ? TDurationMap[TModel]
86
+ : number
87
+ : number
88
+
53
89
  // ===========================
54
90
  // Activity Options Types
55
91
 
@@ -84,12 +120,25 @@ export type VideoCreateOptions<
84
120
  > = VideoActivityBaseOptions<TAdapter> & {
85
121
  /** Request type - create a new job (default if not specified) */
86
122
  request?: 'create'
87
- /** Text description of the desired video */
88
- prompt: string
123
+ /**
124
+ * Description of the desired video. Either a plain string, or — for models
125
+ * that support image-conditioned generation — an ordered array of content
126
+ * parts interleaving text with image inputs. Image parts may carry
127
+ * `metadata.role` (`'start_frame' | 'end_frame' | 'reference' |
128
+ * 'character'`) to disambiguate intent; positional fallback otherwise. The
129
+ * accepted part types are narrowed per model via the adapter's
130
+ * input-modality map.
131
+ */
132
+ prompt: VideoPromptForAdapter<TAdapter>
89
133
  /** Video size — format depends on the provider (e.g., "16:9", "1280x720") */
90
134
  size?: VideoSizeForAdapter<TAdapter>
91
- /** Video duration in seconds */
92
- duration?: number
135
+ /**
136
+ * Video duration in seconds. Adapters that declare a per-model duration
137
+ * map narrow this to the model's valid union (e.g. `4 | 6 | 8` for Veo 3).
138
+ * Pass `adapter.snapDuration(seconds)` to coerce raw seconds to a valid
139
+ * value.
140
+ */
141
+ duration?: VideoDurationForAdapter<TAdapter>
93
142
  /**
94
143
  * Whether to stream the video generation lifecycle.
95
144
  * When true, returns an AsyncIterable<StreamChunk> that handles the full
@@ -0,0 +1,100 @@
1
+ import type { DurationOptions } from './adapter'
2
+
3
+ /**
4
+ * Extract a numeric seconds value from a `DurationOptions` entry. Returns
5
+ * `null` for entries that don't parse as a number — e.g. `'auto'`.
6
+ *
7
+ * Handles the keyword-with-unit form FAL uses for Luma/Veo (`'8s'`, `'9s'`)
8
+ * by stripping a trailing `s`. Pure-numeric strings (`'5'`, `'10'`) parse via
9
+ * Number(). Numbers pass through.
10
+ */
11
+ function entryToSeconds(entry: string | number): number | null {
12
+ if (typeof entry === 'number') {
13
+ return Number.isFinite(entry) ? entry : null
14
+ }
15
+ const stripped = entry.endsWith('s') ? entry.slice(0, -1) : entry
16
+ const parsed = Number(stripped)
17
+ return Number.isFinite(parsed) ? parsed : null
18
+ }
19
+
20
+ /**
21
+ * Snap a raw seconds value to the closest valid duration for a model's
22
+ * `DurationOptions`.
23
+ *
24
+ * - `none` → `undefined`
25
+ * - `discrete` → closest numeric-parseable entry; if none parse,
26
+ * returns `values[0]` (keyword-only models like 'auto')
27
+ * - `range` → clamped to [min, max] and rounded to `step` (default 1)
28
+ * - `mixed` → closest of (discrete numerics ∪ range values)
29
+ *
30
+ * @experimental Video generation is an experimental feature and may change.
31
+ */
32
+ export function snapToDurationOption<T extends string | number | undefined>(
33
+ seconds: number,
34
+ options: DurationOptions<T>,
35
+ ): T | undefined {
36
+ switch (options.kind) {
37
+ case 'none':
38
+ return undefined
39
+
40
+ case 'discrete': {
41
+ return pickClosestDiscrete(seconds, options.values)
42
+ }
43
+
44
+ case 'range': {
45
+ const step = options.step ?? 1
46
+ const clamped = Math.min(options.max, Math.max(options.min, seconds))
47
+ const snapped =
48
+ Math.round((clamped - options.min) / step) * step + options.min
49
+ return Math.min(options.max, Math.max(options.min, snapped)) as T
50
+ }
51
+
52
+ case 'mixed': {
53
+ const discreteCandidate = pickClosestDiscrete(seconds, options.values)
54
+ if (!options.range) return discreteCandidate
55
+
56
+ const { min, max, step = 1 } = options.range
57
+ const clamped = Math.min(max, Math.max(min, seconds))
58
+ const rangeValue = Math.min(
59
+ max,
60
+ Math.max(min, Math.round((clamped - min) / step) * step + min),
61
+ )
62
+
63
+ // Compare distance; range value is numeric, discrete may have non-numeric
64
+ // first-entry fallback (return distance Infinity for non-numerics).
65
+ const discreteSeconds =
66
+ typeof discreteCandidate === 'number'
67
+ ? discreteCandidate
68
+ : discreteCandidate !== undefined
69
+ ? (entryToSeconds(discreteCandidate) ?? Infinity)
70
+ : Infinity
71
+
72
+ return Math.abs(discreteSeconds - seconds) <=
73
+ Math.abs(rangeValue - seconds)
74
+ ? discreteCandidate
75
+ : (rangeValue as T)
76
+ }
77
+ }
78
+ }
79
+
80
+ function pickClosestDiscrete<T extends string | number>(
81
+ seconds: number,
82
+ values: ReadonlyArray<T>,
83
+ ): T | undefined {
84
+ if (values.length === 0) return undefined
85
+
86
+ let best: T | undefined
87
+ let bestDistance = Infinity
88
+ for (const value of values) {
89
+ const v = entryToSeconds(value)
90
+ if (v === null) continue
91
+ const distance = Math.abs(v - seconds)
92
+ if (distance < bestDistance) {
93
+ bestDistance = distance
94
+ best = value
95
+ }
96
+ }
97
+
98
+ // Keyword-only set (no numeric-parseable entries) — fall back to first entry.
99
+ return best ?? values[0]
100
+ }
@@ -119,6 +119,7 @@ export {
119
119
  type VideoCreateOptions,
120
120
  type VideoStatusOptions,
121
121
  type VideoUrlOptions,
122
+ type VideoDurationForAdapter,
122
123
  } from './generateVideo/index'
123
124
 
124
125
  export {
@@ -126,8 +127,11 @@ export {
126
127
  type VideoAdapter,
127
128
  type VideoAdapterConfig,
128
129
  type AnyVideoAdapter,
130
+ type DurationOptions,
129
131
  } from './generateVideo/adapter'
130
132
 
133
+ export { snapToDurationOption } from './generateVideo/snap'
134
+
131
135
  // ===========================
132
136
  // TTS Activity
133
137
  // ===========================
package/src/client.ts CHANGED
@@ -97,6 +97,10 @@ export type {
97
97
  CustomEvent,
98
98
  DocumentPart,
99
99
  ImagePart,
100
+ MediaInputMetadata,
101
+ MediaInputRole,
102
+ MediaPrompt,
103
+ MediaPromptPart,
100
104
  MessagePart,
101
105
  ModelMessage,
102
106
  RunErrorEvent,
package/src/index.ts CHANGED
@@ -138,6 +138,10 @@ export * from './types'
138
138
  // Usage utilities
139
139
  export { buildBaseUsage, type BaseUsageInput } from './utilities/usage'
140
140
 
141
+ // Media-generation prompt resolution (used by image / video adapters)
142
+ export { resolveMediaPrompt } from './utilities/media-prompt'
143
+ export type { ResolvedMediaPrompt } from './utilities/media-prompt'
144
+
141
145
  // System prompts (type + normaliser used by adapters)
142
146
  export type { SystemPrompt, NormalizedSystemPrompt } from './system-prompts'
143
147
  export { normalizeSystemPrompts } from './system-prompts'