@mevdragon/vidfarm-devcli 0.20.0 → 0.20.2

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/SKILL.director.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: vidfarm-director
3
- description: Use Vidfarm as a director. Browse/add inspiration videos, fork a template into a composition, edit it in the Trackpad Editor (timeline-based like Premiere/DaVinci), auto-decompose source video into scenes, render to MP4, approve into a shareable post, and schedule it. Includes login, provider keys, discovery, versioning, uploads/downloads, and billing. Every step is available as a raw REST route and as a 1:1 `vidfarm-devcli` command.
3
+ description: Use Vidfarm as a director. Browse/add inspiration videos, fork a template into a composition, edit it in the Trackpad Editor (timeline-based like Premiere/DaVinci), auto-decompose source video into scenes, render to MP4, approve into a shareable post, and schedule it. Includes login, provider keys, discovery, versioning, uploads/downloads, and billing. Every step is available as raw REST; `vidfarm-devcli` wraps those routes and composes the file-backed scripting flows.
4
4
  ---
5
5
 
6
6
  # Vidfarm Director
@@ -136,6 +136,19 @@ Content-Type: application/json
136
136
 
137
137
  Returns the same fork metadata shape as `POST /api/v1/compositions` (201). devcli: `vidfarm clone <forkId> [--from current|default] [--version N] [--title …]`. In the in-editor AI chat this is the `editor_action` `fork_composition` action (`fork_from: current|default`).
138
138
 
139
+ ## Automate a template via REST
140
+
141
+ Templates now have the same job-backed REST pattern as primitives, so a script can run them repeatably without the editor UI:
142
+
143
+ ```
144
+ POST /api/v1/templates/:templateId/operations/:operationName
145
+ Content-Type: application/json
146
+
147
+ { "tracer": "my-run", "payload": { ... }, "webhook_url": "https://..." }
148
+ ```
149
+
150
+ The route returns `202` with a `job_id`, and you can poll the job with `GET /api/v1/user/me/jobs/:jobId` or the template-scoped `GET /api/v1/templates/:templateId/jobs/:jobId`. devcli wraps the same flow as `vidfarm template run <templateId> <operationName> --payload-file payload.json --wait`.
151
+
139
152
  ## Agentic editing: the three axes (SWAP ↔ REPLACE)
140
153
 
141
154
  Almost every editor session is a director taking a template / fork / project and **re-working** it, and a re-work only ever touches three independent axes — **SCENES** (the video/image clips carrying the visuals), **AUDIO** (narration/voiceover, music, SFX), and **TEXT** (captions, titles, overlays). On each axis the intent sits on a **SWAP ↔ REPLACE** spectrum, and the three axes in one request can sit at different points — decide each before you act:
@@ -439,7 +452,7 @@ Beyond the Ken Burns / transition / animated-caption presets, the copilot can ha
439
452
 
440
453
  ## Render (publish to MP4)
441
454
 
442
- Rendering publishes the fork's current working state to an MP4 using HyperFrames (cloud Lambda fan-out on the deployed host, or the free in-process renderer on a local `vidfarm serve` box). In the Trackpad Editor this is the **Render** button. The REST route is `/render`; the older `/export` path is kept as a deprecated alias for already-published devcli clients (treat "Render", "publish", `/render`, and `/export` as the same operation). The devcli exposes it as `vidfarm render <forkId> [--wait]`.
455
+ Rendering publishes the fork's current working state to an MP4 using HyperFrames (cloud Lambda fan-out on the deployed host, or the free in-process renderer on a local `vidfarm serve` box). In the Trackpad Editor this is the **Render** button. The REST route is `/render`; the older `/export` path is kept as a deprecated alias for already-published devcli clients (treat "Render", "publish", `/render`, and `/export` as the same operation). The devcli exposes it as `vidfarm render <forkId> [--wait]`; scripted local dirs can use `vidfarm render <forkId> --dir ./work --wait`.
443
456
 
444
457
  ```
445
458
  POST /api/v1/compositions/:forkId/render
@@ -448,16 +461,18 @@ Content-Type: application/json
448
461
  { "title": "optional", "version": null, "tracer": "optional-trace-id", "html": "optional HTML to save to working state before rendering" }
449
462
  ```
450
463
 
451
- Returns 202 with `{ ok, renderId, status, progress, outputUrl, cost, title, version, ... }` where `version` is the snapshot version created for this publish. Failure modes: `402` if the fork owner is not on a paid plan, `409` while GhostCut subtitle removal is still `pending` (retry after `/remove-video-captions-poll` reports done/failed), `412` if the provider-key preflight fails. Poll:
464
+ Returns 202 with `{ ok, renderId, status, progress, expectedOutputPublicUrl, outputUrl, cost, title, version, ... }` where `expectedOutputPublicUrl` is the deterministic public MP4 URL and `version` is the snapshot version created for this publish. Failure modes: `402` if the fork owner is not on a paid plan, `409` while GhostCut subtitle removal is still `pending` (retry after `/remove-video-captions-poll` reports done/failed), `412` if the provider-key preflight fails. Poll:
452
465
 
453
466
  ```
454
467
  GET /api/v1/compositions/:forkId/renders/:renderId
455
468
  ```
456
469
 
457
- Response includes `{ ok, renderId, status: "RUNNING" | "SUCCEEDED" | "FAILED", progress, framesRendered, totalFrames, cost, outputUrl, outputS3Uri, errors }` (`progress` is 0..1). On success, `outputUrl` is the durable MP4 URL.
470
+ Response includes `{ ok, renderId, status: "RUNNING" | "SUCCEEDED" | "FAILED", progress, framesRendered, totalFrames, cost, expectedOutputPublicUrl, outputUrl, outputS3Uri, errors }` (`progress` is 0..1). On success, `expectedOutputPublicUrl` is the durable public MP4 URL and `outputUrl` remains the completion-time field.
458
471
 
459
472
  Every publish creates an immutable version snapshot at `versions/<N>/composition.html` and `versions/<N>/composition.json`.
460
473
 
474
+ The Web UI **Render** button and devcli render both use this same endpoint. The fast `202` response includes the deterministic `expectedOutputPublicUrl` so a caller can store or pass along the final public S3 URL before the render has completed, then poll by `renderId` until `status` settles.
475
+
461
476
  ## Approve a finished post
462
477
 
463
478
  A render produces a bare MP4 URL. **Approving** wraps that MP4 (plus caption, title, pinned comment, and any carousel slides) into a shareable preview page — the phone-mockup page a human opens to review and copy the post.
@@ -600,16 +615,73 @@ For agents that operate Vidfarm headlessly, the typical loop is:
600
615
  3. `PATCH /api/v1/compositions/:forkId/composition.json` → update metadata
601
616
  4. `POST /api/v1/compositions/:forkId/render { tracer }` → render
602
617
  5. Poll `GET /api/v1/compositions/:forkId/renders/:renderId` until `SUCCEEDED`
603
- 6. Use `outputUrl` in the next stage
618
+ 6. Use `expectedOutputPublicUrl` in the next stage when you need the stable public URL immediately; otherwise fall back to `outputUrl` after completion
604
619
 
605
620
  Send a stable `tracer` on export so retries are traceable and filterable in job history — but note that submission is **not idempotent**: every POST creates a new job (and a new charge) even with the same tracer. Do not blind-retry expensive submissions; check the render status first.
606
621
 
622
+ ## Scripting mode
623
+
624
+ **Scripting mode** is the recommended posture for repeatable template automation. Use it when a director wants to take a template they like, agree on a base fork, and then drive bulk or one-off edits entirely through REST or `vidfarm api` from a script, Lambda, or local machine.
625
+
626
+ Contract:
627
+
628
+ 1. Pick the template once, then fork once and treat the resulting `forkId` as the stable base.
629
+ 2. Read the working state with `GET /api/v1/compositions/:forkId/composition.html` and `GET /api/v1/compositions/:forkId/composition.json`.
630
+ 3. Modify the composition deterministically in your script.
631
+ 4. Write back with `PUT /api/v1/compositions/:forkId/composition.html` and `PATCH /api/v1/compositions/:forkId/composition.json`.
632
+ 5. Snapshot with `POST /api/v1/compositions/:forkId/versions` before or after render, depending on whether you want the version to capture the exact render input or the post-render state.
633
+ 6. Render with `POST /api/v1/compositions/:forkId/render`, choosing local or cloud based on the host and runtime.
634
+
635
+ Devcli shortcut:
636
+
637
+ ```bash
638
+ vidfarm render "$FORK_ID" --dir ./work --tracer "batch-2026-07-09-row-42" --wait
639
+ ```
640
+
641
+ That command validates `./work/composition.html`, shallow-patches `./work/composition.json` if present, then submits the same `POST /api/v1/compositions/:forkId/render` call used by the Web UI. `--dir` may also point directly at `composition.html`.
642
+
643
+ Best practices:
644
+
645
+ - Prefer one canonical base fork per automation run, then branch from that fork if you need variants.
646
+ - Treat `composition.json` as a shallow merged metadata document. The server merges the posted JSON object into the existing object; it is not RFC 6902 JSON Patch.
647
+ - Keep edits idempotent in your script. Re-run the script against the same fork only if it computes the same desired state.
648
+ - Use a stable `tracer` on render jobs so logs and job history stay searchable.
649
+ - Use the same REST sequence in Lambda, CI, or a local shell. The only thing that changes is the host and auth.
650
+
651
+ Canonical shell shape:
652
+
653
+ ```bash
654
+ BASE_TEMPLATE_ID="template_..."
655
+ FORK_ID="$(vidfarm api POST /api/v1/compositions --data "{\"template_id\":\"${BASE_TEMPLATE_ID}\"}" --json | jq -r '.fork_id')"
656
+
657
+ vidfarm api GET "/api/v1/compositions/${FORK_ID}/composition.html" --raw > /tmp/composition.html
658
+ vidfarm api GET "/api/v1/compositions/${FORK_ID}/composition.json" --raw > /tmp/composition.json
659
+
660
+ # edit /tmp/composition.html and /tmp/composition.json in your script
661
+
662
+ vidfarm api PUT "/api/v1/compositions/${FORK_ID}/composition.html" --body-file /tmp/composition.html --content-type "text/html; charset=utf-8"
663
+ vidfarm api PATCH "/api/v1/compositions/${FORK_ID}/composition.json" --data-file /tmp/composition.json
664
+ vidfarm api POST "/api/v1/compositions/${FORK_ID}/versions" --data '{"message":"scripting mode snapshot"}'
665
+ vidfarm api POST "/api/v1/compositions/${FORK_ID}/render" --data '{"tracer":"scripting-mode"}'
666
+ ```
667
+
668
+ If you need many variants, keep the base fork fixed and fan out by cloning that fork or by reapplying the same edit function to multiple fork ids. Use the raw REST routes directly when you want maximum control; use `vidfarm-devcli` when you want auth, polling, and file helpers without writing the plumbing yourself.
669
+
607
670
  ## `vidfarm-devcli` — full command surface
608
671
 
609
- `@mevdragon/vidfarm-devcli` wraps the **entire director REST flow** as CLI commands. It is a thin shell over the REST API, not a second implementation: **every named command maps 1:1 to exactly one REST route**, and all it adds is fork auto-resolution, the `vidfarm-api-key` header, prod frontend links in the output, render-poll waiting, and the multi-step upload/download flows. Auth via `--api-key <key>` or `VIDFARM_API_KEY`.
672
+ `@mevdragon/vidfarm-devcli` wraps the **entire director REST flow** as CLI commands. It is a thin shell over the REST API, not a second implementation: most named commands map 1:1 to one REST route, and the file-backed commands compose the documented routes for upload/download + render-polling. Auth via `--api-key <key>` or `VIDFARM_API_KEY`.
610
673
 
611
674
  **Raw REST vs devcli — your choice.** If you want full control, call the REST API directly (or use the raw passthrough `vidfarm api <METHOD> <path> [--data <json>] [--query k=v]`). If you want ergonomics + openable frontend URLs, use the named commands. They are interchangeable — pick per call.
612
675
 
676
+ **Scripting mode recommendation.** For automation, prefer:
677
+
678
+ - `vidfarm api` for the actual REST calls
679
+ - `--data-file` for file-backed payloads
680
+ - a single pinned base fork id per template family
681
+ - `POST /api/v1/compositions/:forkId/versions` as the versioning boundary
682
+ - `POST /api/v1/compositions/:forkId/render` with a stable `tracer`, or `vidfarm render <forkId> --dir ./work --wait` for the same composed flow
683
+ - `render_target: "cloud"` when you want cloud handoff from a local `vidfarm serve` box, or the default local renderer when you want free in-process output
684
+
613
685
  | Command | REST route | Flow step |
614
686
  |---|---|---|
615
687
  | `vidfarm discover [query]` | `GET /discover/feed[?q=]` | browse/search templates |
@@ -636,7 +708,7 @@ Send a stable `tracer` on export so retries are traceable and filterable in job
636
708
  | `vidfarm remove-video-captions <forkId>` (alias: `ghostcut`) | `GET .../compositions/:forkId/remove-video-captions` | subtitle-removal status |
637
709
  | `vidfarm snapshot <forkId>` | `POST .../compositions/:forkId/versions` | save composition fork version |
638
710
  | `vidfarm versions <forkId>` | `GET .../compositions/:forkId/versions` | list versions |
639
- | `vidfarm render <forkId> [--wait]` | `POST .../compositions/:forkId/render` | render video to MP4 |
711
+ | `vidfarm render <forkId> [--dir <dir\|composition.html>] [--wait] [--target local\|cloud]` | `PUT/PATCH working files, then POST .../compositions/:forkId/render` | script-friendly render to MP4; no `--dir` uses the fork's current working state |
640
712
  | `vidfarm render-status <forkId> <renderId>` | `GET .../compositions/:forkId/renders/:renderId` | poll a render |
641
713
  | `vidfarm visibility <forkId> <private\|public>` | `PATCH .../compositions/:forkId/visibility` | set visibility |
642
714
  | `vidfarm clone <forkId>` | `POST .../compositions/:forkId/clone` | clone a fork |
package/SKILL.platform.md CHANGED
@@ -205,8 +205,8 @@ Publish flow:
205
205
  3. API resolves the caller's provider keys (preflight check for required models)
206
206
  4. API creates a `job` record and invokes the `hyperframes_render` primitive Lambda
207
207
  5. The renderer runs HyperFrames: on the deployed host it stages the composition and dispatches to the shared HyperFrames render state machine (chunked Lambda fan-out); on a local `vidfarm serve` box with no cloud stack it renders in-process (headless Chromium → ffmpeg) for free. See `HyperframesService` in `src/services/hyperframes.ts`.
208
- 6. On success, the primitive returns `{ primary_file_url: "s3://.../output.mp4" }`, the API creates a `ForkVersionRecord` with `reason: "publish"`, writes the snapshot to `versions/<N>/`, and updates the fork's `latestVersion` and `currentRenderJobId`
209
- 7. Client polls `GET /api/v1/compositions/:forkId/renders/:renderId` for `{ status: "RUNNING" | "SUCCEEDED" | "FAILED", progress, outputUrl, cost }` (see `adaptJobToPublishStatus` in `src/app.ts`)
208
+ 6. On success, the primitive returns `{ primary_file_url: "s3://.../output.mp4" }`, the API creates a `ForkVersionRecord` with `reason: "publish"`, writes the snapshot to `versions/<N>/`, updates the fork's `latestVersion` and `currentRenderJobId`, and now also exposes the deterministic public artifact URL immediately as `expected_output_public_url`
209
+ 7. Client polls `GET /api/v1/compositions/:forkId/renders/:renderId` for `{ status: "RUNNING" | "SUCCEEDED" | "FAILED", progress, expectedOutputPublicUrl, outputUrl, cost }` (see `adaptJobToPublishStatus` in `src/app.ts`); `expectedOutputPublicUrl` is the stable public S3 URL, while `outputUrl` remains the completion-time field
210
210
 
211
211
  The HyperFrames render state machine is **shared across all templates and forks** — it's an infrastructure primitive, not a per-template deployment. Its ARN/bucket are passed to the Vidfarm stack as env vars (`HYPERFRAMES_RENDER_*`). Remotion has been fully removed.
212
212