@officexapp/vidfarm-devcli 0.21.11 → 0.21.14
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/.agents/skills/hyperframes-core/SKILL.md +2 -0
- package/.agents/skills/hyperframes-creative/SKILL.md +1 -0
- package/.agents/skills/hyperframes-creative/references/beat-direction.md +17 -0
- package/.agents/skills/vidfarm-director/SKILL.md +4 -0
- package/.agents/skills/vidfarm-director/recipes/local-edit-render-approve.md +1 -1
- package/.agents/skills/vidfarm-director/references/automation-and-local-dev.md +23 -6
- package/.agents/skills/vidfarm-director/references/core-workflows.md +1 -1
- package/.agents/skills/vidfarm-director/references/editor-workflows.md +15 -2
- package/.agents/skills/vidfarm-director/references/primitives.md +1 -1
- package/.agents/skills/vidfarm-director/references/rest-api.md +1 -1
- package/.agents/skills/vidfarm-media/SKILL.md +16 -6
- package/README.md +2 -2
- package/SKILL.director.md +45 -11
- package/demo/dist/app.js +247 -226
- package/dist/src/cli.js +198 -30
- package/dist/src/devcli/composition-edit.js +99 -23
- package/dist/src/devcli/cost-mode.js +13 -4
- package/dist/src/devcli/doctor.js +65 -9
- package/dist/src/devcli/local-frontend-server.js +342 -50
- package/dist/src/devcli/port-utils.js +43 -0
- package/dist/src/devcli/process-scan.js +173 -0
- package/package.json +3 -1
- package/public/serve-shells/editor.html +75 -13
- package/public/serve-shells/library-files.html +75 -13
- package/public/serve-shells/library-raws.html +75 -13
- package/public/serve-shells/tools-clipper.html +75 -13
- package/public/serve-shells/tools-image.html +75 -13
- package/public/serve-shells/tools-video.html +75 -13
|
@@ -87,8 +87,12 @@ export function resolveCostMode(values) {
|
|
|
87
87
|
}
|
|
88
88
|
export const COST_MODE_BLURB = {
|
|
89
89
|
minimize: "Minimize costs — stay on FREE local compute wherever possible (local render, " +
|
|
90
|
-
"local TTS/STT, local greenscreen/matting, reused clips + HTML motion).
|
|
91
|
-
|
|
90
|
+
"local TTS/STT, local greenscreen/matting, reused clips + HTML motion). For assets, " +
|
|
91
|
+
'reach for the free stock catalog first — vidfarm media search "<meaning>" --type ' +
|
|
92
|
+
"bgm|sfx|image|vector|icon|video. Check the KEYLESS sources first: Openverse (CC/CC0 " +
|
|
93
|
+
"music, SFX, images) and iconify (icons) need no account at all. A free Pixabay key adds " +
|
|
94
|
+
"photos/vectors/stock-video and may already be saved (check vidfarm provider-keys). " +
|
|
95
|
+
"Billed cloud/AI generation is refused unless you re-confirm it (--yes).",
|
|
92
96
|
hybrid: "Hybrid (recommended) — free where it's free, spend AI credits only where they " +
|
|
93
97
|
"clearly win (a hero shot, a voice you can't fake locally). Billed ops run but " +
|
|
94
98
|
"each prints its cost so nothing is a surprise.",
|
|
@@ -104,9 +108,14 @@ export function costModeSummaryLine(resolved) {
|
|
|
104
108
|
export function costModeExplainer() {
|
|
105
109
|
return [
|
|
106
110
|
"How much do you want Vidfarm to spend on AI credits?",
|
|
107
|
-
" • minimize — cheapest: free local compute, no surprise AI spend.",
|
|
111
|
+
" • minimize — cheapest: free local compute + free stock media, no surprise AI spend.",
|
|
108
112
|
" • hybrid — recommended: free where free, pay AI only where it clearly wins.",
|
|
109
|
-
" • pure-ai — best quality: use AI image/video/voice/music freely."
|
|
113
|
+
" • pure-ai — best quality: use AI image/video/voice/music freely.",
|
|
114
|
+
"Tip: before paying to generate music/SFX/images/video, try the free stock catalog —",
|
|
115
|
+
' vidfarm media search "<meaning>" --type bgm|sfx|image|vector|icon|video.',
|
|
116
|
+
" Check the keyless sources first — Openverse (CC/CC0 music, SFX, images) and iconify (icons)",
|
|
117
|
+
" need no account. A free Pixabay key adds photos/vectors/stock-video (it may already be saved —",
|
|
118
|
+
" check `vidfarm provider-keys` or vidfarm.cc/settings/developer; add via `vidfarm add-provider-key pixabay <key>`)."
|
|
110
119
|
].join("\n");
|
|
111
120
|
}
|
|
112
121
|
export class CostModeBlockedError extends Error {
|
|
@@ -16,6 +16,8 @@ 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
18
|
import { resolveSkillsRoot } from "./skills.js";
|
|
19
|
+
import { readStoredAuth } from "./auth-store.js";
|
|
20
|
+
import { scanLocalServers, reapProcesses } from "./process-scan.js";
|
|
19
21
|
const GREEN = "\x1b[32m";
|
|
20
22
|
const RED = "\x1b[31m";
|
|
21
23
|
const YELLOW = "\x1b[33m";
|
|
@@ -108,10 +110,14 @@ export async function runDoctorCommand(argv) {
|
|
|
108
110
|
options: {
|
|
109
111
|
host: { type: "string", default: "https://vidfarm.cc" },
|
|
110
112
|
"api-key": { type: "string" },
|
|
111
|
-
json: { type: "boolean", default: false }
|
|
113
|
+
json: { type: "boolean", default: false },
|
|
114
|
+
// Reap orphaned local serve/preview processes (running from a deleted
|
|
115
|
+
// package path) so their squatted ports are reclaimed.
|
|
116
|
+
"kill-orphans": { type: "boolean", default: false }
|
|
112
117
|
}
|
|
113
118
|
});
|
|
114
119
|
const json = Boolean(parsed.values.json);
|
|
120
|
+
const killOrphans = Boolean(parsed.values["kill-orphans"]);
|
|
115
121
|
const checks = [];
|
|
116
122
|
const add = (name, level, detail) => checks.push({ name, level, detail });
|
|
117
123
|
// 1. Node version.
|
|
@@ -129,14 +135,21 @@ export async function runDoctorCommand(argv) {
|
|
|
129
135
|
// 4. Chrome for the in-process render (stills / serve local render).
|
|
130
136
|
const chrome = detectChromeForRender();
|
|
131
137
|
add("chrome", chrome.found ? "ok" : "warn", chrome.found ? chrome.detail : `${chrome.detail} — local render/stills will try to download one on first run`);
|
|
132
|
-
// 5. Vidfarm cloud auth
|
|
133
|
-
|
|
138
|
+
// 5. Vidfarm cloud auth — --api-key / env, else the persisted `vidfarm login`
|
|
139
|
+
// (auth-store), which is how most users authenticate. Without the store
|
|
140
|
+
// lookup a logged-in user got a false "VIDFARM_API_KEY not set" warning.
|
|
141
|
+
const storedAuth = readStoredAuth();
|
|
142
|
+
const explicitKey = parsed.values["api-key"] ?? process.env.VIDFARM_API_KEY;
|
|
143
|
+
const apiKey = explicitKey ?? storedAuth?.apiKey;
|
|
134
144
|
if (apiKey) {
|
|
135
|
-
|
|
136
|
-
|
|
145
|
+
// A stored login was minted for its own host; only an explicit key uses --host.
|
|
146
|
+
const host = explicitKey ? String(parsed.values.host).replace(/\/+$/, "") : (storedAuth?.host ?? String(parsed.values.host)).replace(/\/+$/, "");
|
|
147
|
+
const who = await fetchWhoami(host, apiKey);
|
|
148
|
+
const source = explicitKey ? "" : " (persisted `vidfarm login`)";
|
|
149
|
+
add("vidfarm auth", who.ok ? "ok" : "warn", who.ok ? `${who.detail}${source}` : `${who.detail} — serve will fall back to local browse mode`);
|
|
137
150
|
}
|
|
138
151
|
else {
|
|
139
|
-
add("vidfarm auth", "warn", "
|
|
152
|
+
add("vidfarm auth", "warn", "no login found — run `vidfarm login` (or set VIDFARM_API_KEY); serve will fall back to local browse mode, cloud catalog/bulk routes need it");
|
|
140
153
|
}
|
|
141
154
|
// 6. Provider keys in env (BYOK local-first engines).
|
|
142
155
|
const presentKeys = PROVIDER_KEY_ENV_VARS.filter((name) => process.env[name]?.trim());
|
|
@@ -157,9 +170,52 @@ export async function runDoctorCommand(argv) {
|
|
|
157
170
|
add("env cloud ARNs/URLs", poisoned.length > 0 ? "warn" : "ok", poisoned.length > 0
|
|
158
171
|
? `${poisoned.join(", ")} set — outside \`vidfarm serve\` these route local work to cloud infra (serve blanks them itself)`
|
|
159
172
|
: "no stray cloud ARNs/URLs in env");
|
|
160
|
-
// 9.
|
|
161
|
-
|
|
162
|
-
|
|
173
|
+
// 9. Local serve/preview processes — concurrency map + orphan reaping.
|
|
174
|
+
// Customers run several local video jobs at once; a renamed/pruned devcli can
|
|
175
|
+
// also leave an orphaned server squatting a port forever (the "Waiting for
|
|
176
|
+
// preview server…" hang). List them, flag orphans, and optionally reap.
|
|
177
|
+
const scan = scanLocalServers();
|
|
178
|
+
let reapedSummary = "";
|
|
179
|
+
if (killOrphans && scan.supported) {
|
|
180
|
+
const orphans = scan.servers.filter((s) => s.orphaned && !s.isSelf);
|
|
181
|
+
if (orphans.length > 0) {
|
|
182
|
+
const results = await reapProcesses(orphans.map((s) => s.pid));
|
|
183
|
+
const killedPids = new Set(results.filter((r) => r.killed).map((r) => r.pid));
|
|
184
|
+
const survivors = results.filter((r) => !r.killed);
|
|
185
|
+
reapedSummary = `reaped ${killedPids.size}/${orphans.length} orphaned server(s): ${orphans.map((s) => `pid ${s.pid}${s.port ? `:${s.port}` : ""}`).join(", ")}`;
|
|
186
|
+
if (survivors.length > 0) {
|
|
187
|
+
reapedSummary += ` (could not kill: ${survivors.map((r) => `pid ${r.pid}${r.error ? ` — ${r.error}` : ""}`).join(", ")})`;
|
|
188
|
+
}
|
|
189
|
+
// Drop the confirmed-dead rows so the report reflects the fix.
|
|
190
|
+
scan.servers = scan.servers.filter((s) => !killedPids.has(s.pid));
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
reapedSummary = "no orphaned servers to reap";
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
const describeServer = (s) => `${s.kind}${s.port ? ` :${s.port}` : ""} pid ${s.pid}${s.isSelf ? " (self)" : ""}${s.orphaned ? " ⚠ORPHAN (binary deleted)" : ""}`;
|
|
197
|
+
if (!scan.supported) {
|
|
198
|
+
add("local servers", "ok", scan.note ?? "scan unavailable");
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
const others = scan.servers.filter((s) => !s.isSelf);
|
|
202
|
+
const orphanCount = others.filter((s) => s.orphaned).length;
|
|
203
|
+
// 3000 is only serve's DEFAULT start port (serve auto-advances past a busy
|
|
204
|
+
// one) — a busy 3000 is informational, and we can't be sure whose it is.
|
|
205
|
+
const portBusy = await isPortInUse(3000);
|
|
206
|
+
const port3000Note = portBusy && !others.some((s) => s.port === 3000)
|
|
207
|
+
? "; default port 3000 is in use by another process (serve auto-advances to the next free port)"
|
|
208
|
+
: "";
|
|
209
|
+
const detail = others.length === 0
|
|
210
|
+
? `none running${port3000Note}`
|
|
211
|
+
: `${others.length} running — ${others.map(describeServer).join("; ")}${port3000Note}`;
|
|
212
|
+
const suffix = orphanCount > 0 && !killOrphans
|
|
213
|
+
? ` — run \`vidfarm doctor --kill-orphans\` to reclaim their ports`
|
|
214
|
+
: reapedSummary
|
|
215
|
+
? ` — ${reapedSummary}`
|
|
216
|
+
: "";
|
|
217
|
+
add("local servers", orphanCount > 0 ? "warn" : "ok", detail + suffix);
|
|
218
|
+
}
|
|
163
219
|
// 10. HeyGen credential file — vidfarm never uses it.
|
|
164
220
|
const heygenCredentials = path.join(homedir(), ".heygen", "credentials");
|
|
165
221
|
if (existsSync(heygenCredentials) || existsSync(path.join(homedir(), ".heygen", "credentials.json"))) {
|