@vanillaskyai/video 0.10.22 → 0.11.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.
- package/CHANGELOG.md +74 -1
- package/PUBLIC-API.md +45 -438
- package/README.md +57 -96
- package/dist/builtin-metadata-OT6V7TB4.js +8 -0
- package/dist/{chapter-title-2JVDU62E.js → chapter-title-2RCXX7SN.js} +1 -2
- package/dist/{chunk-PDQFQIQW.js → chunk-3EQ6PVWL.js} +1 -1
- package/dist/chunk-4G4JBMCM.js +37 -0
- package/dist/{chunk-7AA2JWHZ.js → chunk-5DOQTIMD.js} +6 -6
- package/dist/chunk-666HGTVZ.js +41 -0
- package/dist/{chunk-7M56IUUX.js → chunk-6Z3ID54H.js} +0 -18
- package/dist/{chunk-5BSJLT6H.js → chunk-E7FHBLAC.js} +16 -29
- package/dist/chunk-HIQM4J3U.js +30 -0
- package/dist/chunk-ISWQ6T5X.js +36 -0
- package/dist/{chunk-224QNWRA.js → chunk-K5J7ESRO.js} +1 -10
- package/dist/chunk-KMVRBUL5.js +50 -0
- package/dist/chunk-NM4CXXZY.js +25 -0
- package/dist/{chunk-44WND2VP.js → chunk-V2CP7PVY.js} +19 -63
- package/dist/{chunk-3O7OMMMF.js → chunk-WZESNEPT.js} +0 -1
- package/dist/{chunk-RXTN2CW6.js → chunk-Z3DLSLAJ.js} +1 -1
- package/dist/cinema-media-YZ2UANJG.js +365 -0
- package/dist/cli.js +154 -1753
- package/dist/{compose-video-BH5K6XWT.js → compose-video-H2YUQDUY.js} +4 -4
- package/dist/{events-B4YCc4vc.d.ts → events-BZAfl0Dm.d.ts} +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +4 -6
- package/dist/preload-media-23JXUFCF.js +77 -0
- package/dist/react.d.ts +39 -15
- package/dist/react.js +1350 -739
- package/dist/scene-validation-SGLLLFY5.js +9 -0
- package/dist/server.d.ts +67 -117
- package/dist/server.js +262 -614
- package/dist/test.d.ts +2 -2
- package/dist/test.js +21 -21
- package/dist/{text-stream-LD364KBI.js → text-stream-SOVLYR2L.js} +2 -2
- package/dist/{types-BqB8zC9u.d.ts → types-CG-kPI81.d.ts} +3 -1
- package/dist/{types-DdZw4GRQ.d.ts → types-ht-Zw3Wv.d.ts} +1 -1
- package/docs/agent-integration.md +19 -64
- package/docs/architecture.md +82 -87
- package/docs/customization.md +49 -66
- package/docs/development.md +18 -17
- package/docs/errors.md +4 -4
- package/docs/getting-started.md +74 -93
- package/docs/media-and-audio.md +9 -7
- package/docs/performance.md +11 -6
- package/docs/persistence.md +3 -7
- package/docs/production.md +4 -15
- package/docs/prompt-and-input.md +1 -2
- package/docs/provider-integration.md +134 -181
- package/docs/reference/protocol.md +5 -14
- package/docs/reference/provider-adapters.md +21 -13
- package/docs/security.md +1 -14
- package/docs/testing.md +56 -123
- package/package.json +5 -27
- package/starters/video-chat/.env.example +12 -4
- package/starters/video-chat/.env.native.example +13 -0
- package/starters/video-chat/README.md +72 -11
- package/starters/video-chat/package.json +1 -1
- package/starters/video-chat/providers/text-native.ts +94 -0
- package/starters/video-chat/providers/text.ts +19 -0
- package/starters/video-chat/providers/transcription.ts +32 -0
- package/starters/video-chat/providers/video-custom.ts +45 -0
- package/starters/video-chat/providers/video-delivery.ts +57 -0
- package/starters/video-chat/providers/video-google.ts +48 -0
- package/starters/video-chat/providers/video-job.ts +103 -0
- package/starters/video-chat/providers/video-runway.ts +45 -0
- package/starters/video-chat/providers/video.ts +39 -63
- package/starters/video-chat/server.ts +3 -29
- package/starters/video-chat/vite.config.ts +2 -8
- package/styles/video-chat.css +8 -105
- package/dist/builtin-server-W4PLJUZ5.js +0 -8
- package/dist/catalog-types-WTbLP6Jh.d.ts +0 -78
- package/dist/check-runtime.d.ts +0 -15
- package/dist/check-runtime.js +0 -96
- package/dist/chunk-2E6T633S.js +0 -27
- package/dist/chunk-4YM2M62S.js +0 -13
- package/dist/chunk-4ZJLPHBV.js +0 -684
- package/dist/chunk-5JBMYQP6.js +0 -156
- package/dist/chunk-73NTSFFI.js +0 -81
- package/dist/chunk-EGVQODKU.js +0 -83
- package/dist/chunk-HFVNAPHZ.js +0 -35
- package/dist/chunk-IIN5M5HW.js +0 -697
- package/dist/chunk-IQMYK5DX.js +0 -133
- package/dist/chunk-IR44XKBI.js +0 -46
- package/dist/chunk-JKVOBTRO.js +0 -145
- package/dist/chunk-LVM5Q2DL.js +0 -68
- package/dist/chunk-M4QTEJTK.js +0 -709
- package/dist/chunk-QSBDB4J2.js +0 -16
- package/dist/chunk-R3XAOMKP.js +0 -29
- package/dist/chunk-SPVTJH3F.js +0 -24
- package/dist/chunk-YAHT3LST.js +0 -663
- package/dist/chunk-ZD2VTUYR.js +0 -28
- package/dist/cinema-media-HYCDG65Z.js +0 -11
- package/dist/comparison-XXAP4S4J.js +0 -36
- package/dist/editorial-timeline-VUQC6KPA.js +0 -42
- package/dist/key-figure-4TJK7HLT.js +0 -29
- package/dist/kit-DrRpdn0p.d.ts +0 -79
- package/dist/mobile-message-FIHAO6XC.js +0 -49
- package/dist/preload-media-LJXWKTWG.js +0 -57
- package/dist/quote-GRPIYKQJ.js +0 -32
- package/dist/system-prompt-AG26KJAA.js +0 -12
- package/dist/template-catalog.d.ts +0 -400
- package/dist/template-catalog.js +0 -6
- package/dist/templates.d.ts +0 -25
- package/dist/templates.js +0 -102
- package/dist/validate-4OUD2CLX.js +0 -10
- package/docs/concepts.md +0 -107
- package/docs/custom-templates.md +0 -346
- package/docs/immersive-interface.md +0 -86
- package/docs/maintainers/cinematic-migration.md +0 -38
- package/docs/motion-and-effects.md +0 -109
- package/docs/reference/design-system.html +0 -125
- package/docs/responsive-orientation.md +0 -37
- package/docs/streaming-protocol.md +0 -15
- package/examples/custom-template/README.md +0 -19
- package/examples/custom-template/minimal-text.tsx +0 -82
- package/examples/custom-template/structured-data.tsx +0 -104
- package/registry/items/backgrounds.json +0 -70
- package/registry/items/chapterTitle.json +0 -80
- package/registry/items/cinemaMedia.json +0 -136
- package/registry/items/comparison.json +0 -168
- package/registry/items/editorialTimeline.json +0 -172
- package/registry/items/keyFigure.json +0 -162
- package/registry/items/mobileMessage.json +0 -153
- package/registry/items/motion.json +0 -45
- package/registry/items/quote.json +0 -161
- package/registry/items/template-context.json +0 -31
- package/registry/items/theme.json +0 -47
- package/registry/items/typography.json +0 -47
package/dist/chunk-IQMYK5DX.js
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
validateTemplateSchemaValue
|
|
3
|
-
} from "./chunk-EGVQODKU.js";
|
|
4
|
-
import {
|
|
5
|
-
getTemplateSchemaGates,
|
|
6
|
-
isMeaningfullyPresentTemplateValue
|
|
7
|
-
} from "./chunk-73NTSFFI.js";
|
|
8
|
-
|
|
9
|
-
// src/visual-system/catalog/validate.ts
|
|
10
|
-
function* walkSchemaValue(property, value, path) {
|
|
11
|
-
yield { property, value, path };
|
|
12
|
-
if (property.type === "array" && property.items && Array.isArray(value)) {
|
|
13
|
-
for (const [index, item] of value.entries()) {
|
|
14
|
-
yield* walkSchemaValue(property.items, item, `${path}.${index}`);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
if (property.type === "object" && value && typeof value === "object" && !Array.isArray(value)) {
|
|
18
|
-
for (const [name, child] of Object.entries(property.properties ?? {})) {
|
|
19
|
-
if (Object.hasOwn(value, name)) {
|
|
20
|
-
yield* walkSchemaValue(child, value[name], `${path}.${name}`);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
function schemaValues(schema, variables) {
|
|
26
|
-
const values = [];
|
|
27
|
-
for (const [name, property] of Object.entries(schema.properties)) {
|
|
28
|
-
if (Object.hasOwn(variables, name)) values.push(...walkSchemaValue(property, variables[name], name));
|
|
29
|
-
}
|
|
30
|
-
return values;
|
|
31
|
-
}
|
|
32
|
-
function validateTemplateSceneStructure(schema, value, deferMediaUrls = false) {
|
|
33
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
34
|
-
throw new Error("Template variable variables must be object");
|
|
35
|
-
}
|
|
36
|
-
const object = value;
|
|
37
|
-
const requiredFields = new Set(schema.required ?? []);
|
|
38
|
-
for (const required of schema.required ?? []) {
|
|
39
|
-
if (!Object.hasOwn(object, required)) throw new Error(`Template variable ${required} is required`);
|
|
40
|
-
}
|
|
41
|
-
if (schema.additionalProperties === false) {
|
|
42
|
-
for (const name of Object.keys(object)) {
|
|
43
|
-
if (!Object.hasOwn(schema.properties, name)) throw new Error(`Template variable ${name} is not declared`);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
for (const [name, property] of Object.entries(schema.properties)) {
|
|
47
|
-
if (Object.hasOwn(object, name)) validateTemplateSchemaValue(property, object[name], name, {
|
|
48
|
-
deferMediaUrls,
|
|
49
|
-
errorPrefix: "Template variable ",
|
|
50
|
-
includeTypeArticle: true,
|
|
51
|
-
allowEmptyOptionalMedia: property.default === "",
|
|
52
|
-
optional: !requiredFields.has(name)
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
function validateConditionalPresence(templateId, groups, variables) {
|
|
57
|
-
for (const group of groups) {
|
|
58
|
-
if (group.some((field) => Object.hasOwn(variables, field) && isMeaningfullyPresentTemplateValue(variables[field]))) continue;
|
|
59
|
-
throw new Error(`Template ${templateId} requires a non-empty value for ${group.join(" or ")}`);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
function suppliedUrls(input) {
|
|
63
|
-
const urls = /* @__PURE__ */ new Set();
|
|
64
|
-
for (const media of input.suppliedMedia ?? []) {
|
|
65
|
-
urls.add(media.url);
|
|
66
|
-
if (media.posterUrl) urls.add(media.posterUrl);
|
|
67
|
-
}
|
|
68
|
-
return urls;
|
|
69
|
-
}
|
|
70
|
-
function containsSuppliedQuantity(input, value) {
|
|
71
|
-
if (typeof value !== "string" && typeof value !== "number") return false;
|
|
72
|
-
const normalize = (text) => text.normalize("NFKC").replace(/\u2212/g, "-").replace(/\s+/gu, " ").replace(/([\p{Sc}]) (?=[+−-]?\d)/gu, "$1").replace(/(\d) (?=[%‰])/gu, "$1").trim();
|
|
73
|
-
const quantity = normalize(String(value));
|
|
74
|
-
if (!/\d/u.test(quantity)) return false;
|
|
75
|
-
const source = normalize(input);
|
|
76
|
-
let offset = source.indexOf(quantity);
|
|
77
|
-
while (offset !== -1) {
|
|
78
|
-
const before = source.slice(0, offset);
|
|
79
|
-
const after = source.slice(offset + quantity.length);
|
|
80
|
-
const beginsInside = /[\p{L}\p{N}\p{Sc}%‰+−-]$/u.test(before) || /\d[.,]$/u.test(before);
|
|
81
|
-
const endsInside = /^[\p{L}\p{N}\p{Sc}%‰]/u.test(after) || /^[.,]\d/u.test(after);
|
|
82
|
-
const dropsUnit = /\d$/u.test(quantity) && /^ (?:%|‰|percent\b|per cent\b|thousand\b|million\b|billion\b|trillion\b|usd\b|eur\b|gbp\b|dollars?\b|euros?\b|pounds?\b)/iu.test(after);
|
|
83
|
-
if (!beginsInside && !endsInside && !dropsUnit) return true;
|
|
84
|
-
offset = source.indexOf(quantity, offset + 1);
|
|
85
|
-
}
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
function createTemplateSceneValidator(options) {
|
|
89
|
-
return (scene, context) => {
|
|
90
|
-
const template = options.kit.getTemplateMetadata(scene.templateId);
|
|
91
|
-
if (!template) throw new Error(`Template ${scene.templateId} is not installed`);
|
|
92
|
-
const schema = template.schema;
|
|
93
|
-
const gates = getTemplateSchemaGates(schema);
|
|
94
|
-
validateConditionalPresence(scene.templateId, gates.requiredAnyOf, scene.variables);
|
|
95
|
-
validateTemplateSceneStructure(schema, scene.variables);
|
|
96
|
-
const values = schemaValues(schema, scene.variables);
|
|
97
|
-
const allowedUrls = suppliedUrls(context.input);
|
|
98
|
-
const suppliedImageUrls = new Set((context.input.suppliedMedia ?? []).filter(({ type }) => type === "image").map(({ url }) => url));
|
|
99
|
-
if (gates.requiresScreenshot) {
|
|
100
|
-
const screenshots = values.filter(({ property }) => property.format === "supplied-image").map(({ value }) => value).filter((value) => typeof value === "string" && Boolean(value.trim()));
|
|
101
|
-
if (!screenshots.length || screenshots.some((url) => !suppliedImageUrls.has(url))) {
|
|
102
|
-
throw new Error(`Template ${scene.templateId} requires a supplied screenshot image`);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
for (const { path, property, value } of values) {
|
|
106
|
-
const isMedia = property.format === "uri" || property.format === "supplied-image";
|
|
107
|
-
if (!isMedia || typeof value !== "string" || !value.trim()) continue;
|
|
108
|
-
const permitted = allowedUrls.has(value) || options.allowMediaUrl?.(value, {
|
|
109
|
-
...context,
|
|
110
|
-
scene,
|
|
111
|
-
variable: path
|
|
112
|
-
});
|
|
113
|
-
if (!permitted) throw new Error(`Template variable ${path} must use supplied media`);
|
|
114
|
-
}
|
|
115
|
-
if (gates.requiresStat) {
|
|
116
|
-
const quantities = values.filter(({ property }) => property.format === "grounded-stat");
|
|
117
|
-
if (!quantities.length || quantities.some(({ value }) => !containsSuppliedQuantity(context.input.input, value))) {
|
|
118
|
-
throw new Error(`Template ${scene.templateId} requires an exact supplied quantity, preserving its unit`);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
if (gates.requiresQuote) {
|
|
122
|
-
const quoteValues = values.filter(({ property, value }) => property.format === "grounded-quote" && typeof value === "string" && value.trim()).map(({ value }) => String(value).trim());
|
|
123
|
-
if (!quoteValues.length || quoteValues.some((quote) => !context.input.input.includes(quote))) {
|
|
124
|
-
throw new Error(`Template ${scene.templateId} requires an exact quote from the raw input`);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export {
|
|
131
|
-
validateTemplateSceneStructure,
|
|
132
|
-
createTemplateSceneValidator
|
|
133
|
-
};
|
package/dist/chunk-IR44XKBI.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BUILTIN_TEMPLATE_CATALOG
|
|
3
|
-
} from "./chunk-IIN5M5HW.js";
|
|
4
|
-
import {
|
|
5
|
-
assertTemplateTransitionMetadata
|
|
6
|
-
} from "./chunk-2E6T633S.js";
|
|
7
|
-
|
|
8
|
-
// src/visual-system/catalog/server-kit.ts
|
|
9
|
-
function createServerTemplateRegistry(options) {
|
|
10
|
-
const byId = /* @__PURE__ */ new Map();
|
|
11
|
-
for (const template of options.templates) {
|
|
12
|
-
assertTemplateTransitionMetadata(template);
|
|
13
|
-
if (byId.has(template.id)) throw new Error(`Duplicate template id: ${template.id}`);
|
|
14
|
-
byId.set(template.id, template);
|
|
15
|
-
}
|
|
16
|
-
const templates = Object.freeze([...options.templates]);
|
|
17
|
-
const capabilities = { templates: templates.map(({ id }) => id) };
|
|
18
|
-
return Object.freeze({
|
|
19
|
-
capabilities,
|
|
20
|
-
getTemplateMetadata: (id) => byId.get(id),
|
|
21
|
-
listTemplateMetadata: () => [...templates]
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
function overlayServerTemplateRegistry(defaults, customer) {
|
|
25
|
-
const defaultTemplates = defaults.listTemplateMetadata();
|
|
26
|
-
const customerTemplates = customer.listTemplateMetadata();
|
|
27
|
-
const customerMetadata = new Map(customerTemplates.map((template) => [template.id, template]));
|
|
28
|
-
const defaultIds = new Set(defaultTemplates.map(({ id }) => id));
|
|
29
|
-
return createServerTemplateRegistry({
|
|
30
|
-
templates: [
|
|
31
|
-
...defaultTemplates.map((template) => customerMetadata.get(template.id) ?? template),
|
|
32
|
-
...customerTemplates.filter(({ id }) => !defaultIds.has(id))
|
|
33
|
-
]
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// src/visual-system/catalog/builtin-server.ts
|
|
38
|
-
var BUILTIN_SERVER_TEMPLATE_KIT = createServerTemplateRegistry({
|
|
39
|
-
templates: BUILTIN_TEMPLATE_CATALOG
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
export {
|
|
43
|
-
createServerTemplateRegistry,
|
|
44
|
-
overlayServerTemplateRegistry,
|
|
45
|
-
BUILTIN_SERVER_TEMPLATE_KIT
|
|
46
|
-
};
|
package/dist/chunk-JKVOBTRO.js
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createVideoSystemPrompt
|
|
3
|
-
} from "./chunk-LVM5Q2DL.js";
|
|
4
|
-
import {
|
|
5
|
-
PACING_PLANNER_RULES
|
|
6
|
-
} from "./chunk-3O7OMMMF.js";
|
|
7
|
-
import {
|
|
8
|
-
getTemplateSchemaGates,
|
|
9
|
-
templateVariableNotation
|
|
10
|
-
} from "./chunk-73NTSFFI.js";
|
|
11
|
-
|
|
12
|
-
// src/visual-system/catalog/media-resolver-contract.ts
|
|
13
|
-
function getStandardMediaResolverContract(schema) {
|
|
14
|
-
const keyword = schema.properties.mediaKeyword;
|
|
15
|
-
const url = schema.properties.mediaUrl;
|
|
16
|
-
const type = schema.properties.mediaType;
|
|
17
|
-
const allowedTypes = new Set(type?.enum ?? []);
|
|
18
|
-
if (keyword?.format !== "stock-media-keyword" || url?.format !== "uri" || !["photo", "video"].every((value) => allowedTypes.has(value))) {
|
|
19
|
-
return void 0;
|
|
20
|
-
}
|
|
21
|
-
return {
|
|
22
|
-
acceptsPoster: schema.properties.mediaPoster?.format === "uri"
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// src/visual-system/catalog/prompt.ts
|
|
27
|
-
function plannerProperty(property) {
|
|
28
|
-
return {
|
|
29
|
-
...property.description == null ? {} : { description: property.description },
|
|
30
|
-
...property.examples == null ? {} : { examples: property.examples.slice(0, 1) },
|
|
31
|
-
...property.type == null ? {} : { type: property.type },
|
|
32
|
-
...property.format == null ? {} : { format: property.format },
|
|
33
|
-
...property.enum == null ? {} : { enum: property.enum },
|
|
34
|
-
...property.minItems == null ? {} : { minItems: property.minItems },
|
|
35
|
-
...property.maxItems == null ? {} : { maxItems: property.maxItems },
|
|
36
|
-
...property.minLength == null ? {} : { minLength: property.minLength },
|
|
37
|
-
...property.maxLength == null ? {} : { maxLength: property.maxLength },
|
|
38
|
-
...property.minimum == null ? {} : { minimum: property.minimum },
|
|
39
|
-
...property.maximum == null ? {} : { maximum: property.maximum },
|
|
40
|
-
...property.items == null ? {} : { items: plannerProperty(property.items) },
|
|
41
|
-
...property.properties == null ? {} : {
|
|
42
|
-
properties: Object.fromEntries(Object.entries(property.properties).map(([name, child]) => [name, plannerProperty(child)]))
|
|
43
|
-
},
|
|
44
|
-
...property.required == null ? {} : { required: property.required },
|
|
45
|
-
...property.additionalProperties == null ? {} : {
|
|
46
|
-
additionalProperties: property.additionalProperties
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
function plannerSchema(schema, exposeMediaKeyword) {
|
|
51
|
-
const hiddenFields = exposeMediaKeyword ? /* @__PURE__ */ new Set() : /* @__PURE__ */ new Set(["mediaKeyword"]);
|
|
52
|
-
const properties = Object.fromEntries(
|
|
53
|
-
Object.entries(schema.properties).filter(([name]) => !hiddenFields.has(name)).map(([name, property]) => [name, name === "mediaKeyword" ? plannerProperty({ ...property, minLength: 2, maxLength: 80 }) : plannerProperty(property)])
|
|
54
|
-
);
|
|
55
|
-
const required = schema.required?.filter((name) => !hiddenFields.has(name));
|
|
56
|
-
return {
|
|
57
|
-
type: "object",
|
|
58
|
-
properties,
|
|
59
|
-
...required === void 0 ? {} : { required },
|
|
60
|
-
...schema.additionalProperties == null ? {} : {
|
|
61
|
-
additionalProperties: schema.additionalProperties
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
function isMediaProperty(property) {
|
|
66
|
-
return property?.format === "uri" || property?.format === "supplied-image" || property?.format === "stock-media-keyword";
|
|
67
|
-
}
|
|
68
|
-
function requiresAvailableMedia(template) {
|
|
69
|
-
const gates = getTemplateSchemaGates(template.schema);
|
|
70
|
-
return (template.schema.required ?? []).some((name) => isMediaProperty(template.schema.properties[name])) || gates.requiredAnyOf.some((group) => group.every((name) => isMediaProperty(template.schema.properties[name])));
|
|
71
|
-
}
|
|
72
|
-
function plannerCatalog(templates, mediaResolverAvailable) {
|
|
73
|
-
return templates.map((template) => {
|
|
74
|
-
const gates = getTemplateSchemaGates(template.schema);
|
|
75
|
-
const exposeMediaKeyword = mediaResolverAvailable && getStandardMediaResolverContract(template.schema) != null;
|
|
76
|
-
const variables = Object.fromEntries(
|
|
77
|
-
Object.entries(template.schema.properties).filter(([name]) => name !== "mediaKeyword" || exposeMediaKeyword).map(([name, property]) => [
|
|
78
|
-
name,
|
|
79
|
-
name === "mediaKeyword" ? "string{2..80}" : templateVariableNotation(property, template.schema.required?.includes(name) === true)
|
|
80
|
-
])
|
|
81
|
-
);
|
|
82
|
-
return {
|
|
83
|
-
id: template.id,
|
|
84
|
-
jobs: template.jobs,
|
|
85
|
-
use: template.useWhen ?? template.description,
|
|
86
|
-
...template.avoidWhen ? { avoid: template.avoidWhen } : {},
|
|
87
|
-
...template.minDuration == null && template.preferredDuration == null ? {} : {
|
|
88
|
-
seconds: [template.minDuration ?? null, template.preferredDuration ?? null]
|
|
89
|
-
},
|
|
90
|
-
...gates.requiresStat ? { requiresStat: true } : {},
|
|
91
|
-
...gates.requiresQuote ? { requiresQuote: true } : {},
|
|
92
|
-
...gates.requiresScreenshot ? { requiresScreenshot: true } : {},
|
|
93
|
-
...gates.requiredAnyOf.length > 0 ? { requiredAnyOf: gates.requiredAnyOf.map((group) => group.filter((name) => name !== "mediaKeyword" || exposeMediaKeyword)) } : {},
|
|
94
|
-
schema: plannerSchema(template.schema, exposeMediaKeyword),
|
|
95
|
-
variables
|
|
96
|
-
};
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
function createTemplateSystemPrompt(options) {
|
|
100
|
-
const templates = options.kit.listTemplateMetadata().filter((template) => !requiresAvailableMedia(template) || options.suppliedMediaAvailable === true || options.mediaResolverAvailable === true && getStandardMediaResolverContract(template.schema) != null);
|
|
101
|
-
const resolverMediaAvailable = options.mediaResolverAvailable === true && templates.some(({ schema }) => getStandardMediaResolverContract(schema) != null);
|
|
102
|
-
const basePrompt = createVideoSystemPrompt(options.knowledgeMode, options.narrate === true).split("\n").filter(
|
|
103
|
-
(line) => !line.includes("Never use media, ctaMedia, or reaction as the first generated body template") && // The rule that keeps the opening beat asset-free belongs to the same
|
|
104
|
-
// pair as the one below it: both exist so playback can start without
|
|
105
|
-
// waiting on a provider, and both go when the host owns that wait.
|
|
106
|
-
!(options.mediaOnFirstScene === true && line.includes("The first generated body scene must be asset-free")) && !(resolverMediaAvailable && line.includes("Never expose a loading placeholder or unresolved media keyword"))
|
|
107
|
-
).join("\n");
|
|
108
|
-
const mediaTemplates = templates.filter(({ schema }) => getStandardMediaResolverContract(schema) != null).map(({ id }) => id);
|
|
109
|
-
const terminalPayoffs = templates.filter(({ jobs }) => jobs?.includes("payoff")).map(({ id }) => id);
|
|
110
|
-
return [
|
|
111
|
-
basePrompt.trim(),
|
|
112
|
-
options.basePrompt?.trim() ? `
|
|
113
|
-
APPLICATION GUIDANCE
|
|
114
|
-
${options.basePrompt.trim()}` : void 0,
|
|
115
|
-
"",
|
|
116
|
-
"TRUSTED TEMPLATE CATALOG",
|
|
117
|
-
"Only use template IDs from this catalog. Only emit variables declared for the selected template.",
|
|
118
|
-
"Variable notation is type[count]{characters}(options)! where count is list cardinality, characters is the inclusive character count for a string or each string-array item, and ! means required. Omitted ! means optional.",
|
|
119
|
-
"Choose a template only when the permitted factual basis contains every fact it needs. Never invent peer values to complete a chart, comparison, stat set, timeline, or list.",
|
|
120
|
-
...PACING_PLANNER_RULES,
|
|
121
|
-
"Let narration carry ordinary lists. Use a structured overlay only when a comparison, sequence, exact quote or key figure adds understanding beyond the voice. Prefer relevant full-bleed footage for the remaining visual beats, with varied purposeful action and framing.",
|
|
122
|
-
"If the catalog includes a suitable ask template and the input supplies a grounded CTA or URL, keep that concise action closer as its own final scene instead of folding it into preceding content.",
|
|
123
|
-
"When a grounded CTA or URL is supplied and the catalog contains jobs:[ask], emit that final closer. A brand name may accompany the action but never qualifies as an ask by itself.",
|
|
124
|
-
terminalPayoffs.length > 0 ? `When there is no grounded action, end with a concise supported payoff using a suitable template from ${terminalPayoffs.join(", ")}. Do not repeat the hook or invent a CTA.` : void 0,
|
|
125
|
-
"requiresQuote is a hard gate: use those templates only for exact quoted words and attribution present in raw input. Never turn a role, relationship, or summary into speech. requiresScreenshot likewise needs an actual supplied screenshot URL.",
|
|
126
|
-
templates.some(({ schema }) => (schema["x-vanillasky"]?.requiredAnyOf?.length ?? 0) > 0) ? "requiredAnyOf is a hard presence gate: satisfy every listed group with at least one non-empty value." : void 0,
|
|
127
|
-
mediaTemplates.length > 0 && options.mediaOnFirstScene !== true ? `The host owns immediate startup; reserve external media templates (${mediaTemplates.join(", ")}) for later beats when an asset-free opening is required.` : void 0,
|
|
128
|
-
"For list and event variables emit actual JSON arrays. Follow each field's content budget; never use pipe-delimited strings or invent entries.",
|
|
129
|
-
resolverMediaAvailable ? "Media-capable scenes may carry mediaKeyword: a literal 2\u20138 word shot description, at most 80 characters. Choose mediaSource=generate for distinctive illustrative shots and mediaSource=stock for common subjects a verified asset can depict. For generated footage, optional shotDirection gives action, framing and continuity separately from the stock query. Keep people, actions and essential details precise. Never broaden an exact identity or action into unrelated atmosphere. Supply a grounded fallbackText where declared. Only the host fills mediaUrl and mediaPoster; never invent them. If no media fits an abstract beat, choose an appropriate graphic template instead." : "Use media only when a supplied asset satisfies the scene. Never invent asset URLs. Otherwise choose a grounded graphic template.",
|
|
130
|
-
"When the catalog offers media, make relevant footage the default. For a typical 30-second explanation start with roughly one structured explanatory overlay plus an optional brief chapter opening; other intents may need different pacing and visual emphasis. Do not chain graphic-only beats when honest media is available. Reuse suitable supplied media behind overlays with optional media fields; retain black when no relevant asset exists. Never invent a stock match or spend beyond host generation limits.",
|
|
131
|
-
"Catalog guidance describes composition; it is not a factual source and must never replace the permitted factual basis.",
|
|
132
|
-
JSON.stringify(plannerCatalog(templates, resolverMediaAvailable)),
|
|
133
|
-
// Last, because the catalogue is thousands of tokens of per-scene field
|
|
134
|
-
// lists and it is what the model matches when it emits a scene. The wire
|
|
135
|
-
// format above says narration belongs there; said only above, a third of
|
|
136
|
-
// the way through, it loses to the schema the model has just finished
|
|
137
|
-
// reading, and every scene comes back silent.
|
|
138
|
-
options.narrate === true ? '\nThe catalog lists variables only. Every scene.add also carries "narration" beside "variables" and "timing", as specified in the wire format above. A scene without it is incomplete.' : void 0
|
|
139
|
-
].filter((line) => line != null).join("\n");
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export {
|
|
143
|
-
getStandardMediaResolverContract,
|
|
144
|
-
createTemplateSystemPrompt
|
|
145
|
-
};
|
package/dist/chunk-LVM5Q2DL.js
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
// src/server/prompts/system-prompt.ts
|
|
2
|
-
function videoPlanInstruction(narrate = false) {
|
|
3
|
-
const narration = narrate ? `,"narration":"words spoken over this scene"` : "";
|
|
4
|
-
return `Wire format: newline-delimited JSON (NDJSON), exactly one complete JSON object per line.
|
|
5
|
-
Allowed plan parts:
|
|
6
|
-
{"type":"scene.add","scene":{"id":"stable-id","templateId":"trusted-template-id","variables":{},"timing":{"fixedDuration":4}${narration}}}
|
|
7
|
-
{"type":"scene.add","placement":"closer","scene":{"id":"closer","templateId":"trusted-closer-template-id","variables":{},"timing":{"fixedDuration":3}${narration}}}
|
|
8
|
-
{"type":"plan.complete","finishReason":"stop"}
|
|
9
|
-
Do not emit protocol envelopes, Markdown fences, comments, prose, partial objects, audio, generated source, or any part type not listed above.`;
|
|
10
|
-
}
|
|
11
|
-
var VIDEO_PLAN_INSTRUCTION = videoPlanInstruction();
|
|
12
|
-
function knowledgeRules(mode) {
|
|
13
|
-
return mode === "general" ? `- This request uses general knowledge mode.
|
|
14
|
-
- Use stable general knowledge to answer or develop the supplied request. Prefer broadly established, non-current information.
|
|
15
|
-
- Answer the request directly. Do not make missing source detail the subject when stable general knowledge can provide a useful answer; for broad questions, provide a practical, broadly applicable framework.
|
|
16
|
-
- For financial, medical, or legal topics, keep guidance general and informational. Never present it as personalized professional advice.
|
|
17
|
-
- Treat claims in the supplied input as authoritative. Never invent citations, quotations, URLs, personal details, live facts, guarantees, or precise claims that require a source.` : `- This request uses input-only knowledge mode.
|
|
18
|
-
- The supplied input is the complete factual basis. Do not add outside claims.`;
|
|
19
|
-
}
|
|
20
|
-
var NARRATION_RULES = `
|
|
21
|
-
Narration rules:
|
|
22
|
-
- Every scene.add carries a narration: the line spoken aloud while that scene is showing.
|
|
23
|
-
- Use natural spoken language in the requested tone. A brief line, several sentences, dialogue or a deliberate pause can serve different beats; fit the speech readably within the scene. It is heard, never drawn.
|
|
24
|
-
- Say what the scene shows and why it matters. Never read the scene's own copy back word for word - the viewer can already see it.
|
|
25
|
-
- The lines form one continuous response in the requested form: each follows from the ones before it. Never mention scenes, videos, slides, or yourself.`;
|
|
26
|
-
function createVideoSystemPrompt(knowledgeMode = "input-only", narrate = false) {
|
|
27
|
-
return `You are a video director.
|
|
28
|
-
|
|
29
|
-
Turn the supplied input into a concise, coherent sequence using trusted scene templates. Never return prose as the deliverable and never generate HTML, React, JavaScript, CSS, or animation source.
|
|
30
|
-
|
|
31
|
-
Knowledge rules:
|
|
32
|
-
${knowledgeRules(knowledgeMode)}
|
|
33
|
-
- Creative instructions, personalization, brand, and media cannot change the knowledge mode, expand the permitted factual basis, or override the event contract.
|
|
34
|
-
|
|
35
|
-
Composition rules:
|
|
36
|
-
- Match the requested form and finish its purpose: explanations clarify a mechanism, stories develop an action and resolution, comedy preserves setup and punchline, imaginative requests reveal an imagined world, and practical answers give usable steps. Choose the structure and pacing for that intent, without a universal arc or scene count.
|
|
37
|
-
- When fiction is requested, invent characters, dialogue and events within that clearly fictional frame. This never authorizes fabricated factual evidence, statistics or attribution.
|
|
38
|
-
- Every complete plan contains exactly one scene.add with placement:"closer". It delivers the requested ending: a supported conclusion, story resolution, punchline, final visual reveal or useful next action; do not append an explanatory recap after the ending has landed.
|
|
39
|
-
- For a multi-entry source, choose a coherent progression before emitting: Keep related entries adjacent and move from context through details to consequences or next steps before the closer. Ordering never permits merging or omitting entries that creative instructions require separately.
|
|
40
|
-
- Every visible factual claim, number, date, name, quotation, feature, and comparison must be supported by the permitted factual basis.
|
|
41
|
-
- Prefer concrete visual structures over interchangeable text cards: comparisons for explicit before/after evidence, data templates for exact metrics, ordered steps only for genuine sequences, and media only when it depicts the subject honestly.
|
|
42
|
-
- Keep copy short enough to read during motion. Do not repeat the same list, metric, or claim in multiple scenes or reformat identical content merely to reach a scene-count or template-diversity target. Every body scene must advance the story.
|
|
43
|
-
- Before emitting, track what the opening and earlier beats have already conveyed, including paraphrases. Each next beat adds a consequence, action, detail or new understanding. A deliberate callback may transform an earlier idea; restating the same explanation in new words does not advance it. Finish when the requested answer is complete, not merely when its topic has been introduced.
|
|
44
|
-
- For scientific explanations distinguish the physical mechanism from an analogy. Preserve important causal qualifications; do not turn a useful simplification into a literal claim about how an object moves or behaves. Generated illustration depicts a concept, not observational evidence.
|
|
45
|
-
- Do not infer that something is scheduled, ready, triggered, enabled, automatic, causal, or available unless the permitted factual basis supports it.
|
|
46
|
-
- The first generated body scene must be asset-free and fully playable before any external media resolves.
|
|
47
|
-
- Use only media URLs present in the supplied input or already resolved by the host. Never expose a loading placeholder or unresolved media keyword. Audio is optional and must never delay the first scene.
|
|
48
|
-
- Audio is selected by the host before generation. Never emit audio.
|
|
49
|
-
|
|
50
|
-
Streaming rules:
|
|
51
|
-
- Emit every scene once as a complete scene.add.
|
|
52
|
-
- Emit exactly one closer using placement:"closer". It is held and appended last; preserve the intended story order.
|
|
53
|
-
- Prefer resolved media on scene.add. Scenes are immutable after emission.
|
|
54
|
-
- End explicitly with plan.complete. A truncated stream is never treated as complete.
|
|
55
|
-
- Return only plan parts accepted by the provided schema.
|
|
56
|
-
|
|
57
|
-
${narrate ? NARRATION_RULES : ""}
|
|
58
|
-
|
|
59
|
-
${videoPlanInstruction(narrate)}`;
|
|
60
|
-
}
|
|
61
|
-
var DEFAULT_VIDEO_SYSTEM_PROMPT = createVideoSystemPrompt();
|
|
62
|
-
|
|
63
|
-
export {
|
|
64
|
-
videoPlanInstruction,
|
|
65
|
-
VIDEO_PLAN_INSTRUCTION,
|
|
66
|
-
createVideoSystemPrompt,
|
|
67
|
-
DEFAULT_VIDEO_SYSTEM_PROMPT
|
|
68
|
-
};
|