@vosjs/cli 0.59.1 → 0.60.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/assetManifest-Y5FYTZW6.js +15 -0
- package/dist/{chunk-YC3LY4LW.js → chunk-LWHVZ5WI.js} +54 -539
- package/dist/chunk-LWHVZ5WI.js.map +1 -0
- package/dist/{chunk-CYU7LVPB.js → chunk-QL25OPZB.js} +455 -923
- package/dist/chunk-QL25OPZB.js.map +1 -0
- package/dist/chunk-WCF6KIOK.js +770 -0
- package/dist/chunk-WCF6KIOK.js.map +1 -0
- package/dist/chunk-YMVRTZ4L.js +719 -0
- package/dist/chunk-YMVRTZ4L.js.map +1 -0
- package/dist/cli.js +72 -16
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.js +15 -11
- package/dist/{run-TVTM3QJW.js → run-BJ77A4G6.js} +5 -3
- package/dist/run-BJ77A4G6.js.map +1 -0
- package/package.json +4 -4
- package/skills/VERSION +1 -1
- package/skills/vos-authoring/references/schema-reference.md +40 -2
- package/skills/vos-port/SKILL.md +3 -1
- package/skills/vos-port/references/elements-and-context.md +5 -0
- package/skills/vos-port/references/hyperframes.md +1 -1
- package/skills/vos-port/references/remotion.md +1 -1
- package/dist/chunk-CYU7LVPB.js.map +0 -1
- package/dist/chunk-YC3LY4LW.js.map +0 -1
- /package/dist/{run-TVTM3QJW.js.map → assetManifest-Y5FYTZW6.js.map} +0 -0
|
@@ -1,135 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return new Proxy(bag, {
|
|
8
|
-
get(target, key, receiver) {
|
|
9
|
-
if (typeof key === "string") used.add(key);
|
|
10
|
-
return Reflect.get(target, key, receiver);
|
|
11
|
-
},
|
|
12
|
-
has(target, key) {
|
|
13
|
-
if (typeof key === "string") used.add(key);
|
|
14
|
-
return Reflect.has(target, key);
|
|
15
|
-
},
|
|
16
|
-
// hasOwnProperty.call(flags, name) lands here.
|
|
17
|
-
getOwnPropertyDescriptor(target, key) {
|
|
18
|
-
if (typeof key === "string") used.add(key);
|
|
19
|
-
return Reflect.getOwnPropertyDescriptor(target, key);
|
|
20
|
-
},
|
|
21
|
-
// A spread, Object.keys or JSON.stringify hands every flag onward; what
|
|
22
|
-
// happens to them after that cannot be seen, so they all count as read.
|
|
23
|
-
ownKeys(target) {
|
|
24
|
-
for (const key of Reflect.ownKeys(target))
|
|
25
|
-
if (typeof key === "string") used.add(key);
|
|
26
|
-
return Reflect.ownKeys(target);
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
function noteGivenFlag(name) {
|
|
31
|
-
given.add(name);
|
|
32
|
-
}
|
|
33
|
-
function unusedFlags() {
|
|
34
|
-
return [...given].filter((name) => !used.has(name) && name !== "help");
|
|
35
|
-
}
|
|
36
|
-
function helpFlagsFor(help, verb) {
|
|
37
|
-
const out = /* @__PURE__ */ new Set();
|
|
38
|
-
let inVerb = false;
|
|
39
|
-
for (const line of help.split("\n")) {
|
|
40
|
-
const head = /^\s{2}vos\s+(\S+)/.exec(line);
|
|
41
|
-
if (head) inVerb = head[1] === verb;
|
|
42
|
-
else if (!/^\s{3,}\S/.test(line)) inVerb = false;
|
|
43
|
-
if (!inVerb) continue;
|
|
44
|
-
for (const m of line.matchAll(/--([a-z][a-z0-9-]*)/g)) out.add(m[1]);
|
|
45
|
-
}
|
|
46
|
-
return [...out];
|
|
47
|
-
}
|
|
48
|
-
function editDistance(a, b) {
|
|
49
|
-
const row = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
50
|
-
for (let i = 1; i <= a.length; i++) {
|
|
51
|
-
let prev = row[0];
|
|
52
|
-
row[0] = i;
|
|
53
|
-
for (let j = 1; j <= b.length; j++) {
|
|
54
|
-
const keep = row[j];
|
|
55
|
-
row[j] = Math.min(
|
|
56
|
-
row[j] + 1,
|
|
57
|
-
row[j - 1] + 1,
|
|
58
|
-
prev + (a[i - 1] === b[j - 1] ? 0 : 1)
|
|
59
|
-
);
|
|
60
|
-
prev = keep;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
return row[b.length];
|
|
64
|
-
}
|
|
65
|
-
function nearestFlag(name, candidates) {
|
|
66
|
-
let best = null;
|
|
67
|
-
let bestScore = Infinity;
|
|
68
|
-
for (const c of candidates) {
|
|
69
|
-
if (c === name) continue;
|
|
70
|
-
const d = c.includes(name) || name.includes(c) ? 1 : editDistance(name, c);
|
|
71
|
-
if (d < bestScore) {
|
|
72
|
-
bestScore = d;
|
|
73
|
-
best = c;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return best !== null && bestScore <= Math.max(2, Math.floor(name.length / 3)) ? best : null;
|
|
77
|
-
}
|
|
78
|
-
function unusedFlagsMessage(verb, documented) {
|
|
79
|
-
const unused = unusedFlags();
|
|
80
|
-
if (!unused.length) return null;
|
|
81
|
-
const parts = unused.map((name) => {
|
|
82
|
-
const near = nearestFlag(name, documented);
|
|
83
|
-
return `--${name}${near ? ` (did you mean --${near}?)` : ""}`;
|
|
84
|
-
});
|
|
85
|
-
const list = documented.length ? ` It reads: ${documented.map((f) => `--${f}`).join(" ")}.` : "";
|
|
86
|
-
return `vos ${verb} RAN, and ignored ${parts.join(", ")}: ${unused.length > 1 ? "they are" : "it is"} not something this verb reads, so what it printed above was made without ${unused.length > 1 ? "them" : "it"}.${list}`;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// src/args.ts
|
|
90
|
-
var UsageError = class extends Error {
|
|
91
|
-
};
|
|
92
|
-
function parseArgs(argv, booleanFlags) {
|
|
93
|
-
const positionals = [];
|
|
94
|
-
const flags = {};
|
|
95
|
-
for (let i = 0; i < argv.length; i++) {
|
|
96
|
-
const arg = argv[i];
|
|
97
|
-
if (arg === "--") {
|
|
98
|
-
positionals.push(...argv.slice(i + 1));
|
|
99
|
-
break;
|
|
100
|
-
}
|
|
101
|
-
if (arg.startsWith("--")) {
|
|
102
|
-
const eq = arg.indexOf("=");
|
|
103
|
-
if (eq !== -1) {
|
|
104
|
-
flags[arg.slice(2, eq)] = arg.slice(eq + 1);
|
|
105
|
-
continue;
|
|
106
|
-
}
|
|
107
|
-
const name = arg.slice(2);
|
|
108
|
-
if (booleanFlags.has(name)) {
|
|
109
|
-
flags[name] = true;
|
|
110
|
-
continue;
|
|
111
|
-
}
|
|
112
|
-
const next = argv[i + 1];
|
|
113
|
-
if (next === void 0 || next.startsWith("--")) {
|
|
114
|
-
throw new UsageError(`--${name} expects a value`);
|
|
115
|
-
}
|
|
116
|
-
flags[name] = next;
|
|
117
|
-
i++;
|
|
118
|
-
continue;
|
|
119
|
-
}
|
|
120
|
-
positionals.push(arg);
|
|
121
|
-
}
|
|
122
|
-
for (const name of Object.keys(flags)) noteGivenFlag(name);
|
|
123
|
-
return { positionals, flags: trackFlags(flags) };
|
|
124
|
-
}
|
|
125
|
-
function numFlag(flags, name, fallback) {
|
|
126
|
-
const v = flags[name];
|
|
127
|
-
if (v === void 0) return fallback;
|
|
128
|
-
const n = Number(v);
|
|
129
|
-
if (!Number.isFinite(n))
|
|
130
|
-
throw new UsageError(`--${name} expects a number, got "${String(v)}"`);
|
|
131
|
-
return n;
|
|
132
|
-
}
|
|
2
|
+
import {
|
|
3
|
+
ASSET_ROUTE,
|
|
4
|
+
UsageError,
|
|
5
|
+
serveFile
|
|
6
|
+
} from "./chunk-WCF6KIOK.js";
|
|
133
7
|
|
|
134
8
|
// src/loadConfig.ts
|
|
135
9
|
import { readFile } from "fs/promises";
|
|
@@ -326,8 +200,31 @@ function stillWarnings(picture, pageErrors, engineNotes = []) {
|
|
|
326
200
|
out.push(`the page threw ${pageErrors.length - 3} more errors`);
|
|
327
201
|
return out;
|
|
328
202
|
}
|
|
329
|
-
function compile(config) {
|
|
330
|
-
return compileVosConfig(config, { tweenEngine: "vos" });
|
|
203
|
+
function compile(config, assets) {
|
|
204
|
+
if (!assets) return compileVosConfig(config, { tweenEngine: "vos" });
|
|
205
|
+
const byRef = /* @__PURE__ */ new Map();
|
|
206
|
+
const manifest = config.assets ?? {};
|
|
207
|
+
for (const [name, decl] of Object.entries(manifest)) {
|
|
208
|
+
const got = assets.assets[name];
|
|
209
|
+
const refs = Array.isArray(decl.ref) ? decl.ref : [decl.ref];
|
|
210
|
+
const urls = Array.isArray(got) ? got : [got];
|
|
211
|
+
refs.forEach((ref, i) => {
|
|
212
|
+
if (typeof urls[i] === "string") byRef.set(`${name}\0${ref}`, urls[i]);
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
return compileVosConfig(config, {
|
|
216
|
+
tweenEngine: "vos",
|
|
217
|
+
resolveAssetRef: (ref, name) => byRef.get(`${name}\0${ref}`) ?? ref
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
function captureAssets(assets) {
|
|
221
|
+
if (!assets) return {};
|
|
222
|
+
const absolute = (url) => url.startsWith(ASSET_ROUTE) ? `${RENDER_ORIGIN}${url}` : url;
|
|
223
|
+
const out = {};
|
|
224
|
+
for (const [name, url] of Object.entries(assets.assets)) {
|
|
225
|
+
out[name] = Array.isArray(url) ? url.map(absolute) : absolute(url);
|
|
226
|
+
}
|
|
227
|
+
return { assets: out };
|
|
331
228
|
}
|
|
332
229
|
async function runCapturePage(browser, html, opts) {
|
|
333
230
|
const context = await browser.newContext({
|
|
@@ -350,6 +247,18 @@ async function runCapturePage(browser, html, opts) {
|
|
|
350
247
|
`${RENDER_ORIGIN}/**`,
|
|
351
248
|
(route) => route.fulfill({ status: 200, contentType: "text/html", body: html })
|
|
352
249
|
);
|
|
250
|
+
const files = opts.files ?? {};
|
|
251
|
+
if (Object.keys(files).length > 0) {
|
|
252
|
+
await page.route(`${RENDER_ORIGIN}${ASSET_ROUTE}**`, async (route) => {
|
|
253
|
+
const request = route.request();
|
|
254
|
+
const file = files[new URL(request.url()).pathname];
|
|
255
|
+
if (!file) {
|
|
256
|
+
return route.fulfill({ status: 404, body: "no such declared file" });
|
|
257
|
+
}
|
|
258
|
+
const answer = serveFile(file, await request.headerValue("range"));
|
|
259
|
+
return route.fulfill(answer);
|
|
260
|
+
});
|
|
261
|
+
}
|
|
353
262
|
await page.goto(`${RENDER_ORIGIN}/render`, {
|
|
354
263
|
waitUntil: "domcontentloaded"
|
|
355
264
|
});
|
|
@@ -395,7 +304,8 @@ async function renderVideo(browser, opts) {
|
|
|
395
304
|
duration: opts.duration,
|
|
396
305
|
fps: opts.fps,
|
|
397
306
|
format: opts.format,
|
|
398
|
-
...opts.audioProducerCode ? { audioProducerCode: opts.audioProducerCode } : {}
|
|
307
|
+
...opts.audioProducerCode ? { audioProducerCode: opts.audioProducerCode } : {},
|
|
308
|
+
...captureAssets(opts.assets)
|
|
399
309
|
},
|
|
400
310
|
elementsBundleCode,
|
|
401
311
|
tweenEngine: "vos",
|
|
@@ -406,7 +316,8 @@ async function renderVideo(browser, opts) {
|
|
|
406
316
|
const done = await runCapturePage(browser, html, {
|
|
407
317
|
width: opts.width,
|
|
408
318
|
height: opts.height,
|
|
409
|
-
timeoutMs
|
|
319
|
+
timeoutMs,
|
|
320
|
+
files: opts.assets?.files
|
|
410
321
|
});
|
|
411
322
|
if (!done.success || !done.data)
|
|
412
323
|
throw new Error(done.error ?? "render failed");
|
|
@@ -422,7 +333,8 @@ async function renderStill(browser, opts) {
|
|
|
422
333
|
height: opts.height,
|
|
423
334
|
duration: Math.max(1, opts.time + 1),
|
|
424
335
|
fps: 30,
|
|
425
|
-
thumbnailTime: opts.time
|
|
336
|
+
thumbnailTime: opts.time,
|
|
337
|
+
...captureAssets(opts.assets)
|
|
426
338
|
},
|
|
427
339
|
elementsBundleCode,
|
|
428
340
|
tweenEngine: "vos",
|
|
@@ -432,7 +344,8 @@ async function renderStill(browser, opts) {
|
|
|
432
344
|
const done = await runCapturePage(browser, html, {
|
|
433
345
|
width: opts.width,
|
|
434
346
|
height: opts.height,
|
|
435
|
-
timeoutMs: 12e4
|
|
347
|
+
timeoutMs: 12e4,
|
|
348
|
+
files: opts.assets?.files
|
|
436
349
|
});
|
|
437
350
|
if (!done.success || !done.data)
|
|
438
351
|
throw new Error(done.error ?? "still render failed");
|
|
@@ -495,8 +408,8 @@ async function reencodeStill(browser, webp, format) {
|
|
|
495
408
|
await page.close();
|
|
496
409
|
}
|
|
497
410
|
}
|
|
498
|
-
function previewPages(config) {
|
|
499
|
-
const code = compile(config);
|
|
411
|
+
function previewPages(config, assets) {
|
|
412
|
+
const code = compile(config, assets);
|
|
500
413
|
const playerHtml = generateRenderTemplate(code, {
|
|
501
414
|
mode: "playback",
|
|
502
415
|
elementsBundleCode,
|
|
@@ -549,107 +462,6 @@ function previewPages(config) {
|
|
|
549
462
|
return { hostHtml, playerHtml };
|
|
550
463
|
}
|
|
551
464
|
|
|
552
|
-
// src/plugin/container.ts
|
|
553
|
-
var OCTET_STREAM = "application/octet-stream";
|
|
554
|
-
var TYPES_BY_EXTENSION = {
|
|
555
|
-
svg: "image/svg+xml",
|
|
556
|
-
png: "image/png",
|
|
557
|
-
jpg: "image/jpeg",
|
|
558
|
-
jpeg: "image/jpeg",
|
|
559
|
-
webp: "image/webp",
|
|
560
|
-
gif: "image/gif",
|
|
561
|
-
avif: "image/avif",
|
|
562
|
-
webm: "video/webm",
|
|
563
|
-
mp4: "video/mp4",
|
|
564
|
-
mov: "video/quicktime",
|
|
565
|
-
mp3: "audio/mpeg",
|
|
566
|
-
wav: "audio/wav",
|
|
567
|
-
ogg: "audio/ogg",
|
|
568
|
-
m4a: "audio/mp4",
|
|
569
|
-
glb: "model/gltf-binary"
|
|
570
|
-
};
|
|
571
|
-
var EXTENSION_BY_TYPE = {
|
|
572
|
-
"image/jpeg": ".jpg",
|
|
573
|
-
"video/mp4": ".mp4",
|
|
574
|
-
"audio/mp4": ".m4a"
|
|
575
|
-
};
|
|
576
|
-
var TAKE_MEDIA_EXTENSIONS = [
|
|
577
|
-
".webm",
|
|
578
|
-
".mp4",
|
|
579
|
-
".mov",
|
|
580
|
-
".m4a",
|
|
581
|
-
".mp3",
|
|
582
|
-
".ogg",
|
|
583
|
-
".wav"
|
|
584
|
-
];
|
|
585
|
-
var MEDIA_HEAD_BYTES = 16;
|
|
586
|
-
var ISO_BRANDS = {
|
|
587
|
-
"qt ": "video/quicktime",
|
|
588
|
-
"M4A ": "audio/mp4",
|
|
589
|
-
"M4B ": "audio/mp4",
|
|
590
|
-
avif: "image/avif",
|
|
591
|
-
avis: "image/avif"
|
|
592
|
-
};
|
|
593
|
-
var RIFF_FORMS = {
|
|
594
|
-
WEBP: "image/webp",
|
|
595
|
-
WAVE: "audio/wav",
|
|
596
|
-
"AVI ": "video/x-msvideo"
|
|
597
|
-
};
|
|
598
|
-
function sniffMediaType(head) {
|
|
599
|
-
const ascii = (at, len) => head.length >= at + len ? String.fromCharCode(...head.subarray(at, at + len)) : "";
|
|
600
|
-
const startsWith = (...bytes) => bytes.every((b, i) => head[i] === b);
|
|
601
|
-
if (startsWith(26, 69, 223, 163)) return "video/webm";
|
|
602
|
-
if (ascii(4, 4) === "ftyp") return ISO_BRANDS[ascii(8, 4)] ?? "video/mp4";
|
|
603
|
-
if (ascii(0, 4) === "RIFF") return RIFF_FORMS[ascii(8, 4)] ?? null;
|
|
604
|
-
if (startsWith(137, 80, 78, 71, 13, 10, 26, 10))
|
|
605
|
-
return "image/png";
|
|
606
|
-
if (startsWith(255, 216, 255)) return "image/jpeg";
|
|
607
|
-
if (ascii(0, 4) === "GIF8") return "image/gif";
|
|
608
|
-
if (ascii(0, 4) === "OggS") return "audio/ogg";
|
|
609
|
-
if (ascii(0, 3) === "ID3") return "audio/mpeg";
|
|
610
|
-
if (ascii(0, 4) === "glTF") return "model/gltf-binary";
|
|
611
|
-
return null;
|
|
612
|
-
}
|
|
613
|
-
function bareType(value) {
|
|
614
|
-
const type = (value ?? "").split(";")[0].trim().toLowerCase();
|
|
615
|
-
return !type || type === OCTET_STREAM || type === "binary/octet-stream" ? "" : type;
|
|
616
|
-
}
|
|
617
|
-
function mediaContentType(file) {
|
|
618
|
-
const ext = (/\.([a-z0-9]+)$/i.exec(file)?.[1] ?? "").toLowerCase();
|
|
619
|
-
return TYPES_BY_EXTENSION[ext] ?? OCTET_STREAM;
|
|
620
|
-
}
|
|
621
|
-
function extensionFor(contentType) {
|
|
622
|
-
const type = (contentType ?? "").split(";")[0].trim().toLowerCase();
|
|
623
|
-
if (EXTENSION_BY_TYPE[type]) return EXTENSION_BY_TYPE[type];
|
|
624
|
-
const ext = Object.keys(TYPES_BY_EXTENSION).find(
|
|
625
|
-
(e) => TYPES_BY_EXTENSION[e] === type
|
|
626
|
-
);
|
|
627
|
-
return ext ? `.${ext}` : "";
|
|
628
|
-
}
|
|
629
|
-
function resolveMediaType(claims) {
|
|
630
|
-
const sniffed = claims.head?.length ? sniffMediaType(claims.head) : null;
|
|
631
|
-
if (sniffed) return { type: sniffed, from: "bytes" };
|
|
632
|
-
const declared = bareType(claims.declared);
|
|
633
|
-
if (declared) return { type: declared, from: "declared" };
|
|
634
|
-
const named = mediaContentType(claims.filename ?? "");
|
|
635
|
-
if (named !== OCTET_STREAM) return { type: named, from: "filename" };
|
|
636
|
-
return { type: OCTET_STREAM, from: "unknown" };
|
|
637
|
-
}
|
|
638
|
-
function nameForType(filename, type) {
|
|
639
|
-
const ext = extensionFor(type);
|
|
640
|
-
if (!ext) return filename;
|
|
641
|
-
const current = /\.[a-z0-9]+$/i.exec(filename)?.[0] ?? "";
|
|
642
|
-
if (current && mediaContentType(`x${current}`) === type) return filename;
|
|
643
|
-
return `${filename.slice(0, filename.length - current.length)}${ext}`;
|
|
644
|
-
}
|
|
645
|
-
function containerMismatch(filename, head) {
|
|
646
|
-
const actual = sniffMediaType(head);
|
|
647
|
-
if (!actual) return null;
|
|
648
|
-
const claimed = mediaContentType(filename);
|
|
649
|
-
if (claimed === actual) return null;
|
|
650
|
-
return `${filename} is ${actual}, not the ${claimed} its name claims \u2014 rename it to ${nameForType(filename, actual)}`;
|
|
651
|
-
}
|
|
652
|
-
|
|
653
465
|
// src/outputs.ts
|
|
654
466
|
function extOf(path) {
|
|
655
467
|
return /\.([a-z0-9]+)$/i.exec(path ?? "")?.[1]?.toLowerCase() ?? "";
|
|
@@ -728,278 +540,7 @@ function applyDataSets(config, sets) {
|
|
|
728
540
|
return { ...config, data };
|
|
729
541
|
}
|
|
730
542
|
|
|
731
|
-
// src/plugin/args.ts
|
|
732
|
-
function parseArgs2(argv, booleanFlags, multiFlags = /* @__PURE__ */ new Set()) {
|
|
733
|
-
const positionals = [];
|
|
734
|
-
const flags = {};
|
|
735
|
-
const multi = {};
|
|
736
|
-
const put = (name, value) => {
|
|
737
|
-
if (multiFlags.has(name)) (multi[name] ??= []).push(value);
|
|
738
|
-
else flags[name] = value;
|
|
739
|
-
};
|
|
740
|
-
for (let i = 0; i < argv.length; i++) {
|
|
741
|
-
const arg = argv[i];
|
|
742
|
-
if (arg === "--") {
|
|
743
|
-
positionals.push(...argv.slice(i + 1));
|
|
744
|
-
break;
|
|
745
|
-
}
|
|
746
|
-
if (arg.startsWith("--")) {
|
|
747
|
-
const eq = arg.indexOf("=");
|
|
748
|
-
if (eq !== -1) {
|
|
749
|
-
put(arg.slice(2, eq), arg.slice(eq + 1));
|
|
750
|
-
continue;
|
|
751
|
-
}
|
|
752
|
-
const name = arg.slice(2);
|
|
753
|
-
if (booleanFlags.has(name)) {
|
|
754
|
-
flags[name] = true;
|
|
755
|
-
continue;
|
|
756
|
-
}
|
|
757
|
-
if (i + 1 >= argv.length || argv[i + 1].startsWith("--")) {
|
|
758
|
-
throw new UsageError(`--${name} expects a value`);
|
|
759
|
-
}
|
|
760
|
-
put(name, argv[i + 1]);
|
|
761
|
-
i++;
|
|
762
|
-
continue;
|
|
763
|
-
}
|
|
764
|
-
positionals.push(arg);
|
|
765
|
-
}
|
|
766
|
-
for (const name of Object.keys(flags)) noteGivenFlag(name);
|
|
767
|
-
for (const name of Object.keys(multi)) noteGivenFlag(name);
|
|
768
|
-
return { positionals, flags: trackFlags(flags), multi: trackFlags(multi) };
|
|
769
|
-
}
|
|
770
|
-
function numFlag2(flags, name, fallback) {
|
|
771
|
-
const v = flags[name];
|
|
772
|
-
if (typeof v !== "string") return fallback;
|
|
773
|
-
const n = Number(v);
|
|
774
|
-
if (!Number.isFinite(n))
|
|
775
|
-
throw new UsageError(`--${name} expects a number, got "${v}"`);
|
|
776
|
-
return n;
|
|
777
|
-
}
|
|
778
|
-
function strFlag(flags, name) {
|
|
779
|
-
const v = flags[name];
|
|
780
|
-
return typeof v === "string" ? v : void 0;
|
|
781
|
-
}
|
|
782
|
-
function hasFlag(flags, name) {
|
|
783
|
-
return Object.prototype.hasOwnProperty.call(flags, name);
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
// src/plugin/platform.ts
|
|
787
|
-
import { mkdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
788
|
-
import { homedir } from "os";
|
|
789
|
-
import { join as join2 } from "path";
|
|
790
|
-
|
|
791
|
-
// src/plugin/hostAgent.ts
|
|
792
|
-
import { existsSync as existsSync2 } from "fs";
|
|
793
|
-
var SLUG = /^[a-z0-9][a-z0-9.-]{0,39}$/;
|
|
794
|
-
var MARKERS = [
|
|
795
|
-
["cursor", (e) => !!e.CURSOR_TRACE_ID],
|
|
796
|
-
[
|
|
797
|
-
"cursor-cli",
|
|
798
|
-
(e) => !!e.CURSOR_AGENT || e.CURSOR_EXTENSION_HOST_ROLE === "agent-exec"
|
|
799
|
-
],
|
|
800
|
-
["gemini-cli", (e) => !!e.GEMINI_CLI],
|
|
801
|
-
["codex", (e) => !!(e.CODEX_SANDBOX || e.CODEX_CI || e.CODEX_THREAD_ID)],
|
|
802
|
-
["antigravity", (e) => !!e.ANTIGRAVITY_AGENT],
|
|
803
|
-
["augment-cli", (e) => !!e.AUGMENT_AGENT],
|
|
804
|
-
["opencode", (e) => !!e.OPENCODE_CLIENT],
|
|
805
|
-
[
|
|
806
|
-
"claude-code",
|
|
807
|
-
(e) => !!(e.CLAUDECODE || e.CLAUDE_CODE) && !e.CLAUDE_CODE_IS_COWORK
|
|
808
|
-
],
|
|
809
|
-
["claude-cowork", (e) => !!(e.CLAUDECODE || e.CLAUDE_CODE)],
|
|
810
|
-
["replit", (e) => !!e.REPL_ID],
|
|
811
|
-
[
|
|
812
|
-
"github-copilot",
|
|
813
|
-
(e) => !!(e.COPILOT_MODEL || e.COPILOT_ALLOW_ALL || e.COPILOT_GITHUB_TOKEN)
|
|
814
|
-
]
|
|
815
|
-
];
|
|
816
|
-
var DEVIN_LOCAL_PATH = "/opt/.devin";
|
|
817
|
-
function slugFromAiAgent(value) {
|
|
818
|
-
const head = value.trim().toLowerCase().split("_")[0] ?? "";
|
|
819
|
-
if (head === "github-copilot-cli") return "github-copilot";
|
|
820
|
-
return SLUG.test(head) ? head : null;
|
|
821
|
-
}
|
|
822
|
-
function detectHostAgent(env = process.env, exists = existsSync2) {
|
|
823
|
-
if (env.AI_AGENT) {
|
|
824
|
-
const slug = slugFromAiAgent(env.AI_AGENT);
|
|
825
|
-
if (slug) return slug;
|
|
826
|
-
}
|
|
827
|
-
for (const [slug, test] of MARKERS) if (test(env)) return slug;
|
|
828
|
-
try {
|
|
829
|
-
if (exists(DEVIN_LOCAL_PATH)) return "devin";
|
|
830
|
-
} catch {
|
|
831
|
-
}
|
|
832
|
-
return null;
|
|
833
|
-
}
|
|
834
|
-
|
|
835
|
-
// src/plugin/platform.ts
|
|
836
|
-
function platformOrigin(flags = {}) {
|
|
837
|
-
const legacyEnv = process.env.VOS_API_BASE?.trim();
|
|
838
|
-
const raw = flags.origin ?? flags.api ?? process.env.VOS_ORIGIN?.trim() ?? legacyEnv ?? "https://vos.so";
|
|
839
|
-
if (!flags.origin && !flags.api && !process.env.VOS_ORIGIN && legacyEnv) {
|
|
840
|
-
process.stderr.write(
|
|
841
|
-
"note: VOS_API_BASE is deprecated \u2014 set VOS_ORIGIN (an origin, no /api suffix)\n"
|
|
842
|
-
);
|
|
843
|
-
}
|
|
844
|
-
return raw.replace(/\/+$/, "").replace(/\/api$/, "");
|
|
845
|
-
}
|
|
846
|
-
function parseVosId(input) {
|
|
847
|
-
if (!/^https?:\/\//.test(input)) {
|
|
848
|
-
if (/^[A-Za-z0-9_-]+$/.test(input)) return input;
|
|
849
|
-
throw new UsageError(`"${input}" is not a vos id or URL`);
|
|
850
|
-
}
|
|
851
|
-
let url;
|
|
852
|
-
try {
|
|
853
|
-
url = new URL(input);
|
|
854
|
-
} catch {
|
|
855
|
-
throw new UsageError(`"${input}" is not a valid URL`);
|
|
856
|
-
}
|
|
857
|
-
const query = url.searchParams.get("vos");
|
|
858
|
-
if (query) return query;
|
|
859
|
-
const path = url.pathname.match(/\/vos\/([A-Za-z0-9_-]+)/);
|
|
860
|
-
if (path) return path[1];
|
|
861
|
-
throw new UsageError(
|
|
862
|
-
`could not find a vos id in ${input} \u2014 expected /vos/{id} or ?vos={id}`
|
|
863
|
-
);
|
|
864
|
-
}
|
|
865
|
-
function deriveSlug(title) {
|
|
866
|
-
return title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 50).replace(/-+$/, "") || "remix";
|
|
867
|
-
}
|
|
868
|
-
var CREDENTIALS_PATH = join2(homedir(), ".config", "vos", "credentials");
|
|
869
|
-
function resolveCredential(explicit) {
|
|
870
|
-
const flag = explicit?.trim();
|
|
871
|
-
if (flag) return flag;
|
|
872
|
-
const env = process.env.VOS_API_KEY?.trim();
|
|
873
|
-
if (env) return env;
|
|
874
|
-
try {
|
|
875
|
-
const first = readFileSync2(CREDENTIALS_PATH, "utf8").split("\n")[0].trim();
|
|
876
|
-
return first || null;
|
|
877
|
-
} catch {
|
|
878
|
-
return null;
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
function requireCredential(explicit) {
|
|
882
|
-
const key = resolveCredential(explicit);
|
|
883
|
-
if (!key) {
|
|
884
|
-
throw new Error(
|
|
885
|
-
"no credential found \u2014 pass --key, set VOS_API_KEY, or run `vos login` (mint a content key at https://vos.so/app/api; a vos_rg_ remix grant works too)"
|
|
886
|
-
);
|
|
887
|
-
}
|
|
888
|
-
return key;
|
|
889
|
-
}
|
|
890
|
-
function writeCredential(key) {
|
|
891
|
-
mkdirSync(join2(homedir(), ".config", "vos"), { recursive: true, mode: 448 });
|
|
892
|
-
writeFileSync(CREDENTIALS_PATH, `${key.trim()}
|
|
893
|
-
`, { mode: 384 });
|
|
894
|
-
return CREDENTIALS_PATH;
|
|
895
|
-
}
|
|
896
|
-
function clientId(env = process.env, exists) {
|
|
897
|
-
const explicit = env.VOS_CLIENT?.trim();
|
|
898
|
-
if (explicit && explicit.length <= 60 && !/[\r\n]/.test(explicit))
|
|
899
|
-
return explicit;
|
|
900
|
-
const host = detectHostAgent(env, exists);
|
|
901
|
-
return host ? `${host} vos-cli` : "vos-cli";
|
|
902
|
-
}
|
|
903
|
-
async function apiJson(origin, path, init = {}) {
|
|
904
|
-
const headers = {
|
|
905
|
-
accept: "application/json",
|
|
906
|
-
...init.headers
|
|
907
|
-
};
|
|
908
|
-
if (init.key) headers.authorization = `Bearer ${init.key}`;
|
|
909
|
-
if (init.body !== void 0) headers["content-type"] = "application/json";
|
|
910
|
-
const reqBody = init.raw !== void 0 ? init.raw : init.body === void 0 ? void 0 : JSON.stringify(init.body);
|
|
911
|
-
const res = await fetch(`${origin}${path}`, {
|
|
912
|
-
method: init.method ?? "GET",
|
|
913
|
-
headers,
|
|
914
|
-
body: reqBody
|
|
915
|
-
});
|
|
916
|
-
let body = {};
|
|
917
|
-
try {
|
|
918
|
-
body = await res.json();
|
|
919
|
-
} catch {
|
|
920
|
-
}
|
|
921
|
-
return { status: res.status, body };
|
|
922
|
-
}
|
|
923
|
-
function apiError(what, r) {
|
|
924
|
-
const detail = typeof r.body.error === "string" ? r.body.error : r.body.details !== void 0 ? JSON.stringify(r.body.details) : "";
|
|
925
|
-
const hint = r.status === 401 ? " (run `vos login`, or set VOS_API_KEY \u2014 mint a key at https://vos.so/app/api)" : "";
|
|
926
|
-
return `${what} \u2192 ${r.status}${detail ? `: ${detail}` : ""}${hint}`;
|
|
927
|
-
}
|
|
928
|
-
var SYNC_STATE_NAME = "vos.json";
|
|
929
|
-
function readJsonFile(file) {
|
|
930
|
-
try {
|
|
931
|
-
return JSON.parse(readFileSync2(file, "utf8"));
|
|
932
|
-
} catch {
|
|
933
|
-
return null;
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
function readSyncState(dir) {
|
|
937
|
-
const own = readJsonFile(join2(dir, SYNC_STATE_NAME));
|
|
938
|
-
if (own && typeof own.vosId === "string") {
|
|
939
|
-
return {
|
|
940
|
-
vosId: own.vosId,
|
|
941
|
-
versionId: typeof own.versionId === "string" ? own.versionId : null,
|
|
942
|
-
...typeof own.pushedAt === "string" ? { pushedAt: own.pushedAt } : {},
|
|
943
|
-
...typeof own.title === "string" ? { title: own.title } : {},
|
|
944
|
-
...typeof own.slug === "string" ? { slug: own.slug } : {},
|
|
945
|
-
...typeof own.remixOfId === "string" ? { remixOfId: own.remixOfId } : {}
|
|
946
|
-
};
|
|
947
|
-
}
|
|
948
|
-
const push = readJsonFile(join2(dir, "push.json"));
|
|
949
|
-
if (push && typeof push.vosId === "string") {
|
|
950
|
-
return {
|
|
951
|
-
vosId: push.vosId,
|
|
952
|
-
versionId: typeof push.versionId === "string" ? push.versionId : null,
|
|
953
|
-
...typeof push.pushedAt === "string" ? { pushedAt: push.pushedAt } : {}
|
|
954
|
-
};
|
|
955
|
-
}
|
|
956
|
-
const meta = readJsonFile(join2(dir, "meta.json"));
|
|
957
|
-
if (meta && typeof meta.id === "string") {
|
|
958
|
-
return {
|
|
959
|
-
vosId: meta.id,
|
|
960
|
-
versionId: typeof meta.currentVersionId === "string" ? meta.currentVersionId : null,
|
|
961
|
-
...typeof meta.title === "string" ? { title: meta.title } : {},
|
|
962
|
-
...typeof meta.slug === "string" ? { slug: meta.slug } : {},
|
|
963
|
-
...typeof meta.remixOfId === "string" ? { remixOfId: meta.remixOfId } : {}
|
|
964
|
-
};
|
|
965
|
-
}
|
|
966
|
-
return null;
|
|
967
|
-
}
|
|
968
|
-
function writeSyncState(dir, patch) {
|
|
969
|
-
const merged = {
|
|
970
|
-
...readSyncState(dir) ?? { versionId: null },
|
|
971
|
-
...patch
|
|
972
|
-
};
|
|
973
|
-
writeFileSync(
|
|
974
|
-
join2(dir, SYNC_STATE_NAME),
|
|
975
|
-
`${JSON.stringify(merged, null, 2)}
|
|
976
|
-
`
|
|
977
|
-
);
|
|
978
|
-
return merged;
|
|
979
|
-
}
|
|
980
|
-
function formatChanges(changes) {
|
|
981
|
-
const lines = [];
|
|
982
|
-
for (const ch of changes) {
|
|
983
|
-
const label = ch.label ? ` \xB7 ${ch.label}` : "";
|
|
984
|
-
const who = ch.origin === "studio" ? "human" : ch.origin ?? "unknown";
|
|
985
|
-
lines.push(
|
|
986
|
-
`v${String(ch.versionNumber ?? "?")} (${who}${label}): ${ch.summary ?? ""}`
|
|
987
|
-
);
|
|
988
|
-
if (ch.note) lines.push(` note: ${ch.note}`);
|
|
989
|
-
}
|
|
990
|
-
return lines;
|
|
991
|
-
}
|
|
992
|
-
function serverWarnings(body, log) {
|
|
993
|
-
const warnings = Array.isArray(body.warnings) ? body.warnings : [];
|
|
994
|
-
for (const w of warnings) if (typeof w === "string") log(`warning ${w}`);
|
|
995
|
-
}
|
|
996
|
-
|
|
997
543
|
export {
|
|
998
|
-
helpFlagsFor,
|
|
999
|
-
unusedFlagsMessage,
|
|
1000
|
-
UsageError,
|
|
1001
|
-
parseArgs,
|
|
1002
|
-
numFlag,
|
|
1003
544
|
directoryKind,
|
|
1004
545
|
loadProgramDirectory,
|
|
1005
546
|
readSourceText,
|
|
@@ -1013,37 +554,11 @@ export {
|
|
|
1013
554
|
inspectStill,
|
|
1014
555
|
reencodeStill,
|
|
1015
556
|
previewPages,
|
|
1016
|
-
TAKE_MEDIA_EXTENSIONS,
|
|
1017
|
-
MEDIA_HEAD_BYTES,
|
|
1018
|
-
sniffMediaType,
|
|
1019
|
-
extensionFor,
|
|
1020
|
-
resolveMediaType,
|
|
1021
|
-
nameForType,
|
|
1022
|
-
containerMismatch,
|
|
1023
557
|
videoFormat,
|
|
1024
558
|
stillFormat,
|
|
1025
559
|
parseTimes,
|
|
1026
560
|
stillOutFor,
|
|
1027
561
|
setFlags,
|
|
1028
|
-
applyDataSets
|
|
1029
|
-
parseArgs2,
|
|
1030
|
-
numFlag2,
|
|
1031
|
-
strFlag,
|
|
1032
|
-
hasFlag,
|
|
1033
|
-
platformOrigin,
|
|
1034
|
-
parseVosId,
|
|
1035
|
-
deriveSlug,
|
|
1036
|
-
CREDENTIALS_PATH,
|
|
1037
|
-
resolveCredential,
|
|
1038
|
-
requireCredential,
|
|
1039
|
-
writeCredential,
|
|
1040
|
-
clientId,
|
|
1041
|
-
apiJson,
|
|
1042
|
-
apiError,
|
|
1043
|
-
SYNC_STATE_NAME,
|
|
1044
|
-
readSyncState,
|
|
1045
|
-
writeSyncState,
|
|
1046
|
-
formatChanges,
|
|
1047
|
-
serverWarnings
|
|
562
|
+
applyDataSets
|
|
1048
563
|
};
|
|
1049
|
-
//# sourceMappingURL=chunk-
|
|
564
|
+
//# sourceMappingURL=chunk-LWHVZ5WI.js.map
|