hyper-animator-codex 0.8.0 → 0.8.3
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/README.md +30 -13
- package/bin/hyper-animator-codex.mjs +4 -4
- package/lib/install-skill.mjs +49 -20
- package/lib/minimax-config.mjs +5 -9
- package/package.json +10 -2
- package/skills/hyper-animator-codex/SKILL.md +33 -25
- package/skills/hyper-animator-codex/agents/openai.yaml +2 -2
- package/skills/hyper-animator-codex/contracts/shot-plan.schema.json +113 -7
- package/skills/hyper-animator-codex/contracts/workflow-policy.json +21 -3
- package/skills/hyper-animator-codex/references/examples/shot-plan-dual-catalog.json +41 -5
- package/skills/hyper-animator-codex/references/hyperframes-intent-workflow.md +20 -10
- package/skills/hyper-animator-codex/references/minimax-music-workflow.md +5 -7
- package/skills/hyper-animator-codex/references/narration-audio-workflow.md +20 -14
- package/skills/hyper-animator-codex/references/preview-controls-workflow.md +4 -2
- package/skills/hyper-animator-codex/references/shotcraft/motion-pack/README.md +32 -0
- package/skills/hyper-animator-codex/references/shotcraft/motion-pack/shotcraft-motion-pack.js +178 -0
- package/skills/hyper-animator-codex/scripts/generate_minimax_music.mjs +11 -6
- package/skills/hyper-animator-codex/scripts/generate_minimax_tts.mjs +20 -8
- package/skills/hyper-animator-codex/scripts/git_checkpoint.mjs +29 -3
- package/skills/hyper-animator-codex/scripts/inject_preview_controls.mjs +37 -1
- package/skills/hyper-animator-codex/scripts/minimax_runtime_config.mjs +5 -9
- package/skills/hyper-animator-codex/scripts/query_shotcraft.mjs +10 -1
- package/skills/hyper-animator-codex/scripts/shot_plan_schema_validator.mjs +3 -0
- package/skills/hyper-animator-codex/scripts/validate_hyperframes_html.py +122 -36
- package/skills/hyper-animator-codex/scripts/validate_shot_plan.mjs +110 -17
|
@@ -32,6 +32,32 @@ const DEFAULT_EXCLUDES = [
|
|
|
32
32
|
"tmp/",
|
|
33
33
|
".tmp/",
|
|
34
34
|
];
|
|
35
|
+
const SENSITIVE_EXCLUDES = [
|
|
36
|
+
".env",
|
|
37
|
+
".env.*",
|
|
38
|
+
"**/.env",
|
|
39
|
+
"**/.env.*",
|
|
40
|
+
".npmrc",
|
|
41
|
+
"**/.npmrc",
|
|
42
|
+
".pypirc",
|
|
43
|
+
"**/.pypirc",
|
|
44
|
+
".netrc",
|
|
45
|
+
"**/.netrc",
|
|
46
|
+
"credentials.json",
|
|
47
|
+
"**/credentials.json",
|
|
48
|
+
"secrets.json",
|
|
49
|
+
"**/secrets.json",
|
|
50
|
+
"*.pem",
|
|
51
|
+
"**/*.pem",
|
|
52
|
+
"*.key",
|
|
53
|
+
"**/*.key",
|
|
54
|
+
"*.p12",
|
|
55
|
+
"**/*.p12",
|
|
56
|
+
"id_rsa",
|
|
57
|
+
"**/id_rsa",
|
|
58
|
+
"id_ed25519",
|
|
59
|
+
"**/id_ed25519",
|
|
60
|
+
];
|
|
35
61
|
|
|
36
62
|
let repositoryRootCache = null;
|
|
37
63
|
let gitPrefixCache = null;
|
|
@@ -162,7 +188,7 @@ function resolveGitDirPath(value) {
|
|
|
162
188
|
function isDefaultExcluded(path) {
|
|
163
189
|
const normalized = normalizeGitPath(path);
|
|
164
190
|
|
|
165
|
-
return DEFAULT_EXCLUDES.some((entry) => {
|
|
191
|
+
return isExplicitlyExcluded(normalized, SENSITIVE_EXCLUDES) || DEFAULT_EXCLUDES.some((entry) => {
|
|
166
192
|
const cleaned = entry.endsWith("/") ? entry.slice(0, -1) : entry;
|
|
167
193
|
return normalized === cleaned || normalized.startsWith(`${cleaned}/`);
|
|
168
194
|
});
|
|
@@ -193,7 +219,7 @@ function parsePorcelainLine(line) {
|
|
|
193
219
|
}
|
|
194
220
|
|
|
195
221
|
function porcelainLines(pathspecs = []) {
|
|
196
|
-
const args = ["status", "--porcelain=v1", "--untracked-files=all"];
|
|
222
|
+
const args = ["-c", "core.quotePath=false", "status", "--porcelain=v1", "--untracked-files=all"];
|
|
197
223
|
|
|
198
224
|
if (pathspecs.length > 0) {
|
|
199
225
|
args.push("--", ...pathspecs);
|
|
@@ -230,7 +256,7 @@ function trackedOrUntrackedMatching(pathspecs) {
|
|
|
230
256
|
}
|
|
231
257
|
|
|
232
258
|
function stagedFiles() {
|
|
233
|
-
return git(["diff", "--cached", "--name-only", "--diff-filter=ACDMR"], { check: true }).stdout
|
|
259
|
+
return git(["-c", "core.quotePath=false", "diff", "--cached", "--name-only", "--diff-filter=ACDMR"], { check: true }).stdout
|
|
234
260
|
.split("\n")
|
|
235
261
|
.map((line) => line.trim())
|
|
236
262
|
.filter(Boolean)
|
|
@@ -166,7 +166,7 @@ function injectPreviewControls(html, componentId) {
|
|
|
166
166
|
bottom: 0;
|
|
167
167
|
z-index: 2147483647;
|
|
168
168
|
display: grid;
|
|
169
|
-
grid-template-columns: auto minmax(0, 1fr);
|
|
169
|
+
grid-template-columns: auto auto minmax(0, 1fr);
|
|
170
170
|
align-items: center;
|
|
171
171
|
gap: 10px;
|
|
172
172
|
padding: 6px 10px 8px;
|
|
@@ -184,6 +184,17 @@ function injectPreviewControls(html, componentId) {
|
|
|
184
184
|
font-variant-numeric: tabular-nums lining-nums;
|
|
185
185
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
|
|
186
186
|
}
|
|
187
|
+
.hyper-preview-play {
|
|
188
|
+
min-width: 54px;
|
|
189
|
+
padding: 5px 9px;
|
|
190
|
+
border: 1px solid rgba(255, 255, 255, 0.35);
|
|
191
|
+
border-radius: 999px;
|
|
192
|
+
color: #fff;
|
|
193
|
+
background: rgba(3, 8, 20, 0.7);
|
|
194
|
+
font: 600 12px/1 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
195
|
+
cursor: pointer;
|
|
196
|
+
pointer-events: auto;
|
|
197
|
+
}
|
|
187
198
|
.hyper-preview-progress {
|
|
188
199
|
width: 100%;
|
|
189
200
|
height: 3px;
|
|
@@ -193,6 +204,7 @@ function injectPreviewControls(html, componentId) {
|
|
|
193
204
|
}
|
|
194
205
|
</style>
|
|
195
206
|
<div class="hyper-preview-ui" data-hyper-preview-ui hidden aria-label="Animation preview controls">
|
|
207
|
+
<button class="hyper-preview-play" data-hyper-preview-play type="button" aria-label="Play">播放</button>
|
|
196
208
|
<div class="hyper-preview-page" data-hyper-preview-page aria-live="polite">1 / 1</div>
|
|
197
209
|
<input class="hyper-preview-progress" data-hyper-preview-progress type="range" min="0" max="1000" step="1" value="0" aria-label="Preview progress" />
|
|
198
210
|
</div>
|
|
@@ -210,6 +222,7 @@ function injectPreviewControls(html, componentId) {
|
|
|
210
222
|
}
|
|
211
223
|
|
|
212
224
|
const pageLabel = root.querySelector("[data-hyper-preview-page]");
|
|
225
|
+
const playButton = root.querySelector("[data-hyper-preview-play]");
|
|
213
226
|
const progress = root.querySelector("[data-hyper-preview-progress]");
|
|
214
227
|
const composition = findComposition();
|
|
215
228
|
const duration = readDuration(composition);
|
|
@@ -220,6 +233,21 @@ function injectPreviewControls(html, componentId) {
|
|
|
220
233
|
root.style.display = "";
|
|
221
234
|
updateForTime(0);
|
|
222
235
|
|
|
236
|
+
if (playButton) {
|
|
237
|
+
playButton.addEventListener("click", function () {
|
|
238
|
+
const timeline = getTimeline();
|
|
239
|
+
if (!timeline) return;
|
|
240
|
+
const atEnd = typeof timeline.progress === "function" && timeline.progress() >= 1;
|
|
241
|
+
if (typeof timeline.paused === "function" && (timeline.paused() || atEnd)) timeline.play(atEnd ? 0 : undefined);
|
|
242
|
+
else if (typeof timeline.pause === "function") timeline.pause();
|
|
243
|
+
syncPlayButton();
|
|
244
|
+
});
|
|
245
|
+
syncPlayButton();
|
|
246
|
+
const timeline = getTimeline();
|
|
247
|
+
if (timeline && typeof timeline.play === "function") timeline.play(0);
|
|
248
|
+
syncPlayButton();
|
|
249
|
+
}
|
|
250
|
+
|
|
223
251
|
progress.addEventListener("input", function () {
|
|
224
252
|
const seconds = (Number(progress.value) / Number(progress.max)) * duration;
|
|
225
253
|
seek(seconds);
|
|
@@ -280,6 +308,14 @@ function injectPreviewControls(html, componentId) {
|
|
|
280
308
|
}
|
|
281
309
|
}
|
|
282
310
|
|
|
311
|
+
function syncPlayButton() {
|
|
312
|
+
const timeline = getTimeline();
|
|
313
|
+
if (!playButton || !timeline || typeof timeline.paused !== "function") return;
|
|
314
|
+
const paused = timeline.paused();
|
|
315
|
+
playButton.textContent = paused ? "播放" : "暂停";
|
|
316
|
+
playButton.setAttribute("aria-label", paused ? "Play" : "Pause");
|
|
317
|
+
}
|
|
318
|
+
|
|
283
319
|
function goToPage(nextIndex) {
|
|
284
320
|
pageIndex = nextIndex;
|
|
285
321
|
const seconds = pages[pageIndex] || 0;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { readFile, stat } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
|
|
4
|
-
export const DEFAULT_MINIMAX_MODEL = "music-
|
|
5
|
-
export const TEXT_MUSIC_MODELS = new Set(["music-3.0", "music-2.6", "music-2.6-free"]);
|
|
4
|
+
export const DEFAULT_MINIMAX_MODEL = "music-3.0";
|
|
5
|
+
export const TEXT_MUSIC_MODELS = new Set(["music-3.0", "music-3.0-free", "music-2.6", "music-2.6-free"]);
|
|
6
6
|
|
|
7
7
|
async function pathExists(path) {
|
|
8
8
|
try {
|
|
@@ -42,7 +42,7 @@ export function redactMinimaxConfig(config = {}) {
|
|
|
42
42
|
|
|
43
43
|
return {
|
|
44
44
|
api_key: normalized.api_key ? "[redacted]" : undefined,
|
|
45
|
-
group_id: normalized.group_id,
|
|
45
|
+
...(normalized.group_id ? { group_id: normalized.group_id } : {}),
|
|
46
46
|
model: normalized.model || DEFAULT_MINIMAX_MODEL,
|
|
47
47
|
};
|
|
48
48
|
}
|
|
@@ -54,19 +54,15 @@ export function validateMinimaxConfig(config = {}) {
|
|
|
54
54
|
throw new Error("MiniMax api_key is required");
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
if (!normalized.group_id) {
|
|
58
|
-
throw new Error("MiniMax group_id is required");
|
|
59
|
-
}
|
|
60
|
-
|
|
61
57
|
const model = normalized.model || DEFAULT_MINIMAX_MODEL;
|
|
62
58
|
|
|
63
59
|
if (!TEXT_MUSIC_MODELS.has(model)) {
|
|
64
|
-
throw new Error(`Unsupported MiniMax text music model: ${model}. Use music-3.0, music-2.6, or music-2.6-free.`);
|
|
60
|
+
throw new Error(`Unsupported MiniMax text music model: ${model}. Use music-3.0, music-3.0-free, music-2.6, or music-2.6-free.`);
|
|
65
61
|
}
|
|
66
62
|
|
|
67
63
|
return {
|
|
68
64
|
api_key: normalized.api_key,
|
|
69
|
-
group_id: normalized.group_id,
|
|
65
|
+
...(normalized.group_id ? { group_id: normalized.group_id } : {}),
|
|
70
66
|
model,
|
|
71
67
|
};
|
|
72
68
|
}
|
|
@@ -36,11 +36,16 @@ function parseArgs(args) {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
function tokens(value) {
|
|
39
|
-
|
|
39
|
+
const raw = String(value)
|
|
40
40
|
.toLowerCase()
|
|
41
41
|
.split(/[\s,,。::;;/|()[\]{}"'`_-]+/)
|
|
42
42
|
.map((token) => token.trim())
|
|
43
43
|
.filter(Boolean);
|
|
44
|
+
const expanded = raw.flatMap((token) => {
|
|
45
|
+
if (!/^[\p{Script=Han}]+$/u.test(token) || token.length < 3) return [token];
|
|
46
|
+
return [token, ...Array.from({ length: token.length - 1 }, (_, index) => token.slice(index, index + 2))];
|
|
47
|
+
});
|
|
48
|
+
return [...new Set(expanded)];
|
|
44
49
|
}
|
|
45
50
|
|
|
46
51
|
function scoreText(queryTokens, fields) {
|
|
@@ -121,6 +126,10 @@ async function main() {
|
|
|
121
126
|
.sort((left, right) => right.score - left.score || left.card.localeCompare(right.card))
|
|
122
127
|
.slice(0, args.limit);
|
|
123
128
|
|
|
129
|
+
if (results.length === 0) {
|
|
130
|
+
throw new Error(`No ShotCraft references matched: ${args.query}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
124
133
|
if (args.json) {
|
|
125
134
|
console.log(JSON.stringify({
|
|
126
135
|
ok: true,
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// Generated by tools/build-shot-plan-validator.mjs; do not edit.
|
|
2
|
+
export const schemaSha256 = "78d808af826b34473732b407d825a89ef1103e04c8cc3b56a5fe4eb013f54261";
|
|
3
|
+
"use strict";export const validate = validate20;export default validate20;const schema31 = {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://hyper-animator-codex.local/contracts/shot-plan.schema.json","title":"Hyper Animator dual-catalog shot plan","type":"object","additionalProperties":false,"required":["schema_version","workflow_stage","generation_mode","catalog_strategy","dimensions","duration_seconds","audio","model_routing","shots"],"properties":{"schema_version":{"const":"1.1.0"},"workflow_stage":{"enum":["visual_draft","audio_integrated","render_ready"]},"generation_mode":{"enum":["assemble_existing_catalog_items","generate_new_hyperframes_html"]},"catalog_strategy":{"const":"dual_catalog"},"dimensions":{"type":"object","additionalProperties":false,"required":["width","height"],"properties":{"width":{"type":"integer","minimum":1},"height":{"type":"integer","minimum":1}}},"duration_seconds":{"type":"number","exclusiveMinimum":0},"audio":{"type":"object","additionalProperties":false,"required":["narration","bgm"],"properties":{"narration":{"$ref":"#/$defs/audioTrack"},"bgm":{"$ref":"#/$defs/audioTrack"}}},"model_routing":{"type":"object","additionalProperties":false,"required":["page_animation_authoring","planning_and_validation"],"properties":{"page_animation_authoring":{"allOf":[{"$ref":"#/$defs/modelRoute"},{"properties":{"tier":{"const":"high_quality"}}}]},"planning_and_validation":{"allOf":[{"$ref":"#/$defs/modelRoute"},{"properties":{"tier":{"const":"fast"}}}]}}},"shots":{"type":"array","minItems":1,"items":{"$ref":"#/$defs/shot"}},"assumptions":{"type":"array","items":{"type":"string"}}},"$defs":{"modelRoute":{"type":"object","additionalProperties":false,"required":["tier","actual_model"],"properties":{"tier":{"enum":["high_quality","fast"]},"actual_model":{"type":"string","minLength":1}}},"audioTrack":{"type":"object","additionalProperties":false,"required":["mode"],"properties":{"mode":{"enum":["generated","user_local_file","none","deferred"]},"provider":{"enum":["minimax_cn"]},"path":{"type":"string","minLength":1}},"allOf":[{"if":{"properties":{"mode":{"const":"generated"}}},"then":{"required":["provider"],"properties":{"provider":{"const":"minimax_cn"}}}},{"if":{"properties":{"mode":{"const":"user_local_file"}}},"then":{"required":["path"]}}]},"shot":{"type":"object","additionalProperties":false,"required":["id","start_seconds","end_seconds","purpose","hyperframes_refs","shotcraft_refs","motion_contract"],"properties":{"id":{"type":"string","pattern":"^[a-z][a-z0-9-]*$"},"start_seconds":{"type":"number","minimum":0},"end_seconds":{"type":"number","exclusiveMinimum":0},"purpose":{"type":"string","minLength":1},"hyperframes_refs":{"type":"array","minItems":1,"items":{"type":"string","minLength":1},"uniqueItems":true},"shotcraft_refs":{"type":"array","minItems":1,"items":{"type":"string","minLength":1},"uniqueItems":true},"narration_scene":{"type":["string","null"]},"motion_contract":{"type":"object","additionalProperties":false,"required":["motion_preset","energy","camera","transition","shotcraft_commitments","readable_rest_seconds"],"properties":{"motion_preset":{"enum":["none","slam-entrance","whip-transition","crash-zoom","push-stack-wipe","dataviz-landscape-open","panel-grid-reflow","brand-resolve"]},"energy":{"enum":["quiet","balanced","high","cinematic"]},"camera":{"type":"string","minLength":1},"transition":{"type":"string","minLength":1},"shotcraft_commitments":{"type":"array","minItems":1,"items":{"type":"string","minLength":1}},"readable_rest_seconds":{"type":"number","minimum":0}}}}}}};const schema32 = {"type":"object","additionalProperties":false,"required":["mode"],"properties":{"mode":{"enum":["generated","user_local_file","none","deferred"]},"provider":{"enum":["minimax_cn"]},"path":{"type":"string","minLength":1}},"allOf":[{"if":{"properties":{"mode":{"const":"generated"}}},"then":{"required":["provider"],"properties":{"provider":{"const":"minimax_cn"}}}},{"if":{"properties":{"mode":{"const":"user_local_file"}}},"then":{"required":["path"]}}]};const schema34 = {"type":"object","additionalProperties":false,"required":["tier","actual_model"],"properties":{"tier":{"enum":["high_quality","fast"]},"actual_model":{"type":"string","minLength":1}}};const schema36 = {"type":"object","additionalProperties":false,"required":["id","start_seconds","end_seconds","purpose","hyperframes_refs","shotcraft_refs","motion_contract"],"properties":{"id":{"type":"string","pattern":"^[a-z][a-z0-9-]*$"},"start_seconds":{"type":"number","minimum":0},"end_seconds":{"type":"number","exclusiveMinimum":0},"purpose":{"type":"string","minLength":1},"hyperframes_refs":{"type":"array","minItems":1,"items":{"type":"string","minLength":1},"uniqueItems":true},"shotcraft_refs":{"type":"array","minItems":1,"items":{"type":"string","minLength":1},"uniqueItems":true},"narration_scene":{"type":["string","null"]},"motion_contract":{"type":"object","additionalProperties":false,"required":["motion_preset","energy","camera","transition","shotcraft_commitments","readable_rest_seconds"],"properties":{"motion_preset":{"enum":["none","slam-entrance","whip-transition","crash-zoom","push-stack-wipe","dataviz-landscape-open","panel-grid-reflow","brand-resolve"]},"energy":{"enum":["quiet","balanced","high","cinematic"]},"camera":{"type":"string","minLength":1},"transition":{"type":"string","minLength":1},"shotcraft_commitments":{"type":"array","minItems":1,"items":{"type":"string","minLength":1}},"readable_rest_seconds":{"type":"number","minimum":0}}}}};const func1 = Object.prototype.hasOwnProperty;const func2 = (value) => [...value].length;const pattern4 = new RegExp("^[a-z][a-z0-9-]*$", "u");function validate20(data, {instancePath="", parentData, parentDataProperty, rootData=data, dynamicAnchors={}}={}){/*# sourceURL="https://hyper-animator-codex.local/contracts/shot-plan.schema.json" */;let vErrors = null;let errors = 0;const evaluated0 = validate20.evaluated;if(evaluated0.dynamicProps){evaluated0.props = undefined;}if(evaluated0.dynamicItems){evaluated0.items = undefined;}if(data && typeof data == "object" && !Array.isArray(data)){if(data.schema_version === undefined){const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "schema_version"},message:"must have required property '"+"schema_version"+"'"};if(vErrors === null){vErrors = [err0];}else {vErrors.push(err0);}errors++;}if(data.workflow_stage === undefined){const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "workflow_stage"},message:"must have required property '"+"workflow_stage"+"'"};if(vErrors === null){vErrors = [err1];}else {vErrors.push(err1);}errors++;}if(data.generation_mode === undefined){const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation_mode"},message:"must have required property '"+"generation_mode"+"'"};if(vErrors === null){vErrors = [err2];}else {vErrors.push(err2);}errors++;}if(data.catalog_strategy === undefined){const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "catalog_strategy"},message:"must have required property '"+"catalog_strategy"+"'"};if(vErrors === null){vErrors = [err3];}else {vErrors.push(err3);}errors++;}if(data.dimensions === undefined){const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "dimensions"},message:"must have required property '"+"dimensions"+"'"};if(vErrors === null){vErrors = [err4];}else {vErrors.push(err4);}errors++;}if(data.duration_seconds === undefined){const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "duration_seconds"},message:"must have required property '"+"duration_seconds"+"'"};if(vErrors === null){vErrors = [err5];}else {vErrors.push(err5);}errors++;}if(data.audio === undefined){const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "audio"},message:"must have required property '"+"audio"+"'"};if(vErrors === null){vErrors = [err6];}else {vErrors.push(err6);}errors++;}if(data.model_routing === undefined){const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "model_routing"},message:"must have required property '"+"model_routing"+"'"};if(vErrors === null){vErrors = [err7];}else {vErrors.push(err7);}errors++;}if(data.shots === undefined){const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "shots"},message:"must have required property '"+"shots"+"'"};if(vErrors === null){vErrors = [err8];}else {vErrors.push(err8);}errors++;}for(const key0 in data){if(!(func1.call(schema31.properties, key0))){const err9 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"};if(vErrors === null){vErrors = [err9];}else {vErrors.push(err9);}errors++;}}if(data.schema_version !== undefined){if("1.1.0" !== data.schema_version){const err10 = {instancePath:instancePath+"/schema_version",schemaPath:"#/properties/schema_version/const",keyword:"const",params:{allowedValue: "1.1.0"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err10];}else {vErrors.push(err10);}errors++;}}if(data.workflow_stage !== undefined){let data1 = data.workflow_stage;if(!(((data1 === "visual_draft") || (data1 === "audio_integrated")) || (data1 === "render_ready"))){const err11 = {instancePath:instancePath+"/workflow_stage",schemaPath:"#/properties/workflow_stage/enum",keyword:"enum",params:{allowedValues: schema31.properties.workflow_stage.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err11];}else {vErrors.push(err11);}errors++;}}if(data.generation_mode !== undefined){let data2 = data.generation_mode;if(!((data2 === "assemble_existing_catalog_items") || (data2 === "generate_new_hyperframes_html"))){const err12 = {instancePath:instancePath+"/generation_mode",schemaPath:"#/properties/generation_mode/enum",keyword:"enum",params:{allowedValues: schema31.properties.generation_mode.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err12];}else {vErrors.push(err12);}errors++;}}if(data.catalog_strategy !== undefined){if("dual_catalog" !== data.catalog_strategy){const err13 = {instancePath:instancePath+"/catalog_strategy",schemaPath:"#/properties/catalog_strategy/const",keyword:"const",params:{allowedValue: "dual_catalog"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err13];}else {vErrors.push(err13);}errors++;}}if(data.dimensions !== undefined){let data4 = data.dimensions;if(data4 && typeof data4 == "object" && !Array.isArray(data4)){if(data4.width === undefined){const err14 = {instancePath:instancePath+"/dimensions",schemaPath:"#/properties/dimensions/required",keyword:"required",params:{missingProperty: "width"},message:"must have required property '"+"width"+"'"};if(vErrors === null){vErrors = [err14];}else {vErrors.push(err14);}errors++;}if(data4.height === undefined){const err15 = {instancePath:instancePath+"/dimensions",schemaPath:"#/properties/dimensions/required",keyword:"required",params:{missingProperty: "height"},message:"must have required property '"+"height"+"'"};if(vErrors === null){vErrors = [err15];}else {vErrors.push(err15);}errors++;}for(const key1 in data4){if(!((key1 === "width") || (key1 === "height"))){const err16 = {instancePath:instancePath+"/dimensions",schemaPath:"#/properties/dimensions/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"};if(vErrors === null){vErrors = [err16];}else {vErrors.push(err16);}errors++;}}if(data4.width !== undefined){let data5 = data4.width;if(!((typeof data5 == "number") && (!(data5 % 1) && !isNaN(data5)))){const err17 = {instancePath:instancePath+"/dimensions/width",schemaPath:"#/properties/dimensions/properties/width/type",keyword:"type",params:{type: "integer"},message:"must be integer"};if(vErrors === null){vErrors = [err17];}else {vErrors.push(err17);}errors++;}if(typeof data5 == "number"){if(data5 < 1 || isNaN(data5)){const err18 = {instancePath:instancePath+"/dimensions/width",schemaPath:"#/properties/dimensions/properties/width/minimum",keyword:"minimum",params:{comparison: ">=", limit: 1},message:"must be >= 1"};if(vErrors === null){vErrors = [err18];}else {vErrors.push(err18);}errors++;}}}if(data4.height !== undefined){let data6 = data4.height;if(!((typeof data6 == "number") && (!(data6 % 1) && !isNaN(data6)))){const err19 = {instancePath:instancePath+"/dimensions/height",schemaPath:"#/properties/dimensions/properties/height/type",keyword:"type",params:{type: "integer"},message:"must be integer"};if(vErrors === null){vErrors = [err19];}else {vErrors.push(err19);}errors++;}if(typeof data6 == "number"){if(data6 < 1 || isNaN(data6)){const err20 = {instancePath:instancePath+"/dimensions/height",schemaPath:"#/properties/dimensions/properties/height/minimum",keyword:"minimum",params:{comparison: ">=", limit: 1},message:"must be >= 1"};if(vErrors === null){vErrors = [err20];}else {vErrors.push(err20);}errors++;}}}}else {const err21 = {instancePath:instancePath+"/dimensions",schemaPath:"#/properties/dimensions/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err21];}else {vErrors.push(err21);}errors++;}}if(data.duration_seconds !== undefined){let data7 = data.duration_seconds;if(typeof data7 == "number"){if(data7 <= 0 || isNaN(data7)){const err22 = {instancePath:instancePath+"/duration_seconds",schemaPath:"#/properties/duration_seconds/exclusiveMinimum",keyword:"exclusiveMinimum",params:{comparison: ">", limit: 0},message:"must be > 0"};if(vErrors === null){vErrors = [err22];}else {vErrors.push(err22);}errors++;}}else {const err23 = {instancePath:instancePath+"/duration_seconds",schemaPath:"#/properties/duration_seconds/type",keyword:"type",params:{type: "number"},message:"must be number"};if(vErrors === null){vErrors = [err23];}else {vErrors.push(err23);}errors++;}}if(data.audio !== undefined){let data8 = data.audio;if(data8 && typeof data8 == "object" && !Array.isArray(data8)){if(data8.narration === undefined){const err24 = {instancePath:instancePath+"/audio",schemaPath:"#/properties/audio/required",keyword:"required",params:{missingProperty: "narration"},message:"must have required property '"+"narration"+"'"};if(vErrors === null){vErrors = [err24];}else {vErrors.push(err24);}errors++;}if(data8.bgm === undefined){const err25 = {instancePath:instancePath+"/audio",schemaPath:"#/properties/audio/required",keyword:"required",params:{missingProperty: "bgm"},message:"must have required property '"+"bgm"+"'"};if(vErrors === null){vErrors = [err25];}else {vErrors.push(err25);}errors++;}for(const key2 in data8){if(!((key2 === "narration") || (key2 === "bgm"))){const err26 = {instancePath:instancePath+"/audio",schemaPath:"#/properties/audio/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"};if(vErrors === null){vErrors = [err26];}else {vErrors.push(err26);}errors++;}}if(data8.narration !== undefined){let data9 = data8.narration;const _errs22 = errors;let valid5 = true;const _errs23 = errors;if(data9 && typeof data9 == "object" && !Array.isArray(data9)){if(data9.mode !== undefined){if("generated" !== data9.mode){const err27 = {};if(vErrors === null){vErrors = [err27];}else {vErrors.push(err27);}errors++;}}}var _valid0 = _errs23 === errors;errors = _errs22;if(vErrors !== null){if(_errs22){vErrors.length = _errs22;}else {vErrors = null;}}if(_valid0){const _errs25 = errors;if(data9 && typeof data9 == "object" && !Array.isArray(data9)){if(data9.provider === undefined){const err28 = {instancePath:instancePath+"/audio/narration",schemaPath:"#/$defs/audioTrack/allOf/0/then/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"};if(vErrors === null){vErrors = [err28];}else {vErrors.push(err28);}errors++;}if(data9.provider !== undefined){if("minimax_cn" !== data9.provider){const err29 = {instancePath:instancePath+"/audio/narration/provider",schemaPath:"#/$defs/audioTrack/allOf/0/then/properties/provider/const",keyword:"const",params:{allowedValue: "minimax_cn"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err29];}else {vErrors.push(err29);}errors++;}}}var _valid0 = _errs25 === errors;valid5 = _valid0;if(valid5){var props0 = {};props0.provider = true;props0.mode = true;}}if(!valid5){const err30 = {instancePath:instancePath+"/audio/narration",schemaPath:"#/$defs/audioTrack/allOf/0/if",keyword:"if",params:{failingKeyword: "then"},message:"must match \"then\" schema"};if(vErrors === null){vErrors = [err30];}else {vErrors.push(err30);}errors++;}const _errs28 = errors;let valid8 = true;const _errs29 = errors;if(data9 && typeof data9 == "object" && !Array.isArray(data9)){if(data9.mode !== undefined){if("user_local_file" !== data9.mode){const err31 = {};if(vErrors === null){vErrors = [err31];}else {vErrors.push(err31);}errors++;}}}var _valid1 = _errs29 === errors;errors = _errs28;if(vErrors !== null){if(_errs28){vErrors.length = _errs28;}else {vErrors = null;}}if(_valid1){const _errs31 = errors;if(data9 && typeof data9 == "object" && !Array.isArray(data9)){if(data9.path === undefined){const err32 = {instancePath:instancePath+"/audio/narration",schemaPath:"#/$defs/audioTrack/allOf/1/then/required",keyword:"required",params:{missingProperty: "path"},message:"must have required property '"+"path"+"'"};if(vErrors === null){vErrors = [err32];}else {vErrors.push(err32);}errors++;}}var _valid1 = _errs31 === errors;valid8 = _valid1;}if(!valid8){const err33 = {instancePath:instancePath+"/audio/narration",schemaPath:"#/$defs/audioTrack/allOf/1/if",keyword:"if",params:{failingKeyword: "then"},message:"must match \"then\" schema"};if(vErrors === null){vErrors = [err33];}else {vErrors.push(err33);}errors++;}if(props0 !== true){props0 = props0 || {};props0.mode = true;}if(data9 && typeof data9 == "object" && !Array.isArray(data9)){if(data9.mode === undefined){const err34 = {instancePath:instancePath+"/audio/narration",schemaPath:"#/$defs/audioTrack/required",keyword:"required",params:{missingProperty: "mode"},message:"must have required property '"+"mode"+"'"};if(vErrors === null){vErrors = [err34];}else {vErrors.push(err34);}errors++;}for(const key3 in data9){if(!(((key3 === "mode") || (key3 === "provider")) || (key3 === "path"))){const err35 = {instancePath:instancePath+"/audio/narration",schemaPath:"#/$defs/audioTrack/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"};if(vErrors === null){vErrors = [err35];}else {vErrors.push(err35);}errors++;}}if(data9.mode !== undefined){let data13 = data9.mode;if(!((((data13 === "generated") || (data13 === "user_local_file")) || (data13 === "none")) || (data13 === "deferred"))){const err36 = {instancePath:instancePath+"/audio/narration/mode",schemaPath:"#/$defs/audioTrack/properties/mode/enum",keyword:"enum",params:{allowedValues: schema32.properties.mode.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err36];}else {vErrors.push(err36);}errors++;}}if(data9.provider !== undefined){if(!(data9.provider === "minimax_cn")){const err37 = {instancePath:instancePath+"/audio/narration/provider",schemaPath:"#/$defs/audioTrack/properties/provider/enum",keyword:"enum",params:{allowedValues: schema32.properties.provider.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err37];}else {vErrors.push(err37);}errors++;}}if(data9.path !== undefined){let data15 = data9.path;if(typeof data15 === "string"){if(func2(data15) < 1){const err38 = {instancePath:instancePath+"/audio/narration/path",schemaPath:"#/$defs/audioTrack/properties/path/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err38];}else {vErrors.push(err38);}errors++;}}else {const err39 = {instancePath:instancePath+"/audio/narration/path",schemaPath:"#/$defs/audioTrack/properties/path/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err39];}else {vErrors.push(err39);}errors++;}}}else {const err40 = {instancePath:instancePath+"/audio/narration",schemaPath:"#/$defs/audioTrack/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err40];}else {vErrors.push(err40);}errors++;}}if(data8.bgm !== undefined){let data16 = data8.bgm;const _errs41 = errors;let valid13 = true;const _errs42 = errors;if(data16 && typeof data16 == "object" && !Array.isArray(data16)){if(data16.mode !== undefined){if("generated" !== data16.mode){const err41 = {};if(vErrors === null){vErrors = [err41];}else {vErrors.push(err41);}errors++;}}}var _valid2 = _errs42 === errors;errors = _errs41;if(vErrors !== null){if(_errs41){vErrors.length = _errs41;}else {vErrors = null;}}if(_valid2){const _errs44 = errors;if(data16 && typeof data16 == "object" && !Array.isArray(data16)){if(data16.provider === undefined){const err42 = {instancePath:instancePath+"/audio/bgm",schemaPath:"#/$defs/audioTrack/allOf/0/then/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"};if(vErrors === null){vErrors = [err42];}else {vErrors.push(err42);}errors++;}if(data16.provider !== undefined){if("minimax_cn" !== data16.provider){const err43 = {instancePath:instancePath+"/audio/bgm/provider",schemaPath:"#/$defs/audioTrack/allOf/0/then/properties/provider/const",keyword:"const",params:{allowedValue: "minimax_cn"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err43];}else {vErrors.push(err43);}errors++;}}}var _valid2 = _errs44 === errors;valid13 = _valid2;if(valid13){var props1 = {};props1.provider = true;props1.mode = true;}}if(!valid13){const err44 = {instancePath:instancePath+"/audio/bgm",schemaPath:"#/$defs/audioTrack/allOf/0/if",keyword:"if",params:{failingKeyword: "then"},message:"must match \"then\" schema"};if(vErrors === null){vErrors = [err44];}else {vErrors.push(err44);}errors++;}const _errs47 = errors;let valid16 = true;const _errs48 = errors;if(data16 && typeof data16 == "object" && !Array.isArray(data16)){if(data16.mode !== undefined){if("user_local_file" !== data16.mode){const err45 = {};if(vErrors === null){vErrors = [err45];}else {vErrors.push(err45);}errors++;}}}var _valid3 = _errs48 === errors;errors = _errs47;if(vErrors !== null){if(_errs47){vErrors.length = _errs47;}else {vErrors = null;}}if(_valid3){const _errs50 = errors;if(data16 && typeof data16 == "object" && !Array.isArray(data16)){if(data16.path === undefined){const err46 = {instancePath:instancePath+"/audio/bgm",schemaPath:"#/$defs/audioTrack/allOf/1/then/required",keyword:"required",params:{missingProperty: "path"},message:"must have required property '"+"path"+"'"};if(vErrors === null){vErrors = [err46];}else {vErrors.push(err46);}errors++;}}var _valid3 = _errs50 === errors;valid16 = _valid3;}if(!valid16){const err47 = {instancePath:instancePath+"/audio/bgm",schemaPath:"#/$defs/audioTrack/allOf/1/if",keyword:"if",params:{failingKeyword: "then"},message:"must match \"then\" schema"};if(vErrors === null){vErrors = [err47];}else {vErrors.push(err47);}errors++;}if(props1 !== true){props1 = props1 || {};props1.mode = true;}if(data16 && typeof data16 == "object" && !Array.isArray(data16)){if(data16.mode === undefined){const err48 = {instancePath:instancePath+"/audio/bgm",schemaPath:"#/$defs/audioTrack/required",keyword:"required",params:{missingProperty: "mode"},message:"must have required property '"+"mode"+"'"};if(vErrors === null){vErrors = [err48];}else {vErrors.push(err48);}errors++;}for(const key4 in data16){if(!(((key4 === "mode") || (key4 === "provider")) || (key4 === "path"))){const err49 = {instancePath:instancePath+"/audio/bgm",schemaPath:"#/$defs/audioTrack/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key4},message:"must NOT have additional properties"};if(vErrors === null){vErrors = [err49];}else {vErrors.push(err49);}errors++;}}if(data16.mode !== undefined){let data20 = data16.mode;if(!((((data20 === "generated") || (data20 === "user_local_file")) || (data20 === "none")) || (data20 === "deferred"))){const err50 = {instancePath:instancePath+"/audio/bgm/mode",schemaPath:"#/$defs/audioTrack/properties/mode/enum",keyword:"enum",params:{allowedValues: schema32.properties.mode.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err50];}else {vErrors.push(err50);}errors++;}}if(data16.provider !== undefined){if(!(data16.provider === "minimax_cn")){const err51 = {instancePath:instancePath+"/audio/bgm/provider",schemaPath:"#/$defs/audioTrack/properties/provider/enum",keyword:"enum",params:{allowedValues: schema32.properties.provider.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err51];}else {vErrors.push(err51);}errors++;}}if(data16.path !== undefined){let data22 = data16.path;if(typeof data22 === "string"){if(func2(data22) < 1){const err52 = {instancePath:instancePath+"/audio/bgm/path",schemaPath:"#/$defs/audioTrack/properties/path/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err52];}else {vErrors.push(err52);}errors++;}}else {const err53 = {instancePath:instancePath+"/audio/bgm/path",schemaPath:"#/$defs/audioTrack/properties/path/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err53];}else {vErrors.push(err53);}errors++;}}}else {const err54 = {instancePath:instancePath+"/audio/bgm",schemaPath:"#/$defs/audioTrack/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err54];}else {vErrors.push(err54);}errors++;}}}else {const err55 = {instancePath:instancePath+"/audio",schemaPath:"#/properties/audio/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err55];}else {vErrors.push(err55);}errors++;}}if(data.model_routing !== undefined){let data23 = data.model_routing;if(data23 && typeof data23 == "object" && !Array.isArray(data23)){if(data23.page_animation_authoring === undefined){const err56 = {instancePath:instancePath+"/model_routing",schemaPath:"#/properties/model_routing/required",keyword:"required",params:{missingProperty: "page_animation_authoring"},message:"must have required property '"+"page_animation_authoring"+"'"};if(vErrors === null){vErrors = [err56];}else {vErrors.push(err56);}errors++;}if(data23.planning_and_validation === undefined){const err57 = {instancePath:instancePath+"/model_routing",schemaPath:"#/properties/model_routing/required",keyword:"required",params:{missingProperty: "planning_and_validation"},message:"must have required property '"+"planning_and_validation"+"'"};if(vErrors === null){vErrors = [err57];}else {vErrors.push(err57);}errors++;}for(const key5 in data23){if(!((key5 === "page_animation_authoring") || (key5 === "planning_and_validation"))){const err58 = {instancePath:instancePath+"/model_routing",schemaPath:"#/properties/model_routing/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key5},message:"must NOT have additional properties"};if(vErrors === null){vErrors = [err58];}else {vErrors.push(err58);}errors++;}}if(data23.page_animation_authoring !== undefined){let data24 = data23.page_animation_authoring;if(data24 && typeof data24 == "object" && !Array.isArray(data24)){if(data24.tier === undefined){const err59 = {instancePath:instancePath+"/model_routing/page_animation_authoring",schemaPath:"#/$defs/modelRoute/required",keyword:"required",params:{missingProperty: "tier"},message:"must have required property '"+"tier"+"'"};if(vErrors === null){vErrors = [err59];}else {vErrors.push(err59);}errors++;}if(data24.actual_model === undefined){const err60 = {instancePath:instancePath+"/model_routing/page_animation_authoring",schemaPath:"#/$defs/modelRoute/required",keyword:"required",params:{missingProperty: "actual_model"},message:"must have required property '"+"actual_model"+"'"};if(vErrors === null){vErrors = [err60];}else {vErrors.push(err60);}errors++;}for(const key6 in data24){if(!((key6 === "tier") || (key6 === "actual_model"))){const err61 = {instancePath:instancePath+"/model_routing/page_animation_authoring",schemaPath:"#/$defs/modelRoute/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key6},message:"must NOT have additional properties"};if(vErrors === null){vErrors = [err61];}else {vErrors.push(err61);}errors++;}}if(data24.tier !== undefined){let data25 = data24.tier;if(!((data25 === "high_quality") || (data25 === "fast"))){const err62 = {instancePath:instancePath+"/model_routing/page_animation_authoring/tier",schemaPath:"#/$defs/modelRoute/properties/tier/enum",keyword:"enum",params:{allowedValues: schema34.properties.tier.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err62];}else {vErrors.push(err62);}errors++;}}if(data24.actual_model !== undefined){let data26 = data24.actual_model;if(typeof data26 === "string"){if(func2(data26) < 1){const err63 = {instancePath:instancePath+"/model_routing/page_animation_authoring/actual_model",schemaPath:"#/$defs/modelRoute/properties/actual_model/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err63];}else {vErrors.push(err63);}errors++;}}else {const err64 = {instancePath:instancePath+"/model_routing/page_animation_authoring/actual_model",schemaPath:"#/$defs/modelRoute/properties/actual_model/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err64];}else {vErrors.push(err64);}errors++;}}}else {const err65 = {instancePath:instancePath+"/model_routing/page_animation_authoring",schemaPath:"#/$defs/modelRoute/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err65];}else {vErrors.push(err65);}errors++;}if(data24 && typeof data24 == "object" && !Array.isArray(data24)){if(data24.tier !== undefined){if("high_quality" !== data24.tier){const err66 = {instancePath:instancePath+"/model_routing/page_animation_authoring/tier",schemaPath:"#/properties/model_routing/properties/page_animation_authoring/allOf/1/properties/tier/const",keyword:"const",params:{allowedValue: "high_quality"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err66];}else {vErrors.push(err66);}errors++;}}}}if(data23.planning_and_validation !== undefined){let data28 = data23.planning_and_validation;if(data28 && typeof data28 == "object" && !Array.isArray(data28)){if(data28.tier === undefined){const err67 = {instancePath:instancePath+"/model_routing/planning_and_validation",schemaPath:"#/$defs/modelRoute/required",keyword:"required",params:{missingProperty: "tier"},message:"must have required property '"+"tier"+"'"};if(vErrors === null){vErrors = [err67];}else {vErrors.push(err67);}errors++;}if(data28.actual_model === undefined){const err68 = {instancePath:instancePath+"/model_routing/planning_and_validation",schemaPath:"#/$defs/modelRoute/required",keyword:"required",params:{missingProperty: "actual_model"},message:"must have required property '"+"actual_model"+"'"};if(vErrors === null){vErrors = [err68];}else {vErrors.push(err68);}errors++;}for(const key7 in data28){if(!((key7 === "tier") || (key7 === "actual_model"))){const err69 = {instancePath:instancePath+"/model_routing/planning_and_validation",schemaPath:"#/$defs/modelRoute/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key7},message:"must NOT have additional properties"};if(vErrors === null){vErrors = [err69];}else {vErrors.push(err69);}errors++;}}if(data28.tier !== undefined){let data29 = data28.tier;if(!((data29 === "high_quality") || (data29 === "fast"))){const err70 = {instancePath:instancePath+"/model_routing/planning_and_validation/tier",schemaPath:"#/$defs/modelRoute/properties/tier/enum",keyword:"enum",params:{allowedValues: schema34.properties.tier.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err70];}else {vErrors.push(err70);}errors++;}}if(data28.actual_model !== undefined){let data30 = data28.actual_model;if(typeof data30 === "string"){if(func2(data30) < 1){const err71 = {instancePath:instancePath+"/model_routing/planning_and_validation/actual_model",schemaPath:"#/$defs/modelRoute/properties/actual_model/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err71];}else {vErrors.push(err71);}errors++;}}else {const err72 = {instancePath:instancePath+"/model_routing/planning_and_validation/actual_model",schemaPath:"#/$defs/modelRoute/properties/actual_model/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err72];}else {vErrors.push(err72);}errors++;}}}else {const err73 = {instancePath:instancePath+"/model_routing/planning_and_validation",schemaPath:"#/$defs/modelRoute/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err73];}else {vErrors.push(err73);}errors++;}if(data28 && typeof data28 == "object" && !Array.isArray(data28)){if(data28.tier !== undefined){if("fast" !== data28.tier){const err74 = {instancePath:instancePath+"/model_routing/planning_and_validation/tier",schemaPath:"#/properties/model_routing/properties/planning_and_validation/allOf/1/properties/tier/const",keyword:"const",params:{allowedValue: "fast"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err74];}else {vErrors.push(err74);}errors++;}}}}}else {const err75 = {instancePath:instancePath+"/model_routing",schemaPath:"#/properties/model_routing/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err75];}else {vErrors.push(err75);}errors++;}}if(data.shots !== undefined){let data32 = data.shots;if(Array.isArray(data32)){if(data32.length < 1){const err76 = {instancePath:instancePath+"/shots",schemaPath:"#/properties/shots/minItems",keyword:"minItems",params:{limit: 1},message:"must NOT have fewer than 1 items"};if(vErrors === null){vErrors = [err76];}else {vErrors.push(err76);}errors++;}const len0 = data32.length;for(let i0=0; i0<len0; i0++){let data33 = data32[i0];if(data33 && typeof data33 == "object" && !Array.isArray(data33)){if(data33.id === undefined){const err77 = {instancePath:instancePath+"/shots/" + i0,schemaPath:"#/$defs/shot/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"};if(vErrors === null){vErrors = [err77];}else {vErrors.push(err77);}errors++;}if(data33.start_seconds === undefined){const err78 = {instancePath:instancePath+"/shots/" + i0,schemaPath:"#/$defs/shot/required",keyword:"required",params:{missingProperty: "start_seconds"},message:"must have required property '"+"start_seconds"+"'"};if(vErrors === null){vErrors = [err78];}else {vErrors.push(err78);}errors++;}if(data33.end_seconds === undefined){const err79 = {instancePath:instancePath+"/shots/" + i0,schemaPath:"#/$defs/shot/required",keyword:"required",params:{missingProperty: "end_seconds"},message:"must have required property '"+"end_seconds"+"'"};if(vErrors === null){vErrors = [err79];}else {vErrors.push(err79);}errors++;}if(data33.purpose === undefined){const err80 = {instancePath:instancePath+"/shots/" + i0,schemaPath:"#/$defs/shot/required",keyword:"required",params:{missingProperty: "purpose"},message:"must have required property '"+"purpose"+"'"};if(vErrors === null){vErrors = [err80];}else {vErrors.push(err80);}errors++;}if(data33.hyperframes_refs === undefined){const err81 = {instancePath:instancePath+"/shots/" + i0,schemaPath:"#/$defs/shot/required",keyword:"required",params:{missingProperty: "hyperframes_refs"},message:"must have required property '"+"hyperframes_refs"+"'"};if(vErrors === null){vErrors = [err81];}else {vErrors.push(err81);}errors++;}if(data33.shotcraft_refs === undefined){const err82 = {instancePath:instancePath+"/shots/" + i0,schemaPath:"#/$defs/shot/required",keyword:"required",params:{missingProperty: "shotcraft_refs"},message:"must have required property '"+"shotcraft_refs"+"'"};if(vErrors === null){vErrors = [err82];}else {vErrors.push(err82);}errors++;}if(data33.motion_contract === undefined){const err83 = {instancePath:instancePath+"/shots/" + i0,schemaPath:"#/$defs/shot/required",keyword:"required",params:{missingProperty: "motion_contract"},message:"must have required property '"+"motion_contract"+"'"};if(vErrors === null){vErrors = [err83];}else {vErrors.push(err83);}errors++;}for(const key8 in data33){if(!((((((((key8 === "id") || (key8 === "start_seconds")) || (key8 === "end_seconds")) || (key8 === "purpose")) || (key8 === "hyperframes_refs")) || (key8 === "shotcraft_refs")) || (key8 === "narration_scene")) || (key8 === "motion_contract"))){const err84 = {instancePath:instancePath+"/shots/" + i0,schemaPath:"#/$defs/shot/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key8},message:"must NOT have additional properties"};if(vErrors === null){vErrors = [err84];}else {vErrors.push(err84);}errors++;}}if(data33.id !== undefined){let data34 = data33.id;if(typeof data34 === "string"){if(!pattern4.test(data34)){const err85 = {instancePath:instancePath+"/shots/" + i0+"/id",schemaPath:"#/$defs/shot/properties/id/pattern",keyword:"pattern",params:{pattern: "^[a-z][a-z0-9-]*$"},message:"must match pattern \""+"^[a-z][a-z0-9-]*$"+"\""};if(vErrors === null){vErrors = [err85];}else {vErrors.push(err85);}errors++;}}else {const err86 = {instancePath:instancePath+"/shots/" + i0+"/id",schemaPath:"#/$defs/shot/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err86];}else {vErrors.push(err86);}errors++;}}if(data33.start_seconds !== undefined){let data35 = data33.start_seconds;if(typeof data35 == "number"){if(data35 < 0 || isNaN(data35)){const err87 = {instancePath:instancePath+"/shots/" + i0+"/start_seconds",schemaPath:"#/$defs/shot/properties/start_seconds/minimum",keyword:"minimum",params:{comparison: ">=", limit: 0},message:"must be >= 0"};if(vErrors === null){vErrors = [err87];}else {vErrors.push(err87);}errors++;}}else {const err88 = {instancePath:instancePath+"/shots/" + i0+"/start_seconds",schemaPath:"#/$defs/shot/properties/start_seconds/type",keyword:"type",params:{type: "number"},message:"must be number"};if(vErrors === null){vErrors = [err88];}else {vErrors.push(err88);}errors++;}}if(data33.end_seconds !== undefined){let data36 = data33.end_seconds;if(typeof data36 == "number"){if(data36 <= 0 || isNaN(data36)){const err89 = {instancePath:instancePath+"/shots/" + i0+"/end_seconds",schemaPath:"#/$defs/shot/properties/end_seconds/exclusiveMinimum",keyword:"exclusiveMinimum",params:{comparison: ">", limit: 0},message:"must be > 0"};if(vErrors === null){vErrors = [err89];}else {vErrors.push(err89);}errors++;}}else {const err90 = {instancePath:instancePath+"/shots/" + i0+"/end_seconds",schemaPath:"#/$defs/shot/properties/end_seconds/type",keyword:"type",params:{type: "number"},message:"must be number"};if(vErrors === null){vErrors = [err90];}else {vErrors.push(err90);}errors++;}}if(data33.purpose !== undefined){let data37 = data33.purpose;if(typeof data37 === "string"){if(func2(data37) < 1){const err91 = {instancePath:instancePath+"/shots/" + i0+"/purpose",schemaPath:"#/$defs/shot/properties/purpose/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err91];}else {vErrors.push(err91);}errors++;}}else {const err92 = {instancePath:instancePath+"/shots/" + i0+"/purpose",schemaPath:"#/$defs/shot/properties/purpose/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err92];}else {vErrors.push(err92);}errors++;}}if(data33.hyperframes_refs !== undefined){let data38 = data33.hyperframes_refs;if(Array.isArray(data38)){if(data38.length < 1){const err93 = {instancePath:instancePath+"/shots/" + i0+"/hyperframes_refs",schemaPath:"#/$defs/shot/properties/hyperframes_refs/minItems",keyword:"minItems",params:{limit: 1},message:"must NOT have fewer than 1 items"};if(vErrors === null){vErrors = [err93];}else {vErrors.push(err93);}errors++;}const len1 = data38.length;for(let i1=0; i1<len1; i1++){let data39 = data38[i1];if(typeof data39 === "string"){if(func2(data39) < 1){const err94 = {instancePath:instancePath+"/shots/" + i0+"/hyperframes_refs/" + i1,schemaPath:"#/$defs/shot/properties/hyperframes_refs/items/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err94];}else {vErrors.push(err94);}errors++;}}else {const err95 = {instancePath:instancePath+"/shots/" + i0+"/hyperframes_refs/" + i1,schemaPath:"#/$defs/shot/properties/hyperframes_refs/items/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err95];}else {vErrors.push(err95);}errors++;}}let i2 = data38.length;let j0;if(i2 > 1){const indices0 = {};for(;i2--;){let item0 = data38[i2];if(typeof item0 !== "string"){continue;}if(typeof indices0[item0] == "number"){j0 = indices0[item0];const err96 = {instancePath:instancePath+"/shots/" + i0+"/hyperframes_refs",schemaPath:"#/$defs/shot/properties/hyperframes_refs/uniqueItems",keyword:"uniqueItems",params:{i: i2, j: j0},message:"must NOT have duplicate items (items ## "+j0+" and "+i2+" are identical)"};if(vErrors === null){vErrors = [err96];}else {vErrors.push(err96);}errors++;break;}indices0[item0] = i2;}}}else {const err97 = {instancePath:instancePath+"/shots/" + i0+"/hyperframes_refs",schemaPath:"#/$defs/shot/properties/hyperframes_refs/type",keyword:"type",params:{type: "array"},message:"must be array"};if(vErrors === null){vErrors = [err97];}else {vErrors.push(err97);}errors++;}}if(data33.shotcraft_refs !== undefined){let data40 = data33.shotcraft_refs;if(Array.isArray(data40)){if(data40.length < 1){const err98 = {instancePath:instancePath+"/shots/" + i0+"/shotcraft_refs",schemaPath:"#/$defs/shot/properties/shotcraft_refs/minItems",keyword:"minItems",params:{limit: 1},message:"must NOT have fewer than 1 items"};if(vErrors === null){vErrors = [err98];}else {vErrors.push(err98);}errors++;}const len2 = data40.length;for(let i3=0; i3<len2; i3++){let data41 = data40[i3];if(typeof data41 === "string"){if(func2(data41) < 1){const err99 = {instancePath:instancePath+"/shots/" + i0+"/shotcraft_refs/" + i3,schemaPath:"#/$defs/shot/properties/shotcraft_refs/items/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err99];}else {vErrors.push(err99);}errors++;}}else {const err100 = {instancePath:instancePath+"/shots/" + i0+"/shotcraft_refs/" + i3,schemaPath:"#/$defs/shot/properties/shotcraft_refs/items/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err100];}else {vErrors.push(err100);}errors++;}}let i4 = data40.length;let j1;if(i4 > 1){const indices1 = {};for(;i4--;){let item1 = data40[i4];if(typeof item1 !== "string"){continue;}if(typeof indices1[item1] == "number"){j1 = indices1[item1];const err101 = {instancePath:instancePath+"/shots/" + i0+"/shotcraft_refs",schemaPath:"#/$defs/shot/properties/shotcraft_refs/uniqueItems",keyword:"uniqueItems",params:{i: i4, j: j1},message:"must NOT have duplicate items (items ## "+j1+" and "+i4+" are identical)"};if(vErrors === null){vErrors = [err101];}else {vErrors.push(err101);}errors++;break;}indices1[item1] = i4;}}}else {const err102 = {instancePath:instancePath+"/shots/" + i0+"/shotcraft_refs",schemaPath:"#/$defs/shot/properties/shotcraft_refs/type",keyword:"type",params:{type: "array"},message:"must be array"};if(vErrors === null){vErrors = [err102];}else {vErrors.push(err102);}errors++;}}if(data33.narration_scene !== undefined){let data42 = data33.narration_scene;if((typeof data42 !== "string") && (data42 !== null)){const err103 = {instancePath:instancePath+"/shots/" + i0+"/narration_scene",schemaPath:"#/$defs/shot/properties/narration_scene/type",keyword:"type",params:{type: schema36.properties.narration_scene.type},message:"must be string,null"};if(vErrors === null){vErrors = [err103];}else {vErrors.push(err103);}errors++;}}if(data33.motion_contract !== undefined){let data43 = data33.motion_contract;if(data43 && typeof data43 == "object" && !Array.isArray(data43)){if(data43.motion_preset === undefined){const err104 = {instancePath:instancePath+"/shots/" + i0+"/motion_contract",schemaPath:"#/$defs/shot/properties/motion_contract/required",keyword:"required",params:{missingProperty: "motion_preset"},message:"must have required property '"+"motion_preset"+"'"};if(vErrors === null){vErrors = [err104];}else {vErrors.push(err104);}errors++;}if(data43.energy === undefined){const err105 = {instancePath:instancePath+"/shots/" + i0+"/motion_contract",schemaPath:"#/$defs/shot/properties/motion_contract/required",keyword:"required",params:{missingProperty: "energy"},message:"must have required property '"+"energy"+"'"};if(vErrors === null){vErrors = [err105];}else {vErrors.push(err105);}errors++;}if(data43.camera === undefined){const err106 = {instancePath:instancePath+"/shots/" + i0+"/motion_contract",schemaPath:"#/$defs/shot/properties/motion_contract/required",keyword:"required",params:{missingProperty: "camera"},message:"must have required property '"+"camera"+"'"};if(vErrors === null){vErrors = [err106];}else {vErrors.push(err106);}errors++;}if(data43.transition === undefined){const err107 = {instancePath:instancePath+"/shots/" + i0+"/motion_contract",schemaPath:"#/$defs/shot/properties/motion_contract/required",keyword:"required",params:{missingProperty: "transition"},message:"must have required property '"+"transition"+"'"};if(vErrors === null){vErrors = [err107];}else {vErrors.push(err107);}errors++;}if(data43.shotcraft_commitments === undefined){const err108 = {instancePath:instancePath+"/shots/" + i0+"/motion_contract",schemaPath:"#/$defs/shot/properties/motion_contract/required",keyword:"required",params:{missingProperty: "shotcraft_commitments"},message:"must have required property '"+"shotcraft_commitments"+"'"};if(vErrors === null){vErrors = [err108];}else {vErrors.push(err108);}errors++;}if(data43.readable_rest_seconds === undefined){const err109 = {instancePath:instancePath+"/shots/" + i0+"/motion_contract",schemaPath:"#/$defs/shot/properties/motion_contract/required",keyword:"required",params:{missingProperty: "readable_rest_seconds"},message:"must have required property '"+"readable_rest_seconds"+"'"};if(vErrors === null){vErrors = [err109];}else {vErrors.push(err109);}errors++;}for(const key9 in data43){if(!((((((key9 === "motion_preset") || (key9 === "energy")) || (key9 === "camera")) || (key9 === "transition")) || (key9 === "shotcraft_commitments")) || (key9 === "readable_rest_seconds"))){const err110 = {instancePath:instancePath+"/shots/" + i0+"/motion_contract",schemaPath:"#/$defs/shot/properties/motion_contract/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key9},message:"must NOT have additional properties"};if(vErrors === null){vErrors = [err110];}else {vErrors.push(err110);}errors++;}}if(data43.motion_preset !== undefined){let data44 = data43.motion_preset;if(!((((((((data44 === "none") || (data44 === "slam-entrance")) || (data44 === "whip-transition")) || (data44 === "crash-zoom")) || (data44 === "push-stack-wipe")) || (data44 === "dataviz-landscape-open")) || (data44 === "panel-grid-reflow")) || (data44 === "brand-resolve"))){const err111 = {instancePath:instancePath+"/shots/" + i0+"/motion_contract/motion_preset",schemaPath:"#/$defs/shot/properties/motion_contract/properties/motion_preset/enum",keyword:"enum",params:{allowedValues: schema36.properties.motion_contract.properties.motion_preset.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err111];}else {vErrors.push(err111);}errors++;}}if(data43.energy !== undefined){let data45 = data43.energy;if(!((((data45 === "quiet") || (data45 === "balanced")) || (data45 === "high")) || (data45 === "cinematic"))){const err112 = {instancePath:instancePath+"/shots/" + i0+"/motion_contract/energy",schemaPath:"#/$defs/shot/properties/motion_contract/properties/energy/enum",keyword:"enum",params:{allowedValues: schema36.properties.motion_contract.properties.energy.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err112];}else {vErrors.push(err112);}errors++;}}if(data43.camera !== undefined){let data46 = data43.camera;if(typeof data46 === "string"){if(func2(data46) < 1){const err113 = {instancePath:instancePath+"/shots/" + i0+"/motion_contract/camera",schemaPath:"#/$defs/shot/properties/motion_contract/properties/camera/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err113];}else {vErrors.push(err113);}errors++;}}else {const err114 = {instancePath:instancePath+"/shots/" + i0+"/motion_contract/camera",schemaPath:"#/$defs/shot/properties/motion_contract/properties/camera/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err114];}else {vErrors.push(err114);}errors++;}}if(data43.transition !== undefined){let data47 = data43.transition;if(typeof data47 === "string"){if(func2(data47) < 1){const err115 = {instancePath:instancePath+"/shots/" + i0+"/motion_contract/transition",schemaPath:"#/$defs/shot/properties/motion_contract/properties/transition/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err115];}else {vErrors.push(err115);}errors++;}}else {const err116 = {instancePath:instancePath+"/shots/" + i0+"/motion_contract/transition",schemaPath:"#/$defs/shot/properties/motion_contract/properties/transition/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err116];}else {vErrors.push(err116);}errors++;}}if(data43.shotcraft_commitments !== undefined){let data48 = data43.shotcraft_commitments;if(Array.isArray(data48)){if(data48.length < 1){const err117 = {instancePath:instancePath+"/shots/" + i0+"/motion_contract/shotcraft_commitments",schemaPath:"#/$defs/shot/properties/motion_contract/properties/shotcraft_commitments/minItems",keyword:"minItems",params:{limit: 1},message:"must NOT have fewer than 1 items"};if(vErrors === null){vErrors = [err117];}else {vErrors.push(err117);}errors++;}const len3 = data48.length;for(let i5=0; i5<len3; i5++){let data49 = data48[i5];if(typeof data49 === "string"){if(func2(data49) < 1){const err118 = {instancePath:instancePath+"/shots/" + i0+"/motion_contract/shotcraft_commitments/" + i5,schemaPath:"#/$defs/shot/properties/motion_contract/properties/shotcraft_commitments/items/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err118];}else {vErrors.push(err118);}errors++;}}else {const err119 = {instancePath:instancePath+"/shots/" + i0+"/motion_contract/shotcraft_commitments/" + i5,schemaPath:"#/$defs/shot/properties/motion_contract/properties/shotcraft_commitments/items/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err119];}else {vErrors.push(err119);}errors++;}}}else {const err120 = {instancePath:instancePath+"/shots/" + i0+"/motion_contract/shotcraft_commitments",schemaPath:"#/$defs/shot/properties/motion_contract/properties/shotcraft_commitments/type",keyword:"type",params:{type: "array"},message:"must be array"};if(vErrors === null){vErrors = [err120];}else {vErrors.push(err120);}errors++;}}if(data43.readable_rest_seconds !== undefined){let data50 = data43.readable_rest_seconds;if(typeof data50 == "number"){if(data50 < 0 || isNaN(data50)){const err121 = {instancePath:instancePath+"/shots/" + i0+"/motion_contract/readable_rest_seconds",schemaPath:"#/$defs/shot/properties/motion_contract/properties/readable_rest_seconds/minimum",keyword:"minimum",params:{comparison: ">=", limit: 0},message:"must be >= 0"};if(vErrors === null){vErrors = [err121];}else {vErrors.push(err121);}errors++;}}else {const err122 = {instancePath:instancePath+"/shots/" + i0+"/motion_contract/readable_rest_seconds",schemaPath:"#/$defs/shot/properties/motion_contract/properties/readable_rest_seconds/type",keyword:"type",params:{type: "number"},message:"must be number"};if(vErrors === null){vErrors = [err122];}else {vErrors.push(err122);}errors++;}}}else {const err123 = {instancePath:instancePath+"/shots/" + i0+"/motion_contract",schemaPath:"#/$defs/shot/properties/motion_contract/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err123];}else {vErrors.push(err123);}errors++;}}}else {const err124 = {instancePath:instancePath+"/shots/" + i0,schemaPath:"#/$defs/shot/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err124];}else {vErrors.push(err124);}errors++;}}}else {const err125 = {instancePath:instancePath+"/shots",schemaPath:"#/properties/shots/type",keyword:"type",params:{type: "array"},message:"must be array"};if(vErrors === null){vErrors = [err125];}else {vErrors.push(err125);}errors++;}}if(data.assumptions !== undefined){let data51 = data.assumptions;if(Array.isArray(data51)){const len4 = data51.length;for(let i6=0; i6<len4; i6++){if(typeof data51[i6] !== "string"){const err126 = {instancePath:instancePath+"/assumptions/" + i6,schemaPath:"#/properties/assumptions/items/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err126];}else {vErrors.push(err126);}errors++;}}}else {const err127 = {instancePath:instancePath+"/assumptions",schemaPath:"#/properties/assumptions/type",keyword:"type",params:{type: "array"},message:"must be array"};if(vErrors === null){vErrors = [err127];}else {vErrors.push(err127);}errors++;}}}else {const err128 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err128];}else {vErrors.push(err128);}errors++;}validate20.errors = vErrors;return errors === 0;}validate20.evaluated = {"props":true,"dynamicProps":false,"dynamicItems":false};
|
|
@@ -4,27 +4,72 @@
|
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
6
|
import argparse
|
|
7
|
+
import json
|
|
7
8
|
import re
|
|
8
9
|
import sys
|
|
10
|
+
from html.parser import HTMLParser
|
|
9
11
|
from pathlib import Path
|
|
10
12
|
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
14
|
+
MOTION_HELPERS = {
|
|
15
|
+
"slam-entrance": "slamEntrance",
|
|
16
|
+
"whip-transition": "whipTransition",
|
|
17
|
+
"crash-zoom": "crashZoom",
|
|
18
|
+
"push-stack-wipe": "pushStackWipe",
|
|
19
|
+
"dataviz-landscape-open": "datavizLandscapeOpen",
|
|
20
|
+
"panel-grid-reflow": "panelGridReflow",
|
|
21
|
+
"brand-resolve": "brandResolve",
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class CompositionParser(HTMLParser):
|
|
26
|
+
def __init__(self) -> None:
|
|
27
|
+
super().__init__(convert_charrefs=True)
|
|
28
|
+
self.elements: list[tuple[str, dict[str, str | None]]] = []
|
|
29
|
+
self.scripts: list[str] = []
|
|
30
|
+
self.styles: list[str] = []
|
|
31
|
+
self.comments: list[str] = []
|
|
32
|
+
self._raw_tag: str | None = None
|
|
33
|
+
self._raw_text: list[str] = []
|
|
34
|
+
|
|
35
|
+
def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None:
|
|
36
|
+
self.elements.append((tag.lower(), {name.lower(): value for name, value in attrs}))
|
|
37
|
+
if tag.lower() in ("script", "style"):
|
|
38
|
+
self._raw_tag = tag.lower()
|
|
39
|
+
self._raw_text = []
|
|
40
|
+
|
|
41
|
+
def handle_startendtag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None:
|
|
42
|
+
self.handle_starttag(tag, attrs)
|
|
43
|
+
self.handle_endtag(tag)
|
|
44
|
+
|
|
45
|
+
def handle_data(self, data: str) -> None:
|
|
46
|
+
if self._raw_tag:
|
|
47
|
+
self._raw_text.append(data)
|
|
48
|
+
|
|
49
|
+
def handle_endtag(self, tag: str) -> None:
|
|
50
|
+
if tag.lower() != self._raw_tag:
|
|
51
|
+
return
|
|
52
|
+
target = self.scripts if self._raw_tag == "script" else self.styles
|
|
53
|
+
target.append("".join(self._raw_text))
|
|
54
|
+
self._raw_tag = None
|
|
55
|
+
self._raw_text = []
|
|
56
|
+
|
|
57
|
+
def handle_comment(self, data: str) -> None:
|
|
58
|
+
self.comments.append(data)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def parse_html(html: str) -> CompositionParser:
|
|
62
|
+
parser = CompositionParser()
|
|
63
|
+
parser.feed(html)
|
|
64
|
+
parser.close()
|
|
65
|
+
return parser
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def positive_number(value: str | None) -> bool:
|
|
24
69
|
try:
|
|
25
|
-
return float(
|
|
70
|
+
return value is not None and float(value) > 0
|
|
26
71
|
except ValueError:
|
|
27
|
-
return
|
|
72
|
+
return False
|
|
28
73
|
|
|
29
74
|
|
|
30
75
|
def check_html(
|
|
@@ -32,70 +77,98 @@ def check_html(
|
|
|
32
77
|
*,
|
|
33
78
|
component: bool = False,
|
|
34
79
|
preview_controls: bool = False,
|
|
80
|
+
shot_plan: dict | None = None,
|
|
35
81
|
) -> tuple[list[str], list[str]]:
|
|
36
82
|
failures: list[str] = []
|
|
37
83
|
warnings: list[str] = []
|
|
84
|
+
document = parse_html(html)
|
|
85
|
+
script = "\n".join(document.scripts)
|
|
86
|
+
style = "\n".join(document.styles)
|
|
87
|
+
composition_elements = [
|
|
88
|
+
attrs for _, attrs in document.elements if attrs.get("data-composition-id")
|
|
89
|
+
]
|
|
38
90
|
|
|
39
91
|
if not component:
|
|
92
|
+
composition = composition_elements[0] if composition_elements else {}
|
|
40
93
|
for attr in ("data-width", "data-height", "data-duration", "data-composition-id"):
|
|
41
|
-
if not
|
|
94
|
+
if not composition.get(attr):
|
|
42
95
|
failures.append(f"missing {attr}")
|
|
43
96
|
for attr in ("data-width", "data-height", "data-duration"):
|
|
44
|
-
if
|
|
45
|
-
|
|
46
|
-
if value is None or value <= 0:
|
|
47
|
-
failures.append(f"{attr} must be a positive number")
|
|
97
|
+
if attr in composition and not positive_number(composition.get(attr)):
|
|
98
|
+
failures.append(f"{attr} must be a positive number")
|
|
48
99
|
|
|
49
|
-
if "
|
|
100
|
+
if any("paste from " in comment.lower() for comment in document.comments):
|
|
50
101
|
failures.append("unresolved component paste placeholder")
|
|
51
102
|
|
|
52
103
|
paused_timeline = re.search(
|
|
53
104
|
r"gsap\s*\.\s*timeline\s*\(\s*\{[^}]*paused\s*:\s*true",
|
|
54
|
-
|
|
105
|
+
script,
|
|
55
106
|
re.IGNORECASE | re.DOTALL,
|
|
56
107
|
)
|
|
57
108
|
if not paused_timeline:
|
|
58
109
|
failures.append("missing gsap.timeline({ paused: true })")
|
|
59
110
|
|
|
60
|
-
if "window.__timelines" not in
|
|
111
|
+
if "window.__timelines" not in script:
|
|
61
112
|
failures.append("missing window.__timelines registration")
|
|
62
113
|
|
|
63
|
-
if re.search(r"\bDate\s*\.\s*now\s*\(",
|
|
114
|
+
if re.search(r"\bDate\s*\.\s*now\s*\(", script):
|
|
64
115
|
failures.append("uses Date.now(); render progress must be timeline-driven")
|
|
65
116
|
|
|
66
|
-
if re.search(r"\bsetInterval\s*\(",
|
|
117
|
+
if re.search(r"\bsetInterval\s*\(", script):
|
|
67
118
|
failures.append("uses setInterval(); primary render progress must be timeline-driven")
|
|
68
119
|
|
|
69
|
-
if re.search(r"\bMath\s*\.\s*random\s*\(",
|
|
120
|
+
if re.search(r"\bMath\s*\.\s*random\s*\(", script):
|
|
70
121
|
failures.append("uses Math.random(); visual generation must use a fixed-seed deterministic PRNG")
|
|
71
122
|
|
|
72
|
-
if re.search(r"\brequestAnimationFrame\s*\(",
|
|
123
|
+
if re.search(r"\brequestAnimationFrame\s*\(", script) and "fallback" not in script.lower():
|
|
73
124
|
warnings.append("requestAnimationFrame found; ensure it is not the primary render clock and has render fallback")
|
|
74
125
|
|
|
75
|
-
if
|
|
126
|
+
if document.styles and "[data-composition-id" not in style:
|
|
76
127
|
warnings.append("style block found without [data-composition-id] scoped selector")
|
|
77
128
|
|
|
78
|
-
if
|
|
129
|
+
if sum("data-duration" in attrs for _, attrs in document.elements) > 1:
|
|
79
130
|
warnings.append("multiple data-duration values found; verify the intended render duration")
|
|
80
131
|
|
|
81
132
|
if preview_controls:
|
|
82
|
-
|
|
133
|
+
attrs = [attributes for _, attributes in document.elements]
|
|
134
|
+
if not any("data-hyper-preview-ui" in attributes for attributes in attrs):
|
|
83
135
|
failures.append("missing preview controls: data-hyper-preview-ui")
|
|
84
|
-
if "data-hyper-preview-page"
|
|
136
|
+
if not any("data-hyper-preview-page" in attributes for attributes in attrs):
|
|
85
137
|
failures.append("missing preview controls: page indicator")
|
|
86
|
-
if "data-hyper-preview-progress"
|
|
138
|
+
if not any("data-hyper-preview-progress" in attributes for attributes in attrs):
|
|
87
139
|
failures.append("missing preview controls: progress input")
|
|
88
|
-
if not
|
|
140
|
+
if not any(tag == "input" and attributes.get("type") == "range" for tag, attributes in document.elements):
|
|
89
141
|
failures.append("missing preview controls: range input")
|
|
90
|
-
if "ArrowLeft" not in
|
|
142
|
+
if "ArrowLeft" not in script or "ArrowRight" not in script:
|
|
91
143
|
failures.append("missing preview controls: left/right keyboard handlers")
|
|
92
|
-
if 'params.get("render") === "1"' not in
|
|
144
|
+
if 'params.get("render") === "1"' not in script:
|
|
93
145
|
failures.append("missing preview controls: ?render=1 hidden-mode check")
|
|
94
|
-
if 'params.get("preview") === "0"' not in
|
|
146
|
+
if 'params.get("preview") === "0"' not in script:
|
|
95
147
|
failures.append("missing preview controls: ?preview=0 hidden-mode check")
|
|
96
|
-
if 'dataset.renderMode === "video"' not in
|
|
148
|
+
if 'dataset.renderMode === "video"' not in script:
|
|
97
149
|
failures.append("missing preview controls: data-render-mode video hidden-mode check")
|
|
98
150
|
|
|
151
|
+
if shot_plan is not None:
|
|
152
|
+
shot_elements = {
|
|
153
|
+
attrs.get("data-shot-id"): attrs
|
|
154
|
+
for _, attrs in document.elements
|
|
155
|
+
if attrs.get("data-shot-id")
|
|
156
|
+
}
|
|
157
|
+
for shot in shot_plan.get("shots", []):
|
|
158
|
+
shot_id = shot.get("id")
|
|
159
|
+
preset = shot.get("motion_contract", {}).get("motion_preset")
|
|
160
|
+
attrs = shot_elements.get(shot_id)
|
|
161
|
+
if attrs is None:
|
|
162
|
+
failures.append(f"missing data-shot-id element for shot: {shot_id}")
|
|
163
|
+
continue
|
|
164
|
+
if attrs.get("data-motion-preset") != preset:
|
|
165
|
+
failures.append(f"shot {shot_id} data-motion-preset must be {preset}")
|
|
166
|
+
helper = MOTION_HELPERS.get(preset)
|
|
167
|
+
if helper:
|
|
168
|
+
calls_only = re.sub(rf"\bfunction\s+{re.escape(helper)}\s*\(", "", script)
|
|
169
|
+
if not re.search(rf"\b{re.escape(helper)}\s*\(", calls_only):
|
|
170
|
+
failures.append(f"shot {shot_id} must call motion-pack helper {helper}")
|
|
171
|
+
|
|
99
172
|
return failures, warnings
|
|
100
173
|
|
|
101
174
|
|
|
@@ -112,6 +185,10 @@ def main() -> int:
|
|
|
112
185
|
action="store_true",
|
|
113
186
|
help="Require injected Hyper Animator preview controls",
|
|
114
187
|
)
|
|
188
|
+
parser.add_argument(
|
|
189
|
+
"--shot-plan",
|
|
190
|
+
help="Cross-check data-shot-id and motion-pack usage against a shot-plan JSON file",
|
|
191
|
+
)
|
|
115
192
|
args = parser.parse_args()
|
|
116
193
|
|
|
117
194
|
path = Path(args.html_file)
|
|
@@ -120,10 +197,19 @@ def main() -> int:
|
|
|
120
197
|
return 2
|
|
121
198
|
|
|
122
199
|
html = path.read_text(encoding="utf-8")
|
|
200
|
+
shot_plan = None
|
|
201
|
+
if args.shot_plan:
|
|
202
|
+
try:
|
|
203
|
+
shot_plan = json.loads(Path(args.shot_plan).read_text(encoding="utf-8"))
|
|
204
|
+
except (OSError, json.JSONDecodeError) as error:
|
|
205
|
+
print(f"FAIL: cannot read shot plan: {error}", file=sys.stderr)
|
|
206
|
+
return 2
|
|
207
|
+
|
|
123
208
|
failures, warnings = check_html(
|
|
124
209
|
html,
|
|
125
210
|
component=args.component,
|
|
126
211
|
preview_controls=args.preview_controls,
|
|
212
|
+
shot_plan=shot_plan,
|
|
127
213
|
)
|
|
128
214
|
|
|
129
215
|
for warning in warnings:
|