@vibeframe/cli 0.96.0 → 0.96.4
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 +133 -21
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -24528,7 +24528,7 @@ var init_fal = __esm({
|
|
|
24528
24528
|
displayName: "Seedance 2.0",
|
|
24529
24529
|
gateway: "fal.ai",
|
|
24530
24530
|
// `fal` is a deprecated v0.x alias kept so existing scripts keep working.
|
|
24531
|
-
//
|
|
24531
|
+
// Review this alias at the 1.0 cut.
|
|
24532
24532
|
aliases: ["fal"],
|
|
24533
24533
|
models: ["seedance-2.0", "seedance-2.0-fast"],
|
|
24534
24534
|
capabilities: ["text-to-video", "image-to-video", "native-audio"],
|
|
@@ -25847,8 +25847,8 @@ async function isConfigured() {
|
|
|
25847
25847
|
}
|
|
25848
25848
|
return false;
|
|
25849
25849
|
}
|
|
25850
|
-
async function getApiKeyFromConfig(providerKey) {
|
|
25851
|
-
const config2 = await loadConfig();
|
|
25850
|
+
async function getApiKeyFromConfig(providerKey, options = {}) {
|
|
25851
|
+
const config2 = await loadConfig({ cwd: options.cwd });
|
|
25852
25852
|
if (config2?.providers[providerKey]) {
|
|
25853
25853
|
return config2.providers[providerKey];
|
|
25854
25854
|
}
|
|
@@ -28827,6 +28827,20 @@ Requirements (non-negotiable):
|
|
|
28827
28827
|
This is the #2 source of "text disappears mid-beat" bugs after \`.clip\` sizing.
|
|
28828
28828
|
- Timed children inside the composition have \`class="clip"\` plus
|
|
28829
28829
|
\`data-start\`, \`data-duration\`, \`data-track-index\`.
|
|
28830
|
+
- If the beat cues include \`backdrop\`, the build step has already generated
|
|
28831
|
+
\`assets/backdrop-${ctx.beat.id}.png\`. Use that local file as the full-frame
|
|
28832
|
+
visual backdrop. Do NOT replace it with abstract CSS, an external stock image,
|
|
28833
|
+
Unsplash, a CDN URL, or a remote placeholder.
|
|
28834
|
+
- The exact backdrop path string is \`assets/backdrop-${ctx.beat.id}.png\`.
|
|
28835
|
+
Do NOT prefix it with \`../\` or \`./\`: sub-composition fragments are mounted
|
|
28836
|
+
from the project root \`index.html\`, so \`../assets/...\` resolves outside the
|
|
28837
|
+
project and renders black.
|
|
28838
|
+
- Do not import external font or image URLs. Use the project DESIGN.md font
|
|
28839
|
+
choice when explicit; otherwise use \`Inter\`, which is available in the
|
|
28840
|
+
deterministic render font map.
|
|
28841
|
+
- If the beat cues include \`narration\`, do not embed an \`<audio>\` tag in the
|
|
28842
|
+
scene fragment. The root timeline wires \`assets/narration-${ctx.beat.id}.wav\`
|
|
28843
|
+
or \`assets/narration-${ctx.beat.id}.mp3\` separately.
|
|
28830
28844
|
- **\`.clip\` elements get visibility control from the framework but NO
|
|
28831
28845
|
sizing.** Always give \`.clip\` explicit fill via CSS:
|
|
28832
28846
|
\`{ position: absolute; inset: 0; }\` (or equivalent
|
|
@@ -29027,6 +29041,18 @@ async function composeBeatWithRetry(ctx, overrides) {
|
|
|
29027
29041
|
${formatLintFeedback(lint2.findings)}`
|
|
29028
29042
|
);
|
|
29029
29043
|
}
|
|
29044
|
+
async function resolveComposerConfigAware(explicit, cwd) {
|
|
29045
|
+
if (explicit) {
|
|
29046
|
+
const configKey = await getApiKeyFromConfig(CONFIG_PROVIDER_BY_COMPOSER[explicit], { cwd });
|
|
29047
|
+
if (configKey) return { provider: explicit, apiKey: configKey };
|
|
29048
|
+
return resolveComposer(explicit);
|
|
29049
|
+
}
|
|
29050
|
+
for (const candidate of ["claude", "gemini", "openai"]) {
|
|
29051
|
+
const configKey = await getApiKeyFromConfig(CONFIG_PROVIDER_BY_COMPOSER[candidate], { cwd });
|
|
29052
|
+
if (configKey) return { provider: candidate, apiKey: configKey };
|
|
29053
|
+
}
|
|
29054
|
+
return resolveComposer();
|
|
29055
|
+
}
|
|
29030
29056
|
async function executeComposeScenesWithSkills(params, outputDir, overrides) {
|
|
29031
29057
|
const projectRoot = params.project ? resolve9(outputDir, params.project) : resolve9(outputDir);
|
|
29032
29058
|
const designPath = resolve9(projectRoot, params.design ?? "DESIGN.md");
|
|
@@ -29051,7 +29077,7 @@ async function executeComposeScenesWithSkills(params, outputDir, overrides) {
|
|
|
29051
29077
|
let provider;
|
|
29052
29078
|
let apiKey;
|
|
29053
29079
|
try {
|
|
29054
|
-
const resolved =
|
|
29080
|
+
const resolved = await resolveComposerConfigAware(params.composer, projectRoot);
|
|
29055
29081
|
provider = resolved.provider;
|
|
29056
29082
|
apiKey = resolved.apiKey;
|
|
29057
29083
|
} catch {
|
|
@@ -29156,7 +29182,7 @@ ${failures.map((f) => ` - ${f.beatId}: ${f.error}`).join("\n")}`,
|
|
|
29156
29182
|
data: aggregateData
|
|
29157
29183
|
};
|
|
29158
29184
|
}
|
|
29159
|
-
var MODEL_SETTINGS_BY_PROVIDER, ComposeBeatError, defaultCallLLM;
|
|
29185
|
+
var MODEL_SETTINGS_BY_PROVIDER, ComposeBeatError, defaultCallLLM, CONFIG_PROVIDER_BY_COMPOSER;
|
|
29160
29186
|
var init_compose_scenes_skills = __esm({
|
|
29161
29187
|
"src/commands/_shared/compose-scenes-skills.ts"() {
|
|
29162
29188
|
"use strict";
|
|
@@ -29164,6 +29190,7 @@ var init_compose_scenes_skills = __esm({
|
|
|
29164
29190
|
init_scene_lint();
|
|
29165
29191
|
init_storyboard_parse();
|
|
29166
29192
|
init_composer_resolve();
|
|
29193
|
+
init_config();
|
|
29167
29194
|
MODEL_SETTINGS_BY_PROVIDER = {
|
|
29168
29195
|
// Anthropic Claude Sonnet 4.6 — v0.69 baseline. ~9 s/beat, $3/$15 per MTok.
|
|
29169
29196
|
claude: {
|
|
@@ -29254,6 +29281,11 @@ var init_compose_scenes_skills = __esm({
|
|
|
29254
29281
|
outputTokens: usage?.candidatesTokenCount ?? 0
|
|
29255
29282
|
};
|
|
29256
29283
|
};
|
|
29284
|
+
CONFIG_PROVIDER_BY_COMPOSER = {
|
|
29285
|
+
claude: "anthropic",
|
|
29286
|
+
openai: "openai",
|
|
29287
|
+
gemini: "google"
|
|
29288
|
+
};
|
|
29257
29289
|
}
|
|
29258
29290
|
});
|
|
29259
29291
|
|
|
@@ -52528,9 +52560,7 @@ overlay, etc.) \u2014 useful at the tail of a pipeline.
|
|
|
52528
52560
|
|
|
52529
52561
|
The CLI has three orchestrating commands that coordinate other primitives:
|
|
52530
52562
|
\`vibe agent\`, \`vibe build\`, \`vibe run\`. New users routinely ask which one
|
|
52531
|
-
they want for a given task.
|
|
52532
|
-
[\`docs/cli-architecture.md\`](../../../docs/cli-architecture.md); this
|
|
52533
|
-
guide is the operator-facing summary.
|
|
52563
|
+
they want for a given task. This guide is the operator-facing summary.
|
|
52534
52564
|
|
|
52535
52565
|
If you already use Claude Code, Codex, Cursor, Aider, Gemini CLI, OpenCode,
|
|
52536
52566
|
or another coding agent, let that host drive \`vibe\` directly through shell
|
|
@@ -53448,7 +53478,7 @@ async function dispatchBackdrop(beat, ctx) {
|
|
|
53448
53478
|
return { status: "cached", path: rel };
|
|
53449
53479
|
}
|
|
53450
53480
|
loadSceneBuildEnv(ctx.projectDir);
|
|
53451
|
-
const apiKey = process.env.OPENAI_API_KEY ?? "";
|
|
53481
|
+
const apiKey = await getApiKeyFromConfig("openai", { cwd: ctx.projectDir }) ?? process.env.OPENAI_API_KEY ?? "";
|
|
53452
53482
|
if (!apiKey) {
|
|
53453
53483
|
const error = "OPENAI_API_KEY not set \u2014 cannot dispatch backdrop";
|
|
53454
53484
|
ctx.onProgress({ type: "backdrop-failed", beatId: beat.id, error });
|
|
@@ -53580,6 +53610,7 @@ var init_scene_build = __esm({
|
|
|
53580
53610
|
init_compose_scenes_skills();
|
|
53581
53611
|
init_compose_prompts();
|
|
53582
53612
|
init_agent_host_detect();
|
|
53613
|
+
init_config();
|
|
53583
53614
|
init_scene_render();
|
|
53584
53615
|
init_storyboard_parse();
|
|
53585
53616
|
init_scene_project();
|
|
@@ -54360,25 +54391,102 @@ function getOutput(params, outputDir, defaultName) {
|
|
|
54360
54391
|
}
|
|
54361
54392
|
return resolve57(outputDir, defaultName);
|
|
54362
54393
|
}
|
|
54394
|
+
function stringParam(value) {
|
|
54395
|
+
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
54396
|
+
}
|
|
54397
|
+
function numberParam2(value) {
|
|
54398
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : void 0;
|
|
54399
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
54400
|
+
const n = Number(value);
|
|
54401
|
+
return Number.isFinite(n) ? n : void 0;
|
|
54402
|
+
}
|
|
54403
|
+
return void 0;
|
|
54404
|
+
}
|
|
54405
|
+
async function resolvePipelineImageProvider(provider) {
|
|
54406
|
+
const explicit = stringParam(provider)?.toLowerCase();
|
|
54407
|
+
if (explicit) return explicit;
|
|
54408
|
+
await loadProviderDefaults();
|
|
54409
|
+
return resolveProvider("image")?.name ?? "gemini";
|
|
54410
|
+
}
|
|
54411
|
+
async function resolvePipelineVideoProvider(provider) {
|
|
54412
|
+
const explicit = stringParam(provider)?.toLowerCase();
|
|
54413
|
+
if (explicit === "fal") return "seedance";
|
|
54414
|
+
if (explicit) return explicit;
|
|
54415
|
+
await loadProviderDefaults();
|
|
54416
|
+
return resolveProvider("video")?.name ?? "grok";
|
|
54417
|
+
}
|
|
54418
|
+
function providerKeyForImage(provider) {
|
|
54419
|
+
switch (provider) {
|
|
54420
|
+
case "openai":
|
|
54421
|
+
return "openai";
|
|
54422
|
+
case "gemini":
|
|
54423
|
+
return "google";
|
|
54424
|
+
case "grok":
|
|
54425
|
+
return "xai";
|
|
54426
|
+
default:
|
|
54427
|
+
return void 0;
|
|
54428
|
+
}
|
|
54429
|
+
}
|
|
54430
|
+
function providerKeyForVideo(provider) {
|
|
54431
|
+
switch (provider) {
|
|
54432
|
+
case "seedance":
|
|
54433
|
+
case "fal":
|
|
54434
|
+
return "fal";
|
|
54435
|
+
case "grok":
|
|
54436
|
+
return "xai";
|
|
54437
|
+
case "kling":
|
|
54438
|
+
return "kling";
|
|
54439
|
+
case "runway":
|
|
54440
|
+
return "runway";
|
|
54441
|
+
case "veo":
|
|
54442
|
+
return "google";
|
|
54443
|
+
default:
|
|
54444
|
+
return void 0;
|
|
54445
|
+
}
|
|
54446
|
+
}
|
|
54447
|
+
async function apiKeyForProvider(providerKey) {
|
|
54448
|
+
return providerKey ? getApiKeyFromConfig(providerKey) : void 0;
|
|
54449
|
+
}
|
|
54363
54450
|
async function ensureActionsRegistered() {
|
|
54364
54451
|
if (Object.keys(ACTION_HANDLERS).length > 0) return;
|
|
54365
54452
|
registerAction("generate-image", async (params, outputDir) => {
|
|
54366
54453
|
const { executeImageGenerate: executeImageGenerate2 } = await Promise.resolve().then(() => (init_ai_image(), ai_image_exports));
|
|
54367
54454
|
const output = getOutput(params, outputDir, "image.png");
|
|
54368
|
-
const
|
|
54455
|
+
const provider = await resolvePipelineImageProvider(params.provider);
|
|
54456
|
+
const r = await executeImageGenerate2({
|
|
54457
|
+
prompt: params.prompt,
|
|
54458
|
+
provider,
|
|
54459
|
+
output,
|
|
54460
|
+
model: stringParam(params.model),
|
|
54461
|
+
ratio: stringParam(params.ratio),
|
|
54462
|
+
size: stringParam(params.size),
|
|
54463
|
+
quality: stringParam(params.quality),
|
|
54464
|
+
style: stringParam(params.style),
|
|
54465
|
+
count: numberParam2(params.count),
|
|
54466
|
+
apiKey: await apiKeyForProvider(providerKeyForImage(provider))
|
|
54467
|
+
});
|
|
54369
54468
|
return { id: "", action: "generate-image", success: r.success, output: r.outputPath, data: { provider: r.provider, model: r.model }, error: r.error };
|
|
54370
54469
|
});
|
|
54371
54470
|
registerAction("generate-video", async (params, outputDir) => {
|
|
54372
54471
|
const { executeVideoGenerate: executeVideoGenerate2 } = await Promise.resolve().then(() => (init_ai_video(), ai_video_exports));
|
|
54373
54472
|
const output = getOutput(params, outputDir, "video.mp4");
|
|
54473
|
+
const provider = await resolvePipelineVideoProvider(params.provider);
|
|
54374
54474
|
const r = await executeVideoGenerate2({
|
|
54375
54475
|
prompt: params.prompt,
|
|
54376
|
-
provider
|
|
54377
|
-
image: params.image,
|
|
54378
|
-
duration: params.duration,
|
|
54379
|
-
ratio: params.ratio,
|
|
54476
|
+
provider,
|
|
54477
|
+
image: stringParam(params.image),
|
|
54478
|
+
duration: numberParam2(params.duration),
|
|
54479
|
+
ratio: stringParam(params.ratio),
|
|
54480
|
+
seed: numberParam2(params.seed),
|
|
54481
|
+
mode: stringParam(params.mode),
|
|
54482
|
+
negative: stringParam(params.negative),
|
|
54483
|
+
resolution: stringParam(params.resolution),
|
|
54484
|
+
veoModel: stringParam(params.veoModel),
|
|
54485
|
+
runwayModel: stringParam(params.runwayModel),
|
|
54486
|
+
seedanceModel: stringParam(params.seedanceModel),
|
|
54380
54487
|
output,
|
|
54381
|
-
wait: true
|
|
54488
|
+
wait: true,
|
|
54489
|
+
apiKey: await apiKeyForProvider(providerKeyForVideo(provider))
|
|
54382
54490
|
});
|
|
54383
54491
|
return { id: "", action: "generate-video", success: r.success, output: r.outputPath || r.videoUrl, data: { taskId: r.taskId, provider: r.provider, videoUrl: r.videoUrl }, error: r.error };
|
|
54384
54492
|
});
|
|
@@ -54782,6 +54890,8 @@ var init_executor = __esm({
|
|
|
54782
54890
|
import_yaml8 = __toESM(require_dist(), 1);
|
|
54783
54891
|
init_resolver();
|
|
54784
54892
|
init_output();
|
|
54893
|
+
init_config();
|
|
54894
|
+
init_provider_resolver();
|
|
54785
54895
|
ACTION_METADATA = {
|
|
54786
54896
|
"generate-image": { id: "generate-image", title: "Generate image", category: "generate", command: "generate image", outputs: ["image"] },
|
|
54787
54897
|
"generate-video": { id: "generate-video", title: "Generate video", category: "generate", command: "generate video", outputs: ["video"], requiredKeys: ["provider-dependent"] },
|
|
@@ -64048,7 +64158,7 @@ init_source();
|
|
|
64048
64158
|
// package.json
|
|
64049
64159
|
var package_default = {
|
|
64050
64160
|
name: "@vibeframe/cli",
|
|
64051
|
-
version: "0.96.
|
|
64161
|
+
version: "0.96.4",
|
|
64052
64162
|
description: "VibeFrame CLI - natural language video editing from the terminal",
|
|
64053
64163
|
private: false,
|
|
64054
64164
|
license: "MIT",
|
|
@@ -66476,7 +66586,8 @@ function inferType(opt, name) {
|
|
|
66476
66586
|
"<ms>",
|
|
66477
66587
|
"<n>",
|
|
66478
66588
|
"<count>",
|
|
66479
|
-
"<duration>"
|
|
66589
|
+
"<duration>",
|
|
66590
|
+
"<usd>"
|
|
66480
66591
|
];
|
|
66481
66592
|
if (numericFlags.some((f) => opt.flags.includes(f))) {
|
|
66482
66593
|
return "number";
|
|
@@ -66497,7 +66608,8 @@ function inferType(opt, name) {
|
|
|
66497
66608
|
"fps",
|
|
66498
66609
|
"bitrate",
|
|
66499
66610
|
"width",
|
|
66500
|
-
"height"
|
|
66611
|
+
"height",
|
|
66612
|
+
"budgetUsd"
|
|
66501
66613
|
];
|
|
66502
66614
|
if (numericNames.includes(name)) {
|
|
66503
66615
|
return "number";
|
|
@@ -74750,8 +74862,8 @@ async function startAgent(options = {}) {
|
|
|
74750
74862
|
const isNonInteractive = !!options.input;
|
|
74751
74863
|
const confirmAlways = options.confirm || false;
|
|
74752
74864
|
const noConfirm = options.noConfirm || false;
|
|
74753
|
-
const budgetUsd = options.budgetUsd ?
|
|
74754
|
-
if (budgetUsd !== void 0 && (Number.
|
|
74865
|
+
const budgetUsd = options.budgetUsd !== void 0 ? Number(options.budgetUsd) : void 0;
|
|
74866
|
+
if (budgetUsd !== void 0 && (!Number.isFinite(budgetUsd) || budgetUsd < 0)) {
|
|
74755
74867
|
exitWithError(generalError(`Invalid --budget-usd: ${options.budgetUsd}`, "Must be a non-negative number (e.g., --budget-usd 5)"));
|
|
74756
74868
|
}
|
|
74757
74869
|
if (!isNonInteractive && !hasTTY()) {
|
|
@@ -74956,7 +75068,7 @@ async function startAgent(options = {}) {
|
|
|
74956
75068
|
rl.prompt();
|
|
74957
75069
|
});
|
|
74958
75070
|
}
|
|
74959
|
-
var agentCommand = new Command("agent").description("Optional built-in natural-language agent (fallback when no external coding agent is driving vibe)").option("-p, --provider <provider>", "LLM provider (openai, claude, gemini, ollama, xai, openrouter)", "openai").option("-m, --model <model>", "Model to use (provider-specific)").option("--project <path>", "Timeline file or directory to load").option("-v, --verbose", "Show verbose output including tool calls").option("--max-turns <n>", "Maximum turns per request", "10").option("-i, --input <query>", "Run a single query and exit (non-interactive)").option("-c, --confirm", "Confirm before every tool \u2014 broadens the default cost gate (paid only) to all calls").option("--no-confirm", "Disable all confirm prompts including the high/very-high cost gate (CI / automation)").option("--budget-usd <usd>", "Reject tool calls past this cumulative USD ceiling
|
|
75071
|
+
var agentCommand = new Command("agent").description("Optional built-in natural-language agent (fallback when no external coding agent is driving vibe)").option("-p, --provider <provider>", "LLM provider (openai, claude, gemini, ollama, xai, openrouter)", "openai").option("-m, --model <model>", "Model to use (provider-specific)").option("--project <path>", "Timeline file or directory to load").option("-v, --verbose", "Show verbose output including tool calls").option("--max-turns <n>", "Maximum turns per request", "10").option("-i, --input <query>", "Run a single query and exit (non-interactive)").option("-c, --confirm", "Confirm before every tool \u2014 broadens the default cost gate (paid only) to all calls").option("--no-confirm", "Disable all confirm prompts including the high/very-high cost gate (CI / automation)").option("--budget-usd <usd>", "Reject tool calls past this cumulative USD ceiling using conservative tier estimates", parseFloat).action(async (options) => {
|
|
74960
75072
|
await startAgent(options);
|
|
74961
75073
|
});
|
|
74962
75074
|
function getEnvVar(provider) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeframe/cli",
|
|
3
|
-
"version": "0.96.
|
|
3
|
+
"version": "0.96.4",
|
|
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/
|
|
187
|
-
"@vibeframe/
|
|
186
|
+
"@vibeframe/ai-providers": "0.96.4",
|
|
187
|
+
"@vibeframe/core": "0.96.4"
|
|
188
188
|
},
|
|
189
189
|
"engines": {
|
|
190
190
|
"node": ">=20"
|