@vosjs/cli 0.29.0 → 0.30.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 CHANGED
@@ -161,7 +161,7 @@ Verified the flow in agent-browser already? `vos actions from-agent-browser step
161
161
 
162
162
  **Image and video overlays.** Media kinds on the same lane: `{ "id": "m0", "kind": "image" | "video", "start": 2, "duration": 4, "key": "/logo.png", "width": 0.35, "radius": 12, "opacity": 1, "loop": false, "transform": { … } }`. `key` is a file inside the take directory (`"/logo.png"`) or a URL; `width` is a fraction of the frame width, height follows the media's aspect; corners in design px. Video time is clip-local and muted by design; soundtracks belong to `doc.audio`.
163
163
 
164
- **HTML layers.** A UI component authored as DOM on the same lane, sharp at any export size because it is rasterized from source, not magnified from the footage: `{ "id": "h0", "kind": "html", "start": 2, "duration": 4, "html": "<div class=\"card\">Open Code</div>", "css": ".card{font-family:'Inter';background:#0b0b0d;border-radius:16px;box-shadow:0 24px 60px rgba(0,0,0,.45)}", "box": { "width": 452, "height": 132 }, "transform": { … } }`. The markup is well-formed XML (`<br />`, `&amp;`, quoted attributes; `vos validate` refuses the rest in words, because a malformed layer decodes to nothing and says nothing). `box` is the design box in 1080p px; `width` defaults to the design size. The CSS is the chrome (shadow, radius, border; `bleed` is derived from the shadows, or stated), a `font-family` it names resolves against the hosted catalog at every `font-weight` it names (a face outside the catalog rides `fonts: [{ family, url }]`), an image inside must be a `data:` URI, and an `animation` runs on the wall clock rather than the timeline, so animate the layer with `anim` and `motion`. It is never re-hosted and never an upload.
164
+ **HTML layers.** A UI component authored as DOM on the same lane, sharp at any export size because it is rasterized from source, not magnified from the footage: `{ "id": "h0", "kind": "html", "start": 2, "duration": 4, "html": "<div class=\"card\">Open Code</div>", "css": ".card{font-family:'Inter';background:#0b0b0d;border-radius:16px;box-shadow:0 24px 60px rgba(0,0,0,.45)}", "box": { "width": 452, "height": 132 }, "transform": { … } }`. The markup is well-formed XML (`<br />`, `&amp;`, quoted attributes; `vos validate` refuses the rest in words, because a malformed layer decodes to nothing and says nothing). `box` is the design box in 1080p px; `width` defaults to the design size. The CSS is the chrome (shadow, radius, border; `bleed` is derived from the shadows, or stated), a `font-family` it names resolves against the hosted catalog at every `font-weight` it names (a face outside the catalog rides `fonts: [{ family, url }]`), and an image inside is inlined for you when its URL is on `https://assets.vos.so/` (`vos asset upload` puts it there; any other host paints blank, so inline it as a `data:` URI). A still layer's `animation` runs on the wall clock rather than the timeline, so animate the layer with `anim` and `motion`; a LIVE layer (`"live": true`) is re-rasterized per frame at clip-local time: its `@keyframes` are scrubbed to `t` (paused, delayed by `-t`; fold any `animation-delay` into the keyframes) and `{{t}}` / `{{data.<name>}}` placeholders in the markup and CSS fill from the clock and the clip's `data`, so a counter, a progress bar or a typed line come out on the timeline's clock in the preview and in every export chunk alike. It is never re-hosted and never an upload.
165
165
 
166
166
  **3D props.** `doc.objects`: world-space props between the card and the overlays. `{ "id": "p0", "asset": { "kind": "primitive", "shape": "knot", "color": "#ffb03a" }, "span": { "start": 1, "duration": 3 }, "transform3d": { "x": 0.8, "y": 0.28, "z": 0.5, "rx": 0, "ry": 40, "rz": 0, "scale": 0.18 }, "animation": "spin" }`. Shapes `cube`, `sphere`, `torus`, `knot`; `kind: "gltf"` with `key` loads a GLB (bounding-box normalized so `scale` means the same for every model; a bad model fails open). `x`/`y` are frame fractions, `z` world units toward the camera from the card plane, `scale` a fraction of the frame height; `animation` is `spin` or `float`, deterministic.
167
167
 
@@ -1143,6 +1143,20 @@ function lintDoc(docIn) {
1143
1143
  `${name}.width must be a fraction of the frame width in (0..1] (got ${String(o.width)}; absent = the design size)`
1144
1144
  );
1145
1145
  }
1146
+ if (o.live !== void 0 && typeof o.live !== "boolean") {
1147
+ problems.push(
1148
+ `${name}.live must be true or absent: a live layer is re-rasterized per frame at clip-local t (its @keyframes scrubbed, its {{t}} and {{data.\u2026}} filled)`
1149
+ );
1150
+ }
1151
+ if (o.data !== void 0) {
1152
+ const bad = !isObj(o.data) || Object.values(o.data).some(
1153
+ (v) => !["string", "number", "boolean"].includes(typeof v)
1154
+ );
1155
+ if (bad)
1156
+ problems.push(
1157
+ `${name}.data must be a map of strings, numbers or booleans: the values a live layer's {{data.<name>}} placeholders read`
1158
+ );
1159
+ }
1146
1160
  if (o.opacity !== void 0 && (!isNum(o.opacity) || o.opacity < 0 || o.opacity > 1)) {
1147
1161
  problems.push(`${name}.opacity must be 0..1`);
1148
1162
  }
@@ -7406,7 +7420,7 @@ import {
7406
7420
  migrateConfig,
7407
7421
  vosConfigJsonSchema
7408
7422
  } from "@vosjs/core";
7409
- import { migrateHostedDoc as migrateHostedDoc4 } from "@vosjs/studio-core";
7423
+ import { lowerProgramDoc, migrateHostedDoc as migrateHostedDoc4 } from "@vosjs/studio-core";
7410
7424
 
7411
7425
  // src/plugin/login.ts
7412
7426
  import { hostname } from "os";
@@ -7704,6 +7718,7 @@ async function createProgramVos(opts) {
7704
7718
  if (opts.remixOfId) body.remixOfId = opts.remixOfId;
7705
7719
  if (opts.label) body.label = opts.label;
7706
7720
  if (opts.note) body.note = opts.note;
7721
+ if (opts.doc) body.doc = opts.doc;
7707
7722
  const res = await apiJson(opts.origin, "/api/vos", {
7708
7723
  method: "POST",
7709
7724
  key: opts.key,
@@ -7804,7 +7819,10 @@ with their key: vos push ${source} --vos ${String(created2.id ?? "<id>")}`
7804
7819
  }
7805
7820
  if (vosId) {
7806
7821
  const trackedBase = state && state.vosId === vosId && state.versionId ? state.versionId : void 0;
7807
- const body = { config, client: clientId() };
7822
+ const body = {
7823
+ config: storedProgramConfig(config, programDoc),
7824
+ client: clientId()
7825
+ };
7808
7826
  if (programDoc) body.doc = programDoc;
7809
7827
  const base = strFlag(flags, "base") ?? trackedBase;
7810
7828
  if (base) body.baseVersionId = base;
@@ -7869,7 +7887,12 @@ with their key: vos push ${source} --vos ${String(created2.id ?? "<id>")}`
7869
7887
  const created = await createProgramVos({
7870
7888
  origin,
7871
7889
  key,
7872
- config,
7890
+ config: storedProgramConfig(config, programDoc),
7891
+ // The document rode the version path and not the create path, so a
7892
+ // fresh push of a program directory silently dropped its doc.json
7893
+ // (found seeding one-layer members: `--with` then said the vos carried
7894
+ // no doc).
7895
+ doc: programDoc ?? void 0,
7873
7896
  title,
7874
7897
  slug: strFlag(flags, "slug"),
7875
7898
  description: desc,
@@ -8066,6 +8089,11 @@ async function storeKey(key, origin, r) {
8066
8089
  function isTakeDir(target) {
8067
8090
  return directoryKind(target) === "take";
8068
8091
  }
8092
+ function storedProgramConfig(config, programDoc) {
8093
+ if (!programDoc) return config;
8094
+ const doc = { audio: [], ...programDoc };
8095
+ return lowerProgramDoc(doc).config;
8096
+ }
8069
8097
  async function readProgramDoc(dir, config) {
8070
8098
  const docPath = join16(dir, "doc.json");
8071
8099
  if (!existsSync13(docPath)) return null;
@@ -10587,4 +10615,4 @@ export {
10587
10615
  convertAgentBrowser,
10588
10616
  run
10589
10617
  };
10590
- //# sourceMappingURL=chunk-GSRCASV2.js.map
10618
+ //# sourceMappingURL=chunk-N5CNC3B7.js.map