@vosjs/cli 0.3.0 → 0.5.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 +8 -0
- package/dist/cli.js +532 -7
- package/dist/cli.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -26,10 +26,18 @@ vos plan <take> [--fresh]
|
|
|
26
26
|
vos frames <take> [--at-zooms | --frame <t> --size WxH]
|
|
27
27
|
vos open <take>
|
|
28
28
|
vos validate <actions.json|take>
|
|
29
|
+
|
|
30
|
+
# Platform (vos.so) — fetch a program, validate locally, push a private remix
|
|
31
|
+
vos fetch <vosId|watch-url> [--out dir] # writes config.json + meta.json (no auth for public programs)
|
|
32
|
+
vos check <config.json> # migrate → schema → syntax → compile → determinism/dialect lints, all local
|
|
33
|
+
vos push <config.json|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
|
|
29
35
|
```
|
|
30
36
|
|
|
31
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.
|
|
32
38
|
|
|
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.
|
|
40
|
+
|
|
33
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.
|
|
34
42
|
|
|
35
43
|
Rendering runs the same deterministic pipeline everywhere: the config is compiled with `@vosjs/core`, wrapped in the engine's capture template, and encoded frame-by-frame (WebCodecs) in headless Chromium. Same input, same video — locally, in CI, or on a server.
|
package/dist/cli.js
CHANGED
|
@@ -13,9 +13,9 @@ import {
|
|
|
13
13
|
} from "./chunk-A5AN2K5L.js";
|
|
14
14
|
|
|
15
15
|
// src/cli.ts
|
|
16
|
-
import { writeFile } from "fs/promises";
|
|
17
|
-
import { existsSync, readFileSync } from "fs";
|
|
18
|
-
import { basename, dirname, join } from "path";
|
|
16
|
+
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
17
|
+
import { existsSync, readFileSync as readFileSync2 } from "fs";
|
|
18
|
+
import { basename, dirname, join as join2 } from "path";
|
|
19
19
|
import { createServer } from "http";
|
|
20
20
|
import { createRequire } from "module";
|
|
21
21
|
import { fileURLToPath } from "url";
|
|
@@ -45,8 +45,200 @@ 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, writeFileSync } 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
|
+
function readMeta(dir) {
|
|
218
|
+
try {
|
|
219
|
+
return JSON.parse(readFileSync(join(dir, "meta.json"), "utf8"));
|
|
220
|
+
} catch {
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
function writeMeta(dir, patch) {
|
|
225
|
+
const merged = { ...readMeta(dir) ?? {}, ...patch };
|
|
226
|
+
writeFileSync(join(dir, "meta.json"), JSON.stringify(merged, null, 2));
|
|
227
|
+
}
|
|
228
|
+
function formatChanges(changes) {
|
|
229
|
+
const lines = [];
|
|
230
|
+
for (const ch of changes) {
|
|
231
|
+
const label = ch.label ? ` \xB7 ${ch.label}` : "";
|
|
232
|
+
lines.push(
|
|
233
|
+
`v${String(ch.versionNumber ?? "?")} (${ch.origin ?? "unknown"}${label}): ${ch.summary ?? ""}`
|
|
234
|
+
);
|
|
235
|
+
if (ch.note) lines.push(` note: ${ch.note}`);
|
|
236
|
+
}
|
|
237
|
+
return lines;
|
|
238
|
+
}
|
|
239
|
+
|
|
48
240
|
// src/cli.ts
|
|
49
|
-
var BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["json", "help", "version"]);
|
|
241
|
+
var BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["json", "help", "version", "check"]);
|
|
50
242
|
var HELP = `vos \u2014 command line for the vos programmatic video engine (https://vos.so)
|
|
51
243
|
|
|
52
244
|
Usage
|
|
@@ -57,6 +249,27 @@ Usage
|
|
|
57
249
|
vos preview <config.json|url> [--port 0]
|
|
58
250
|
vos versions [--json]
|
|
59
251
|
|
|
252
|
+
Platform (vos.so) \u2014 the iteration loop: fetch, edit, push, pull, repeat
|
|
253
|
+
vos fetch <vosId|watch-url> [--out dir] [--json]
|
|
254
|
+
writes config.json + meta.json (no auth needed for public programs)
|
|
255
|
+
vos check <config.json> [--json]
|
|
256
|
+
migrate \u2192 schema \u2192 compile \u2192 determinism/dialect lints, all local
|
|
257
|
+
vos push <config.json|take> [--vos id] [--title t] [--slug s] [--remix-of id]
|
|
258
|
+
[--note n] [--label l] [--base versionId] [--overrides id,id] [--json]
|
|
259
|
+
no --vos: create a PRIVATE vos (lineage from meta.json / --remix-of)
|
|
260
|
+
with --vos: add a version; the base defaults to the tracked one in
|
|
261
|
+
meta.json, so a stale push 409s WITH the changes made on the platform.
|
|
262
|
+
--overrides consents to touching protected (human-edited) nodes \u2014
|
|
263
|
+
only when the user asked for that change. Take DIRECTORIES push
|
|
264
|
+
through the take pipeline (@vosso/cli) automatically.
|
|
265
|
+
vos pull [dir|take] [--vos id] [--since versionId] [--check] [--json]
|
|
266
|
+
what changed on vos.so since your base: attributed versions with
|
|
267
|
+
typed summaries + the protected node set. Syncs config.json to the
|
|
268
|
+
head (previous copy kept as config.backup.json) and repoints the
|
|
269
|
+
base \u2014 re-apply your edit on top, then push. --check reports only.
|
|
270
|
+
auth: VOS_API_KEY or ~/.config/vos/credentials \u2014 mint at vos.so/app/api;
|
|
271
|
+
keys can never publish (visibility stays private; humans publish on vos.so)
|
|
272
|
+
|
|
60
273
|
Take pipeline \u2014 screen recordings in, polished product video out
|
|
61
274
|
(ships separately: npm i -D @vosso/cli)
|
|
62
275
|
vos create --actions actions.json [out.webm] [--strict] (record + plan + render, one shot)
|
|
@@ -78,7 +291,7 @@ function outName(source, ext) {
|
|
|
78
291
|
}
|
|
79
292
|
async function cmdRender(argv) {
|
|
80
293
|
const first = argv.find((a) => !a.startsWith("-"));
|
|
81
|
-
if (first && existsSync(
|
|
294
|
+
if (first && existsSync(join2(first, "doc.json"))) {
|
|
82
295
|
return delegateTake(["render", ...argv]);
|
|
83
296
|
}
|
|
84
297
|
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS);
|
|
@@ -205,7 +418,7 @@ function packageVersion(name) {
|
|
|
205
418
|
let dir = dirname(entry);
|
|
206
419
|
for (let i = 0; i < 6; i++) {
|
|
207
420
|
try {
|
|
208
|
-
const pkg = JSON.parse(
|
|
421
|
+
const pkg = JSON.parse(readFileSync2(join2(dir, "package.json"), "utf8"));
|
|
209
422
|
if (pkg.name === name && pkg.version) return pkg.version;
|
|
210
423
|
} catch {
|
|
211
424
|
}
|
|
@@ -221,7 +434,7 @@ async function cmdVersions(argv) {
|
|
|
221
434
|
const versions = {};
|
|
222
435
|
try {
|
|
223
436
|
const own = JSON.parse(
|
|
224
|
-
|
|
437
|
+
readFileSync2(fileURLToPath(new URL("../package.json", import.meta.url)), "utf8")
|
|
225
438
|
);
|
|
226
439
|
versions["@vosjs/cli"] = own.version;
|
|
227
440
|
} catch {
|
|
@@ -259,6 +472,310 @@ async function cmdPreview(argv) {
|
|
|
259
472
|
});
|
|
260
473
|
return EXIT_OK;
|
|
261
474
|
}
|
|
475
|
+
async function cmdFetch(argv) {
|
|
476
|
+
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS);
|
|
477
|
+
const source = positionals[0];
|
|
478
|
+
if (!source) throw new UsageError("vos fetch <vosId|watch-url> [--out dir]");
|
|
479
|
+
const r = createReporter(flags.json === true);
|
|
480
|
+
const id = parseVosId(source);
|
|
481
|
+
const key = resolveCredential();
|
|
482
|
+
const meta = await apiJson(`/api/vos/${id}`, { key });
|
|
483
|
+
if (meta.status !== 200) throw new Error(apiError(`fetch vos ${id}`, meta));
|
|
484
|
+
const cfg = await apiJson(`/api/vos/${id}/config`, { key });
|
|
485
|
+
if (cfg.status !== 200) throw new Error(apiError(`fetch config for ${id}`, cfg));
|
|
486
|
+
const vosMeta = meta.body.vos ?? {};
|
|
487
|
+
const slug = typeof vosMeta.slug === "string" && vosMeta.slug ? vosMeta.slug : id;
|
|
488
|
+
const out = flags.out ?? slug;
|
|
489
|
+
await mkdir(out, { recursive: true });
|
|
490
|
+
await writeFile(join2(out, "config.json"), JSON.stringify(cfg.body.config, null, 2));
|
|
491
|
+
await writeFile(join2(out, "meta.json"), JSON.stringify(vosMeta, null, 2));
|
|
492
|
+
const title = typeof vosMeta.title === "string" ? vosMeta.title : "";
|
|
493
|
+
r.done(
|
|
494
|
+
{
|
|
495
|
+
out,
|
|
496
|
+
id,
|
|
497
|
+
slug,
|
|
498
|
+
title,
|
|
499
|
+
currentVersionId: vosMeta.currentVersionId ?? null
|
|
500
|
+
},
|
|
501
|
+
`Wrote ${out}/config.json + meta.json (${title || id})
|
|
502
|
+
Edit config.json, then: vos check ${out}/config.json && vos push ${out}/config.json`
|
|
503
|
+
);
|
|
504
|
+
return EXIT_OK;
|
|
505
|
+
}
|
|
506
|
+
async function cmdCheck(argv) {
|
|
507
|
+
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS);
|
|
508
|
+
const source = positionals[0];
|
|
509
|
+
if (!source) throw new UsageError("vos check <config.json>");
|
|
510
|
+
const r = createReporter(flags.json === true);
|
|
511
|
+
let raw;
|
|
512
|
+
if (/^https?:\/\//.test(source)) {
|
|
513
|
+
const res = await fetch(source);
|
|
514
|
+
if (!res.ok) throw new Error(`fetch ${source} \u2192 ${res.status}`);
|
|
515
|
+
raw = await res.text();
|
|
516
|
+
} else {
|
|
517
|
+
raw = await readFile(source, "utf8");
|
|
518
|
+
}
|
|
519
|
+
let parsed;
|
|
520
|
+
try {
|
|
521
|
+
parsed = JSON.parse(raw);
|
|
522
|
+
} catch (e) {
|
|
523
|
+
parsed = void 0;
|
|
524
|
+
if (!r.json) process.stdout.write(`error [json] ${e.message}
|
|
525
|
+
`);
|
|
526
|
+
r.done({ ok: false, errors: 1, warnings: 0, issues: [{ level: "error", source: "json", message: e.message }] }, `${source}: 1 error`);
|
|
527
|
+
return EXIT_ERROR;
|
|
528
|
+
}
|
|
529
|
+
const result = runCheck(parsed);
|
|
530
|
+
if (r.json) {
|
|
531
|
+
r.done(
|
|
532
|
+
{ ok: result.ok, errors: result.errors, warnings: result.warnings, issues: result.issues },
|
|
533
|
+
""
|
|
534
|
+
);
|
|
535
|
+
} else {
|
|
536
|
+
for (const i of result.issues) {
|
|
537
|
+
process.stdout.write(`${i.level} [${i.source}] ${i.message}
|
|
538
|
+
`);
|
|
539
|
+
}
|
|
540
|
+
process.stdout.write(
|
|
541
|
+
result.ok ? `${source}: ok (${result.warnings} warning${result.warnings === 1 ? "" : "s"})
|
|
542
|
+
` : `${source}: ${result.errors} error${result.errors === 1 ? "" : "s"}, ${result.warnings} warning${result.warnings === 1 ? "" : "s"}
|
|
543
|
+
`
|
|
544
|
+
);
|
|
545
|
+
}
|
|
546
|
+
return result.ok ? EXIT_OK : EXIT_ERROR;
|
|
547
|
+
}
|
|
548
|
+
async function cmdPush(argv) {
|
|
549
|
+
const firstArg = argv.find((a) => !a.startsWith("-"));
|
|
550
|
+
if (firstArg && existsSync(join2(firstArg, "doc.json"))) {
|
|
551
|
+
return delegateTake(["push", ...argv]);
|
|
552
|
+
}
|
|
553
|
+
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS);
|
|
554
|
+
const source = positionals[0];
|
|
555
|
+
if (!source) {
|
|
556
|
+
throw new UsageError(
|
|
557
|
+
"vos push <config.json|take> [--vos id] [--title t] [--slug s] [--remix-of id] [--note n] [--label l] [--base versionId] [--overrides id,id]"
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
const r = createReporter(flags.json === true);
|
|
561
|
+
const dir = dirname(source);
|
|
562
|
+
const parsed = JSON.parse(await readFile(source, "utf8"));
|
|
563
|
+
const check = runCheck(parsed);
|
|
564
|
+
if (!check.ok || !check.config) {
|
|
565
|
+
for (const i of check.issues) {
|
|
566
|
+
if (i.level === "error") r.log(`error [${i.source}] ${i.message}`);
|
|
567
|
+
}
|
|
568
|
+
throw new Error(`config does not validate \u2014 run: vos check ${source}`);
|
|
569
|
+
}
|
|
570
|
+
const config = check.config;
|
|
571
|
+
const key = resolveCredential();
|
|
572
|
+
if (!key) {
|
|
573
|
+
throw new Error(
|
|
574
|
+
"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)"
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
if (flags.vos) {
|
|
578
|
+
const vosId = parseVosId(String(flags.vos));
|
|
579
|
+
const meta2 = readMeta(dir);
|
|
580
|
+
const trackedBase = meta2 && meta2.id === vosId && typeof meta2.currentVersionId === "string" ? meta2.currentVersionId : void 0;
|
|
581
|
+
const body = { config };
|
|
582
|
+
const base = flags.base ? String(flags.base) : trackedBase;
|
|
583
|
+
if (base) body.baseVersionId = base;
|
|
584
|
+
if (flags.note) body.note = String(flags.note);
|
|
585
|
+
if (flags.label) body.label = String(flags.label);
|
|
586
|
+
if (flags.overrides) {
|
|
587
|
+
body.overrides = String(flags.overrides).split(",").map((s) => s.trim()).filter(Boolean);
|
|
588
|
+
}
|
|
589
|
+
const res = await apiJson(`/api/vos/${vosId}/versions`, { method: "POST", key, body });
|
|
590
|
+
if (res.status === 409) {
|
|
591
|
+
const changes = Array.isArray(res.body.changes) ? res.body.changes : [];
|
|
592
|
+
for (const line of formatChanges(changes)) r.log(`platform: ${line}`);
|
|
593
|
+
const protectedIds = Array.isArray(res.body.protected) ? res.body.protected : [];
|
|
594
|
+
const nodes = Array.isArray(res.body.nodes) ? res.body.nodes : [];
|
|
595
|
+
r.event({
|
|
596
|
+
event: "conflict",
|
|
597
|
+
reason: res.body.error ?? "conflict",
|
|
598
|
+
changes,
|
|
599
|
+
protected: protectedIds,
|
|
600
|
+
nodes
|
|
601
|
+
});
|
|
602
|
+
if (res.body.error === "protected_conflict") {
|
|
603
|
+
throw new Error(
|
|
604
|
+
`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`
|
|
605
|
+
);
|
|
606
|
+
}
|
|
607
|
+
throw new Error(
|
|
608
|
+
`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`
|
|
609
|
+
);
|
|
610
|
+
}
|
|
611
|
+
if (res.status !== 201) throw new Error(apiError(`push version to ${vosId}`, res));
|
|
612
|
+
const version = res.body.version ?? {};
|
|
613
|
+
if (typeof version.id === "string") {
|
|
614
|
+
writeMeta(dir, { id: vosId, currentVersionId: version.id });
|
|
615
|
+
}
|
|
616
|
+
const watchUrl = `${PLATFORM_ORIGIN}/vos/${vosId}`;
|
|
617
|
+
const studioUrl = `${PLATFORM_ORIGIN}/studio?vos=${vosId}`;
|
|
618
|
+
r.done(
|
|
619
|
+
{
|
|
620
|
+
id: vosId,
|
|
621
|
+
versionId: version.id ?? null,
|
|
622
|
+
versionNumber: version.versionNumber ?? null,
|
|
623
|
+
base: base ?? null,
|
|
624
|
+
watchUrl,
|
|
625
|
+
studioUrl
|
|
626
|
+
},
|
|
627
|
+
`Pushed version ${String(version.versionNumber ?? "?")} of ${vosId}
|
|
628
|
+
watch: ${watchUrl}
|
|
629
|
+
studio: ${studioUrl}`
|
|
630
|
+
);
|
|
631
|
+
return EXIT_OK;
|
|
632
|
+
}
|
|
633
|
+
let meta = {};
|
|
634
|
+
try {
|
|
635
|
+
meta = JSON.parse(await readFile(join2(dirname(source), "meta.json"), "utf8"));
|
|
636
|
+
} catch {
|
|
637
|
+
}
|
|
638
|
+
const remixOfId = flags["remix-of"] ? String(flags["remix-of"]) : typeof meta.id === "string" ? meta.id : void 0;
|
|
639
|
+
const fallbackTitle = typeof meta.title === "string" && meta.title ? `${meta.title} remix` : basename(source).replace(/\.json$/i, "") || "vos remix";
|
|
640
|
+
const title = (flags.title ?? fallbackTitle).slice(0, 100);
|
|
641
|
+
const slugGiven = typeof flags.slug === "string";
|
|
642
|
+
const baseSlug = slugGiven ? flags.slug : deriveSlug(title);
|
|
643
|
+
for (let attempt = 0; ; attempt++) {
|
|
644
|
+
const slug = attempt === 0 ? baseSlug : `${baseSlug}-${attempt + 1}`.slice(0, 50);
|
|
645
|
+
const body = {
|
|
646
|
+
title,
|
|
647
|
+
slug,
|
|
648
|
+
visibility: "private",
|
|
649
|
+
config
|
|
650
|
+
};
|
|
651
|
+
if (remixOfId) body.remixOfId = remixOfId;
|
|
652
|
+
const res = await apiJson("/api/vos", { method: "POST", key, body });
|
|
653
|
+
if (res.status === 409 && !slugGiven && attempt < 3) {
|
|
654
|
+
r.log(`slug "${slug}" is taken \u2014 retrying`);
|
|
655
|
+
continue;
|
|
656
|
+
}
|
|
657
|
+
if (res.status !== 201) throw new Error(apiError("push vos", res));
|
|
658
|
+
const created = res.body.vos ?? {};
|
|
659
|
+
const id = String(created.id ?? "");
|
|
660
|
+
writeMeta(dir, {
|
|
661
|
+
id,
|
|
662
|
+
currentVersionId: created.currentVersionId ?? null,
|
|
663
|
+
title,
|
|
664
|
+
slug: created.slug ?? slug,
|
|
665
|
+
...remixOfId ? { remixOfId } : {}
|
|
666
|
+
});
|
|
667
|
+
const watchUrl = `${PLATFORM_ORIGIN}/vos/${id}`;
|
|
668
|
+
const studioUrl = `${PLATFORM_ORIGIN}/studio?vos=${id}`;
|
|
669
|
+
r.done(
|
|
670
|
+
{
|
|
671
|
+
id,
|
|
672
|
+
slug: created.slug ?? slug,
|
|
673
|
+
title,
|
|
674
|
+
visibility: created.visibility ?? "private",
|
|
675
|
+
remixOfId: remixOfId ?? null,
|
|
676
|
+
currentVersionId: created.currentVersionId ?? null,
|
|
677
|
+
watchUrl,
|
|
678
|
+
studioUrl
|
|
679
|
+
},
|
|
680
|
+
`Created private vos ${id} (${title})
|
|
681
|
+
watch: ${watchUrl}
|
|
682
|
+
studio: ${studioUrl}
|
|
683
|
+
Iterate with: vos push ${source} --vos ${id}`
|
|
684
|
+
);
|
|
685
|
+
return EXIT_OK;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
async function cmdPull(argv) {
|
|
689
|
+
const firstPos = argv.find((a) => !a.startsWith("-"));
|
|
690
|
+
if (firstPos && existsSync(join2(firstPos, "doc.json")) || !firstPos && existsSync("doc.json")) {
|
|
691
|
+
return delegateTake(["pull", ...argv]);
|
|
692
|
+
}
|
|
693
|
+
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS);
|
|
694
|
+
const target = positionals[0] ?? ".";
|
|
695
|
+
const dir = target.endsWith(".json") ? dirname(target) : target;
|
|
696
|
+
const r = createReporter(flags.json === true);
|
|
697
|
+
const meta = readMeta(dir);
|
|
698
|
+
const vosId = flags.vos ? parseVosId(String(flags.vos)) : typeof meta?.id === "string" ? meta.id : null;
|
|
699
|
+
if (!vosId) {
|
|
700
|
+
throw new UsageError(
|
|
701
|
+
`no tracked vos in ${dir}/meta.json \u2014 pass --vos <id>, or fetch/push first`
|
|
702
|
+
);
|
|
703
|
+
}
|
|
704
|
+
const since = flags.since ? String(flags.since) : typeof meta?.currentVersionId === "string" ? meta.currentVersionId : null;
|
|
705
|
+
if (!since) {
|
|
706
|
+
throw new UsageError(
|
|
707
|
+
`no base version in ${dir}/meta.json \u2014 pass --since <versionId>`
|
|
708
|
+
);
|
|
709
|
+
}
|
|
710
|
+
const key = resolveCredential();
|
|
711
|
+
if (!key) {
|
|
712
|
+
throw new Error(
|
|
713
|
+
"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)"
|
|
714
|
+
);
|
|
715
|
+
}
|
|
716
|
+
const res = await apiJson(`/api/vos/${vosId}/changes?since=${encodeURIComponent(since)}`, {
|
|
717
|
+
key
|
|
718
|
+
});
|
|
719
|
+
if (res.status !== 200) throw new Error(apiError(`pull changes for ${vosId}`, res));
|
|
720
|
+
const head = res.body.head ?? {};
|
|
721
|
+
const changes = Array.isArray(res.body.changes) ? res.body.changes : [];
|
|
722
|
+
const protectedIds = Array.isArray(res.body.protected) ? res.body.protected : [];
|
|
723
|
+
if (changes.length === 0) {
|
|
724
|
+
r.done(
|
|
725
|
+
{ id: vosId, upToDate: true, head: head.id ?? since },
|
|
726
|
+
`${vosId}: up to date (base ${since.slice(0, 8)}\u2026 is the head)`
|
|
727
|
+
);
|
|
728
|
+
return EXIT_OK;
|
|
729
|
+
}
|
|
730
|
+
for (const line of formatChanges(changes)) r.log(line);
|
|
731
|
+
if (protectedIds.length) {
|
|
732
|
+
r.log(
|
|
733
|
+
`protected (human-edited \u2014 keep their values unless asked): ${protectedIds.join(", ")}`
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
if (res.body.truncated === true) {
|
|
737
|
+
r.log("walk truncated \u2014 more versions exist; pull again after syncing");
|
|
738
|
+
}
|
|
739
|
+
if (flags.check === true) {
|
|
740
|
+
r.done(
|
|
741
|
+
{
|
|
742
|
+
id: vosId,
|
|
743
|
+
upToDate: false,
|
|
744
|
+
versions: changes.length,
|
|
745
|
+
head: head.id ?? null,
|
|
746
|
+
protected: protectedIds,
|
|
747
|
+
changes
|
|
748
|
+
},
|
|
749
|
+
`${changes.length} version${changes.length === 1 ? "" : "s"} behind \u2014 run without --check to sync`
|
|
750
|
+
);
|
|
751
|
+
return EXIT_OK;
|
|
752
|
+
}
|
|
753
|
+
const cfg = await apiJson(`/api/vos/${vosId}/config`, { key });
|
|
754
|
+
if (cfg.status !== 200) throw new Error(apiError(`fetch head config for ${vosId}`, cfg));
|
|
755
|
+
const configPath = join2(dir, "config.json");
|
|
756
|
+
let backedUp = false;
|
|
757
|
+
if (existsSync(configPath)) {
|
|
758
|
+
await writeFile(join2(dir, "config.backup.json"), await readFile(configPath));
|
|
759
|
+
backedUp = true;
|
|
760
|
+
}
|
|
761
|
+
await writeFile(configPath, JSON.stringify(cfg.body.config, null, 2));
|
|
762
|
+
writeMeta(dir, { id: vosId, currentVersionId: head.id ?? since });
|
|
763
|
+
r.done(
|
|
764
|
+
{
|
|
765
|
+
id: vosId,
|
|
766
|
+
upToDate: false,
|
|
767
|
+
versions: changes.length,
|
|
768
|
+
head: head.id ?? null,
|
|
769
|
+
protected: protectedIds,
|
|
770
|
+
changes,
|
|
771
|
+
out: configPath,
|
|
772
|
+
backup: backedUp ? join2(dir, "config.backup.json") : null
|
|
773
|
+
},
|
|
774
|
+
`Pulled ${changes.length} version${changes.length === 1 ? "" : "s"} \u2192 ${configPath}` + (backedUp ? ` (previous copy: config.backup.json)` : "") + `
|
|
775
|
+
Re-apply your edit on the new head, then: vos push ${configPath} --vos ${vosId}`
|
|
776
|
+
);
|
|
777
|
+
return EXIT_OK;
|
|
778
|
+
}
|
|
262
779
|
var TAKE_VERBS = /* @__PURE__ */ new Set(["create", "record", "plan", "frames", "open", "validate"]);
|
|
263
780
|
async function delegateTake(argv, viaAlias = false) {
|
|
264
781
|
for (const name of ["@vosso/cli", "@vosso/voila-cli"]) {
|
|
@@ -302,6 +819,14 @@ async function main() {
|
|
|
302
819
|
return cmdVersions(rest);
|
|
303
820
|
case "preview":
|
|
304
821
|
return cmdPreview(rest);
|
|
822
|
+
case "fetch":
|
|
823
|
+
return cmdFetch(rest);
|
|
824
|
+
case "check":
|
|
825
|
+
return cmdCheck(rest);
|
|
826
|
+
case "push":
|
|
827
|
+
return cmdPush(rest);
|
|
828
|
+
case "pull":
|
|
829
|
+
return cmdPull(rest);
|
|
305
830
|
// Hidden alias for existing scripts; not in HELP. Same code path as the
|
|
306
831
|
// promoted verbs, plus a one-line pointer at the new spelling.
|
|
307
832
|
case "voila":
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/output.ts"],"sourcesContent":["import { writeFile } from 'node:fs/promises'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { basename, dirname, join } from 'node:path'\nimport { createServer } from 'node:http'\nimport { createRequire } from 'node:module'\nimport { fileURLToPath } from 'node:url'\nimport { parseArgs, numFlag, UsageError } from './args'\nimport {\n createReporter,\n EXIT_ERROR,\n EXIT_NO_BROWSER,\n EXIT_OK,\n EXIT_USAGE,\n} from './output'\nimport { loadVosConfig, configDuration } from './loadConfig'\nimport { launchBrowser, BrowserUnavailableError } from './browser'\nimport { renderVideo, renderStill, previewPages } from './render'\n\nconst BOOLEAN_FLAGS = new Set(['json', 'help', 'version'])\n\nconst HELP = `vos — command line for the vos programmatic video engine (https://vos.so)\n\nUsage\n vos render <config.json|url|take> [out] [--width 1920] [--height 1080] [--fps 30]\n [--duration <s>] [--format webm|mp4] [--json]\n vos still <config.json|url> [out.webp] [--time 0] [--width] [--height] [--json]\n vos info <config.json|url> [--json]\n vos preview <config.json|url> [--port 0]\n vos versions [--json]\n\nTake pipeline — screen recordings in, polished product video out\n(ships separately: npm i -D @vosso/cli)\n vos create --actions actions.json [out.webm] [--strict] (record + plan + render, one shot)\n vos record --actions actions.json [--out take] [--strict]\n vos plan <take> [--fresh]\n vos frames <take> [--at-zooms | --frame <t> --size WxH]\n vos open <take> (serve the take into the studio at vos.so)\n vos validate <actions.json|take>\n vos render <take> [out] (a take directory is detected by its doc.json)\n\nConventions\n Results go to stdout; logs go to stderr. --json switches stdout to NDJSON\n events ending with {\"event\":\"done\",…}. Exit codes: 0 ok, 1 error, 2 usage,\n 3 no browser available.\n`\n\nfunction outName(source: string, ext: string): string {\n const base = basename(source).replace(/\\.[a-z0-9]+$/i, '') || 'vos'\n return `${base}.${ext}`\n}\n\nasync function cmdRender(argv: string[]): Promise<number> {\n // Polymorphic render: a take DIRECTORY (detected by its doc.json — the take\n // pipeline's editable document) renders through the take pipeline; anything\n // else is an engine config render. A deterministic sniff, never a flag.\n const first = argv.find((a) => !a.startsWith('-'))\n if (first && existsSync(join(first, 'doc.json'))) {\n return delegateTake(['render', ...argv])\n }\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const source = positionals[0]\n if (!source) throw new UsageError('vos render <config.json|url|take> [out]')\n const r = createReporter(flags.json === true)\n const format = (flags.format as string) ?? 'webm'\n if (format !== 'webm' && format !== 'mp4') throw new UsageError('--format must be webm or mp4')\n\n const { config, warnings } = await loadVosConfig(source)\n for (const w of warnings) r.log(`note: ${w}`)\n const duration = numFlag(flags, 'duration', configDuration(config) ?? 5)\n const width = numFlag(flags, 'width', 1920)\n const height = numFlag(flags, 'height', 1080)\n const fps = numFlag(flags, 'fps', 30)\n const out = positionals[1] ?? outName(source, format)\n\n const browser = await launchBrowser()\n try {\n const result = await renderVideo(browser, {\n config,\n width,\n height,\n fps,\n duration,\n format,\n onPhase: (phase) => {\n r.log(`${phase}…`)\n r.event({ event: 'phase', phase })\n },\n })\n await writeFile(out, result.bytes)\n r.done(\n { out, bytes: result.bytes.length, width, height, fps, duration, format },\n `Wrote ${out} (${(result.bytes.length / 1024).toFixed(0)} KB, ${width}x${height}@${fps}, ${duration}s)`,\n )\n return EXIT_OK\n } finally {\n await browser.close()\n }\n}\n\nasync function cmdStill(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const source = positionals[0]\n if (!source) throw new UsageError('vos still <config.json|url> [out.webp]')\n const r = createReporter(flags.json === true)\n\n const { config, warnings } = await loadVosConfig(source)\n for (const w of warnings) r.log(`note: ${w}`)\n const time = numFlag(flags, 'time', 0)\n const width = numFlag(flags, 'width', 1280)\n const height = numFlag(flags, 'height', 720)\n const out = positionals[1] ?? outName(source, 'webp')\n\n const browser = await launchBrowser()\n try {\n const result = await renderStill(browser, {\n config,\n width,\n height,\n time,\n onPhase: (phase) => {\n r.log(`${phase}…`)\n r.event({ event: 'phase', phase })\n },\n })\n await writeFile(out, result.bytes)\n r.done(\n { out, bytes: result.bytes.length, width, height, time, mimeType: result.mimeType },\n `Wrote ${out} (${(result.bytes.length / 1024).toFixed(0)} KB, ${width}x${height} @ t=${time}s)`,\n )\n return EXIT_OK\n } finally {\n await browser.close()\n }\n}\n\nasync function cmdInfo(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const source = positionals[0]\n if (!source) throw new UsageError('vos info <config.json|url>')\n const r = createReporter(flags.json === true)\n\n const { config, warnings } = await loadVosConfig(source)\n const elements = Array.isArray(config.elements) ? config.elements.length : 0\n const data = typeof config.data === 'object' && config.data !== null ? Object.keys(config.data) : []\n const fns = ['setup', 'createContent', 'createTimeline', 'onFrame'].filter(\n (k) => typeof config[k] === 'string',\n )\n const info = {\n version: config.version,\n duration: configDuration(config) ?? null,\n camera: (config.camera as Record<string, unknown> | undefined)?.preset ?? null,\n elements,\n dataKeys: data,\n functions: fns,\n warnings,\n }\n if (r.json) r.done(info, '')\n else {\n for (const w of warnings) r.log(`note: ${w}`)\n process.stdout.write(\n `version: v${String(info.version)}\\n` +\n `duration: ${info.duration === null ? '(none)' : `${info.duration}s`}\\n` +\n `camera: ${String(info.camera ?? '(default)')}\\n` +\n `elements: ${elements}\\n` +\n `data keys: ${data.length ? data.join(', ') : '(none)'}\\n` +\n `functions: ${fns.join(', ')}\\n`,\n )\n }\n return EXIT_OK\n}\n\nfunction packageVersion(name: string): string | null {\n const require = createRequire(import.meta.url)\n // Fast path — packages that export ./package.json (e.g. playwright).\n try {\n return (require(`${name}/package.json`) as { version: string }).version\n } catch {\n // Strict `exports` maps (the @vosjs packages) hide package.json — resolve\n // the entry module instead and walk up to the owning package.json.\n }\n let entry: string | null = null\n try {\n entry = fileURLToPath(import.meta.resolve(name))\n } catch {\n try {\n entry = require.resolve(name)\n } catch {\n return null\n }\n }\n let dir = dirname(entry)\n for (let i = 0; i < 6; i++) {\n try {\n const pkg = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')) as {\n name?: string\n version?: string\n }\n if (pkg.name === name && pkg.version) return pkg.version\n } catch {\n // keep walking\n }\n const parent = dirname(dir)\n if (parent === dir) return null\n dir = parent\n }\n return null\n}\n\nasync function cmdVersions(argv: string[]): Promise<number> {\n const { flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const r = createReporter(flags.json === true)\n const versions: Record<string, string> = {}\n // Own version: read relative to dist (self-require is blocked by `exports`).\n try {\n const own = JSON.parse(\n readFileSync(fileURLToPath(new URL('../package.json', import.meta.url)), 'utf8'),\n ) as { version: string }\n versions['@vosjs/cli'] = own.version\n } catch {\n versions['@vosjs/cli'] = '(unknown)'\n }\n for (const name of ['@vosjs/core', '@vosjs/elements', '@vosjs/tween', 'playwright']) {\n versions[name] = packageVersion(name) ?? '(not found)'\n }\n if (r.json) r.done({ versions }, '')\n else for (const [k, v] of Object.entries(versions)) process.stdout.write(`${k} ${v}\\n`)\n return EXIT_OK\n}\n\nasync function cmdPreview(argv: string[]): Promise<number> {\n const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS)\n const source = positionals[0]\n if (!source) throw new UsageError('vos preview <config.json|url> [--port 0]')\n const r = createReporter(false)\n const { config, warnings } = await loadVosConfig(source)\n for (const w of warnings) r.log(`note: ${w}`)\n const { hostHtml, playerHtml } = previewPages(config)\n const server = createServer((req, res) => {\n const path = new URL(req.url ?? '/', 'http://x').pathname\n res.writeHead(200, { 'content-type': 'text/html' })\n res.end(path === '/player' ? playerHtml : hostHtml)\n })\n const port = numFlag(flags, 'port', 0)\n await new Promise<void>((resolve) => server.listen(port, resolve))\n const addr = server.address()\n const url = `http://localhost:${typeof addr === 'object' && addr ? addr.port : port}/`\n process.stdout.write(`${url}\\n`)\n r.log('Serving playback preview — Ctrl-C to stop.')\n await new Promise(() => {}) // keep alive until interrupted\n return EXIT_OK\n}\n\n// The take pipeline's verbs live in @vosso/cli (published; previously\n// @vosso/voila-cli, kept as an install fallback during the transition).\n// The delegation contract is its `run(argv)` export.\nconst TAKE_VERBS = new Set(['create', 'record', 'plan', 'frames', 'open', 'validate'])\n\nasync function delegateTake(argv: string[], viaAlias = false): Promise<number> {\n for (const name of ['@vosso/cli', '@vosso/voila-cli']) {\n let mod: { run?: (argv: string[]) => Promise<number> }\n try {\n mod = (await import(name as string)) as typeof mod\n } catch {\n continue\n }\n if (typeof mod.run !== 'function') continue\n if (viaAlias && argv[0]) {\n process.stderr.write(`note: \"vos voila ${argv[0]}\" is now \"vos ${argv[0]}\".\\n`)\n }\n return await mod.run(argv)\n }\n process.stderr.write(\n 'The take pipeline (screen recordings in, product video out) ships separately.\\n' +\n ' npm i -D @vosso/cli\\n' +\n `then re-run: vos ${argv.join(' ')}\\n`,\n )\n return EXIT_ERROR\n}\n\nasync function main(): Promise<number> {\n const [cmd, ...rest] = process.argv.slice(2)\n if (!cmd || cmd === 'help' || cmd === '--help' || cmd === '-h') {\n process.stdout.write(HELP)\n return cmd ? EXIT_OK : EXIT_USAGE\n }\n if (cmd === '--version') return cmdVersions(['--json'])\n if (TAKE_VERBS.has(cmd)) return delegateTake([cmd, ...rest])\n switch (cmd) {\n case 'render':\n return cmdRender(rest)\n case 'still':\n return cmdStill(rest)\n case 'info':\n return cmdInfo(rest)\n case 'versions':\n return cmdVersions(rest)\n case 'preview':\n return cmdPreview(rest)\n // Hidden alias for existing scripts; not in HELP. Same code path as the\n // promoted verbs, plus a one-line pointer at the new spelling.\n case 'voila':\n return delegateTake(rest, true)\n default:\n throw new UsageError(`unknown command \"${cmd}\" — run vos help`)\n }\n}\n\nmain()\n .then((code) => process.exit(code))\n .catch((e) => {\n if (e instanceof UsageError) {\n process.stderr.write(`usage error: ${e.message}\\n`)\n process.exit(EXIT_USAGE)\n }\n if (e instanceof BrowserUnavailableError) {\n process.stderr.write(`${e.message}\\n`)\n process.exit(EXIT_NO_BROWSER)\n }\n process.stderr.write(`error: ${e instanceof Error ? e.message : String(e)}\\n`)\n process.exit(EXIT_ERROR)\n })\n","/**\n * Output conventions (agent-safe by construction):\n * - logs/progress → stderr (human readable)\n * - results → stdout; with --json, NDJSON events (`{\"event\":\"phase\"...}` then\n * `{\"event\":\"done\"...}`) so scripts and agents never parse prose\n * - exit codes: 0 ok · 1 failure · 2 usage · 3 browser unavailable\n */\nexport const EXIT_OK = 0\nexport const EXIT_ERROR = 1\nexport const EXIT_USAGE = 2\nexport const EXIT_NO_BROWSER = 3\n\nexport interface Reporter {\n json: boolean\n /** Human log line (stderr; suppressed in --json mode). */\n log: (msg: string) => void\n /** Machine event (stdout NDJSON in --json mode; no-op otherwise). */\n event: (obj: Record<string, unknown>) => void\n /** Final result: NDJSON `done` event in --json mode, plain line otherwise. */\n done: (obj: Record<string, unknown>, humanLine: string) => void\n}\n\nexport function createReporter(json: boolean): Reporter {\n return {\n json,\n log: (msg) => {\n if (!json) process.stderr.write(`${msg}\\n`)\n },\n event: (obj) => {\n if (json) process.stdout.write(`${JSON.stringify(obj)}\\n`)\n },\n done: (obj, humanLine) => {\n if (json) process.stdout.write(`${JSON.stringify({ event: 'done', ...obj })}\\n`)\n else process.stdout.write(`${humanLine}\\n`)\n },\n }\n}\n"],"mappings":"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","names":["require"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/output.ts","../src/check.ts","../src/platform.ts"],"sourcesContent":["import { mkdir, readFile, writeFile } from 'node:fs/promises'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { basename, dirname, join } from 'node:path'\nimport { createServer } from 'node:http'\nimport { createRequire } from 'node:module'\nimport { fileURLToPath } from 'node:url'\nimport { parseArgs, numFlag, UsageError } from './args'\nimport {\n createReporter,\n EXIT_ERROR,\n EXIT_NO_BROWSER,\n EXIT_OK,\n EXIT_USAGE,\n} from './output'\nimport { loadVosConfig, configDuration } from './loadConfig'\nimport { launchBrowser, BrowserUnavailableError } from './browser'\nimport { renderVideo, renderStill, previewPages } from './render'\nimport { runCheck } from './check'\nimport {\n PLATFORM_ORIGIN,\n apiError,\n apiJson,\n deriveSlug,\n 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 } 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, 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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vosjs/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.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/elements": "^0.3.1",
|
|
46
45
|
"@vosjs/core": "^0.10.0",
|
|
47
|
-
"@vosjs/tween": "^0.7.2"
|
|
46
|
+
"@vosjs/tween": "^0.7.2",
|
|
47
|
+
"@vosjs/elements": "^0.3.1"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@types/node": "^22",
|