@vibeframe/cli 0.106.7 → 0.106.8
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/dist/commands/_shared/scene-render.d.ts +18 -0
- package/dist/index.js +126 -19
- package/dist/tools/adapters/mcp.js +56 -4
- package/dist/tools/manifest/index.js +110 -15
- package/dist/tools/manifest/scene.d.ts +6 -0
- package/package.json +3 -3
|
@@ -17,6 +17,7 @@ import { type SceneAspect } from "./scene-project.js";
|
|
|
17
17
|
export type RenderFps = 24 | 30 | 60;
|
|
18
18
|
export type RenderQuality = "draft" | "standard" | "high";
|
|
19
19
|
export type RenderFormat = "mp4" | "webm" | "mov";
|
|
20
|
+
export type RenderOpenAction = "open" | "reveal";
|
|
20
21
|
export interface SceneRenderOptions {
|
|
21
22
|
/** Project directory (defaults to cwd). */
|
|
22
23
|
projectDir?: string;
|
|
@@ -33,6 +34,10 @@ export interface SceneRenderOptions {
|
|
|
33
34
|
/** Hyperframes capture worker count. Default 1 (the existing backend's
|
|
34
35
|
* default — auto-worker mode times out on small comps). */
|
|
35
36
|
workers?: number;
|
|
37
|
+
/** Open the rendered media in the OS default app after a successful render. */
|
|
38
|
+
openAfterRender?: boolean;
|
|
39
|
+
/** Reveal the rendered media in Finder/file manager after a successful render. */
|
|
40
|
+
revealInFinder?: boolean;
|
|
36
41
|
signal?: AbortSignal;
|
|
37
42
|
onProgress?: (pct: number, stage: string) => void;
|
|
38
43
|
}
|
|
@@ -42,6 +47,13 @@ export interface SceneRenderResult {
|
|
|
42
47
|
beat?: string | null;
|
|
43
48
|
root?: string;
|
|
44
49
|
outputPath?: string;
|
|
50
|
+
absoluteOutputPath?: string;
|
|
51
|
+
openCommand?: string;
|
|
52
|
+
revealCommand?: string;
|
|
53
|
+
opened?: boolean;
|
|
54
|
+
revealed?: boolean;
|
|
55
|
+
openError?: string;
|
|
56
|
+
revealError?: string;
|
|
45
57
|
durationMs?: number;
|
|
46
58
|
framesRendered?: number;
|
|
47
59
|
totalFrames?: number;
|
|
@@ -59,6 +71,11 @@ export interface SceneRenderResult {
|
|
|
59
71
|
error?: string;
|
|
60
72
|
retryWith?: string[];
|
|
61
73
|
}
|
|
74
|
+
export interface MediaOpenCommand {
|
|
75
|
+
command: string;
|
|
76
|
+
args: string[];
|
|
77
|
+
display: string;
|
|
78
|
+
}
|
|
62
79
|
/** Map a quality preset to an x264 CRF (lower = higher quality). */
|
|
63
80
|
export declare function qualityToCrf(quality?: RenderQuality): number;
|
|
64
81
|
/**
|
|
@@ -85,6 +102,7 @@ export declare function buildRenderConfig(opts: {
|
|
|
85
102
|
workers?: number;
|
|
86
103
|
entryFile?: string;
|
|
87
104
|
}): RenderConfig;
|
|
105
|
+
export declare function buildMediaOpenCommand(action: RenderOpenAction, filePath: string, platform?: NodeJS.Platform): MediaOpenCommand;
|
|
88
106
|
/**
|
|
89
107
|
* Render a scene project. Mirrors the contract of the existing Hyperframes
|
|
90
108
|
* backend (preflight → execute → structured result), but skips the
|
package/dist/index.js
CHANGED
|
@@ -31472,11 +31472,11 @@ registerRoot(Root);
|
|
|
31472
31472
|
return dir;
|
|
31473
31473
|
}
|
|
31474
31474
|
async function this_npmInstall(dir) {
|
|
31475
|
-
const { execFile:
|
|
31476
|
-
const { promisify:
|
|
31477
|
-
const
|
|
31475
|
+
const { execFile: execFile3 } = await import("node:child_process");
|
|
31476
|
+
const { promisify: promisify3 } = await import("node:util");
|
|
31477
|
+
const execFileAsync3 = promisify3(execFile3);
|
|
31478
31478
|
try {
|
|
31479
|
-
await
|
|
31479
|
+
await execFileAsync3("npm", ["install", "--prefer-offline", "--no-audit", "--no-fund"], {
|
|
31480
31480
|
cwd: dir,
|
|
31481
31481
|
timeout: 18e4
|
|
31482
31482
|
});
|
|
@@ -31500,13 +31500,13 @@ async function renderMotion(options) {
|
|
|
31500
31500
|
);
|
|
31501
31501
|
try {
|
|
31502
31502
|
const entryPoint = join9(dir, "Root.tsx");
|
|
31503
|
-
const { execFile:
|
|
31504
|
-
const { promisify:
|
|
31505
|
-
const
|
|
31503
|
+
const { execFile: execFile3 } = await import("node:child_process");
|
|
31504
|
+
const { promisify: promisify3 } = await import("node:util");
|
|
31505
|
+
const execFileAsync3 = promisify3(execFile3);
|
|
31506
31506
|
if (transparent) {
|
|
31507
31507
|
const webmOut = options.outputPath.replace(/\.\w+$/, ".webm");
|
|
31508
31508
|
try {
|
|
31509
|
-
await
|
|
31509
|
+
await execFileAsync3("npx", [
|
|
31510
31510
|
"remotion",
|
|
31511
31511
|
"render",
|
|
31512
31512
|
entryPoint,
|
|
@@ -31523,7 +31523,7 @@ async function renderMotion(options) {
|
|
|
31523
31523
|
} catch {
|
|
31524
31524
|
}
|
|
31525
31525
|
try {
|
|
31526
|
-
await
|
|
31526
|
+
await execFileAsync3("npx", [
|
|
31527
31527
|
"remotion",
|
|
31528
31528
|
"render",
|
|
31529
31529
|
entryPoint,
|
|
@@ -31543,7 +31543,7 @@ async function renderMotion(options) {
|
|
|
31543
31543
|
}
|
|
31544
31544
|
}
|
|
31545
31545
|
const mp4Out = options.outputPath.replace(/\.\w+$/, ".mp4");
|
|
31546
|
-
await
|
|
31546
|
+
await execFileAsync3("npx", [
|
|
31547
31547
|
"remotion",
|
|
31548
31548
|
"render",
|
|
31549
31549
|
entryPoint,
|
|
@@ -59857,15 +59857,18 @@ var init_scene_audio_mux = __esm({
|
|
|
59857
59857
|
// src/commands/_shared/scene-render.ts
|
|
59858
59858
|
var scene_render_exports = {};
|
|
59859
59859
|
__export(scene_render_exports, {
|
|
59860
|
+
buildMediaOpenCommand: () => buildMediaOpenCommand,
|
|
59860
59861
|
buildRenderConfig: () => buildRenderConfig,
|
|
59861
59862
|
defaultOutputPath: () => defaultOutputPath,
|
|
59862
59863
|
executeSceneRender: () => executeSceneRender,
|
|
59863
59864
|
prepareBeatRenderRoot: () => prepareBeatRenderRoot,
|
|
59864
59865
|
qualityToCrf: () => qualityToCrf2
|
|
59865
59866
|
});
|
|
59867
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
59866
59868
|
import { existsSync as existsSync46 } from "node:fs";
|
|
59867
59869
|
import { mkdir as mkdir24, readFile as readFile43, stat as stat8, writeFile as writeFile48 } from "node:fs/promises";
|
|
59868
59870
|
import { resolve as resolve62, relative as relative11, dirname as dirname22, basename as basename21, join as join22, isAbsolute as isAbsolute6 } from "node:path";
|
|
59871
|
+
import { promisify as promisify2 } from "node:util";
|
|
59869
59872
|
import {
|
|
59870
59873
|
createRenderJob,
|
|
59871
59874
|
executeRenderJob
|
|
@@ -59892,6 +59895,38 @@ function buildRenderConfig(opts) {
|
|
|
59892
59895
|
workers: opts.workers ?? 1
|
|
59893
59896
|
};
|
|
59894
59897
|
}
|
|
59898
|
+
function buildMediaOpenCommand(action, filePath, platform3 = process.platform) {
|
|
59899
|
+
if (platform3 === "darwin") {
|
|
59900
|
+
const args = action === "reveal" ? ["-R", filePath] : [filePath];
|
|
59901
|
+
return {
|
|
59902
|
+
command: "open",
|
|
59903
|
+
args,
|
|
59904
|
+
display: ["open", ...args].map(quoteCliArg).join(" ")
|
|
59905
|
+
};
|
|
59906
|
+
}
|
|
59907
|
+
if (platform3 === "win32") {
|
|
59908
|
+
if (action === "reveal") {
|
|
59909
|
+
const args2 = [`/select,${filePath}`];
|
|
59910
|
+
return {
|
|
59911
|
+
command: "explorer",
|
|
59912
|
+
args: args2,
|
|
59913
|
+
display: ["explorer", ...args2].map(quoteCliArg).join(" ")
|
|
59914
|
+
};
|
|
59915
|
+
}
|
|
59916
|
+
const args = ["/c", "start", "", filePath];
|
|
59917
|
+
return {
|
|
59918
|
+
command: "cmd",
|
|
59919
|
+
args,
|
|
59920
|
+
display: ["cmd", ...args].map(quoteCliArg).join(" ")
|
|
59921
|
+
};
|
|
59922
|
+
}
|
|
59923
|
+
const target = action === "reveal" ? dirname22(filePath) : filePath;
|
|
59924
|
+
return {
|
|
59925
|
+
command: "xdg-open",
|
|
59926
|
+
args: [target],
|
|
59927
|
+
display: ["xdg-open", target].map(quoteCliArg).join(" ")
|
|
59928
|
+
};
|
|
59929
|
+
}
|
|
59895
59930
|
async function executeSceneRender(opts = {}) {
|
|
59896
59931
|
const projectDir = resolve62(opts.projectDir ?? ".");
|
|
59897
59932
|
const projectConfig = await readProjectConfig(projectDir);
|
|
@@ -60015,6 +60050,9 @@ async function executeSceneRender(opts = {}) {
|
|
|
60015
60050
|
beat: opts.beatId ?? null,
|
|
60016
60051
|
root,
|
|
60017
60052
|
outputPath: relative11(process.cwd(), outputPath) || outputPath,
|
|
60053
|
+
absoluteOutputPath: outputPath,
|
|
60054
|
+
openCommand: buildMediaOpenCommand("open", outputPath).display,
|
|
60055
|
+
revealCommand: buildMediaOpenCommand("reveal", outputPath).display,
|
|
60018
60056
|
durationMs: Date.now() - start,
|
|
60019
60057
|
framesRendered: job.framesRendered,
|
|
60020
60058
|
totalFrames: job.totalFrames,
|
|
@@ -60025,12 +60063,38 @@ async function executeSceneRender(opts = {}) {
|
|
|
60025
60063
|
audioMuxApplied,
|
|
60026
60064
|
audioMuxWarning
|
|
60027
60065
|
};
|
|
60066
|
+
if (opts.revealInFinder) {
|
|
60067
|
+
try {
|
|
60068
|
+
await runMediaOpenAction("reveal", outputPath);
|
|
60069
|
+
result.revealed = true;
|
|
60070
|
+
} catch (err) {
|
|
60071
|
+
result.revealed = false;
|
|
60072
|
+
result.revealError = err instanceof Error ? err.message : String(err);
|
|
60073
|
+
}
|
|
60074
|
+
}
|
|
60075
|
+
if (opts.openAfterRender) {
|
|
60076
|
+
try {
|
|
60077
|
+
await runMediaOpenAction("open", outputPath);
|
|
60078
|
+
result.opened = true;
|
|
60079
|
+
} catch (err) {
|
|
60080
|
+
result.opened = false;
|
|
60081
|
+
result.openError = err instanceof Error ? err.message : String(err);
|
|
60082
|
+
}
|
|
60083
|
+
}
|
|
60028
60084
|
result.reportPath = await writeRenderReport(projectDir, {
|
|
60029
60085
|
...result,
|
|
60030
60086
|
outputPath
|
|
60031
60087
|
});
|
|
60032
60088
|
return result;
|
|
60033
60089
|
}
|
|
60090
|
+
async function runMediaOpenAction(action, filePath) {
|
|
60091
|
+
const cmd = buildMediaOpenCommand(action, filePath);
|
|
60092
|
+
await execFileAsync2(cmd.command, cmd.args);
|
|
60093
|
+
}
|
|
60094
|
+
function quoteCliArg(value) {
|
|
60095
|
+
if (/^[A-Za-z0-9_/@%+=:,.-]+$/.test(value)) return value;
|
|
60096
|
+
return `"${value.replace(/(["\\$`])/g, "\\$1")}"`;
|
|
60097
|
+
}
|
|
60034
60098
|
async function safeStat(p) {
|
|
60035
60099
|
try {
|
|
60036
60100
|
return await stat8(p);
|
|
@@ -60201,6 +60265,13 @@ async function writeRenderReport(projectDir, result) {
|
|
|
60201
60265
|
beat: result.beat ?? null,
|
|
60202
60266
|
root: result.root,
|
|
60203
60267
|
outputPath: result.outputPath,
|
|
60268
|
+
absoluteOutputPath: result.absoluteOutputPath,
|
|
60269
|
+
openCommand: result.openCommand,
|
|
60270
|
+
revealCommand: result.revealCommand,
|
|
60271
|
+
opened: result.opened,
|
|
60272
|
+
revealed: result.revealed,
|
|
60273
|
+
openError: result.openError,
|
|
60274
|
+
revealError: result.revealError,
|
|
60204
60275
|
fps: result.fps,
|
|
60205
60276
|
quality: result.quality,
|
|
60206
60277
|
format: result.format,
|
|
@@ -60245,6 +60316,7 @@ function escapeAttr(value) {
|
|
|
60245
60316
|
function unique4(items) {
|
|
60246
60317
|
return [...new Set(items.filter((item) => Boolean(item)))];
|
|
60247
60318
|
}
|
|
60319
|
+
var execFileAsync2;
|
|
60248
60320
|
var init_scene_render = __esm({
|
|
60249
60321
|
"src/commands/_shared/scene-render.ts"() {
|
|
60250
60322
|
"use strict";
|
|
@@ -60254,6 +60326,7 @@ var init_scene_render = __esm({
|
|
|
60254
60326
|
init_scene_audio_mux();
|
|
60255
60327
|
init_project_config();
|
|
60256
60328
|
init_scene_project();
|
|
60329
|
+
execFileAsync2 = promisify2(execFile2);
|
|
60257
60330
|
}
|
|
60258
60331
|
});
|
|
60259
60332
|
|
|
@@ -67341,7 +67414,9 @@ var init_scene2 = __esm({
|
|
|
67341
67414
|
fps: external_exports.number().optional().describe("Frames per second. Must be 24, 30, or 60. Default 30."),
|
|
67342
67415
|
quality: external_exports.enum(["draft", "standard", "high"]).optional().describe("Quality preset. Default 'standard'."),
|
|
67343
67416
|
format: external_exports.enum(["mp4", "webm", "mov"]).optional().describe("Container format. Default 'mp4'."),
|
|
67344
|
-
workers: external_exports.number().optional().describe("Capture worker count (1-16). Default 1.")
|
|
67417
|
+
workers: external_exports.number().optional().describe("Capture worker count (1-16). Default 1."),
|
|
67418
|
+
openAfterRender: external_exports.boolean().optional().describe("Open the rendered video in the OS default app after render. Default false."),
|
|
67419
|
+
revealInFinder: external_exports.boolean().optional().describe("Reveal the rendered video in Finder/file manager after render. Default false.")
|
|
67345
67420
|
});
|
|
67346
67421
|
sceneRenderTool = defineTool({
|
|
67347
67422
|
name: "render",
|
|
@@ -67359,7 +67434,9 @@ var init_scene2 = __esm({
|
|
|
67359
67434
|
fps: args.fps,
|
|
67360
67435
|
quality: args.quality,
|
|
67361
67436
|
format: args.format,
|
|
67362
|
-
workers: args.workers
|
|
67437
|
+
workers: args.workers,
|
|
67438
|
+
openAfterRender: args.openAfterRender,
|
|
67439
|
+
revealInFinder: args.revealInFinder
|
|
67363
67440
|
});
|
|
67364
67441
|
if (!result.success) {
|
|
67365
67442
|
return { success: false, error: result.error ?? "render failed" };
|
|
@@ -67368,6 +67445,13 @@ var init_scene2 = __esm({
|
|
|
67368
67445
|
success: true,
|
|
67369
67446
|
data: {
|
|
67370
67447
|
outputPath: result.outputPath,
|
|
67448
|
+
absoluteOutputPath: result.absoluteOutputPath,
|
|
67449
|
+
openCommand: result.openCommand,
|
|
67450
|
+
revealCommand: result.revealCommand,
|
|
67451
|
+
opened: result.opened,
|
|
67452
|
+
revealed: result.revealed,
|
|
67453
|
+
openError: result.openError,
|
|
67454
|
+
revealError: result.revealError,
|
|
67371
67455
|
beat: result.beat,
|
|
67372
67456
|
root: result.root,
|
|
67373
67457
|
reportPath: result.reportPath,
|
|
@@ -67376,13 +67460,24 @@ var init_scene2 = __esm({
|
|
|
67376
67460
|
totalFrames: result.totalFrames,
|
|
67377
67461
|
fps: result.fps,
|
|
67378
67462
|
quality: result.quality,
|
|
67379
|
-
format: result.format
|
|
67463
|
+
format: result.format,
|
|
67464
|
+
audioCount: result.audioCount,
|
|
67465
|
+
audioMuxApplied: result.audioMuxApplied,
|
|
67466
|
+
audioMuxWarning: result.audioMuxWarning
|
|
67380
67467
|
},
|
|
67381
67468
|
humanLines: [
|
|
67382
|
-
`\u2705 Render complete: ${result.outputPath}`,
|
|
67469
|
+
`\u2705 Render complete: ${result.absoluteOutputPath ?? result.outputPath}`,
|
|
67383
67470
|
` duration: ${((result.durationMs ?? 0) / 1e3).toFixed(1)}s`,
|
|
67384
67471
|
` frames: ${result.framesRendered ?? "?"}${result.totalFrames ? ` / ${result.totalFrames}` : ""}`,
|
|
67385
|
-
` config: ${result.fps}fps \xB7 ${result.quality} \xB7 ${result.format}
|
|
67472
|
+
` config: ${result.fps}fps \xB7 ${result.quality} \xB7 ${result.format}`,
|
|
67473
|
+
` audio: ${result.audioCount && result.audioCount > 0 ? `${result.audioCount} track${result.audioCount === 1 ? "" : "s"} muxed` : "silent"}`,
|
|
67474
|
+
...result.openCommand ? [` open: ${result.openCommand}`] : [],
|
|
67475
|
+
...result.revealCommand ? [` reveal: ${result.revealCommand}`] : [],
|
|
67476
|
+
` inspect: vibe inspect render ${projectDir} --cheap --json`,
|
|
67477
|
+
...result.opened ? [` opened: yes`] : [],
|
|
67478
|
+
...result.revealed ? [` revealed: yes`] : [],
|
|
67479
|
+
...result.openError ? [` open warning: ${result.openError}`] : [],
|
|
67480
|
+
...result.revealError ? [` reveal warning: ${result.revealError}`] : []
|
|
67386
67481
|
]
|
|
67387
67482
|
};
|
|
67388
67483
|
}
|
|
@@ -72028,7 +72123,7 @@ init_source();
|
|
|
72028
72123
|
// package.json
|
|
72029
72124
|
var package_default = {
|
|
72030
72125
|
name: "@vibeframe/cli",
|
|
72031
|
-
version: "0.106.
|
|
72126
|
+
version: "0.106.8",
|
|
72032
72127
|
description: "VibeFrame CLI - agentic video workflow runtime",
|
|
72033
72128
|
private: false,
|
|
72034
72129
|
license: "MIT",
|
|
@@ -82731,7 +82826,7 @@ import { resolve as resolve65 } from "node:path";
|
|
|
82731
82826
|
var VALID_FPS = [24, 30, 60];
|
|
82732
82827
|
var VALID_QUALITIES = ["draft", "standard", "high"];
|
|
82733
82828
|
var VALID_FORMATS = ["mp4", "webm", "mov"];
|
|
82734
|
-
var renderCommand = new Command("render").description("Render a VibeFrame video project to MP4/WebM/MOV").argument("[project-dir]", "Video project directory", ".").option("-o, --out <path>", "Output file (default: renders/<name>-<timestamp>.<format>)").option("--root <file>", "Root composition file", "index.html").option("--beat <id>", "Render only one storyboard beat using a temporary root").option("--fps <n>", `Frames per second: ${VALID_FPS.join("|")}`, "30").option("--quality <q>", `Quality preset: ${VALID_QUALITIES.join("|")}`, "standard").option("--format <f>", `Output container: ${VALID_FORMATS.join("|")}`, "mp4").option("--workers <n>", "Capture workers (1-16, default 1)", "1").option("--dry-run", "Preview parameters without rendering").addHelpText("after", `
|
|
82829
|
+
var renderCommand = new Command("render").description("Render a VibeFrame video project to MP4/WebM/MOV").argument("[project-dir]", "Video project directory", ".").option("-o, --out <path>", "Output file (default: renders/<name>-<timestamp>.<format>)").option("--root <file>", "Root composition file", "index.html").option("--beat <id>", "Render only one storyboard beat using a temporary root").option("--fps <n>", `Frames per second: ${VALID_FPS.join("|")}`, "30").option("--quality <q>", `Quality preset: ${VALID_QUALITIES.join("|")}`, "standard").option("--format <f>", `Output container: ${VALID_FORMATS.join("|")}`, "mp4").option("--workers <n>", "Capture workers (1-16, default 1)", "1").option("--open", "Open the rendered video in the OS default app after render").option("--reveal", "Reveal the rendered video in Finder/file manager after render").option("--dry-run", "Preview parameters without rendering").addHelpText("after", `
|
|
82735
82830
|
Examples:
|
|
82736
82831
|
$ vibe render my-video
|
|
82737
82832
|
$ vibe render my-video -o renders/final.mp4 --quality high
|
|
@@ -82751,7 +82846,9 @@ Alias note: this is the project-level entrypoint for \`vibe scene render\`.`).ac
|
|
|
82751
82846
|
fps,
|
|
82752
82847
|
quality,
|
|
82753
82848
|
format,
|
|
82754
|
-
workers
|
|
82849
|
+
workers,
|
|
82850
|
+
openAfterRender: Boolean(options.open),
|
|
82851
|
+
revealInFinder: Boolean(options.reveal)
|
|
82755
82852
|
};
|
|
82756
82853
|
if (options.dryRun) {
|
|
82757
82854
|
if (!isJsonMode() && !isQuietMode()) {
|
|
@@ -82776,6 +82873,8 @@ Alias note: this is the project-level entrypoint for \`vibe scene render\`.`).ac
|
|
|
82776
82873
|
quality,
|
|
82777
82874
|
format,
|
|
82778
82875
|
workers,
|
|
82876
|
+
openAfterRender: Boolean(options.open),
|
|
82877
|
+
revealInFinder: Boolean(options.reveal),
|
|
82779
82878
|
onProgress: (pct, stage) => {
|
|
82780
82879
|
if (spinner2) spinner2.text = `Rendering [${Math.round(pct * 100)}%] ${stage}`;
|
|
82781
82880
|
}
|
|
@@ -82806,6 +82905,8 @@ function printRenderDryRun(projectDirArg, params) {
|
|
|
82806
82905
|
console.log(` Format: ${source_default.bold(params.format)}`);
|
|
82807
82906
|
console.log(` Quality/FPS: ${source_default.bold(`${params.quality} / ${params.fps}`)}`);
|
|
82808
82907
|
console.log(` Workers: ${source_default.bold(String(params.workers))}`);
|
|
82908
|
+
if (params.openAfterRender) console.log(` Open: ${source_default.bold("yes")}`);
|
|
82909
|
+
if (params.revealInFinder) console.log(` Reveal: ${source_default.bold("yes")}`);
|
|
82809
82910
|
console.log();
|
|
82810
82911
|
console.log(source_default.dim("No browser capture, FFmpeg mux, or video files were created."));
|
|
82811
82912
|
}
|
|
@@ -82814,7 +82915,7 @@ function printRenderResult(spinner2, result) {
|
|
|
82814
82915
|
console.log();
|
|
82815
82916
|
console.log(source_default.bold.cyan("Output"));
|
|
82816
82917
|
console.log(source_default.dim("-".repeat(60)));
|
|
82817
|
-
console.log(` File: ${source_default.bold(result.outputPath)}`);
|
|
82918
|
+
console.log(` File: ${source_default.bold(result.absoluteOutputPath ?? result.outputPath)}`);
|
|
82818
82919
|
if (result.beat) console.log(` Beat: ${result.beat}`);
|
|
82819
82920
|
if (result.root) console.log(` Root: ${result.root}`);
|
|
82820
82921
|
console.log(` Format: ${result.format ?? "mp4"}`);
|
|
@@ -82827,6 +82928,12 @@ function printRenderResult(spinner2, result) {
|
|
|
82827
82928
|
console.log(` Audio: ${audio}`);
|
|
82828
82929
|
}
|
|
82829
82930
|
if (result.audioMuxWarning) console.log(source_default.yellow(` Warning: ${result.audioMuxWarning}`));
|
|
82931
|
+
if (result.openCommand) console.log(` Open: ${source_default.dim(result.openCommand)}`);
|
|
82932
|
+
if (result.revealCommand) console.log(` Reveal: ${source_default.dim(result.revealCommand)}`);
|
|
82933
|
+
if (result.opened) console.log(source_default.green(" Opened: yes"));
|
|
82934
|
+
if (result.revealed) console.log(source_default.green(" Revealed: yes"));
|
|
82935
|
+
if (result.openError) console.log(source_default.yellow(` Open warn: ${result.openError}`));
|
|
82936
|
+
if (result.revealError) console.log(source_default.yellow(` Reveal warn: ${result.revealError}`));
|
|
82830
82937
|
}
|
|
82831
82938
|
function parseFps(value) {
|
|
82832
82939
|
const n = Number.parseInt(value, 10);
|
|
@@ -109,6 +109,56 @@ function zodToJsonSchema(schema) {
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
// src/tools/adapters/mcp.ts
|
|
112
|
+
function formatConsolePart(value) {
|
|
113
|
+
if (typeof value === "string") return value;
|
|
114
|
+
if (value instanceof Error) return value.stack ?? value.message;
|
|
115
|
+
try {
|
|
116
|
+
return JSON.stringify(value);
|
|
117
|
+
} catch {
|
|
118
|
+
return String(value);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function invokeWriteCallback(encodingOrCallback, callback) {
|
|
122
|
+
const cb = typeof encodingOrCallback === "function" ? encodingOrCallback : typeof callback === "function" ? callback : void 0;
|
|
123
|
+
if (cb) queueMicrotask(() => cb());
|
|
124
|
+
}
|
|
125
|
+
function formatStdoutChunk(chunk, encodingOrCallback) {
|
|
126
|
+
if (Buffer.isBuffer(chunk)) {
|
|
127
|
+
const encoding = typeof encodingOrCallback === "string" ? encodingOrCallback : "utf8";
|
|
128
|
+
return chunk.toString(encoding);
|
|
129
|
+
}
|
|
130
|
+
return String(chunk);
|
|
131
|
+
}
|
|
132
|
+
async function withCapturedStdout(fn) {
|
|
133
|
+
const originalWrite = process.stdout.write;
|
|
134
|
+
const originalConsoleLog = console.log;
|
|
135
|
+
const originalConsoleInfo = console.info;
|
|
136
|
+
const originalConsoleDebug = console.debug;
|
|
137
|
+
let captured = "";
|
|
138
|
+
const captureConsole = (...values) => {
|
|
139
|
+
captured += `${values.map(formatConsolePart).join(" ")}
|
|
140
|
+
`;
|
|
141
|
+
};
|
|
142
|
+
process.stdout.write = (chunk, encodingOrCallback, callback) => {
|
|
143
|
+
captured += formatStdoutChunk(chunk, encodingOrCallback);
|
|
144
|
+
invokeWriteCallback(encodingOrCallback, callback);
|
|
145
|
+
return true;
|
|
146
|
+
};
|
|
147
|
+
console.log = captureConsole;
|
|
148
|
+
console.info = captureConsole;
|
|
149
|
+
console.debug = captureConsole;
|
|
150
|
+
try {
|
|
151
|
+
return await fn();
|
|
152
|
+
} finally {
|
|
153
|
+
process.stdout.write = originalWrite;
|
|
154
|
+
console.log = originalConsoleLog;
|
|
155
|
+
console.info = originalConsoleInfo;
|
|
156
|
+
console.debug = originalConsoleDebug;
|
|
157
|
+
if (captured.trim() && process.env.VIBE_MCP_DEBUG_STDIO === "1") {
|
|
158
|
+
process.stderr.write(captured);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
112
162
|
function formatZodError(err) {
|
|
113
163
|
const missing = err.issues.filter((i) => {
|
|
114
164
|
if (i.code !== "invalid_type") return false;
|
|
@@ -155,10 +205,12 @@ function buildMcpDispatcher(manifest) {
|
|
|
155
205
|
};
|
|
156
206
|
}
|
|
157
207
|
try {
|
|
158
|
-
const result = await
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
208
|
+
const result = await withCapturedStdout(
|
|
209
|
+
() => tool.execute(parsed.data, {
|
|
210
|
+
workingDirectory: process.cwd(),
|
|
211
|
+
surface: "mcp"
|
|
212
|
+
})
|
|
213
|
+
);
|
|
162
214
|
const text = result.success ? JSON.stringify({ success: true, ...result.data }) : result.data ? JSON.stringify({
|
|
163
215
|
success: false,
|
|
164
216
|
error: result.error ?? "unknown error",
|
|
@@ -29537,15 +29537,18 @@ var init_scene_audio_mux = __esm({
|
|
|
29537
29537
|
// src/commands/_shared/scene-render.ts
|
|
29538
29538
|
var scene_render_exports = {};
|
|
29539
29539
|
__export(scene_render_exports, {
|
|
29540
|
+
buildMediaOpenCommand: () => buildMediaOpenCommand,
|
|
29540
29541
|
buildRenderConfig: () => buildRenderConfig,
|
|
29541
29542
|
defaultOutputPath: () => defaultOutputPath,
|
|
29542
29543
|
executeSceneRender: () => executeSceneRender,
|
|
29543
29544
|
prepareBeatRenderRoot: () => prepareBeatRenderRoot,
|
|
29544
29545
|
qualityToCrf: () => qualityToCrf
|
|
29545
29546
|
});
|
|
29547
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
29546
29548
|
import { existsSync as existsSync11 } from "node:fs";
|
|
29547
29549
|
import { mkdir as mkdir6, readFile as readFile12, stat as stat2, writeFile as writeFile11 } from "node:fs/promises";
|
|
29548
29550
|
import { resolve as resolve15, relative as relative6, dirname as dirname5, basename as basename3, join as join10, isAbsolute } from "node:path";
|
|
29551
|
+
import { promisify as promisify2 } from "node:util";
|
|
29549
29552
|
import {
|
|
29550
29553
|
createRenderJob,
|
|
29551
29554
|
executeRenderJob
|
|
@@ -29572,6 +29575,38 @@ function buildRenderConfig(opts) {
|
|
|
29572
29575
|
workers: opts.workers ?? 1
|
|
29573
29576
|
};
|
|
29574
29577
|
}
|
|
29578
|
+
function buildMediaOpenCommand(action, filePath, platform = process.platform) {
|
|
29579
|
+
if (platform === "darwin") {
|
|
29580
|
+
const args = action === "reveal" ? ["-R", filePath] : [filePath];
|
|
29581
|
+
return {
|
|
29582
|
+
command: "open",
|
|
29583
|
+
args,
|
|
29584
|
+
display: ["open", ...args].map(quoteCliArg).join(" ")
|
|
29585
|
+
};
|
|
29586
|
+
}
|
|
29587
|
+
if (platform === "win32") {
|
|
29588
|
+
if (action === "reveal") {
|
|
29589
|
+
const args2 = [`/select,${filePath}`];
|
|
29590
|
+
return {
|
|
29591
|
+
command: "explorer",
|
|
29592
|
+
args: args2,
|
|
29593
|
+
display: ["explorer", ...args2].map(quoteCliArg).join(" ")
|
|
29594
|
+
};
|
|
29595
|
+
}
|
|
29596
|
+
const args = ["/c", "start", "", filePath];
|
|
29597
|
+
return {
|
|
29598
|
+
command: "cmd",
|
|
29599
|
+
args,
|
|
29600
|
+
display: ["cmd", ...args].map(quoteCliArg).join(" ")
|
|
29601
|
+
};
|
|
29602
|
+
}
|
|
29603
|
+
const target = action === "reveal" ? dirname5(filePath) : filePath;
|
|
29604
|
+
return {
|
|
29605
|
+
command: "xdg-open",
|
|
29606
|
+
args: [target],
|
|
29607
|
+
display: ["xdg-open", target].map(quoteCliArg).join(" ")
|
|
29608
|
+
};
|
|
29609
|
+
}
|
|
29575
29610
|
async function executeSceneRender(opts = {}) {
|
|
29576
29611
|
const projectDir = resolve15(opts.projectDir ?? ".");
|
|
29577
29612
|
const projectConfig = await readProjectConfig(projectDir);
|
|
@@ -29695,6 +29730,9 @@ async function executeSceneRender(opts = {}) {
|
|
|
29695
29730
|
beat: opts.beatId ?? null,
|
|
29696
29731
|
root,
|
|
29697
29732
|
outputPath: relative6(process.cwd(), outputPath) || outputPath,
|
|
29733
|
+
absoluteOutputPath: outputPath,
|
|
29734
|
+
openCommand: buildMediaOpenCommand("open", outputPath).display,
|
|
29735
|
+
revealCommand: buildMediaOpenCommand("reveal", outputPath).display,
|
|
29698
29736
|
durationMs: Date.now() - start,
|
|
29699
29737
|
framesRendered: job.framesRendered,
|
|
29700
29738
|
totalFrames: job.totalFrames,
|
|
@@ -29705,12 +29743,38 @@ async function executeSceneRender(opts = {}) {
|
|
|
29705
29743
|
audioMuxApplied,
|
|
29706
29744
|
audioMuxWarning
|
|
29707
29745
|
};
|
|
29746
|
+
if (opts.revealInFinder) {
|
|
29747
|
+
try {
|
|
29748
|
+
await runMediaOpenAction("reveal", outputPath);
|
|
29749
|
+
result.revealed = true;
|
|
29750
|
+
} catch (err) {
|
|
29751
|
+
result.revealed = false;
|
|
29752
|
+
result.revealError = err instanceof Error ? err.message : String(err);
|
|
29753
|
+
}
|
|
29754
|
+
}
|
|
29755
|
+
if (opts.openAfterRender) {
|
|
29756
|
+
try {
|
|
29757
|
+
await runMediaOpenAction("open", outputPath);
|
|
29758
|
+
result.opened = true;
|
|
29759
|
+
} catch (err) {
|
|
29760
|
+
result.opened = false;
|
|
29761
|
+
result.openError = err instanceof Error ? err.message : String(err);
|
|
29762
|
+
}
|
|
29763
|
+
}
|
|
29708
29764
|
result.reportPath = await writeRenderReport(projectDir, {
|
|
29709
29765
|
...result,
|
|
29710
29766
|
outputPath
|
|
29711
29767
|
});
|
|
29712
29768
|
return result;
|
|
29713
29769
|
}
|
|
29770
|
+
async function runMediaOpenAction(action, filePath) {
|
|
29771
|
+
const cmd = buildMediaOpenCommand(action, filePath);
|
|
29772
|
+
await execFileAsync2(cmd.command, cmd.args);
|
|
29773
|
+
}
|
|
29774
|
+
function quoteCliArg(value) {
|
|
29775
|
+
if (/^[A-Za-z0-9_/@%+=:,.-]+$/.test(value)) return value;
|
|
29776
|
+
return `"${value.replace(/(["\\$`])/g, "\\$1")}"`;
|
|
29777
|
+
}
|
|
29714
29778
|
async function safeStat(p) {
|
|
29715
29779
|
try {
|
|
29716
29780
|
return await stat2(p);
|
|
@@ -29881,6 +29945,13 @@ async function writeRenderReport(projectDir, result) {
|
|
|
29881
29945
|
beat: result.beat ?? null,
|
|
29882
29946
|
root: result.root,
|
|
29883
29947
|
outputPath: result.outputPath,
|
|
29948
|
+
absoluteOutputPath: result.absoluteOutputPath,
|
|
29949
|
+
openCommand: result.openCommand,
|
|
29950
|
+
revealCommand: result.revealCommand,
|
|
29951
|
+
opened: result.opened,
|
|
29952
|
+
revealed: result.revealed,
|
|
29953
|
+
openError: result.openError,
|
|
29954
|
+
revealError: result.revealError,
|
|
29884
29955
|
fps: result.fps,
|
|
29885
29956
|
quality: result.quality,
|
|
29886
29957
|
format: result.format,
|
|
@@ -29925,6 +29996,7 @@ function escapeAttr(value) {
|
|
|
29925
29996
|
function unique(items) {
|
|
29926
29997
|
return [...new Set(items.filter((item) => Boolean(item)))];
|
|
29927
29998
|
}
|
|
29999
|
+
var execFileAsync2;
|
|
29928
30000
|
var init_scene_render = __esm({
|
|
29929
30001
|
"src/commands/_shared/scene-render.ts"() {
|
|
29930
30002
|
"use strict";
|
|
@@ -29934,6 +30006,7 @@ var init_scene_render = __esm({
|
|
|
29934
30006
|
init_scene_audio_mux();
|
|
29935
30007
|
init_project_config();
|
|
29936
30008
|
init_scene_project();
|
|
30009
|
+
execFileAsync2 = promisify2(execFile2);
|
|
29937
30010
|
}
|
|
29938
30011
|
});
|
|
29939
30012
|
|
|
@@ -35843,11 +35916,11 @@ registerRoot(Root);
|
|
|
35843
35916
|
return dir;
|
|
35844
35917
|
}
|
|
35845
35918
|
async function this_npmInstall(dir) {
|
|
35846
|
-
const { execFile:
|
|
35847
|
-
const { promisify:
|
|
35848
|
-
const
|
|
35919
|
+
const { execFile: execFile3 } = await import("node:child_process");
|
|
35920
|
+
const { promisify: promisify3 } = await import("node:util");
|
|
35921
|
+
const execFileAsync3 = promisify3(execFile3);
|
|
35849
35922
|
try {
|
|
35850
|
-
await
|
|
35923
|
+
await execFileAsync3("npm", ["install", "--prefer-offline", "--no-audit", "--no-fund"], {
|
|
35851
35924
|
cwd: dir,
|
|
35852
35925
|
timeout: 18e4
|
|
35853
35926
|
});
|
|
@@ -35871,13 +35944,13 @@ async function renderMotion(options) {
|
|
|
35871
35944
|
);
|
|
35872
35945
|
try {
|
|
35873
35946
|
const entryPoint = join16(dir, "Root.tsx");
|
|
35874
|
-
const { execFile:
|
|
35875
|
-
const { promisify:
|
|
35876
|
-
const
|
|
35947
|
+
const { execFile: execFile3 } = await import("node:child_process");
|
|
35948
|
+
const { promisify: promisify3 } = await import("node:util");
|
|
35949
|
+
const execFileAsync3 = promisify3(execFile3);
|
|
35877
35950
|
if (transparent) {
|
|
35878
35951
|
const webmOut = options.outputPath.replace(/\.\w+$/, ".webm");
|
|
35879
35952
|
try {
|
|
35880
|
-
await
|
|
35953
|
+
await execFileAsync3("npx", [
|
|
35881
35954
|
"remotion",
|
|
35882
35955
|
"render",
|
|
35883
35956
|
entryPoint,
|
|
@@ -35894,7 +35967,7 @@ async function renderMotion(options) {
|
|
|
35894
35967
|
} catch {
|
|
35895
35968
|
}
|
|
35896
35969
|
try {
|
|
35897
|
-
await
|
|
35970
|
+
await execFileAsync3("npx", [
|
|
35898
35971
|
"remotion",
|
|
35899
35972
|
"render",
|
|
35900
35973
|
entryPoint,
|
|
@@ -35914,7 +35987,7 @@ async function renderMotion(options) {
|
|
|
35914
35987
|
}
|
|
35915
35988
|
}
|
|
35916
35989
|
const mp4Out = options.outputPath.replace(/\.\w+$/, ".mp4");
|
|
35917
|
-
await
|
|
35990
|
+
await execFileAsync3("npx", [
|
|
35918
35991
|
"remotion",
|
|
35919
35992
|
"render",
|
|
35920
35993
|
entryPoint,
|
|
@@ -52583,7 +52656,9 @@ var sceneRenderSchema = external_exports.object({
|
|
|
52583
52656
|
fps: external_exports.number().optional().describe("Frames per second. Must be 24, 30, or 60. Default 30."),
|
|
52584
52657
|
quality: external_exports.enum(["draft", "standard", "high"]).optional().describe("Quality preset. Default 'standard'."),
|
|
52585
52658
|
format: external_exports.enum(["mp4", "webm", "mov"]).optional().describe("Container format. Default 'mp4'."),
|
|
52586
|
-
workers: external_exports.number().optional().describe("Capture worker count (1-16). Default 1.")
|
|
52659
|
+
workers: external_exports.number().optional().describe("Capture worker count (1-16). Default 1."),
|
|
52660
|
+
openAfterRender: external_exports.boolean().optional().describe("Open the rendered video in the OS default app after render. Default false."),
|
|
52661
|
+
revealInFinder: external_exports.boolean().optional().describe("Reveal the rendered video in Finder/file manager after render. Default false.")
|
|
52587
52662
|
});
|
|
52588
52663
|
var sceneRenderTool = defineTool({
|
|
52589
52664
|
name: "render",
|
|
@@ -52601,7 +52676,9 @@ var sceneRenderTool = defineTool({
|
|
|
52601
52676
|
fps: args.fps,
|
|
52602
52677
|
quality: args.quality,
|
|
52603
52678
|
format: args.format,
|
|
52604
|
-
workers: args.workers
|
|
52679
|
+
workers: args.workers,
|
|
52680
|
+
openAfterRender: args.openAfterRender,
|
|
52681
|
+
revealInFinder: args.revealInFinder
|
|
52605
52682
|
});
|
|
52606
52683
|
if (!result.success) {
|
|
52607
52684
|
return { success: false, error: result.error ?? "render failed" };
|
|
@@ -52610,6 +52687,13 @@ var sceneRenderTool = defineTool({
|
|
|
52610
52687
|
success: true,
|
|
52611
52688
|
data: {
|
|
52612
52689
|
outputPath: result.outputPath,
|
|
52690
|
+
absoluteOutputPath: result.absoluteOutputPath,
|
|
52691
|
+
openCommand: result.openCommand,
|
|
52692
|
+
revealCommand: result.revealCommand,
|
|
52693
|
+
opened: result.opened,
|
|
52694
|
+
revealed: result.revealed,
|
|
52695
|
+
openError: result.openError,
|
|
52696
|
+
revealError: result.revealError,
|
|
52613
52697
|
beat: result.beat,
|
|
52614
52698
|
root: result.root,
|
|
52615
52699
|
reportPath: result.reportPath,
|
|
@@ -52618,13 +52702,24 @@ var sceneRenderTool = defineTool({
|
|
|
52618
52702
|
totalFrames: result.totalFrames,
|
|
52619
52703
|
fps: result.fps,
|
|
52620
52704
|
quality: result.quality,
|
|
52621
|
-
format: result.format
|
|
52705
|
+
format: result.format,
|
|
52706
|
+
audioCount: result.audioCount,
|
|
52707
|
+
audioMuxApplied: result.audioMuxApplied,
|
|
52708
|
+
audioMuxWarning: result.audioMuxWarning
|
|
52622
52709
|
},
|
|
52623
52710
|
humanLines: [
|
|
52624
|
-
`\u2705 Render complete: ${result.outputPath}`,
|
|
52711
|
+
`\u2705 Render complete: ${result.absoluteOutputPath ?? result.outputPath}`,
|
|
52625
52712
|
` duration: ${((result.durationMs ?? 0) / 1e3).toFixed(1)}s`,
|
|
52626
52713
|
` frames: ${result.framesRendered ?? "?"}${result.totalFrames ? ` / ${result.totalFrames}` : ""}`,
|
|
52627
|
-
` config: ${result.fps}fps \xB7 ${result.quality} \xB7 ${result.format}
|
|
52714
|
+
` config: ${result.fps}fps \xB7 ${result.quality} \xB7 ${result.format}`,
|
|
52715
|
+
` audio: ${result.audioCount && result.audioCount > 0 ? `${result.audioCount} track${result.audioCount === 1 ? "" : "s"} muxed` : "silent"}`,
|
|
52716
|
+
...result.openCommand ? [` open: ${result.openCommand}`] : [],
|
|
52717
|
+
...result.revealCommand ? [` reveal: ${result.revealCommand}`] : [],
|
|
52718
|
+
` inspect: vibe inspect render ${projectDir} --cheap --json`,
|
|
52719
|
+
...result.opened ? [` opened: yes`] : [],
|
|
52720
|
+
...result.revealed ? [` revealed: yes`] : [],
|
|
52721
|
+
...result.openError ? [` open warning: ${result.openError}`] : [],
|
|
52722
|
+
...result.revealError ? [` reveal warning: ${result.revealError}`] : []
|
|
52628
52723
|
]
|
|
52629
52724
|
};
|
|
52630
52725
|
}
|
|
@@ -108,6 +108,8 @@ export declare const sceneRenderTool: import("../define-tool.js").ToolDefinition
|
|
|
108
108
|
quality: z.ZodOptional<z.ZodEnum<["draft", "standard", "high"]>>;
|
|
109
109
|
format: z.ZodOptional<z.ZodEnum<["mp4", "webm", "mov"]>>;
|
|
110
110
|
workers: z.ZodOptional<z.ZodNumber>;
|
|
111
|
+
openAfterRender: z.ZodOptional<z.ZodBoolean>;
|
|
112
|
+
revealInFinder: z.ZodOptional<z.ZodBoolean>;
|
|
111
113
|
}, "strip", z.ZodTypeAny, {
|
|
112
114
|
output?: string | undefined;
|
|
113
115
|
fps?: number | undefined;
|
|
@@ -117,6 +119,8 @@ export declare const sceneRenderTool: import("../define-tool.js").ToolDefinition
|
|
|
117
119
|
root?: string | undefined;
|
|
118
120
|
beat?: string | undefined;
|
|
119
121
|
workers?: number | undefined;
|
|
122
|
+
openAfterRender?: boolean | undefined;
|
|
123
|
+
revealInFinder?: boolean | undefined;
|
|
120
124
|
}, {
|
|
121
125
|
output?: string | undefined;
|
|
122
126
|
fps?: number | undefined;
|
|
@@ -126,6 +130,8 @@ export declare const sceneRenderTool: import("../define-tool.js").ToolDefinition
|
|
|
126
130
|
root?: string | undefined;
|
|
127
131
|
beat?: string | undefined;
|
|
128
132
|
workers?: number | undefined;
|
|
133
|
+
openAfterRender?: boolean | undefined;
|
|
134
|
+
revealInFinder?: boolean | undefined;
|
|
129
135
|
}>>;
|
|
130
136
|
export declare const sceneBuildTool: import("../define-tool.js").ToolDefinition<z.ZodObject<{
|
|
131
137
|
projectDir: z.ZodOptional<z.ZodString>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeframe/cli",
|
|
3
|
-
"version": "0.106.
|
|
3
|
+
"version": "0.106.8",
|
|
4
4
|
"description": "VibeFrame CLI - agentic video workflow runtime",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
@@ -83,8 +83,8 @@
|
|
|
83
83
|
"tsx": "^4.21.0",
|
|
84
84
|
"typescript": "^5.3.3",
|
|
85
85
|
"vitest": "^1.2.2",
|
|
86
|
-
"@vibeframe/ai-providers": "0.106.
|
|
87
|
-
"@vibeframe/core": "0.106.
|
|
86
|
+
"@vibeframe/ai-providers": "0.106.8",
|
|
87
|
+
"@vibeframe/core": "0.106.8"
|
|
88
88
|
},
|
|
89
89
|
"engines": {
|
|
90
90
|
"node": ">=20"
|