@vanillaskyai/video 0.10.3 → 0.10.4

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 (39) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/PUBLIC-API.md +43 -31
  3. package/README.md +11 -7
  4. package/dist/check-runtime.js +2 -2
  5. package/dist/{chunk-UCXQORDZ.js → chunk-G5TYLTL5.js} +1 -1
  6. package/dist/{chunk-SI6CFFAA.js → chunk-O6FBIB4L.js} +6 -5
  7. package/dist/{chunk-YZZSWGC3.js → chunk-OOBT4X46.js} +8 -3
  8. package/dist/{chunk-LJR5VLEI.js → chunk-QZAZT44G.js} +2 -2
  9. package/dist/{chunk-3U2F7C7C.js → chunk-WZFLEPLM.js} +7 -3
  10. package/dist/{chunk-VVNZCY2U.js → chunk-Z2ZI5G7O.js} +1 -1
  11. package/dist/{cinema-media-4JUYKPQI.js → cinema-media-3SIGVVCY.js} +4 -4
  12. package/dist/{comparison-3QLMUC5V.js → comparison-VDGRWPB5.js} +4 -4
  13. package/dist/{editorial-timeline-IVE2P25N.js → editorial-timeline-QJU4JJWB.js} +4 -4
  14. package/dist/{key-figure-APD56LCO.js → key-figure-YUAQW6OE.js} +4 -4
  15. package/dist/{mobile-message-WLK3WY5B.js → mobile-message-ZMMTUDUQ.js} +4 -4
  16. package/dist/{quote-Z6YET5BO.js → quote-BB6UJT6L.js} +4 -4
  17. package/dist/react.d.ts +3 -1
  18. package/dist/react.js +79 -81
  19. package/dist/{scene-video-backdrop-OWUXPXHZ.js → scene-video-backdrop-4EZVVQY7.js} +2 -2
  20. package/dist/server.d.ts +15 -3
  21. package/dist/server.js +129 -33
  22. package/dist/{types-CdBmNTGD.d.ts → types-BqB8zC9u.d.ts} +1 -1
  23. package/docs/concepts.md +2 -2
  24. package/docs/development.md +23 -0
  25. package/docs/getting-started.md +2 -2
  26. package/docs/media-and-audio.md +26 -13
  27. package/docs/performance.md +21 -10
  28. package/docs/production.md +11 -13
  29. package/docs/prompt-and-input.md +3 -3
  30. package/docs/provider-integration.md +9 -11
  31. package/docs/reference/provider-adapters.md +3 -2
  32. package/package.json +5 -2
  33. package/registry/items/backgrounds.json +2 -2
  34. package/starters/video-chat/README.md +13 -15
  35. package/starters/video-chat/package.json +1 -1
  36. package/starters/video-chat/providers/video.ts +5 -2
  37. package/starters/video-chat/server.ts +1 -1
  38. package/starters/video-chat/stock.ts +59 -31
  39. package/styles/video-chat.css +6 -61
package/CHANGELOG.md CHANGED
@@ -4,6 +4,15 @@ VanillaSky follows semantic versioning. This changelog begins with the 0.1 beta.
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 0.10.4
8
+
9
+ - Show the canonical chapter immediately after submitting a prompt; remove the separate gradient loading placeholder and opening stock requests.
10
+ - Separate AI video and Pexels in Settings. AI mode uses generated footage only; Pexels performs full bounded video search without AI-video calls. Missing or late footage becomes an authored chapter with complete narration.
11
+ - Prepare speech while footage generates, reuse prepared lines, and limit concurrent speech requests so an answer does not flood host admission. Describe HTTP throttling as a retryable request limit.
12
+ - Keep silent footage looping for the finite narrated scene, and recover missing URLs or rejected playback to a chapter rather than an unavailable screen. Preserve user pause, cancellation and replay.
13
+ - Allow hosts to configure the actual generated clip duration (default five seconds) and apply scene-position deadlines to media preparation.
14
+ - Add optional host-only phase diagnostics with bounded timing and fixed recovery reasons, without retaining prompt or provider content.
15
+
7
16
  ## 0.10.3
8
17
 
9
18
  - Remove the implicit documentary visual style from the chat interface; preserve explicitly supplied application styles and let the answer direct its own look.
package/PUBLIC-API.md CHANGED
@@ -116,6 +116,19 @@ provider-neutral text-delta escape hatch.
116
116
 
117
117
  ### Handler contract
118
118
 
119
+ The chat contract includes two footage modes: `"cinematic"` (labelled AI video)
120
+ and `"pexels"`. AI mode does not fall back to stock; either mode recovers missing
121
+ footage to an authored chapter. Existing `"cinematic"` requests remain valid.
122
+ `generatedClipDurationSec?: number` on the handler defaults to 5 and accepts 2–20;
123
+ it must match the host adapter's requested duration. `VideoChatTurn.mode` is
124
+ optional so older in-memory saved turns remain readable.
125
+
126
+ A declared `data.video-chat-preparation` extension carries
127
+ `{ sceneId: string, narration: string }` before media resolves. It permits bounded
128
+ speech preparation, not playback of an unvalidated scene. The client limits
129
+ speech preparation to two concurrent jobs and reuses it when `scene.add` arrives.
130
+ The six public exports, persisted video schema and protocol version are unchanged.
131
+
119
132
  `createVideoChatHandler` is the opinionated general-purpose video-chat route.
120
133
  Mount it once and use its bounded `action` query parameter for capabilities,
121
134
  responses, opening media, narration, suggestions, speech,
@@ -124,33 +137,28 @@ application-configured visual-mode attempt limits, capability fallbacks, and aux
124
137
  shapes. The application supplies provider-neutral `streamText`, `generateText`,
125
138
  `generateSpeech`, `transcribe`, `searchMedia`, and `generateVideo` callbacks.
126
139
  Only the two text callbacks are required. Missing optional callbacks remove
127
- their capability; templates and browser speech remain available. During response
128
- creation, failed generated footage falls back to stock when available, then to
129
- matching completed footage and finally a safe template. The default handler skips invalid planner parts and preserves
130
- playable scenes on an interrupted plan, emitting non-fatal warnings. Explicit
131
- `invalidPartBehavior: "fail"` retains strict generation semantics.
140
+ their capability; templates and browser speech remain available. Failed or late
141
+ footage becomes an authored chapter with complete narration. The default handler
142
+ skips invalid planner parts and preserves playable scenes on an interrupted plan,
143
+ emitting non-fatal warnings. Explicit `invalidPartBehavior: "fail"` retains strict
144
+ generation semantics.
132
145
 
133
146
  - A response accepts `prompt`, `mode`, `orientation`, optional bounded
134
147
  `conversation`, `opening`, and `style`. `opening` is an optional
135
148
  prewritten hook from a selected suggestion. The response returns protocol
136
- `0.6` SSE and negotiates `data.video-chat-opening`, which carries the bounded
137
- 6-9 word hook and optional stock-search `keyword` and `fallbackKeyword` before the first scene.
138
- - The planner produces that opening as the first line of the same model stream
139
- that produces the scenes. The separate opening-media action resolves its
140
- keyword through the application-owned `searchMedia` callback, with an optional
141
- bounded `fallbackQuery` for broader opening atmosphere. Stock lookup
142
- never delays speech or planning. In `full` mode the first line also directs
143
- the exact first generated scene; the handler consumes that private direction
144
- and starts the clip while the model continues with scenes two through five.
145
- - `templates` never generates video. `full` uses an application-owned
146
- `maxGeneratedVideos` limit (default five, nonnegative safe integer). The limit
147
- counts attempts including failed attempts and the reserved first shot; it is
148
- neither a currency nor duration cap. Stock lookup remains available after
149
- the limit. With zero, full mode uses stock only. The planner receives this
150
- budget, and the server enforces it independently. If providers fail, an
151
- already completed video with the identical search query and visual look may
152
- be reused once in the same response before a readable template fallback. Without `generateVideo`, only `templates` is exposed
153
- and forged generated-mode requests degrade to it.
149
+ `0.6` SSE and negotiates `data.video-chat-opening` and
150
+ `data.video-chat-preparation` before the associated scene is ready.
151
+ - The planner produces the opening and shots in one model stream, reserving the
152
+ intended ending. Each shot supplies an authored recovery title, complete
153
+ narration and visual direction. The default UI uses a chapter opening; the
154
+ separate opening-media action remains available to custom consumers.
155
+ - `cinematic` uses the application-owned `maxGeneratedVideos` limit (default
156
+ five, nonnegative safe integer). It counts generation attempts, including
157
+ failures. Zero skips generation and keeps authored chapters. Expired scene
158
+ deadlines also skip generation without consuming an attempt. This limit is
159
+ neither a currency nor duration cap. Pexels mode uses only `searchMedia` and
160
+ never consumes this allowance. Capabilities expose Pexels when stock search
161
+ is configured; AI mode remains usable with chapter recovery without video.
154
162
  - The response planner writes narration on each scene. The narration action is
155
163
  retained as a compatibility fallback for missing lines, not used in the
156
164
  normal path.
@@ -251,9 +259,9 @@ playable output; an error is shown only when no playable response remains.
251
259
  `ask(prompt, { opening, openingMedia })` lets a custom interface start a
252
260
  prewritten suggestion hook immediately and reuse its image or video without
253
261
  another model or media lookup. The hook otherwise reads the opening from the
254
- response stream, resolves its media keyword, holds that media while it is
255
- spoken, and starts the planned timeline only when both speech and the first
256
- scene are ready. `UseVideoChatOptions.onFirstFrame` receives a
262
+ response stream and starts the planned timeline only when opening speech and
263
+ the contiguous prepared scenes are ready. It no longer requests opening stock
264
+ automatically. `UseVideoChatOptions.onFirstFrame` receives a
257
265
  `VideoChatFirstFrameMetric` once after its first active scene commits and reaches
258
266
  an animation-frame opportunity. This measures presentation readiness, not physical
259
267
  screen paint or media decoding. Each `VideoChatTurn` exposes `openingMedia` and `completed`, so
@@ -428,6 +436,7 @@ from `/server` without crossing a React type boundary.
428
436
  and nonnegative `elapsedMs` since the prompt was submitted:
429
437
 
430
438
  - `first-frame`: first committed active scene at an animation-frame opportunity;
439
+ - `first-media-frame`: first decoded frame reported by the mounted footage surface;
431
440
  - `first-speech`: actual speech playback onset, with `source` equal to `browser`,
432
441
  `generated`, or `custom`;
433
442
  - `stall`: a finished wait for the next prepared scene, with `durationMs` and
@@ -455,8 +464,11 @@ resolver deadline (integer 1–120000 milliseconds, default 15000). The host sti
455
464
  provider cancellation, authorization and spend limits; a timeout does not prove the
456
465
  provider avoided a charge. `maxGeneratedVideos` continues to count attempted clips.
457
466
 
458
- `VideoChatProps.generatedVideoLabel` and `generatedVideoDescription` customize the
459
- existing generated-video Settings choice without changing server capabilities.
460
- `showRecoveryNotice` opts into a dismissible, fixed SDK media-fallback notice. It
461
- never displays arbitrary provider messages. All three default to existing behavior.
462
- These are additive members; no new entry points or exports are introduced.
467
+ `VideoChatProps.showRecoveryNotice` opts into a dismissible, fixed SDK
468
+ media-recovery notice; it never displays arbitrary provider messages.
469
+
470
+ `VideoChatHandlerOptions.onDiagnostic` is an optional host-only observer for
471
+ request, authoring and media phase timings with fixed recovery reason codes.
472
+ It does not retain prompt, narration, query, asset URL or provider error text,
473
+ and cannot affect response delivery. No new entry points or named exports are
474
+ introduced; its additive signature is checked in the packed consumer contract.
package/README.md CHANGED
@@ -26,9 +26,8 @@ npm run dev
26
26
  ```
27
27
 
28
28
  Open the reported localhost URL. One text key gives you the chat, an immediate introduction, and browser voice.
29
- Add the video adapter for generated footage and optional stock for fallback.
30
- Without a media provider, answers retain narration and subtitles with an
31
- unavailable-visual state. If installation is interrupted, rerun the init command.
29
+ Add the video adapter for AI footage, or a Pexels key for the lower-cost stock mode.
30
+ Without footage, authored chapter scenes carry the narration and subtitles. If installation is interrupted, rerun the init command.
32
31
 
33
32
  Optional upgrades keep the same client:
34
33
 
@@ -36,7 +35,7 @@ Optional upgrades keep the same client:
36
35
  | --- | --- | --- |
37
36
  | Generated speech | `npx vanillasky providers add speech` | `XAI_API_KEY` |
38
37
  | Generated video and voice transcription | `npx vanillasky providers add video` | `FAL_KEY` |
39
- | Stock media, including opening backgrounds | No install needed | `PEXELS_API_KEY` |
38
+ | Pexels video search | No install needed | `PEXELS_API_KEY` |
40
39
 
41
40
  Run the selected command, add its key to `.env.local`, and restart the server.
42
41
  Only selected provider packages are installed. `npx vanillasky doctor` reports
@@ -84,18 +83,22 @@ both boundaries.
84
83
  ## An immediate intro, then moving footage
85
84
 
86
85
  The default chat uses a template introduction while its first shot prepares,
87
- then generated footage with narration and subtitles. Relevant stock is the
88
- fallback when generation is unavailable or fails. The planner adapts its
86
+ then footage with narration and subtitles. Choose AI video or Pexels in Settings.
87
+ AI mode never substitutes stock, and Pexels mode never calls the AI-video provider.
88
+ Missing or late footage becomes a useful chapter scene. The planner adapts its
89
89
  visible actions and spoken beats to explanations, stories, comedy, imagination,
90
90
  and practical requests. It does not choose body templates.
91
91
 
92
+ Speech and footage prepare together. Silent clips loop through the remaining
93
+ narration when necessary, and every answer preserves its intended ending.
94
+
92
95
  Packaged templates remain available for custom compositions and source ownership.
93
96
 
94
97
  Copy template source only when you want to own and edit it:
95
98
 
96
99
  ```bash
97
100
  npm install --save-dev tsx
98
- npx vanillasky templates add bigNumber
101
+ npx vanillasky templates add chapterTitle
99
102
  ```
100
103
 
101
104
  That compiler is needed only for source-owned templates. See
@@ -118,6 +121,7 @@ MP4/WebM export remains application-owned.
118
121
  | Add media or voice | [Media and voice](docs/media-and-audio.md) |
119
122
  | Persist and replay results | [Performance measurements](docs/performance.md) · [Persistence and replay](docs/persistence.md) |
120
123
  | Test routes and streams | [Test integrations](docs/testing.md) |
124
+ | Iterate on SDK chat | [Development](docs/development.md): `dev:chat`, `check:chat`, `verify:release` |
121
125
  | Deploy securely | [Production](docs/production.md) · [Security](docs/security.md) |
122
126
  | Inspect the API contract | [Public API](PUBLIC-API.md) · [Protocol](docs/reference/protocol.md) |
123
127
 
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  VideoFrame
3
- } from "./chunk-3U2F7C7C.js";
3
+ } from "./chunk-WZFLEPLM.js";
4
4
  import "./chunk-224QNWRA.js";
5
- import "./chunk-YZZSWGC3.js";
5
+ import "./chunk-OOBT4X46.js";
6
6
  import "./chunk-SPVTJH3F.js";
7
7
  import "./chunk-R3XAOMKP.js";
8
8
  import "./chunk-73NTSFFI.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  SceneBackground,
3
3
  getMediaBackgroundProps
4
- } from "./chunk-LJR5VLEI.js";
4
+ } from "./chunk-QZAZT44G.js";
5
5
  import {
6
6
  editorialFont
7
7
  } from "./chunk-4YM2M62S.js";
@@ -2,8 +2,9 @@ import {
2
2
  darken,
3
3
  resolveTokens,
4
4
  useMediaAudio,
5
+ useMediaFailure,
5
6
  useNarrationPreroll
6
- } from "./chunk-YZZSWGC3.js";
7
+ } from "./chunk-OOBT4X46.js";
7
8
 
8
9
  // src/visual-system/scene-templates/scene-video-backdrop.tsx
9
10
  import { useCallback, useEffect, useRef, useState } from "react";
@@ -243,6 +244,7 @@ var SceneVideoBackdrop = ({
243
244
  onError
244
245
  }) => {
245
246
  const inheritedAudio = useMediaAudio();
247
+ const reportMediaFailure = useMediaFailure();
246
248
  const inheritedPreroll = useNarrationPreroll();
247
249
  const rewindPreroll = preparingNarration || inheritedPreroll;
248
250
  const resolvedMuted = muted ?? inheritedAudio.muted;
@@ -252,7 +254,6 @@ var SceneVideoBackdrop = ({
252
254
  const [decodedVideoUrl, setDecodedVideoUrl] = useState();
253
255
  const [waitingKey, setWaitingKey] = useState();
254
256
  const [exhaustedKey, setExhaustedKey] = useState();
255
- const continuityReplay = useRef(void 0);
256
257
  const videoRef = useRef(null);
257
258
  const startedVideoUrl = useRef(void 0);
258
259
  const startedPlaybackId = useRef(void 0);
@@ -263,6 +264,7 @@ var SceneVideoBackdrop = ({
263
264
  if (presentationRef.current.key === videoPresentationKey && presentationRef.current.playing) {
264
265
  setExhaustedKey(videoPresentationKey);
265
266
  onError?.();
267
+ reportMediaFailure?.();
266
268
  }
267
269
  };
268
270
  const fitDuration = useCallback((video) => {
@@ -273,11 +275,10 @@ var SceneVideoBackdrop = ({
273
275
  }, [fitDuration]);
274
276
  const continueMotion = (video) => {
275
277
  if (!isPlaying) return;
276
- if (!resolvedMuted || continuityReplay.current === videoPresentationKey) {
277
- setExhaustedKey(videoPresentationKey);
278
+ if (!resolvedMuted) {
279
+ unavailable();
278
280
  return;
279
281
  }
280
- continuityReplay.current = videoPresentationKey;
281
282
  video.currentTime = 0;
282
283
  void video.play().catch(unavailable);
283
284
  };
@@ -9,11 +9,12 @@ function ExternalVideoBackdropProvider({
9
9
  audioMuted = true,
10
10
  audioVolume = 1,
11
11
  preparingNarration = false,
12
+ onMediaError,
12
13
  children
13
14
  }) {
14
15
  const value = React.useMemo(
15
- () => ({ mode, audioMuted, audioVolume, preparingNarration }),
16
- [mode, audioMuted, audioVolume, preparingNarration]
16
+ () => ({ mode, audioMuted, audioVolume, preparingNarration, onMediaError }),
17
+ [mode, audioMuted, audioVolume, preparingNarration, onMediaError]
17
18
  );
18
19
  return /* @__PURE__ */ jsx(BackdropContext.Provider, { value, children });
19
20
  }
@@ -27,6 +28,9 @@ function useMediaAudio() {
27
28
  function useNarrationPreroll() {
28
29
  return React.useContext(BackdropContext).preparingNarration === true;
29
30
  }
31
+ function useMediaFailure() {
32
+ return React.useContext(BackdropContext).onMediaError;
33
+ }
30
34
 
31
35
  // src/visual-system/scene-templates/tokens.ts
32
36
  var STYLE_PRESETS = {
@@ -147,5 +151,6 @@ export {
147
151
  ExternalVideoBackdropProvider,
148
152
  useExternalVideoBackdrop,
149
153
  useMediaAudio,
150
- useNarrationPreroll
154
+ useNarrationPreroll,
155
+ useMediaFailure
151
156
  };
@@ -3,13 +3,13 @@ import {
3
3
  SceneVideoBackdrop,
4
4
  getBackgroundTransform,
5
5
  resolveMediaPosition
6
- } from "./chunk-SI6CFFAA.js";
6
+ } from "./chunk-O6FBIB4L.js";
7
7
  import {
8
8
  resolveMediaType
9
9
  } from "./chunk-224QNWRA.js";
10
10
  import {
11
11
  useExternalVideoBackdrop
12
- } from "./chunk-YZZSWGC3.js";
12
+ } from "./chunk-OOBT4X46.js";
13
13
 
14
14
  // src/visual-system/scene-templates/scene-background.tsx
15
15
  import { useEffect, useState } from "react";
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  ExternalVideoBackdropProvider,
7
7
  resolveDensity
8
- } from "./chunk-YZZSWGC3.js";
8
+ } from "./chunk-OOBT4X46.js";
9
9
  import {
10
10
  resolveVideoTimeline
11
11
  } from "./chunk-SPVTJH3F.js";
@@ -209,7 +209,7 @@ var SceneBoundary = class extends Component {
209
209
  }
210
210
  };
211
211
  var SCENE_TRANSITION_SECONDS = 0.3;
212
- var SceneVideoBackdrop = lazy(() => import("./scene-video-backdrop-OWUXPXHZ.js").then((module) => ({ default: module.SceneVideoBackdrop })));
212
+ var SceneVideoBackdrop = lazy(() => import("./scene-video-backdrop-4EZVVQY7.js").then((module) => ({ default: module.SceneVideoBackdrop })));
213
213
  var MEDIA_PREROLL_SECONDS = 1.2;
214
214
  var CONTIGUITY_ULP_FACTOR = 4;
215
215
  var subscribeToDecoderPolicy = () => () => {
@@ -257,6 +257,7 @@ function sceneBackgroundChanges(left, right) {
257
257
  }
258
258
  function SceneLayer({
259
259
  onFramePresented,
260
+ onMediaError,
260
261
  kit,
261
262
  config,
262
263
  range,
@@ -274,7 +275,7 @@ function SceneLayer({
274
275
  zIndex,
275
276
  externalVideoBackdrop
276
277
  }) {
277
- const mediaFailed = externalVideoBackdrop === "fallback";
278
+ const mediaFailed = externalVideoBackdrop === "fallback" || range.scene.templateId === "cinemaMedia" && !String(range.scene.variables.mediaUrl || "").trim();
278
279
  const recoveryTitle = mediaFailed && range.scene.templateId === "cinemaMedia" && typeof range.scene.variables.fallbackText === "string" ? range.scene.variables.fallbackText : void 0;
279
280
  const template = kit.getTemplate(recoveryTitle ? "chapterTitle" : range.scene.templateId);
280
281
  const duration = range.end - range.start;
@@ -285,6 +286,7 @@ function SceneLayer({
285
286
  audioMuted: mediaAudioMuted || !playing,
286
287
  audioVolume: mediaAudioVolume,
287
288
  preparingNarration,
289
+ onMediaError,
288
290
  children: /* @__PURE__ */ jsxs(
289
291
  "div",
290
292
  {
@@ -594,6 +596,7 @@ function VideoFrame({
594
596
  kit,
595
597
  config,
596
598
  range: active,
599
+ onMediaError: () => markMediaFailed(sceneReadinessKey(active.scene)),
597
600
  progress,
598
601
  motionProgress,
599
602
  width: canvas.width,
@@ -640,6 +643,7 @@ function VideoFrame({
640
643
  kit,
641
644
  config,
642
645
  range: active,
646
+ onMediaError: () => markMediaFailed(sceneReadinessKey(active.scene)),
643
647
  progress,
644
648
  motionProgress,
645
649
  width: canvas.width,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  SceneBackground,
3
3
  getMediaBackgroundProps
4
- } from "./chunk-LJR5VLEI.js";
4
+ } from "./chunk-QZAZT44G.js";
5
5
 
6
6
  // src/visual-system/scene-templates/cinema-media.tsx
7
7
  import { jsx } from "react/jsx-runtime";
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  MediaScene,
3
3
  MediaSceneTemplate
4
- } from "./chunk-VVNZCY2U.js";
5
- import "./chunk-LJR5VLEI.js";
6
- import "./chunk-SI6CFFAA.js";
4
+ } from "./chunk-Z2ZI5G7O.js";
5
+ import "./chunk-QZAZT44G.js";
6
+ import "./chunk-O6FBIB4L.js";
7
7
  import "./chunk-224QNWRA.js";
8
- import "./chunk-YZZSWGC3.js";
8
+ import "./chunk-OOBT4X46.js";
9
9
  export {
10
10
  MediaScene,
11
11
  MediaSceneTemplate
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  EditorialSurface
3
- } from "./chunk-UCXQORDZ.js";
4
- import "./chunk-LJR5VLEI.js";
5
- import "./chunk-SI6CFFAA.js";
3
+ } from "./chunk-G5TYLTL5.js";
4
+ import "./chunk-QZAZT44G.js";
5
+ import "./chunk-O6FBIB4L.js";
6
6
  import {
7
7
  editorialLabel,
8
8
  fade
@@ -10,7 +10,7 @@ import {
10
10
  import {
11
11
  hasSceneMedia
12
12
  } from "./chunk-224QNWRA.js";
13
- import "./chunk-YZZSWGC3.js";
13
+ import "./chunk-OOBT4X46.js";
14
14
 
15
15
  // src/visual-system/scene-templates/comparison.tsx
16
16
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  EditorialSurface
3
- } from "./chunk-UCXQORDZ.js";
4
- import "./chunk-LJR5VLEI.js";
5
- import "./chunk-SI6CFFAA.js";
3
+ } from "./chunk-G5TYLTL5.js";
4
+ import "./chunk-QZAZT44G.js";
5
+ import "./chunk-O6FBIB4L.js";
6
6
  import {
7
7
  fade
8
8
  } from "./chunk-4YM2M62S.js";
9
9
  import "./chunk-224QNWRA.js";
10
- import "./chunk-YZZSWGC3.js";
10
+ import "./chunk-OOBT4X46.js";
11
11
 
12
12
  // src/visual-system/scene-templates/editorial-timeline.tsx
13
13
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  EditorialSurface
3
- } from "./chunk-UCXQORDZ.js";
4
- import "./chunk-LJR5VLEI.js";
5
- import "./chunk-SI6CFFAA.js";
3
+ } from "./chunk-G5TYLTL5.js";
4
+ import "./chunk-QZAZT44G.js";
5
+ import "./chunk-O6FBIB4L.js";
6
6
  import {
7
7
  editorialLabel,
8
8
  fade
@@ -10,7 +10,7 @@ import {
10
10
  import {
11
11
  hasSceneMedia
12
12
  } from "./chunk-224QNWRA.js";
13
- import "./chunk-YZZSWGC3.js";
13
+ import "./chunk-OOBT4X46.js";
14
14
 
15
15
  // src/visual-system/scene-templates/key-figure.tsx
16
16
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  MediaScene
3
- } from "./chunk-VVNZCY2U.js";
4
- import "./chunk-LJR5VLEI.js";
3
+ } from "./chunk-Z2ZI5G7O.js";
4
+ import "./chunk-QZAZT44G.js";
5
5
  import {
6
6
  spring
7
- } from "./chunk-SI6CFFAA.js";
7
+ } from "./chunk-O6FBIB4L.js";
8
8
  import {
9
9
  editorialFont
10
10
  } from "./chunk-4YM2M62S.js";
11
11
  import "./chunk-224QNWRA.js";
12
- import "./chunk-YZZSWGC3.js";
12
+ import "./chunk-OOBT4X46.js";
13
13
 
14
14
  // src/visual-system/scene-templates/mobile-message.tsx
15
15
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  EditorialSurface
3
- } from "./chunk-UCXQORDZ.js";
4
- import "./chunk-LJR5VLEI.js";
5
- import "./chunk-SI6CFFAA.js";
3
+ } from "./chunk-G5TYLTL5.js";
4
+ import "./chunk-QZAZT44G.js";
5
+ import "./chunk-O6FBIB4L.js";
6
6
  import {
7
7
  fade
8
8
  } from "./chunk-4YM2M62S.js";
9
9
  import {
10
10
  hasSceneMedia
11
11
  } from "./chunk-224QNWRA.js";
12
- import "./chunk-YZZSWGC3.js";
12
+ import "./chunk-OOBT4X46.js";
13
13
 
14
14
  // src/visual-system/scene-templates/quote.tsx
15
15
  import { jsx, jsxs } from "react/jsx-runtime";
package/dist/react.d.ts CHANGED
@@ -3,7 +3,7 @@ import { CSSProperties, ReactElement, ReactNode } from 'react';
3
3
  import { b as VideoEvent } from './events-B4YCc4vc.js';
4
4
  import { b as VideoOrientation, e as VideoScene, c as Video, i as VideoStyleOptions } from './types-DdZw4GRQ.js';
5
5
  import { T as TemplateRegistry } from './kit-DrRpdn0p.js';
6
- import { V as VideoChatMode, a as VideoChatAskOptions, b as VideoChatMedia, c as VideoChatSuggestion, d as VideoChatCapabilities, e as VideoChatWelcome } from './types-CdBmNTGD.js';
6
+ import { V as VideoChatMode, a as VideoChatAskOptions, b as VideoChatMedia, c as VideoChatSuggestion, d as VideoChatCapabilities, e as VideoChatWelcome } from './types-BqB8zC9u.js';
7
7
  import './catalog-types-WTbLP6Jh.js';
8
8
 
9
9
  type VideoPlaybackMode = "manual" | "muted-autoplay" | "autoplay-with-sound" | "autoplay-after-interaction";
@@ -185,6 +185,8 @@ interface VideoChatTurn {
185
185
  orientation: VideoOrientation;
186
186
  /** Generated footage keeps the orientation it was created in. */
187
187
  fixedOrientation: boolean;
188
+ /** Footage source selected for this answer; omitted in older saved turns. */
189
+ mode?: VideoChatMode;
188
190
  video?: Video;
189
191
  suggestions: readonly VideoChatSuggestion[];
190
192
  }