@vosjs/cli 0.6.4 → 0.7.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
@@ -13,32 +13,23 @@ npx vos render animation.json out.webm
13
13
  ## Commands
14
14
 
15
15
  ```bash
16
- vos render <config.json|url|take> [out] # config → video; a take directory renders via the take pipeline
16
+ vos render <config.json|url|take> [out] # config → video; a take directory renders via the plugin
17
17
  vos still <config.json|url> [out] # config → single frame (WebP)
18
18
  vos info <config.json|url> # inspect a config
19
+ vos check <config.json|url> # migrate → schema → syntax → compile → determinism/dialect lints, all local
19
20
  vos preview <config.json|url> # serve a local playback page
20
- vos versions # installed @vosjs/* versions
21
-
22
- # Take pipeline — screen recordings in, product video out (npm i -D @vosso/cli)
23
- vos create --actions actions.json [out.webm] [--strict] # record + plan + render, one shot
24
- vos record --actions actions.json [--out take] [--strict]
25
- vos plan <take> [--fresh]
26
- vos frames <take> [--at-zooms | --frame <t> --size WxH]
27
- vos open <take>
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|take> [--vos id] [--title t] [--slug s] [--remix-of id] [--note n] [--label l] [--base versionId] [--overrides id,id]
34
- vos pull [dir|take] [--vos id] [--since versionId] [--check] # what changed on vos.so since your base; syncs config + base
21
+ vos versions # installed @vosjs/* (and plugin) versions
35
22
  ```
36
23
 
37
- 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.
24
+ That is the whole engine surface: local, deterministic, no account, no auth this package knows nothing about any hosting platform. Everything else the take pipeline (screen recordings in, product video out: `create` / `record` / `plan` / `frames` / `open` / `validate`) and the vos.so platform verbs (`fetch` / `push` / `pull` / `login`) ships as a separately installed plugin:
38
25
 
39
- The platform verbs implement the iteration loop of 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. A directory that has fetched or pushed TRACKS its vos through `meta.json`, so `--base` defaults to the version you actually edited from: a push against a moved head is rejected with the attributed, typed changelog of what changed there, and `vos pull` brings those changes down — versions with origin, label, note and a semantic summary, plus the `protected` set of human-edited nodes (keep their values unless the user asked; `--overrides` is the explicit consent). The previous local copy survives as `config.backup.json`. Take directories (recognized by `doc.json`) push and pull through the take pipeline in `@vosso/cli` automatically. `VOS_ORIGIN` overrides the platform origin for self-hosted or local development.
26
+ ```bash
27
+ npm i -D @vosso/vos-plugin
28
+ ```
29
+
30
+ Any verb this CLI does not own is forwarded to the plugin (its `run(argv)` export is the contract; the earlier package names `@vosso/cli` and `@vosso/voila-cli` still resolve as fallbacks, and `vos voila <verb>` keeps working as a hidden alias for existing scripts). Installed plugin verbs appear in `vos help` via the plugin's manifest, and run as plain `vos <verb>` — one binary either way. `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. The plugin's verbs and the vos.so contracts are documented at [vos.so/llms.txt](https://vos.so/llms.txt).
40
31
 
41
- `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.
32
+ `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. `vos check` runs the full local validation pipeline — the same compiler a hosted push runs server-side, so a clean check is a config that will compile anywhere.
42
33
 
43
34
  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.
44
35
 
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 { mkdir, readFile, writeFile } from "fs/promises";
17
- import { existsSync, readFileSync as readFileSync2 } from "fs";
18
- import { basename, dirname, join as join2 } from "path";
16
+ import { readFile, writeFile } from "fs/promises";
17
+ import { existsSync, readFileSync } from "fs";
18
+ import { basename, dirname, join } from "path";
19
19
  import { createServer } from "http";
20
20
  import { createRequire } from "module";
21
21
  import { fileURLToPath } from "url";
@@ -177,128 +177,27 @@ function runCheck(parsed) {
177
177
  return finish(migrated);
178
178
  }
179
179
 
180
- // src/platform.ts
181
- import { readFileSync, writeFileSync } from "fs";
182
- import { homedir } from "os";
183
- import { join } from "path";
184
- var PLATFORM_ORIGIN = process.env.VOS_ORIGIN ?? "https://vos.so";
185
- function parseVosId(input) {
186
- if (!/^https?:\/\//.test(input)) {
187
- if (/^[A-Za-z0-9_-]+$/.test(input)) return input;
188
- throw new UsageError(`"${input}" is not a vos id or URL`);
189
- }
190
- let url;
191
- try {
192
- url = new URL(input);
193
- } catch {
194
- throw new UsageError(`"${input}" is not a valid URL`);
195
- }
196
- const query = url.searchParams.get("vos");
197
- if (query) return query;
198
- const path = url.pathname.match(/\/vos\/([A-Za-z0-9_-]+)/);
199
- if (path) return path[1];
200
- throw new UsageError(`could not find a vos id in ${input} \u2014 expected /vos/{id} or ?vos={id}`);
201
- }
202
- function resolveCredential() {
203
- const env = process.env.VOS_API_KEY?.trim();
204
- if (env) return env;
205
- try {
206
- const first = readFileSync(join(homedir(), ".config", "vos", "credentials"), "utf8").split("\n")[0].trim();
207
- return first || null;
208
- } catch {
209
- return null;
210
- }
211
- }
212
- function deriveSlug(title) {
213
- return title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 50).replace(/-+$/, "") || "remix";
214
- }
215
- async function apiJson(path, init = {}) {
216
- const headers = { accept: "application/json" };
217
- if (init.key) headers.authorization = `Bearer ${init.key}`;
218
- if (init.body !== void 0) headers["content-type"] = "application/json";
219
- const res = await fetch(`${PLATFORM_ORIGIN}${path}`, {
220
- method: init.method ?? "GET",
221
- headers,
222
- body: init.body === void 0 ? void 0 : JSON.stringify(init.body)
223
- });
224
- let body = {};
225
- try {
226
- body = await res.json();
227
- } catch {
228
- }
229
- return { status: res.status, body };
230
- }
231
- function apiError(what, r) {
232
- const detail = typeof r.body.error === "string" ? r.body.error : r.body.details !== void 0 ? JSON.stringify(r.body.details) : "";
233
- const hint = r.status === 401 ? " (set VOS_API_KEY or write ~/.config/vos/credentials \u2014 mint a key at https://vos.so/app/api)" : "";
234
- return `${what} \u2192 ${r.status}${detail ? `: ${detail}` : ""}${hint}`;
235
- }
236
- function readMeta(dir) {
237
- try {
238
- return JSON.parse(readFileSync(join(dir, "meta.json"), "utf8"));
239
- } catch {
240
- return null;
241
- }
242
- }
243
- function writeMeta(dir, patch) {
244
- const merged = { ...readMeta(dir) ?? {}, ...patch };
245
- writeFileSync(join(dir, "meta.json"), JSON.stringify(merged, null, 2));
246
- }
247
- function formatChanges(changes) {
248
- const lines = [];
249
- for (const ch of changes) {
250
- const label = ch.label ? ` \xB7 ${ch.label}` : "";
251
- lines.push(
252
- `v${String(ch.versionNumber ?? "?")} (${ch.origin ?? "unknown"}${label}): ${ch.summary ?? ""}`
253
- );
254
- if (ch.note) lines.push(` note: ${ch.note}`);
255
- }
256
- return lines;
257
- }
258
-
259
180
  // src/cli.ts
260
- var BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["json", "help", "version", "check"]);
261
- var HELP = `vos \u2014 command line for the vos programmatic video engine (https://vos.so)
181
+ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["json", "help", "version"]);
182
+ var HELP_ENGINE = `vos \u2014 command line for the vos programmatic video engine (https://vos.so/engine)
262
183
 
263
- Usage
184
+ Engine verbs (local, no account, no network beyond the render page's CDN deps)
264
185
  vos render <config.json|url|take> [out] [--width 1920] [--height 1080] [--fps 30]
265
186
  [--duration <s>] [--format webm|mp4] [--json]
266
187
  vos still <config.json|url> [out.webp] [--time 0] [--width] [--height] [--json]
267
188
  vos info <config.json|url> [--json]
189
+ vos check <config.json|url> [--json]
190
+ migrate \u2192 schema \u2192 syntax \u2192 compile \u2192 determinism/dialect lints, all local
268
191
  vos preview <config.json|url> [--port 0]
269
192
  vos versions [--json]
270
-
271
- Platform (vos.so) \u2014 the iteration loop: fetch, edit, push, pull, repeat
272
- vos fetch <vosId|watch-url> [--out dir] [--json]
273
- writes config.json + meta.json (no auth needed for public programs)
274
- vos check <config.json> [--json]
275
- migrate \u2192 schema \u2192 compile \u2192 determinism/dialect lints, all local
276
- vos push <config.json|take> [--vos id] [--title t] [--slug s] [--remix-of id]
277
- [--note n] [--label l] [--base versionId] [--overrides id,id] [--json]
278
- no --vos: create a PRIVATE vos (lineage from meta.json / --remix-of)
279
- with --vos: add a version; the base defaults to the tracked one in
280
- meta.json, so a stale push 409s WITH the changes made on the platform.
281
- --overrides consents to touching protected (human-edited) nodes \u2014
282
- only when the user asked for that change. Take DIRECTORIES push
283
- through the take pipeline (@vosso/cli) automatically.
284
- vos pull [dir|take] [--vos id] [--since versionId] [--check] [--json]
285
- what changed on vos.so since your base: attributed versions with
286
- typed summaries + the protected node set. Syncs config.json to the
287
- head (previous copy kept as config.backup.json) and repoints the
288
- base \u2014 re-apply your edit on top, then push. --check reports only.
289
- auth: VOS_API_KEY or ~/.config/vos/credentials \u2014 mint at vos.so/app/api;
290
- keys can never publish (visibility stays private; humans publish on vos.so)
291
-
292
- Take pipeline \u2014 screen recordings in, polished product video out
293
- (ships separately: npm i -D @vosso/cli)
294
- vos create --actions actions.json [out.webm] [--strict] (record + plan + render, one shot)
295
- vos record --actions actions.json [--out take] [--strict]
296
- vos plan <take> [--fresh]
297
- vos frames <take> [--at-zooms | --frame <t> --size WxH]
298
- vos open <take> (serve the take into the studio at vos.so)
299
- vos validate <actions.json|take>
300
- vos render <take> [out] (a take directory is detected by its doc.json)
301
-
193
+ `;
194
+ var HELP_PLUGIN_HINT = `
195
+ Everything else \u2014 the take pipeline (screen recordings in, product video out)
196
+ and the vos.so platform verbs (fetch/push/pull/login) \u2014 ships as a plugin:
197
+ npm i -D @vosso/vos-plugin
198
+ Installed plugin verbs appear here and run as plain \`vos <verb>\`.
199
+ `;
200
+ var HELP_CONVENTIONS = `
302
201
  Conventions
303
202
  Results go to stdout; logs go to stderr. --json switches stdout to NDJSON
304
203
  events ending with {"event":"done",\u2026}. Exit codes: 0 ok, 1 error, 2 usage,
@@ -310,8 +209,8 @@ function outName(source, ext) {
310
209
  }
311
210
  async function cmdRender(argv) {
312
211
  const first = argv.find((a) => !a.startsWith("-"));
313
- if (first && existsSync(join2(first, "doc.json"))) {
314
- return delegateTake(["render", ...argv]);
212
+ if (first && existsSync(join(first, "doc.json"))) {
213
+ return delegate(["render", ...argv]);
315
214
  }
316
215
  const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS);
317
216
  const source = positionals[0];
@@ -437,7 +336,7 @@ function packageVersion(name) {
437
336
  let dir = dirname(entry);
438
337
  for (let i = 0; i < 6; i++) {
439
338
  try {
440
- const pkg = JSON.parse(readFileSync2(join2(dir, "package.json"), "utf8"));
339
+ const pkg = JSON.parse(readFileSync(join(dir, "package.json"), "utf8"));
441
340
  if (pkg.name === name && pkg.version) return pkg.version;
442
341
  } catch {
443
342
  }
@@ -447,21 +346,31 @@ function packageVersion(name) {
447
346
  }
448
347
  return null;
449
348
  }
450
- async function cmdVersions(argv) {
451
- const { flags } = parseArgs(argv, BOOLEAN_FLAGS);
452
- const r = createReporter(flags.json === true);
453
- const versions = {};
349
+ function ownVersion() {
454
350
  try {
455
351
  const own = JSON.parse(
456
- readFileSync2(fileURLToPath(new URL("../package.json", import.meta.url)), "utf8")
352
+ readFileSync(fileURLToPath(new URL("../package.json", import.meta.url)), "utf8")
457
353
  );
458
- versions["@vosjs/cli"] = own.version;
354
+ return own.version;
459
355
  } catch {
460
- versions["@vosjs/cli"] = "(unknown)";
356
+ return "(unknown)";
461
357
  }
358
+ }
359
+ async function cmdVersions(argv) {
360
+ const { flags } = parseArgs(argv, BOOLEAN_FLAGS);
361
+ const r = createReporter(flags.json === true);
362
+ const versions = {};
363
+ versions["@vosjs/cli"] = ownVersion();
462
364
  for (const name of ["@vosjs/core", "@vosjs/elements", "@vosjs/tween", "playwright"]) {
463
365
  versions[name] = packageVersion(name) ?? "(not found)";
464
366
  }
367
+ for (const name of PLUGIN_PACKAGES) {
368
+ const v = packageVersion(name);
369
+ if (v) {
370
+ versions[name] = v;
371
+ break;
372
+ }
373
+ }
465
374
  if (r.json) r.done({ versions }, "");
466
375
  else for (const [k, v] of Object.entries(versions)) process.stdout.write(`${k} ${v}
467
376
  `);
@@ -491,37 +400,6 @@ async function cmdPreview(argv) {
491
400
  });
492
401
  return EXIT_OK;
493
402
  }
494
- async function cmdFetch(argv) {
495
- const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS);
496
- const source = positionals[0];
497
- if (!source) throw new UsageError("vos fetch <vosId|watch-url> [--out dir]");
498
- const r = createReporter(flags.json === true);
499
- const id = parseVosId(source);
500
- const key = resolveCredential();
501
- const meta = await apiJson(`/api/vos/${id}`, { key });
502
- if (meta.status !== 200) throw new Error(apiError(`fetch vos ${id}`, meta));
503
- const cfg = await apiJson(`/api/vos/${id}/config`, { key });
504
- if (cfg.status !== 200) throw new Error(apiError(`fetch config for ${id}`, cfg));
505
- const vosMeta = meta.body.vos ?? {};
506
- const slug = typeof vosMeta.slug === "string" && vosMeta.slug ? vosMeta.slug : id;
507
- const out = flags.out ?? slug;
508
- await mkdir(out, { recursive: true });
509
- await writeFile(join2(out, "config.json"), JSON.stringify(cfg.body.config, null, 2));
510
- await writeFile(join2(out, "meta.json"), JSON.stringify(vosMeta, null, 2));
511
- const title = typeof vosMeta.title === "string" ? vosMeta.title : "";
512
- r.done(
513
- {
514
- out,
515
- id,
516
- slug,
517
- title,
518
- currentVersionId: vosMeta.currentVersionId ?? null
519
- },
520
- `Wrote ${out}/config.json + meta.json (${title || id})
521
- Edit config.json, then: vos check ${out}/config.json && vos push ${out}/config.json`
522
- );
523
- return EXIT_OK;
524
- }
525
403
  async function cmdCheck(argv) {
526
404
  const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS);
527
405
  const source = positionals[0];
@@ -564,269 +442,85 @@ async function cmdCheck(argv) {
564
442
  }
565
443
  return result.ok ? EXIT_OK : EXIT_ERROR;
566
444
  }
567
- async function cmdPush(argv) {
568
- const firstArg = argv.find((a) => !a.startsWith("-"));
569
- if (firstArg && existsSync(join2(firstArg, "doc.json"))) {
570
- return delegateTake(["push", ...argv]);
571
- }
572
- const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS);
573
- const source = positionals[0];
574
- if (!source) {
575
- throw new UsageError(
576
- "vos push <config.json|take> [--vos id] [--title t] [--slug s] [--remix-of id] [--note n] [--label l] [--base versionId] [--overrides id,id]"
577
- );
578
- }
579
- const r = createReporter(flags.json === true);
580
- const dir = dirname(source);
581
- const parsed = JSON.parse(await readFile(source, "utf8"));
582
- const check = runCheck(parsed);
583
- if (!check.ok || !check.config) {
584
- for (const i of check.issues) {
585
- if (i.level === "error") r.log(`error [${i.source}] ${i.message}`);
586
- }
587
- throw new Error(`config does not validate \u2014 run: vos check ${source}`);
588
- }
589
- const config = check.config;
590
- const key = resolveCredential();
591
- if (!key) {
592
- throw new Error(
593
- "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)"
594
- );
595
- }
596
- if (flags.vos) {
597
- const vosId = parseVosId(String(flags.vos));
598
- const meta2 = readMeta(dir);
599
- const trackedBase = meta2 && meta2.id === vosId && typeof meta2.currentVersionId === "string" ? meta2.currentVersionId : void 0;
600
- const body = { config };
601
- const base = flags.base ? String(flags.base) : trackedBase;
602
- if (base) body.baseVersionId = base;
603
- if (flags.note) body.note = String(flags.note);
604
- if (flags.label) body.label = String(flags.label);
605
- if (flags.overrides) {
606
- body.overrides = String(flags.overrides).split(",").map((s) => s.trim()).filter(Boolean);
607
- }
608
- const res = await apiJson(`/api/vos/${vosId}/versions`, { method: "POST", key, body });
609
- if (res.status === 409) {
610
- const changes = Array.isArray(res.body.changes) ? res.body.changes : [];
611
- for (const line of formatChanges(changes)) r.log(`platform: ${line}`);
612
- const protectedIds = Array.isArray(res.body.protected) ? res.body.protected : [];
613
- const nodes = Array.isArray(res.body.nodes) ? res.body.nodes : [];
614
- r.event({
615
- event: "conflict",
616
- reason: res.body.error ?? "conflict",
617
- changes,
618
- protected: protectedIds,
619
- nodes
620
- });
621
- if (res.body.error === "protected_conflict") {
622
- throw new Error(
623
- `push touches human-edited nodes: ${nodes.join(", ")} \u2014 keep the human's values, or re-push with --overrides ${nodes.join(",")} ONLY if the user asked for this change`
624
- );
625
- }
626
- throw new Error(
627
- `version base is stale \u2014 the platform copy changed (${changes.length} edit${changes.length === 1 ? "s" : ""} above). Run: vos pull ${dir} \u2014 then re-apply your edit and push again`
628
- );
629
- }
630
- if (res.status !== 201) throw new Error(apiError(`push version to ${vosId}`, res));
631
- const version = res.body.version ?? {};
632
- if (typeof version.id === "string") {
633
- writeMeta(dir, { id: vosId, currentVersionId: version.id });
634
- }
635
- const watchUrl = `${PLATFORM_ORIGIN}/vos/${vosId}`;
636
- const studioUrl = `${PLATFORM_ORIGIN}/studio?vos=${vosId}`;
637
- r.done(
638
- {
639
- id: vosId,
640
- versionId: version.id ?? null,
641
- versionNumber: version.versionNumber ?? null,
642
- base: base ?? null,
643
- watchUrl,
644
- studioUrl
645
- },
646
- `Pushed version ${String(version.versionNumber ?? "?")} of ${vosId}
647
- watch: ${watchUrl}
648
- studio: ${studioUrl}`
649
- );
650
- return EXIT_OK;
651
- }
652
- let meta = {};
653
- try {
654
- meta = JSON.parse(await readFile(join2(dirname(source), "meta.json"), "utf8"));
655
- } catch {
656
- }
657
- const remixOfId = flags["remix-of"] ? String(flags["remix-of"]) : typeof meta.id === "string" ? meta.id : void 0;
658
- const fallbackTitle = typeof meta.title === "string" && meta.title ? `${meta.title} remix` : basename(source).replace(/\.json$/i, "") || "vos remix";
659
- const title = (flags.title ?? fallbackTitle).slice(0, 100);
660
- const slugGiven = typeof flags.slug === "string";
661
- const baseSlug = slugGiven ? flags.slug : deriveSlug(title);
662
- for (let attempt = 0; ; attempt++) {
663
- const slug = attempt === 0 ? baseSlug : `${baseSlug}-${attempt + 1}`.slice(0, 50);
664
- const body = {
665
- title,
666
- slug,
667
- visibility: "private",
668
- config
669
- };
670
- if (remixOfId) body.remixOfId = remixOfId;
671
- const res = await apiJson("/api/vos", { method: "POST", key, body });
672
- if (res.status === 409 && !slugGiven && attempt < 3) {
673
- r.log(`slug "${slug}" is taken \u2014 retrying`);
445
+ var PLUGIN_PACKAGES = ["@vosso/vos-plugin", "@vosso/cli", "@vosso/voila-cli"];
446
+ async function loadPlugin() {
447
+ for (const name of PLUGIN_PACKAGES) {
448
+ let mod;
449
+ try {
450
+ mod = await import(name);
451
+ } catch {
674
452
  continue;
675
453
  }
676
- if (res.status !== 201) throw new Error(apiError("push vos", res));
677
- const created = res.body.vos ?? {};
678
- const id = String(created.id ?? "");
679
- writeMeta(dir, {
680
- id,
681
- currentVersionId: created.currentVersionId ?? null,
682
- title,
683
- slug: created.slug ?? slug,
684
- ...remixOfId ? { remixOfId } : {}
685
- });
686
- const watchUrl = `${PLATFORM_ORIGIN}/vos/${id}`;
687
- const studioUrl = `${PLATFORM_ORIGIN}/studio?vos=${id}`;
688
- r.done(
689
- {
690
- id,
691
- slug: created.slug ?? slug,
692
- title,
693
- visibility: created.visibility ?? "private",
694
- remixOfId: remixOfId ?? null,
695
- currentVersionId: created.currentVersionId ?? null,
696
- watchUrl,
697
- studioUrl
698
- },
699
- `Created private vos ${id} (${title})
700
- watch: ${watchUrl}
701
- studio: ${studioUrl}
702
- Iterate with: vos push ${source} --vos ${id}`
703
- );
704
- return EXIT_OK;
454
+ if (typeof mod.run === "function") return mod;
705
455
  }
456
+ return null;
706
457
  }
707
- async function cmdPull(argv) {
708
- const firstPos = argv.find((a) => !a.startsWith("-"));
709
- if (firstPos && existsSync(join2(firstPos, "doc.json")) || !firstPos && existsSync("doc.json")) {
710
- return delegateTake(["pull", ...argv]);
711
- }
712
- const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS);
713
- const target = positionals[0] ?? ".";
714
- const dir = target.endsWith(".json") ? dirname(target) : target;
715
- const r = createReporter(flags.json === true);
716
- const meta = readMeta(dir);
717
- const vosId = flags.vos ? parseVosId(String(flags.vos)) : typeof meta?.id === "string" ? meta.id : null;
718
- if (!vosId) {
719
- throw new UsageError(
720
- `no tracked vos in ${dir}/meta.json \u2014 pass --vos <id>, or fetch/push first`
721
- );
722
- }
723
- const since = flags.since ? String(flags.since) : typeof meta?.currentVersionId === "string" ? meta.currentVersionId : null;
724
- if (!since) {
725
- throw new UsageError(
726
- `no base version in ${dir}/meta.json \u2014 pass --since <versionId>`
727
- );
728
- }
729
- const key = resolveCredential();
730
- if (!key) {
731
- throw new Error(
732
- "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)"
733
- );
734
- }
735
- const res = await apiJson(`/api/vos/${vosId}/changes?since=${encodeURIComponent(since)}`, {
736
- key
737
- });
738
- if (res.status !== 200) throw new Error(apiError(`pull changes for ${vosId}`, res));
739
- const head = res.body.head ?? {};
740
- const changes = Array.isArray(res.body.changes) ? res.body.changes : [];
741
- const protectedIds = Array.isArray(res.body.protected) ? res.body.protected : [];
742
- if (changes.length === 0) {
743
- r.done(
744
- { id: vosId, upToDate: true, head: head.id ?? since },
745
- `${vosId}: up to date (base ${since.slice(0, 8)}\u2026 is the head)`
458
+ function versionAtLeast(version, min) {
459
+ const pa = version.split(".").map((n) => Number.parseInt(n, 10));
460
+ const pb = min.split(".").map((n) => Number.parseInt(n, 10));
461
+ for (let i = 0; i < 3; i++) {
462
+ const a = pa[i] ?? 0;
463
+ const b = pb[i] ?? 0;
464
+ if (a !== b) return a > b;
465
+ }
466
+ return true;
467
+ }
468
+ async function delegate(argv, viaAlias = false) {
469
+ const plugin = await loadPlugin();
470
+ if (!plugin?.run) {
471
+ process.stderr.write(
472
+ `vos ${argv[0] ?? ""}: not an engine verb.
473
+ The take pipeline and the vos.so platform verbs (create, record, plan,
474
+ frames, open, validate, fetch, push, pull, login) ship as a plugin:
475
+ npm i -D @vosso/vos-plugin
476
+ then re-run: vos ${argv.join(" ")}
477
+ (If this was a typo, run: vos help)
478
+ `
746
479
  );
747
- return EXIT_OK;
480
+ return EXIT_ERROR;
748
481
  }
749
- for (const line of formatChanges(changes)) r.log(line);
750
- if (protectedIds.length) {
751
- r.log(
752
- `protected (human-edited \u2014 keep their values unless asked): ${protectedIds.join(", ")}`
482
+ const range = plugin.manifest?.hostRange;
483
+ const min = range ? /^>=\s*(\d+\.\d+\.\d+)/.exec(range)?.[1] : void 0;
484
+ if (min && !versionAtLeast(ownVersion(), min)) {
485
+ process.stderr.write(
486
+ `note: the installed plugin expects @vosjs/cli ${range} (this is ${ownVersion()}) \u2014 upgrade with: npm i -D @vosjs/cli@latest
487
+ `
753
488
  );
754
489
  }
755
- if (res.body.truncated === true) {
756
- r.log("walk truncated \u2014 more versions exist; pull again after syncing");
757
- }
758
- if (flags.check === true) {
759
- r.done(
760
- {
761
- id: vosId,
762
- upToDate: false,
763
- versions: changes.length,
764
- head: head.id ?? null,
765
- protected: protectedIds,
766
- changes
767
- },
768
- `${changes.length} version${changes.length === 1 ? "" : "s"} behind \u2014 run without --check to sync`
769
- );
770
- return EXIT_OK;
490
+ if (viaAlias && argv[0]) {
491
+ process.stderr.write(`note: "vos voila ${argv[0]}" is now "vos ${argv[0]}".
492
+ `);
771
493
  }
772
- const cfg = await apiJson(`/api/vos/${vosId}/config`, { key });
773
- if (cfg.status !== 200) throw new Error(apiError(`fetch head config for ${vosId}`, cfg));
774
- const configPath = join2(dir, "config.json");
775
- let backedUp = false;
776
- if (existsSync(configPath)) {
777
- await writeFile(join2(dir, "config.backup.json"), await readFile(configPath));
778
- backedUp = true;
779
- }
780
- await writeFile(configPath, JSON.stringify(cfg.body.config, null, 2));
781
- writeMeta(dir, { id: vosId, currentVersionId: head.id ?? since });
782
- r.done(
783
- {
784
- id: vosId,
785
- upToDate: false,
786
- versions: changes.length,
787
- head: head.id ?? null,
788
- protected: protectedIds,
789
- changes,
790
- out: configPath,
791
- backup: backedUp ? join2(dir, "config.backup.json") : null
792
- },
793
- `Pulled ${changes.length} version${changes.length === 1 ? "" : "s"} \u2192 ${configPath}` + (backedUp ? ` (previous copy: config.backup.json)` : "") + `
794
- Re-apply your edit on the new head, then: vos push ${configPath} --vos ${vosId}`
795
- );
796
- return EXIT_OK;
494
+ return await plugin.run(argv);
797
495
  }
798
- var TAKE_VERBS = /* @__PURE__ */ new Set(["create", "record", "plan", "frames", "open", "validate"]);
799
- async function delegateTake(argv, viaAlias = false) {
800
- for (const name of ["@vosso/cli", "@vosso/voila-cli"]) {
801
- let mod;
802
- try {
803
- mod = await import(name);
804
- } catch {
805
- continue;
806
- }
807
- if (typeof mod.run !== "function") continue;
808
- if (viaAlias && argv[0]) {
809
- process.stderr.write(`note: "vos voila ${argv[0]}" is now "vos ${argv[0]}".
496
+ async function printHelp() {
497
+ process.stdout.write(HELP_ENGINE);
498
+ const plugin = await loadPlugin();
499
+ const verbs = plugin?.manifest?.verbs;
500
+ if (verbs?.length) {
501
+ const label = plugin?.manifest?.name ?? "vos plugin";
502
+ process.stdout.write(`
503
+ Platform + take pipeline (via ${label})
504
+ `);
505
+ for (const v of verbs) {
506
+ if (v.name === "render") continue;
507
+ process.stdout.write(` vos ${v.name.padEnd(8)} ${v.summary}
810
508
  `);
811
509
  }
812
- return await mod.run(argv);
510
+ } else {
511
+ process.stdout.write(HELP_PLUGIN_HINT);
813
512
  }
814
- process.stderr.write(
815
- `The take pipeline (screen recordings in, product video out) ships separately.
816
- npm i -D @vosso/cli
817
- then re-run: vos ${argv.join(" ")}
818
- `
819
- );
820
- return EXIT_ERROR;
513
+ process.stdout.write(HELP_CONVENTIONS);
821
514
  }
515
+ var ENGINE_VERBS = /* @__PURE__ */ new Set(["render", "still", "info", "versions", "preview", "check"]);
822
516
  async function main() {
823
517
  const [cmd, ...rest] = process.argv.slice(2);
824
518
  if (!cmd || cmd === "help" || cmd === "--help" || cmd === "-h") {
825
- process.stdout.write(HELP);
519
+ await printHelp();
826
520
  return cmd ? EXIT_OK : EXIT_USAGE;
827
521
  }
828
522
  if (cmd === "--version") return cmdVersions(["--json"]);
829
- if (TAKE_VERBS.has(cmd)) return delegateTake([cmd, ...rest]);
523
+ if (!ENGINE_VERBS.has(cmd) && cmd !== "voila") return delegate([cmd, ...rest]);
830
524
  switch (cmd) {
831
525
  case "render":
832
526
  return cmdRender(rest);
@@ -838,18 +532,12 @@ async function main() {
838
532
  return cmdVersions(rest);
839
533
  case "preview":
840
534
  return cmdPreview(rest);
841
- case "fetch":
842
- return cmdFetch(rest);
843
535
  case "check":
844
536
  return cmdCheck(rest);
845
- case "push":
846
- return cmdPush(rest);
847
- case "pull":
848
- return cmdPull(rest);
849
537
  // Hidden alias for existing scripts; not in HELP. Same code path as the
850
538
  // promoted verbs, plus a one-line pointer at the new spelling.
851
539
  case "voila":
852
- return delegateTake(rest, true);
540
+ return delegate(rest, true);
853
541
  default:
854
542
  throw new UsageError(`unknown command "${cmd}" \u2014 run vos help`);
855
543
  }
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
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 formatChanges,\n parseVosId,\n readMeta,\n resolveCredential,\n writeMeta,\n type VersionChange,\n} from './platform'\n\nconst BOOLEAN_FLAGS = new Set(['json', 'help', 'version', 'check'])\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) — the iteration loop: fetch, edit, push, pull, repeat\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|take> [--vos id] [--title t] [--slug s] [--remix-of id]\n [--note n] [--label l] [--base versionId] [--overrides id,id] [--json]\n no --vos: create a PRIVATE vos (lineage from meta.json / --remix-of)\n with --vos: add a version; the base defaults to the tracked one in\n meta.json, so a stale push 409s WITH the changes made on the platform.\n --overrides consents to touching protected (human-edited) nodes —\n only when the user asked for that change. Take DIRECTORIES push\n through the take pipeline (@vosso/cli) automatically.\n vos pull [dir|take] [--vos id] [--since versionId] [--check] [--json]\n what changed on vos.so since your base: attributed versions with\n typed summaries + the protected node set. Syncs config.json to the\n head (previous copy kept as config.backup.json) and repoints the\n base — re-apply your edit on top, then push. --check reports only.\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 // Polymorphic like `render`: a take DIRECTORY (doc.json) pushes through\n // the take pipeline in @vosso/cli — recording upload + doc persistence.\n const firstArg = argv.find((a) => !a.startsWith('-'))\n if (firstArg && existsSync(join(firstArg, 'doc.json'))) {\n return delegateTake(['push', ...argv])\n }\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|take> [--vos id] [--title t] [--slug s] [--remix-of id] [--note n] [--label l] [--base versionId] [--overrides id,id]',\n )\n }\n const r = createReporter(flags.json === true)\n const dir = dirname(source)\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 (defaulting to the tracked base in meta.json, so a\n // fetch→edit→push loop gets stale detection for free), --note/--label\n // say what changed, and --overrides consents to touching protected\n // (human-edited) nodes — ONLY when the user asked for that change.\n const vosId = parseVosId(String(flags.vos))\n const meta = readMeta(dir)\n const trackedBase =\n meta && meta.id === vosId && typeof meta.currentVersionId === 'string'\n ? meta.currentVersionId\n : undefined\n const body: Record<string, unknown> = { config }\n const base = flags.base ? String(flags.base) : trackedBase\n if (base) body.baseVersionId = base\n if (flags.note) body.note = String(flags.note)\n if (flags.label) body.label = String(flags.label)\n if (flags.overrides) {\n body.overrides = String(flags.overrides)\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean)\n }\n const res = await apiJson(`/api/vos/${vosId}/versions`, { method: 'POST', key, body })\n if (res.status === 409) {\n // The correction path is the data path: both 409 shapes carry what to\n // read. stale_base embeds the changes made on the platform since your\n // base; protected_conflict lists the human-touched nodes you'd clobber.\n const changes = Array.isArray(res.body.changes)\n ? (res.body.changes as VersionChange[])\n : []\n for (const line of formatChanges(changes)) r.log(`platform: ${line}`)\n const protectedIds = Array.isArray(res.body.protected) ? res.body.protected : []\n const nodes = Array.isArray(res.body.nodes) ? res.body.nodes : []\n r.event({\n event: 'conflict',\n reason: res.body.error ?? 'conflict',\n changes,\n protected: protectedIds,\n nodes,\n })\n if (res.body.error === 'protected_conflict') {\n throw new Error(\n `push touches human-edited nodes: ${nodes.join(', ')} — keep the human's values, ` +\n `or re-push with --overrides ${nodes.join(',')} ONLY if the user asked for this change`,\n )\n }\n throw new Error(\n `version base is stale — the platform copy changed (${changes.length} edit${changes.length === 1 ? 's' : ''} above). ` +\n `Run: vos pull ${dir} — then re-apply your edit and push again`,\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 // Track what we just made: the new version is the next push's base.\n if (typeof version.id === 'string') {\n writeMeta(dir, { id: vosId, currentVersionId: version.id })\n }\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 base: base ?? 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 // The directory now TRACKS the created vos (its source stays as\n // remixOfId) — the next push/pull needs no flags.\n writeMeta(dir, {\n id,\n currentVersionId: created.currentVersionId ?? null,\n title,\n slug: created.slug ?? slug,\n ...(remixOfId ? { remixOfId } : {}),\n })\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\nasync function cmdPull(argv: string[]): Promise<number> {\n // Take directories pull through @vosso/cli (doc.json comes back into the\n // take); a tracked config directory pulls the program path below.\n const firstPos = argv.find((a) => !a.startsWith('-'))\n if (\n (firstPos && existsSync(join(firstPos, 'doc.json'))) ||\n (!firstPos && existsSync('doc.json'))\n ) {\n return delegateTake(['pull', ...argv])\n }\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n // Positional: the tracked directory or its config.json (default cwd).\n const target = positionals[0] ?? '.'\n const dir = target.endsWith('.json') ? dirname(target) : target\n const r = createReporter(flags.json === true)\n\n const meta = readMeta(dir)\n const vosId = flags.vos\n ? parseVosId(String(flags.vos))\n : typeof meta?.id === 'string'\n ? (meta.id as string)\n : null\n if (!vosId) {\n throw new UsageError(\n `no tracked vos in ${dir}/meta.json — pass --vos <id>, or fetch/push first`,\n )\n }\n const since = flags.since\n ? String(flags.since)\n : typeof meta?.currentVersionId === 'string'\n ? (meta.currentVersionId as string)\n : null\n if (!since) {\n throw new UsageError(\n `no base version in ${dir}/meta.json — pass --since <versionId>`,\n )\n }\n // The changelog walk is owner-only (edits on private work).\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)',\n )\n }\n\n const res = await apiJson(`/api/vos/${vosId}/changes?since=${encodeURIComponent(since)}`, {\n key,\n })\n if (res.status !== 200) throw new Error(apiError(`pull changes for ${vosId}`, res))\n\n const head = (res.body.head ?? {}) as Record<string, unknown>\n const changes = Array.isArray(res.body.changes)\n ? (res.body.changes as VersionChange[])\n : []\n const protectedIds = Array.isArray(res.body.protected)\n ? (res.body.protected as string[])\n : []\n\n if (changes.length === 0) {\n r.done(\n { id: vosId, upToDate: true, head: head.id ?? since },\n `${vosId}: up to date (base ${since.slice(0, 8)}… is the head)`,\n )\n return EXIT_OK\n }\n\n for (const line of formatChanges(changes)) r.log(line)\n if (protectedIds.length) {\n r.log(\n `protected (human-edited — keep their values unless asked): ${protectedIds.join(', ')}`,\n )\n }\n if (res.body.truncated === true) {\n r.log('walk truncated — more versions exist; pull again after syncing')\n }\n\n if (flags.check === true) {\n r.done(\n {\n id: vosId,\n upToDate: false,\n versions: changes.length,\n head: head.id ?? null,\n protected: protectedIds,\n changes,\n },\n `${changes.length} version${changes.length === 1 ? '' : 's'} behind — run without --check to sync`,\n )\n return EXIT_OK\n }\n\n // Sync: the head config replaces config.json (the old file is kept as\n // config.backup.json), and meta repoints so the next push has the fresh\n // base. Your uncommitted local edits live in the backup — re-apply on top.\n const cfg = await apiJson(`/api/vos/${vosId}/config`, { key })\n if (cfg.status !== 200) throw new Error(apiError(`fetch head config for ${vosId}`, cfg))\n const configPath = join(dir, 'config.json')\n let backedUp = false\n if (existsSync(configPath)) {\n await writeFile(join(dir, 'config.backup.json'), await readFile(configPath))\n backedUp = true\n }\n await writeFile(configPath, JSON.stringify(cfg.body.config, null, 2))\n writeMeta(dir, { id: vosId, currentVersionId: head.id ?? since })\n\n r.done(\n {\n id: vosId,\n upToDate: false,\n versions: changes.length,\n head: head.id ?? null,\n protected: protectedIds,\n changes,\n out: configPath,\n backup: backedUp ? join(dir, 'config.backup.json') : null,\n },\n `Pulled ${changes.length} version${changes.length === 1 ? '' : 's'} → ${configPath}` +\n (backedUp ? ` (previous copy: config.backup.json)` : '') +\n `\\nRe-apply your edit on the new head, then: vos push ${configPath} --vos ${vosId}`,\n )\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 case 'fetch':\n return cmdFetch(rest)\n case 'check':\n return cmdCheck(rest)\n case 'push':\n return cmdPush(rest)\n case 'pull':\n return cmdPull(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, lintVosFonts } from '@vosjs/core/lint'\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 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 !== 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([\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 // 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\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, writeFileSync } 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\n// ---------------------------------------------------------------------------\n// Local tracking state (meta.json) + the pull-contract payload\n// ---------------------------------------------------------------------------\n\n/**\n * meta.json beside a config.json makes the directory TRACK a vos, like a\n * remote: `id` + `currentVersionId` are the pull/push base. `vos fetch`\n * seeds it from the source; `vos push` repoints it at what it created.\n */\nexport function readMeta(dir: string): Record<string, unknown> | null {\n try {\n return JSON.parse(readFileSync(join(dir, 'meta.json'), 'utf8')) as Record<\n string,\n unknown\n >\n } catch {\n return null\n }\n}\n\nexport function writeMeta(dir: string, patch: Record<string, unknown>): void {\n const merged = { ...(readMeta(dir) ?? {}), ...patch }\n writeFileSync(join(dir, 'meta.json'), JSON.stringify(merged, null, 2))\n}\n\n/** One version of the /changes walk (shape mirrored from the platform). */\nexport interface VersionChange {\n versionId?: string\n versionNumber?: number\n origin?: string\n label?: string | null\n note?: string | null\n summary?: string\n}\n\n/** Human lines for a changes walk — origin/label attributed, note indented. */\nexport function formatChanges(changes: readonly VersionChange[]): string[] {\n const lines: string[] = []\n for (const ch of changes) {\n const label = ch.label ? ` · ${ch.label}` : ''\n lines.push(\n `v${String(ch.versionNumber ?? '?')} (${ch.origin ?? 'unknown'}${label}): ${ch.summary ?? ''}`,\n )\n if (ch.note) lines.push(` note: ${ch.note}`)\n }\n return lines\n}\n"],"mappings":"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","names":["readFileSync","join","join","require","readFileSync","meta"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/output.ts","../src/check.ts"],"sourcesContent":["import { 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'\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] [--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 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_PLUGIN_HINT = `\nEverything else — the take pipeline (screen recordings in, product video out)\nand the vos.so platform verbs (fetch/push/pull/login) — ships as a plugin:\n npm i -D @vosso/vos-plugin\nInstalled plugin verbs appear here and run as plain \\`vos <verb>\\`.\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.\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 plugin; anything else\n // 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 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 = (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\nfunction ownVersion(): string {\n try {\n const own = JSON.parse(\n readFileSync(fileURLToPath(new URL('../package.json', import.meta.url)), 'utf8'),\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 ['@vosjs/core', '@vosjs/elements', '@vosjs/tween', 'playwright']) {\n versions[name] = packageVersion(name) ?? '(not found)'\n }\n // The plugin, under whichever of its names is installed (the doctor's row).\n for (const name of PLUGIN_PACKAGES) {\n const v = packageVersion(name)\n if (v) {\n versions[name] = v\n break\n }\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 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\n// ---------------------------------------------------------------------------\n// The extension seam: every verb this CLI does not own delegates to the vos\n// plugin (the vosso platform layer — take pipeline + vos.so verbs). The\n// contract is the plugin's `run(argv)` export; its optional `manifest`\n// (verb list + supported host range) feeds `vos help` and the doctor, so a\n// new plugin verb never needs a release of this package.\n// ---------------------------------------------------------------------------\n\nconst PLUGIN_PACKAGES = ['@vosso/vos-plugin', '@vosso/cli', '@vosso/voila-cli']\n\ninterface PluginManifest {\n name?: string\n hostRange?: string\n verbs?: { name: string; summary: string }[]\n}\n\ninterface PluginModule {\n run?: (argv: string[]) => Promise<number>\n manifest?: PluginManifest\n}\n\nasync function loadPlugin(): Promise<PluginModule | null> {\n for (const name of PLUGIN_PACKAGES) {\n let mod: PluginModule\n try {\n mod = (await import(name as string)) as PluginModule\n } catch {\n continue\n }\n if (typeof mod.run === 'function') return mod\n }\n return null\n}\n\nfunction versionAtLeast(version: string, min: string): boolean {\n const pa = version.split('.').map((n) => Number.parseInt(n, 10))\n const pb = min.split('.').map((n) => Number.parseInt(n, 10))\n for (let i = 0; i < 3; i++) {\n const a = pa[i] ?? 0\n const b = pb[i] ?? 0\n if (a !== b) return a > b\n }\n return true\n}\n\nasync function delegate(argv: string[], viaAlias = false): Promise<number> {\n const plugin = await loadPlugin()\n if (!plugin?.run) {\n process.stderr.write(\n `vos ${argv[0] ?? ''}: not an engine verb.\\n` +\n 'The take pipeline and the vos.so platform verbs (create, record, plan,\\n' +\n 'frames, open, validate, fetch, push, pull, login) ship as a plugin:\\n' +\n ' npm i -D @vosso/vos-plugin\\n' +\n `then re-run: vos ${argv.join(' ')}\\n` +\n '(If this was a typo, run: vos help)\\n',\n )\n return EXIT_ERROR\n }\n const range = plugin.manifest?.hostRange\n const min = range ? /^>=\\s*(\\d+\\.\\d+\\.\\d+)/.exec(range)?.[1] : undefined\n if (min && !versionAtLeast(ownVersion(), min)) {\n process.stderr.write(\n `note: the installed plugin expects @vosjs/cli ${range} (this is ${ownVersion()}) — upgrade with: npm i -D @vosjs/cli@latest\\n`,\n )\n }\n if (viaAlias && argv[0]) {\n process.stderr.write(`note: \"vos voila ${argv[0]}\" is now \"vos ${argv[0]}\".\\n`)\n }\n return await plugin.run(argv)\n}\n\nasync function printHelp(): Promise<void> {\n process.stdout.write(HELP_ENGINE)\n const plugin = await loadPlugin()\n const verbs = plugin?.manifest?.verbs\n if (verbs?.length) {\n const label = plugin?.manifest?.name ?? 'vos plugin'\n process.stdout.write(`\\nPlatform + take pipeline (via ${label})\\n`)\n for (const v of 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 } else {\n process.stdout.write(HELP_PLUGIN_HINT)\n }\n process.stdout.write(HELP_CONVENTIONS)\n}\n\nconst ENGINE_VERBS = new Set(['render', 'still', 'info', 'versions', 'preview', 'check'])\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 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((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, lintVosFonts } from '@vosjs/core/lint'\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 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 !== 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([\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 // 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\n return finish(migrated)\n}\n"],"mappings":"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","names":["require"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vosjs/cli",
3
- "version": "0.6.4",
3
+ "version": "0.7.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,7 +42,7 @@
42
42
  "sideEffects": false,
43
43
  "dependencies": {
44
44
  "playwright": "^1.49.0",
45
- "@vosjs/core": "^0.17.0",
45
+ "@vosjs/core": "^0.17.1",
46
46
  "@vosjs/tween": "^0.7.2",
47
47
  "@vosjs/elements": "^0.7.0"
48
48
  },