@vosjs/cli 0.2.2 → 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 +17 -3
- package/dist/cli.js +408 -21
- package/dist/cli.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -13,15 +13,29 @@ npx vos render animation.json out.webm
|
|
|
13
13
|
## Commands
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
vos render <config.json|url> [out]
|
|
16
|
+
vos render <config.json|url|take> [out] # config → video; a take directory renders via the take pipeline
|
|
17
17
|
vos still <config.json|url> [out] # config → single frame (WebP)
|
|
18
18
|
vos info <config.json|url> # inspect a config
|
|
19
19
|
vos preview <config.json|url> # serve a local playback page
|
|
20
20
|
vos versions # installed @vosjs/* versions
|
|
21
|
-
|
|
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> [--vos id] [--title t] [--slug s] [--remix-of id] [--note n] [--base versionId]
|
|
22
34
|
```
|
|
23
35
|
|
|
24
|
-
The
|
|
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.
|
|
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.
|
|
25
39
|
|
|
26
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.
|
|
27
41
|
|
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 { 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,19 +45,210 @@ 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)
|
|
51
221
|
|
|
52
222
|
Usage
|
|
53
|
-
vos render <config.json|url> [out] [--width 1920] [--height 1080] [--fps 30]
|
|
223
|
+
vos render <config.json|url|take> [out] [--width 1920] [--height 1080] [--fps 30]
|
|
54
224
|
[--duration <s>] [--format webm|mp4] [--json]
|
|
55
225
|
vos still <config.json|url> [out.webp] [--time 0] [--width] [--height] [--json]
|
|
56
226
|
vos info <config.json|url> [--json]
|
|
57
227
|
vos preview <config.json|url> [--port 0]
|
|
58
228
|
vos versions [--json]
|
|
59
|
-
|
|
60
|
-
|
|
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
|
+
|
|
243
|
+
Take pipeline \u2014 screen recordings in, polished product video out
|
|
244
|
+
(ships separately: npm i -D @vosso/cli)
|
|
245
|
+
vos create --actions actions.json [out.webm] [--strict] (record + plan + render, one shot)
|
|
246
|
+
vos record --actions actions.json [--out take] [--strict]
|
|
247
|
+
vos plan <take> [--fresh]
|
|
248
|
+
vos frames <take> [--at-zooms | --frame <t> --size WxH]
|
|
249
|
+
vos open <take> (serve the take into the studio at vos.so)
|
|
250
|
+
vos validate <actions.json|take>
|
|
251
|
+
vos render <take> [out] (a take directory is detected by its doc.json)
|
|
61
252
|
|
|
62
253
|
Conventions
|
|
63
254
|
Results go to stdout; logs go to stderr. --json switches stdout to NDJSON
|
|
@@ -69,9 +260,13 @@ function outName(source, ext) {
|
|
|
69
260
|
return `${base}.${ext}`;
|
|
70
261
|
}
|
|
71
262
|
async function cmdRender(argv) {
|
|
263
|
+
const first = argv.find((a) => !a.startsWith("-"));
|
|
264
|
+
if (first && existsSync(join2(first, "doc.json"))) {
|
|
265
|
+
return delegateTake(["render", ...argv]);
|
|
266
|
+
}
|
|
72
267
|
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS);
|
|
73
268
|
const source = positionals[0];
|
|
74
|
-
if (!source) throw new UsageError("vos render <config.json|url> [out]");
|
|
269
|
+
if (!source) throw new UsageError("vos render <config.json|url|take> [out]");
|
|
75
270
|
const r = createReporter(flags.json === true);
|
|
76
271
|
const format = flags.format ?? "webm";
|
|
77
272
|
if (format !== "webm" && format !== "mp4") throw new UsageError("--format must be webm or mp4");
|
|
@@ -193,7 +388,7 @@ function packageVersion(name) {
|
|
|
193
388
|
let dir = dirname(entry);
|
|
194
389
|
for (let i = 0; i < 6; i++) {
|
|
195
390
|
try {
|
|
196
|
-
const pkg = JSON.parse(
|
|
391
|
+
const pkg = JSON.parse(readFileSync2(join2(dir, "package.json"), "utf8"));
|
|
197
392
|
if (pkg.name === name && pkg.version) return pkg.version;
|
|
198
393
|
} catch {
|
|
199
394
|
}
|
|
@@ -209,7 +404,7 @@ async function cmdVersions(argv) {
|
|
|
209
404
|
const versions = {};
|
|
210
405
|
try {
|
|
211
406
|
const own = JSON.parse(
|
|
212
|
-
|
|
407
|
+
readFileSync2(fileURLToPath(new URL("../package.json", import.meta.url)), "utf8")
|
|
213
408
|
);
|
|
214
409
|
versions["@vosjs/cli"] = own.version;
|
|
215
410
|
} catch {
|
|
@@ -247,22 +442,207 @@ async function cmdPreview(argv) {
|
|
|
247
442
|
});
|
|
248
443
|
return EXIT_OK;
|
|
249
444
|
}
|
|
250
|
-
async function
|
|
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;
|
|
251
490
|
try {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
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`);
|
|
255
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"));
|
|
256
580
|
} catch {
|
|
257
|
-
|
|
258
|
-
|
|
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}`
|
|
259
621
|
);
|
|
260
|
-
return
|
|
622
|
+
return EXIT_OK;
|
|
261
623
|
}
|
|
262
624
|
}
|
|
263
|
-
|
|
625
|
+
var TAKE_VERBS = /* @__PURE__ */ new Set(["create", "record", "plan", "frames", "open", "validate"]);
|
|
626
|
+
async function delegateTake(argv, viaAlias = false) {
|
|
627
|
+
for (const name of ["@vosso/cli", "@vosso/voila-cli"]) {
|
|
628
|
+
let mod;
|
|
629
|
+
try {
|
|
630
|
+
mod = await import(name);
|
|
631
|
+
} catch {
|
|
632
|
+
continue;
|
|
633
|
+
}
|
|
634
|
+
if (typeof mod.run !== "function") continue;
|
|
635
|
+
if (viaAlias && argv[0]) {
|
|
636
|
+
process.stderr.write(`note: "vos voila ${argv[0]}" is now "vos ${argv[0]}".
|
|
637
|
+
`);
|
|
638
|
+
}
|
|
639
|
+
return await mod.run(argv);
|
|
640
|
+
}
|
|
264
641
|
process.stderr.write(
|
|
265
|
-
|
|
642
|
+
`The take pipeline (screen recordings in, product video out) ships separately.
|
|
643
|
+
npm i -D @vosso/cli
|
|
644
|
+
then re-run: vos ${argv.join(" ")}
|
|
645
|
+
`
|
|
266
646
|
);
|
|
267
647
|
return EXIT_ERROR;
|
|
268
648
|
}
|
|
@@ -273,6 +653,7 @@ async function main() {
|
|
|
273
653
|
return cmd ? EXIT_OK : EXIT_USAGE;
|
|
274
654
|
}
|
|
275
655
|
if (cmd === "--version") return cmdVersions(["--json"]);
|
|
656
|
+
if (TAKE_VERBS.has(cmd)) return delegateTake([cmd, ...rest]);
|
|
276
657
|
switch (cmd) {
|
|
277
658
|
case "render":
|
|
278
659
|
return cmdRender(rest);
|
|
@@ -284,10 +665,16 @@ async function main() {
|
|
|
284
665
|
return cmdVersions(rest);
|
|
285
666
|
case "preview":
|
|
286
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);
|
|
674
|
+
// Hidden alias for existing scripts; not in HELP. Same code path as the
|
|
675
|
+
// promoted verbs, plus a one-line pointer at the new spelling.
|
|
287
676
|
case "voila":
|
|
288
|
-
return
|
|
289
|
-
case "riff":
|
|
290
|
-
return cmdRiff();
|
|
677
|
+
return delegateTake(rest, true);
|
|
291
678
|
default:
|
|
292
679
|
throw new UsageError(`unknown command "${cmd}" \u2014 run vos help`);
|
|
293
680
|
}
|
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 { 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> [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 vos voila <subcommand> … (product-video pipeline — separate install)\n vos riff … (remix vos programs — CLI verb planned; contract: vos.so/llms-remix.txt)\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 const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const source = positionals[0]\n if (!source) throw new UsageError('vos render <config.json|url> [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 cmdVoila(argv: string[]): Promise<number> {\n try {\n const mod = (await import('@vosso/voila-cli' as string)) as {\n run?: (argv: string[]) => Promise<number>\n }\n if (typeof mod.run === 'function') return await mod.run(argv)\n process.stderr.write('@vosso/voila-cli is installed but exposes no run() — update it.\\n')\n return EXIT_ERROR\n } catch {\n process.stderr.write(\n 'The Voila product-video pipeline ships separately.\\n' +\n ' npm i -D @vosso/voila-cli\\n' +\n 'then re-run: vos voila …\\n',\n )\n return EXIT_ERROR\n }\n}\n\n// A product namespace that is reserved but not yet shipped. An honest stub:\n// it says exactly what works today and exits non-zero so scripts and agents\n// never mistake it for a successful run. (3D showcase belongs to riff — a\n// showcase program is a plain riff program, so there is no separate verb.)\nfunction cmdRiff(): number {\n process.stderr.write(\n 'vos riff — remix vos programs (the animation product at https://vos.so/riff).\\n' +\n 'The CLI verb is planned and not yet shipped. What works today:\\n' +\n ' - the agent remix contract: https://vos.so/llms-remix.txt\\n' +\n ' (fetch a program config, edit it, push a private remix back over HTTP)\\n' +\n ' - the browser editor: https://vos.so/stage\\n' +\n ' - 3D showcase: drop a GLB at https://vos.so/riff, or remix a program\\n' +\n ' from https://vos.so/gallery?tag=3d — buildProduct() in each config\\n' +\n ' is the documented swap point for your own model\\n' +\n ' - render any vos config locally: vos render <config.json>\\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 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 'voila':\n return cmdVoila(rest)\n case 'riff':\n return cmdRiff()\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":"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","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
|
+
"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/core": "^0.10.0",
|
|
46
45
|
"@vosjs/tween": "^0.7.2",
|
|
47
|
-
"@vosjs/elements": "^0.3.1"
|
|
46
|
+
"@vosjs/elements": "^0.3.1",
|
|
47
|
+
"@vosjs/core": "^0.10.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@types/node": "^22",
|