@vosjs/cli 0.53.6 → 0.54.1

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.
@@ -46,6 +46,18 @@ var manifest = {
46
46
  name: "ingest",
47
47
  summary: "a take from a recording someone else made, with its cursor track from a trace beside it (Playwright trace.zip, stamped records, CSV); without one nothing is planned"
48
48
  },
49
+ {
50
+ name: "port",
51
+ summary: "bring a page, a HyperFrames or a Remotion piece: inventory (its words, colours, faces, media, scenes) then scaffold (a data-first program.mjs to translate the motion into)"
52
+ },
53
+ {
54
+ name: "build",
55
+ summary: "program.mjs (real functions) \u2192 config.json, refusing what cannot run on its own (module-scope reads, syntax the page cannot parse, non-JSON data)"
56
+ },
57
+ {
58
+ name: "compare",
59
+ summary: "a program against the source's own render: per-frame SSIM and source | vos | difference sheets; exits 1 when any frame is under the threshold"
60
+ },
49
61
  {
50
62
  name: "brand",
51
63
  summary: "write a product's BRAND.md, witnessed: /design.md, /llms.txt, then the page (palette, faces, marks, the avoid list)"
@@ -101,4 +113,4 @@ var manifest = {
101
113
  export {
102
114
  manifest
103
115
  };
104
- //# sourceMappingURL=chunk-2EHIFIYC.js.map
116
+ //# sourceMappingURL=chunk-WZGCEAXB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/plugin/manifest.ts"],"sourcesContent":["/**\n * The verb manifest of the take pipeline and the vos.so verbs — what\n * `vos help` lists under the engine verbs. It kept the shape a separately\n * installed plugin once handed the host (name + host range), so a script\n * reading it keeps working.\n */\nexport interface PluginVerb {\n name: string\n summary: string\n}\n\nexport interface PluginManifest {\n name: string\n /** Host versions this plugin speaks the run(argv) contract with. */\n hostRange: string\n verbs: PluginVerb[]\n}\n\nexport const manifest: PluginManifest = {\n name: '@vosjs/cli',\n hostRange: '>=0.9.0',\n verbs: [\n {\n name: 'create',\n summary: 'record + auto-plan + render, one command (--strict)',\n },\n {\n name: 'record',\n summary: 'drive actions.json into a take (screencast + cursor track)',\n },\n {\n name: 'plan',\n summary:\n 'plan zoom/cursor effects into doc.json (wand contract); --reuse re-times a previous cut onto a re-recording',\n },\n {\n name: 'render',\n summary: 'render a take directory (engine configs render in the host)',\n },\n {\n name: 'frames',\n summary:\n 'PNG stills at output times / zoom apexes / moments / exact sizes',\n },\n {\n name: 'deliver',\n summary:\n 'render a take to release destinations (CWS, Product Hunt, X, LinkedIn, OG…) + verified kit.json',\n },\n {\n name: 'digest',\n summary:\n 'see a recording before cutting it: moments (clicks, typing, scrolls, idle, scenes) + footage frames + crops, in doc units',\n },\n { name: 'open', summary: 'serve the take into the vos.so studio' },\n {\n name: 'validate',\n summary:\n 'lint actions.json, a take dir (doc.json semantics), or re-measure a kit.json against the channel specs',\n },\n {\n name: 'actions',\n summary:\n 'from-agent-browser: turn an agent-browser walk (steps.jsonl) into actions.json; what cannot follow is named',\n },\n {\n name: 'ingest',\n summary:\n 'a take from a recording someone else made, with its cursor track from a trace beside it (Playwright trace.zip, stamped records, CSV); without one nothing is planned',\n },\n {\n name: 'port',\n summary:\n 'bring a page, a HyperFrames or a Remotion piece: inventory (its words, colours, faces, media, scenes) then scaffold (a data-first program.mjs to translate the motion into)',\n },\n {\n name: 'build',\n summary:\n 'program.mjs (real functions) → config.json, refusing what cannot run on its own (module-scope reads, syntax the page cannot parse, non-JSON data)',\n },\n {\n name: 'compare',\n summary:\n \"a program against the source's own render: per-frame SSIM and source | vos | difference sheets; exits 1 when any frame is under the threshold\",\n },\n {\n name: 'brand',\n summary:\n \"write a product's BRAND.md, witnessed: /design.md, /llms.txt, then the page (palette, faces, marks, the avoid list)\",\n },\n {\n name: 'fetch',\n summary: 'download a hosted program: config.json + vos.json tracking',\n },\n {\n name: 'push',\n summary: 'push a config.json or take to vos.so (private; versioned)',\n },\n {\n name: 'duplicate',\n summary:\n 'a private sibling of your OWN vos (someone else\\u2019s is remixed: fetch + push --remix-of)',\n },\n {\n name: 'pull',\n summary:\n 'sync what changed on vos.so since your base (--media brings a take’s footage home)',\n },\n {\n name: 'folder',\n summary:\n 'list/create/pull folders, move voses and assets into them (pull = the context package on disk)',\n },\n {\n name: 'asset',\n summary: 'rename one of your assets in place (recipes included)',\n },\n {\n name: 'recipe',\n summary:\n 'push a recipe .md into a folder, or replace one in place (prior body kept)',\n },\n {\n name: 'login',\n summary: 'sign in via the browser (or --key); stores a content key',\n },\n {\n name: 'setup',\n summary:\n 'ready this machine: the vos skills into your agent, a browser, one rules block, then doctor',\n },\n {\n name: 'doctor',\n summary:\n 'what is ready, in words: node, browser, ffmpeg, skills, a credential (never printed), the dev server',\n },\n {\n name: 'whoami',\n summary: 'the key’s name and the account it belongs to, never the key',\n },\n { name: 'logout', summary: 'remove ~/.config/vos/credentials' },\n ],\n}\n"],"mappings":";;;AAkBO,IAAM,WAA2B;AAAA,EACtC,MAAM;AAAA,EACN,WAAW;AAAA,EACX,OAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA,EAAE,MAAM,QAAQ,SAAS,wCAAwC;AAAA,IACjE;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA,EAAE,MAAM,UAAU,SAAS,mCAAmC;AAAA,EAChE;AACF;","names":[]}
package/dist/cli.js CHANGED
@@ -1,12 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- inspectStill,
4
- previewPages,
5
- reencodeStill,
6
- renderStill,
7
- renderVideo,
8
- stillWarnings
9
- } from "./chunk-ZCLGXETO.js";
10
2
  import {
11
3
  BrowserUnavailableError,
12
4
  MEDIA_HEAD_BYTES,
@@ -15,6 +7,7 @@ import {
15
7
  configDuration,
16
8
  directoryKind,
17
9
  helpFlagsFor,
10
+ inspectStill,
18
11
  launchBrowser,
19
12
  loadProgramDirectory,
20
13
  loadVosConfig,
@@ -22,15 +15,20 @@ import {
22
15
  parseArgs,
23
16
  parseTimes,
24
17
  platformOrigin,
18
+ previewPages,
25
19
  readSourceText,
20
+ reencodeStill,
21
+ renderStill,
22
+ renderVideo,
26
23
  resolveCredential,
27
24
  resolveMediaType,
28
25
  setFlags,
29
26
  stillFormat,
30
27
  stillOutFor,
28
+ stillWarnings,
31
29
  unusedFlagsMessage,
32
30
  videoFormat
33
- } from "./chunk-WLUWDQQO.js";
31
+ } from "./chunk-JX2YEL3M.js";
34
32
 
35
33
  // src/cli.ts
36
34
  import { writeFile } from "fs/promises";
@@ -445,7 +443,8 @@ async function cmdRender(argv) {
445
443
  await writeFile(out, result.bytes);
446
444
  const warnings = stillWarnings(
447
445
  { transparent: false, flat: false },
448
- result.pageErrors
446
+ result.pageErrors,
447
+ result.engineNotes
449
448
  );
450
449
  for (const w of warnings) r.log(`warn: ${w}`);
451
450
  r.done(
@@ -509,7 +508,8 @@ async function cmdStill(argv) {
509
508
  await writeFile(target, bytes);
510
509
  const warnings = stillWarnings(
511
510
  await inspectStill(browser, result.bytes),
512
- result.pageErrors
511
+ result.pageErrors,
512
+ result.engineNotes
513
513
  );
514
514
  written.push({
515
515
  out: target,
@@ -728,7 +728,7 @@ async function cmdCheck(argv) {
728
728
  return result.ok ? EXIT_OK : EXIT_ERROR;
729
729
  }
730
730
  async function delegate(argv, viaAlias = false) {
731
- const { run } = await import("./run-DYNCGXWO.js");
731
+ const { run } = await import("./run-SYDEWMK2.js");
732
732
  if (viaAlias && argv[0]) {
733
733
  process.stderr.write(
734
734
  `note: "vos voila ${argv[0]}" is now "vos ${argv[0]}".
@@ -739,7 +739,7 @@ async function delegate(argv, viaAlias = false) {
739
739
  }
740
740
  async function printHelp() {
741
741
  process.stdout.write(HELP_ENGINE);
742
- const { manifest } = await import("./manifest-IG2WSARS.js");
742
+ const { manifest } = await import("./manifest-Q4QMVIYR.js");
743
743
  process.stdout.write("\nTake pipeline + vos.so verbs\n");
744
744
  for (const v of manifest.verbs) {
745
745
  if (v.name === "render") continue;
@@ -768,7 +768,7 @@ async function main() {
768
768
  const engine = HELP_ENGINE.split("\n").filter(
769
769
  (l) => l.startsWith(` vos ${cmd} `)
770
770
  );
771
- const { verbHelp } = await import("./run-DYNCGXWO.js");
771
+ const { verbHelp } = await import("./run-SYDEWMK2.js");
772
772
  const take = verbHelp(cmd);
773
773
  process.stdout.write(
774
774
  `${engine.join("\n")}
@@ -800,7 +800,7 @@ ${take.includes("no such verb") ? "" : take}`
800
800
  main().then(async (code) => {
801
801
  if (code === EXIT_OK) {
802
802
  const verb = process.argv[2] ?? "";
803
- const { HELP } = await import("./run-DYNCGXWO.js");
803
+ const { HELP } = await import("./run-SYDEWMK2.js");
804
804
  const documented = [
805
805
  ...helpFlagsFor(HELP_ENGINE, verb),
806
806
  ...helpFlagsFor(HELP, verb)
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/output.ts","../src/check.ts","../src/plugin/knobs.ts","../src/programAudio.ts"],"sourcesContent":["import { writeFile } from 'node:fs/promises'\nimport { existsSync, readFileSync, statSync } from 'node:fs'\nimport { basename, dirname, join } from 'node:path'\nimport { createServer } from 'node:http'\nimport { createRequire } from 'node:module'\nimport { fileURLToPath } from 'node:url'\nimport { parseArgs, numFlag, UsageError } from './args'\nimport { helpFlagsFor, unusedFlagsMessage } from './flagUse'\nimport {\n createReporter,\n EXIT_ERROR,\n EXIT_NO_BROWSER,\n EXIT_OK,\n EXIT_USAGE,\n} from './output'\nimport {\n loadVosConfig,\n configDuration,\n directoryKind,\n loadProgramDirectory,\n readSourceText,\n} from './loadConfig'\nimport { launchBrowser, BrowserUnavailableError } from './browser'\nimport {\n inspectStill,\n previewPages,\n reencodeStill,\n renderStill,\n renderVideo,\n stillWarnings,\n} from './render'\nimport { runCheck } from './check'\nimport { programAudio } from './programAudio'\nimport {\n applyDataSets,\n parseTimes,\n setFlags,\n stillFormat,\n stillOutFor,\n videoFormat,\n} from './outputs'\nimport { platformOrigin, resolveCredential } from './plugin/platform'\n\nconst BOOLEAN_FLAGS = new Set(['json', 'help', 'version'])\n\nconst HELP_ENGINE = `vos — command line for the vos programmatic video engine (https://vos.so/engine)\n\nEngine verbs (local, no account, no network beyond the render page's CDN deps)\n vos render <config.json|url|take> [out.mp4|out.webm] [--width 1920] [--height 1080] [--fps 30]\n [--duration <s>] [--format webm|mp4] [--set data.<key>=<value>]... [--json]\n the output's name picks the container; a program document's sound is mixed in\n vos still <config.json|url> [out.webp|out.png|out.jpg] [--time 0 | --times 0,1.5,50%]\n [--width] [--height] [--set data.<key>=<value>]... [--json]\n vos info <config.json|url> [--json]\n vos check <config.json|url> [--json]\n migrate → schema → syntax → compile → determinism/dialect lints, all local\n vos preview <config.json|url> [--port 0]\n vos versions [--json]\n`\n\nconst HELP_CONVENTIONS = `\nConventions\n Results go to stdout; logs go to stderr. --json switches stdout to NDJSON\n events ending with {\"event\":\"done\",…}. Exit codes: 0 ok, 1 error, 2 usage,\n 3 no browser available, 4 the recorder met a sign-in instead of the page\n it was asked for (nothing was recorded; it needs a session, not a new\n script). vos <verb> --help prints that verb's flags.\n`\n\n/** An `audio` element in the config: something a render never mixes. */\nfunction hasAudioElements(config: unknown): boolean {\n const elements = (config as { elements?: unknown }).elements\n return (\n Array.isArray(elements) &&\n elements.some(\n (e) =>\n !!e &&\n typeof e === 'object' &&\n (e as { type?: unknown }).type === 'audio',\n )\n )\n}\n\nfunction outName(source: string, ext: string): string {\n const base = basename(source).replace(/\\.[a-z0-9]+$/i, '') || 'vos'\n return `${base}.${ext}`\n}\n\nasync function cmdRender(argv: string[]): Promise<number> {\n // Polymorphic render: a take DIRECTORY (its doc.json is a recording\n // document) renders through the plugin; a program directory (config.json,\n // composed with a program document when one sits beside it) and every\n // other source are engine config renders. A deterministic sniff, never a\n // flag — and the sniff reads the document, because a program directory\n // carries a doc.json too.\n const first = argv.find((a) => !a.startsWith('-'))\n if (first && directoryKind(first) === 'take') {\n return delegate(['render', ...argv])\n }\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const source = positionals[0]\n if (!source) throw new UsageError('vos render <config.json|url|take> [out]')\n const r = createReporter(flags.json === true)\n const format = videoFormat(\n flags.format === undefined ? undefined : String(flags.format),\n positionals[1],\n )\n\n const loaded = await loadVosConfig(source)\n for (const w of loaded.warnings) r.log(`note: ${w}`)\n void flags.set\n const config = applyDataSets(\n loaded.config as Record<string, unknown>,\n setFlags(argv),\n )\n const duration = numFlag(flags, 'duration', configDuration(config) ?? 5)\n const width = numFlag(flags, 'width', 1920)\n const height = numFlag(flags, 'height', 1080)\n const fps = numFlag(flags, 'fps', 30)\n const out = positionals[1] ?? outName(source, format)\n\n // A program document's sound rides its studio entry; mix it like a take's.\n const audio = await programAudio(config as Record<string, unknown>, {\n baseDir:\n existsSync(source) && statSync(source).isDirectory()\n ? source\n : dirname(source),\n duration,\n origin: platformOrigin({}),\n key: resolveCredential(),\n log: (line) => r.log(line),\n })\n if (audio) r.log(`mixing ${audio.clips} sound${audio.clips === 1 ? '' : 's'}`)\n if (hasAudioElements(config)) {\n r.log(\n 'note: an audio ELEMENT is not mixed by a render; put the sound on the program document instead (doc.json audio: [{ key, start, in, out, duration, gain }])',\n )\n }\n\n const browser = await launchBrowser()\n try {\n const result = await renderVideo(browser, {\n config,\n width,\n height,\n fps,\n duration,\n format,\n audioProducerCode: audio?.producerCode,\n onPhase: (phase) => {\n r.log(`${phase}…`)\n r.event({ event: 'phase', phase })\n },\n })\n await writeFile(out, result.bytes)\n const warnings = stillWarnings(\n { transparent: false, flat: false },\n result.pageErrors,\n )\n for (const w of warnings) r.log(`warn: ${w}`)\n r.done(\n {\n out,\n bytes: result.bytes.length,\n width,\n height,\n fps,\n duration,\n format,\n audio: audio?.clips ?? 0,\n ...(warnings.length ? { warnings } : {}),\n },\n `Wrote ${out} (${(result.bytes.length / 1024).toFixed(0)} KB, ${width}x${height}@${fps}, ${duration}s)`,\n )\n return EXIT_OK\n } finally {\n await browser.close()\n }\n}\n\nasync function cmdStill(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const source = positionals[0]\n if (!source)\n throw new UsageError(\n 'vos still <config.json|url> [out.webp|out.png|out.jpg] [--time t | --times a,b,50%]',\n )\n const r = createReporter(flags.json === true)\n\n const loaded = await loadVosConfig(source)\n for (const w of loaded.warnings) r.log(`note: ${w}`)\n void flags.set\n const config = applyDataSets(\n loaded.config as Record<string, unknown>,\n setFlags(argv),\n )\n const width = numFlag(flags, 'width', 1280)\n const height = numFlag(flags, 'height', 720)\n const out = positionals[1] ?? outName(source, 'webp')\n const encoding = stillFormat(out)\n const timesRaw = flags.times === undefined ? undefined : String(flags.times)\n if (timesRaw !== undefined && flags.time !== undefined)\n throw new UsageError('--time and --times: pass one')\n const times =\n timesRaw !== undefined\n ? parseTimes(timesRaw, configDuration(config) ?? 5)\n : [numFlag(flags, 'time', 0)]\n const many = times.length > 1\n\n // One browser for every time: each still is its own capture page.\n const browser = await launchBrowser()\n try {\n const written: {\n out: string\n bytes: number\n time: number\n warnings?: string[]\n }[] = []\n for (const time of times) {\n const target = stillOutFor(out, time, many)\n const result = await renderStill(browser, {\n config,\n width,\n height,\n time,\n onPhase: (phase) => {\n r.event({ event: 'phase', phase, time })\n },\n })\n // The engine captures WebP; a .png or .jpg name is re-encoded in the\n // page, so the bytes always match the name.\n const bytes =\n encoding === 'webp'\n ? result.bytes\n : await reencodeStill(browser, result.bytes, encoding)\n await writeFile(target, bytes)\n // A still is checked before anyone looks at it: a fully transparent\n // or flat frame is written, and said, never passed off as a picture.\n const warnings = stillWarnings(\n await inspectStill(browser, result.bytes),\n result.pageErrors,\n )\n written.push({\n out: target,\n bytes: bytes.length,\n time,\n ...(warnings.length ? { warnings } : {}),\n })\n r.log(\n `Wrote ${target} (${(bytes.length / 1024).toFixed(0)} KB @ t=${Number(time.toFixed(2))}s)`,\n )\n for (const w of warnings)\n r.log(`warn: t=${Number(time.toFixed(2))}s ${w}`)\n }\n const first = written[0]\n r.done(\n many\n ? { stills: written, width, height, format: encoding }\n : { ...first, width, height, format: encoding },\n many\n ? `Wrote ${written.length} stills (${width}x${height})`\n : `Wrote ${first.out} (${(first.bytes / 1024).toFixed(0)} KB, ${width}x${height} @ t=${first.time}s)`,\n )\n return EXIT_OK\n } finally {\n await browser.close()\n }\n}\n\nasync function cmdInfo(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const source = positionals[0]\n if (!source) throw new UsageError('vos info <config.json|url>')\n const r = createReporter(flags.json === true)\n\n const { config, warnings } = await loadVosConfig(source)\n const elements = Array.isArray(config.elements) ? config.elements.length : 0\n const data =\n typeof config.data === 'object' && config.data !== null\n ? Object.keys(config.data)\n : []\n const fns = ['setup', 'createContent', 'createTimeline', 'onFrame'].filter(\n (k) => typeof config[k] === 'string',\n )\n const info = {\n version: config.version,\n duration: configDuration(config) ?? null,\n camera:\n (config.camera as Record<string, unknown> | undefined)?.preset ?? null,\n elements,\n dataKeys: data,\n functions: fns,\n warnings,\n }\n if (r.json) r.done(info, '')\n else {\n for (const w of warnings) r.log(`note: ${w}`)\n process.stdout.write(\n `version: v${String(info.version)}\\n` +\n `duration: ${info.duration === null ? '(none)' : `${info.duration}s`}\\n` +\n `camera: ${String(info.camera ?? '(default)')}\\n` +\n `elements: ${elements}\\n` +\n `data keys: ${data.length ? data.join(', ') : '(none)'}\\n` +\n `functions: ${fns.join(', ')}\\n`,\n )\n }\n return EXIT_OK\n}\n\nfunction packageVersion(name: string): string | null {\n const require = createRequire(import.meta.url)\n // Fast path — packages that export ./package.json (e.g. playwright).\n try {\n return (require(`${name}/package.json`) as { version: string }).version\n } catch {\n // Strict `exports` maps (the @vosjs packages) hide package.json — resolve\n // the entry module instead and walk up to the owning package.json.\n }\n let entry: string | null = null\n try {\n entry = fileURLToPath(import.meta.resolve(name))\n } catch {\n try {\n entry = require.resolve(name)\n } catch {\n return null\n }\n }\n let dir = dirname(entry)\n for (let i = 0; i < 6; i++) {\n try {\n const pkg = JSON.parse(\n readFileSync(join(dir, 'package.json'), 'utf8'),\n ) as {\n name?: string\n version?: string\n }\n if (pkg.name === name && pkg.version) return pkg.version\n } catch {\n // keep walking\n }\n const parent = dirname(dir)\n if (parent === dir) return null\n dir = parent\n }\n return null\n}\n\nfunction ownVersion(): string {\n try {\n const own = JSON.parse(\n readFileSync(\n fileURLToPath(new URL('../package.json', import.meta.url)),\n 'utf8',\n ),\n ) as { version: string }\n return own.version\n } catch {\n return '(unknown)'\n }\n}\n\nasync function cmdVersions(argv: string[]): Promise<number> {\n const { flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const r = createReporter(flags.json === true)\n const versions: Record<string, string> = {}\n versions['@vosjs/cli'] = ownVersion()\n for (const name of [\n '@vosjs/core',\n '@vosjs/elements',\n '@vosjs/tween',\n '@vosjs/editor',\n '@vosjs/timeline',\n '@vosjs/studio-core',\n '@vosjs/render-core',\n '@vosjs/shared',\n 'mediabunny',\n 'playwright',\n ]) {\n versions[name] = packageVersion(name) ?? '(not found)'\n }\n if (r.json) r.done({ versions }, '')\n else\n for (const [k, v] of Object.entries(versions))\n process.stdout.write(`${k} ${v}\\n`)\n return EXIT_OK\n}\n\nasync function cmdPreview(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const source = positionals[0]\n if (!source) throw new UsageError('vos preview <config.json|url> [--port 0]')\n const r = createReporter(false)\n const { config, warnings } = await loadVosConfig(source)\n for (const w of warnings) r.log(`note: ${w}`)\n const { hostHtml, playerHtml } = previewPages(config)\n const server = createServer((req, res) => {\n const path = new URL(req.url ?? '/', 'http://x').pathname\n res.writeHead(200, { 'content-type': 'text/html' })\n res.end(path === '/player' ? playerHtml : hostHtml)\n })\n const port = numFlag(flags, 'port', 0)\n await new Promise<void>((resolve) => server.listen(port, resolve))\n const addr = server.address()\n const url = `http://localhost:${typeof addr === 'object' && addr ? addr.port : port}/`\n process.stdout.write(`${url}\\n`)\n r.log('Serving playback preview — Ctrl-C to stop.')\n await new Promise(() => {}) // keep alive until interrupted\n return EXIT_OK\n}\n\nasync function cmdCheck(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const source = positionals[0]\n if (!source) throw new UsageError('vos check <config.json>')\n const r = createReporter(flags.json === true)\n\n // A directory is a take (refused here: its document is `vos validate`'s\n // job) or a program directory (config.json, composed with the program\n // document beside it so the ladder reads the layers' strings too).\n const kind = /^https?:\\/\\//.test(source) ? 'none' : directoryKind(source)\n if (kind === 'take') {\n throw new UsageError(\n `${source} is a take (its doc.json is a recording document). vos validate ${source} lints it; vos render ${source} renders it.`,\n )\n }\n let raw: string\n let parsed: unknown\n try {\n if (kind === 'program') {\n const notes: string[] = []\n parsed = await loadProgramDirectory(source, notes)\n for (const n of notes) r.log(`note: ${n}`)\n raw = ''\n } else {\n raw = await readSourceText(source)\n parsed = JSON.parse(raw)\n }\n } catch (e) {\n if (!(e instanceof SyntaxError)) throw e\n parsed = undefined\n if (!r.json) process.stdout.write(`error [json] ${(e as Error).message}\\n`)\n r.done(\n {\n ok: false,\n errors: 1,\n warnings: 0,\n issues: [\n { level: 'error', source: 'json', message: (e as Error).message },\n ],\n },\n `${source}: 1 error`,\n )\n return EXIT_ERROR\n }\n\n const result = runCheck(parsed)\n if (r.json) {\n r.done(\n {\n ok: result.ok,\n errors: result.errors,\n warnings: result.warnings,\n issues: result.issues,\n },\n '',\n )\n } else {\n for (const i of result.issues) {\n process.stdout.write(`${i.level} [${i.source}] ${i.message}\\n`)\n }\n process.stdout.write(\n result.ok\n ? `${source}: ok (${result.warnings} warning${result.warnings === 1 ? '' : 's'})\\n`\n : `${source}: ${result.errors} error${result.errors === 1 ? '' : 's'}, ${result.warnings} warning${result.warnings === 1 ? '' : 's'}\\n`,\n )\n }\n return result.ok ? EXIT_OK : EXIT_ERROR\n}\n\n// ---------------------------------------------------------------------------\n// Every verb this file does not own is a take-pipeline or vos.so verb from\n// `./plugin` (what used to ship separately as @vosso/vos-plugin). It loads on\n// demand, so the engine verbs never pay for the recorder's imports, and the\n// old names (`@vosso/cli`, `@vosso/voila-cli`, the `vos voila` alias) keep\n// resolving here for scripts that still use them.\n// ---------------------------------------------------------------------------\n\nasync function delegate(argv: string[], viaAlias = false): Promise<number> {\n const { run } = await import('./plugin/run')\n if (viaAlias && argv[0]) {\n process.stderr.write(\n `note: \"vos voila ${argv[0]}\" is now \"vos ${argv[0]}\".\\n`,\n )\n }\n return await run(argv)\n}\n\nasync function printHelp(): Promise<void> {\n process.stdout.write(HELP_ENGINE)\n const { manifest } = await import('./plugin/manifest')\n process.stdout.write('\\nTake pipeline + vos.so verbs\\n')\n for (const v of manifest.verbs) {\n if (v.name === 'render') continue // polymorphic — already listed above\n process.stdout.write(` vos ${v.name.padEnd(8)} ${v.summary}\\n`)\n }\n process.stdout.write(HELP_CONVENTIONS)\n}\n\nconst ENGINE_VERBS = new Set([\n 'render',\n 'still',\n 'info',\n 'versions',\n 'preview',\n 'check',\n])\n\nasync function main(): Promise<number> {\n const [cmd, ...rest] = process.argv.slice(2)\n if (!cmd || cmd === 'help' || cmd === '--help' || cmd === '-h') {\n await printHelp()\n return cmd ? EXIT_OK : EXIT_USAGE\n }\n if (cmd === '--version') return cmdVersions(['--json'])\n if (!ENGINE_VERBS.has(cmd) && cmd !== 'voila') return delegate([cmd, ...rest])\n // An engine verb asked for its flags: the engine's usage lines, plus the\n // take pipeline's where the verb is shared (render takes a config OR a take).\n if (rest.includes('--help') || rest.includes('-h')) {\n const engine = HELP_ENGINE.split('\\n').filter((l) =>\n l.startsWith(` vos ${cmd} `),\n )\n const { verbHelp } = await import('./plugin/run')\n const take = verbHelp(cmd)\n process.stdout.write(\n `${engine.join('\\n')}\\n${take.includes('no such verb') ? '' : take}`,\n )\n return EXIT_OK\n }\n switch (cmd) {\n case 'render':\n return cmdRender(rest)\n case 'still':\n return cmdStill(rest)\n case 'info':\n return cmdInfo(rest)\n case 'versions':\n return cmdVersions(rest)\n case 'preview':\n return cmdPreview(rest)\n case 'check':\n return cmdCheck(rest)\n // Hidden alias for existing scripts; not in HELP. Same code path as the\n // promoted verbs, plus a one-line pointer at the new spelling.\n case 'voila':\n return delegate(rest, true)\n default:\n throw new UsageError(`unknown command \"${cmd}\" — run vos help`)\n }\n}\n\nmain()\n .then(async (code) => {\n // A run that succeeded while ignoring a flag it was given did not do\n // what was asked (flagUse.ts): say so, and do not exit 0.\n if (code === EXIT_OK) {\n const verb = process.argv[2] ?? ''\n const { HELP } = await import('./plugin/run')\n const documented = [\n ...helpFlagsFor(HELP_ENGINE, verb),\n ...helpFlagsFor(HELP, verb),\n ]\n const message = unusedFlagsMessage(verb, [...new Set(documented)])\n if (message) {\n process.stderr.write(`usage error: ${message}\\n`)\n process.exit(EXIT_USAGE)\n }\n }\n process.exit(code)\n })\n .catch((e) => {\n if (e instanceof UsageError) {\n process.stderr.write(`usage error: ${e.message}\\n`)\n process.exit(EXIT_USAGE)\n }\n if (e instanceof BrowserUnavailableError) {\n process.stderr.write(`${e.message}\\n`)\n process.exit(EXIT_NO_BROWSER)\n }\n process.stderr.write(\n `error: ${e instanceof Error ? e.message : String(e)}\\n`,\n )\n process.exit(EXIT_ERROR)\n })\n","/**\n * Output conventions (agent-safe by construction):\n * - logs/progress → stderr (human readable)\n * - results → stdout; with --json, NDJSON events (`{\"event\":\"phase\"...}` then\n * `{\"event\":\"done\"...}`) so scripts and agents never parse prose\n * - exit codes: 0 ok · 1 failure · 2 usage · 3 browser unavailable ·\n * 4 the recorder met a sign-in (the take pipeline's wall check)\n */\nexport const EXIT_OK = 0\nexport const EXIT_ERROR = 1\nexport const EXIT_USAGE = 2\nexport const EXIT_NO_BROWSER = 3\n\nexport interface Reporter {\n json: boolean\n /** Human log line (stderr; suppressed in --json mode). */\n log: (msg: string) => void\n /** Machine event (stdout NDJSON in --json mode; no-op otherwise). */\n event: (obj: Record<string, unknown>) => void\n /** Final result: NDJSON `done` event in --json mode, plain line otherwise. */\n done: (obj: Record<string, unknown>, humanLine: string) => void\n}\n\nexport function createReporter(json: boolean): Reporter {\n return {\n json,\n log: (msg) => {\n if (!json) process.stderr.write(`${msg}\\n`)\n },\n event: (obj) => {\n if (json) process.stdout.write(`${JSON.stringify(obj)}\\n`)\n },\n done: (obj, humanLine) => {\n if (json)\n process.stdout.write(`${JSON.stringify({ event: 'done', ...obj })}\\n`)\n else process.stdout.write(`${humanLine}\\n`)\n },\n }\n}\n","/**\n * `vos check` — the local validation pipeline, pure so it can be unit-tested:\n * envelope unwrap → migrate → schema → compile → determinism + dialect lints.\n * Everything runs locally (no network, no browser). The platform runs the\n * same compiler server-side, so a clean check is a push that will compile.\n */\nimport {\n CURRENT_CONFIG_VERSION,\n compileVosConfig,\n migrateConfig,\n vosConfigJsonSchema,\n} from '@vosjs/core'\nimport {\n lintVosConfig,\n lintVosDialect,\n lintVosFonts,\n lintVosPostprocessing,\n} from '@vosjs/core/lint'\nimport { knobWarnings } from './plugin/knobs'\n\nexport interface CheckIssue {\n level: 'error' | 'warn'\n source:\n | 'schema'\n | 'syntax'\n | 'compile'\n | 'determinism'\n | 'dialect'\n | 'shape'\n | 'fonts'\n | 'postprocessing'\n message: string\n}\n\nexport interface CheckResult {\n ok: boolean\n errors: number\n warnings: number\n issues: CheckIssue[]\n /** The migrated config (params/presets untouched) — what a push should send. */\n config: Record<string, unknown> | null\n}\n\n// Top-level keys the schema does not know but the platform preserves on push.\nconst PLATFORM_EXTRA_KEYS = new Set(['params', 'presets'])\n\nexport function runCheck(parsed: unknown): CheckResult {\n const issues: CheckIssue[] = []\n const finish = (config: Record<string, unknown> | null): CheckResult => {\n const errors = issues.filter((i) => i.level === 'error').length\n return {\n ok: errors === 0,\n errors,\n warnings: issues.length - errors,\n issues,\n config,\n }\n }\n\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n issues.push({\n level: 'error',\n source: 'shape',\n message: 'not a JSON object',\n })\n return finish(null)\n }\n\n // API endpoints wrap the config: { config: {...} } — accept both shapes.\n let obj = parsed as Record<string, unknown>\n if (\n typeof obj.config === 'object' &&\n obj.config !== null &&\n !('createTimeline' in obj)\n ) {\n obj = obj.config as Record<string, unknown>\n }\n\n const version = obj.version\n let migrated: Record<string, unknown>\n try {\n migrated = migrateConfig(obj) as Record<string, unknown>\n } catch (e) {\n issues.push({\n level: 'error',\n source: 'shape',\n message: `migration failed: ${e instanceof Error ? e.message : String(e)}`,\n })\n return finish(null)\n }\n if (version === undefined) {\n // It compiles (the engine reads an absent version as the current one),\n // but a push is refused: a stored config must say which schema era it was\n // written against, and nobody can tell that from the file later.\n issues.push({\n level: 'warn',\n source: 'shape',\n message: `config declares no \"version\". It plays here, but a push is refused without one. Add \"version\": ${CURRENT_CONFIG_VERSION}.`,\n })\n } else if (version !== CURRENT_CONFIG_VERSION) {\n issues.push({\n level: 'warn',\n source: 'shape',\n message: `config is v${String(version)}, migrated to v${CURRENT_CONFIG_VERSION}. Save the migrated form.`,\n })\n }\n\n const schema = vosConfigJsonSchema.safeParse(migrated)\n if (!schema.success) {\n for (const i of schema.error.issues.slice(0, 10)) {\n issues.push({\n level: 'error',\n source: 'schema',\n message: `${i.path.join('.') || '(root)'}: ${i.message}`,\n })\n }\n return finish(null)\n }\n\n // Keys the platform's schema will silently drop on push (params/presets\n // excepted — those are re-attached by contract).\n const known = new Set([\n ...Object.keys(vosConfigJsonSchema.shape),\n ...PLATFORM_EXTRA_KEYS,\n ])\n for (const key of Object.keys(migrated)) {\n if (!known.has(key)) {\n issues.push({\n level: 'warn',\n source: 'shape',\n message: `unknown top-level key \"${key}\" — the platform drops it on push`,\n })\n }\n }\n\n // Knobs and Looks vos.so would drop (the push still saves, without them).\n for (const message of knobWarnings(migrated as Record<string, unknown>)) {\n issues.push({ level: 'warn', source: 'shape', message })\n }\n\n // Sound as an ELEMENT is not a track: no timeline row, no gain or fades,\n // nothing a render mixes, and a `data:` source inflates the config past\n // what a claimable push can carry. The document is where sound goes.\n const elements = Array.isArray(migrated.elements) ? migrated.elements : []\n for (const el of elements) {\n if (!el || typeof el !== 'object') continue\n const e = el as { type?: unknown; id?: unknown; src?: unknown }\n if (e.type !== 'audio') continue\n const inline =\n typeof e.src === 'string' && e.src.startsWith('data:')\n ? ` (embedded, ${Math.round(e.src.length / 1024)} KB of config)`\n : ''\n issues.push({\n level: 'warn',\n source: 'shape',\n message: `audio element \"${String(e.id ?? '?')}\"${inline} is not a track: renders do not mix it and the studio cannot edit it. Put the file beside the config and name it in doc.json (audio: [{ key: \"score.ogg\", start, in, out, duration, gain }]); vos push uploads it`,\n })\n }\n\n // Function strings are pasted into the template as text, so the compiler\n // cannot see a syntax error — parse each one here (construction only,\n // nothing executes).\n let syntaxErrors = 0\n for (const key of [\n 'setup',\n 'createContent',\n 'createTimeline',\n 'onFrame',\n ] as const) {\n const src = migrated[key]\n if (typeof src !== 'string' || !src.length) continue\n try {\n new Function(`\"use strict\"; return (${src}\\n)`)\n } catch (e) {\n syntaxErrors++\n issues.push({\n level: 'error',\n source: 'syntax',\n message: `${key}: ${e instanceof Error ? e.message : String(e)}`,\n })\n }\n }\n if (syntaxErrors) return finish(migrated)\n\n try {\n // Same options as `vos render` — a clean check is a config the CLI's own\n // render path will accept.\n compileVosConfig(migrated as never, { tweenEngine: 'vos' })\n } catch (e) {\n issues.push({\n level: 'error',\n source: 'compile',\n message: e instanceof Error ? e.message : String(e),\n })\n return finish(migrated)\n }\n\n for (const i of lintVosConfig(migrated as never)) {\n issues.push({\n level: i.severity === 'error' ? 'error' : 'warn',\n source: 'determinism',\n message: `${i.fn}:${i.line} [${i.rule}] ${i.message}`,\n })\n }\n for (const i of lintVosDialect(migrated as never)) {\n issues.push({\n level: i.severity === 'error' ? 'error' : 'warn',\n source: 'dialect',\n message: `${i.fn}:${i.line} [${i.rule}] ${i.message}`,\n })\n }\n for (const i of lintVosFonts(migrated as never)) {\n issues.push({\n level: 'warn',\n source: 'fonts',\n message: `[${i.rule}] ${i.message}`,\n })\n }\n for (const i of lintVosPostprocessing(migrated as never)) {\n issues.push({\n level: 'warn',\n source: 'postprocessing',\n message: `[${i.rule}] ${i.message}`,\n })\n }\n\n return finish(migrated)\n}\n","/**\n * What vos.so keeps of a config's knobs (`params`) and Looks (`presets`).\n *\n * A vos.so fact, so it lives in the platform client: the platform keeps at\n * most 12 knobs and 8 Looks, each within its field limits, and drops the\n * rest ONE BY ONE with a warning (it used to drop them all, silently). This\n * mirrors that rule so `vos check` says the same thing before a push does.\n */\nexport const MAX_PARAMS = 12\nexport const MAX_LOOKS = 8\n\nconst KINDS = new Set(['number', 'color', 'select', 'toggle', 'text', 'font'])\n\nconst str = (v: unknown, max: number, min = 0) =>\n typeof v === 'string' && v.length >= min && v.length <= max\n\n/** Why one knob would be dropped, or null when vos.so keeps it. */\nexport function knobProblem(p: unknown): string | null {\n if (!p || typeof p !== 'object') return 'not an object'\n const k = p as Record<string, unknown>\n if (!str(k.key, 40, 1)) return 'key must be 1 to 40 characters'\n if (typeof k.kind !== 'string' || !KINDS.has(k.kind))\n return `kind must be one of ${[...KINDS].join(', ')}`\n if (k.label !== undefined && !str(k.label, 60))\n return 'label: at most 60 characters'\n if (k.hint !== undefined && !str(k.hint, 140))\n return 'hint: at most 140 characters'\n if (k.unit !== undefined && !str(k.unit, 8))\n return 'unit: at most 8 characters'\n if (k.group !== undefined && !str(k.group, 24))\n return 'group: at most 24 characters'\n if (k.options !== undefined) {\n if (!Array.isArray(k.options) || k.options.length > 12)\n return 'options: at most 12'\n if (k.options.some((o) => !str(o, 40, 1)))\n return 'options: each 1 to 40 characters'\n }\n const d = k.default\n if (\n !(\n typeof d === 'number' ||\n typeof d === 'boolean' ||\n (typeof d === 'string' && d.length <= 280)\n )\n )\n return 'default must be a number, a boolean or at most 280 characters'\n return null\n}\n\n/** Why one Look would be dropped, or null when vos.so keeps it. */\nexport function lookProblem(l: unknown): string | null {\n if (!l || typeof l !== 'object') return 'not an object'\n const look = l as Record<string, unknown>\n if (!str(look.name, 24, 1)) return 'name must be 1 to 24 characters'\n if (!look.values || typeof look.values !== 'object') return 'values missing'\n return null\n}\n\n/** Every knob and Look vos.so would drop, in words, in order. */\nexport function knobWarnings(config: Record<string, unknown>): string[] {\n const out: string[] = []\n const sort = (\n raw: unknown,\n noun: 'knob' | 'look',\n field: string,\n max: number,\n problem: (e: unknown) => string | null,\n ) => {\n if (raw === undefined) return\n if (!Array.isArray(raw)) {\n out.push(`${noun === 'knob' ? 'params' : 'presets'} is not a list`)\n return\n }\n let kept = 0\n raw.forEach((entry, i) => {\n const id =\n entry && typeof (entry as Record<string, unknown>)[field] === 'string'\n ? `${noun} \"${String((entry as Record<string, unknown>)[field])}\"`\n : `${noun} #${i + 1}`\n const why = problem(entry)\n if (why) out.push(`${id} would be dropped on vos.so (${why})`)\n else if (kept >= max)\n out.push(\n `${id} would be dropped on vos.so: a vos keeps at most ${max} ${noun}s${noun === 'knob' ? ' (the rest can stay bound data)' : ''}`,\n )\n else kept += 1\n })\n }\n sort(config.params, 'knob', 'key', MAX_PARAMS, knobProblem)\n sort(config.presets, 'look', 'name', MAX_LOOKS, lookProblem)\n return out\n}\n","/**\n * The sound a program document adds, for a LOCAL render of the program.\n *\n * A composed program carries its `doc.audio` clips on the studio stack entry,\n * exactly as a take does, and the capture page mixes them through the same\n * producer a take render uses. The one difference is WHERE the bytes are: a\n * capture page has no origin of its own, so a clip keyed by a file beside the\n * document (`score.ogg`) or by a hosted asset path (`/api/assets/…`) cannot be\n * fetched from inside it. Each is inlined as a `data:` URI here: a local file\n * read from disk, a hosted asset downloaded with the caller's credential.\n * A clip that cannot be reached is left out and said, never a silent track.\n */\nimport { existsSync } from 'node:fs'\nimport { readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { audioProducerCode, studioEntryData } from '@vosjs/render-core'\nimport { studioAudioPlan } from '@vosjs/studio-core'\nimport { MEDIA_HEAD_BYTES, resolveMediaType } from './plugin/container'\nimport type { EnvelopePoint, LoweredAudioClip } from '@vosjs/studio-core'\n\nexport interface ProgramAudioOptions {\n /** The directory the document's relative keys are read against. */\n baseDir: string\n /** The output length the mix is cut to, seconds. */\n duration: number\n /** For a clip keyed by a hosted asset: where it lives and who may read it. */\n origin?: string\n key?: string | null\n log: (line: string) => void\n}\n\nexport interface ProgramAudio {\n producerCode: string\n clips: number\n}\n\nfunction dataUri(bytes: Uint8Array, filename: string): string {\n const { type } = resolveMediaType({\n head: bytes.subarray(0, MEDIA_HEAD_BYTES),\n filename,\n })\n return `data:${type};base64,${Buffer.from(bytes).toString('base64')}`\n}\n\nasync function reach(\n clipKey: string,\n opts: ProgramAudioOptions,\n): Promise<string | null> {\n if (/^(data:|https?:)/.test(clipKey)) return clipKey\n if (clipKey.startsWith('/api/')) {\n if (!opts.origin || !opts.key) {\n opts.log(\n `note: sound ${clipKey} is a hosted asset and no credential is set, so the render leaves it out (vos login, or keep the file beside the document)`,\n )\n return null\n }\n const res = await fetch(`${opts.origin}${clipKey}`, {\n headers: { authorization: `Bearer ${opts.key}` },\n })\n if (!res.ok) {\n opts.log(\n `note: sound ${clipKey} could not be read (${res.status}), so the render leaves it out`,\n )\n return null\n }\n return dataUri(new Uint8Array(await res.arrayBuffer()), clipKey)\n }\n const file = join(opts.baseDir, clipKey.replace(/^\\/+/, ''))\n if (!existsSync(file)) {\n opts.log(\n `note: sound ${clipKey} is not beside the document, so the render leaves it out`,\n )\n return null\n }\n return dataUri(new Uint8Array(await readFile(file)), file)\n}\n\n/** The producer for a composed program's sound, or null when it adds none. */\nexport async function programAudio(\n config: Record<string, unknown>,\n opts: ProgramAudioOptions,\n): Promise<ProgramAudio | null> {\n const entry = studioEntryData(config.stack)\n const clips = Array.isArray(entry?.audio)\n ? (entry.audio as LoweredAudioClip[])\n : []\n if (!clips.length) return null\n const reached: LoweredAudioClip[] = []\n for (const clip of clips) {\n const key = await reach(clip.key, opts)\n if (key) reached.push({ ...clip, key })\n }\n if (!reached.length) return null\n const duckEnv = Array.isArray(entry?.duckEnv)\n ? (entry.duckEnv as EnvelopePoint[])\n : []\n const plan = studioAudioPlan(reached, duckEnv, opts.duration)\n return {\n producerCode: audioProducerCode({ plan }),\n clips: reached.length,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,iBAAiB;AAC1B,SAAS,cAAAA,aAAY,cAAc,gBAAgB;AACnD,SAAS,UAAU,SAAS,QAAAC,aAAY;AACxC,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;;;ACGvB,IAAM,UAAU;AAChB,IAAM,aAAa;AACnB,IAAM,aAAa;AACnB,IAAM,kBAAkB;AAYxB,SAAS,eAAe,MAAyB;AACtD,SAAO;AAAA,IACL;AAAA,IACA,KAAK,CAAC,QAAQ;AACZ,UAAI,CAAC,KAAM,SAAQ,OAAO,MAAM,GAAG,GAAG;AAAA,CAAI;AAAA,IAC5C;AAAA,IACA,OAAO,CAAC,QAAQ;AACd,UAAI,KAAM,SAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,GAAG,CAAC;AAAA,CAAI;AAAA,IAC3D;AAAA,IACA,MAAM,CAAC,KAAK,cAAc;AACxB,UAAI;AACF,gBAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,IAAI,CAAC,CAAC;AAAA,CAAI;AAAA,UAClE,SAAQ,OAAO,MAAM,GAAG,SAAS;AAAA,CAAI;AAAA,IAC5C;AAAA,EACF;AACF;;;AChCA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACTA,IAAM,aAAa;AACnB,IAAM,YAAY;AAEzB,IAAM,QAAQ,oBAAI,IAAI,CAAC,UAAU,SAAS,UAAU,UAAU,QAAQ,MAAM,CAAC;AAE7E,IAAM,MAAM,CAAC,GAAY,KAAa,MAAM,MAC1C,OAAO,MAAM,YAAY,EAAE,UAAU,OAAO,EAAE,UAAU;AAGnD,SAAS,YAAY,GAA2B;AACrD,MAAI,CAAC,KAAK,OAAO,MAAM,SAAU,QAAO;AACxC,QAAM,IAAI;AACV,MAAI,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,EAAG,QAAO;AAC/B,MAAI,OAAO,EAAE,SAAS,YAAY,CAAC,MAAM,IAAI,EAAE,IAAI;AACjD,WAAO,uBAAuB,CAAC,GAAG,KAAK,EAAE,KAAK,IAAI,CAAC;AACrD,MAAI,EAAE,UAAU,UAAa,CAAC,IAAI,EAAE,OAAO,EAAE;AAC3C,WAAO;AACT,MAAI,EAAE,SAAS,UAAa,CAAC,IAAI,EAAE,MAAM,GAAG;AAC1C,WAAO;AACT,MAAI,EAAE,SAAS,UAAa,CAAC,IAAI,EAAE,MAAM,CAAC;AACxC,WAAO;AACT,MAAI,EAAE,UAAU,UAAa,CAAC,IAAI,EAAE,OAAO,EAAE;AAC3C,WAAO;AACT,MAAI,EAAE,YAAY,QAAW;AAC3B,QAAI,CAAC,MAAM,QAAQ,EAAE,OAAO,KAAK,EAAE,QAAQ,SAAS;AAClD,aAAO;AACT,QAAI,EAAE,QAAQ,KAAK,CAAC,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;AACtC,aAAO;AAAA,EACX;AACA,QAAM,IAAI,EAAE;AACZ,MACE,EACE,OAAO,MAAM,YACb,OAAO,MAAM,aACZ,OAAO,MAAM,YAAY,EAAE,UAAU;AAGxC,WAAO;AACT,SAAO;AACT;AAGO,SAAS,YAAY,GAA2B;AACrD,MAAI,CAAC,KAAK,OAAO,MAAM,SAAU,QAAO;AACxC,QAAM,OAAO;AACb,MAAI,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,EAAG,QAAO;AACnC,MAAI,CAAC,KAAK,UAAU,OAAO,KAAK,WAAW,SAAU,QAAO;AAC5D,SAAO;AACT;AAGO,SAAS,aAAa,QAA2C;AACtE,QAAM,MAAgB,CAAC;AACvB,QAAM,OAAO,CACX,KACA,MACA,OACA,KACA,YACG;AACH,QAAI,QAAQ,OAAW;AACvB,QAAI,CAAC,MAAM,QAAQ,GAAG,GAAG;AACvB,UAAI,KAAK,GAAG,SAAS,SAAS,WAAW,SAAS,gBAAgB;AAClE;AAAA,IACF;AACA,QAAI,OAAO;AACX,QAAI,QAAQ,CAAC,OAAO,MAAM;AACxB,YAAM,KACJ,SAAS,OAAQ,MAAkC,KAAK,MAAM,WAC1D,GAAG,IAAI,KAAK,OAAQ,MAAkC,KAAK,CAAC,CAAC,MAC7D,GAAG,IAAI,KAAK,IAAI,CAAC;AACvB,YAAM,MAAM,QAAQ,KAAK;AACzB,UAAI,IAAK,KAAI,KAAK,GAAG,EAAE,gCAAgC,GAAG,GAAG;AAAA,eACpD,QAAQ;AACf,YAAI;AAAA,UACF,GAAG,EAAE,oDAAoD,GAAG,IAAI,IAAI,IAAI,SAAS,SAAS,oCAAoC,EAAE;AAAA,QAClI;AAAA,UACG,SAAQ;AAAA,IACf,CAAC;AAAA,EACH;AACA,OAAK,OAAO,QAAQ,QAAQ,OAAO,YAAY,WAAW;AAC1D,OAAK,OAAO,SAAS,QAAQ,QAAQ,WAAW,WAAW;AAC3D,SAAO;AACT;;;AD/CA,IAAM,sBAAsB,oBAAI,IAAI,CAAC,UAAU,SAAS,CAAC;AAElD,SAAS,SAAS,QAA8B;AACrD,QAAM,SAAuB,CAAC;AAC9B,QAAM,SAAS,CAAC,WAAwD;AACtE,UAAM,SAAS,OAAO,OAAO,CAAC,MAAM,EAAE,UAAU,OAAO,EAAE;AACzD,WAAO;AAAA,MACL,IAAI,WAAW;AAAA,MACf;AAAA,MACA,UAAU,OAAO,SAAS;AAAA,MAC1B;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,OAAO,WAAW,YAAY,WAAW,QAAQ,MAAM,QAAQ,MAAM,GAAG;AAC1E,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAS;AAAA,IACX,CAAC;AACD,WAAO,OAAO,IAAI;AAAA,EACpB;AAGA,MAAI,MAAM;AACV,MACE,OAAO,IAAI,WAAW,YACtB,IAAI,WAAW,QACf,EAAE,oBAAoB,MACtB;AACA,UAAM,IAAI;AAAA,EACZ;AAEA,QAAM,UAAU,IAAI;AACpB,MAAI;AACJ,MAAI;AACF,eAAW,cAAc,GAAG;AAAA,EAC9B,SAAS,GAAG;AACV,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAS,qBAAqB,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,IAC1E,CAAC;AACD,WAAO,OAAO,IAAI;AAAA,EACpB;AACA,MAAI,YAAY,QAAW;AAIzB,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAS,kGAAkG,sBAAsB;AAAA,IACnI,CAAC;AAAA,EACH,WAAW,YAAY,wBAAwB;AAC7C,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAS,cAAc,OAAO,OAAO,CAAC,kBAAkB,sBAAsB;AAAA,IAChF,CAAC;AAAA,EACH;AAEA,QAAM,SAAS,oBAAoB,UAAU,QAAQ;AACrD,MAAI,CAAC,OAAO,SAAS;AACnB,eAAW,KAAK,OAAO,MAAM,OAAO,MAAM,GAAG,EAAE,GAAG;AAChD,aAAO,KAAK;AAAA,QACV,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,SAAS,GAAG,EAAE,KAAK,KAAK,GAAG,KAAK,QAAQ,KAAK,EAAE,OAAO;AAAA,MACxD,CAAC;AAAA,IACH;AACA,WAAO,OAAO,IAAI;AAAA,EACpB;AAIA,QAAM,QAAQ,oBAAI,IAAI;AAAA,IACpB,GAAG,OAAO,KAAK,oBAAoB,KAAK;AAAA,IACxC,GAAG;AAAA,EACL,CAAC;AACD,aAAW,OAAO,OAAO,KAAK,QAAQ,GAAG;AACvC,QAAI,CAAC,MAAM,IAAI,GAAG,GAAG;AACnB,aAAO,KAAK;AAAA,QACV,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,SAAS,0BAA0B,GAAG;AAAA,MACxC,CAAC;AAAA,IACH;AAAA,EACF;AAGA,aAAW,WAAW,aAAa,QAAmC,GAAG;AACvE,WAAO,KAAK,EAAE,OAAO,QAAQ,QAAQ,SAAS,QAAQ,CAAC;AAAA,EACzD;AAKA,QAAM,WAAW,MAAM,QAAQ,SAAS,QAAQ,IAAI,SAAS,WAAW,CAAC;AACzE,aAAW,MAAM,UAAU;AACzB,QAAI,CAAC,MAAM,OAAO,OAAO,SAAU;AACnC,UAAM,IAAI;AACV,QAAI,EAAE,SAAS,QAAS;AACxB,UAAM,SACJ,OAAO,EAAE,QAAQ,YAAY,EAAE,IAAI,WAAW,OAAO,IACjD,eAAe,KAAK,MAAM,EAAE,IAAI,SAAS,IAAI,CAAC,mBAC9C;AACN,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAS,kBAAkB,OAAO,EAAE,MAAM,GAAG,CAAC,IAAI,MAAM;AAAA,IAC1D,CAAC;AAAA,EACH;AAKA,MAAI,eAAe;AACnB,aAAW,OAAO;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAY;AACV,UAAM,MAAM,SAAS,GAAG;AACxB,QAAI,OAAO,QAAQ,YAAY,CAAC,IAAI,OAAQ;AAC5C,QAAI;AACF,UAAI,SAAS,yBAAyB,GAAG;AAAA,EAAK;AAAA,IAChD,SAAS,GAAG;AACV;AACA,aAAO,KAAK;AAAA,QACV,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,SAAS,GAAG,GAAG,KAAK,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,MAChE,CAAC;AAAA,IACH;AAAA,EACF;AACA,MAAI,aAAc,QAAO,OAAO,QAAQ;AAExC,MAAI;AAGF,qBAAiB,UAAmB,EAAE,aAAa,MAAM,CAAC;AAAA,EAC5D,SAAS,GAAG;AACV,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAS,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AAAA,IACpD,CAAC;AACD,WAAO,OAAO,QAAQ;AAAA,EACxB;AAEA,aAAW,KAAK,cAAc,QAAiB,GAAG;AAChD,WAAO,KAAK;AAAA,MACV,OAAO,EAAE,aAAa,UAAU,UAAU;AAAA,MAC1C,QAAQ;AAAA,MACR,SAAS,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,KAAK,EAAE,IAAI,KAAK,EAAE,OAAO;AAAA,IACrD,CAAC;AAAA,EACH;AACA,aAAW,KAAK,eAAe,QAAiB,GAAG;AACjD,WAAO,KAAK;AAAA,MACV,OAAO,EAAE,aAAa,UAAU,UAAU;AAAA,MAC1C,QAAQ;AAAA,MACR,SAAS,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,KAAK,EAAE,IAAI,KAAK,EAAE,OAAO;AAAA,IACrD,CAAC;AAAA,EACH;AACA,aAAW,KAAK,aAAa,QAAiB,GAAG;AAC/C,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAS,IAAI,EAAE,IAAI,KAAK,EAAE,OAAO;AAAA,IACnC,CAAC;AAAA,EACH;AACA,aAAW,KAAK,sBAAsB,QAAiB,GAAG;AACxD,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAS,IAAI,EAAE,IAAI,KAAK,EAAE,OAAO;AAAA,IACnC,CAAC;AAAA,EACH;AAEA,SAAO,OAAO,QAAQ;AACxB;;;AEvNA,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB;AACzB,SAAS,YAAY;AACrB,SAAS,mBAAmB,uBAAuB;AACnD,SAAS,uBAAuB;AAoBhC,SAAS,QAAQ,OAAmB,UAA0B;AAC5D,QAAM,EAAE,KAAK,IAAI,iBAAiB;AAAA,IAChC,MAAM,MAAM,SAAS,GAAG,gBAAgB;AAAA,IACxC;AAAA,EACF,CAAC;AACD,SAAO,QAAQ,IAAI,WAAW,OAAO,KAAK,KAAK,EAAE,SAAS,QAAQ,CAAC;AACrE;AAEA,eAAe,MACb,SACA,MACwB;AACxB,MAAI,mBAAmB,KAAK,OAAO,EAAG,QAAO;AAC7C,MAAI,QAAQ,WAAW,OAAO,GAAG;AAC/B,QAAI,CAAC,KAAK,UAAU,CAAC,KAAK,KAAK;AAC7B,WAAK;AAAA,QACH,eAAe,OAAO;AAAA,MACxB;AACA,aAAO;AAAA,IACT;AACA,UAAM,MAAM,MAAM,MAAM,GAAG,KAAK,MAAM,GAAG,OAAO,IAAI;AAAA,MAClD,SAAS,EAAE,eAAe,UAAU,KAAK,GAAG,GAAG;AAAA,IACjD,CAAC;AACD,QAAI,CAAC,IAAI,IAAI;AACX,WAAK;AAAA,QACH,eAAe,OAAO,uBAAuB,IAAI,MAAM;AAAA,MACzD;AACA,aAAO;AAAA,IACT;AACA,WAAO,QAAQ,IAAI,WAAW,MAAM,IAAI,YAAY,CAAC,GAAG,OAAO;AAAA,EACjE;AACA,QAAM,OAAO,KAAK,KAAK,SAAS,QAAQ,QAAQ,QAAQ,EAAE,CAAC;AAC3D,MAAI,CAAC,WAAW,IAAI,GAAG;AACrB,SAAK;AAAA,MACH,eAAe,OAAO;AAAA,IACxB;AACA,WAAO;AAAA,EACT;AACA,SAAO,QAAQ,IAAI,WAAW,MAAM,SAAS,IAAI,CAAC,GAAG,IAAI;AAC3D;AAGA,eAAsB,aACpB,QACA,MAC8B;AAC9B,QAAM,QAAQ,gBAAgB,OAAO,KAAK;AAC1C,QAAM,QAAQ,MAAM,QAAQ,OAAO,KAAK,IACnC,MAAM,QACP,CAAC;AACL,MAAI,CAAC,MAAM,OAAQ,QAAO;AAC1B,QAAM,UAA8B,CAAC;AACrC,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,MAAM,MAAM,KAAK,KAAK,IAAI;AACtC,QAAI,IAAK,SAAQ,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC;AAAA,EACxC;AACA,MAAI,CAAC,QAAQ,OAAQ,QAAO;AAC5B,QAAM,UAAU,MAAM,QAAQ,OAAO,OAAO,IACvC,MAAM,UACP,CAAC;AACL,QAAM,OAAO,gBAAgB,SAAS,SAAS,KAAK,QAAQ;AAC5D,SAAO;AAAA,IACL,cAAc,kBAAkB,EAAE,KAAK,CAAC;AAAA,IACxC,OAAO,QAAQ;AAAA,EACjB;AACF;;;AJ1DA,IAAM,gBAAgB,oBAAI,IAAI,CAAC,QAAQ,QAAQ,SAAS,CAAC;AAEzD,IAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAepB,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUzB,SAAS,iBAAiB,QAA0B;AAClD,QAAM,WAAY,OAAkC;AACpD,SACE,MAAM,QAAQ,QAAQ,KACtB,SAAS;AAAA,IACP,CAAC,MACC,CAAC,CAAC,KACF,OAAO,MAAM,YACZ,EAAyB,SAAS;AAAA,EACvC;AAEJ;AAEA,SAAS,QAAQ,QAAgB,KAAqB;AACpD,QAAM,OAAO,SAAS,MAAM,EAAE,QAAQ,iBAAiB,EAAE,KAAK;AAC9D,SAAO,GAAG,IAAI,IAAI,GAAG;AACvB;AAEA,eAAe,UAAU,MAAiC;AAOxD,QAAM,QAAQ,KAAK,KAAK,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,CAAC;AACjD,MAAI,SAAS,cAAc,KAAK,MAAM,QAAQ;AAC5C,WAAO,SAAS,CAAC,UAAU,GAAG,IAAI,CAAC;AAAA,EACrC;AACA,QAAM,EAAE,aAAa,MAAM,IAAI,UAAU,MAAM,aAAa;AAC5D,QAAM,SAAS,YAAY,CAAC;AAC5B,MAAI,CAAC,OAAQ,OAAM,IAAI,WAAW,yCAAyC;AAC3E,QAAM,IAAI,eAAe,MAAM,SAAS,IAAI;AAC5C,QAAM,SAAS;AAAA,IACb,MAAM,WAAW,SAAY,SAAY,OAAO,MAAM,MAAM;AAAA,IAC5D,YAAY,CAAC;AAAA,EACf;AAEA,QAAM,SAAS,MAAM,cAAc,MAAM;AACzC,aAAW,KAAK,OAAO,SAAU,GAAE,IAAI,SAAS,CAAC,EAAE;AACnD,OAAK,MAAM;AACX,QAAM,SAAS;AAAA,IACb,OAAO;AAAA,IACP,SAAS,IAAI;AAAA,EACf;AACA,QAAM,WAAW,QAAQ,OAAO,YAAY,eAAe,MAAM,KAAK,CAAC;AACvE,QAAM,QAAQ,QAAQ,OAAO,SAAS,IAAI;AAC1C,QAAM,SAAS,QAAQ,OAAO,UAAU,IAAI;AAC5C,QAAM,MAAM,QAAQ,OAAO,OAAO,EAAE;AACpC,QAAM,MAAM,YAAY,CAAC,KAAK,QAAQ,QAAQ,MAAM;AAGpD,QAAM,QAAQ,MAAM,aAAa,QAAmC;AAAA,IAClE,SACEC,YAAW,MAAM,KAAK,SAAS,MAAM,EAAE,YAAY,IAC/C,SACA,QAAQ,MAAM;AAAA,IACpB;AAAA,IACA,QAAQ,eAAe,CAAC,CAAC;AAAA,IACzB,KAAK,kBAAkB;AAAA,IACvB,KAAK,CAAC,SAAS,EAAE,IAAI,IAAI;AAAA,EAC3B,CAAC;AACD,MAAI,MAAO,GAAE,IAAI,UAAU,MAAM,KAAK,SAAS,MAAM,UAAU,IAAI,KAAK,GAAG,EAAE;AAC7E,MAAI,iBAAiB,MAAM,GAAG;AAC5B,MAAE;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,cAAc;AACpC,MAAI;AACF,UAAM,SAAS,MAAM,YAAY,SAAS;AAAA,MACxC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,mBAAmB,OAAO;AAAA,MAC1B,SAAS,CAAC,UAAU;AAClB,UAAE,IAAI,GAAG,KAAK,QAAG;AACjB,UAAE,MAAM,EAAE,OAAO,SAAS,MAAM,CAAC;AAAA,MACnC;AAAA,IACF,CAAC;AACD,UAAM,UAAU,KAAK,OAAO,KAAK;AACjC,UAAM,WAAW;AAAA,MACf,EAAE,aAAa,OAAO,MAAM,MAAM;AAAA,MAClC,OAAO;AAAA,IACT;AACA,eAAW,KAAK,SAAU,GAAE,IAAI,SAAS,CAAC,EAAE;AAC5C,MAAE;AAAA,MACA;AAAA,QACE;AAAA,QACA,OAAO,OAAO,MAAM;AAAA,QACpB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO,OAAO,SAAS;AAAA,QACvB,GAAI,SAAS,SAAS,EAAE,SAAS,IAAI,CAAC;AAAA,MACxC;AAAA,MACA,SAAS,GAAG,MAAM,OAAO,MAAM,SAAS,MAAM,QAAQ,CAAC,CAAC,QAAQ,KAAK,IAAI,MAAM,IAAI,GAAG,KAAK,QAAQ;AAAA,IACrG;AACA,WAAO;AAAA,EACT,UAAE;AACA,UAAM,QAAQ,MAAM;AAAA,EACtB;AACF;AAEA,eAAe,SAAS,MAAiC;AACvD,QAAM,EAAE,aAAa,MAAM,IAAI,UAAU,MAAM,aAAa;AAC5D,QAAM,SAAS,YAAY,CAAC;AAC5B,MAAI,CAAC;AACH,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AACF,QAAM,IAAI,eAAe,MAAM,SAAS,IAAI;AAE5C,QAAM,SAAS,MAAM,cAAc,MAAM;AACzC,aAAW,KAAK,OAAO,SAAU,GAAE,IAAI,SAAS,CAAC,EAAE;AACnD,OAAK,MAAM;AACX,QAAM,SAAS;AAAA,IACb,OAAO;AAAA,IACP,SAAS,IAAI;AAAA,EACf;AACA,QAAM,QAAQ,QAAQ,OAAO,SAAS,IAAI;AAC1C,QAAM,SAAS,QAAQ,OAAO,UAAU,GAAG;AAC3C,QAAM,MAAM,YAAY,CAAC,KAAK,QAAQ,QAAQ,MAAM;AACpD,QAAM,WAAW,YAAY,GAAG;AAChC,QAAM,WAAW,MAAM,UAAU,SAAY,SAAY,OAAO,MAAM,KAAK;AAC3E,MAAI,aAAa,UAAa,MAAM,SAAS;AAC3C,UAAM,IAAI,WAAW,8BAA8B;AACrD,QAAM,QACJ,aAAa,SACT,WAAW,UAAU,eAAe,MAAM,KAAK,CAAC,IAChD,CAAC,QAAQ,OAAO,QAAQ,CAAC,CAAC;AAChC,QAAM,OAAO,MAAM,SAAS;AAG5B,QAAM,UAAU,MAAM,cAAc;AACpC,MAAI;AACF,UAAM,UAKA,CAAC;AACP,eAAW,QAAQ,OAAO;AACxB,YAAM,SAAS,YAAY,KAAK,MAAM,IAAI;AAC1C,YAAM,SAAS,MAAM,YAAY,SAAS;AAAA,QACxC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS,CAAC,UAAU;AAClB,YAAE,MAAM,EAAE,OAAO,SAAS,OAAO,KAAK,CAAC;AAAA,QACzC;AAAA,MACF,CAAC;AAGD,YAAM,QACJ,aAAa,SACT,OAAO,QACP,MAAM,cAAc,SAAS,OAAO,OAAO,QAAQ;AACzD,YAAM,UAAU,QAAQ,KAAK;AAG7B,YAAM,WAAW;AAAA,QACf,MAAM,aAAa,SAAS,OAAO,KAAK;AAAA,QACxC,OAAO;AAAA,MACT;AACA,cAAQ,KAAK;AAAA,QACX,KAAK;AAAA,QACL,OAAO,MAAM;AAAA,QACb;AAAA,QACA,GAAI,SAAS,SAAS,EAAE,SAAS,IAAI,CAAC;AAAA,MACxC,CAAC;AACD,QAAE;AAAA,QACA,SAAS,MAAM,MAAM,MAAM,SAAS,MAAM,QAAQ,CAAC,CAAC,WAAW,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC;AAAA,MACxF;AACA,iBAAW,KAAK;AACd,UAAE,IAAI,WAAW,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE;AAAA,IACpD;AACA,UAAM,QAAQ,QAAQ,CAAC;AACvB,MAAE;AAAA,MACA,OACI,EAAE,QAAQ,SAAS,OAAO,QAAQ,QAAQ,SAAS,IACnD,EAAE,GAAG,OAAO,OAAO,QAAQ,QAAQ,SAAS;AAAA,MAChD,OACI,SAAS,QAAQ,MAAM,YAAY,KAAK,IAAI,MAAM,MAClD,SAAS,MAAM,GAAG,MAAM,MAAM,QAAQ,MAAM,QAAQ,CAAC,CAAC,QAAQ,KAAK,IAAI,MAAM,QAAQ,MAAM,IAAI;AAAA,IACrG;AACA,WAAO;AAAA,EACT,UAAE;AACA,UAAM,QAAQ,MAAM;AAAA,EACtB;AACF;AAEA,eAAe,QAAQ,MAAiC;AACtD,QAAM,EAAE,aAAa,MAAM,IAAI,UAAU,MAAM,aAAa;AAC5D,QAAM,SAAS,YAAY,CAAC;AAC5B,MAAI,CAAC,OAAQ,OAAM,IAAI,WAAW,4BAA4B;AAC9D,QAAM,IAAI,eAAe,MAAM,SAAS,IAAI;AAE5C,QAAM,EAAE,QAAQ,SAAS,IAAI,MAAM,cAAc,MAAM;AACvD,QAAM,WAAW,MAAM,QAAQ,OAAO,QAAQ,IAAI,OAAO,SAAS,SAAS;AAC3E,QAAM,OACJ,OAAO,OAAO,SAAS,YAAY,OAAO,SAAS,OAC/C,OAAO,KAAK,OAAO,IAAI,IACvB,CAAC;AACP,QAAM,MAAM,CAAC,SAAS,iBAAiB,kBAAkB,SAAS,EAAE;AAAA,IAClE,CAAC,MAAM,OAAO,OAAO,CAAC,MAAM;AAAA,EAC9B;AACA,QAAM,OAAO;AAAA,IACX,SAAS,OAAO;AAAA,IAChB,UAAU,eAAe,MAAM,KAAK;AAAA,IACpC,QACG,OAAO,QAAgD,UAAU;AAAA,IACpE;AAAA,IACA,UAAU;AAAA,IACV,WAAW;AAAA,IACX;AAAA,EACF;AACA,MAAI,EAAE,KAAM,GAAE,KAAK,MAAM,EAAE;AAAA,OACtB;AACH,eAAW,KAAK,SAAU,GAAE,IAAI,SAAS,CAAC,EAAE;AAC5C,YAAQ,OAAO;AAAA,MACb,eAAe,OAAO,KAAK,OAAO,CAAC;AAAA,aACnB,KAAK,aAAa,OAAO,WAAW,GAAG,KAAK,QAAQ,GAAG;AAAA,aACvD,OAAO,KAAK,UAAU,WAAW,CAAC;AAAA,aAClC,QAAQ;AAAA,aACR,KAAK,SAAS,KAAK,KAAK,IAAI,IAAI,QAAQ;AAAA,aACxC,IAAI,KAAK,IAAI,CAAC;AAAA;AAAA,IAChC;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,eAAe,MAA6B;AACnD,QAAMC,WAAU,cAAc,YAAY,GAAG;AAE7C,MAAI;AACF,WAAQA,SAAQ,GAAG,IAAI,eAAe,EAA0B;AAAA,EAClE,QAAQ;AAAA,EAGR;AACA,MAAI,QAAuB;AAC3B,MAAI;AACF,YAAQ,cAAc,YAAY,QAAQ,IAAI,CAAC;AAAA,EACjD,QAAQ;AACN,QAAI;AACF,cAAQA,SAAQ,QAAQ,IAAI;AAAA,IAC9B,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACA,MAAI,MAAM,QAAQ,KAAK;AACvB,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,QAAI;AACF,YAAM,MAAM,KAAK;AAAA,QACf,aAAaC,MAAK,KAAK,cAAc,GAAG,MAAM;AAAA,MAChD;AAIA,UAAI,IAAI,SAAS,QAAQ,IAAI,QAAS,QAAO,IAAI;AAAA,IACnD,QAAQ;AAAA,IAER;AACA,UAAM,SAAS,QAAQ,GAAG;AAC1B,QAAI,WAAW,IAAK,QAAO;AAC3B,UAAM;AAAA,EACR;AACA,SAAO;AACT;AAEA,SAAS,aAAqB;AAC5B,MAAI;AACF,UAAM,MAAM,KAAK;AAAA,MACf;AAAA,QACE,cAAc,IAAI,IAAI,mBAAmB,YAAY,GAAG,CAAC;AAAA,QACzD;AAAA,MACF;AAAA,IACF;AACA,WAAO,IAAI;AAAA,EACb,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,YAAY,MAAiC;AAC1D,QAAM,EAAE,MAAM,IAAI,UAAU,MAAM,aAAa;AAC/C,QAAM,IAAI,eAAe,MAAM,SAAS,IAAI;AAC5C,QAAM,WAAmC,CAAC;AAC1C,WAAS,YAAY,IAAI,WAAW;AACpC,aAAW,QAAQ;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAG;AACD,aAAS,IAAI,IAAI,eAAe,IAAI,KAAK;AAAA,EAC3C;AACA,MAAI,EAAE,KAAM,GAAE,KAAK,EAAE,SAAS,GAAG,EAAE;AAAA;AAEjC,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,QAAQ;AAC1C,cAAQ,OAAO,MAAM,GAAG,CAAC,IAAI,CAAC;AAAA,CAAI;AACtC,SAAO;AACT;AAEA,eAAe,WAAW,MAAiC;AACzD,QAAM,EAAE,aAAa,MAAM,IAAI,UAAU,MAAM,aAAa;AAC5D,QAAM,SAAS,YAAY,CAAC;AAC5B,MAAI,CAAC,OAAQ,OAAM,IAAI,WAAW,0CAA0C;AAC5E,QAAM,IAAI,eAAe,KAAK;AAC9B,QAAM,EAAE,QAAQ,SAAS,IAAI,MAAM,cAAc,MAAM;AACvD,aAAW,KAAK,SAAU,GAAE,IAAI,SAAS,CAAC,EAAE;AAC5C,QAAM,EAAE,UAAU,WAAW,IAAI,aAAa,MAAM;AACpD,QAAM,SAAS,aAAa,CAAC,KAAK,QAAQ;AACxC,UAAM,OAAO,IAAI,IAAI,IAAI,OAAO,KAAK,UAAU,EAAE;AACjD,QAAI,UAAU,KAAK,EAAE,gBAAgB,YAAY,CAAC;AAClD,QAAI,IAAI,SAAS,YAAY,aAAa,QAAQ;AAAA,EACpD,CAAC;AACD,QAAM,OAAO,QAAQ,OAAO,QAAQ,CAAC;AACrC,QAAM,IAAI,QAAc,CAAC,YAAY,OAAO,OAAO,MAAM,OAAO,CAAC;AACjE,QAAM,OAAO,OAAO,QAAQ;AAC5B,QAAM,MAAM,oBAAoB,OAAO,SAAS,YAAY,OAAO,KAAK,OAAO,IAAI;AACnF,UAAQ,OAAO,MAAM,GAAG,GAAG;AAAA,CAAI;AAC/B,IAAE,IAAI,iDAA4C;AAClD,QAAM,IAAI,QAAQ,MAAM;AAAA,EAAC,CAAC;AAC1B,SAAO;AACT;AAEA,eAAe,SAAS,MAAiC;AACvD,QAAM,EAAE,aAAa,MAAM,IAAI,UAAU,MAAM,aAAa;AAC5D,QAAM,SAAS,YAAY,CAAC;AAC5B,MAAI,CAAC,OAAQ,OAAM,IAAI,WAAW,yBAAyB;AAC3D,QAAM,IAAI,eAAe,MAAM,SAAS,IAAI;AAK5C,QAAM,OAAO,eAAe,KAAK,MAAM,IAAI,SAAS,cAAc,MAAM;AACxE,MAAI,SAAS,QAAQ;AACnB,UAAM,IAAI;AAAA,MACR,GAAG,MAAM,mEAAmE,MAAM,yBAAyB,MAAM;AAAA,IACnH;AAAA,EACF;AACA,MAAI;AACJ,MAAI;AACJ,MAAI;AACF,QAAI,SAAS,WAAW;AACtB,YAAM,QAAkB,CAAC;AACzB,eAAS,MAAM,qBAAqB,QAAQ,KAAK;AACjD,iBAAW,KAAK,MAAO,GAAE,IAAI,SAAS,CAAC,EAAE;AACzC,YAAM;AAAA,IACR,OAAO;AACL,YAAM,MAAM,eAAe,MAAM;AACjC,eAAS,KAAK,MAAM,GAAG;AAAA,IACzB;AAAA,EACF,SAAS,GAAG;AACV,QAAI,EAAE,aAAa,aAAc,OAAM;AACvC,aAAS;AACT,QAAI,CAAC,EAAE,KAAM,SAAQ,OAAO,MAAM,gBAAiB,EAAY,OAAO;AAAA,CAAI;AAC1E,MAAE;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,QAAQ;AAAA,UACN,EAAE,OAAO,SAAS,QAAQ,QAAQ,SAAU,EAAY,QAAQ;AAAA,QAClE;AAAA,MACF;AAAA,MACA,GAAG,MAAM;AAAA,IACX;AACA,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,SAAS,MAAM;AAC9B,MAAI,EAAE,MAAM;AACV,MAAE;AAAA,MACA;AAAA,QACE,IAAI,OAAO;AAAA,QACX,QAAQ,OAAO;AAAA,QACf,UAAU,OAAO;AAAA,QACjB,QAAQ,OAAO;AAAA,MACjB;AAAA,MACA;AAAA,IACF;AAAA,EACF,OAAO;AACL,eAAW,KAAK,OAAO,QAAQ;AAC7B,cAAQ,OAAO,MAAM,GAAG,EAAE,KAAK,KAAK,EAAE,MAAM,KAAK,EAAE,OAAO;AAAA,CAAI;AAAA,IAChE;AACA,YAAQ,OAAO;AAAA,MACb,OAAO,KACH,GAAG,MAAM,SAAS,OAAO,QAAQ,WAAW,OAAO,aAAa,IAAI,KAAK,GAAG;AAAA,IAC5E,GAAG,MAAM,KAAK,OAAO,MAAM,SAAS,OAAO,WAAW,IAAI,KAAK,GAAG,KAAK,OAAO,QAAQ,WAAW,OAAO,aAAa,IAAI,KAAK,GAAG;AAAA;AAAA,IACvI;AAAA,EACF;AACA,SAAO,OAAO,KAAK,UAAU;AAC/B;AAUA,eAAe,SAAS,MAAgB,WAAW,OAAwB;AACzE,QAAM,EAAE,IAAI,IAAI,MAAM,OAAO,mBAAc;AAC3C,MAAI,YAAY,KAAK,CAAC,GAAG;AACvB,YAAQ,OAAO;AAAA,MACb,oBAAoB,KAAK,CAAC,CAAC,iBAAiB,KAAK,CAAC,CAAC;AAAA;AAAA,IACrD;AAAA,EACF;AACA,SAAO,MAAM,IAAI,IAAI;AACvB;AAEA,eAAe,YAA2B;AACxC,UAAQ,OAAO,MAAM,WAAW;AAChC,QAAM,EAAE,SAAS,IAAI,MAAM,OAAO,wBAAmB;AACrD,UAAQ,OAAO,MAAM,kCAAkC;AACvD,aAAW,KAAK,SAAS,OAAO;AAC9B,QAAI,EAAE,SAAS,SAAU;AACzB,YAAQ,OAAO,MAAM,SAAS,EAAE,KAAK,OAAO,CAAC,CAAC,IAAI,EAAE,OAAO;AAAA,CAAI;AAAA,EACjE;AACA,UAAQ,OAAO,MAAM,gBAAgB;AACvC;AAEA,IAAM,eAAe,oBAAI,IAAI;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,eAAe,OAAwB;AACrC,QAAM,CAAC,KAAK,GAAG,IAAI,IAAI,QAAQ,KAAK,MAAM,CAAC;AAC3C,MAAI,CAAC,OAAO,QAAQ,UAAU,QAAQ,YAAY,QAAQ,MAAM;AAC9D,UAAM,UAAU;AAChB,WAAO,MAAM,UAAU;AAAA,EACzB;AACA,MAAI,QAAQ,YAAa,QAAO,YAAY,CAAC,QAAQ,CAAC;AACtD,MAAI,CAAC,aAAa,IAAI,GAAG,KAAK,QAAQ,QAAS,QAAO,SAAS,CAAC,KAAK,GAAG,IAAI,CAAC;AAG7E,MAAI,KAAK,SAAS,QAAQ,KAAK,KAAK,SAAS,IAAI,GAAG;AAClD,UAAM,SAAS,YAAY,MAAM,IAAI,EAAE;AAAA,MAAO,CAAC,MAC7C,EAAE,WAAW,SAAS,GAAG,GAAG;AAAA,IAC9B;AACA,UAAM,EAAE,SAAS,IAAI,MAAM,OAAO,mBAAc;AAChD,UAAM,OAAO,SAAS,GAAG;AACzB,YAAQ,OAAO;AAAA,MACb,GAAG,OAAO,KAAK,IAAI,CAAC;AAAA,EAAK,KAAK,SAAS,cAAc,IAAI,KAAK,IAAI;AAAA,IACpE;AACA,WAAO;AAAA,EACT;AACA,UAAQ,KAAK;AAAA,IACX,KAAK;AACH,aAAO,UAAU,IAAI;AAAA,IACvB,KAAK;AACH,aAAO,SAAS,IAAI;AAAA,IACtB,KAAK;AACH,aAAO,QAAQ,IAAI;AAAA,IACrB,KAAK;AACH,aAAO,YAAY,IAAI;AAAA,IACzB,KAAK;AACH,aAAO,WAAW,IAAI;AAAA,IACxB,KAAK;AACH,aAAO,SAAS,IAAI;AAAA;AAAA;AAAA,IAGtB,KAAK;AACH,aAAO,SAAS,MAAM,IAAI;AAAA,IAC5B;AACE,YAAM,IAAI,WAAW,oBAAoB,GAAG,uBAAkB;AAAA,EAClE;AACF;AAEA,KAAK,EACF,KAAK,OAAO,SAAS;AAGpB,MAAI,SAAS,SAAS;AACpB,UAAM,OAAO,QAAQ,KAAK,CAAC,KAAK;AAChC,UAAM,EAAE,KAAK,IAAI,MAAM,OAAO,mBAAc;AAC5C,UAAM,aAAa;AAAA,MACjB,GAAG,aAAa,aAAa,IAAI;AAAA,MACjC,GAAG,aAAa,MAAM,IAAI;AAAA,IAC5B;AACA,UAAM,UAAU,mBAAmB,MAAM,CAAC,GAAG,IAAI,IAAI,UAAU,CAAC,CAAC;AACjE,QAAI,SAAS;AACX,cAAQ,OAAO,MAAM,gBAAgB,OAAO;AAAA,CAAI;AAChD,cAAQ,KAAK,UAAU;AAAA,IACzB;AAAA,EACF;AACA,UAAQ,KAAK,IAAI;AACnB,CAAC,EACA,MAAM,CAAC,MAAM;AACZ,MAAI,aAAa,YAAY;AAC3B,YAAQ,OAAO,MAAM,gBAAgB,EAAE,OAAO;AAAA,CAAI;AAClD,YAAQ,KAAK,UAAU;AAAA,EACzB;AACA,MAAI,aAAa,yBAAyB;AACxC,YAAQ,OAAO,MAAM,GAAG,EAAE,OAAO;AAAA,CAAI;AACrC,YAAQ,KAAK,eAAe;AAAA,EAC9B;AACA,UAAQ,OAAO;AAAA,IACb,UAAU,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA;AAAA,EACtD;AACA,UAAQ,KAAK,UAAU;AACzB,CAAC;","names":["existsSync","join","existsSync","require","join"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/output.ts","../src/check.ts","../src/plugin/knobs.ts","../src/programAudio.ts"],"sourcesContent":["import { writeFile } from 'node:fs/promises'\nimport { existsSync, readFileSync, statSync } from 'node:fs'\nimport { basename, dirname, join } from 'node:path'\nimport { createServer } from 'node:http'\nimport { createRequire } from 'node:module'\nimport { fileURLToPath } from 'node:url'\nimport { parseArgs, numFlag, UsageError } from './args'\nimport { helpFlagsFor, unusedFlagsMessage } from './flagUse'\nimport {\n createReporter,\n EXIT_ERROR,\n EXIT_NO_BROWSER,\n EXIT_OK,\n EXIT_USAGE,\n} from './output'\nimport {\n loadVosConfig,\n configDuration,\n directoryKind,\n loadProgramDirectory,\n readSourceText,\n} from './loadConfig'\nimport { launchBrowser, BrowserUnavailableError } from './browser'\nimport {\n inspectStill,\n previewPages,\n reencodeStill,\n renderStill,\n renderVideo,\n stillWarnings,\n} from './render'\nimport { runCheck } from './check'\nimport { programAudio } from './programAudio'\nimport {\n applyDataSets,\n parseTimes,\n setFlags,\n stillFormat,\n stillOutFor,\n videoFormat,\n} from './outputs'\nimport { platformOrigin, resolveCredential } from './plugin/platform'\n\nconst BOOLEAN_FLAGS = new Set(['json', 'help', 'version'])\n\nconst HELP_ENGINE = `vos — command line for the vos programmatic video engine (https://vos.so/engine)\n\nEngine verbs (local, no account, no network beyond the render page's CDN deps)\n vos render <config.json|url|take> [out.mp4|out.webm] [--width 1920] [--height 1080] [--fps 30]\n [--duration <s>] [--format webm|mp4] [--set data.<key>=<value>]... [--json]\n the output's name picks the container; a program document's sound is mixed in\n vos still <config.json|url> [out.webp|out.png|out.jpg] [--time 0 | --times 0,1.5,50%]\n [--width] [--height] [--set data.<key>=<value>]... [--json]\n vos info <config.json|url> [--json]\n vos check <config.json|url> [--json]\n migrate → schema → syntax → compile → determinism/dialect lints, all local\n vos preview <config.json|url> [--port 0]\n vos versions [--json]\n`\n\nconst HELP_CONVENTIONS = `\nConventions\n Results go to stdout; logs go to stderr. --json switches stdout to NDJSON\n events ending with {\"event\":\"done\",…}. Exit codes: 0 ok, 1 error, 2 usage,\n 3 no browser available, 4 the recorder met a sign-in instead of the page\n it was asked for (nothing was recorded; it needs a session, not a new\n script). vos <verb> --help prints that verb's flags.\n`\n\n/** An `audio` element in the config: something a render never mixes. */\nfunction hasAudioElements(config: unknown): boolean {\n const elements = (config as { elements?: unknown }).elements\n return (\n Array.isArray(elements) &&\n elements.some(\n (e) =>\n !!e &&\n typeof e === 'object' &&\n (e as { type?: unknown }).type === 'audio',\n )\n )\n}\n\nfunction outName(source: string, ext: string): string {\n const base = basename(source).replace(/\\.[a-z0-9]+$/i, '') || 'vos'\n return `${base}.${ext}`\n}\n\nasync function cmdRender(argv: string[]): Promise<number> {\n // Polymorphic render: a take DIRECTORY (its doc.json is a recording\n // document) renders through the plugin; a program directory (config.json,\n // composed with a program document when one sits beside it) and every\n // other source are engine config renders. A deterministic sniff, never a\n // flag — and the sniff reads the document, because a program directory\n // carries a doc.json too.\n const first = argv.find((a) => !a.startsWith('-'))\n if (first && directoryKind(first) === 'take') {\n return delegate(['render', ...argv])\n }\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const source = positionals[0]\n if (!source) throw new UsageError('vos render <config.json|url|take> [out]')\n const r = createReporter(flags.json === true)\n const format = videoFormat(\n flags.format === undefined ? undefined : String(flags.format),\n positionals[1],\n )\n\n const loaded = await loadVosConfig(source)\n for (const w of loaded.warnings) r.log(`note: ${w}`)\n void flags.set\n const config = applyDataSets(\n loaded.config as Record<string, unknown>,\n setFlags(argv),\n )\n const duration = numFlag(flags, 'duration', configDuration(config) ?? 5)\n const width = numFlag(flags, 'width', 1920)\n const height = numFlag(flags, 'height', 1080)\n const fps = numFlag(flags, 'fps', 30)\n const out = positionals[1] ?? outName(source, format)\n\n // A program document's sound rides its studio entry; mix it like a take's.\n const audio = await programAudio(config as Record<string, unknown>, {\n baseDir:\n existsSync(source) && statSync(source).isDirectory()\n ? source\n : dirname(source),\n duration,\n origin: platformOrigin({}),\n key: resolveCredential(),\n log: (line) => r.log(line),\n })\n if (audio) r.log(`mixing ${audio.clips} sound${audio.clips === 1 ? '' : 's'}`)\n if (hasAudioElements(config)) {\n r.log(\n 'note: an audio ELEMENT is not mixed by a render; put the sound on the program document instead (doc.json audio: [{ key, start, in, out, duration, gain }])',\n )\n }\n\n const browser = await launchBrowser()\n try {\n const result = await renderVideo(browser, {\n config,\n width,\n height,\n fps,\n duration,\n format,\n audioProducerCode: audio?.producerCode,\n onPhase: (phase) => {\n r.log(`${phase}…`)\n r.event({ event: 'phase', phase })\n },\n })\n await writeFile(out, result.bytes)\n const warnings = stillWarnings(\n { transparent: false, flat: false },\n result.pageErrors,\n result.engineNotes,\n )\n for (const w of warnings) r.log(`warn: ${w}`)\n r.done(\n {\n out,\n bytes: result.bytes.length,\n width,\n height,\n fps,\n duration,\n format,\n audio: audio?.clips ?? 0,\n ...(warnings.length ? { warnings } : {}),\n },\n `Wrote ${out} (${(result.bytes.length / 1024).toFixed(0)} KB, ${width}x${height}@${fps}, ${duration}s)`,\n )\n return EXIT_OK\n } finally {\n await browser.close()\n }\n}\n\nasync function cmdStill(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const source = positionals[0]\n if (!source)\n throw new UsageError(\n 'vos still <config.json|url> [out.webp|out.png|out.jpg] [--time t | --times a,b,50%]',\n )\n const r = createReporter(flags.json === true)\n\n const loaded = await loadVosConfig(source)\n for (const w of loaded.warnings) r.log(`note: ${w}`)\n void flags.set\n const config = applyDataSets(\n loaded.config as Record<string, unknown>,\n setFlags(argv),\n )\n const width = numFlag(flags, 'width', 1280)\n const height = numFlag(flags, 'height', 720)\n const out = positionals[1] ?? outName(source, 'webp')\n const encoding = stillFormat(out)\n const timesRaw = flags.times === undefined ? undefined : String(flags.times)\n if (timesRaw !== undefined && flags.time !== undefined)\n throw new UsageError('--time and --times: pass one')\n const times =\n timesRaw !== undefined\n ? parseTimes(timesRaw, configDuration(config) ?? 5)\n : [numFlag(flags, 'time', 0)]\n const many = times.length > 1\n\n // One browser for every time: each still is its own capture page.\n const browser = await launchBrowser()\n try {\n const written: {\n out: string\n bytes: number\n time: number\n warnings?: string[]\n }[] = []\n for (const time of times) {\n const target = stillOutFor(out, time, many)\n const result = await renderStill(browser, {\n config,\n width,\n height,\n time,\n onPhase: (phase) => {\n r.event({ event: 'phase', phase, time })\n },\n })\n // The engine captures WebP; a .png or .jpg name is re-encoded in the\n // page, so the bytes always match the name.\n const bytes =\n encoding === 'webp'\n ? result.bytes\n : await reencodeStill(browser, result.bytes, encoding)\n await writeFile(target, bytes)\n // A still is checked before anyone looks at it: a fully transparent\n // or flat frame is written, and said, never passed off as a picture.\n const warnings = stillWarnings(\n await inspectStill(browser, result.bytes),\n result.pageErrors,\n result.engineNotes,\n )\n written.push({\n out: target,\n bytes: bytes.length,\n time,\n ...(warnings.length ? { warnings } : {}),\n })\n r.log(\n `Wrote ${target} (${(bytes.length / 1024).toFixed(0)} KB @ t=${Number(time.toFixed(2))}s)`,\n )\n for (const w of warnings)\n r.log(`warn: t=${Number(time.toFixed(2))}s ${w}`)\n }\n const first = written[0]\n r.done(\n many\n ? { stills: written, width, height, format: encoding }\n : { ...first, width, height, format: encoding },\n many\n ? `Wrote ${written.length} stills (${width}x${height})`\n : `Wrote ${first.out} (${(first.bytes / 1024).toFixed(0)} KB, ${width}x${height} @ t=${first.time}s)`,\n )\n return EXIT_OK\n } finally {\n await browser.close()\n }\n}\n\nasync function cmdInfo(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const source = positionals[0]\n if (!source) throw new UsageError('vos info <config.json|url>')\n const r = createReporter(flags.json === true)\n\n const { config, warnings } = await loadVosConfig(source)\n const elements = Array.isArray(config.elements) ? config.elements.length : 0\n const data =\n typeof config.data === 'object' && config.data !== null\n ? Object.keys(config.data)\n : []\n const fns = ['setup', 'createContent', 'createTimeline', 'onFrame'].filter(\n (k) => typeof config[k] === 'string',\n )\n const info = {\n version: config.version,\n duration: configDuration(config) ?? null,\n camera:\n (config.camera as Record<string, unknown> | undefined)?.preset ?? null,\n elements,\n dataKeys: data,\n functions: fns,\n warnings,\n }\n if (r.json) r.done(info, '')\n else {\n for (const w of warnings) r.log(`note: ${w}`)\n process.stdout.write(\n `version: v${String(info.version)}\\n` +\n `duration: ${info.duration === null ? '(none)' : `${info.duration}s`}\\n` +\n `camera: ${String(info.camera ?? '(default)')}\\n` +\n `elements: ${elements}\\n` +\n `data keys: ${data.length ? data.join(', ') : '(none)'}\\n` +\n `functions: ${fns.join(', ')}\\n`,\n )\n }\n return EXIT_OK\n}\n\nfunction packageVersion(name: string): string | null {\n const require = createRequire(import.meta.url)\n // Fast path — packages that export ./package.json (e.g. playwright).\n try {\n return (require(`${name}/package.json`) as { version: string }).version\n } catch {\n // Strict `exports` maps (the @vosjs packages) hide package.json — resolve\n // the entry module instead and walk up to the owning package.json.\n }\n let entry: string | null = null\n try {\n entry = fileURLToPath(import.meta.resolve(name))\n } catch {\n try {\n entry = require.resolve(name)\n } catch {\n return null\n }\n }\n let dir = dirname(entry)\n for (let i = 0; i < 6; i++) {\n try {\n const pkg = JSON.parse(\n readFileSync(join(dir, 'package.json'), 'utf8'),\n ) as {\n name?: string\n version?: string\n }\n if (pkg.name === name && pkg.version) return pkg.version\n } catch {\n // keep walking\n }\n const parent = dirname(dir)\n if (parent === dir) return null\n dir = parent\n }\n return null\n}\n\nfunction ownVersion(): string {\n try {\n const own = JSON.parse(\n readFileSync(\n fileURLToPath(new URL('../package.json', import.meta.url)),\n 'utf8',\n ),\n ) as { version: string }\n return own.version\n } catch {\n return '(unknown)'\n }\n}\n\nasync function cmdVersions(argv: string[]): Promise<number> {\n const { flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const r = createReporter(flags.json === true)\n const versions: Record<string, string> = {}\n versions['@vosjs/cli'] = ownVersion()\n for (const name of [\n '@vosjs/core',\n '@vosjs/elements',\n '@vosjs/tween',\n '@vosjs/editor',\n '@vosjs/timeline',\n '@vosjs/studio-core',\n '@vosjs/render-core',\n '@vosjs/shared',\n 'mediabunny',\n 'playwright',\n ]) {\n versions[name] = packageVersion(name) ?? '(not found)'\n }\n if (r.json) r.done({ versions }, '')\n else\n for (const [k, v] of Object.entries(versions))\n process.stdout.write(`${k} ${v}\\n`)\n return EXIT_OK\n}\n\nasync function cmdPreview(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const source = positionals[0]\n if (!source) throw new UsageError('vos preview <config.json|url> [--port 0]')\n const r = createReporter(false)\n const { config, warnings } = await loadVosConfig(source)\n for (const w of warnings) r.log(`note: ${w}`)\n const { hostHtml, playerHtml } = previewPages(config)\n const server = createServer((req, res) => {\n const path = new URL(req.url ?? '/', 'http://x').pathname\n res.writeHead(200, { 'content-type': 'text/html' })\n res.end(path === '/player' ? playerHtml : hostHtml)\n })\n const port = numFlag(flags, 'port', 0)\n await new Promise<void>((resolve) => server.listen(port, resolve))\n const addr = server.address()\n const url = `http://localhost:${typeof addr === 'object' && addr ? addr.port : port}/`\n process.stdout.write(`${url}\\n`)\n r.log('Serving playback preview — Ctrl-C to stop.')\n await new Promise(() => {}) // keep alive until interrupted\n return EXIT_OK\n}\n\nasync function cmdCheck(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const source = positionals[0]\n if (!source) throw new UsageError('vos check <config.json>')\n const r = createReporter(flags.json === true)\n\n // A directory is a take (refused here: its document is `vos validate`'s\n // job) or a program directory (config.json, composed with the program\n // document beside it so the ladder reads the layers' strings too).\n const kind = /^https?:\\/\\//.test(source) ? 'none' : directoryKind(source)\n if (kind === 'take') {\n throw new UsageError(\n `${source} is a take (its doc.json is a recording document). vos validate ${source} lints it; vos render ${source} renders it.`,\n )\n }\n let raw: string\n let parsed: unknown\n try {\n if (kind === 'program') {\n const notes: string[] = []\n parsed = await loadProgramDirectory(source, notes)\n for (const n of notes) r.log(`note: ${n}`)\n raw = ''\n } else {\n raw = await readSourceText(source)\n parsed = JSON.parse(raw)\n }\n } catch (e) {\n if (!(e instanceof SyntaxError)) throw e\n parsed = undefined\n if (!r.json) process.stdout.write(`error [json] ${(e as Error).message}\\n`)\n r.done(\n {\n ok: false,\n errors: 1,\n warnings: 0,\n issues: [\n { level: 'error', source: 'json', message: (e as Error).message },\n ],\n },\n `${source}: 1 error`,\n )\n return EXIT_ERROR\n }\n\n const result = runCheck(parsed)\n if (r.json) {\n r.done(\n {\n ok: result.ok,\n errors: result.errors,\n warnings: result.warnings,\n issues: result.issues,\n },\n '',\n )\n } else {\n for (const i of result.issues) {\n process.stdout.write(`${i.level} [${i.source}] ${i.message}\\n`)\n }\n process.stdout.write(\n result.ok\n ? `${source}: ok (${result.warnings} warning${result.warnings === 1 ? '' : 's'})\\n`\n : `${source}: ${result.errors} error${result.errors === 1 ? '' : 's'}, ${result.warnings} warning${result.warnings === 1 ? '' : 's'}\\n`,\n )\n }\n return result.ok ? EXIT_OK : EXIT_ERROR\n}\n\n// ---------------------------------------------------------------------------\n// Every verb this file does not own is a take-pipeline or vos.so verb from\n// `./plugin` (what used to ship separately as @vosso/vos-plugin). It loads on\n// demand, so the engine verbs never pay for the recorder's imports, and the\n// old names (`@vosso/cli`, `@vosso/voila-cli`, the `vos voila` alias) keep\n// resolving here for scripts that still use them.\n// ---------------------------------------------------------------------------\n\nasync function delegate(argv: string[], viaAlias = false): Promise<number> {\n const { run } = await import('./plugin/run')\n if (viaAlias && argv[0]) {\n process.stderr.write(\n `note: \"vos voila ${argv[0]}\" is now \"vos ${argv[0]}\".\\n`,\n )\n }\n return await run(argv)\n}\n\nasync function printHelp(): Promise<void> {\n process.stdout.write(HELP_ENGINE)\n const { manifest } = await import('./plugin/manifest')\n process.stdout.write('\\nTake pipeline + vos.so verbs\\n')\n for (const v of manifest.verbs) {\n if (v.name === 'render') continue // polymorphic — already listed above\n process.stdout.write(` vos ${v.name.padEnd(8)} ${v.summary}\\n`)\n }\n process.stdout.write(HELP_CONVENTIONS)\n}\n\nconst ENGINE_VERBS = new Set([\n 'render',\n 'still',\n 'info',\n 'versions',\n 'preview',\n 'check',\n])\n\nasync function main(): Promise<number> {\n const [cmd, ...rest] = process.argv.slice(2)\n if (!cmd || cmd === 'help' || cmd === '--help' || cmd === '-h') {\n await printHelp()\n return cmd ? EXIT_OK : EXIT_USAGE\n }\n if (cmd === '--version') return cmdVersions(['--json'])\n if (!ENGINE_VERBS.has(cmd) && cmd !== 'voila') return delegate([cmd, ...rest])\n // An engine verb asked for its flags: the engine's usage lines, plus the\n // take pipeline's where the verb is shared (render takes a config OR a take).\n if (rest.includes('--help') || rest.includes('-h')) {\n const engine = HELP_ENGINE.split('\\n').filter((l) =>\n l.startsWith(` vos ${cmd} `),\n )\n const { verbHelp } = await import('./plugin/run')\n const take = verbHelp(cmd)\n process.stdout.write(\n `${engine.join('\\n')}\\n${take.includes('no such verb') ? '' : take}`,\n )\n return EXIT_OK\n }\n switch (cmd) {\n case 'render':\n return cmdRender(rest)\n case 'still':\n return cmdStill(rest)\n case 'info':\n return cmdInfo(rest)\n case 'versions':\n return cmdVersions(rest)\n case 'preview':\n return cmdPreview(rest)\n case 'check':\n return cmdCheck(rest)\n // Hidden alias for existing scripts; not in HELP. Same code path as the\n // promoted verbs, plus a one-line pointer at the new spelling.\n case 'voila':\n return delegate(rest, true)\n default:\n throw new UsageError(`unknown command \"${cmd}\" — run vos help`)\n }\n}\n\nmain()\n .then(async (code) => {\n // A run that succeeded while ignoring a flag it was given did not do\n // what was asked (flagUse.ts): say so, and do not exit 0.\n if (code === EXIT_OK) {\n const verb = process.argv[2] ?? ''\n const { HELP } = await import('./plugin/run')\n const documented = [\n ...helpFlagsFor(HELP_ENGINE, verb),\n ...helpFlagsFor(HELP, verb),\n ]\n const message = unusedFlagsMessage(verb, [...new Set(documented)])\n if (message) {\n process.stderr.write(`usage error: ${message}\\n`)\n process.exit(EXIT_USAGE)\n }\n }\n process.exit(code)\n })\n .catch((e) => {\n if (e instanceof UsageError) {\n process.stderr.write(`usage error: ${e.message}\\n`)\n process.exit(EXIT_USAGE)\n }\n if (e instanceof BrowserUnavailableError) {\n process.stderr.write(`${e.message}\\n`)\n process.exit(EXIT_NO_BROWSER)\n }\n process.stderr.write(\n `error: ${e instanceof Error ? e.message : String(e)}\\n`,\n )\n process.exit(EXIT_ERROR)\n })\n","/**\n * Output conventions (agent-safe by construction):\n * - logs/progress → stderr (human readable)\n * - results → stdout; with --json, NDJSON events (`{\"event\":\"phase\"...}` then\n * `{\"event\":\"done\"...}`) so scripts and agents never parse prose\n * - exit codes: 0 ok · 1 failure · 2 usage · 3 browser unavailable ·\n * 4 the recorder met a sign-in (the take pipeline's wall check)\n */\nexport const EXIT_OK = 0\nexport const EXIT_ERROR = 1\nexport const EXIT_USAGE = 2\nexport const EXIT_NO_BROWSER = 3\n\nexport interface Reporter {\n json: boolean\n /** Human log line (stderr; suppressed in --json mode). */\n log: (msg: string) => void\n /** Machine event (stdout NDJSON in --json mode; no-op otherwise). */\n event: (obj: Record<string, unknown>) => void\n /** Final result: NDJSON `done` event in --json mode, plain line otherwise. */\n done: (obj: Record<string, unknown>, humanLine: string) => void\n}\n\nexport function createReporter(json: boolean): Reporter {\n return {\n json,\n log: (msg) => {\n if (!json) process.stderr.write(`${msg}\\n`)\n },\n event: (obj) => {\n if (json) process.stdout.write(`${JSON.stringify(obj)}\\n`)\n },\n done: (obj, humanLine) => {\n if (json)\n process.stdout.write(`${JSON.stringify({ event: 'done', ...obj })}\\n`)\n else process.stdout.write(`${humanLine}\\n`)\n },\n }\n}\n","/**\n * `vos check` — the local validation pipeline, pure so it can be unit-tested:\n * envelope unwrap → migrate → schema → compile → determinism + dialect lints.\n * Everything runs locally (no network, no browser). The platform runs the\n * same compiler server-side, so a clean check is a push that will compile.\n */\nimport {\n CURRENT_CONFIG_VERSION,\n compileVosConfig,\n migrateConfig,\n vosConfigJsonSchema,\n} from '@vosjs/core'\nimport {\n lintVosConfig,\n lintVosDialect,\n lintVosFonts,\n lintVosPostprocessing,\n} from '@vosjs/core/lint'\nimport { knobWarnings } from './plugin/knobs'\n\nexport interface CheckIssue {\n level: 'error' | 'warn'\n source:\n | 'schema'\n | 'syntax'\n | 'compile'\n | 'determinism'\n | 'dialect'\n | 'shape'\n | 'fonts'\n | 'postprocessing'\n message: string\n}\n\nexport interface CheckResult {\n ok: boolean\n errors: number\n warnings: number\n issues: CheckIssue[]\n /** The migrated config (params/presets untouched) — what a push should send. */\n config: Record<string, unknown> | null\n}\n\n// Top-level keys the schema does not know but the platform preserves on push.\nconst PLATFORM_EXTRA_KEYS = new Set(['params', 'presets'])\n\nexport function runCheck(parsed: unknown): CheckResult {\n const issues: CheckIssue[] = []\n const finish = (config: Record<string, unknown> | null): CheckResult => {\n const errors = issues.filter((i) => i.level === 'error').length\n return {\n ok: errors === 0,\n errors,\n warnings: issues.length - errors,\n issues,\n config,\n }\n }\n\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n issues.push({\n level: 'error',\n source: 'shape',\n message: 'not a JSON object',\n })\n return finish(null)\n }\n\n // API endpoints wrap the config: { config: {...} } — accept both shapes.\n let obj = parsed as Record<string, unknown>\n if (\n typeof obj.config === 'object' &&\n obj.config !== null &&\n !('createTimeline' in obj)\n ) {\n obj = obj.config as Record<string, unknown>\n }\n\n const version = obj.version\n let migrated: Record<string, unknown>\n try {\n migrated = migrateConfig(obj) as Record<string, unknown>\n } catch (e) {\n issues.push({\n level: 'error',\n source: 'shape',\n message: `migration failed: ${e instanceof Error ? e.message : String(e)}`,\n })\n return finish(null)\n }\n if (version === undefined) {\n // It compiles (the engine reads an absent version as the current one),\n // but a push is refused: a stored config must say which schema era it was\n // written against, and nobody can tell that from the file later.\n issues.push({\n level: 'warn',\n source: 'shape',\n message: `config declares no \"version\". It plays here, but a push is refused without one. Add \"version\": ${CURRENT_CONFIG_VERSION}.`,\n })\n } else if (version !== CURRENT_CONFIG_VERSION) {\n issues.push({\n level: 'warn',\n source: 'shape',\n message: `config is v${String(version)}, migrated to v${CURRENT_CONFIG_VERSION}. Save the migrated form.`,\n })\n }\n\n const schema = vosConfigJsonSchema.safeParse(migrated)\n if (!schema.success) {\n for (const i of schema.error.issues.slice(0, 10)) {\n issues.push({\n level: 'error',\n source: 'schema',\n message: `${i.path.join('.') || '(root)'}: ${i.message}`,\n })\n }\n return finish(null)\n }\n\n // Keys the platform's schema will silently drop on push (params/presets\n // excepted — those are re-attached by contract).\n const known = new Set([\n ...Object.keys(vosConfigJsonSchema.shape),\n ...PLATFORM_EXTRA_KEYS,\n ])\n for (const key of Object.keys(migrated)) {\n if (!known.has(key)) {\n issues.push({\n level: 'warn',\n source: 'shape',\n message: `unknown top-level key \"${key}\" — the platform drops it on push`,\n })\n }\n }\n\n // Knobs and Looks vos.so would drop (the push still saves, without them).\n for (const message of knobWarnings(migrated as Record<string, unknown>)) {\n issues.push({ level: 'warn', source: 'shape', message })\n }\n\n // Sound as an ELEMENT is not a track: no timeline row, no gain or fades,\n // nothing a render mixes, and a `data:` source inflates the config past\n // what a claimable push can carry. The document is where sound goes.\n const elements = Array.isArray(migrated.elements) ? migrated.elements : []\n for (const el of elements) {\n if (!el || typeof el !== 'object') continue\n const e = el as { type?: unknown; id?: unknown; src?: unknown }\n if (e.type !== 'audio') continue\n const inline =\n typeof e.src === 'string' && e.src.startsWith('data:')\n ? ` (embedded, ${Math.round(e.src.length / 1024)} KB of config)`\n : ''\n issues.push({\n level: 'warn',\n source: 'shape',\n message: `audio element \"${String(e.id ?? '?')}\"${inline} is not a track: renders do not mix it and the studio cannot edit it. Put the file beside the config and name it in doc.json (audio: [{ key: \"score.ogg\", start, in, out, duration, gain }]); vos push uploads it`,\n })\n }\n\n // Function strings are pasted into the template as text, so the compiler\n // cannot see a syntax error — parse each one here (construction only,\n // nothing executes).\n let syntaxErrors = 0\n for (const key of [\n 'setup',\n 'createContent',\n 'createTimeline',\n 'onFrame',\n ] as const) {\n const src = migrated[key]\n if (typeof src !== 'string' || !src.length) continue\n try {\n new Function(`\"use strict\"; return (${src}\\n)`)\n } catch (e) {\n syntaxErrors++\n issues.push({\n level: 'error',\n source: 'syntax',\n message: `${key}: ${e instanceof Error ? e.message : String(e)}`,\n })\n }\n }\n if (syntaxErrors) return finish(migrated)\n\n try {\n // Same options as `vos render` — a clean check is a config the CLI's own\n // render path will accept.\n compileVosConfig(migrated as never, { tweenEngine: 'vos' })\n } catch (e) {\n issues.push({\n level: 'error',\n source: 'compile',\n message: e instanceof Error ? e.message : String(e),\n })\n return finish(migrated)\n }\n\n for (const i of lintVosConfig(migrated as never)) {\n issues.push({\n level: i.severity === 'error' ? 'error' : 'warn',\n source: 'determinism',\n message: `${i.fn}:${i.line} [${i.rule}] ${i.message}`,\n })\n }\n for (const i of lintVosDialect(migrated as never)) {\n issues.push({\n level: i.severity === 'error' ? 'error' : 'warn',\n source: 'dialect',\n message: `${i.fn}:${i.line} [${i.rule}] ${i.message}`,\n })\n }\n for (const i of lintVosFonts(migrated as never)) {\n issues.push({\n level: 'warn',\n source: 'fonts',\n message: `[${i.rule}] ${i.message}`,\n })\n }\n for (const i of lintVosPostprocessing(migrated as never)) {\n issues.push({\n level: 'warn',\n source: 'postprocessing',\n message: `[${i.rule}] ${i.message}`,\n })\n }\n\n return finish(migrated)\n}\n","/**\n * What vos.so keeps of a config's knobs (`params`) and Looks (`presets`).\n *\n * A vos.so fact, so it lives in the platform client: the platform keeps at\n * most 12 knobs and 8 Looks, each within its field limits, and drops the\n * rest ONE BY ONE with a warning (it used to drop them all, silently). This\n * mirrors that rule so `vos check` says the same thing before a push does.\n */\nexport const MAX_PARAMS = 12\nexport const MAX_LOOKS = 8\n\nconst KINDS = new Set(['number', 'color', 'select', 'toggle', 'text', 'font'])\n\nconst str = (v: unknown, max: number, min = 0) =>\n typeof v === 'string' && v.length >= min && v.length <= max\n\n/** Why one knob would be dropped, or null when vos.so keeps it. */\nexport function knobProblem(p: unknown): string | null {\n if (!p || typeof p !== 'object') return 'not an object'\n const k = p as Record<string, unknown>\n if (!str(k.key, 40, 1)) return 'key must be 1 to 40 characters'\n if (typeof k.kind !== 'string' || !KINDS.has(k.kind))\n return `kind must be one of ${[...KINDS].join(', ')}`\n if (k.label !== undefined && !str(k.label, 60))\n return 'label: at most 60 characters'\n if (k.hint !== undefined && !str(k.hint, 140))\n return 'hint: at most 140 characters'\n if (k.unit !== undefined && !str(k.unit, 8))\n return 'unit: at most 8 characters'\n if (k.group !== undefined && !str(k.group, 24))\n return 'group: at most 24 characters'\n if (k.options !== undefined) {\n if (!Array.isArray(k.options) || k.options.length > 12)\n return 'options: at most 12'\n if (k.options.some((o) => !str(o, 40, 1)))\n return 'options: each 1 to 40 characters'\n }\n const d = k.default\n if (\n !(\n typeof d === 'number' ||\n typeof d === 'boolean' ||\n (typeof d === 'string' && d.length <= 280)\n )\n )\n return 'default must be a number, a boolean or at most 280 characters'\n return null\n}\n\n/** Why one Look would be dropped, or null when vos.so keeps it. */\nexport function lookProblem(l: unknown): string | null {\n if (!l || typeof l !== 'object') return 'not an object'\n const look = l as Record<string, unknown>\n if (!str(look.name, 24, 1)) return 'name must be 1 to 24 characters'\n if (!look.values || typeof look.values !== 'object') return 'values missing'\n return null\n}\n\n/** Every knob and Look vos.so would drop, in words, in order. */\nexport function knobWarnings(config: Record<string, unknown>): string[] {\n const out: string[] = []\n const sort = (\n raw: unknown,\n noun: 'knob' | 'look',\n field: string,\n max: number,\n problem: (e: unknown) => string | null,\n ) => {\n if (raw === undefined) return\n if (!Array.isArray(raw)) {\n out.push(`${noun === 'knob' ? 'params' : 'presets'} is not a list`)\n return\n }\n let kept = 0\n raw.forEach((entry, i) => {\n const id =\n entry && typeof (entry as Record<string, unknown>)[field] === 'string'\n ? `${noun} \"${String((entry as Record<string, unknown>)[field])}\"`\n : `${noun} #${i + 1}`\n const why = problem(entry)\n if (why) out.push(`${id} would be dropped on vos.so (${why})`)\n else if (kept >= max)\n out.push(\n `${id} would be dropped on vos.so: a vos keeps at most ${max} ${noun}s${noun === 'knob' ? ' (the rest can stay bound data)' : ''}`,\n )\n else kept += 1\n })\n }\n sort(config.params, 'knob', 'key', MAX_PARAMS, knobProblem)\n sort(config.presets, 'look', 'name', MAX_LOOKS, lookProblem)\n return out\n}\n","/**\n * The sound a program document adds, for a LOCAL render of the program.\n *\n * A composed program carries its `doc.audio` clips on the studio stack entry,\n * exactly as a take does, and the capture page mixes them through the same\n * producer a take render uses. The one difference is WHERE the bytes are: a\n * capture page has no origin of its own, so a clip keyed by a file beside the\n * document (`score.ogg`) or by a hosted asset path (`/api/assets/…`) cannot be\n * fetched from inside it. Each is inlined as a `data:` URI here: a local file\n * read from disk, a hosted asset downloaded with the caller's credential.\n * A clip that cannot be reached is left out and said, never a silent track.\n */\nimport { existsSync } from 'node:fs'\nimport { readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { audioProducerCode, studioEntryData } from '@vosjs/render-core'\nimport { studioAudioPlan } from '@vosjs/studio-core'\nimport { MEDIA_HEAD_BYTES, resolveMediaType } from './plugin/container'\nimport type { EnvelopePoint, LoweredAudioClip } from '@vosjs/studio-core'\n\nexport interface ProgramAudioOptions {\n /** The directory the document's relative keys are read against. */\n baseDir: string\n /** The output length the mix is cut to, seconds. */\n duration: number\n /** For a clip keyed by a hosted asset: where it lives and who may read it. */\n origin?: string\n key?: string | null\n log: (line: string) => void\n}\n\nexport interface ProgramAudio {\n producerCode: string\n clips: number\n}\n\nfunction dataUri(bytes: Uint8Array, filename: string): string {\n const { type } = resolveMediaType({\n head: bytes.subarray(0, MEDIA_HEAD_BYTES),\n filename,\n })\n return `data:${type};base64,${Buffer.from(bytes).toString('base64')}`\n}\n\nasync function reach(\n clipKey: string,\n opts: ProgramAudioOptions,\n): Promise<string | null> {\n if (/^(data:|https?:)/.test(clipKey)) return clipKey\n if (clipKey.startsWith('/api/')) {\n if (!opts.origin || !opts.key) {\n opts.log(\n `note: sound ${clipKey} is a hosted asset and no credential is set, so the render leaves it out (vos login, or keep the file beside the document)`,\n )\n return null\n }\n const res = await fetch(`${opts.origin}${clipKey}`, {\n headers: { authorization: `Bearer ${opts.key}` },\n })\n if (!res.ok) {\n opts.log(\n `note: sound ${clipKey} could not be read (${res.status}), so the render leaves it out`,\n )\n return null\n }\n return dataUri(new Uint8Array(await res.arrayBuffer()), clipKey)\n }\n const file = join(opts.baseDir, clipKey.replace(/^\\/+/, ''))\n if (!existsSync(file)) {\n opts.log(\n `note: sound ${clipKey} is not beside the document, so the render leaves it out`,\n )\n return null\n }\n return dataUri(new Uint8Array(await readFile(file)), file)\n}\n\n/** The producer for a composed program's sound, or null when it adds none. */\nexport async function programAudio(\n config: Record<string, unknown>,\n opts: ProgramAudioOptions,\n): Promise<ProgramAudio | null> {\n const entry = studioEntryData(config.stack)\n const clips = Array.isArray(entry?.audio)\n ? (entry.audio as LoweredAudioClip[])\n : []\n if (!clips.length) return null\n const reached: LoweredAudioClip[] = []\n for (const clip of clips) {\n const key = await reach(clip.key, opts)\n if (key) reached.push({ ...clip, key })\n }\n if (!reached.length) return null\n const duckEnv = Array.isArray(entry?.duckEnv)\n ? (entry.duckEnv as EnvelopePoint[])\n : []\n const plan = studioAudioPlan(reached, duckEnv, opts.duration)\n return {\n producerCode: audioProducerCode({ plan }),\n clips: reached.length,\n }\n}\n"],"mappings":"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","names":["existsSync","join","existsSync","require","join"]}
package/dist/index.d.ts CHANGED
@@ -30,6 +30,8 @@ interface RenderResult {
30
30
  /** Uncaught exceptions the page threw while it rendered (it may still have
31
31
  * written a frame, so a caller says them instead of hiding them). */
32
32
  pageErrors: string[];
33
+ /** The engine's own '[vos] …' warnings: causes a picture cannot show. */
34
+ engineNotes: string[];
33
35
  }
34
36
  /** Render a vos config to a video (WebM/MP4) in a headless browser. */
35
37
  declare function renderVideo(browser: Browser, opts: RenderVideoOptions): Promise<RenderResult>;
package/dist/index.js CHANGED
@@ -1,9 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- previewPages,
4
- renderStill,
5
- renderVideo
6
- } from "./chunk-ZCLGXETO.js";
7
2
  import {
8
3
  RECORDING_NAME,
9
4
  convertAgentBrowser,
@@ -23,7 +18,7 @@ import {
23
18
  takePaths,
24
19
  validateActions,
25
20
  waitForPageDone
26
- } from "./chunk-MJYXP4AA.js";
21
+ } from "./chunk-M7FLXLBN.js";
27
22
  import {
28
23
  BrowserUnavailableError,
29
24
  apiError,
@@ -33,14 +28,17 @@ import {
33
28
  loadVosConfig,
34
29
  parseVosId,
35
30
  platformOrigin,
31
+ previewPages,
36
32
  readSyncState,
33
+ renderStill,
34
+ renderVideo,
37
35
  resolveCredential,
38
36
  writeSyncState
39
- } from "./chunk-WLUWDQQO.js";
37
+ } from "./chunk-JX2YEL3M.js";
40
38
  import "./chunk-6XPFWQKP.js";
41
39
  import {
42
40
  manifest
43
- } from "./chunk-2EHIFIYC.js";
41
+ } from "./chunk-WZGCEAXB.js";
44
42
  export {
45
43
  BrowserUnavailableError,
46
44
  RECORDING_NAME,
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ manifest
4
+ } from "./chunk-WZGCEAXB.js";
5
+ export {
6
+ manifest
7
+ };
8
+ //# sourceMappingURL=manifest-Q4QMVIYR.js.map
@@ -6,8 +6,8 @@ import {
6
6
  takeBackdrop,
7
7
  takeBrowserArgs,
8
8
  verbHelp
9
- } from "./chunk-MJYXP4AA.js";
10
- import "./chunk-WLUWDQQO.js";
9
+ } from "./chunk-M7FLXLBN.js";
10
+ import "./chunk-JX2YEL3M.js";
11
11
  import "./chunk-6XPFWQKP.js";
12
12
  export {
13
13
  HELP,
@@ -17,4 +17,4 @@ export {
17
17
  takeBrowserArgs,
18
18
  verbHelp
19
19
  };
20
- //# sourceMappingURL=run-DYNCGXWO.js.map
20
+ //# sourceMappingURL=run-SYDEWMK2.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vosjs/cli",
3
- "version": "0.53.6",
3
+ "version": "0.54.1",
4
4
  "description": "The vos CLI: record the real product from a scripted browser flow, auto-zoom from the cursor track, cut as data in doc.json, render deterministic video and stills, deliver a release's media per destination spec, and sync with vos.so. One binary, every verb, MIT.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -47,16 +47,18 @@
47
47
  ],
48
48
  "sideEffects": false,
49
49
  "dependencies": {
50
+ "acorn": "^8.18.0",
51
+ "acorn-walk": "^8.3.5",
50
52
  "mediabunny": "^1.55.7",
51
53
  "playwright": "^1.49.0",
54
+ "@vosjs/core": "^0.25.4",
52
55
  "@vosjs/editor": "^1.4.0",
53
56
  "@vosjs/elements": "^0.9.0",
54
- "@vosjs/core": "^0.25.3",
55
57
  "@vosjs/render-core": "^0.3.9",
56
- "@vosjs/studio-core": "^0.33.2",
57
58
  "@vosjs/shared": "^0.6.0",
58
- "@vosjs/tween": "^0.8.2",
59
- "@vosjs/timeline": "^0.4.1"
59
+ "@vosjs/studio-core": "^0.33.2",
60
+ "@vosjs/timeline": "^0.4.1",
61
+ "@vosjs/tween": "^0.8.2"
60
62
  },
61
63
  "devDependencies": {
62
64
  "@types/node": "^22",
package/skills/VERSION CHANGED
@@ -1 +1 @@
1
- 0.12.0
1
+ 0.13.0
@@ -151,33 +151,36 @@ approximation.
151
151
 
152
152
  ## The procedure
153
153
 
154
- 1. **Inventory before writing.** From the source: size, fps, duration;
155
- scenes and their frame windows; every visible string; every colour (CSS
156
- custom properties, theme constants); fonts; media and audio files; the
157
- variables or `defaultProps` (they become params). Write them into `data`
158
- first. This IS the port's contract.
159
- 2. **Get the source's own render.** Remotion: `npx remotion render <id>
160
- out/source.mp4`. HyperFrames: `npx hyperframes render`. It is the
161
- reference every check compares against.
162
- 3. **Scaffold** a `build.mjs` from `references/intro-port.mjs`: real
163
- functions stringified, a template-literal guard, `data`, `params`,
164
- `fonts`, one element per string and shape, a label per scene.
165
- 4. **Translate scene by scene** with the tables. One scene, then check it,
166
- then the next.
154
+ 1. **Get the source's own render.** Remotion: `npx remotion render <id>
155
+ out/source.mp4`. HyperFrames: `npx hyperframes render` (or the one in
156
+ `renders/`). It is the reference every check compares against.
157
+ 2. **Inventory before writing** (cli 0.54+): `npx vos port inventory
158
+ <page.html|project dir>` reads the piece as a browser renders it (words,
159
+ the palette from its custom properties, faces with their catalog match,
160
+ media, scenes, the CSS no element can say) into `port/inventory.json`,
161
+ with stills from its render. A HyperFrames word is laid out where it
162
+ SETTLES in its scene. A Remotion project's words live in `src/`: read
163
+ them there. This IS the port's contract.
164
+ 3. **Scaffold**: `npx vos port scaffold` writes `port/program/program.mjs`
165
+ (every word a bound element, every colour a key, the knobs, a label and a
166
+ TODO per scene, each scene's words shown in its window, a painter only
167
+ when the inventory needs one), `doc.json` with the score as a track, and
168
+ `port/REPORT.md` (substituted faces, gaps). Read the report first. On an
169
+ older CLI, scaffold from `references/intro-port.mjs` by hand.
170
+ 4. **Translate scene by scene** with the tables, replacing each TODO. One
171
+ scene, then check it, then the next.
167
172
  5. **Check** after every scene:
168
173
 
169
174
  ```bash
170
- node build.mjs && vos check config.json
171
- vos still config.json v.png --times 0.5,1,2 --width 1920 --height 1080
172
- ffmpeg -ss 1 -i out/source.mp4 -frames:v 1 r-1.png
173
- ffmpeg -i r-1.png -i v-1.00s.png -filter_complex "[0:v][1:v]ssim" -f null - # SSIM
174
- ffmpeg -i r-1.png -i v-1.00s.png -filter_complex hstack side.png # LOOK at it
175
- vos render config.json small.mp4 --width 960 --height 540 # the scale check
175
+ npx vos build program.mjs && npx vos check . # real functions → config.json; refuses module-scope reads
176
+ npx vos compare . --against ../../renders/source.mp4 # per-frame SSIM + source | vos | difference sheets
177
+ npx vos render . small.mp4 --width 960 --height 540 # the scale check (and the score, from doc.json)
176
178
  ```
177
179
 
178
- A number does not catch a missing element: look at every side-by-side.
179
- Text that `onFrame` writes is in the still too (core 0.25.2+); on an
180
- older CLI check it in a rendered frame.
180
+ `vos compare` exits 1 when ANY frame is under 0.95 and writes a sheet
181
+ per frame: LOOK at them, because a number does not catch a missing
182
+ element. Without the 0.54 CLI, the same loop is `ffmpeg -ss <t>` for the
183
+ source frame, `vos still` for yours, and ffmpeg's `ssim` and `hstack`.
181
184
  6. **Knob honesty**: one `--set data.<key>=<value>` still per param.
182
185
  7. **Push** with the score: `vos push config.json --folder <slug> --label
183
186
  "port of <source>" --note "<what was substituted, what is a painter>"
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/plugin/manifest.ts"],"sourcesContent":["/**\n * The verb manifest of the take pipeline and the vos.so verbs — what\n * `vos help` lists under the engine verbs. It kept the shape a separately\n * installed plugin once handed the host (name + host range), so a script\n * reading it keeps working.\n */\nexport interface PluginVerb {\n name: string\n summary: string\n}\n\nexport interface PluginManifest {\n name: string\n /** Host versions this plugin speaks the run(argv) contract with. */\n hostRange: string\n verbs: PluginVerb[]\n}\n\nexport const manifest: PluginManifest = {\n name: '@vosjs/cli',\n hostRange: '>=0.9.0',\n verbs: [\n {\n name: 'create',\n summary: 'record + auto-plan + render, one command (--strict)',\n },\n {\n name: 'record',\n summary: 'drive actions.json into a take (screencast + cursor track)',\n },\n {\n name: 'plan',\n summary:\n 'plan zoom/cursor effects into doc.json (wand contract); --reuse re-times a previous cut onto a re-recording',\n },\n {\n name: 'render',\n summary: 'render a take directory (engine configs render in the host)',\n },\n {\n name: 'frames',\n summary:\n 'PNG stills at output times / zoom apexes / moments / exact sizes',\n },\n {\n name: 'deliver',\n summary:\n 'render a take to release destinations (CWS, Product Hunt, X, LinkedIn, OG…) + verified kit.json',\n },\n {\n name: 'digest',\n summary:\n 'see a recording before cutting it: moments (clicks, typing, scrolls, idle, scenes) + footage frames + crops, in doc units',\n },\n { name: 'open', summary: 'serve the take into the vos.so studio' },\n {\n name: 'validate',\n summary:\n 'lint actions.json, a take dir (doc.json semantics), or re-measure a kit.json against the channel specs',\n },\n {\n name: 'actions',\n summary:\n 'from-agent-browser: turn an agent-browser walk (steps.jsonl) into actions.json; what cannot follow is named',\n },\n {\n name: 'ingest',\n summary:\n 'a take from a recording someone else made, with its cursor track from a trace beside it (Playwright trace.zip, stamped records, CSV); without one nothing is planned',\n },\n {\n name: 'brand',\n summary:\n \"write a product's BRAND.md, witnessed: /design.md, /llms.txt, then the page (palette, faces, marks, the avoid list)\",\n },\n {\n name: 'fetch',\n summary: 'download a hosted program: config.json + vos.json tracking',\n },\n {\n name: 'push',\n summary: 'push a config.json or take to vos.so (private; versioned)',\n },\n {\n name: 'duplicate',\n summary:\n 'a private sibling of your OWN vos (someone else\\u2019s is remixed: fetch + push --remix-of)',\n },\n {\n name: 'pull',\n summary:\n 'sync what changed on vos.so since your base (--media brings a take’s footage home)',\n },\n {\n name: 'folder',\n summary:\n 'list/create/pull folders, move voses and assets into them (pull = the context package on disk)',\n },\n {\n name: 'asset',\n summary: 'rename one of your assets in place (recipes included)',\n },\n {\n name: 'recipe',\n summary:\n 'push a recipe .md into a folder, or replace one in place (prior body kept)',\n },\n {\n name: 'login',\n summary: 'sign in via the browser (or --key); stores a content key',\n },\n {\n name: 'setup',\n summary:\n 'ready this machine: the vos skills into your agent, a browser, one rules block, then doctor',\n },\n {\n name: 'doctor',\n summary:\n 'what is ready, in words: node, browser, ffmpeg, skills, a credential (never printed), the dev server',\n },\n {\n name: 'whoami',\n summary: 'the key’s name and the account it belongs to, never the key',\n },\n { name: 'logout', summary: 'remove ~/.config/vos/credentials' },\n ],\n}\n"],"mappings":";;;AAkBO,IAAM,WAA2B;AAAA,EACtC,MAAM;AAAA,EACN,WAAW;AAAA,EACX,OAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA,EAAE,MAAM,QAAQ,SAAS,wCAAwC;AAAA,IACjE;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SACE;AAAA,IACJ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA,EAAE,MAAM,UAAU,SAAS,mCAAmC;AAAA,EAChE;AACF;","names":[]}