@vosjs/cli 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -26,10 +26,17 @@ vos plan <take> [--fresh]
26
26
  vos frames <take> [--at-zooms | --frame <t> --size WxH]
27
27
  vos open <take>
28
28
  vos validate <actions.json|take>
29
+
30
+ # Platform (vos.so) — fetch a program, validate locally, push a private remix
31
+ vos fetch <vosId|watch-url> [--out dir] # writes config.json + meta.json (no auth for public programs)
32
+ vos check <config.json> # migrate → schema → syntax → compile → determinism/dialect lints, all local
33
+ vos push <config.json> [--vos id] [--title t] [--slug s] [--remix-of id] [--note n] [--base versionId]
29
34
  ```
30
35
 
31
36
  The take verbs delegate to the separately installed [`@vosso/cli`](https://www.npmjs.com/package/@vosso/cli) (its `run(argv)` export is the contract; `@vosso/voila-cli` remains an install fallback, and `vos voila <verb>` keeps working as a hidden alias for existing scripts). `vos render` is polymorphic by a deterministic sniff, never a flag: a take directory is recognized by its `doc.json`; anything else renders as an engine config.
32
37
 
38
+ The platform verbs implement the remix contract at [vos.so/llms-remix.txt](https://vos.so/llms-remix.txt): `fetch` a public program's config (params and presets preserved), edit it, `check` it locally (the same compiler the platform runs), and `push` it back as a **private** vos with lineage — or iterate an existing one with `--vos`. Auth resolves from `VOS_API_KEY`, then the first line of `~/.config/vos/credentials` (mint a key at [vos.so/app/api](https://vos.so/app/api); an ephemeral `vos_rg_` remix grant works too). Keys can never publish — the pushed vos stays private until a human publishes it on vos.so. `--base` names the version an edit was made from and `--note` describes it; both are forwarded and recorded where the platform supports them. `VOS_ORIGIN` overrides the platform origin for self-hosted or local development.
39
+
33
40
  `vos render` accepts `--width` / `--height` / `--fps` / `--duration` / `--format webm|mp4`; `vos still` accepts `--time` / `--width` / `--height`. Configs can be local files or URLs, and API `{ "config": … }` envelopes are unwrapped automatically. Old config versions are migrated before rendering.
34
41
 
35
42
  Rendering runs the same deterministic pipeline everywhere: the config is compiled with `@vosjs/core`, wrapped in the engine's capture template, and encoded frame-by-frame (WebCodecs) in headless Chromium. Same input, same video — locally, in CI, or on a server.
package/dist/cli.js CHANGED
@@ -13,9 +13,9 @@ import {
13
13
  } from "./chunk-A5AN2K5L.js";
14
14
 
15
15
  // src/cli.ts
16
- import { writeFile } from "fs/promises";
17
- import { existsSync, readFileSync } from "fs";
18
- import { basename, dirname, join } from "path";
16
+ import { mkdir, readFile, writeFile } from "fs/promises";
17
+ import { existsSync, readFileSync as readFileSync2 } from "fs";
18
+ import { basename, dirname, join as join2 } from "path";
19
19
  import { createServer } from "http";
20
20
  import { createRequire } from "module";
21
21
  import { fileURLToPath } from "url";
@@ -45,6 +45,176 @@ function createReporter(json) {
45
45
  };
46
46
  }
47
47
 
48
+ // src/check.ts
49
+ import {
50
+ CURRENT_CONFIG_VERSION,
51
+ compileVosConfig,
52
+ migrateConfig,
53
+ vosConfigJsonSchema
54
+ } from "@vosjs/core";
55
+ import { lintVosConfig, lintVosDialect } from "@vosjs/core/lint";
56
+ var PLATFORM_EXTRA_KEYS = /* @__PURE__ */ new Set(["params", "presets"]);
57
+ function runCheck(parsed) {
58
+ const issues = [];
59
+ const finish = (config) => {
60
+ const errors = issues.filter((i) => i.level === "error").length;
61
+ return {
62
+ ok: errors === 0,
63
+ errors,
64
+ warnings: issues.length - errors,
65
+ issues,
66
+ config
67
+ };
68
+ };
69
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
70
+ issues.push({ level: "error", source: "shape", message: "not a JSON object" });
71
+ return finish(null);
72
+ }
73
+ let obj = parsed;
74
+ if (typeof obj.config === "object" && obj.config !== null && !("createTimeline" in obj)) {
75
+ obj = obj.config;
76
+ }
77
+ const version = obj.version;
78
+ let migrated;
79
+ try {
80
+ migrated = migrateConfig(obj);
81
+ } catch (e) {
82
+ issues.push({
83
+ level: "error",
84
+ source: "shape",
85
+ message: `migration failed: ${e instanceof Error ? e.message : String(e)}`
86
+ });
87
+ return finish(null);
88
+ }
89
+ if (version !== CURRENT_CONFIG_VERSION) {
90
+ issues.push({
91
+ level: "warn",
92
+ source: "shape",
93
+ message: `config is v${String(version ?? 1)} \u2014 migrated to v${CURRENT_CONFIG_VERSION}; save the migrated form`
94
+ });
95
+ }
96
+ const schema = vosConfigJsonSchema.safeParse(migrated);
97
+ if (!schema.success) {
98
+ for (const i of schema.error.issues.slice(0, 10)) {
99
+ issues.push({
100
+ level: "error",
101
+ source: "schema",
102
+ message: `${i.path.join(".") || "(root)"}: ${i.message}`
103
+ });
104
+ }
105
+ return finish(null);
106
+ }
107
+ const known = /* @__PURE__ */ new Set([...Object.keys(vosConfigJsonSchema.shape), ...PLATFORM_EXTRA_KEYS]);
108
+ for (const key of Object.keys(migrated)) {
109
+ if (!known.has(key)) {
110
+ issues.push({
111
+ level: "warn",
112
+ source: "shape",
113
+ message: `unknown top-level key "${key}" \u2014 the platform drops it on push`
114
+ });
115
+ }
116
+ }
117
+ let syntaxErrors = 0;
118
+ for (const key of ["setup", "createContent", "createTimeline", "onFrame"]) {
119
+ const src = migrated[key];
120
+ if (typeof src !== "string" || !src.length) continue;
121
+ try {
122
+ new Function(`"use strict"; return (${src}
123
+ )`);
124
+ } catch (e) {
125
+ syntaxErrors++;
126
+ issues.push({
127
+ level: "error",
128
+ source: "syntax",
129
+ message: `${key}: ${e instanceof Error ? e.message : String(e)}`
130
+ });
131
+ }
132
+ }
133
+ if (syntaxErrors) return finish(migrated);
134
+ try {
135
+ compileVosConfig(migrated, { tweenEngine: "vos" });
136
+ } catch (e) {
137
+ issues.push({
138
+ level: "error",
139
+ source: "compile",
140
+ message: e instanceof Error ? e.message : String(e)
141
+ });
142
+ return finish(migrated);
143
+ }
144
+ for (const i of lintVosConfig(migrated)) {
145
+ issues.push({
146
+ level: i.severity === "error" ? "error" : "warn",
147
+ source: "determinism",
148
+ message: `${i.fn}:${i.line} [${i.rule}] ${i.message}`
149
+ });
150
+ }
151
+ for (const i of lintVosDialect(migrated)) {
152
+ issues.push({
153
+ level: i.severity === "error" ? "error" : "warn",
154
+ source: "dialect",
155
+ message: `${i.fn}:${i.line} [${i.rule}] ${i.message}`
156
+ });
157
+ }
158
+ return finish(migrated);
159
+ }
160
+
161
+ // src/platform.ts
162
+ import { readFileSync } from "fs";
163
+ import { homedir } from "os";
164
+ import { join } from "path";
165
+ var PLATFORM_ORIGIN = process.env.VOS_ORIGIN ?? "https://vos.so";
166
+ function parseVosId(input) {
167
+ if (!/^https?:\/\//.test(input)) {
168
+ if (/^[A-Za-z0-9_-]+$/.test(input)) return input;
169
+ throw new UsageError(`"${input}" is not a vos id or URL`);
170
+ }
171
+ let url;
172
+ try {
173
+ url = new URL(input);
174
+ } catch {
175
+ throw new UsageError(`"${input}" is not a valid URL`);
176
+ }
177
+ const query = url.searchParams.get("vos");
178
+ if (query) return query;
179
+ const path = url.pathname.match(/\/vos\/([A-Za-z0-9_-]+)/);
180
+ if (path) return path[1];
181
+ throw new UsageError(`could not find a vos id in ${input} \u2014 expected /vos/{id} or ?vos={id}`);
182
+ }
183
+ function resolveCredential() {
184
+ const env = process.env.VOS_API_KEY?.trim();
185
+ if (env) return env;
186
+ try {
187
+ const first = readFileSync(join(homedir(), ".config", "vos", "credentials"), "utf8").split("\n")[0].trim();
188
+ return first || null;
189
+ } catch {
190
+ return null;
191
+ }
192
+ }
193
+ function deriveSlug(title) {
194
+ return title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 50).replace(/-+$/, "") || "remix";
195
+ }
196
+ async function apiJson(path, init = {}) {
197
+ const headers = { accept: "application/json" };
198
+ if (init.key) headers.authorization = `Bearer ${init.key}`;
199
+ if (init.body !== void 0) headers["content-type"] = "application/json";
200
+ const res = await fetch(`${PLATFORM_ORIGIN}${path}`, {
201
+ method: init.method ?? "GET",
202
+ headers,
203
+ body: init.body === void 0 ? void 0 : JSON.stringify(init.body)
204
+ });
205
+ let body = {};
206
+ try {
207
+ body = await res.json();
208
+ } catch {
209
+ }
210
+ return { status: res.status, body };
211
+ }
212
+ function apiError(what, r) {
213
+ const detail = typeof r.body.error === "string" ? r.body.error : r.body.details !== void 0 ? JSON.stringify(r.body.details) : "";
214
+ const hint = r.status === 401 ? " (set VOS_API_KEY or write ~/.config/vos/credentials \u2014 mint a key at https://vos.so/app/api)" : "";
215
+ return `${what} \u2192 ${r.status}${detail ? `: ${detail}` : ""}${hint}`;
216
+ }
217
+
48
218
  // src/cli.ts
49
219
  var BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["json", "help", "version"]);
50
220
  var HELP = `vos \u2014 command line for the vos programmatic video engine (https://vos.so)
@@ -57,6 +227,19 @@ Usage
57
227
  vos preview <config.json|url> [--port 0]
58
228
  vos versions [--json]
59
229
 
230
+ Platform (vos.so) \u2014 fetch a program, validate locally, push a private remix
231
+ vos fetch <vosId|watch-url> [--out dir] [--json]
232
+ writes config.json + meta.json (no auth needed for public programs)
233
+ vos check <config.json> [--json]
234
+ migrate \u2192 schema \u2192 compile \u2192 determinism/dialect lints, all local
235
+ vos push <config.json> [--vos id] [--title t] [--slug s] [--remix-of id]
236
+ [--note n] [--base versionId] [--json]
237
+ no --vos: create a PRIVATE vos (lineage from meta.json / --remix-of)
238
+ with --vos: add a version to it; --base = the version you edited
239
+ from, --note = what changed (recorded where the platform supports it)
240
+ auth: VOS_API_KEY or ~/.config/vos/credentials \u2014 mint at vos.so/app/api;
241
+ keys can never publish (visibility stays private; humans publish on vos.so)
242
+
60
243
  Take pipeline \u2014 screen recordings in, polished product video out
61
244
  (ships separately: npm i -D @vosso/cli)
62
245
  vos create --actions actions.json [out.webm] [--strict] (record + plan + render, one shot)
@@ -78,7 +261,7 @@ function outName(source, ext) {
78
261
  }
79
262
  async function cmdRender(argv) {
80
263
  const first = argv.find((a) => !a.startsWith("-"));
81
- if (first && existsSync(join(first, "doc.json"))) {
264
+ if (first && existsSync(join2(first, "doc.json"))) {
82
265
  return delegateTake(["render", ...argv]);
83
266
  }
84
267
  const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS);
@@ -205,7 +388,7 @@ function packageVersion(name) {
205
388
  let dir = dirname(entry);
206
389
  for (let i = 0; i < 6; i++) {
207
390
  try {
208
- const pkg = JSON.parse(readFileSync(join(dir, "package.json"), "utf8"));
391
+ const pkg = JSON.parse(readFileSync2(join2(dir, "package.json"), "utf8"));
209
392
  if (pkg.name === name && pkg.version) return pkg.version;
210
393
  } catch {
211
394
  }
@@ -221,7 +404,7 @@ async function cmdVersions(argv) {
221
404
  const versions = {};
222
405
  try {
223
406
  const own = JSON.parse(
224
- readFileSync(fileURLToPath(new URL("../package.json", import.meta.url)), "utf8")
407
+ readFileSync2(fileURLToPath(new URL("../package.json", import.meta.url)), "utf8")
225
408
  );
226
409
  versions["@vosjs/cli"] = own.version;
227
410
  } catch {
@@ -259,6 +442,186 @@ async function cmdPreview(argv) {
259
442
  });
260
443
  return EXIT_OK;
261
444
  }
445
+ async function cmdFetch(argv) {
446
+ const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS);
447
+ const source = positionals[0];
448
+ if (!source) throw new UsageError("vos fetch <vosId|watch-url> [--out dir]");
449
+ const r = createReporter(flags.json === true);
450
+ const id = parseVosId(source);
451
+ const key = resolveCredential();
452
+ const meta = await apiJson(`/api/vos/${id}`, { key });
453
+ if (meta.status !== 200) throw new Error(apiError(`fetch vos ${id}`, meta));
454
+ const cfg = await apiJson(`/api/vos/${id}/config`, { key });
455
+ if (cfg.status !== 200) throw new Error(apiError(`fetch config for ${id}`, cfg));
456
+ const vosMeta = meta.body.vos ?? {};
457
+ const slug = typeof vosMeta.slug === "string" && vosMeta.slug ? vosMeta.slug : id;
458
+ const out = flags.out ?? slug;
459
+ await mkdir(out, { recursive: true });
460
+ await writeFile(join2(out, "config.json"), JSON.stringify(cfg.body.config, null, 2));
461
+ await writeFile(join2(out, "meta.json"), JSON.stringify(vosMeta, null, 2));
462
+ const title = typeof vosMeta.title === "string" ? vosMeta.title : "";
463
+ r.done(
464
+ {
465
+ out,
466
+ id,
467
+ slug,
468
+ title,
469
+ currentVersionId: vosMeta.currentVersionId ?? null
470
+ },
471
+ `Wrote ${out}/config.json + meta.json (${title || id})
472
+ Edit config.json, then: vos check ${out}/config.json && vos push ${out}/config.json`
473
+ );
474
+ return EXIT_OK;
475
+ }
476
+ async function cmdCheck(argv) {
477
+ const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS);
478
+ const source = positionals[0];
479
+ if (!source) throw new UsageError("vos check <config.json>");
480
+ const r = createReporter(flags.json === true);
481
+ let raw;
482
+ if (/^https?:\/\//.test(source)) {
483
+ const res = await fetch(source);
484
+ if (!res.ok) throw new Error(`fetch ${source} \u2192 ${res.status}`);
485
+ raw = await res.text();
486
+ } else {
487
+ raw = await readFile(source, "utf8");
488
+ }
489
+ let parsed;
490
+ try {
491
+ parsed = JSON.parse(raw);
492
+ } catch (e) {
493
+ parsed = void 0;
494
+ if (!r.json) process.stdout.write(`error [json] ${e.message}
495
+ `);
496
+ r.done({ ok: false, errors: 1, warnings: 0, issues: [{ level: "error", source: "json", message: e.message }] }, `${source}: 1 error`);
497
+ return EXIT_ERROR;
498
+ }
499
+ const result = runCheck(parsed);
500
+ if (r.json) {
501
+ r.done(
502
+ { ok: result.ok, errors: result.errors, warnings: result.warnings, issues: result.issues },
503
+ ""
504
+ );
505
+ } else {
506
+ for (const i of result.issues) {
507
+ process.stdout.write(`${i.level} [${i.source}] ${i.message}
508
+ `);
509
+ }
510
+ process.stdout.write(
511
+ result.ok ? `${source}: ok (${result.warnings} warning${result.warnings === 1 ? "" : "s"})
512
+ ` : `${source}: ${result.errors} error${result.errors === 1 ? "" : "s"}, ${result.warnings} warning${result.warnings === 1 ? "" : "s"}
513
+ `
514
+ );
515
+ }
516
+ return result.ok ? EXIT_OK : EXIT_ERROR;
517
+ }
518
+ async function cmdPush(argv) {
519
+ const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS);
520
+ const source = positionals[0];
521
+ if (!source) {
522
+ throw new UsageError(
523
+ "vos push <config.json> [--vos id] [--title t] [--slug s] [--remix-of id] [--note n] [--base versionId]"
524
+ );
525
+ }
526
+ const r = createReporter(flags.json === true);
527
+ const parsed = JSON.parse(await readFile(source, "utf8"));
528
+ const check = runCheck(parsed);
529
+ if (!check.ok || !check.config) {
530
+ for (const i of check.issues) {
531
+ if (i.level === "error") r.log(`error [${i.source}] ${i.message}`);
532
+ }
533
+ throw new Error(`config does not validate \u2014 run: vos check ${source}`);
534
+ }
535
+ const config = check.config;
536
+ const key = resolveCredential();
537
+ if (!key) {
538
+ throw new Error(
539
+ "no credential found \u2014 set VOS_API_KEY or write the key as the first line of ~/.config/vos/credentials (mint one at https://vos.so/app/api; a vos_rg_ remix grant works too)"
540
+ );
541
+ }
542
+ if (flags.vos) {
543
+ const vosId = parseVosId(String(flags.vos));
544
+ const body = { config };
545
+ if (flags.base) body.baseVersionId = String(flags.base);
546
+ if (flags.note) body.note = String(flags.note);
547
+ const res = await apiJson(`/api/vos/${vosId}/versions`, { method: "POST", key, body });
548
+ if (res.status === 409) {
549
+ const changes = Array.isArray(res.body.changes) ? res.body.changes : [];
550
+ for (const ch of changes) {
551
+ const summary = typeof ch === "object" && ch !== null && "summary" in ch ? String(ch.summary) : JSON.stringify(ch);
552
+ r.log(`platform change: ${summary}`);
553
+ }
554
+ r.event({ event: "conflict", reason: res.body.error ?? "conflict", changes });
555
+ throw new Error(
556
+ `version base is stale \u2014 the platform copy changed (${changes.length} edit${changes.length === 1 ? "s" : ""} above). Fetch, rebase your edit, and push again: vos fetch ${vosId}`
557
+ );
558
+ }
559
+ if (res.status !== 201) throw new Error(apiError(`push version to ${vosId}`, res));
560
+ const version = res.body.version ?? {};
561
+ const watchUrl = `${PLATFORM_ORIGIN}/vos/${vosId}`;
562
+ const studioUrl = `${PLATFORM_ORIGIN}/studio?vos=${vosId}`;
563
+ r.done(
564
+ {
565
+ id: vosId,
566
+ versionId: version.id ?? null,
567
+ versionNumber: version.versionNumber ?? null,
568
+ watchUrl,
569
+ studioUrl
570
+ },
571
+ `Pushed version ${String(version.versionNumber ?? "?")} of ${vosId}
572
+ watch: ${watchUrl}
573
+ studio: ${studioUrl}`
574
+ );
575
+ return EXIT_OK;
576
+ }
577
+ let meta = {};
578
+ try {
579
+ meta = JSON.parse(await readFile(join2(dirname(source), "meta.json"), "utf8"));
580
+ } catch {
581
+ }
582
+ const remixOfId = flags["remix-of"] ? String(flags["remix-of"]) : typeof meta.id === "string" ? meta.id : void 0;
583
+ const fallbackTitle = typeof meta.title === "string" && meta.title ? `${meta.title} remix` : basename(source).replace(/\.json$/i, "") || "vos remix";
584
+ const title = (flags.title ?? fallbackTitle).slice(0, 100);
585
+ const slugGiven = typeof flags.slug === "string";
586
+ const baseSlug = slugGiven ? flags.slug : deriveSlug(title);
587
+ for (let attempt = 0; ; attempt++) {
588
+ const slug = attempt === 0 ? baseSlug : `${baseSlug}-${attempt + 1}`.slice(0, 50);
589
+ const body = {
590
+ title,
591
+ slug,
592
+ visibility: "private",
593
+ config
594
+ };
595
+ if (remixOfId) body.remixOfId = remixOfId;
596
+ const res = await apiJson("/api/vos", { method: "POST", key, body });
597
+ if (res.status === 409 && !slugGiven && attempt < 3) {
598
+ r.log(`slug "${slug}" is taken \u2014 retrying`);
599
+ continue;
600
+ }
601
+ if (res.status !== 201) throw new Error(apiError("push vos", res));
602
+ const created = res.body.vos ?? {};
603
+ const id = String(created.id ?? "");
604
+ const watchUrl = `${PLATFORM_ORIGIN}/vos/${id}`;
605
+ const studioUrl = `${PLATFORM_ORIGIN}/studio?vos=${id}`;
606
+ r.done(
607
+ {
608
+ id,
609
+ slug: created.slug ?? slug,
610
+ title,
611
+ visibility: created.visibility ?? "private",
612
+ remixOfId: remixOfId ?? null,
613
+ currentVersionId: created.currentVersionId ?? null,
614
+ watchUrl,
615
+ studioUrl
616
+ },
617
+ `Created private vos ${id} (${title})
618
+ watch: ${watchUrl}
619
+ studio: ${studioUrl}
620
+ Iterate with: vos push ${source} --vos ${id}`
621
+ );
622
+ return EXIT_OK;
623
+ }
624
+ }
262
625
  var TAKE_VERBS = /* @__PURE__ */ new Set(["create", "record", "plan", "frames", "open", "validate"]);
263
626
  async function delegateTake(argv, viaAlias = false) {
264
627
  for (const name of ["@vosso/cli", "@vosso/voila-cli"]) {
@@ -302,6 +665,12 @@ async function main() {
302
665
  return cmdVersions(rest);
303
666
  case "preview":
304
667
  return cmdPreview(rest);
668
+ case "fetch":
669
+ return cmdFetch(rest);
670
+ case "check":
671
+ return cmdCheck(rest);
672
+ case "push":
673
+ return cmdPush(rest);
305
674
  // Hidden alias for existing scripts; not in HELP. Same code path as the
306
675
  // promoted verbs, plus a one-line pointer at the new spelling.
307
676
  case "voila":
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/output.ts"],"sourcesContent":["import { writeFile } from 'node:fs/promises'\nimport { existsSync, readFileSync } 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 {\n createReporter,\n EXIT_ERROR,\n EXIT_NO_BROWSER,\n EXIT_OK,\n EXIT_USAGE,\n} from './output'\nimport { loadVosConfig, configDuration } from './loadConfig'\nimport { launchBrowser, BrowserUnavailableError } from './browser'\nimport { renderVideo, renderStill, previewPages } from './render'\n\nconst BOOLEAN_FLAGS = new Set(['json', 'help', 'version'])\n\nconst HELP = `vos — command line for the vos programmatic video engine (https://vos.so)\n\nUsage\n vos render <config.json|url|take> [out] [--width 1920] [--height 1080] [--fps 30]\n [--duration <s>] [--format webm|mp4] [--json]\n vos still <config.json|url> [out.webp] [--time 0] [--width] [--height] [--json]\n vos info <config.json|url> [--json]\n vos preview <config.json|url> [--port 0]\n vos versions [--json]\n\nTake pipeline — screen recordings in, polished product video out\n(ships separately: npm i -D @vosso/cli)\n vos create --actions actions.json [out.webm] [--strict] (record + plan + render, one shot)\n vos record --actions actions.json [--out take] [--strict]\n vos plan <take> [--fresh]\n vos frames <take> [--at-zooms | --frame <t> --size WxH]\n vos open <take> (serve the take into the studio at vos.so)\n vos validate <actions.json|take>\n vos render <take> [out] (a take directory is detected by its doc.json)\n\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.\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 (detected by its doc.json — the take\n // pipeline's editable document) renders through the take pipeline; anything\n // else is an engine config render. A deterministic sniff, never a flag.\n const first = argv.find((a) => !a.startsWith('-'))\n if (first && existsSync(join(first, 'doc.json'))) {\n return delegateTake(['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 = (flags.format as string) ?? 'webm'\n if (format !== 'webm' && format !== 'mp4') throw new UsageError('--format must be webm or mp4')\n\n const { config, warnings } = await loadVosConfig(source)\n for (const w of warnings) r.log(`note: ${w}`)\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 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 onPhase: (phase) => {\n r.log(`${phase}…`)\n r.event({ event: 'phase', phase })\n },\n })\n await writeFile(out, result.bytes)\n r.done(\n { out, bytes: result.bytes.length, width, height, fps, duration, format },\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) throw new UsageError('vos still <config.json|url> [out.webp]')\n const r = createReporter(flags.json === true)\n\n const { config, warnings } = await loadVosConfig(source)\n for (const w of warnings) r.log(`note: ${w}`)\n const time = numFlag(flags, 'time', 0)\n const width = numFlag(flags, 'width', 1280)\n const height = numFlag(flags, 'height', 720)\n const out = positionals[1] ?? outName(source, 'webp')\n\n const browser = await launchBrowser()\n try {\n const result = await renderStill(browser, {\n config,\n width,\n height,\n time,\n onPhase: (phase) => {\n r.log(`${phase}…`)\n r.event({ event: 'phase', phase })\n },\n })\n await writeFile(out, result.bytes)\n r.done(\n { out, bytes: result.bytes.length, width, height, time, mimeType: result.mimeType },\n `Wrote ${out} (${(result.bytes.length / 1024).toFixed(0)} KB, ${width}x${height} @ t=${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 = typeof config.data === 'object' && config.data !== null ? Object.keys(config.data) : []\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: (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(readFileSync(join(dir, 'package.json'), 'utf8')) 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\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 // Own version: read relative to dist (self-require is blocked by `exports`).\n try {\n const own = JSON.parse(\n readFileSync(fileURLToPath(new URL('../package.json', import.meta.url)), 'utf8'),\n ) as { version: string }\n versions['@vosjs/cli'] = own.version\n } catch {\n versions['@vosjs/cli'] = '(unknown)'\n }\n for (const name of ['@vosjs/core', '@vosjs/elements', '@vosjs/tween', 'playwright']) {\n versions[name] = packageVersion(name) ?? '(not found)'\n }\n if (r.json) r.done({ versions }, '')\n else for (const [k, v] of Object.entries(versions)) 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\n// The take pipeline's verbs live in @vosso/cli (published; previously\n// @vosso/voila-cli, kept as an install fallback during the transition).\n// The delegation contract is its `run(argv)` export.\nconst TAKE_VERBS = new Set(['create', 'record', 'plan', 'frames', 'open', 'validate'])\n\nasync function delegateTake(argv: string[], viaAlias = false): Promise<number> {\n for (const name of ['@vosso/cli', '@vosso/voila-cli']) {\n let mod: { run?: (argv: string[]) => Promise<number> }\n try {\n mod = (await import(name as string)) as typeof mod\n } catch {\n continue\n }\n if (typeof mod.run !== 'function') continue\n if (viaAlias && argv[0]) {\n process.stderr.write(`note: \"vos voila ${argv[0]}\" is now \"vos ${argv[0]}\".\\n`)\n }\n return await mod.run(argv)\n }\n process.stderr.write(\n 'The take pipeline (screen recordings in, product video out) ships separately.\\n' +\n ' npm i -D @vosso/cli\\n' +\n `then re-run: vos ${argv.join(' ')}\\n`,\n )\n return EXIT_ERROR\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 process.stdout.write(HELP)\n return cmd ? EXIT_OK : EXIT_USAGE\n }\n if (cmd === '--version') return cmdVersions(['--json'])\n if (TAKE_VERBS.has(cmd)) return delegateTake([cmd, ...rest])\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 // 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 delegateTake(rest, true)\n default:\n throw new UsageError(`unknown command \"${cmd}\" — run vos help`)\n }\n}\n\nmain()\n .then((code) => process.exit(code))\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(`error: ${e instanceof Error ? e.message : String(e)}\\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 */\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) process.stdout.write(`${JSON.stringify({ event: 'done', ...obj })}\\n`)\n else process.stdout.write(`${humanLine}\\n`)\n },\n }\n}\n"],"mappings":"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","names":["require"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/output.ts","../src/check.ts","../src/platform.ts"],"sourcesContent":["import { mkdir, readFile, writeFile } from 'node:fs/promises'\nimport { existsSync, readFileSync } 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 {\n createReporter,\n EXIT_ERROR,\n EXIT_NO_BROWSER,\n EXIT_OK,\n EXIT_USAGE,\n} from './output'\nimport { loadVosConfig, configDuration } from './loadConfig'\nimport { launchBrowser, BrowserUnavailableError } from './browser'\nimport { renderVideo, renderStill, previewPages } from './render'\nimport { runCheck } from './check'\nimport {\n PLATFORM_ORIGIN,\n apiError,\n apiJson,\n deriveSlug,\n parseVosId,\n resolveCredential,\n} from './platform'\n\nconst BOOLEAN_FLAGS = new Set(['json', 'help', 'version'])\n\nconst HELP = `vos — command line for the vos programmatic video engine (https://vos.so)\n\nUsage\n vos render <config.json|url|take> [out] [--width 1920] [--height 1080] [--fps 30]\n [--duration <s>] [--format webm|mp4] [--json]\n vos still <config.json|url> [out.webp] [--time 0] [--width] [--height] [--json]\n vos info <config.json|url> [--json]\n vos preview <config.json|url> [--port 0]\n vos versions [--json]\n\nPlatform (vos.so) — fetch a program, validate locally, push a private remix\n vos fetch <vosId|watch-url> [--out dir] [--json]\n writes config.json + meta.json (no auth needed for public programs)\n vos check <config.json> [--json]\n migrate → schema → compile → determinism/dialect lints, all local\n vos push <config.json> [--vos id] [--title t] [--slug s] [--remix-of id]\n [--note n] [--base versionId] [--json]\n no --vos: create a PRIVATE vos (lineage from meta.json / --remix-of)\n with --vos: add a version to it; --base = the version you edited\n from, --note = what changed (recorded where the platform supports it)\n auth: VOS_API_KEY or ~/.config/vos/credentials — mint at vos.so/app/api;\n keys can never publish (visibility stays private; humans publish on vos.so)\n\nTake pipeline — screen recordings in, polished product video out\n(ships separately: npm i -D @vosso/cli)\n vos create --actions actions.json [out.webm] [--strict] (record + plan + render, one shot)\n vos record --actions actions.json [--out take] [--strict]\n vos plan <take> [--fresh]\n vos frames <take> [--at-zooms | --frame <t> --size WxH]\n vos open <take> (serve the take into the studio at vos.so)\n vos validate <actions.json|take>\n vos render <take> [out] (a take directory is detected by its doc.json)\n\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.\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 (detected by its doc.json — the take\n // pipeline's editable document) renders through the take pipeline; anything\n // else is an engine config render. A deterministic sniff, never a flag.\n const first = argv.find((a) => !a.startsWith('-'))\n if (first && existsSync(join(first, 'doc.json'))) {\n return delegateTake(['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 = (flags.format as string) ?? 'webm'\n if (format !== 'webm' && format !== 'mp4') throw new UsageError('--format must be webm or mp4')\n\n const { config, warnings } = await loadVosConfig(source)\n for (const w of warnings) r.log(`note: ${w}`)\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 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 onPhase: (phase) => {\n r.log(`${phase}…`)\n r.event({ event: 'phase', phase })\n },\n })\n await writeFile(out, result.bytes)\n r.done(\n { out, bytes: result.bytes.length, width, height, fps, duration, format },\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) throw new UsageError('vos still <config.json|url> [out.webp]')\n const r = createReporter(flags.json === true)\n\n const { config, warnings } = await loadVosConfig(source)\n for (const w of warnings) r.log(`note: ${w}`)\n const time = numFlag(flags, 'time', 0)\n const width = numFlag(flags, 'width', 1280)\n const height = numFlag(flags, 'height', 720)\n const out = positionals[1] ?? outName(source, 'webp')\n\n const browser = await launchBrowser()\n try {\n const result = await renderStill(browser, {\n config,\n width,\n height,\n time,\n onPhase: (phase) => {\n r.log(`${phase}…`)\n r.event({ event: 'phase', phase })\n },\n })\n await writeFile(out, result.bytes)\n r.done(\n { out, bytes: result.bytes.length, width, height, time, mimeType: result.mimeType },\n `Wrote ${out} (${(result.bytes.length / 1024).toFixed(0)} KB, ${width}x${height} @ t=${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 = typeof config.data === 'object' && config.data !== null ? Object.keys(config.data) : []\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: (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(readFileSync(join(dir, 'package.json'), 'utf8')) 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\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 // Own version: read relative to dist (self-require is blocked by `exports`).\n try {\n const own = JSON.parse(\n readFileSync(fileURLToPath(new URL('../package.json', import.meta.url)), 'utf8'),\n ) as { version: string }\n versions['@vosjs/cli'] = own.version\n } catch {\n versions['@vosjs/cli'] = '(unknown)'\n }\n for (const name of ['@vosjs/core', '@vosjs/elements', '@vosjs/tween', 'playwright']) {\n versions[name] = packageVersion(name) ?? '(not found)'\n }\n if (r.json) r.done({ versions }, '')\n else for (const [k, v] of Object.entries(versions)) 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 cmdFetch(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const source = positionals[0]\n if (!source) throw new UsageError('vos fetch <vosId|watch-url> [--out dir]')\n const r = createReporter(flags.json === true)\n const id = parseVosId(source)\n // Attached when present so your own private programs fetch too; public and\n // unlisted programs need no credential at all.\n const key = resolveCredential()\n\n const meta = await apiJson(`/api/vos/${id}`, { key })\n if (meta.status !== 200) throw new Error(apiError(`fetch vos ${id}`, meta))\n const cfg = await apiJson(`/api/vos/${id}/config`, { key })\n if (cfg.status !== 200) throw new Error(apiError(`fetch config for ${id}`, cfg))\n\n const vosMeta = (meta.body.vos ?? {}) as Record<string, unknown>\n const slug = typeof vosMeta.slug === 'string' && vosMeta.slug ? vosMeta.slug : id\n const out = (flags.out as string) ?? slug\n await mkdir(out, { recursive: true })\n // The config is written EXACTLY as stored (params/presets included) — this\n // file round-trips back through `vos push`.\n await writeFile(join(out, 'config.json'), JSON.stringify(cfg.body.config, null, 2))\n await writeFile(join(out, 'meta.json'), JSON.stringify(vosMeta, null, 2))\n\n const title = typeof vosMeta.title === 'string' ? vosMeta.title : ''\n r.done(\n {\n out,\n id,\n slug,\n title,\n currentVersionId: vosMeta.currentVersionId ?? null,\n },\n `Wrote ${out}/config.json + meta.json (${title || id})\\n` +\n `Edit config.json, then: vos check ${out}/config.json && vos push ${out}/config.json`,\n )\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 let raw: string\n if (/^https?:\\/\\//.test(source)) {\n const res = await fetch(source)\n if (!res.ok) throw new Error(`fetch ${source} → ${res.status}`)\n raw = await res.text()\n } else {\n raw = await readFile(source, 'utf8')\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (e) {\n parsed = undefined\n if (!r.json) process.stdout.write(`error [json] ${(e as Error).message}\\n`)\n r.done({ ok: false, errors: 1, warnings: 0, issues: [{ level: 'error', source: 'json', message: (e as Error).message }] }, `${source}: 1 error`)\n return EXIT_ERROR\n }\n\n const result = runCheck(parsed)\n if (r.json) {\n r.done(\n { ok: result.ok, errors: result.errors, warnings: result.warnings, issues: result.issues },\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\nasync function cmdPush(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 push <config.json> [--vos id] [--title t] [--slug s] [--remix-of id] [--note n] [--base versionId]',\n )\n }\n const r = createReporter(flags.json === true)\n\n const parsed = JSON.parse(await readFile(source, 'utf8')) as unknown\n const check = runCheck(parsed)\n if (!check.ok || !check.config) {\n for (const i of check.issues) {\n if (i.level === 'error') r.log(`error [${i.source}] ${i.message}`)\n }\n throw new Error(`config does not validate — run: vos check ${source}`)\n }\n const config = check.config\n\n const key = resolveCredential()\n if (!key) {\n throw new Error(\n 'no credential found — set VOS_API_KEY or write the key as the first line of ' +\n '~/.config/vos/credentials (mint one at https://vos.so/app/api; a vos_rg_ remix grant works too)',\n )\n }\n\n if (flags.vos) {\n // Iterate an existing vos: add a version. --base names the version this\n // edit was made FROM and --note says what changed — both are forwarded\n // and recorded where the platform supports them.\n const vosId = parseVosId(String(flags.vos))\n const body: Record<string, unknown> = { config }\n if (flags.base) body.baseVersionId = String(flags.base)\n if (flags.note) body.note = String(flags.note)\n const res = await apiJson(`/api/vos/${vosId}/versions`, { method: 'POST', key, body })\n if (res.status === 409) {\n // The platform copy moved since --base: it answers with the changes made\n // there. Surface them — the correction path is the data path.\n const changes = Array.isArray(res.body.changes) ? res.body.changes : []\n for (const ch of changes) {\n const summary =\n typeof ch === 'object' && ch !== null && 'summary' in ch\n ? String((ch as Record<string, unknown>).summary)\n : JSON.stringify(ch)\n r.log(`platform change: ${summary}`)\n }\n r.event({ event: 'conflict', reason: res.body.error ?? 'conflict', changes })\n throw new Error(\n `version base is stale — the platform copy changed (${changes.length} edit${changes.length === 1 ? 's' : ''} above). ` +\n `Fetch, rebase your edit, and push again: vos fetch ${vosId}`,\n )\n }\n if (res.status !== 201) throw new Error(apiError(`push version to ${vosId}`, res))\n const version = (res.body.version ?? {}) as Record<string, unknown>\n const watchUrl = `${PLATFORM_ORIGIN}/vos/${vosId}`\n const studioUrl = `${PLATFORM_ORIGIN}/studio?vos=${vosId}`\n r.done(\n {\n id: vosId,\n versionId: version.id ?? null,\n versionNumber: version.versionNumber ?? null,\n watchUrl,\n studioUrl,\n },\n `Pushed version ${String(version.versionNumber ?? '?')} of ${vosId}\\n` +\n ` watch: ${watchUrl}\\n studio: ${studioUrl}`,\n )\n return EXIT_OK\n }\n\n // Create a new PRIVATE vos. Lineage comes from meta.json (written by\n // `vos fetch` beside the config) or --remix-of; the platform validates it.\n let meta: Record<string, unknown> = {}\n try {\n meta = JSON.parse(await readFile(join(dirname(source), 'meta.json'), 'utf8')) as Record<\n string,\n unknown\n >\n } catch {\n // no meta.json — fine, push without lineage\n }\n const remixOfId = flags['remix-of']\n ? String(flags['remix-of'])\n : typeof meta.id === 'string'\n ? meta.id\n : undefined\n const fallbackTitle =\n typeof meta.title === 'string' && meta.title\n ? `${meta.title} remix`\n : basename(source).replace(/\\.json$/i, '') || 'vos remix'\n const title = ((flags.title as string) ?? fallbackTitle).slice(0, 100)\n const slugGiven = typeof flags.slug === 'string'\n const baseSlug = slugGiven ? (flags.slug as string) : deriveSlug(title)\n\n for (let attempt = 0; ; attempt++) {\n const slug = attempt === 0 ? baseSlug : `${baseSlug}-${attempt + 1}`.slice(0, 50)\n const body: Record<string, unknown> = {\n title,\n slug,\n visibility: 'private',\n config,\n }\n if (remixOfId) body.remixOfId = remixOfId\n const res = await apiJson('/api/vos', { method: 'POST', key, body })\n if (res.status === 409 && !slugGiven && attempt < 3) {\n r.log(`slug \"${slug}\" is taken — retrying`)\n continue\n }\n if (res.status !== 201) throw new Error(apiError('push vos', res))\n const created = (res.body.vos ?? {}) as Record<string, unknown>\n const id = String(created.id ?? '')\n const watchUrl = `${PLATFORM_ORIGIN}/vos/${id}`\n const studioUrl = `${PLATFORM_ORIGIN}/studio?vos=${id}`\n r.done(\n {\n id,\n slug: created.slug ?? slug,\n title,\n visibility: created.visibility ?? 'private',\n remixOfId: remixOfId ?? null,\n currentVersionId: created.currentVersionId ?? null,\n watchUrl,\n studioUrl,\n },\n `Created private vos ${id} (${title})\\n` +\n ` watch: ${watchUrl}\\n studio: ${studioUrl}\\n` +\n `Iterate with: vos push ${source} --vos ${id}`,\n )\n return EXIT_OK\n }\n}\n\n// The take pipeline's verbs live in @vosso/cli (published; previously\n// @vosso/voila-cli, kept as an install fallback during the transition).\n// The delegation contract is its `run(argv)` export.\nconst TAKE_VERBS = new Set(['create', 'record', 'plan', 'frames', 'open', 'validate'])\n\nasync function delegateTake(argv: string[], viaAlias = false): Promise<number> {\n for (const name of ['@vosso/cli', '@vosso/voila-cli']) {\n let mod: { run?: (argv: string[]) => Promise<number> }\n try {\n mod = (await import(name as string)) as typeof mod\n } catch {\n continue\n }\n if (typeof mod.run !== 'function') continue\n if (viaAlias && argv[0]) {\n process.stderr.write(`note: \"vos voila ${argv[0]}\" is now \"vos ${argv[0]}\".\\n`)\n }\n return await mod.run(argv)\n }\n process.stderr.write(\n 'The take pipeline (screen recordings in, product video out) ships separately.\\n' +\n ' npm i -D @vosso/cli\\n' +\n `then re-run: vos ${argv.join(' ')}\\n`,\n )\n return EXIT_ERROR\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 process.stdout.write(HELP)\n return cmd ? EXIT_OK : EXIT_USAGE\n }\n if (cmd === '--version') return cmdVersions(['--json'])\n if (TAKE_VERBS.has(cmd)) return delegateTake([cmd, ...rest])\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 'fetch':\n return cmdFetch(rest)\n case 'check':\n return cmdCheck(rest)\n case 'push':\n return cmdPush(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 delegateTake(rest, true)\n default:\n throw new UsageError(`unknown command \"${cmd}\" — run vos help`)\n }\n}\n\nmain()\n .then((code) => process.exit(code))\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(`error: ${e instanceof Error ? e.message : String(e)}\\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 */\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) 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 { lintVosConfig, lintVosDialect } from '@vosjs/core/lint'\n\nexport interface CheckIssue {\n level: 'error' | 'warn'\n source: 'schema' | 'syntax' | 'compile' | 'determinism' | 'dialect' | 'shape'\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({ level: 'error', source: 'shape', message: 'not a JSON object' })\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 (typeof obj.config === 'object' && obj.config !== null && !('createTimeline' in obj)) {\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 !== CURRENT_CONFIG_VERSION) {\n issues.push({\n level: 'warn',\n source: 'shape',\n message: `config is v${String(version ?? 1)} — 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([...Object.keys(vosConfigJsonSchema.shape), ...PLATFORM_EXTRA_KEYS])\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 // 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 ['setup', 'createContent', 'createTimeline', 'onFrame'] 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\n return finish(migrated)\n}\n","/**\n * vos.so platform client — the pieces of fetch/push that talk HTTP.\n *\n * Contract notes (mirrored at https://vos.so/llms-remix.txt):\n * - public/unlisted programs read with no auth; writes ride a bearer key\n * - credentials resolve env → ~/.config/vos/credentials, and are NEVER\n * printed — not in logs, not in errors, not in NDJSON events\n * - pushed configs travel as the RAW object (params/presets preserved);\n * the platform validates and compiles server-side\n */\nimport { readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { UsageError } from './args'\n\nexport const PLATFORM_ORIGIN = process.env.VOS_ORIGIN ?? 'https://vos.so'\n\n/**\n * Accepts a bare vos id, a watch URL (vos.so/vos/{id}), an embed URL\n * (/embed/vos/{id}), or a studio/stage URL (?vos={id}).\n */\nexport function parseVosId(input: string): string {\n if (!/^https?:\\/\\//.test(input)) {\n if (/^[A-Za-z0-9_-]+$/.test(input)) return input\n throw new UsageError(`\"${input}\" is not a vos id or URL`)\n }\n let url: URL\n try {\n url = new URL(input)\n } catch {\n throw new UsageError(`\"${input}\" is not a valid URL`)\n }\n const query = url.searchParams.get('vos')\n if (query) return query\n const path = url.pathname.match(/\\/vos\\/([A-Za-z0-9_-]+)/)\n if (path) return path[1]\n throw new UsageError(`could not find a vos id in ${input} — expected /vos/{id} or ?vos={id}`)\n}\n\n/**\n * Resolution order (llms-remix.txt): VOS_API_KEY env, then the first line of\n * ~/.config/vos/credentials. Returns null when neither exists — callers\n * decide whether the operation needs auth.\n */\nexport function resolveCredential(): string | null {\n const env = process.env.VOS_API_KEY?.trim()\n if (env) return env\n try {\n const first = readFileSync(join(homedir(), '.config', 'vos', 'credentials'), 'utf8')\n .split('\\n')[0]\n .trim()\n return first || null\n } catch {\n return null\n }\n}\n\nexport function deriveSlug(title: string): string {\n return (\n title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 50)\n .replace(/-+$/, '') || 'remix'\n )\n}\n\nexport interface ApiResult {\n status: number\n body: Record<string, unknown>\n}\n\nexport async function apiJson(\n path: string,\n init: { method?: string; key?: string | null; body?: unknown } = {},\n): Promise<ApiResult> {\n const headers: Record<string, string> = { accept: 'application/json' }\n if (init.key) headers.authorization = `Bearer ${init.key}`\n if (init.body !== undefined) headers['content-type'] = 'application/json'\n const res = await fetch(`${PLATFORM_ORIGIN}${path}`, {\n method: init.method ?? 'GET',\n headers,\n body: init.body === undefined ? undefined : JSON.stringify(init.body),\n })\n let body: Record<string, unknown> = {}\n try {\n body = (await res.json()) as Record<string, unknown>\n } catch {\n // non-JSON error bodies stay {}\n }\n return { status: res.status, body }\n}\n\n/** Human-readable error line for a failed platform response. Never echoes credentials. */\nexport function apiError(what: string, r: ApiResult): string {\n const detail =\n typeof r.body.error === 'string'\n ? r.body.error\n : r.body.details !== undefined\n ? JSON.stringify(r.body.details)\n : ''\n const hint =\n r.status === 401\n ? ' (set VOS_API_KEY or write ~/.config/vos/credentials — mint a key at https://vos.so/app/api)'\n : ''\n return `${what} → ${r.status}${detail ? `: ${detail}` : ''}${hint}`\n}\n"],"mappings":";;;;;;;;;;;;;;;AAAA,SAAS,OAAO,UAAU,iBAAiB;AAC3C,SAAS,YAAY,gBAAAA,qBAAoB;AACzC,SAAS,UAAU,SAAS,QAAAC,aAAY;AACxC,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;;;ACEvB,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,KAAM,SAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,IAAI,CAAC,CAAC;AAAA,CAAI;AAAA,UAC1E,SAAQ,OAAO,MAAM,GAAG,SAAS;AAAA,CAAI;AAAA,IAC5C;AAAA,EACF;AACF;;;AC9BA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,eAAe,sBAAsB;AAkB9C,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,EAAE,OAAO,SAAS,QAAQ,SAAS,SAAS,oBAAoB,CAAC;AAC7E,WAAO,OAAO,IAAI;AAAA,EACpB;AAGA,MAAI,MAAM;AACV,MAAI,OAAO,IAAI,WAAW,YAAY,IAAI,WAAW,QAAQ,EAAE,oBAAoB,MAAM;AACvF,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,wBAAwB;AACtC,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAS,cAAc,OAAO,WAAW,CAAC,CAAC,wBAAmB,sBAAsB;AAAA,IACtF,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,CAAC,GAAG,OAAO,KAAK,oBAAoB,KAAK,GAAG,GAAG,mBAAmB,CAAC;AACzF,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;AAKA,MAAI,eAAe;AACnB,aAAW,OAAO,CAAC,SAAS,iBAAiB,kBAAkB,SAAS,GAAY;AAClF,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;AAEA,SAAO,OAAO,QAAQ;AACxB;;;AC5IA,SAAS,oBAAoB;AAC7B,SAAS,eAAe;AACxB,SAAS,YAAY;AAGd,IAAM,kBAAkB,QAAQ,IAAI,cAAc;AAMlD,SAAS,WAAW,OAAuB;AAChD,MAAI,CAAC,eAAe,KAAK,KAAK,GAAG;AAC/B,QAAI,mBAAmB,KAAK,KAAK,EAAG,QAAO;AAC3C,UAAM,IAAI,WAAW,IAAI,KAAK,0BAA0B;AAAA,EAC1D;AACA,MAAI;AACJ,MAAI;AACF,UAAM,IAAI,IAAI,KAAK;AAAA,EACrB,QAAQ;AACN,UAAM,IAAI,WAAW,IAAI,KAAK,sBAAsB;AAAA,EACtD;AACA,QAAM,QAAQ,IAAI,aAAa,IAAI,KAAK;AACxC,MAAI,MAAO,QAAO;AAClB,QAAM,OAAO,IAAI,SAAS,MAAM,yBAAyB;AACzD,MAAI,KAAM,QAAO,KAAK,CAAC;AACvB,QAAM,IAAI,WAAW,8BAA8B,KAAK,yCAAoC;AAC9F;AAOO,SAAS,oBAAmC;AACjD,QAAM,MAAM,QAAQ,IAAI,aAAa,KAAK;AAC1C,MAAI,IAAK,QAAO;AAChB,MAAI;AACF,UAAM,QAAQ,aAAa,KAAK,QAAQ,GAAG,WAAW,OAAO,aAAa,GAAG,MAAM,EAChF,MAAM,IAAI,EAAE,CAAC,EACb,KAAK;AACR,WAAO,SAAS;AAAA,EAClB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,WAAW,OAAuB;AAChD,SACE,MACG,YAAY,EACZ,QAAQ,eAAe,GAAG,EAC1B,QAAQ,YAAY,EAAE,EACtB,MAAM,GAAG,EAAE,EACX,QAAQ,OAAO,EAAE,KAAK;AAE7B;AAOA,eAAsB,QACpB,MACA,OAAiE,CAAC,GAC9C;AACpB,QAAM,UAAkC,EAAE,QAAQ,mBAAmB;AACrE,MAAI,KAAK,IAAK,SAAQ,gBAAgB,UAAU,KAAK,GAAG;AACxD,MAAI,KAAK,SAAS,OAAW,SAAQ,cAAc,IAAI;AACvD,QAAM,MAAM,MAAM,MAAM,GAAG,eAAe,GAAG,IAAI,IAAI;AAAA,IACnD,QAAQ,KAAK,UAAU;AAAA,IACvB;AAAA,IACA,MAAM,KAAK,SAAS,SAAY,SAAY,KAAK,UAAU,KAAK,IAAI;AAAA,EACtE,CAAC;AACD,MAAI,OAAgC,CAAC;AACrC,MAAI;AACF,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB,QAAQ;AAAA,EAER;AACA,SAAO,EAAE,QAAQ,IAAI,QAAQ,KAAK;AACpC;AAGO,SAAS,SAAS,MAAc,GAAsB;AAC3D,QAAM,SACJ,OAAO,EAAE,KAAK,UAAU,WACpB,EAAE,KAAK,QACP,EAAE,KAAK,YAAY,SACjB,KAAK,UAAU,EAAE,KAAK,OAAO,IAC7B;AACR,QAAM,OACJ,EAAE,WAAW,MACT,sGACA;AACN,SAAO,GAAG,IAAI,WAAM,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,KAAK,EAAE,GAAG,IAAI;AACnE;;;AHhFA,IAAM,gBAAgB,oBAAI,IAAI,CAAC,QAAQ,QAAQ,SAAS,CAAC;AAEzD,IAAM,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuCb,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;AAIxD,QAAM,QAAQ,KAAK,KAAK,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,CAAC;AACjD,MAAI,SAAS,WAAWC,MAAK,OAAO,UAAU,CAAC,GAAG;AAChD,WAAO,aAAa,CAAC,UAAU,GAAG,IAAI,CAAC;AAAA,EACzC;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,SAAU,MAAM,UAAqB;AAC3C,MAAI,WAAW,UAAU,WAAW,MAAO,OAAM,IAAI,WAAW,8BAA8B;AAE9F,QAAM,EAAE,QAAQ,SAAS,IAAI,MAAM,cAAc,MAAM;AACvD,aAAW,KAAK,SAAU,GAAE,IAAI,SAAS,CAAC,EAAE;AAC5C,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;AAEpD,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,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,MAAE;AAAA,MACA,EAAE,KAAK,OAAO,OAAO,MAAM,QAAQ,OAAO,QAAQ,KAAK,UAAU,OAAO;AAAA,MACxE,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,OAAQ,OAAM,IAAI,WAAW,wCAAwC;AAC1E,QAAM,IAAI,eAAe,MAAM,SAAS,IAAI;AAE5C,QAAM,EAAE,QAAQ,SAAS,IAAI,MAAM,cAAc,MAAM;AACvD,aAAW,KAAK,SAAU,GAAE,IAAI,SAAS,CAAC,EAAE;AAC5C,QAAM,OAAO,QAAQ,OAAO,QAAQ,CAAC;AACrC,QAAM,QAAQ,QAAQ,OAAO,SAAS,IAAI;AAC1C,QAAM,SAAS,QAAQ,OAAO,UAAU,GAAG;AAC3C,QAAM,MAAM,YAAY,CAAC,KAAK,QAAQ,QAAQ,MAAM;AAEpD,QAAM,UAAU,MAAM,cAAc;AACpC,MAAI;AACF,UAAM,SAAS,MAAM,YAAY,SAAS;AAAA,MACxC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,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,MAAE;AAAA,MACA,EAAE,KAAK,OAAO,OAAO,MAAM,QAAQ,OAAO,QAAQ,MAAM,UAAU,OAAO,SAAS;AAAA,MAClF,SAAS,GAAG,MAAM,OAAO,MAAM,SAAS,MAAM,QAAQ,CAAC,CAAC,QAAQ,KAAK,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC7F;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,OAAO,OAAO,OAAO,SAAS,YAAY,OAAO,SAAS,OAAO,OAAO,KAAK,OAAO,IAAI,IAAI,CAAC;AACnG,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,QAAS,OAAO,QAAgD,UAAU;AAAA,IAC1E;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,MAAMC,cAAaF,MAAK,KAAK,cAAc,GAAG,MAAM,CAAC;AAItE,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,eAAe,YAAY,MAAiC;AAC1D,QAAM,EAAE,MAAM,IAAI,UAAU,MAAM,aAAa;AAC/C,QAAM,IAAI,eAAe,MAAM,SAAS,IAAI;AAC5C,QAAM,WAAmC,CAAC;AAE1C,MAAI;AACF,UAAM,MAAM,KAAK;AAAA,MACfE,cAAa,cAAc,IAAI,IAAI,mBAAmB,YAAY,GAAG,CAAC,GAAG,MAAM;AAAA,IACjF;AACA,aAAS,YAAY,IAAI,IAAI;AAAA,EAC/B,QAAQ;AACN,aAAS,YAAY,IAAI;AAAA,EAC3B;AACA,aAAW,QAAQ,CAAC,eAAe,mBAAmB,gBAAgB,YAAY,GAAG;AACnF,aAAS,IAAI,IAAI,eAAe,IAAI,KAAK;AAAA,EAC3C;AACA,MAAI,EAAE,KAAM,GAAE,KAAK,EAAE,SAAS,GAAG,EAAE;AAAA,MAC9B,YAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,QAAQ,EAAG,SAAQ,OAAO,MAAM,GAAG,CAAC,IAAI,CAAC;AAAA,CAAI;AACtF,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,yCAAyC;AAC3E,QAAM,IAAI,eAAe,MAAM,SAAS,IAAI;AAC5C,QAAM,KAAK,WAAW,MAAM;AAG5B,QAAM,MAAM,kBAAkB;AAE9B,QAAM,OAAO,MAAM,QAAQ,YAAY,EAAE,IAAI,EAAE,IAAI,CAAC;AACpD,MAAI,KAAK,WAAW,IAAK,OAAM,IAAI,MAAM,SAAS,aAAa,EAAE,IAAI,IAAI,CAAC;AAC1E,QAAM,MAAM,MAAM,QAAQ,YAAY,EAAE,WAAW,EAAE,IAAI,CAAC;AAC1D,MAAI,IAAI,WAAW,IAAK,OAAM,IAAI,MAAM,SAAS,oBAAoB,EAAE,IAAI,GAAG,CAAC;AAE/E,QAAM,UAAW,KAAK,KAAK,OAAO,CAAC;AACnC,QAAM,OAAO,OAAO,QAAQ,SAAS,YAAY,QAAQ,OAAO,QAAQ,OAAO;AAC/E,QAAM,MAAO,MAAM,OAAkB;AACrC,QAAM,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AAGpC,QAAM,UAAUF,MAAK,KAAK,aAAa,GAAG,KAAK,UAAU,IAAI,KAAK,QAAQ,MAAM,CAAC,CAAC;AAClF,QAAM,UAAUA,MAAK,KAAK,WAAW,GAAG,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAExE,QAAM,QAAQ,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ;AAClE,IAAE;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,kBAAkB,QAAQ,oBAAoB;AAAA,IAChD;AAAA,IACA,SAAS,GAAG,6BAA6B,SAAS,EAAE;AAAA,oCACb,GAAG,4BAA4B,GAAG;AAAA,EAC3E;AACA,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;AAE5C,MAAI;AACJ,MAAI,eAAe,KAAK,MAAM,GAAG;AAC/B,UAAM,MAAM,MAAM,MAAM,MAAM;AAC9B,QAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,SAAS,MAAM,WAAM,IAAI,MAAM,EAAE;AAC9D,UAAM,MAAM,IAAI,KAAK;AAAA,EACvB,OAAO;AACL,UAAM,MAAM,SAAS,QAAQ,MAAM;AAAA,EACrC;AACA,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,GAAG;AAAA,EACzB,SAAS,GAAG;AACV,aAAS;AACT,QAAI,CAAC,EAAE,KAAM,SAAQ,OAAO,MAAM,gBAAiB,EAAY,OAAO;AAAA,CAAI;AAC1E,MAAE,KAAK,EAAE,IAAI,OAAO,QAAQ,GAAG,UAAU,GAAG,QAAQ,CAAC,EAAE,OAAO,SAAS,QAAQ,QAAQ,SAAU,EAAY,QAAQ,CAAC,EAAE,GAAG,GAAG,MAAM,WAAW;AAC/I,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,SAAS,MAAM;AAC9B,MAAI,EAAE,MAAM;AACV,MAAE;AAAA,MACA,EAAE,IAAI,OAAO,IAAI,QAAQ,OAAO,QAAQ,UAAU,OAAO,UAAU,QAAQ,OAAO,OAAO;AAAA,MACzF;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;AAEA,eAAe,QAAQ,MAAiC;AACtD,QAAM,EAAE,aAAa,MAAM,IAAI,UAAU,MAAM,aAAa;AAC5D,QAAM,SAAS,YAAY,CAAC;AAC5B,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,QAAM,IAAI,eAAe,MAAM,SAAS,IAAI;AAE5C,QAAM,SAAS,KAAK,MAAM,MAAM,SAAS,QAAQ,MAAM,CAAC;AACxD,QAAM,QAAQ,SAAS,MAAM;AAC7B,MAAI,CAAC,MAAM,MAAM,CAAC,MAAM,QAAQ;AAC9B,eAAW,KAAK,MAAM,QAAQ;AAC5B,UAAI,EAAE,UAAU,QAAS,GAAE,IAAI,UAAU,EAAE,MAAM,KAAK,EAAE,OAAO,EAAE;AAAA,IACnE;AACA,UAAM,IAAI,MAAM,kDAA6C,MAAM,EAAE;AAAA,EACvE;AACA,QAAM,SAAS,MAAM;AAErB,QAAM,MAAM,kBAAkB;AAC9B,MAAI,CAAC,KAAK;AACR,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AAEA,MAAI,MAAM,KAAK;AAIb,UAAM,QAAQ,WAAW,OAAO,MAAM,GAAG,CAAC;AAC1C,UAAM,OAAgC,EAAE,OAAO;AAC/C,QAAI,MAAM,KAAM,MAAK,gBAAgB,OAAO,MAAM,IAAI;AACtD,QAAI,MAAM,KAAM,MAAK,OAAO,OAAO,MAAM,IAAI;AAC7C,UAAM,MAAM,MAAM,QAAQ,YAAY,KAAK,aAAa,EAAE,QAAQ,QAAQ,KAAK,KAAK,CAAC;AACrF,QAAI,IAAI,WAAW,KAAK;AAGtB,YAAM,UAAU,MAAM,QAAQ,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,UAAU,CAAC;AACtE,iBAAW,MAAM,SAAS;AACxB,cAAM,UACJ,OAAO,OAAO,YAAY,OAAO,QAAQ,aAAa,KAClD,OAAQ,GAA+B,OAAO,IAC9C,KAAK,UAAU,EAAE;AACvB,UAAE,IAAI,oBAAoB,OAAO,EAAE;AAAA,MACrC;AACA,QAAE,MAAM,EAAE,OAAO,YAAY,QAAQ,IAAI,KAAK,SAAS,YAAY,QAAQ,CAAC;AAC5E,YAAM,IAAI;AAAA,QACR,2DAAsD,QAAQ,MAAM,QAAQ,QAAQ,WAAW,IAAI,MAAM,EAAE,+DACnD,KAAK;AAAA,MAC/D;AAAA,IACF;AACA,QAAI,IAAI,WAAW,IAAK,OAAM,IAAI,MAAM,SAAS,mBAAmB,KAAK,IAAI,GAAG,CAAC;AACjF,UAAM,UAAW,IAAI,KAAK,WAAW,CAAC;AACtC,UAAM,WAAW,GAAG,eAAe,QAAQ,KAAK;AAChD,UAAM,YAAY,GAAG,eAAe,eAAe,KAAK;AACxD,MAAE;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,WAAW,QAAQ,MAAM;AAAA,QACzB,eAAe,QAAQ,iBAAiB;AAAA,QACxC;AAAA,QACA;AAAA,MACF;AAAA,MACA,kBAAkB,OAAO,QAAQ,iBAAiB,GAAG,CAAC,OAAO,KAAK;AAAA,YACnD,QAAQ;AAAA,YAAe,SAAS;AAAA,IACjD;AACA,WAAO;AAAA,EACT;AAIA,MAAI,OAAgC,CAAC;AACrC,MAAI;AACF,WAAO,KAAK,MAAM,MAAM,SAASA,MAAK,QAAQ,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;AAAA,EAI9E,QAAQ;AAAA,EAER;AACA,QAAM,YAAY,MAAM,UAAU,IAC9B,OAAO,MAAM,UAAU,CAAC,IACxB,OAAO,KAAK,OAAO,WACjB,KAAK,KACL;AACN,QAAM,gBACJ,OAAO,KAAK,UAAU,YAAY,KAAK,QACnC,GAAG,KAAK,KAAK,WACb,SAAS,MAAM,EAAE,QAAQ,YAAY,EAAE,KAAK;AAClD,QAAM,SAAU,MAAM,SAAoB,eAAe,MAAM,GAAG,GAAG;AACrE,QAAM,YAAY,OAAO,MAAM,SAAS;AACxC,QAAM,WAAW,YAAa,MAAM,OAAkB,WAAW,KAAK;AAEtE,WAAS,UAAU,KAAK,WAAW;AACjC,UAAM,OAAO,YAAY,IAAI,WAAW,GAAG,QAAQ,IAAI,UAAU,CAAC,GAAG,MAAM,GAAG,EAAE;AAChF,UAAM,OAAgC;AAAA,MACpC;AAAA,MACA;AAAA,MACA,YAAY;AAAA,MACZ;AAAA,IACF;AACA,QAAI,UAAW,MAAK,YAAY;AAChC,UAAM,MAAM,MAAM,QAAQ,YAAY,EAAE,QAAQ,QAAQ,KAAK,KAAK,CAAC;AACnE,QAAI,IAAI,WAAW,OAAO,CAAC,aAAa,UAAU,GAAG;AACnD,QAAE,IAAI,SAAS,IAAI,4BAAuB;AAC1C;AAAA,IACF;AACA,QAAI,IAAI,WAAW,IAAK,OAAM,IAAI,MAAM,SAAS,YAAY,GAAG,CAAC;AACjE,UAAM,UAAW,IAAI,KAAK,OAAO,CAAC;AAClC,UAAM,KAAK,OAAO,QAAQ,MAAM,EAAE;AAClC,UAAM,WAAW,GAAG,eAAe,QAAQ,EAAE;AAC7C,UAAM,YAAY,GAAG,eAAe,eAAe,EAAE;AACrD,MAAE;AAAA,MACA;AAAA,QACE;AAAA,QACA,MAAM,QAAQ,QAAQ;AAAA,QACtB;AAAA,QACA,YAAY,QAAQ,cAAc;AAAA,QAClC,WAAW,aAAa;AAAA,QACxB,kBAAkB,QAAQ,oBAAoB;AAAA,QAC9C;AAAA,QACA;AAAA,MACF;AAAA,MACA,uBAAuB,EAAE,KAAK,KAAK;AAAA,YACpB,QAAQ;AAAA,YAAe,SAAS;AAAA,yBACnB,MAAM,UAAU,EAAE;AAAA,IAChD;AACA,WAAO;AAAA,EACT;AACF;AAKA,IAAM,aAAa,oBAAI,IAAI,CAAC,UAAU,UAAU,QAAQ,UAAU,QAAQ,UAAU,CAAC;AAErF,eAAe,aAAa,MAAgB,WAAW,OAAwB;AAC7E,aAAW,QAAQ,CAAC,cAAc,kBAAkB,GAAG;AACrD,QAAI;AACJ,QAAI;AACF,YAAO,MAAM,OAAO;AAAA,IACtB,QAAQ;AACN;AAAA,IACF;AACA,QAAI,OAAO,IAAI,QAAQ,WAAY;AACnC,QAAI,YAAY,KAAK,CAAC,GAAG;AACvB,cAAQ,OAAO,MAAM,oBAAoB,KAAK,CAAC,CAAC,iBAAiB,KAAK,CAAC,CAAC;AAAA,CAAM;AAAA,IAChF;AACA,WAAO,MAAM,IAAI,IAAI,IAAI;AAAA,EAC3B;AACA,UAAQ,OAAO;AAAA,IACb;AAAA;AAAA,mBAEsB,KAAK,KAAK,GAAG,CAAC;AAAA;AAAA,EACtC;AACA,SAAO;AACT;AAEA,eAAe,OAAwB;AACrC,QAAM,CAAC,KAAK,GAAG,IAAI,IAAI,QAAQ,KAAK,MAAM,CAAC;AAC3C,MAAI,CAAC,OAAO,QAAQ,UAAU,QAAQ,YAAY,QAAQ,MAAM;AAC9D,YAAQ,OAAO,MAAM,IAAI;AACzB,WAAO,MAAM,UAAU;AAAA,EACzB;AACA,MAAI,QAAQ,YAAa,QAAO,YAAY,CAAC,QAAQ,CAAC;AACtD,MAAI,WAAW,IAAI,GAAG,EAAG,QAAO,aAAa,CAAC,KAAK,GAAG,IAAI,CAAC;AAC3D,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,IACtB,KAAK;AACH,aAAO,SAAS,IAAI;AAAA,IACtB,KAAK;AACH,aAAO,QAAQ,IAAI;AAAA;AAAA;AAAA,IAGrB,KAAK;AACH,aAAO,aAAa,MAAM,IAAI;AAAA,IAChC;AACE,YAAM,IAAI,WAAW,oBAAoB,GAAG,uBAAkB;AAAA,EAClE;AACF;AAEA,KAAK,EACF,KAAK,CAAC,SAAS,QAAQ,KAAK,IAAI,CAAC,EACjC,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,MAAM,UAAU,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,CAAI;AAC7E,UAAQ,KAAK,UAAU;AACzB,CAAC;","names":["readFileSync","join","join","require","readFileSync"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vosjs/cli",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Command line for the vos programmatic video engine — render deterministic videos and stills from vos configs, headlessly, from your terminal or an AI agent.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -42,9 +42,9 @@
42
42
  "sideEffects": false,
43
43
  "dependencies": {
44
44
  "playwright": "^1.49.0",
45
+ "@vosjs/tween": "^0.7.2",
45
46
  "@vosjs/elements": "^0.3.1",
46
- "@vosjs/core": "^0.10.0",
47
- "@vosjs/tween": "^0.7.2"
47
+ "@vosjs/core": "^0.10.0"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@types/node": "^22",