@vosjs/cli 0.71.0 → 0.73.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 +3 -3
- package/dist/{chunk-XB5XRE4Q.js → chunk-EYF3WJIC.js} +45 -11
- package/dist/chunk-EYF3WJIC.js.map +1 -0
- package/dist/cli.js +5 -15
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -1
- package/dist/{run-QPHIGP6N.js → run-FK5HWX4X.js} +2 -2
- package/package.json +6 -6
- package/dist/chunk-XB5XRE4Q.js.map +0 -1
- /package/dist/{run-QPHIGP6N.js.map → run-FK5HWX4X.js.map} +0 -0
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ npx vos render animation.json out.webm
|
|
|
15
15
|
|
|
16
16
|
Deterministic: the preview is the render, and every edit is a data patch to `doc.json`, never a re-record. Rendering is local and free at every resolution up to 4K, no watermark. The workflow skills for agents install with `npx skills add vosjs/skills` (`product-video` records and cuts one video, `vos-cut` cuts an existing recording, `launch-kit` ships the media with a release); `vos setup` runs that for you, and falls back to the copy of the catalog this package ships when skills.sh cannot be reached. A coding agent gets the whole procedure from one line: `Read https://vos.so/agent.md and do what it says.`
|
|
17
17
|
|
|
18
|
-
Until 0.9 the take pipeline and the vos.so verbs shipped separately as `@vosso/vos-plugin`, and before that as `@vosso/cli
|
|
18
|
+
Until 0.9 the take pipeline and the vos.so verbs shipped separately as `@vosso/vos-plugin`, and before that as `@vosso/cli`; those names are deprecated on npm and forward here.
|
|
19
19
|
|
|
20
20
|
## Contents
|
|
21
21
|
|
|
@@ -335,7 +335,7 @@ vos assets ls [--kind <kind>] [--q <text>] [--sort size] | usage | why <id> #
|
|
|
335
335
|
vos recipe push <FILE.md> --folder <slug> | --asset <id> # the one recipe write: create, or replace in place
|
|
336
336
|
```
|
|
337
337
|
|
|
338
|
-
`push` is polymorphic by a deterministic sniff, never a flag: a take directory (a `doc.json` carrying `source`) pushes recording and document through the take pipeline; a `config.json` (or a directory holding one) pushes the program, and a `doc.json` beside it that carries `program` (a program document: overlays, objects, audio, speed, tween edits, its own length; `program.config` omitted on disk) rides along, lint-gated. `fetch` and `pull` write a program document back the same way. `pull` takes `--since <versionId>` (walk the changelog from that base instead of the tracked one) and `--check` (print what changed and stop: nothing on disk moves) on both paths. A program push LANDS where `vos.json` says: a directory that tracks a vos iterates it, so the fetch, edit, check, push, pull loop needs no flags, and making something separate from the same config is the explicit `--remix-of` door. Program pushes take `--vos`, `--title`, `--slug`, `--desc`, `--tags`, `--folder`, `--remix-of`, `--base`, `--label`, `--note`, `--override <id>` (repeatable) and `--claimable`; take pushes take `--title`, `--label`, `--note`, `--folder`, `--override`, `--yes` and `--claimable`. Both take `--wait`. A new vos pushed without `--folder` lands unfiled, at the root of the shelf, and the done line says so.
|
|
338
|
+
`push` is polymorphic by a deterministic sniff, never a flag: a take directory (a `doc.json` carrying `source`) pushes recording and document through the take pipeline; a `config.json` (or a directory holding one) pushes the program, and a `doc.json` beside it that carries `program` (a program document: overlays, objects, audio, speed, tween edits, its own length; `program.config` omitted on disk) rides along, lint-gated. `fetch` and `pull` write a program document back the same way. `pull` takes `--since <versionId>` (walk the changelog from that base instead of the tracked one) and `--check` (print what changed and stop: nothing on disk moves) on both paths. A program push LANDS where `vos.json` says: a directory that tracks a vos iterates it, so the fetch, edit, check, push, pull loop needs no flags, and making something separate from the same config is the explicit `--remix-of` door. Program pushes take `--vos`, `--title`, `--slug`, `--desc`, `--tags`, `--folder`, `--remix-of`, `--base`, `--label`, `--note`, `--override <id>` (repeatable) and `--claimable`; take pushes take `--title`, `--label`, `--note`, `--folder`, `--override`, `--yes` and `--claimable`. Both take `--wait`. A new vos pushed without `--folder` lands unfiled, at the root of the shelf, and the done line says so. `--folder` takes a project on your own shelf (its slug or id) or anyone's project by its address, `<handle>/<slug>` as its page on vos.so names it: the server answers where the push lands, CONTINUING that project when the key is its owner's and otherwise STARTING the person's own from it (a private project made once, named after it, with the recipes they may read copied in, never its videos). The push says which.
|
|
339
339
|
|
|
340
340
|
**A program's files are declared, never typed into a function.** `config.json` names each file it uses in `assets` (`"assets": { "logo": { "ref": "./logo.png", "kind": "image" }, "shots": { "ref": ["./shots/1.png", "./shots/2.png"] } }`) and reads `ctx.assets.logo`, or `"$assets.logo"` in an element, object or font. On disk a `ref` is a path in the config's own directory or below, so `vos render`, `vos still` and `vos preview` serve the file to the page from disk. A path that climbs out of that directory (`../`, an absolute path, a link that points away) is not served and not uploaded, and a config loaded from a URL reads no local file: a program's code runs in a page, and what the page is served the program can send anywhere. `vos push` uploads each local file (content-addressed, so a re-push sends nothing: pictures, SVG, video, sound, `.glb` models, fonts and HDR environments) and what it stores names the hosted file as `asset:<id>`, the one spelling the platform resolves for every render; the config on disk keeps its paths. A file an element names as `src` or a font names as `url` is lifted into the manifest on the way (the element then names `"$assets.<name>"`), and a path in `data` that is a file beside the config is uploaded and rewritten to the hosted file's path, so every place a program can name a file crosses. A file typed inside a function cannot be rewritten: `vos push` says so, with the manifest line to write. `vos fetch --media` brings a program's hosted files home under `assets/` and re-points the manifest at them (`assets/.hosted.json` remembers which hosted file each one is, so a later fetch replaces one that changed); without `--media` the manifest keeps `asset:<id>` and a local render reads each file with your key. `vos check` says when a `"$assets.<name>"` names nothing, when a declared path is not a file, and when a function names a hosted file in code instead of the manifest: a file named only in code does not load on a render of a private program and does not follow a remix. A `--claimable` push carries them too, through the claim's own upload session (below).
|
|
341
341
|
|
|
@@ -369,7 +369,7 @@ vos push /tmp/take --label "$TAG launch" --yes --json # VOS_API_KEY as a r
|
|
|
369
369
|
- **`--max-duration <s>`** on `record` and `create` defaults to the hosted recording cap, read live from `GET /api/limits` (2 s, fail-open to 30 min when the origin is unreachable): the capture stops there and the done event says so. Cut the flow rather than raising the cap; the platform refuses a longer take.
|
|
370
370
|
- **`create`** is the one-shot verb: record, auto-plan and render in one command and one browser session. The take directory still lands on disk, so the full loop (frames, edit `doc.json`, re-render) stays open afterwards.
|
|
371
371
|
- **`vos validate <thing>`** takes an `actions.json`, a take directory, a program directory (`config.json`, plus its program document when present), or a `kit.json`; exit 1 on any problem.
|
|
372
|
-
- **Environment.** `VOS_ORIGIN` (the platform, and the studio `vos open` opens), `VOS_API_KEY`, `VOS_BROWSER_PATH`, `VOS_CLIENT` (the client string a push self-reports; unset, a push names the coding agent that spawned the CLI, read from its environment the way `@vercel/detect-agent` reads it, e.g. `claude-code vos-cli`, else `vos-cli`).
|
|
372
|
+
- **Environment.** `VOS_ORIGIN` (the platform, and the studio `vos open` opens), `VOS_API_KEY`, `VOS_BROWSER_PATH`, `VOS_CLIENT` (the client string a push self-reports; unset, a push names the coding agent that spawned the CLI, read from its environment the way `@vercel/detect-agent` reads it, e.g. `claude-code vos-cli`, else `vos-cli`).
|
|
373
373
|
|
|
374
374
|
## Programmatic use
|
|
375
375
|
|
|
@@ -2400,7 +2400,7 @@ async function renderChunk(context2, serverBase, chunk, opts, onChunkProgress) {
|
|
|
2400
2400
|
bitrate: opts.bitrate ?? 1e7,
|
|
2401
2401
|
mediabunnyUrl: MEDIABUNNY_URL,
|
|
2402
2402
|
outName,
|
|
2403
|
-
debug: process.env.
|
|
2403
|
+
debug: process.env.VOS_DEBUG_CHUNKS === "1",
|
|
2404
2404
|
audioProducerCode: audio?.producerCode,
|
|
2405
2405
|
audioDataJson: audio ? JSON.stringify(audio.data) : void 0,
|
|
2406
2406
|
audioDuration: audio?.duration
|
|
@@ -3226,7 +3226,7 @@ function parseTranscript(raw) {
|
|
|
3226
3226
|
}
|
|
3227
3227
|
|
|
3228
3228
|
// src/plugin/framesTake.ts
|
|
3229
|
-
var VIDEO_TOKEN = "
|
|
3229
|
+
var VIDEO_TOKEN = "__VOS_CLI_VIDEO__";
|
|
3230
3230
|
function stillSupersample(w, h) {
|
|
3231
3231
|
return Math.min(3, Math.max(1, Math.ceil(1800 / Math.max(1, w, h))));
|
|
3232
3232
|
}
|
|
@@ -3512,7 +3512,7 @@ import {
|
|
|
3512
3512
|
resolveExportSize as resolveExportSize2,
|
|
3513
3513
|
studioAudioPlan
|
|
3514
3514
|
} from "@vosjs/studio-core";
|
|
3515
|
-
var VIDEO_TOKEN2 = "
|
|
3515
|
+
var VIDEO_TOKEN2 = "__VOS_CLI_VIDEO__";
|
|
3516
3516
|
async function renderTake(browser, dir, outFile, opts) {
|
|
3517
3517
|
const take = await loadTake(dir);
|
|
3518
3518
|
if (!take.doc) throw new Error(`${dir} has no doc.json \u2014 run plan first`);
|
|
@@ -6022,6 +6022,38 @@ function resolveFolder(rows, ref) {
|
|
|
6022
6022
|
}
|
|
6023
6023
|
return hit;
|
|
6024
6024
|
}
|
|
6025
|
+
function projectAddress(ref) {
|
|
6026
|
+
const m = /^@?([A-Za-z0-9_]{1,30})\/([A-Za-z0-9][\w-]{0,99})$/.exec(
|
|
6027
|
+
ref.trim()
|
|
6028
|
+
);
|
|
6029
|
+
return m ? { handle: m[1], slug: m[2].toLowerCase() } : null;
|
|
6030
|
+
}
|
|
6031
|
+
async function resolvePushFolder(origin, key, ref) {
|
|
6032
|
+
const at2 = projectAddress(ref);
|
|
6033
|
+
if (!at2) {
|
|
6034
|
+
return {
|
|
6035
|
+
id: resolveFolder(await listFolders(origin, key), ref).id,
|
|
6036
|
+
note: null
|
|
6037
|
+
};
|
|
6038
|
+
}
|
|
6039
|
+
const r = await apiJson(
|
|
6040
|
+
origin,
|
|
6041
|
+
`/api/folders/public/${encodeURIComponent(at2.handle)}/${encodeURIComponent(at2.slug)}/push-target`,
|
|
6042
|
+
{ method: "POST", key }
|
|
6043
|
+
);
|
|
6044
|
+
if (r.status !== 200 && r.status !== 201) {
|
|
6045
|
+
throw new Error(apiError(`find the project ${at2.handle}/${at2.slug}`, r));
|
|
6046
|
+
}
|
|
6047
|
+
const body = r.body;
|
|
6048
|
+
if (!body.folder) {
|
|
6049
|
+
throw new Error(
|
|
6050
|
+
`find the project ${at2.handle}/${at2.slug}: no project in the answer`
|
|
6051
|
+
);
|
|
6052
|
+
}
|
|
6053
|
+
const source = body.source?.name ?? `${at2.handle}/${at2.slug}`;
|
|
6054
|
+
const note = body.target === "continue" ? `continuing ${source}` : body.created ? `starting your own ${source} (${body.folder.slug}), its ${body.recipes ?? 0} recipe${body.recipes === 1 ? "" : "s"} copied in` : `adding to your own ${source} (${body.folder.slug})`;
|
|
6055
|
+
return { id: body.folder.id, note };
|
|
6056
|
+
}
|
|
6025
6057
|
function printTree(rows) {
|
|
6026
6058
|
const children = /* @__PURE__ */ new Map();
|
|
6027
6059
|
for (const f of rows) {
|
|
@@ -6404,10 +6436,9 @@ async function pushTake(dir, flags, r) {
|
|
|
6404
6436
|
"--folder applies when CREATING a vos \u2014 this take is already pushed; file it with: vos folder move <vosId> --to <folder>"
|
|
6405
6437
|
);
|
|
6406
6438
|
}
|
|
6407
|
-
|
|
6408
|
-
|
|
6409
|
-
|
|
6410
|
-
).id;
|
|
6439
|
+
const target = await resolvePushFolder(ctx.origin, ctx.key, flags.folder);
|
|
6440
|
+
folderId = target.id;
|
|
6441
|
+
if (target.note) r.log(target.note);
|
|
6411
6442
|
}
|
|
6412
6443
|
if (firstPush && !flags.yes) {
|
|
6413
6444
|
if (!process.stdin.isTTY) {
|
|
@@ -7265,7 +7296,7 @@ async function cmdPushProgram(argv) {
|
|
|
7265
7296
|
const target = positionals[0];
|
|
7266
7297
|
if (!target) {
|
|
7267
7298
|
throw new UsageError(
|
|
7268
|
-
'vos push <config.json|take> [--vos id] [--title t] [--slug s] [--desc d] [--tags a,b] [--folder <id|slug>] [--remix-of id] [--note n] [--label l] [--base versionId] [--override id]... [--prompt "<the prompt that made it>"] [--claimable [--share]]'
|
|
7299
|
+
'vos push <config.json|take> [--vos id] [--title t] [--slug s] [--desc d] [--tags a,b] [--folder <id|slug|handle/slug>] [--remix-of id] [--note n] [--label l] [--base versionId] [--override id]... [--prompt "<the prompt that made it>"] [--claimable [--share]]'
|
|
7269
7300
|
);
|
|
7270
7301
|
}
|
|
7271
7302
|
const source = resolveConfigPath(target);
|
|
@@ -7487,7 +7518,9 @@ ${landedLines(landed2)}` : "")
|
|
|
7487
7518
|
const remixOfId = pushTarget.kind === "create" ? pushTarget.remixOfId : void 0;
|
|
7488
7519
|
const fallbackTitle = state?.title ? `${state.title} remix` : basename3(source).replace(/\.json$/i, "") || "vos remix";
|
|
7489
7520
|
const title = (strFlag(flags, "title") ?? fallbackTitle).slice(0, 100);
|
|
7490
|
-
const
|
|
7521
|
+
const pushFolder = folderRef ? await resolvePushFolder(origin, key, folderRef) : void 0;
|
|
7522
|
+
const folderId = pushFolder?.id;
|
|
7523
|
+
if (pushFolder?.note) r.log(pushFolder.note);
|
|
7491
7524
|
const created = await createProgramVos({
|
|
7492
7525
|
origin,
|
|
7493
7526
|
key,
|
|
@@ -7531,6 +7564,7 @@ ${landedLines(landed2)}` : "")
|
|
|
7531
7564
|
title,
|
|
7532
7565
|
visibility: "private",
|
|
7533
7566
|
folder: folderRef ?? null,
|
|
7567
|
+
...pushFolder?.note ? { folderNote: pushFolder.note } : {},
|
|
7534
7568
|
remixOfId: remixOfId ?? null,
|
|
7535
7569
|
currentVersionId: created.currentVersionId,
|
|
7536
7570
|
watchUrl,
|
|
@@ -7547,7 +7581,7 @@ ${landedLines(landed2)}` : "")
|
|
|
7547
7581
|
watch: ${watchUrl}
|
|
7548
7582
|
studio: ${studioUrl}
|
|
7549
7583
|
` + (landed ? `${landedLines(landed)}
|
|
7550
|
-
` : "") + ` shelf: ${folderRef ? `in ${folderRef}` : `unfiled, at the root of your shelf (file it: vos folder move ${created.id} --to <slug>)`}
|
|
7584
|
+
` : "") + ` shelf: ${folderRef ? `in ${folderRef}${pushFolder?.note ? ` (${pushFolder.note})` : ""}` : `unfiled, at the root of your shelf (file it: vos folder move ${created.id} --to <slug>)`}
|
|
7551
7585
|
cover: ${typeof programDoc?.still === "number" ? `${String(programDoc.still)}s` : "the platform picks an early frame; choose one with --still <seconds>"}
|
|
7552
7586
|
` + (prompt ? ` prompt: shown on the watch page
|
|
7553
7587
|
` : ` prompt: none shown; show the one that made it: ${promptHint(source, created.id)}
|
|
@@ -14328,4 +14362,4 @@ export {
|
|
|
14328
14362
|
verbHelp,
|
|
14329
14363
|
run
|
|
14330
14364
|
};
|
|
14331
|
-
//# sourceMappingURL=chunk-
|
|
14365
|
+
//# sourceMappingURL=chunk-EYF3WJIC.js.map
|