@vosjs/cli 0.51.0 → 0.52.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 +13 -5
- package/dist/{chunk-GCWE75OA.js → chunk-3OIYR5VL.js} +27 -2
- package/dist/chunk-3OIYR5VL.js.map +1 -0
- package/dist/{chunk-JVINOGJG.js → chunk-F2QCWV4U.js} +676 -763
- package/dist/chunk-F2QCWV4U.js.map +1 -0
- package/dist/chunk-KSEU3YK5.js +776 -0
- package/dist/chunk-KSEU3YK5.js.map +1 -0
- package/dist/cli.js +175 -44
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.js +12 -12
- package/dist/{run-AV3X2454.js → run-ASYY2YTV.js} +3 -3
- package/package.json +4 -4
- package/skills/VERSION +1 -1
- package/skills/product-video/SKILL.md +6 -1
- package/skills/vos-footage/SKILL.md +7 -5
- package/skills/vos-migrate/SKILL.md +34 -38
- package/dist/chunk-FACYY7VV.js +0 -308
- package/dist/chunk-FACYY7VV.js.map +0 -1
- package/dist/chunk-GCWE75OA.js.map +0 -1
- package/dist/chunk-JVINOGJG.js.map +0 -1
- /package/dist/{run-AV3X2454.js.map → run-ASYY2YTV.js.map} +0 -0
package/README.md
CHANGED
|
@@ -48,8 +48,8 @@ vos logout # remove ~/.config/vos/credentials
|
|
|
48
48
|
## Engine verbs
|
|
49
49
|
|
|
50
50
|
```bash
|
|
51
|
-
vos render <config.json|url|take> [out] # config → video
|
|
52
|
-
vos still <config.json|url> [out.webp] # config →
|
|
51
|
+
vos render <config.json|url|take> [out] # config → video; the name picks mp4/webm; a program document's sound is mixed in
|
|
52
|
+
vos still <config.json|url> [out.webp] # config → frames: --times 0,1.5,50% in one browser; .png/.jpg re-encoded
|
|
53
53
|
vos info <config.json|url> # inspect a config
|
|
54
54
|
vos check <config.json|url> # migrate → schema → syntax → compile → determinism and dialect lints, all local
|
|
55
55
|
vos preview <config.json|url> [--port N] # serve a local playback page
|
|
@@ -95,8 +95,12 @@ vos ingest video.webm --cursor trace.zip --out take # a Playwright trace: cl
|
|
|
95
95
|
vos ingest demo.mp4 --cursor steps.jsonl --out take # stamped records: {"ts":…,"command":["click","@e1"],"point":{"x":…,"y":…}} per line
|
|
96
96
|
vos ingest demo.mp4 --cursor cursor.csv --out take # t,x,y,type (ms, viewport px; move|down|up|click|scroll)
|
|
97
97
|
vos ingest demo.mp4 --out take # no trace: no cursor track, nothing planned, and the done event says so
|
|
98
|
+
vos ingest reel.mp4 --out take # a render from HyperFrames or Remotion, a film: opens BARE
|
|
99
|
+
vos ingest loom.mp4 --as take --out take # a screen demo with no trace: the card, its ground
|
|
98
100
|
```
|
|
99
101
|
|
|
102
|
+
**A file with no trace is finished footage by default.** Nothing but a cursor trace says a file is a screen recording, so without one the take opens bare: no card, no browser bar, no drawn cursor or webcam, exported at the footage's own frame rate. `--as take` gives a screen demo the card; `--as footage` says the opposite outright.
|
|
103
|
+
|
|
100
104
|
What a trace cannot give is named, never guessed: agent-browser's own log carries neither timestamps nor coordinates (measured), so stamp `ts` and a `point` per command when you keep one, or replay the walk with `vos actions from-agent-browser` and `vos record` instead. `--offset <ms>` shifts a trace whose zero is not the video's; `--viewport WxH` names the coordinate space when the video was scaled. A headed capture with the real pointer baked in shows two cursors under a trace's drawn one; turn the drawn cursor off in `doc.json` for those.
|
|
101
105
|
|
|
102
106
|
**No browser here?** A cloud agent, a CI runner or a chat host records on vos.so instead: the same script goes up, the fleet records, plans and lands the take as a private vos with its doc and its digest, and the take comes home into `--out` with its media, the directory every other verb reads.
|
|
@@ -298,19 +302,23 @@ vos push bright-loop/config.json --vos <id> # add a version to a vos
|
|
|
298
302
|
vos push bright-loop/config.json --remix-of <id> # create a SEPARATE vos from this config, with that lineage
|
|
299
303
|
vos push bright-loop/config.json --claimable # no credential: a 72 h claim link instead (programs only)
|
|
300
304
|
vos push take --yes --label "first pass" --note "…" # host a take: private vos + version history (the recording uploads once)
|
|
305
|
+
vos push … --wait # stay until the version's still renders; print absolute still and preview links
|
|
306
|
+
vos delete <vosId|url|dir> [--yes] # take a vos off vos.so, every version; asks, or --yes headless
|
|
301
307
|
vos pull bright-loop [--since <versionId>] [--check] # what changed on vos.so since your base; syncs config.json (backup kept), or doc.json for a take
|
|
302
308
|
# --check reports without writing; --since walks from a base you name
|
|
303
309
|
vos duplicate <vosId> # a private sibling of your OWN vos (someone else's is remixed: fetch, then push --remix-of)
|
|
304
310
|
vos folder list | create <name> [--parent] [--desc] | move <ids…> --to <folder|none> | pull <ref> [--media]
|
|
305
|
-
vos asset push <file…> [--folder <slug>] | rename <id> <name.ext>
|
|
311
|
+
vos asset push <file…> [--folder <slug>] | rename <id> <name.ext> # sound and video too: they land in Sound > Uploads
|
|
306
312
|
vos recipe push <FILE.md> --folder <slug> | --asset <id> # the one recipe write: create, or replace in place
|
|
307
313
|
```
|
|
308
314
|
|
|
309
|
-
`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` and `--yes`.
|
|
315
|
+
`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` and `--yes`. Both take `--wait`. A new vos pushed without `--folder` lands unfiled, at the root of the shelf, and the done line says so.
|
|
316
|
+
|
|
317
|
+
**Sound is a track, never an element.** A document's added sound lives in `doc.json` (`audio: [{ id, key, name, start, in, out, duration, gain, fadeIn, fadeOut }]`) for a program as for a take: `vos push` uploads each local file its keys name and keys the hosted asset; `vos render` of a program mixes it locally; the studio shows it as a track with gain and fades. An `audio` element embedded in the config is not a track (renders do not mix it, and a `data:` source can push a config past what a claimable push carries); `vos check` says so. `vos asset push score.ogg` uploads a sound on its own and prints the url a key takes; an unfiled sound that no document uses is removed after 7 days, so pass `--folder` or reference it.
|
|
310
318
|
|
|
311
319
|
Both paths share the same base tracking and the same two 409 shapes. `stale_base` replays the platform's typed changelog: run `vos pull`, re-apply, push again. `protected_conflict` lists nodes a human edited in the studio: keep their values, or re-push with `--override <id>` only when the user asked for that exact change. The first push of a take asks before uploading (`--yes` for headless); agents never upload unprompted. The take's duration rides the upload, and the platform refuses a take over the hosted recording cap. Every push should carry `--label` (what changed, one line) and `--note` (why: the user's ask); the version history reads as a conversation, and an unlabelled push is a turn the human cannot read.
|
|
312
320
|
|
|
313
|
-
`--claimable` is the credential-free rung, programs only: no key is resolved, no `vos.json` is written, and the response is a claim URL (72 h; unclaimed work is deleted, which is deliberate cleanup). Hand the link to the user and nowhere else: it is the only reference and the only credential. Claiming moves the vos into the user's library, and iteration after claim rides their key (`vos push --vos <id>`). Limits are the platform's: config ≤ 200 KB, 5 pushes per day per network.
|
|
321
|
+
`--claimable` is the credential-free rung, programs only: no key is resolved, no `vos.json` is written, and the response is a claim URL (72 h; unclaimed work is deleted, which is deliberate cleanup). Hand the link to the user and nowhere else: it is the only reference and the only credential. Claiming moves the vos into the user's library, and iteration after claim rides their key (`vos push --vos <id>`). Limits are the platform's: config ≤ 200 KB, 5 pushes per day per network. A claim carries no files, so a program document's local sounds are left out of it, and said.
|
|
314
322
|
|
|
315
323
|
`vos folder pull <ref>` writes a folder's context package to disk (its recipes, the inherited ones, the exemplar programs and assets), which is what an agent reads to create in the owner's style. Recipes are `.md` files named in capitals (`CUT.md`, `BRAND.md`): the server uppercases an agent-filed name.
|
|
316
324
|
|
|
@@ -59,7 +59,8 @@ async function renderVideo(browser, opts) {
|
|
|
59
59
|
height: opts.height,
|
|
60
60
|
duration: opts.duration,
|
|
61
61
|
fps: opts.fps,
|
|
62
|
-
format: opts.format
|
|
62
|
+
format: opts.format,
|
|
63
|
+
...opts.audioProducerCode ? { audioProducerCode: opts.audioProducerCode } : {}
|
|
63
64
|
},
|
|
64
65
|
elementsBundleCode,
|
|
65
66
|
tweenEngine: "vos",
|
|
@@ -102,6 +103,29 @@ async function renderStill(browser, opts) {
|
|
|
102
103
|
throw new Error(done.error ?? "still render failed");
|
|
103
104
|
return decodeDataUrl(done.data);
|
|
104
105
|
}
|
|
106
|
+
async function reencodeStill(browser, webp, format) {
|
|
107
|
+
const page = await browser.newPage();
|
|
108
|
+
try {
|
|
109
|
+
const src = `data:image/webp;base64,${Buffer.from(webp).toString("base64")}`;
|
|
110
|
+
const dataUrl = await page.evaluate(
|
|
111
|
+
`(async () => {
|
|
112
|
+
const img = new Image()
|
|
113
|
+
img.src = ${JSON.stringify(src)}
|
|
114
|
+
await img.decode()
|
|
115
|
+
const c = document.createElement('canvas')
|
|
116
|
+
c.width = img.naturalWidth
|
|
117
|
+
c.height = img.naturalHeight
|
|
118
|
+
const g = c.getContext('2d')
|
|
119
|
+
${format === "jpeg" ? "g.fillStyle = '#fff'; g.fillRect(0, 0, c.width, c.height)" : ""}
|
|
120
|
+
g.drawImage(img, 0, 0)
|
|
121
|
+
return c.toDataURL(${JSON.stringify(`image/${format}`)}, 0.92)
|
|
122
|
+
})()`
|
|
123
|
+
);
|
|
124
|
+
return decodeDataUrl(dataUrl).bytes;
|
|
125
|
+
} finally {
|
|
126
|
+
await page.close();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
105
129
|
function previewPages(config) {
|
|
106
130
|
const code = compile(config);
|
|
107
131
|
const playerHtml = generateRenderTemplate(code, {
|
|
@@ -157,6 +181,7 @@ function previewPages(config) {
|
|
|
157
181
|
export {
|
|
158
182
|
renderVideo,
|
|
159
183
|
renderStill,
|
|
184
|
+
reencodeStill,
|
|
160
185
|
previewPages
|
|
161
186
|
};
|
|
162
|
-
//# sourceMappingURL=chunk-
|
|
187
|
+
//# sourceMappingURL=chunk-3OIYR5VL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/render.ts"],"sourcesContent":["import { compileVosConfig } from '@vosjs/core'\nimport { generateRenderTemplate } from '@vosjs/core/runtime'\nimport { elementsBundleCode } from '@vosjs/elements/bundle'\nimport { tweenRuntimeCode } from '@vosjs/tween/bundle'\nimport type { Browser, Page } from 'playwright'\n\n/** Fake secure origin the render page is served from (WebCodecs needs one). */\nconst RENDER_ORIGIN = 'https://vos-cli.render'\n\nexport interface RenderCommonOptions {\n config: Record<string, unknown>\n width: number\n height: number\n /** Phase callback for progress reporting. */\n onPhase?: (phase: string) => void\n}\n\nexport interface RenderVideoOptions extends RenderCommonOptions {\n fps: number\n /** Output duration in seconds. */\n duration: number\n format: 'webm' | 'mp4'\n /** The page's audio producer (a program document's sound); absent = silent. */\n audioProducerCode?: string\n}\n\nexport interface RenderStillOptions extends RenderCommonOptions {\n /** Seek time for the captured frame, seconds. */\n time: number\n}\n\nexport interface RenderResult {\n bytes: Uint8Array\n mimeType: string\n}\n\ninterface RenderComplete {\n success: boolean\n data?: string\n error?: string\n}\n\nfunction compile(config: Record<string, unknown>): string {\n return compileVosConfig(config as never, { tweenEngine: 'vos' })\n}\n\nasync function runCapturePage(\n browser: Browser,\n html: string,\n opts: { width: number; height: number; timeoutMs: number },\n): Promise<RenderComplete> {\n const context = await browser.newContext({\n viewport: { width: opts.width, height: opts.height },\n })\n const page: Page = await context.newPage()\n const errors: string[] = []\n page.on('console', (m) => {\n if (m.type() === 'error') errors.push(m.text())\n })\n try {\n await page.route(`${RENDER_ORIGIN}/**`, (route) =>\n route.fulfill({ status: 200, contentType: 'text/html', body: html }),\n )\n await page.goto(`${RENDER_ORIGIN}/render`, {\n waitUntil: 'domcontentloaded',\n })\n const start = Date.now()\n for (;;) {\n const done = (await page.evaluate(\n 'window.__renderComplete ?? null',\n )) as RenderComplete | null\n if (done) return done\n if (Date.now() - start > opts.timeoutMs) {\n return {\n success: false,\n error: `render timed out after ${Math.round(opts.timeoutMs / 1000)}s${\n errors.length\n ? ` (page errors: ${errors.slice(0, 3).join(' | ')})`\n : ''\n }`,\n }\n }\n await new Promise((r) => setTimeout(r, 400))\n }\n } finally {\n await context.close()\n }\n}\n\nfunction decodeDataUrl(dataUrl: string): RenderResult {\n const m = /^data:([^;,]+);base64,(.*)$/s.exec(dataUrl)\n if (!m) throw new Error('capture page returned an unexpected payload')\n return { bytes: Uint8Array.from(Buffer.from(m[2], 'base64')), mimeType: m[1] }\n}\n\n/** Render a vos config to a video (WebM/MP4) in a headless browser. */\nexport async function renderVideo(\n browser: Browser,\n opts: RenderVideoOptions,\n): Promise<RenderResult> {\n opts.onPhase?.('compile')\n const code = compile(opts.config)\n const html = generateRenderTemplate(code, {\n mode: 'capture-video',\n capture: {\n width: opts.width,\n height: opts.height,\n duration: opts.duration,\n fps: opts.fps,\n format: opts.format,\n ...(opts.audioProducerCode\n ? { audioProducerCode: opts.audioProducerCode }\n : {}),\n },\n elementsBundleCode,\n tweenEngine: 'vos',\n tweenBundleCode: tweenRuntimeCode,\n })\n opts.onPhase?.('render')\n // Generous ceiling: startup + CDN module fetch + ~4× realtime per frame batch.\n const timeoutMs = 90_000 + opts.duration * opts.fps * 400\n const done = await runCapturePage(browser, html, {\n width: opts.width,\n height: opts.height,\n timeoutMs,\n })\n if (!done.success || !done.data)\n throw new Error(done.error ?? 'render failed')\n return decodeDataUrl(done.data)\n}\n\n/** Render a single frame of a vos config to an image in a headless browser. */\nexport async function renderStill(\n browser: Browser,\n opts: RenderStillOptions,\n): Promise<RenderResult> {\n opts.onPhase?.('compile')\n const code = compile(opts.config)\n const html = generateRenderTemplate(code, {\n mode: 'capture-thumbnail',\n capture: {\n width: opts.width,\n height: opts.height,\n duration: Math.max(1, opts.time + 1),\n fps: 30,\n thumbnailTime: opts.time,\n },\n elementsBundleCode,\n tweenEngine: 'vos',\n tweenBundleCode: tweenRuntimeCode,\n })\n opts.onPhase?.('render')\n const done = await runCapturePage(browser, html, {\n width: opts.width,\n height: opts.height,\n timeoutMs: 120_000,\n })\n if (!done.success || !done.data)\n throw new Error(done.error ?? 'still render failed')\n return decodeDataUrl(done.data)\n}\n\n/**\n * Re-encode a captured WebP still as PNG or JPEG in a browser page, so a\n * still named `.png` holds PNG bytes. The canvas is the encoder; nothing\n * else is installed for it.\n */\nexport async function reencodeStill(\n browser: Browser,\n webp: Uint8Array,\n format: 'png' | 'jpeg',\n): Promise<Uint8Array> {\n const page = await browser.newPage()\n try {\n const src = `data:image/webp;base64,${Buffer.from(webp).toString('base64')}`\n // A string body: a serialized function would carry the bundler's\n // helpers into a page that has none.\n const dataUrl = (await page.evaluate(\n `(async () => {\n const img = new Image()\n img.src = ${JSON.stringify(src)}\n await img.decode()\n const c = document.createElement('canvas')\n c.width = img.naturalWidth\n c.height = img.naturalHeight\n const g = c.getContext('2d')\n ${format === 'jpeg' ? \"g.fillStyle = '#fff'; g.fillRect(0, 0, c.width, c.height)\" : ''}\n g.drawImage(img, 0, 0)\n return c.toDataURL(${JSON.stringify(`image/${format}`)}, 0.92)\n })()`,\n )) as string\n return decodeDataUrl(dataUrl).bytes\n } finally {\n await page.close()\n }\n}\n\nexport interface PreviewPages {\n /** Host page: iframes the player and drives it over the bridge. */\n hostHtml: string\n /** The engine's playback-mode player (waits for a LOAD postMessage). */\n playerHtml: string\n}\n\n/**\n * Pages for `vos preview`. The playback template is the iframe HALF of the\n * player bridge — it renders nothing until a host posts `LOAD`, so the CLI\n * serves a minimal host page that sends `LOAD { code, autoplay }` and shows\n * a transport line (time / duration, click to play-pause).\n */\nexport function previewPages(config: Record<string, unknown>): PreviewPages {\n const code = compile(config)\n const playerHtml = generateRenderTemplate(code, {\n mode: 'playback',\n elementsBundleCode,\n tweenEngine: 'vos',\n tweenBundleCode: tweenRuntimeCode,\n })\n const codeJson = JSON.stringify(code).replace(/<\\//g, '<\\\\/')\n const hostHtml = `<!doctype html><html><head><meta charset=\"utf-8\"><title>vos preview</title>\n<style>\n html,body{margin:0;height:100%;background:#000;overflow:hidden}\n iframe{position:absolute;inset:0;width:100%;height:100%;border:0}\n #cover{position:fixed;inset:0;cursor:pointer}\n #hud{position:fixed;left:12px;bottom:10px;color:#fff;opacity:.75;font:12px/1.4 ui-monospace,monospace;\n background:rgba(0,0,0,.45);padding:4px 8px;border-radius:6px;pointer-events:none}\n</style></head><body>\n<iframe id=\"p\" src=\"/player\" allow=\"autoplay\"></iframe>\n<div id=\"cover\"></div>\n<div id=\"hud\">loading…</div>\n<script>\n const code = ${codeJson}\n const frame = document.getElementById('p')\n const hud = document.getElementById('hud')\n let ready = false\n let playing = true\n const post = (msg) => frame.contentWindow && frame.contentWindow.postMessage(msg, '*')\n const load = () => post({ type: 'LOAD', code, autoplay: true })\n window.addEventListener('message', (e) => {\n const msg = e.data || {}\n if (msg.type === 'BRIDGE_READY') load()\n if (msg.type === 'READY') { ready = true; hud.textContent = '0.0 / ' + msg.duration.toFixed(1) + 's — click to pause' }\n if (msg.type === 'UPDATE') hud.textContent = msg.time.toFixed(1) + ' / ' + msg.duration.toFixed(1) + 's — click to ' + (playing ? 'pause' : 'play')\n if (msg.type === 'ERROR') hud.textContent = 'error: ' + msg.error\n })\n // Belt and braces: if BRIDGE_READY raced the host, retry LOAD until READY.\n let tries = 0\n const iv = setInterval(() => {\n if (ready || tries++ > 20) return clearInterval(iv)\n load()\n }, 400)\n // The iframe swallows clicks — capture them on an overlay above it.\n document.getElementById('cover').addEventListener('click', () => {\n if (!ready) return\n playing = !playing\n post({ type: playing ? 'PLAY' : 'PAUSE' })\n hud.textContent = hud.textContent.replace(/click to (pause|play)/, 'click to ' + (playing ? 'pause' : 'play'))\n })\n</script></body></html>`\n return { hostHtml, playerHtml }\n}\n"],"mappings":"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","names":[]}
|