@vosjs/cli 0.47.0 → 0.48.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 +16 -5
- package/dist/{chunk-EFI3WUQB.js → chunk-P3X5KVA6.js} +15 -2
- package/dist/{chunk-EFI3WUQB.js.map → chunk-P3X5KVA6.js.map} +1 -1
- package/dist/{chunk-E42NCNWP.js → chunk-RHPRZQRM.js} +688 -58
- package/dist/chunk-RHPRZQRM.js.map +1 -0
- package/dist/cli.js +4 -4
- package/dist/index.js +2 -2
- package/dist/manifest-A4R367EM.js +8 -0
- package/dist/{run-DA5QXZ6F.js → run-DV73Z3MQ.js} +2 -2
- package/package.json +7 -5
- package/skills/VERSION +1 -0
- package/skills/launch-kit/SKILL.md +356 -0
- package/skills/launch-kit/references/channel-specs.md +56 -0
- package/skills/product-video/SKILL.md +263 -0
- package/skills/product-video/references/destinations.md +71 -0
- package/skills/product-video/references/sessions.md +226 -0
- package/skills/product-video/references/taste.md +115 -0
- package/skills/product-video/references/troubleshooting.md +116 -0
- package/skills/vos-authoring/SKILL.md +191 -0
- package/skills/vos-authoring/references/examples.md +239 -0
- package/skills/vos-authoring/references/schema-reference.md +468 -0
- package/skills/vos-create/SKILL.md +258 -0
- package/skills/vos-cut/SKILL.md +241 -0
- package/skills/vos-footage/SKILL.md +98 -0
- package/skills/vos-migrate/SKILL.md +108 -0
- package/skills/vos-remix/SKILL.md +136 -0
- package/skills/vos-remix/references/3d-recipe.md +37 -0
- package/skills/vos-remix/references/params-knobs.md +80 -0
- package/skills/vos-remix/references/remix-contract.md +81 -0
- package/dist/chunk-E42NCNWP.js.map +0 -1
- package/dist/manifest-UCS6OVWZ.js +0 -8
- /package/dist/{manifest-UCS6OVWZ.js.map → manifest-A4R367EM.js.map} +0 -0
- /package/dist/{run-DA5QXZ6F.js.map → run-DV73Z3MQ.js.map} +0 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vos-migrate
|
|
3
|
+
description: Turn an existing Loom, Screen Studio, Cap, or plain mp4/webm screen demo into an editable vosso take — re-encode the file, synthesize the take's metadata, plan, and push, so the old demo becomes a living document you re-cut instead of a file you re-record. Use when asked to "convert this Loom", "migrate our old demos", "re-edit this mp4", "make our Screen Studio recording editable", or to bring any already-recorded demo into vosso.
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Migrate a recorded demo into an editable take
|
|
8
|
+
|
|
9
|
+
You are turning a FINISHED video file into a vosso take: a document whose
|
|
10
|
+
zooms, trims, speed and layers are data, hosted with version history, and
|
|
11
|
+
editable in the studio. What the file loses by being foreign is honesty
|
|
12
|
+
you must carry: it has NO cursor track, so nothing can be auto-zoomed and
|
|
13
|
+
the digest sees little — your eyes are the contact sheet, and every zoom
|
|
14
|
+
is placed by eye.
|
|
15
|
+
|
|
16
|
+
Two doors:
|
|
17
|
+
|
|
18
|
+
- **The human door**: drop the file on https://vos.so/studio — it enters as
|
|
19
|
+
the browser-recorder shape and opens in the take editor directly. When a
|
|
20
|
+
human is present, this is the shortest path; hand them the link.
|
|
21
|
+
- **The agent door** (this skill): build the take directory yourself and
|
|
22
|
+
run the normal pipeline. Proven end to end below.
|
|
23
|
+
|
|
24
|
+
## 1. Probe the source
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
ffprobe -v quiet -print_format json -show_streams -show_format demo.mp4
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Keep: width, height, duration, fps, whether an audio stream exists. A
|
|
31
|
+
Loom/Screen Studio export is typically 1080p H.264 with the camera bubble
|
|
32
|
+
and any edits BAKED IN — they migrate as pixels, not as layers. Say so in
|
|
33
|
+
the handoff: the migration makes the file editable from here on, it does
|
|
34
|
+
not un-bake old edits.
|
|
35
|
+
|
|
36
|
+
## 2. Build the take directory
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
mkdir take
|
|
40
|
+
ffmpeg -i demo.mp4 -c:v libvpx-vp9 -crf 34 -b:v 0 -row-mt 1 \
|
|
41
|
+
-c:a libopus take/recording.webm # drop -c:a if no audio stream
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Then write `take/meta.json` from the probe (every field required; times in
|
|
45
|
+
ms; `producer: "migrated"` marks provenance):
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"producer": "migrated",
|
|
50
|
+
"dpr": 1, "zoom": 1,
|
|
51
|
+
"t0": 0,
|
|
52
|
+
"durationMs": 36766,
|
|
53
|
+
"width": 1920, "height": 1080,
|
|
54
|
+
"fps": 30,
|
|
55
|
+
"hasAudio": false
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`t0` may be any epoch ms; `width`/`height` are the video pixels (there was
|
|
60
|
+
no browser viewport). Set `hasAudio` true only when the webm actually
|
|
61
|
+
carries the track.
|
|
62
|
+
|
|
63
|
+
## 3. Plan, and see it honestly
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
vos plan take --fresh # builds doc.json; cursorKept false, zoomAuto 0
|
|
67
|
+
vos frames take --times 0,10%,25%,50%,75%,90%,100% # the contact sheet IS your eyes
|
|
68
|
+
vos digest take # runs, but expect little: head/tail and only
|
|
69
|
+
# hard scene cuts - no clicks, no typing, no dwells
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
No auto-zoom is possible and none should be faked. Read the stills, find
|
|
73
|
+
the 2–4 moments that matter, and write manual spans by eye:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# doc.json - every span you add carries "source": "manual"
|
|
77
|
+
# zoom: [{ "id": "m1", "in": 10.5, "out": 14.0, "level": 1.6,
|
|
78
|
+
# "cx": 0.52, "cy": 0.35, "source": "manual" }]
|
|
79
|
+
# segments: trim dead heads/tails; speed: only where footage truly idles
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Set `export.resolution` to MATCH the footage (a 1080p source is `1080p` —
|
|
83
|
+
migrating does not add pixels). `vos validate take` must pass; spot-check
|
|
84
|
+
with `vos render take check.webm --range a..b --draft`.
|
|
85
|
+
|
|
86
|
+
## 4. Push — the old demo becomes a living document
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
vos push take --folder <project> --label "migrated from <source>" \
|
|
90
|
+
--note "<what it shows; that old edits are baked; what you re-cut>"
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
End on the loop: the watch page plays it, the studio edits every span you
|
|
94
|
+
wrote plus everything the file never had (backdrops, text layers, speed),
|
|
95
|
+
and `vos pull` brings human edits back down. The pitch belongs in the
|
|
96
|
+
handoff, in one line: **this is the last demo you edit blind — record the
|
|
97
|
+
next one with `vos record` and the camera plans itself.**
|
|
98
|
+
|
|
99
|
+
## Honest limits (say them, never paper over them)
|
|
100
|
+
|
|
101
|
+
- No cursor track ⇒ no auto-zoom, no click effects, no typing zooms, and
|
|
102
|
+
no framing lint — every zoom is yours, by eye, and you say so.
|
|
103
|
+
- Old edits, camera bubbles and captions are baked pixels.
|
|
104
|
+
- The migration re-encodes once (VP9); a badly compressed source stays
|
|
105
|
+
badly compressed — migrating does not restore quality.
|
|
106
|
+
- A spec-size deliverable ladder (store stills, posters) works from the
|
|
107
|
+
migrated take exactly as from a native one — the `launch-kit` skill
|
|
108
|
+
takes over when the ask is a release.
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vos-remix
|
|
3
|
+
description: Remix a vos.so gallery program into your own — fetch its config, edit the declared knobs or code locally, validate with vos check, and push a private copy back with lineage that iterates as versions. Carries the params/Looks doctrine and the GLB 3D-showcase recipe. Use when asked to remix, customize or personalize a gallery animation, swap a 3D model into a showcase, or iterate a fetched program as versions.
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Remix a vos program
|
|
8
|
+
|
|
9
|
+
Every video on [vos.so/gallery](https://vos.so/gallery) is a program:
|
|
10
|
+
inputs + a deterministic function → video. Remixing is editing that
|
|
11
|
+
program's JSON config and pushing the result back as a **private** vos on
|
|
12
|
+
the user's account, with lineage. You edit locally; the platform validates,
|
|
13
|
+
compiles, and renders a preview.
|
|
14
|
+
|
|
15
|
+
## Setup
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm i -D @vosjs/cli # the fetch/check/push/pull loop
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
No browser needed for this loop (rendering previews happens on the
|
|
22
|
+
platform). Everything also works as plain HTTP if the CLI is unavailable:
|
|
23
|
+
`references/remix-contract.md` documents every endpoint.
|
|
24
|
+
|
|
25
|
+
## Credentials (never print them)
|
|
26
|
+
|
|
27
|
+
Two shapes, both used as `Authorization: Bearer`:
|
|
28
|
+
|
|
29
|
+
1. **Remix grant** (`vos_rg_…`) — if the user's prompt contains one, use it.
|
|
30
|
+
24h lifetime, bound to ONE source vos, max 5 pushes.
|
|
31
|
+
2. **Durable key** (`vos_sk_…`) — resolution order before asking:
|
|
32
|
+
`VOS_API_KEY` env, then the first line of `~/.config/vos/credentials`.
|
|
33
|
+
Humans mint keys at https://vos.so/app/api.
|
|
34
|
+
3. **No credential at all** — the claimable push (programs only):
|
|
35
|
+
```bash
|
|
36
|
+
vos push my-remix.json --claimable --title "My remix"
|
|
37
|
+
# → claim: https://vos.so/claim/… expires: <72h from now>
|
|
38
|
+
|
|
39
|
+
# No CLI, or an older one? The same thing over plain HTTP:
|
|
40
|
+
curl -s -X POST https://vos.so/api/claim \
|
|
41
|
+
-H 'content-type: application/json' \
|
|
42
|
+
-d '{"title": "My remix", "config": <the VosConfigJson>}'
|
|
43
|
+
# → { "claimUrl": "https://vos.so/claim/…", "expiresAt": "…" }
|
|
44
|
+
```
|
|
45
|
+
Hand `claimUrl` to the user and nowhere else — it is the only reference
|
|
46
|
+
and the only credential. The link lasts 72 hours; unclaimed work is
|
|
47
|
+
deleted after that (deliberate cleanup, not data loss — re-push if it
|
|
48
|
+
lapses). Claiming moves the vos into the user's library and starts its
|
|
49
|
+
hosted preview; iteration after claim rides their key (the loop below).
|
|
50
|
+
Limits: config ≤200KB, 5 pushes per day per network.
|
|
51
|
+
|
|
52
|
+
The CLI resolves grants and keys automatically (`export VOS_API_KEY=…`). No
|
|
53
|
+
shape can publish: pushed voses stay private until a human publishes on
|
|
54
|
+
vos.so.
|
|
55
|
+
|
|
56
|
+
## The loop
|
|
57
|
+
|
|
58
|
+
1. **Fetch** the source program (public programs need no auth):
|
|
59
|
+
```bash
|
|
60
|
+
vos fetch https://vos.so/vos/<id> # or the bare id
|
|
61
|
+
# → <slug>/config.json (params preserved) + <slug>/vos.json (tracking)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
2. **Edit** `config.json` locally. The function fields (`setup`,
|
|
65
|
+
`createContent`, `createTimeline`, `onFrame`) are JavaScript **as
|
|
66
|
+
strings** — no TypeScript syntax, no `${}` template interpolation.
|
|
67
|
+
Change 1–2 axes decisively (palette, motion grammar, density) — never a
|
|
68
|
+
10%-nudge duplicate. If the program declares `params`, prefer retuning
|
|
69
|
+
or extending those knobs over surgery on function strings.
|
|
70
|
+
|
|
71
|
+
3. **Declare knobs and Looks** — the remix's control surface. 2–4
|
|
72
|
+
intent-named params plus 2–3 presets. This is a craft with rules:
|
|
73
|
+
`references/params-knobs.md`.
|
|
74
|
+
|
|
75
|
+
4. **Check** locally before pushing:
|
|
76
|
+
```bash
|
|
77
|
+
vos check <slug>/config.json # migrate → schema → syntax → compile → lints
|
|
78
|
+
vos still <slug>/config.json probe.webp --time 2 # RUN it — check compiles
|
|
79
|
+
# but never executes the module; a runtime
|
|
80
|
+
# throw (a TDZ against the function's own
|
|
81
|
+
# declarations) ships invisibly on check
|
|
82
|
+
# alone. Render a still after every code
|
|
83
|
+
# edit, before every push.
|
|
84
|
+
```
|
|
85
|
+
Fix every error; treat determinism warnings seriously (a config that
|
|
86
|
+
renders differently per run is broken by definition).
|
|
87
|
+
|
|
88
|
+
5. **Push** as a private vos with lineage (the CLI reads `vos.json` beside
|
|
89
|
+
the config for the `remixOfId` credit):
|
|
90
|
+
```bash
|
|
91
|
+
vos push <slug>/config.json --title "Aurora Ribbons — dusk"
|
|
92
|
+
# → Created private vos <id>
|
|
93
|
+
# watch: https://vos.so/vos/<id>
|
|
94
|
+
# studio: https://vos.so/studio?vos=<id>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
6. **Iterate** — further edits become versions of the same vos:
|
|
98
|
+
```bash
|
|
99
|
+
vos push <slug>/config.json --vos <id> --note "cooler palette, slower drift"
|
|
100
|
+
```
|
|
101
|
+
The directory TRACKS its vos through `vos.json`, so the base version is
|
|
102
|
+
carried automatically: if the human edited in the studio since your last
|
|
103
|
+
push, the push is rejected WITH their typed changelog. `--note` is your
|
|
104
|
+
handoff line — it is what the human reads first; `--label` names the
|
|
105
|
+
version.
|
|
106
|
+
|
|
107
|
+
7. **Pull before every editing round** — the human may have fine-tuned:
|
|
108
|
+
```bash
|
|
109
|
+
vos pull <slug> # what changed since your base, then sync
|
|
110
|
+
```
|
|
111
|
+
Prints each version attributed (`v3 (studio · warmer): knob hue 0.2→0.35`
|
|
112
|
+
plus their notes), syncs `config.json` to the head (your previous copy is
|
|
113
|
+
kept as `config.backup.json`), and repoints the base. **Human-edited
|
|
114
|
+
nodes are protected**: a push that touches them is rejected unless you
|
|
115
|
+
pass `--override <id>` — do that ONLY when the user's instruction
|
|
116
|
+
explicitly targets that node. Their turns of your knobs are preference
|
|
117
|
+
data: read the changelog before deciding what to do next.
|
|
118
|
+
|
|
119
|
+
8. **Hand back BOTH links** — the watch page (preview, knobs, code) and the
|
|
120
|
+
studio (`https://vos.so/studio?vos=<id>`) where the user fine-tunes your
|
|
121
|
+
knobs live. Publishing is their act, on vos.so.
|
|
122
|
+
|
|
123
|
+
## Rules that keep pushes honest
|
|
124
|
+
|
|
125
|
+
- **Private is the contract.** Never try `visibility: "public"` — it clamps
|
|
126
|
+
to private, and publishing by key is rejected by design.
|
|
127
|
+
- **Quota-aware**: durable keys create ≤50 voses/24h; grants push ≤5. Iterate
|
|
128
|
+
versions on one vos instead of creating many voses.
|
|
129
|
+
- **Server-render constraints** (the preview fleet is software-GL): no
|
|
130
|
+
`THREE.DoubleSide` on transmission materials, no `dispersion`, and every
|
|
131
|
+
fetched asset must be an absolute `https` URL the fleet can reach.
|
|
132
|
+
- **Every knob must act.** A param the code never reads is worse than no
|
|
133
|
+
param — see the honesty section of `references/params-knobs.md`.
|
|
134
|
+
- 3D model swaps (GLB into a showcase program): `references/3d-recipe.md`.
|
|
135
|
+
- Full endpoint reference, quotas, and error table:
|
|
136
|
+
`references/remix-contract.md`.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# The 3D recipe — showcase a model
|
|
2
|
+
|
|
3
|
+
The 3D showcase programs (gallery tag `3d` — e.g. Studio Turntable, Dolly
|
|
4
|
+
Reveal: https://vos.so/gallery?tag=3d) are built to take a model swap.
|
|
5
|
+
|
|
6
|
+
## Steps
|
|
7
|
+
|
|
8
|
+
1. **Fetch** a 3d-tagged program: `vos fetch <its watch URL>`.
|
|
9
|
+
2. **Point it at the model**, either way:
|
|
10
|
+
- Add or replace the async `setup` field to load a GLB by URL:
|
|
11
|
+
```js
|
|
12
|
+
"setup": "async (ctx) => { const gltf = await new ctx.loaders.GLTFLoader().loadAsync('https://…/model.glb'); return { model: gltf.scene } }"
|
|
13
|
+
```
|
|
14
|
+
then replace the `buildProduct()` body — it is commented as **THE SWAP
|
|
15
|
+
POINT** in these programs — with the loaded `setupData.model`,
|
|
16
|
+
bbox-normalized to ~1.7 units and grounded at `y = 0` (the templates
|
|
17
|
+
ship the normalization snippet; keep it so `scale` knobs stay
|
|
18
|
+
model-independent).
|
|
19
|
+
- Or keep the template's own product and only retune params.
|
|
20
|
+
3. **The model URL must be CORS-clean and absolute `https`.** Assets
|
|
21
|
+
uploaded to vos.so (`POST /api/assets/upload`, browser-session auth,
|
|
22
|
+
`.glb`/`.gltf` ≤50MB) serve public+immutable with `ACAO: *` at
|
|
23
|
+
`/api/assets/{id}/file` — bake that absolute URL into the config so the
|
|
24
|
+
platform's preview render can fetch it. Any other host must send
|
|
25
|
+
`Access-Control-Allow-Origin` and be publicly reachable.
|
|
26
|
+
4. **Knob honesty on GLBs**: the template's material knobs (hue, finish) do
|
|
27
|
+
nothing on a GLB's own materials — declare only params that act
|
|
28
|
+
(backdrop, light mood, camera pace, and whatever you wire yourself).
|
|
29
|
+
Verify per `params-knobs.md` rule 2.
|
|
30
|
+
5. **Check and push** as usual: `vos check` → `vos push`. Humans do the
|
|
31
|
+
same flow UI-side by dropping a GLB on https://vos.so/gallery.
|
|
32
|
+
|
|
33
|
+
## Server-render cautions (the preview fleet)
|
|
34
|
+
|
|
35
|
+
- No `THREE.DoubleSide` on transmission materials; no `dispersion`.
|
|
36
|
+
- Big GLBs slow the preview render — prefer draco-compressed models and
|
|
37
|
+
keep textures ≤2K for the showcase context.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Params and Looks — the control surface you ship
|
|
2
|
+
|
|
3
|
+
A remix delivers output *plus the controls you considered while making it*.
|
|
4
|
+
The human's next instruction can be a knob turn, a prompt in knob
|
|
5
|
+
vocabulary, or both: human instructs → agent creates (program + knobs +
|
|
6
|
+
Looks) → human feels the space and settles or redirects → settled values
|
|
7
|
+
bake in, the surface renegotiates, repeat. **You ship an interface, not
|
|
8
|
+
just an artifact.**
|
|
9
|
+
|
|
10
|
+
## Format
|
|
11
|
+
|
|
12
|
+
```json
|
|
13
|
+
"params": [{ "key": "hue", "label": "Hue", "kind": "number",
|
|
14
|
+
"min": 0, "max": 1, "default": 0.6,
|
|
15
|
+
"hint": "Shifts every color around the wheel",
|
|
16
|
+
"unit": "°", "group": "Color", "order": 1 }]
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
- kinds: `number` (min/max/step) | `color` | `select` (options) | `toggle`
|
|
20
|
+
- `hint`: ONE sentence on what visibly changes — always write it
|
|
21
|
+
- `unit` shows inside the number field (`px` `%` `s` `×` `°`);
|
|
22
|
+
`group`/`order` cluster related knobs into their own panel card
|
|
23
|
+
- The program reads each key from `ctx.data` where it animates:
|
|
24
|
+
```js
|
|
25
|
+
const d = ctx.data || {}
|
|
26
|
+
if (typeof d.hue === 'number') u.uHue.value = d.hue
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Looks are named points in param space — free variants (one program, three
|
|
30
|
+
directions, zero extra render cost):
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
"presets": [{ "name": "Vivid", "values": { "hue": 0.9, "speed": 2 } },
|
|
34
|
+
{ "name": "Calm", "values": { "hue": 0.3, "speed": 0.6 } }]
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Values must reference declared param keys with matching types (anything
|
|
38
|
+
else is dropped on save; max 8 Looks, names ≤24 chars). Ship 2–3 Looks
|
|
39
|
+
whenever the program has 4+ params.
|
|
40
|
+
|
|
41
|
+
## The five rules
|
|
42
|
+
|
|
43
|
+
1. **The knob budget is a negotiation, not an accumulation.** Curate 2–4
|
|
44
|
+
knobs (the schema caps at 12). A knob earns its slot by being touched or
|
|
45
|
+
asked about. **Collapse**: when the human settles a value and stops
|
|
46
|
+
touching it, bake it into the code as the new default and free the slot —
|
|
47
|
+
the surface is a cache of live decisions, not an archive. **Promotion**:
|
|
48
|
+
recurring prompt themes become knobs ("you keep circling pacing — I
|
|
49
|
+
added `pace`").
|
|
50
|
+
2. **Knob honesty is renderable.** Every knob must visibly change the
|
|
51
|
+
output. Verify: render frames at several points of the knob's range and
|
|
52
|
+
compare — min, MIDPOINT, max for numbers. The midpoint matters:
|
|
53
|
+
circular quantities (hue is the classic) look identical at the two range
|
|
54
|
+
ends (±half a turn is the same rotation), so a min-vs-max check calls a
|
|
55
|
+
working knob dead. If the best pair is near-identical, the knob is dead;
|
|
56
|
+
wire it or drop it. Fake agency poisons the whole paradigm.
|
|
57
|
+
3. **Respect human-set values.** A value the human adjusted is theirs — when
|
|
58
|
+
you regenerate code, preserve what each knob does. Renaming or retiring
|
|
59
|
+
a knob is something you SAY in the iteration note ("replaced `speed`
|
|
60
|
+
with `tempo`"), never something that happens silently. This rule is
|
|
61
|
+
ENFORCED: the platform rejects a push that touches nodes a studio
|
|
62
|
+
version edited since your last push, until you pass `--overrides` — the
|
|
63
|
+
consent switch for "the user asked me to change exactly this".
|
|
64
|
+
4. **Name knobs by intent, not implementation** — `mood`, `drama`, `pace`;
|
|
65
|
+
never `blurRadius`. The knob is language between two authors; its name
|
|
66
|
+
becomes the vocabulary of the next prompt.
|
|
67
|
+
5. **State the boundary.** Knobs cover the aesthetic space (continuous or
|
|
68
|
+
enumerable dimensions). Structural change — a new scene, a new object, a
|
|
69
|
+
different narrative — stays prompt territory. Knobs are for feeling;
|
|
70
|
+
prompts are for asking.
|
|
71
|
+
|
|
72
|
+
## Craft notes
|
|
73
|
+
|
|
74
|
+
- A `select` of curated combinations often beats three independent numbers
|
|
75
|
+
(e.g. `mood: dusk | noon | neon` driving palette + light together).
|
|
76
|
+
- Defaults must reproduce the pushed output exactly: knobs at defaults =
|
|
77
|
+
the video you shipped.
|
|
78
|
+
- On GLB/model swaps, template material knobs usually stop acting (the
|
|
79
|
+
model brings its own materials) — see `3d-recipe.md`; declare only knobs
|
|
80
|
+
you have verified act.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# The remix contract (HTTP)
|
|
2
|
+
|
|
3
|
+
Mirror of https://vos.so/llms-remix.txt — the canonical, always-current
|
|
4
|
+
copy. Everything the CLI's `fetch`/`check`/`push` do rides these endpoints;
|
|
5
|
+
use them directly when the CLI is unavailable.
|
|
6
|
+
|
|
7
|
+
## Auth
|
|
8
|
+
|
|
9
|
+
Two credential shapes; NEVER print either.
|
|
10
|
+
|
|
11
|
+
1. **Remix grant** (`vos_rg_…`) — ephemeral, zero-setup. The watch page's
|
|
12
|
+
"remix with your agent" prompt embeds one. Grants expire in 24h and are
|
|
13
|
+
bound to ONE source vos: they can only POST remixes of it (`remixOfId`
|
|
14
|
+
required, max 5 pushes), iterate the voses they created, and read those.
|
|
15
|
+
2. **Durable content key** (`vos_sk_…`) — minted at https://vos.so/app/api.
|
|
16
|
+
Resolution order before asking the user: `VOS_API_KEY` env, then
|
|
17
|
+
`~/.config/vos/credentials` (first line). If the user pastes a key into
|
|
18
|
+
chat, use it — and suggest rotating it afterward.
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
Authorization: Bearer <token>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Both shapes can create/read/iterate voses. They can NEVER publish
|
|
25
|
+
(`visibility: "public"` is clamped or rejected — publishing stays a human
|
|
26
|
+
act on vos.so) and never touch the render API. Durable-key creates are
|
|
27
|
+
quota'd (50/24h).
|
|
28
|
+
|
|
29
|
+
## Endpoints
|
|
30
|
+
|
|
31
|
+
| Call | What |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| `GET /api/vos/{id}` | metadata: title, slug, params, `contentUrls`, `forkedFrom`, `currentVersionId` |
|
|
34
|
+
| `GET /api/vos/{id}/config` | `{ "config": VosConfigJson }` — the raw stored config, params included |
|
|
35
|
+
| `POST /api/vos` | create: `{ title, slug, visibility: "private", config, remixOfId? }` → `201 { vos: { id, … } }`; preview render auto-queues |
|
|
36
|
+
| `POST /api/vos/{id}/versions` | iterate: `{ config, baseVersionId?, label?, note?, overrides? }` → `201 { version: { id, versionNumber } }`; stale base or protected nodes → 409 (see Errors) |
|
|
37
|
+
| `GET /api/vos/{id}/changes?since={versionId}` | owner-only: the typed changelog after your base — attributed versions (origin/label/note), semantic `summary` + ops per version, and the `protected` human-edited node set |
|
|
38
|
+
| `PATCH /api/vos/{id}` | `{ title \| config \| tags \| visibility: "private"\|"unlisted" }` |
|
|
39
|
+
| `POST /api/claim` | **no auth** — the claimable push: `{ title, slug?, config }` → `201 { claimUrl, expiresAt, vos: { id } }`. Programs only, config ≤200KB, 5/24h per network. The claimUrl goes to the user and nowhere else; unclaimed work is deleted after 72h |
|
|
40
|
+
|
|
41
|
+
Base URL `https://vos.so`. `slug` is `[a-z0-9-]`, unique per user, ≤50
|
|
42
|
+
chars. `remixOfId` stamps the "remixed from" credit — always set it when
|
|
43
|
+
the work started from someone's program.
|
|
44
|
+
|
|
45
|
+
## Config rules (enforced server-side)
|
|
46
|
+
|
|
47
|
+
- Function fields are JS **strings**: no TypeScript syntax; escape
|
|
48
|
+
backticks/`${}` that must survive into output.
|
|
49
|
+
- `createContent` returns `{ objects, refs, dispose }`; `createTimeline`
|
|
50
|
+
reaches custom handles via `content.refs.<x>`.
|
|
51
|
+
- Server-render constraints: no `THREE.DoubleSide` on transmission
|
|
52
|
+
materials, no `dispersion`, assets by absolute `https` URL only.
|
|
53
|
+
- The platform compiles on every push — a push that 400s with a compile
|
|
54
|
+
error was going to render nothing; fix and re-push. `vos check` runs the
|
|
55
|
+
same compiler locally first.
|
|
56
|
+
|
|
57
|
+
## Params and presets (preserved by contract)
|
|
58
|
+
|
|
59
|
+
`config.params` (max 12 declared; curate 2–4) and `config.presets` (max 8,
|
|
60
|
+
names ≤24 chars) survive every create/version/PATCH — the platform
|
|
61
|
+
re-attaches them even though its schema strips unknown fields. Format and
|
|
62
|
+
craft rules: `params-knobs.md`.
|
|
63
|
+
|
|
64
|
+
## Hand-back
|
|
65
|
+
|
|
66
|
+
Give the user both URLs every time:
|
|
67
|
+
|
|
68
|
+
- watch: `https://vos.so/vos/{id}` — preview, knobs, the program
|
|
69
|
+
- studio: `https://vos.so/studio?vos={id}` — live fine-tuning of your knobs
|
|
70
|
+
|
|
71
|
+
## Errors
|
|
72
|
+
|
|
73
|
+
| Status | Meaning | Do |
|
|
74
|
+
| --- | --- | --- |
|
|
75
|
+
| 400 | Invalid input / Failed to compile config | fix locally (`vos check`), re-push |
|
|
76
|
+
| 401 | Invalid or revoked key | re-resolve credentials; ask the user |
|
|
77
|
+
| 403 | missing `content` scope · cannot publish · grant off its source vos | respect the boundary; don't retry |
|
|
78
|
+
| 409 | slug exists (on create) | pick another slug (the CLI retries derived slugs automatically) |
|
|
79
|
+
| 409 | `stale_base` (on versions) | the platform copy moved since your base — the body EMBEDS the typed changes you missed; `vos pull`, re-apply, push with the fresh base |
|
|
80
|
+
| 409 | `protected_conflict` (on versions) | your push touches nodes a studio version edited since your last push — keep the human's values, or include the listed ids in `overrides` ONLY when the user asked for that change |
|
|
81
|
+
| 429 | 50/24h create quota, or grant's 5-push cap | iterate versions instead of creating; or wait |
|