@vibeframe/cli 0.85.0 → 0.87.0
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/index.js +153 -62
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -52677,14 +52677,14 @@ __export(ai_audio_exports, {
|
|
|
52677
52677
|
});
|
|
52678
52678
|
import { resolve as resolve54, dirname as dirname19, basename as basename18, extname as extname12 } from "node:path";
|
|
52679
52679
|
import { readFile as readFile36, writeFile as writeFile40 } from "node:fs/promises";
|
|
52680
|
-
import { existsSync as
|
|
52680
|
+
import { existsSync as existsSync38 } from "node:fs";
|
|
52681
52681
|
async function executeTranscribe(options) {
|
|
52682
52682
|
const { audioPath, language, output, format, apiKey } = options;
|
|
52683
52683
|
try {
|
|
52684
52684
|
const key = apiKey || process.env.OPENAI_API_KEY;
|
|
52685
52685
|
if (!key) return { success: false, error: "OPENAI_API_KEY required" };
|
|
52686
52686
|
const absPath = resolve54(process.cwd(), audioPath);
|
|
52687
|
-
if (!
|
|
52687
|
+
if (!existsSync38(absPath)) return { success: false, error: `File not found: ${absPath}` };
|
|
52688
52688
|
const whisper = new WhisperProvider();
|
|
52689
52689
|
await whisper.initialize({ apiKey: key });
|
|
52690
52690
|
const audioBuffer = await readFile36(absPath);
|
|
@@ -52717,7 +52717,7 @@ async function executeIsolate(options) {
|
|
|
52717
52717
|
const key = apiKey || process.env.ELEVENLABS_API_KEY;
|
|
52718
52718
|
if (!key) return { success: false, error: "ELEVENLABS_API_KEY required" };
|
|
52719
52719
|
const absPath = resolve54(process.cwd(), audioPath);
|
|
52720
|
-
if (!
|
|
52720
|
+
if (!existsSync38(absPath)) return { success: false, error: `File not found: ${absPath}` };
|
|
52721
52721
|
const audioBuffer = await readFile36(absPath);
|
|
52722
52722
|
const elevenlabs = new ElevenLabsProvider();
|
|
52723
52723
|
await elevenlabs.initialize({ apiKey: key });
|
|
@@ -52743,7 +52743,7 @@ async function executeVoiceClone(options) {
|
|
|
52743
52743
|
const audioBuffers = [];
|
|
52744
52744
|
for (const samplePath of samplePaths) {
|
|
52745
52745
|
const absPath = resolve54(process.cwd(), samplePath);
|
|
52746
|
-
if (!
|
|
52746
|
+
if (!existsSync38(absPath)) return { success: false, error: `File not found: ${samplePath}` };
|
|
52747
52747
|
const buffer = await readFile36(absPath);
|
|
52748
52748
|
audioBuffers.push(buffer);
|
|
52749
52749
|
}
|
|
@@ -52765,7 +52765,7 @@ async function executeDub(options) {
|
|
|
52765
52765
|
const { mediaPath, language, source, voice, analyzeOnly, output } = options;
|
|
52766
52766
|
try {
|
|
52767
52767
|
const absPath = resolve54(process.cwd(), mediaPath);
|
|
52768
|
-
if (!
|
|
52768
|
+
if (!existsSync38(absPath)) return { success: false, error: `File not found: ${absPath}` };
|
|
52769
52769
|
const openaiKey = process.env.OPENAI_API_KEY;
|
|
52770
52770
|
const anthropicKey = process.env.ANTHROPIC_API_KEY;
|
|
52771
52771
|
const elevenlabsKey = process.env.ELEVENLABS_API_KEY;
|
|
@@ -52893,8 +52893,8 @@ async function executeDuck(options) {
|
|
|
52893
52893
|
if (!commandExists("ffmpeg")) return { success: false, error: "FFmpeg not found" };
|
|
52894
52894
|
const absMusicPath = resolve54(process.cwd(), musicPath);
|
|
52895
52895
|
const absVoicePath = resolve54(process.cwd(), voicePath);
|
|
52896
|
-
if (!
|
|
52897
|
-
if (!
|
|
52896
|
+
if (!existsSync38(absMusicPath)) return { success: false, error: `Music file not found: ${absMusicPath}` };
|
|
52897
|
+
if (!existsSync38(absVoicePath)) return { success: false, error: `Voice file not found: ${absVoicePath}` };
|
|
52898
52898
|
const defaultOutput = resolve54(dirname19(absMusicPath), `${basename18(absMusicPath, extname12(absMusicPath))}-ducked${extname12(absMusicPath)}`);
|
|
52899
52899
|
const outputPath = resolve54(process.cwd(), output || defaultOutput);
|
|
52900
52900
|
const filter = `[1:a]asplit=2[sc][mix];[0:a][sc]sidechaincompress=threshold=${threshold}dB:ratio=${ratio}:attack=${attack}:release=${release}[ducked];[ducked][mix]amix=inputs=2:duration=longest`;
|
|
@@ -52908,7 +52908,7 @@ async function executeDuck(options) {
|
|
|
52908
52908
|
"-y",
|
|
52909
52909
|
outputPath
|
|
52910
52910
|
], { timeout: 12e4, maxBuffer: 50 * 1024 * 1024 });
|
|
52911
|
-
if (!
|
|
52911
|
+
if (!existsSync38(outputPath)) return { success: false, error: "FFmpeg failed to create output" };
|
|
52912
52912
|
return { success: true, outputPath };
|
|
52913
52913
|
} catch (error) {
|
|
52914
52914
|
return { success: false, error: `Audio ducking failed: ${error instanceof Error ? error.message : String(error)}` };
|
|
@@ -52926,7 +52926,7 @@ var init_ai_audio = __esm({
|
|
|
52926
52926
|
// src/pipeline/executor.ts
|
|
52927
52927
|
import { resolve as resolve55 } from "node:path";
|
|
52928
52928
|
import { readFile as readFile37, writeFile as writeFile41, mkdir as mkdir22 } from "node:fs/promises";
|
|
52929
|
-
import { existsSync as
|
|
52929
|
+
import { existsSync as existsSync39 } from "node:fs";
|
|
52930
52930
|
function maxCostFor(action) {
|
|
52931
52931
|
const cmd = ACTION_METADATA[action]?.command;
|
|
52932
52932
|
if (!cmd) return 0;
|
|
@@ -53143,7 +53143,7 @@ async function ensureActionsRegistered() {
|
|
|
53143
53143
|
}
|
|
53144
53144
|
async function loadPipeline(filePath) {
|
|
53145
53145
|
const absPath = resolve55(process.cwd(), filePath);
|
|
53146
|
-
if (!
|
|
53146
|
+
if (!existsSync39(absPath)) {
|
|
53147
53147
|
throw new Error(`Pipeline file not found: ${absPath}`);
|
|
53148
53148
|
}
|
|
53149
53149
|
const content = await readFile37(absPath, "utf-8");
|
|
@@ -53168,7 +53168,7 @@ async function executePipeline(manifest2, options = {}) {
|
|
|
53168
53168
|
const startTime = Date.now();
|
|
53169
53169
|
if (options.resume) {
|
|
53170
53170
|
const checkpointPath = resolve55(outputDir, CHECKPOINT_FILE);
|
|
53171
|
-
if (
|
|
53171
|
+
if (existsSync39(checkpointPath)) {
|
|
53172
53172
|
const checkpointContent = await readFile37(checkpointPath, "utf-8");
|
|
53173
53173
|
const checkpoint = (0, import_yaml8.parse)(checkpointContent);
|
|
53174
53174
|
for (const cs of checkpoint.completedSteps) {
|
|
@@ -59771,7 +59771,7 @@ var init_generate2 = __esm({
|
|
|
59771
59771
|
// src/tools/manifest/remix.ts
|
|
59772
59772
|
import { writeFile as writeFile43 } from "node:fs/promises";
|
|
59773
59773
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
59774
|
-
import { join as
|
|
59774
|
+
import { join as join14 } from "node:path";
|
|
59775
59775
|
var pipelineHighlightsTool, pipelineAutoShortsTool, pipelineRunTool, pipelineRegenerateSceneTool, remixTools;
|
|
59776
59776
|
var init_remix = __esm({
|
|
59777
59777
|
"src/tools/manifest/remix.ts"() {
|
|
@@ -59879,7 +59879,7 @@ var init_remix = __esm({
|
|
|
59879
59879
|
let resolvedPath = args.pipelinePath;
|
|
59880
59880
|
let tempPath;
|
|
59881
59881
|
if (args.pipelineYaml) {
|
|
59882
|
-
tempPath =
|
|
59882
|
+
tempPath = join14(tmpdir3(), `vibe-mcp-pipeline-${Date.now()}.yaml`);
|
|
59883
59883
|
await writeFile43(tempPath, args.pipelineYaml, "utf-8");
|
|
59884
59884
|
resolvedPath = tempPath;
|
|
59885
59885
|
}
|
|
@@ -60636,7 +60636,7 @@ __export(project_builder_exports, {
|
|
|
60636
60636
|
resolveSourceUrl: () => resolveSourceUrl
|
|
60637
60637
|
});
|
|
60638
60638
|
import { mkdtemp, mkdir as mkdir24, copyFile as copyFile3, writeFile as writeFile47, rm as rm4, readdir as readdir3 } from "node:fs/promises";
|
|
60639
|
-
import { existsSync as
|
|
60639
|
+
import { existsSync as existsSync40 } from "node:fs";
|
|
60640
60640
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
60641
60641
|
import { createRequire } from "node:module";
|
|
60642
60642
|
import * as path from "node:path";
|
|
@@ -60648,7 +60648,7 @@ async function buildTempProject(state, projectFileDir) {
|
|
|
60648
60648
|
for (const source of state.sources) {
|
|
60649
60649
|
if (copied.has(source.id)) continue;
|
|
60650
60650
|
const resolved = resolveSourceUrl(source.url, projectFileDir);
|
|
60651
|
-
if (!
|
|
60651
|
+
if (!existsSync40(resolved)) {
|
|
60652
60652
|
throw new Error(`Source file not found: ${resolved} (from source id=${source.id})`);
|
|
60653
60653
|
}
|
|
60654
60654
|
const dest = path.join(assetsDir, path.basename(resolved));
|
|
@@ -61677,7 +61677,7 @@ var init_export2 = __esm({
|
|
|
61677
61677
|
|
|
61678
61678
|
// src/tools/manifest/agent-only.ts
|
|
61679
61679
|
import { readFile as readFile41, writeFile as writeFile48, readdir as readdir4, stat as stat6, access as access9, unlink as unlink4 } from "node:fs/promises";
|
|
61680
|
-
import { resolve as resolve63, join as
|
|
61680
|
+
import { resolve as resolve63, join as join16, basename as basename22, extname as extname13 } from "node:path";
|
|
61681
61681
|
function matchPattern(filename, pattern) {
|
|
61682
61682
|
const regex2 = new RegExp(
|
|
61683
61683
|
"^" + pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".") + "$",
|
|
@@ -61760,7 +61760,7 @@ var init_agent_only = __esm({
|
|
|
61760
61760
|
const results = [];
|
|
61761
61761
|
for (const entry of entries) {
|
|
61762
61762
|
if (args.pattern && !matchPattern(entry.name, args.pattern)) continue;
|
|
61763
|
-
const fullPath =
|
|
61763
|
+
const fullPath = join16(absPath, entry.name);
|
|
61764
61764
|
const stats = await stat6(fullPath);
|
|
61765
61765
|
if (entry.isDirectory()) {
|
|
61766
61766
|
results.push(`[DIR] ${entry.name}/`);
|
|
@@ -61865,7 +61865,7 @@ var init_agent_only = __esm({
|
|
|
61865
61865
|
const scanDir = async (dir) => {
|
|
61866
61866
|
const entries = await readdir4(dir, { withFileTypes: true });
|
|
61867
61867
|
for (const entry of entries) {
|
|
61868
|
-
const entryPath =
|
|
61868
|
+
const entryPath = join16(dir, entry.name);
|
|
61869
61869
|
if (entry.isDirectory() && recursive) {
|
|
61870
61870
|
await scanDir(entryPath);
|
|
61871
61871
|
} else if (entry.isFile()) {
|
|
@@ -62837,7 +62837,7 @@ init_source();
|
|
|
62837
62837
|
// package.json
|
|
62838
62838
|
var package_default = {
|
|
62839
62839
|
name: "@vibeframe/cli",
|
|
62840
|
-
version: "0.
|
|
62840
|
+
version: "0.87.0",
|
|
62841
62841
|
description: "VibeFrame CLI - natural language video editing from the terminal",
|
|
62842
62842
|
private: false,
|
|
62843
62843
|
license: "MIT",
|
|
@@ -65122,13 +65122,20 @@ applyTiers(remixCommand, {
|
|
|
65122
65122
|
init_esm();
|
|
65123
65123
|
init_output();
|
|
65124
65124
|
init_cost_tier();
|
|
65125
|
-
var schemaCommand = new Command("schema").description("Show JSON schema for a CLI command").argument("[command]", "Command path (e.g., generate.image, edit.silence-cut)").option("--list", "List all available command paths").action((commandPath, options) => {
|
|
65125
|
+
var schemaCommand = new Command("schema").description("Show JSON schema for a CLI command").argument("[command]", "Command path (e.g., generate.image, edit.silence-cut)").option("--list", "List all available command paths").option("--filter <tier>", "With --list, only show commands at the given cost tier (free | low | high | very-high)").action((commandPath, options) => {
|
|
65126
65126
|
const program3 = schemaCommand.parent;
|
|
65127
65127
|
if (!program3) {
|
|
65128
65128
|
exitWithError(generalError("Schema command must be registered on a program"));
|
|
65129
65129
|
}
|
|
65130
65130
|
if (options.list || !commandPath) {
|
|
65131
|
-
|
|
65131
|
+
const validTiers = /* @__PURE__ */ new Set(["free", "low", "high", "very-high"]);
|
|
65132
|
+
if (options.filter && !validTiers.has(options.filter)) {
|
|
65133
|
+
exitWithError(usageError(
|
|
65134
|
+
`Invalid --filter: ${options.filter}`,
|
|
65135
|
+
`Must be one of: free, low, high, very-high (matches the cost field on each subcommand).`
|
|
65136
|
+
));
|
|
65137
|
+
}
|
|
65138
|
+
listCommands(program3, options.filter);
|
|
65132
65139
|
return;
|
|
65133
65140
|
}
|
|
65134
65141
|
const parts = commandPath.split(".");
|
|
@@ -65168,7 +65175,7 @@ var schemaCommand = new Command("schema").description("Show JSON schema for a CL
|
|
|
65168
65175
|
const schema = buildSchema(actionCmd, toolName);
|
|
65169
65176
|
console.log(JSON.stringify(schema, null, 2));
|
|
65170
65177
|
});
|
|
65171
|
-
function listCommands(program3) {
|
|
65178
|
+
function listCommands(program3, filter) {
|
|
65172
65179
|
const commands = [];
|
|
65173
65180
|
const skipTopLevel = /* @__PURE__ */ new Set(["help", "schema"]);
|
|
65174
65181
|
for (const group of program3.commands) {
|
|
@@ -65179,6 +65186,7 @@ function listCommands(program3) {
|
|
|
65179
65186
|
const desc = group.description() || "";
|
|
65180
65187
|
if (desc.toLowerCase().includes("deprecated")) continue;
|
|
65181
65188
|
const cost = getCostTier(group);
|
|
65189
|
+
if (filter && cost !== filter) continue;
|
|
65182
65190
|
commands.push({ path: name, description: desc, ...cost ? { cost } : {} });
|
|
65183
65191
|
continue;
|
|
65184
65192
|
}
|
|
@@ -65186,6 +65194,7 @@ function listCommands(program3) {
|
|
|
65186
65194
|
const desc = sub.description() || "";
|
|
65187
65195
|
if (desc.toLowerCase().includes("deprecated")) continue;
|
|
65188
65196
|
const cost = getCostTier(sub);
|
|
65197
|
+
if (filter && cost !== filter) continue;
|
|
65189
65198
|
commands.push({
|
|
65190
65199
|
path: `${name}.${sub.name()}`,
|
|
65191
65200
|
description: desc,
|
|
@@ -70960,8 +70969,10 @@ init_esm();
|
|
|
70960
70969
|
init_source();
|
|
70961
70970
|
init_ora();
|
|
70962
70971
|
init_scene_build();
|
|
70972
|
+
init_storyboard_parse();
|
|
70963
70973
|
init_output();
|
|
70964
|
-
import { resolve as resolve48 } from "node:path";
|
|
70974
|
+
import { resolve as resolve48, join as join13 } from "node:path";
|
|
70975
|
+
import { readFileSync as readFileSync2, existsSync as existsSync35 } from "node:fs";
|
|
70965
70976
|
var VALID_MODES = ["agent", "batch", "auto"];
|
|
70966
70977
|
var buildCommand = new Command("build").description("Build a VibeFrame video project from STORYBOARD.md").argument("[project-dir]", "Video project directory", ".").option("--mode <mode>", "Build mode: agent|batch|auto", "auto").option("--effort <level>", "Compose effort tier (batch mode only): low|medium|high", "medium").option("--composer <provider>", "Batch composer: claude|openai|gemini").option("--skip-narration", "Don't dispatch TTS even when beats declare narration cues").option("--skip-backdrop", "Don't dispatch image-gen even when beats declare backdrop cues").option("--skip-render", "Compose only \u2014 don't render to MP4").option("--tts <provider>", "TTS provider: auto|elevenlabs|kokoro").option("--voice <id>", "Voice id").option("--image-provider <name>", "Image provider: openai").option("--quality <q>", "Image quality: standard|hd", "hd").option("--image-size <s>", "Image size: 1024x1024|1536x1024|1024x1536", "1536x1024").option("--force", "Re-dispatch primitives even when assets already exist").option("--dry-run", "Preview parameters without dispatching").addHelpText("after", `
|
|
70967
70978
|
Examples:
|
|
@@ -71055,9 +71066,53 @@ function printBuildDryRun(projectDirArg, params) {
|
|
|
71055
71066
|
console.log(` Image: ${source_default.bold(String(params.imageProvider ?? "openai"))} ${source_default.dim(`${params.imageQuality} ${params.imageSize}`)}${params.skipBackdrop ? source_default.dim(" (skipped)") : ""}`);
|
|
71056
71067
|
console.log(` Render: ${source_default.bold(params.skipRender ? "skip" : "yes")}`);
|
|
71057
71068
|
console.log(` Regenerate: ${source_default.bold(params.force ? "yes" : "cache when possible")}`);
|
|
71069
|
+
const estimate = estimateBuildCost(params);
|
|
71070
|
+
if (estimate) {
|
|
71071
|
+
console.log();
|
|
71072
|
+
console.log(source_default.bold.cyan("Estimated cost (tier-derived, conservative)"));
|
|
71073
|
+
console.log(source_default.dim("-".repeat(60)));
|
|
71074
|
+
console.log(` Beats: ${source_default.bold(estimate.beats)}`);
|
|
71075
|
+
if (!params.skipNarration) {
|
|
71076
|
+
console.log(` Narration: ${source_default.cyan(`$${estimate.narrationUsd.toFixed(2)}`)} ${source_default.dim(`(${estimate.beats} \xD7 low)`)}`);
|
|
71077
|
+
}
|
|
71078
|
+
if (!params.skipBackdrop) {
|
|
71079
|
+
console.log(` Backdrops: ${source_default.yellow(`$${estimate.backdropUsd.toFixed(2)}`)} ${source_default.dim(`(${estimate.beats} \xD7 high)`)}`);
|
|
71080
|
+
}
|
|
71081
|
+
if (params.mode !== "agent") {
|
|
71082
|
+
console.log(` Compose (LLM): ${source_default.cyan(`$${estimate.composeUsd.toFixed(2)}`)} ${source_default.dim(`(${estimate.beats} \xD7 ~$0.06 batch mode)`)}`);
|
|
71083
|
+
} else {
|
|
71084
|
+
console.log(` Compose: ${source_default.dim(`$0.00 (agent mode \u2014 host LLM does composition)`)}`);
|
|
71085
|
+
}
|
|
71086
|
+
console.log(` ${source_default.bold("Total:")} ${source_default.bold(`$${estimate.totalUsd.toFixed(2)}`)}`);
|
|
71087
|
+
}
|
|
71058
71088
|
console.log();
|
|
71059
71089
|
console.log(source_default.dim("No assets, provider calls, or video files were created."));
|
|
71060
71090
|
}
|
|
71091
|
+
function estimateBuildCost(params) {
|
|
71092
|
+
const storyboardPath = join13(params.projectDir, "STORYBOARD.md");
|
|
71093
|
+
if (!existsSync35(storyboardPath)) return null;
|
|
71094
|
+
let beats = 0;
|
|
71095
|
+
try {
|
|
71096
|
+
const md = readFileSync2(storyboardPath, "utf-8");
|
|
71097
|
+
beats = parseStoryboard(md).beats.length;
|
|
71098
|
+
} catch {
|
|
71099
|
+
return null;
|
|
71100
|
+
}
|
|
71101
|
+
if (beats === 0) return null;
|
|
71102
|
+
const TTS_PER_BEAT = 0.05;
|
|
71103
|
+
const IMAGE_PER_BEAT = 3;
|
|
71104
|
+
const COMPOSE_PER_BEAT_BATCH = 0.06;
|
|
71105
|
+
const narrationUsd = params.skipNarration ? 0 : beats * TTS_PER_BEAT;
|
|
71106
|
+
const backdropUsd = params.skipBackdrop ? 0 : beats * IMAGE_PER_BEAT;
|
|
71107
|
+
const composeUsd = params.mode === "agent" ? 0 : beats * COMPOSE_PER_BEAT_BATCH;
|
|
71108
|
+
return {
|
|
71109
|
+
beats,
|
|
71110
|
+
narrationUsd,
|
|
71111
|
+
backdropUsd,
|
|
71112
|
+
composeUsd,
|
|
71113
|
+
totalUsd: narrationUsd + backdropUsd + composeUsd
|
|
71114
|
+
};
|
|
71115
|
+
}
|
|
71061
71116
|
function printNeedsAuthor(result) {
|
|
71062
71117
|
console.log(source_default.cyan("Agent authoring required"));
|
|
71063
71118
|
console.log();
|
|
@@ -71266,10 +71321,11 @@ init_exec_safe();
|
|
|
71266
71321
|
init_api_key();
|
|
71267
71322
|
init_agent_host_detect();
|
|
71268
71323
|
init_composer_resolve();
|
|
71324
|
+
init_cost_tier();
|
|
71269
71325
|
init_scene_build();
|
|
71270
71326
|
init_output();
|
|
71271
71327
|
import { access as access7 } from "node:fs/promises";
|
|
71272
|
-
import { existsSync as
|
|
71328
|
+
import { existsSync as existsSync36 } from "node:fs";
|
|
71273
71329
|
import { resolve as resolve50 } from "node:path";
|
|
71274
71330
|
var COMMAND_KEY_MAP = getCommandKeyMap();
|
|
71275
71331
|
var FREE_COMMANDS = [
|
|
@@ -71307,7 +71363,10 @@ Examples:
|
|
|
71307
71363
|
});
|
|
71308
71364
|
return;
|
|
71309
71365
|
}
|
|
71310
|
-
printReport(results, {
|
|
71366
|
+
printReport(results, {
|
|
71367
|
+
verbose: Boolean(options.verbose),
|
|
71368
|
+
program: doctorCommand.parent
|
|
71369
|
+
});
|
|
71311
71370
|
if (options.testKeys) {
|
|
71312
71371
|
await runLiveKeyTests(results);
|
|
71313
71372
|
}
|
|
@@ -71388,20 +71447,20 @@ async function runDiagnostics() {
|
|
|
71388
71447
|
installed = false;
|
|
71389
71448
|
}
|
|
71390
71449
|
} else if (toolName === "chrome") {
|
|
71391
|
-
const { existsSync:
|
|
71450
|
+
const { existsSync: existsSync41 } = await import("node:fs");
|
|
71392
71451
|
const { homedir: homedir6 } = await import("node:os");
|
|
71393
|
-
const { join:
|
|
71452
|
+
const { join: join17 } = await import("node:path");
|
|
71394
71453
|
const chromePaths = [
|
|
71395
71454
|
process.env.HYPERFRAMES_CHROME_PATH,
|
|
71396
71455
|
process.env.CHROME_PATH,
|
|
71397
|
-
|
|
71456
|
+
join17(homedir6(), ".cache", "puppeteer", "chrome-headless-shell", "mac_arm-147.0.7727.56", "chrome-headless-shell-mac_arm", "chrome-headless-shell"),
|
|
71398
71457
|
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
71399
71458
|
"/Applications/Chromium.app/Contents/MacOS/Chromium",
|
|
71400
71459
|
"/usr/bin/google-chrome",
|
|
71401
71460
|
"/usr/bin/chromium",
|
|
71402
71461
|
"/usr/bin/chromium-browser"
|
|
71403
71462
|
];
|
|
71404
|
-
installed = chromePaths.some((p) => p &&
|
|
71463
|
+
installed = chromePaths.some((p) => p && existsSync41(p));
|
|
71405
71464
|
} else {
|
|
71406
71465
|
installed = commandExists(toolName);
|
|
71407
71466
|
}
|
|
@@ -71432,7 +71491,7 @@ async function runDiagnostics() {
|
|
|
71432
71491
|
const cwd = process.cwd();
|
|
71433
71492
|
const projectFiles = ["AGENTS.md", "CLAUDE.md", "vibe.project.yaml"].map((rel) => ({
|
|
71434
71493
|
path: rel,
|
|
71435
|
-
exists:
|
|
71494
|
+
exists: existsSync36(resolve50(cwd, rel))
|
|
71436
71495
|
}));
|
|
71437
71496
|
const projectInitialized = projectFiles.some((f) => f.exists);
|
|
71438
71497
|
const hosts = detectAgentHosts();
|
|
@@ -71447,8 +71506,8 @@ async function runDiagnostics() {
|
|
|
71447
71506
|
} catch (err) {
|
|
71448
71507
|
if (!(err instanceof ComposerResolveError)) throw err;
|
|
71449
71508
|
}
|
|
71450
|
-
const sceneProjectInCwd =
|
|
71451
|
-
const skillInstalled =
|
|
71509
|
+
const sceneProjectInCwd = existsSync36(resolve50(cwd, "STORYBOARD.md"));
|
|
71510
|
+
const skillInstalled = existsSync36(resolve50(cwd, "SKILL.md"));
|
|
71452
71511
|
return {
|
|
71453
71512
|
system: {
|
|
71454
71513
|
node: { version: nodeVersion, ok: true },
|
|
@@ -71474,7 +71533,7 @@ async function runDiagnostics() {
|
|
|
71474
71533
|
};
|
|
71475
71534
|
}
|
|
71476
71535
|
function printReport(results, opts = { verbose: false }) {
|
|
71477
|
-
const { verbose } = opts;
|
|
71536
|
+
const { verbose, program: program3 } = opts;
|
|
71478
71537
|
console.log();
|
|
71479
71538
|
console.log(source_default.bold(" System"));
|
|
71480
71539
|
const nodeIcon = results.system.node.ok ? source_default.green("OK") : source_default.red("MISSING");
|
|
@@ -71611,12 +71670,40 @@ function printReport(results, opts = { verbose: false }) {
|
|
|
71611
71670
|
console.log(
|
|
71612
71671
|
source_default.dim(` Full command catalog: vibe schema --list`)
|
|
71613
71672
|
);
|
|
71673
|
+
if (program3) {
|
|
71674
|
+
const tierCounts = countCostTiers(program3);
|
|
71675
|
+
const total = tierCounts.free + tierCounts.low + tierCounts.high + tierCounts["very-high"];
|
|
71676
|
+
if (total > 0) {
|
|
71677
|
+
const parts = [
|
|
71678
|
+
`${TIER_COLOR.free(`${tierCounts.free} free`)}`,
|
|
71679
|
+
`${TIER_COLOR.low(`${tierCounts.low} low`)}`,
|
|
71680
|
+
`${TIER_COLOR.high(`${tierCounts.high} high`)}`,
|
|
71681
|
+
`${TIER_COLOR["very-high"](`${tierCounts["very-high"]} very-high`)}`
|
|
71682
|
+
];
|
|
71683
|
+
console.log(source_default.dim(` Cost mix:`) + ` ${parts.join(source_default.dim(", "))}`);
|
|
71684
|
+
}
|
|
71685
|
+
}
|
|
71614
71686
|
const nextStep = pickNextStep(results, missing.length > 0);
|
|
71615
71687
|
if (nextStep) {
|
|
71616
71688
|
console.log(source_default.dim(` ${nextStep}`));
|
|
71617
71689
|
}
|
|
71618
71690
|
console.log();
|
|
71619
71691
|
}
|
|
71692
|
+
function countCostTiers(program3) {
|
|
71693
|
+
const counts = {
|
|
71694
|
+
"free": 0,
|
|
71695
|
+
"low": 0,
|
|
71696
|
+
"high": 0,
|
|
71697
|
+
"very-high": 0
|
|
71698
|
+
};
|
|
71699
|
+
const walk = (cmd) => {
|
|
71700
|
+
const tier = getCostTier(cmd);
|
|
71701
|
+
if (tier) counts[tier]++;
|
|
71702
|
+
for (const child of cmd.commands) walk(child);
|
|
71703
|
+
};
|
|
71704
|
+
for (const top of program3.commands) walk(top);
|
|
71705
|
+
return counts;
|
|
71706
|
+
}
|
|
71620
71707
|
async function runLiveKeyTests(results) {
|
|
71621
71708
|
console.log();
|
|
71622
71709
|
console.log(source_default.bold(" Live key tests"));
|
|
@@ -71669,7 +71756,7 @@ init_detect();
|
|
|
71669
71756
|
init_ai_edit();
|
|
71670
71757
|
init_output();
|
|
71671
71758
|
import { resolve as resolve51 } from "node:path";
|
|
71672
|
-
import { existsSync as
|
|
71759
|
+
import { existsSync as existsSync37 } from "node:fs";
|
|
71673
71760
|
import { mkdir as mkdir21, rm as rm3 } from "node:fs/promises";
|
|
71674
71761
|
var DEMO_DIR = resolve51(process.cwd(), ".vibeframe-demo");
|
|
71675
71762
|
async function generateTestVideo(outputPath) {
|
|
@@ -71700,7 +71787,7 @@ async function generateTestVideo(outputPath) {
|
|
|
71700
71787
|
"-y",
|
|
71701
71788
|
outputPath
|
|
71702
71789
|
], { timeout: 3e4, maxBuffer: 50 * 1024 * 1024 });
|
|
71703
|
-
return
|
|
71790
|
+
return existsSync37(outputPath);
|
|
71704
71791
|
} catch {
|
|
71705
71792
|
try {
|
|
71706
71793
|
await execSafe("ffmpeg", [
|
|
@@ -71726,7 +71813,7 @@ async function generateTestVideo(outputPath) {
|
|
|
71726
71813
|
"-y",
|
|
71727
71814
|
outputPath
|
|
71728
71815
|
], { timeout: 3e4, maxBuffer: 50 * 1024 * 1024 });
|
|
71729
|
-
return
|
|
71816
|
+
return existsSync37(outputPath);
|
|
71730
71817
|
} catch {
|
|
71731
71818
|
return false;
|
|
71732
71819
|
}
|
|
@@ -72006,18 +72093,27 @@ Run 'vibe schema run' for structured parameter info.
|
|
|
72006
72093
|
} else {
|
|
72007
72094
|
console.log(source_default.bold(" Execution Plan:"));
|
|
72008
72095
|
console.log();
|
|
72096
|
+
let totalMax = 0;
|
|
72009
72097
|
for (let i = 0; i < result2.steps.length; i++) {
|
|
72010
72098
|
const step = result2.steps[i];
|
|
72011
72099
|
const est = step.data?.estimatedCost;
|
|
72100
|
+
if (typeof est === "string") {
|
|
72101
|
+
const m = est.match(/\$([\d.]+)/);
|
|
72102
|
+
if (m) totalMax += parseFloat(m[1]);
|
|
72103
|
+
}
|
|
72012
72104
|
const costTag = est ? source_default.dim(` ~${est}`) : "";
|
|
72013
72105
|
console.log(` ${source_default.dim(`${i + 1}.`)} ${source_default.bold(step.id)} ${source_default.dim(`\u2192 ${step.action}`)}${costTag}`);
|
|
72014
72106
|
}
|
|
72015
|
-
if (
|
|
72107
|
+
if (totalMax > 0) {
|
|
72016
72108
|
console.log();
|
|
72017
|
-
console.log(source_default.dim(` Total upper-bound: $${
|
|
72109
|
+
console.log(source_default.dim(` Total upper-bound: $${totalMax.toFixed(2)}`) + source_default.dim(` (sum of per-step ceilings)`));
|
|
72110
|
+
}
|
|
72111
|
+
if (result2.budget) {
|
|
72018
72112
|
if (result2.budget.abortedBy) {
|
|
72019
72113
|
console.log(source_default.yellow(` \u26A0 Budget ceiling exceeded (${result2.budget.abortedBy}) \u2014 execution will abort.`));
|
|
72020
72114
|
}
|
|
72115
|
+
} else if (totalMax > 0) {
|
|
72116
|
+
console.log(source_default.dim(` Tip: cap with --budget-usd ${Math.ceil(totalMax)} to abort if cost exceeds the estimate.`));
|
|
72021
72117
|
}
|
|
72022
72118
|
console.log();
|
|
72023
72119
|
console.log(source_default.dim(" Run without --dry-run to execute."));
|
|
@@ -72667,30 +72763,20 @@ init_tty();
|
|
|
72667
72763
|
init_api_key();
|
|
72668
72764
|
init_output();
|
|
72669
72765
|
async function promptConfirm2(toolName, args, cost) {
|
|
72670
|
-
const
|
|
72671
|
-
const
|
|
72672
|
-
|
|
72673
|
-
|
|
72674
|
-
|
|
72675
|
-
|
|
72676
|
-
|
|
72677
|
-
|
|
72678
|
-
|
|
72679
|
-
|
|
72680
|
-
|
|
72681
|
-
|
|
72682
|
-
|
|
72683
|
-
|
|
72684
|
-
"very-high": source_default.red
|
|
72685
|
-
};
|
|
72686
|
-
const costBadge = cost ? ` ${tierColor[cost](`[${cost.toUpperCase()}]`)}` : "";
|
|
72687
|
-
console.log(source_default.yellow(`Execute ${source_default.bold(toolName)}?${costBadge}`));
|
|
72688
|
-
console.log(source_default.dim(argsStr));
|
|
72689
|
-
rl.question(source_default.cyan("(y/n): "), (answer) => {
|
|
72690
|
-
rl.close();
|
|
72691
|
-
resolve64(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
|
|
72692
|
-
});
|
|
72693
|
-
});
|
|
72766
|
+
const argsStr = JSON.stringify(args, null, 2);
|
|
72767
|
+
const tierColor = {
|
|
72768
|
+
"free": source_default.green,
|
|
72769
|
+
"low": source_default.cyan,
|
|
72770
|
+
"medium": source_default.yellow,
|
|
72771
|
+
"high": source_default.yellow,
|
|
72772
|
+
"very-high": source_default.red
|
|
72773
|
+
};
|
|
72774
|
+
const costBadge = cost ? ` ${tierColor[cost](`[${cost.toUpperCase()}]`)}` : "";
|
|
72775
|
+
console.log();
|
|
72776
|
+
console.log(source_default.yellow(`Execute ${source_default.bold(toolName)}?${costBadge}`));
|
|
72777
|
+
console.log(source_default.dim(argsStr));
|
|
72778
|
+
const defaultYes = cost !== "very-high";
|
|
72779
|
+
return promptConfirm("", defaultYes);
|
|
72694
72780
|
}
|
|
72695
72781
|
async function startAgent(options = {}) {
|
|
72696
72782
|
const isNonInteractive = !!options.input;
|
|
@@ -72836,6 +72922,11 @@ async function startAgent(options = {}) {
|
|
|
72836
72922
|
}
|
|
72837
72923
|
console.log();
|
|
72838
72924
|
console.log(source_default.dim(`Total: ${tools.length} tools`));
|
|
72925
|
+
const spent = agent.getCumulativeUsd();
|
|
72926
|
+
if (spent > 0 || budgetUsd !== void 0) {
|
|
72927
|
+
const budgetStr = budgetUsd !== void 0 ? ` / $${budgetUsd.toFixed(2)} cap` : "";
|
|
72928
|
+
console.log(source_default.dim(`Spent (tier-estimated): $${spent.toFixed(2)}${budgetStr}`));
|
|
72929
|
+
}
|
|
72839
72930
|
console.log();
|
|
72840
72931
|
rl.prompt();
|
|
72841
72932
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeframe/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.87.0",
|
|
4
4
|
"description": "VibeFrame CLI - natural language video editing from the terminal",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
@@ -183,8 +183,8 @@
|
|
|
183
183
|
"tsx": "^4.21.0",
|
|
184
184
|
"typescript": "^5.3.3",
|
|
185
185
|
"vitest": "^1.2.2",
|
|
186
|
-
"@vibeframe/ai-providers": "0.
|
|
187
|
-
"@vibeframe/core": "0.
|
|
186
|
+
"@vibeframe/ai-providers": "0.87.0",
|
|
187
|
+
"@vibeframe/core": "0.87.0"
|
|
188
188
|
},
|
|
189
189
|
"engines": {
|
|
190
190
|
"node": ">=20"
|