@vanillaskyai/video 0.10.12 → 0.10.14
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,14 @@ VanillaSky follows semantic versioning. This changelog begins with the 0.1 beta.
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.10.14
|
|
8
|
+
|
|
9
|
+
- Attach content-free record-shape diagnostics to rejected chat plans without accepting alternate formats or exposing model output.
|
|
10
|
+
|
|
11
|
+
## 0.10.13
|
|
12
|
+
|
|
13
|
+
- Plan concise AI answers around the configured video-attempt budget, including the ending, while retaining complete authored narration and chapter recovery.
|
|
14
|
+
|
|
7
15
|
## 0.10.12
|
|
8
16
|
|
|
9
17
|
- Use query context to choose between equally relevant Pexels subject matches in the starter, while preserving subject, activity and equipment priority.
|
package/dist/server.js
CHANGED
|
@@ -892,6 +892,24 @@ function continueAfterOpening(narration, earlier) {
|
|
|
892
892
|
|
|
893
893
|
// src/server/chat-shot-planner.ts
|
|
894
894
|
var object = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
895
|
+
function planShapeError(value) {
|
|
896
|
+
const part = object(value);
|
|
897
|
+
const has = (key) => Boolean(part && Object.hasOwn(part, key));
|
|
898
|
+
const shape = value === null ? "null" : Array.isArray(value) ? "array" : typeof value;
|
|
899
|
+
const discriminator = !has("type") ? "missing" : part.type === "answer" || part.type === "shot" ? part.type : typeof part.type === "string" ? "other-string" : "non-string";
|
|
900
|
+
return new Error("Chat plan requires an answer brief followed by shots", { cause: {
|
|
901
|
+
code: "chat_plan_shape",
|
|
902
|
+
shape,
|
|
903
|
+
discriminator,
|
|
904
|
+
fields: {
|
|
905
|
+
opening: has("opening"),
|
|
906
|
+
subject: has("subject"),
|
|
907
|
+
development: has("development"),
|
|
908
|
+
visualDirection: has("visualDirection"),
|
|
909
|
+
ending: has("ending")
|
|
910
|
+
}
|
|
911
|
+
} });
|
|
912
|
+
}
|
|
895
913
|
function text(value, maximum) {
|
|
896
914
|
return typeof value === "string" && value.trim().length <= maximum ? value.trim() : "";
|
|
897
915
|
}
|
|
@@ -993,7 +1011,8 @@ function createChatShotPlanner(options) {
|
|
|
993
1011
|
const line = (raw) => {
|
|
994
1012
|
const trimmed = raw.trim();
|
|
995
1013
|
if (!trimmed || /^```(?:json|ndjson)?$/i.test(trimmed)) return;
|
|
996
|
-
const
|
|
1014
|
+
const value = JSON.parse(trimmed);
|
|
1015
|
+
const part = object(value);
|
|
997
1016
|
if (part?.type === "answer") {
|
|
998
1017
|
if (brief) throw new Error("Chat answer brief was emitted more than once");
|
|
999
1018
|
brief = { opening: text(part.opening, 300), subject: text(part.subject, 80), visualDirection: text(part.visualDirection, 600), development: text(part.development, 2e3) };
|
|
@@ -1007,7 +1026,7 @@ function createChatShotPlanner(options) {
|
|
|
1007
1026
|
options.publishOpening(brief.opening ? { line: brief.opening, keyword: brief.subject } : void 0);
|
|
1008
1027
|
return;
|
|
1009
1028
|
}
|
|
1010
|
-
if (part?.type !== "shot") throw
|
|
1029
|
+
if (part?.type !== "shot") throw planShapeError(value);
|
|
1011
1030
|
if (!brief) throw new Error("Chat shot arrived before its answer brief");
|
|
1012
1031
|
const shot = readShot(part, clipDurationSec, brief.subject);
|
|
1013
1032
|
if (shot.narration === brief.ending?.narration) return;
|
|
@@ -1177,7 +1196,8 @@ function createVideoChatResponseInstructions(generatedVideoAvailable, openingAlr
|
|
|
1177
1196
|
"Write a complete, intentful video answer as newline-delimited JSON. Match the user's form and tone; mixed intents can combine directions.",
|
|
1178
1197
|
`First write one brief: {"type":"answer","intent":"explanation|story|comedy|imagination|practical","opening":"a short inviting spoken introduction of 6\u20139 words","subject":"literal visual subject","development":"the essential development of this answer","visualDirection":"consistent subjects, appearance and visual approach","ending":{"title":"short meaningful chapter title, at most 65 characters","narration":"the authored payoff","subject":"literal subject","action":"visible action or change","durationSec":${clipDurationSec},"continuity":"cut|continue"}}.`,
|
|
1179
1198
|
`Then stream each developing shot on its own line: {"type":"shot","title":"short meaningful chapter title, at most 65 characters","narration":"the exact spoken beat","subject":"2\u20138 literal filmable words, at most 80 characters","action":"concrete subject, action or visible change and useful framing","durationSec":${clipDurationSec},"continuity":"cut|continue"}.`,
|
|
1180
|
-
`The selected footage mode is ${mode === "pexels" ? "Pexels stock search: use literal filmable subjects; never imply stock proves a mechanism or depicts fictional events exactly" : `AI video, with at most ${generatedVideoAvailable ? maxGeneratedVideos : 0} generation attempts`}. Missing footage becomes the authored chapter title, with complete narration.
|
|
1199
|
+
`The selected footage mode is ${mode === "pexels" ? "Pexels stock search: use literal filmable subjects; never imply stock proves a mechanism or depicts fictional events exactly" : `AI video, with at most ${generatedVideoAvailable ? maxGeneratedVideos : 0} generation attempts`}. Missing footage becomes the authored chapter title, with complete narration. Never truncate already-authored narration when footage fails. The host selects providers; do not make source choices.`,
|
|
1200
|
+
...mode === "cinematic" ? [generatedVideoAvailable && maxGeneratedVideos > 0 ? `Plan at most ${maxGeneratedVideos} generated-video beats in total, including the saved ending. Use at most ${maxGeneratedVideos - 1} developing shot records; the ending uses the remaining beat. The opening chapter does not consume a generated clip. Before writing, choose a concise, complete treatment that fits this budget: combine related ideas, preserve essential facts and qualifiers, and finish the requested answer. Do not plan an extra chapter tail simply because generation attempts will run out.${maxGeneratedVideos === 1 ? " Put the complete answer in the saved ending, set development to an empty string, and emit no developing shot records." : ""}` : "No generated-video attempts are available; plan a complete chapter-led answer with a useful ending. Do not omit the answer to satisfy a zero clip budget."] : [],
|
|
1181
1201
|
...mode === "pexels" ? ["Stock queries must retain the essential subject, activity and distinguishing equipment in the shot's subject field, within its word limit. That field alone is the search query; action and visualDirection do not refine it. Prefer common observable actions with usable framing. Do not replace the required actor or activity with scenery, a different sport or a loosely related setting. Preserve fictional or comic narration, but do not depend on stock showing an exact invented expression or sequence; choose an illustrative action that supports the beat."] : [],
|
|
1182
1202
|
...mode === "pexels" ? ['Include stockSelection on every shot and the saved ending when the essential subject is known: "stockSelection":{"subject":"essential actor or object category","activity":"optional literal activity","equipment":"optional distinguishing equipment","exclude":["optional contradictory subject or activity"]}. Each phrase must be 1\u20134 words and at most 48 characters; exclude has at most 3 phrases. The essential subject is separate from the setting: do not use scenery, mood, camera framing or incidental appearance as the actor. Keep the search query broad enough to find footage; the optional hint helps select results without substituting a different actor or task. Use exclusions only for actual contradictions, not every detail absent from the story. Omit unknown fields or the whole hint rather than inventing an anchor. This is selection guidance, not verification that footage depicts the exact narration.'] : [],
|
|
1183
1203
|
"For a very short answer whose ending alone fulfills the request, development may be empty and no developing shots are needed. Otherwise, develop the essential content before the ending.",
|
|
@@ -96,7 +96,10 @@ stream-reconnect contract.
|
|
|
96
96
|
|
|
97
97
|
Set `maxGeneratedVideos` on `createVideoChatHandler` to a nonnegative safe integer
|
|
98
98
|
(default `5`). This is a per-response generation attempt limit, including
|
|
99
|
-
failures. AI
|
|
99
|
+
failures. The default AI planner is instructed to fit a concise, complete answer
|
|
100
|
+
within that many visual beats, including the ending. This is model guidance, not
|
|
101
|
+
a guaranteed shot count: already-authored content is retained if the model
|
|
102
|
+
exceeds the budget. AI mode uses authored chapter recovery after the allowance is reached;
|
|
100
103
|
`0` skips all generated footage. Pexels mode searches stock independently and
|
|
101
104
|
never consumes the generated-video allowance. Retries inside your
|
|
102
105
|
provider callback can incur additional charges; bound those separately. Never
|
package/package.json
CHANGED