@officexapp/vidfarm-devcli 0.21.29 → 0.21.30
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.
|
@@ -365,6 +365,8 @@ vidfarm doctor # ✓/⚠/✗ for node, ffmpeg, hy
|
|
|
365
365
|
- **`ffmpeg`** — the media engine the devcli drives for every local media op: `remove-greenscreen --local` (chroma-key → transparent PNG/WebP/WebM, ProRes fallback where the local libvpx can't do WebM alpha), STT/caption demux, `raws scan` clip cutting, `stills`, audio trims. **Hard requirement** — `vidfarm doctor` exits non-zero without it.
|
|
366
366
|
- **`hyperframes`** — **Vidfarm's own render/animation engine, open-source under a whitelabel.** *Vidfarm renders ARE hyperframes renders.* The devcli bundles it and re-exposes everything it does locally as **`vidfarm hf <subcommand>`** — `vidfarm hf render <dir> -o out.mp4`, `capture`, `validate`, `preview`, `doctor`, plus the ONNX `remove-background` matting, Kokoro TTS, and Whisper STT engines the `tts`/`stt`/`remove-background` commands ride. Installing it standalone makes these run **natively** instead of a slower `npx -y hyperframes` fallback (which `vidfarm doctor` will warn about).
|
|
367
367
|
|
|
368
|
+
**The local studio UI is whitelabeled automatically.** `hyperframes preview` (and `vidfarm hf preview`) serves a studio SPA whose stock shell paints an upstream "HeyGen · HyperFrames" header logo and a "HyperFrames Studio" tab title. Every devcli hyperframes spawn — and `vidfarm doctor` — idempotently patches that shell in place (`src/devcli/studio-brand.ts`) so the header reads **VidFarm**, the tab title is **VidFarm Studio**, and the product name in the studio's own copy (lint panel, feedback prompt, storyboard/agent prompts, clipboard writes) is rewritten. `.hyperframes/` paths and `data-hyperframes-*` DOM hooks are preserved verbatim — they name real files and hooks — and CLI verbs map to their twins (`hyperframes render` → `vidfarm render`). A fresh `npm install` restores the stock shell; the next devcli command (or `vidfarm doctor`) re-applies it. If a director ever screenshots upstream branding, run `vidfarm doctor`.
|
|
369
|
+
|
|
368
370
|
**Treat `hyperframes` as Vidfarm** (it is — just whitelabeled): never point it at an external HeyGen/vendor account, publish service, or telemetry endpoint. Keep `HYPERFRAMES_SKIP_SKILLS=1` + `HYPERFRAMES_NO_TELEMETRY=1` set (the devcli sets these for its children); do not run `hyperframes auth`/`cloud`/`publish`/`play`/`feedback` — Vidfarm's own render/share/telemetry surfaces replace all of them. Everything else `hyperframes` can do locally is fair game and encouraged.
|
|
369
371
|
|
|
370
372
|
## Local dev loop (`vidfarm serve`)
|
package/SKILL.director.md
CHANGED
|
@@ -2059,6 +2059,8 @@ vidfarm doctor # ✓/⚠/✗ for node, ffmpeg, hy
|
|
|
2059
2059
|
- **`ffmpeg`** — the media engine the devcli drives for every local media op: `remove-greenscreen --local` (chroma-key → transparent PNG/WebP/WebM, ProRes fallback where the local libvpx can't do WebM alpha), STT/caption demux, `raws scan` clip cutting, `stills`, audio trims. **Hard requirement** — `vidfarm doctor` exits non-zero without it.
|
|
2060
2060
|
- **`hyperframes`** — **Vidfarm's own render/animation engine, open-source under a whitelabel.** *Vidfarm renders ARE hyperframes renders.* The devcli bundles it and re-exposes everything it does locally as **`vidfarm hf <subcommand>`** — `vidfarm hf render <dir> -o out.mp4`, `capture`, `validate`, `preview`, `doctor`, plus the ONNX `remove-background` matting, Kokoro TTS, and Whisper STT engines the `tts`/`stt`/`remove-background` commands ride. Installing it standalone makes these run **natively** instead of a slower `npx -y hyperframes` fallback (which `vidfarm doctor` will warn about).
|
|
2061
2061
|
|
|
2062
|
+
**The local studio UI is whitelabeled automatically.** `hyperframes preview` (and `vidfarm hf preview`) serves a studio SPA whose stock shell paints an upstream "HeyGen · HyperFrames" header logo and a "HyperFrames Studio" tab title. Every devcli hyperframes spawn — and `vidfarm doctor` — idempotently patches that shell in place (`src/devcli/studio-brand.ts`) so the header reads **VidFarm**, the tab title is **VidFarm Studio**, and the product name in the studio's own copy (lint panel, feedback prompt, storyboard/agent prompts, clipboard writes) is rewritten. `.hyperframes/` paths and `data-hyperframes-*` DOM hooks are preserved verbatim — they name real files and hooks — and CLI verbs map to their twins (`hyperframes render` → `vidfarm render`). A fresh `npm install` restores the stock shell; the next devcli command (or `vidfarm doctor`) re-applies it. If a director ever screenshots upstream branding, run `vidfarm doctor`.
|
|
2063
|
+
|
|
2062
2064
|
**Treat `hyperframes` as Vidfarm** (it is — just whitelabeled): never point it at an external HeyGen/vendor account, publish service, or telemetry endpoint. Keep `HYPERFRAMES_SKIP_SKILLS=1` + `HYPERFRAMES_NO_TELEMETRY=1` set (the devcli sets these for its children); do not run `hyperframes auth`/`cloud`/`publish`/`play`/`feedback` — Vidfarm's own render/share/telemetry surfaces replace all of them. Everything else `hyperframes` can do locally is fair game and encouraged.
|
|
2063
2065
|
|
|
2064
2066
|
## Local dev loop (`vidfarm serve`)
|
|
@@ -15,6 +15,7 @@ import { parseArgs } from "node:util";
|
|
|
15
15
|
import { detectLocalAgent } from "../services/clip-curation/index.js";
|
|
16
16
|
import { hasFfmpeg, resolveFfmpeg, resolveFfprobe } from "../services/clip-curation/ffmpeg.js";
|
|
17
17
|
import { resolveHyperframesCli } from "./hyperframes-cli.js";
|
|
18
|
+
import { applyVidfarmStudioBrand } from "./studio-brand.js";
|
|
18
19
|
import { resolveSkillsRoot } from "./skills.js";
|
|
19
20
|
import { readStoredAuth } from "./auth-store.js";
|
|
20
21
|
import { scanLocalServers, reapProcesses } from "./process-scan.js";
|
|
@@ -138,6 +139,18 @@ export async function runDoctorCommand(argv) {
|
|
|
138
139
|
add("hyperframes", hyperframesCli ? "ok" : "warn", hyperframesCli
|
|
139
140
|
? `${hyperframesCli} (Vidfarm's whitelabel render/animation engine — reach it via \`vidfarm hf …\`)`
|
|
140
141
|
: "not installed — Vidfarm's render/animation engine (open-source whitelabel). Install for native local render/tts/stt/matting: `npm i -g hyperframes` (else falls back to slow `npx -y hyperframes`)");
|
|
142
|
+
// 3b. Whitelabel the LOCAL studio shell (the `hyperframes preview` editor UI),
|
|
143
|
+
// which otherwise renders the upstream "HeyGen · HyperFrames" header logo and
|
|
144
|
+
// tab title. `doctor` REPAIRS it rather than just reporting: the patch is
|
|
145
|
+
// idempotent and a fresh `npm install` restores the pristine shell.
|
|
146
|
+
if (hyperframesCli) {
|
|
147
|
+
const brand = applyVidfarmStudioBrand();
|
|
148
|
+
add("studio branding", brand === "unavailable" ? "warn" : "ok", brand === "patched"
|
|
149
|
+
? "local studio shell re-branded as VidFarm (upstream logo/title replaced)"
|
|
150
|
+
: brand === "already-branded"
|
|
151
|
+
? "local studio shell already whitelabeled as VidFarm"
|
|
152
|
+
: "could not patch the local studio shell — `hyperframes preview` will show upstream branding (cosmetic only)");
|
|
153
|
+
}
|
|
141
154
|
// 4. Chrome for the in-process render (stills / serve local render).
|
|
142
155
|
const chrome = detectChromeForRender();
|
|
143
156
|
add("chrome", chrome.found ? "ok" : "warn", chrome.found ? chrome.detail : `${chrome.detail} — local render/stills will try to download one on first run`);
|
|
@@ -49,6 +49,18 @@ export async function runHyperframesCommand(subcommand, args, opts = {}) {
|
|
|
49
49
|
"Local engines and vidfarm BYOK keys are the only auth.");
|
|
50
50
|
}
|
|
51
51
|
const cli = resolveHyperframesCli();
|
|
52
|
+
// The local studio SPA shell ships upstream branding (a "HeyGen · HyperFrames"
|
|
53
|
+
// header logo and a "HyperFrames Studio" tab title) that `hyperframes preview`
|
|
54
|
+
// serves straight off disk — the one Vidfarm surface the web editor's own
|
|
55
|
+
// rebrand never reaches. Whitelabel the shell on EVERY hyperframes spawn, not
|
|
56
|
+
// just preview: the patch is a cheap idempotent file check, and doing it here
|
|
57
|
+
// means a director who later runs `hyperframes preview` by hand still gets the
|
|
58
|
+
// VidFarm studio. Best-effort — branding never fails a render.
|
|
59
|
+
try {
|
|
60
|
+
const { applyVidfarmStudioBrand } = await import("./studio-brand.js");
|
|
61
|
+
applyVidfarmStudioBrand();
|
|
62
|
+
}
|
|
63
|
+
catch { /* cosmetic only */ }
|
|
52
64
|
// Fresh empty config dir per invocation — guarantees no ~/.heygen credential
|
|
53
65
|
// (or any other persisted account state) leaks into the child process.
|
|
54
66
|
const emptyConfigDir = mkdtempSync(path.join(os.tmpdir(), "vidfarm-hf-noauth-"));
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
// Whitelabel the LOCAL hyperframes Studio UI as VidFarm.
|
|
2
|
+
//
|
|
3
|
+
// The web editor (`/editor`, `vidfarm serve`) mounts the sealed <StudioApp/>
|
|
4
|
+
// through demo/src/VidfarmStudioEditor.tsx, which already swaps the upstream
|
|
5
|
+
// "HeyGen · HyperFrames" header logo and rewrites the product name in copy.
|
|
6
|
+
// But `hyperframes preview` (and `vidfarm hf preview`) boots the studio SPA
|
|
7
|
+
// straight out of `node_modules/hyperframes/dist/studio/index.html` — that
|
|
8
|
+
// bundle never passes through our editor entry, so it renders upstream branding
|
|
9
|
+
// on a Vidfarm director's screen.
|
|
10
|
+
//
|
|
11
|
+
// The studio server reads that index.html **per request** (studioServer.ts's
|
|
12
|
+
// SPA fallback), so a one-time on-disk patch of the shell is enough: no fork, no
|
|
13
|
+
// dist rewriting of the JS, no proxy in the middle. We inject a marker-delimited
|
|
14
|
+
// <style> + <script> block that does exactly what the web editor does in JS —
|
|
15
|
+
// hide `svg[aria-label="Hyperframes"]`, insert a VidFarm wordmark, and rename
|
|
16
|
+
// the product in text nodes / tooltips / clipboard writes.
|
|
17
|
+
//
|
|
18
|
+
// The patch is idempotent and versioned: a stale block is replaced, an up-to-date
|
|
19
|
+
// one is left alone, and a fresh `npm install` (which restores the pristine file)
|
|
20
|
+
// is re-patched on the next hyperframes spawn. `.hyperframes/` paths, the
|
|
21
|
+
// `data-hyperframes-*` DOM hooks, and CLI verbs are deliberately preserved /
|
|
22
|
+
// mapped, same as the web editor — renaming those would send an agent hunting
|
|
23
|
+
// for files that do not exist.
|
|
24
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
25
|
+
import path from "node:path";
|
|
26
|
+
import { resolveHyperframesCli } from "./hyperframes-cli.js";
|
|
27
|
+
/** Bump when the injected block changes — older blocks are replaced in place. */
|
|
28
|
+
const BRAND_VERSION = 1;
|
|
29
|
+
const MARK_OPEN = `<!-- vidfarm-studio-brand v${BRAND_VERSION} -->`;
|
|
30
|
+
const MARK_OPEN_ANY = /<!-- vidfarm-studio-brand v\d+ -->/;
|
|
31
|
+
const MARK_CLOSE = "<!-- /vidfarm-studio-brand -->";
|
|
32
|
+
// Tab icon: a self-contained gold "V" plate (data URI, so we never have to ship
|
|
33
|
+
// or overwrite a file inside the hyperframes package). Matches the header
|
|
34
|
+
// wordmark's badge below.
|
|
35
|
+
const VIDFARM_FAVICON = "data:image/svg+xml," +
|
|
36
|
+
encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">' +
|
|
37
|
+
'<rect width="100" height="100" rx="26" fill="#f5c518"/>' +
|
|
38
|
+
'<path d="M26 28h14l10 30 10-30h14L58 76H42z" fill="#1c1608"/>' +
|
|
39
|
+
"</svg>");
|
|
40
|
+
/**
|
|
41
|
+
* Locate `hyperframes/dist/studio/index.html` next to the resolved CLI entry.
|
|
42
|
+
* Returns null when hyperframes is not installed locally (the `npx -y` fallback
|
|
43
|
+
* path — nothing on disk of ours to patch).
|
|
44
|
+
*/
|
|
45
|
+
export function resolveStudioIndexPath() {
|
|
46
|
+
const cli = resolveHyperframesCli();
|
|
47
|
+
if (!cli)
|
|
48
|
+
return null;
|
|
49
|
+
const indexPath = path.join(path.dirname(cli), "studio", "index.html");
|
|
50
|
+
return existsSync(indexPath) ? indexPath : null;
|
|
51
|
+
}
|
|
52
|
+
/** The injected head block: hide the upstream mark, paint ours, rename the product. */
|
|
53
|
+
function brandBlock() {
|
|
54
|
+
return `${MARK_OPEN}
|
|
55
|
+
<style>
|
|
56
|
+
/* Belt-and-suspenders: kill the upstream mark before the script runs so it
|
|
57
|
+
never flashes. The wordmark below is inserted in its place. */
|
|
58
|
+
svg[aria-label="Hyperframes"] { display: none !important; }
|
|
59
|
+
</style>
|
|
60
|
+
<script>
|
|
61
|
+
(function () {
|
|
62
|
+
var MARK = "data-vidfarm-logo";
|
|
63
|
+
|
|
64
|
+
function wordmark() {
|
|
65
|
+
var el = document.createElement("div");
|
|
66
|
+
el.setAttribute(MARK, "");
|
|
67
|
+
el.style.cssText = "display:inline-flex;align-items:center;gap:8px;user-select:none;line-height:1";
|
|
68
|
+
var badge = document.createElement("span");
|
|
69
|
+
badge.style.cssText =
|
|
70
|
+
"display:inline-grid;place-items:center;width:24px;height:24px;border-radius:7px;" +
|
|
71
|
+
"background:#f5c518;color:#1c1608;font-weight:800;font-size:14px;font-family:system-ui,sans-serif";
|
|
72
|
+
badge.textContent = "V";
|
|
73
|
+
var word = document.createElement("span");
|
|
74
|
+
word.style.cssText =
|
|
75
|
+
"font-weight:800;font-size:15px;letter-spacing:-.01em;color:#fffbe6;font-family:system-ui,sans-serif";
|
|
76
|
+
word.textContent = "VidFarm";
|
|
77
|
+
el.appendChild(badge);
|
|
78
|
+
el.appendChild(word);
|
|
79
|
+
return el;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function swapLogo() {
|
|
83
|
+
var logos = document.querySelectorAll('svg[aria-label="Hyperframes"]');
|
|
84
|
+
for (var i = 0; i < logos.length; i += 1) {
|
|
85
|
+
var svg = logos[i];
|
|
86
|
+
var prev = svg.previousElementSibling;
|
|
87
|
+
if ((prev && prev.hasAttribute && prev.hasAttribute(MARK)) || svg.getAttribute("data-vidfarm-hidden") === "1") continue;
|
|
88
|
+
svg.setAttribute("data-vidfarm-hidden", "1");
|
|
89
|
+
svg.style.display = "none";
|
|
90
|
+
if (svg.parentElement) svg.parentElement.insertBefore(wordmark(), svg);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Same rewrite table as the web editor: CLI verbs and .hyperframes/ paths are
|
|
95
|
+
// matched BEFORE the bare product name, so real files/commands survive.
|
|
96
|
+
function rewrite(text) {
|
|
97
|
+
return text
|
|
98
|
+
.replace(/\\bhyperframes (render|preview|lint|check|publish|init|add)\\b/g, "vidfarm $1")
|
|
99
|
+
.replace(/(^|[^./\\w-])[Hh]yper[Ff]rames(?![./\\w-])/g, "$1Vidfarm")
|
|
100
|
+
.replace(/(^|[^./\\w-])[Hh]yper[Ff]rame(?![s./\\w-])/g, "$1Vidfarm")
|
|
101
|
+
.replace(/\\bHeyGen\\b/g, "Vidfarm");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function needsRewrite(text) {
|
|
105
|
+
return /[Hh]yper[Ff]rame|HeyGen/.test(text) && rewrite(text) !== text;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function swapText() {
|
|
109
|
+
var walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
|
|
110
|
+
var pending = [];
|
|
111
|
+
for (var node = walker.nextNode(); node; node = walker.nextNode()) {
|
|
112
|
+
var tag = node.parentElement && node.parentElement.tagName;
|
|
113
|
+
if (tag === "SCRIPT" || tag === "STYLE") continue;
|
|
114
|
+
if (needsRewrite(node.nodeValue || "")) pending.push(node);
|
|
115
|
+
}
|
|
116
|
+
for (var i = 0; i < pending.length; i += 1) pending[i].nodeValue = rewrite(pending[i].nodeValue || "");
|
|
117
|
+
var attrs = ["title", "aria-label", "placeholder"];
|
|
118
|
+
var els = document.querySelectorAll("[title],[aria-label],[placeholder]");
|
|
119
|
+
for (var j = 0; j < els.length; j += 1) {
|
|
120
|
+
for (var k = 0; k < attrs.length; k += 1) {
|
|
121
|
+
var value = els[j].getAttribute(attrs[k]);
|
|
122
|
+
if (value && needsRewrite(value)) els[j].setAttribute(attrs[k], rewrite(value));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function apply() {
|
|
128
|
+
swapLogo();
|
|
129
|
+
swapText();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function start() {
|
|
133
|
+
apply();
|
|
134
|
+
new MutationObserver(apply).observe(document.body, { childList: true, subtree: true, characterData: true });
|
|
135
|
+
// Lint / storyboard panels hand agent prompts to the clipboard — rebrand on the way out.
|
|
136
|
+
try {
|
|
137
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
138
|
+
var original = navigator.clipboard.writeText.bind(navigator.clipboard);
|
|
139
|
+
navigator.clipboard.writeText = function (data) {
|
|
140
|
+
return original(typeof data === "string" ? rewrite(data) : data);
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
} catch (err) { /* clipboard locked down — branding is best-effort */ }
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (document.body) start();
|
|
147
|
+
else document.addEventListener("DOMContentLoaded", start);
|
|
148
|
+
})();
|
|
149
|
+
</script>
|
|
150
|
+
${MARK_CLOSE}`;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Patch the installed studio shell in place. Never throws — a read-only or
|
|
154
|
+
* missing node_modules just means the director sees upstream branding, which is
|
|
155
|
+
* cosmetic and must not fail a render.
|
|
156
|
+
*/
|
|
157
|
+
export function applyVidfarmStudioBrand(indexPathOverride) {
|
|
158
|
+
const indexPath = indexPathOverride ?? resolveStudioIndexPath();
|
|
159
|
+
if (!indexPath)
|
|
160
|
+
return "unavailable";
|
|
161
|
+
let html;
|
|
162
|
+
try {
|
|
163
|
+
html = readFileSync(indexPath, "utf-8");
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
return "unavailable";
|
|
167
|
+
}
|
|
168
|
+
const current = brandBlock();
|
|
169
|
+
if (html.includes(MARK_OPEN) && html.includes(MARK_CLOSE)) {
|
|
170
|
+
// Up-to-date block already present (same version) — but the block body can
|
|
171
|
+
// still drift if BRAND_VERSION was not bumped during development, so compare.
|
|
172
|
+
if (html.includes(current))
|
|
173
|
+
return "already-branded";
|
|
174
|
+
}
|
|
175
|
+
// Strip any previous (older-version or drifted) block before re-injecting.
|
|
176
|
+
let out = html.replace(new RegExp(`${MARK_OPEN_ANY.source}[\\s\\S]*?${MARK_CLOSE.replace(/[/]/g, "\\/")}`), "");
|
|
177
|
+
out = out.replace(/<title>[\s\S]*?<\/title>/, "<title>VidFarm Studio</title>");
|
|
178
|
+
// Tab icon (no-op once already swapped — the upstream href is gone by then).
|
|
179
|
+
out = out.replace(/href="\/favicon\.svg"/, `href="${VIDFARM_FAVICON}"`);
|
|
180
|
+
if (out.includes("</head>")) {
|
|
181
|
+
out = out.replace("</head>", `${current}\n </head>`);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
out = `${current}\n${out}`;
|
|
185
|
+
}
|
|
186
|
+
if (out === html)
|
|
187
|
+
return "already-branded";
|
|
188
|
+
try {
|
|
189
|
+
writeFileSync(indexPath, out, "utf-8");
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
return "unavailable";
|
|
193
|
+
}
|
|
194
|
+
return "patched";
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=studio-brand.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@officexapp/vidfarm-devcli",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.30",
|
|
4
4
|
"description": "Local bridge for the Vidfarm Trackpad Editor. `vidfarm serve <template_id>` boots the FULL editor on localhost (disk-backed records/storage, free in-process render); edit composition.html on disk (Claude Code, Codex, etc.) and the browser live-morphs it.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"dist/src/devcli/skills.js",
|
|
33
33
|
"dist/src/devcli/speech.js",
|
|
34
34
|
"dist/src/devcli/sticker-pack.js",
|
|
35
|
+
"dist/src/devcli/studio-brand.js",
|
|
35
36
|
"dist/src/devcli/stills.js",
|
|
36
37
|
"dist/src/devcli/storyboard.js",
|
|
37
38
|
"dist/src/devcli/telemetry.js",
|
|
@@ -93,6 +94,7 @@
|
|
|
93
94
|
"check": "tsc -p tsconfig.json --noEmit && npm run check:skills",
|
|
94
95
|
"test:clips": "node --import tsx --test test/clip-curation.test.ts",
|
|
95
96
|
"test:qa": "node --import tsx --test test/qa-check.test.ts",
|
|
97
|
+
"test:studio-brand": "node --import tsx --test test/studio-brand.test.ts",
|
|
96
98
|
"check:skills": "node scripts/build-director-skill-rollup.mjs --check && node scripts/check-skill-routes.mjs",
|
|
97
99
|
"benchmark:editor-chat": "node --import tsx scripts/benchmark-editor-chat-harness.mjs",
|
|
98
100
|
"cdk:deploy:prod-serverless": "npm run build && dotenv -e .env.production -- npx aws-cdk deploy --app 'node dist/infra/cdk/bin/vidfarm-prod.js'",
|