@vanillaskyai/video 0.10.17 → 0.10.18

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 CHANGED
@@ -4,6 +4,11 @@ VanillaSky follows semantic versioning. This changelog begins with the 0.1 beta.
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 0.10.18
8
+
9
+ - Preserve later valid shots after a malformed body record containing an unescaped newline, while keeping malformed initial containers rejected. Bound unfinished JSON records independently of provider chunk sizes.
10
+ - Keep the outgoing scene visible while a canonical image backdrop prepares or reaches its bounded chapter recovery.
11
+
7
12
  ## 0.10.17
8
13
 
9
14
  - Let video playback prepare without waiting for an optional poster, while retaining actual video-frame and narration readiness checks.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VideoFrame
3
- } from "./chunk-MXLVTOGR.js";
3
+ } from "./chunk-M4QTEJTK.js";
4
4
  import "./chunk-5JBMYQP6.js";
5
5
  import "./chunk-224QNWRA.js";
6
6
  import "./chunk-SPVTJH3F.js";
@@ -448,11 +448,15 @@ function VideoFrame({
448
448
  }
449
449
  const previousIndex = timeline.findIndex((range) => sceneReadinessKey(range.scene) === displayedKey.current);
450
450
  const previous = timeline[previousIndex];
451
- const canPrepare = (range) => Boolean(range && mediaAudioMuted && sceneHasVideoBackdrop(range) && supportsExternalVideoBackdrop(kit.getTemplate(range.scene.templateId)));
451
+ const canPrepare = (range) => Boolean(range && (mediaAudioMuted || !sceneHasVideoBackdrop(range)) && sceneHasBackdrop(range) && supportsExternalVideoBackdrop(kit.getTemplate(range.scene.templateId)));
452
452
  const canRetain = (range) => canPrepare(range) || range?.scene.templateId === "chapterTitle";
453
453
  const hasPlayableMedia = (range) => {
454
454
  if (!range || !preparedMedia.has(sceneReadinessKey(range.scene))) return false;
455
455
  const layer = [...recoveryRoot.current?.querySelectorAll("[data-layer-scene-id]") ?? []].find((node) => node.getAttribute("data-layer-scene-id") === range.scene.id);
456
+ if (!sceneHasVideoBackdrop(range)) {
457
+ const image = [...layer?.querySelectorAll("img") ?? []].find((element) => element.getAttribute("src") === range.scene.variables.mediaUrl);
458
+ return Boolean(image && image.getAttribute("src") === range.scene.variables.mediaUrl && image.complete && image.naturalWidth > 0);
459
+ }
456
460
  const video = layer?.querySelector("video");
457
461
  return Boolean(video && video.getAttribute("src") === range.scene.variables.mediaUrl && video.currentSrc === video.src && video.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA);
458
462
  };
package/dist/react.js CHANGED
@@ -40,7 +40,7 @@ import {
40
40
  VideoFrame,
41
41
  getDimensions,
42
42
  sceneReadinessKey
43
- } from "./chunk-MXLVTOGR.js";
43
+ } from "./chunk-M4QTEJTK.js";
44
44
  import "./chunk-5JBMYQP6.js";
45
45
  import "./chunk-224QNWRA.js";
46
46
  import {
package/dist/server.js CHANGED
@@ -1074,6 +1074,13 @@ function createChatShotPlanner(options) {
1074
1074
  for (; cursor < buffer.length; cursor++) {
1075
1075
  const character = buffer[cursor];
1076
1076
  if (quoted) {
1077
+ if ((character === "\n" || character === "\r") && brief && depth === 1 && buffer[0] === "{") {
1078
+ const raw = buffer.slice(0, cursor + 1);
1079
+ buffer = buffer.slice(cursor + 1);
1080
+ cursor = depth = 0;
1081
+ quoted = escaped = false;
1082
+ return raw;
1083
+ }
1077
1084
  if (escaped) escaped = false;
1078
1085
  else if (character === "\\") escaped = true;
1079
1086
  else if (character === '"') quoted = false;
@@ -1094,17 +1101,22 @@ function createChatShotPlanner(options) {
1094
1101
  for await (const delta of upstream) {
1095
1102
  context.signal.throwIfAborted();
1096
1103
  if (typeof delta !== "string") throw new Error("The LLM adapter returned a non-text delta");
1097
- buffer += delta;
1098
- if (buffer.length > 32768) throw new Error("Chat plan line exceeds the bounded stream limit");
1099
- let raw = takeFrame();
1100
- while (raw !== void 0) {
1101
- try {
1102
- const part = line(raw);
1103
- if (part) yield JSON.stringify(part) + "\n";
1104
- } catch (cause) {
1105
- reject(cause);
1104
+ for (let offset = 0; offset < delta.length; ) {
1105
+ const capacity = 32768 - buffer.length;
1106
+ if (capacity <= 0) throw new Error("Chat plan line exceeds the bounded stream limit");
1107
+ const piece = delta.slice(offset, offset + capacity);
1108
+ buffer += piece;
1109
+ offset += piece.length;
1110
+ let raw = takeFrame();
1111
+ while (raw !== void 0) {
1112
+ try {
1113
+ const part = line(raw);
1114
+ if (part) yield JSON.stringify(part) + "\n";
1115
+ } catch (cause) {
1116
+ reject(cause);
1117
+ }
1118
+ raw = takeFrame();
1106
1119
  }
1107
- raw = takeFrame();
1108
1120
  }
1109
1121
  }
1110
1122
  if (buffer.trim()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vanillaskyai/video",
3
- "version": "0.10.17",
3
+ "version": "0.10.18",
4
4
  "description": "Open-source voice-and-video chat SDK for AI applications.",
5
5
  "keywords": [
6
6
  "video-chat",
@@ -9,7 +9,7 @@
9
9
  "preview": "vite preview"
10
10
  },
11
11
  "dependencies": {
12
- "@vanillaskyai/video": "0.10.17",
12
+ "@vanillaskyai/video": "0.10.18",
13
13
  "react": "^19.2.8",
14
14
  "react-dom": "^19.2.8",
15
15
  "@ai-sdk/anthropic": "^3.0.0",