@vibeframe/cli 0.115.0 → 0.115.2
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/build-cache-model.test.d.ts +1 -0
- package/dist/commands/_shared/build-cache.d.ts +6 -0
- package/dist/commands/_shared/build-plan.d.ts +2 -0
- package/dist/commands/_shared/footage-assemble.d.ts +166 -0
- package/dist/commands/_shared/footage-assemble.test.d.ts +1 -0
- package/dist/commands/_shared/scene-build.d.ts +26 -1
- package/dist/commands/_shared/storyboard-parse.d.ts +7 -1
- package/dist/commands/generate/video-cost.test.d.ts +1 -0
- package/dist/commands/generate/video.d.ts +19 -0
- package/dist/commands/output.d.ts +7 -0
- package/dist/index.js +1191 -531
- package/dist/tools/manifest/index.js +1379 -810
- package/dist/tools/manifest/scene.d.ts +3 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -7768,7 +7768,7 @@ function errorMessage(error) {
|
|
|
7768
7768
|
return error instanceof Error ? error.message : "Unknown error";
|
|
7769
7769
|
}
|
|
7770
7770
|
function sleep(ms) {
|
|
7771
|
-
return new Promise((
|
|
7771
|
+
return new Promise((resolve87) => setTimeout(resolve87, ms));
|
|
7772
7772
|
}
|
|
7773
7773
|
var ProviderHttpError;
|
|
7774
7774
|
var init_http = __esm({
|
|
@@ -11655,14 +11655,14 @@ async function loadKokoroRuntime() {
|
|
|
11655
11655
|
async function loadKokoroFromWorkspace(baseDir = process.cwd()) {
|
|
11656
11656
|
try {
|
|
11657
11657
|
const { readFile: readFile55 } = await import("node:fs/promises");
|
|
11658
|
-
const { join:
|
|
11658
|
+
const { join: join34, resolve: resolve87 } = await import("node:path");
|
|
11659
11659
|
const { pathToFileURL } = await import("node:url");
|
|
11660
|
-
const pkgDir =
|
|
11661
|
-
const pkg = JSON.parse(await readFile55(
|
|
11660
|
+
const pkgDir = resolve87(baseDir, "node_modules", "kokoro-js");
|
|
11661
|
+
const pkg = JSON.parse(await readFile55(join34(pkgDir, "package.json"), "utf-8"));
|
|
11662
11662
|
const entry = pkg.exports?.node?.import ?? pkg.exports?.default ?? pkg.module ?? pkg.main;
|
|
11663
11663
|
if (!entry)
|
|
11664
11664
|
return null;
|
|
11665
|
-
const mod = await import(pathToFileURL(
|
|
11665
|
+
const mod = await import(pathToFileURL(join34(pkgDir, entry)).href);
|
|
11666
11666
|
return mod.KokoroTTS ?? null;
|
|
11667
11667
|
} catch {
|
|
11668
11668
|
return null;
|
|
@@ -11673,20 +11673,20 @@ async function loadBundledKokoroRuntime(runtimeDir = process.env.VIBE_KOKORO_RUN
|
|
|
11673
11673
|
if (!base)
|
|
11674
11674
|
return null;
|
|
11675
11675
|
try {
|
|
11676
|
-
const { readFile: readFile55, writeFile:
|
|
11677
|
-
const { join:
|
|
11676
|
+
const { readFile: readFile55, writeFile: writeFile57, mkdir: mkdir31 } = await import("node:fs/promises");
|
|
11677
|
+
const { join: join34, resolve: resolve87 } = await import("node:path");
|
|
11678
11678
|
const { pathToFileURL } = await import("node:url");
|
|
11679
11679
|
const { homedir: homedir8 } = await import("node:os");
|
|
11680
|
-
const transformersDir =
|
|
11681
|
-
const ortDistDir =
|
|
11682
|
-
const transformers = await import(pathToFileURL(
|
|
11683
|
-
const cacheRoot =
|
|
11680
|
+
const transformersDir = resolve87(base, "node_modules", "@huggingface", "transformers");
|
|
11681
|
+
const ortDistDir = resolve87(base, "node_modules", "onnxruntime-web", "dist");
|
|
11682
|
+
const transformers = await import(pathToFileURL(join34(transformersDir, "dist", "transformers.web.js")).href);
|
|
11683
|
+
const cacheRoot = join34(homedir8(), ".cache", "vibeframe", "models");
|
|
11684
11684
|
transformers.env.allowLocalModels = false;
|
|
11685
11685
|
transformers.env.useCustomCache = true;
|
|
11686
11686
|
transformers.env.customCache = {
|
|
11687
11687
|
async match(key) {
|
|
11688
11688
|
try {
|
|
11689
|
-
return new Response(await readFile55(
|
|
11689
|
+
return new Response(await readFile55(join34(cacheRoot, encodeURIComponent(String(key)))));
|
|
11690
11690
|
} catch {
|
|
11691
11691
|
return void 0;
|
|
11692
11692
|
}
|
|
@@ -11694,8 +11694,8 @@ async function loadBundledKokoroRuntime(runtimeDir = process.env.VIBE_KOKORO_RUN
|
|
|
11694
11694
|
async put(key, response) {
|
|
11695
11695
|
try {
|
|
11696
11696
|
const buf = Buffer.from(await response.arrayBuffer());
|
|
11697
|
-
await
|
|
11698
|
-
await
|
|
11697
|
+
await mkdir31(cacheRoot, { recursive: true });
|
|
11698
|
+
await writeFile57(join34(cacheRoot, encodeURIComponent(String(key))), buf);
|
|
11699
11699
|
} catch {
|
|
11700
11700
|
}
|
|
11701
11701
|
}
|
|
@@ -12470,7 +12470,7 @@ var init_RunwayProvider = __esm({
|
|
|
12470
12470
|
* Sleep helper
|
|
12471
12471
|
*/
|
|
12472
12472
|
sleep(ms) {
|
|
12473
|
-
return new Promise((
|
|
12473
|
+
return new Promise((resolve87) => setTimeout(resolve87, ms));
|
|
12474
12474
|
}
|
|
12475
12475
|
};
|
|
12476
12476
|
RunwayProvider.API_VERSION = "2024-11-06";
|
|
@@ -12911,7 +12911,7 @@ var init_KlingProvider = __esm({
|
|
|
12911
12911
|
* Sleep helper
|
|
12912
12912
|
*/
|
|
12913
12913
|
sleep(ms) {
|
|
12914
|
-
return new Promise((
|
|
12914
|
+
return new Promise((resolve87) => setTimeout(resolve87, ms));
|
|
12915
12915
|
}
|
|
12916
12916
|
};
|
|
12917
12917
|
klingProvider = new KlingProvider();
|
|
@@ -13229,7 +13229,7 @@ var init_GrokProvider = __esm({
|
|
|
13229
13229
|
}
|
|
13230
13230
|
}
|
|
13231
13231
|
sleep(ms) {
|
|
13232
|
-
return new Promise((
|
|
13232
|
+
return new Promise((resolve87) => setTimeout(resolve87, ms));
|
|
13233
13233
|
}
|
|
13234
13234
|
};
|
|
13235
13235
|
grokProvider = new GrokProvider();
|
|
@@ -13264,11 +13264,11 @@ var require_middleware = __commonJS({
|
|
|
13264
13264
|
"use strict";
|
|
13265
13265
|
var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
|
|
13266
13266
|
function adopt(value) {
|
|
13267
|
-
return value instanceof P ? value : new P(function(
|
|
13268
|
-
|
|
13267
|
+
return value instanceof P ? value : new P(function(resolve87) {
|
|
13268
|
+
resolve87(value);
|
|
13269
13269
|
});
|
|
13270
13270
|
}
|
|
13271
|
-
return new (P || (P = Promise))(function(
|
|
13271
|
+
return new (P || (P = Promise))(function(resolve87, reject) {
|
|
13272
13272
|
function fulfilled(value) {
|
|
13273
13273
|
try {
|
|
13274
13274
|
step(generator.next(value));
|
|
@@ -13284,7 +13284,7 @@ var require_middleware = __commonJS({
|
|
|
13284
13284
|
}
|
|
13285
13285
|
}
|
|
13286
13286
|
function step(result) {
|
|
13287
|
-
result.done ?
|
|
13287
|
+
result.done ? resolve87(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
13288
13288
|
}
|
|
13289
13289
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
13290
13290
|
});
|
|
@@ -13369,11 +13369,11 @@ var require_response = __commonJS({
|
|
|
13369
13369
|
"use strict";
|
|
13370
13370
|
var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
|
|
13371
13371
|
function adopt(value) {
|
|
13372
|
-
return value instanceof P ? value : new P(function(
|
|
13373
|
-
|
|
13372
|
+
return value instanceof P ? value : new P(function(resolve87) {
|
|
13373
|
+
resolve87(value);
|
|
13374
13374
|
});
|
|
13375
13375
|
}
|
|
13376
|
-
return new (P || (P = Promise))(function(
|
|
13376
|
+
return new (P || (P = Promise))(function(resolve87, reject) {
|
|
13377
13377
|
function fulfilled(value) {
|
|
13378
13378
|
try {
|
|
13379
13379
|
step(generator.next(value));
|
|
@@ -13389,7 +13389,7 @@ var require_response = __commonJS({
|
|
|
13389
13389
|
}
|
|
13390
13390
|
}
|
|
13391
13391
|
function step(result) {
|
|
13392
|
-
result.done ?
|
|
13392
|
+
result.done ? resolve87(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
13393
13393
|
}
|
|
13394
13394
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
13395
13395
|
});
|
|
@@ -13496,11 +13496,11 @@ var require_utils = __commonJS({
|
|
|
13496
13496
|
"use strict";
|
|
13497
13497
|
var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
|
|
13498
13498
|
function adopt(value) {
|
|
13499
|
-
return value instanceof P ? value : new P(function(
|
|
13500
|
-
|
|
13499
|
+
return value instanceof P ? value : new P(function(resolve87) {
|
|
13500
|
+
resolve87(value);
|
|
13501
13501
|
});
|
|
13502
13502
|
}
|
|
13503
|
-
return new (P || (P = Promise))(function(
|
|
13503
|
+
return new (P || (P = Promise))(function(resolve87, reject) {
|
|
13504
13504
|
function fulfilled(value) {
|
|
13505
13505
|
try {
|
|
13506
13506
|
step(generator.next(value));
|
|
@@ -13516,7 +13516,7 @@ var require_utils = __commonJS({
|
|
|
13516
13516
|
}
|
|
13517
13517
|
}
|
|
13518
13518
|
function step(result) {
|
|
13519
|
-
result.done ?
|
|
13519
|
+
result.done ? resolve87(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
13520
13520
|
}
|
|
13521
13521
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
13522
13522
|
});
|
|
@@ -13609,7 +13609,7 @@ var require_utils = __commonJS({
|
|
|
13609
13609
|
}
|
|
13610
13610
|
function sleep3(ms) {
|
|
13611
13611
|
return __awaiter(this, void 0, void 0, function* () {
|
|
13612
|
-
return new Promise((
|
|
13612
|
+
return new Promise((resolve87) => setTimeout(resolve87, ms));
|
|
13613
13613
|
});
|
|
13614
13614
|
}
|
|
13615
13615
|
}
|
|
@@ -13621,11 +13621,11 @@ var require_retry = __commonJS({
|
|
|
13621
13621
|
"use strict";
|
|
13622
13622
|
var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
|
|
13623
13623
|
function adopt(value) {
|
|
13624
|
-
return value instanceof P ? value : new P(function(
|
|
13625
|
-
|
|
13624
|
+
return value instanceof P ? value : new P(function(resolve87) {
|
|
13625
|
+
resolve87(value);
|
|
13626
13626
|
});
|
|
13627
13627
|
}
|
|
13628
|
-
return new (P || (P = Promise))(function(
|
|
13628
|
+
return new (P || (P = Promise))(function(resolve87, reject) {
|
|
13629
13629
|
function fulfilled(value) {
|
|
13630
13630
|
try {
|
|
13631
13631
|
step(generator.next(value));
|
|
@@ -13641,7 +13641,7 @@ var require_retry = __commonJS({
|
|
|
13641
13641
|
}
|
|
13642
13642
|
}
|
|
13643
13643
|
function step(result) {
|
|
13644
|
-
result.done ?
|
|
13644
|
+
result.done ? resolve87(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
13645
13645
|
}
|
|
13646
13646
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
13647
13647
|
});
|
|
@@ -13848,11 +13848,11 @@ var require_request = __commonJS({
|
|
|
13848
13848
|
"use strict";
|
|
13849
13849
|
var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
|
|
13850
13850
|
function adopt(value) {
|
|
13851
|
-
return value instanceof P ? value : new P(function(
|
|
13852
|
-
|
|
13851
|
+
return value instanceof P ? value : new P(function(resolve87) {
|
|
13852
|
+
resolve87(value);
|
|
13853
13853
|
});
|
|
13854
13854
|
}
|
|
13855
|
-
return new (P || (P = Promise))(function(
|
|
13855
|
+
return new (P || (P = Promise))(function(resolve87, reject) {
|
|
13856
13856
|
function fulfilled(value) {
|
|
13857
13857
|
try {
|
|
13858
13858
|
step(generator.next(value));
|
|
@@ -13868,7 +13868,7 @@ var require_request = __commonJS({
|
|
|
13868
13868
|
}
|
|
13869
13869
|
}
|
|
13870
13870
|
function step(result) {
|
|
13871
|
-
result.done ?
|
|
13871
|
+
result.done ? resolve87(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
13872
13872
|
}
|
|
13873
13873
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
13874
13874
|
});
|
|
@@ -13955,11 +13955,11 @@ var require_storage = __commonJS({
|
|
|
13955
13955
|
"use strict";
|
|
13956
13956
|
var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
|
|
13957
13957
|
function adopt(value) {
|
|
13958
|
-
return value instanceof P ? value : new P(function(
|
|
13959
|
-
|
|
13958
|
+
return value instanceof P ? value : new P(function(resolve87) {
|
|
13959
|
+
resolve87(value);
|
|
13960
13960
|
});
|
|
13961
13961
|
}
|
|
13962
|
-
return new (P || (P = Promise))(function(
|
|
13962
|
+
return new (P || (P = Promise))(function(resolve87, reject) {
|
|
13963
13963
|
function fulfilled(value) {
|
|
13964
13964
|
try {
|
|
13965
13965
|
step(generator.next(value));
|
|
@@ -13975,7 +13975,7 @@ var require_storage = __commonJS({
|
|
|
13975
13975
|
}
|
|
13976
13976
|
}
|
|
13977
13977
|
function step(result) {
|
|
13978
|
-
result.done ?
|
|
13978
|
+
result.done ? resolve87(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
13979
13979
|
}
|
|
13980
13980
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
13981
13981
|
});
|
|
@@ -14303,11 +14303,11 @@ var require_auth = __commonJS({
|
|
|
14303
14303
|
"use strict";
|
|
14304
14304
|
var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
|
|
14305
14305
|
function adopt(value) {
|
|
14306
|
-
return value instanceof P ? value : new P(function(
|
|
14307
|
-
|
|
14306
|
+
return value instanceof P ? value : new P(function(resolve87) {
|
|
14307
|
+
resolve87(value);
|
|
14308
14308
|
});
|
|
14309
14309
|
}
|
|
14310
|
-
return new (P || (P = Promise))(function(
|
|
14310
|
+
return new (P || (P = Promise))(function(resolve87, reject) {
|
|
14311
14311
|
function fulfilled(value) {
|
|
14312
14312
|
try {
|
|
14313
14313
|
step(generator.next(value));
|
|
@@ -14323,7 +14323,7 @@ var require_auth = __commonJS({
|
|
|
14323
14323
|
}
|
|
14324
14324
|
}
|
|
14325
14325
|
function step(result) {
|
|
14326
|
-
result.done ?
|
|
14326
|
+
result.done ? resolve87(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
14327
14327
|
}
|
|
14328
14328
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
14329
14329
|
});
|
|
@@ -14362,11 +14362,11 @@ var require_streaming = __commonJS({
|
|
|
14362
14362
|
"use strict";
|
|
14363
14363
|
var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
|
|
14364
14364
|
function adopt(value) {
|
|
14365
|
-
return value instanceof P ? value : new P(function(
|
|
14366
|
-
|
|
14365
|
+
return value instanceof P ? value : new P(function(resolve87) {
|
|
14366
|
+
resolve87(value);
|
|
14367
14367
|
});
|
|
14368
14368
|
}
|
|
14369
|
-
return new (P || (P = Promise))(function(
|
|
14369
|
+
return new (P || (P = Promise))(function(resolve87, reject) {
|
|
14370
14370
|
function fulfilled(value) {
|
|
14371
14371
|
try {
|
|
14372
14372
|
step(generator.next(value));
|
|
@@ -14382,7 +14382,7 @@ var require_streaming = __commonJS({
|
|
|
14382
14382
|
}
|
|
14383
14383
|
}
|
|
14384
14384
|
function step(result) {
|
|
14385
|
-
result.done ?
|
|
14385
|
+
result.done ? resolve87(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
14386
14386
|
}
|
|
14387
14387
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
14388
14388
|
});
|
|
@@ -14615,7 +14615,7 @@ var require_streaming = __commonJS({
|
|
|
14615
14615
|
query: options.queryParams
|
|
14616
14616
|
});
|
|
14617
14617
|
this.options = options;
|
|
14618
|
-
this.donePromise = new Promise((
|
|
14618
|
+
this.donePromise = new Promise((resolve87, reject) => {
|
|
14619
14619
|
if (this.streamClosed) {
|
|
14620
14620
|
reject(new response_1.ApiError({
|
|
14621
14621
|
message: "Streaming connection is already closed.",
|
|
@@ -14626,11 +14626,11 @@ var require_streaming = __commonJS({
|
|
|
14626
14626
|
}
|
|
14627
14627
|
this.signal.addEventListener("abort", () => {
|
|
14628
14628
|
var _a2;
|
|
14629
|
-
|
|
14629
|
+
resolve87((_a2 = this.currentData) !== null && _a2 !== void 0 ? _a2 : {});
|
|
14630
14630
|
});
|
|
14631
14631
|
this.on("done", (data) => {
|
|
14632
14632
|
this.streamClosed = true;
|
|
14633
|
-
|
|
14633
|
+
resolve87(data);
|
|
14634
14634
|
});
|
|
14635
14635
|
this.on("error", (error) => {
|
|
14636
14636
|
this.streamClosed = true;
|
|
@@ -14655,7 +14655,7 @@ var require_streaming = __commonJS({
|
|
|
14655
14655
|
if (data) {
|
|
14656
14656
|
yield yield __await(data);
|
|
14657
14657
|
}
|
|
14658
|
-
yield __await(new Promise((
|
|
14658
|
+
yield __await(new Promise((resolve87) => setTimeout(resolve87, 16)));
|
|
14659
14659
|
}
|
|
14660
14660
|
});
|
|
14661
14661
|
}
|
|
@@ -14700,11 +14700,11 @@ var require_queue = __commonJS({
|
|
|
14700
14700
|
"use strict";
|
|
14701
14701
|
var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
|
|
14702
14702
|
function adopt(value) {
|
|
14703
|
-
return value instanceof P ? value : new P(function(
|
|
14704
|
-
|
|
14703
|
+
return value instanceof P ? value : new P(function(resolve87) {
|
|
14704
|
+
resolve87(value);
|
|
14705
14705
|
});
|
|
14706
14706
|
}
|
|
14707
|
-
return new (P || (P = Promise))(function(
|
|
14707
|
+
return new (P || (P = Promise))(function(resolve87, reject) {
|
|
14708
14708
|
function fulfilled(value) {
|
|
14709
14709
|
try {
|
|
14710
14710
|
step(generator.next(value));
|
|
@@ -14720,7 +14720,7 @@ var require_queue = __commonJS({
|
|
|
14720
14720
|
}
|
|
14721
14721
|
}
|
|
14722
14722
|
function step(result) {
|
|
14723
|
-
result.done ?
|
|
14723
|
+
result.done ? resolve87(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
14724
14724
|
}
|
|
14725
14725
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
14726
14726
|
});
|
|
@@ -14855,7 +14855,7 @@ var require_queue = __commonJS({
|
|
|
14855
14855
|
}
|
|
14856
14856
|
return doneStatus;
|
|
14857
14857
|
}
|
|
14858
|
-
return new Promise((
|
|
14858
|
+
return new Promise((resolve87, reject) => {
|
|
14859
14859
|
var _a;
|
|
14860
14860
|
let pollingTimeoutId;
|
|
14861
14861
|
const pollInterval = "pollInterval" in options && typeof options.pollInterval === "number" ? (_a = options.pollInterval) !== null && _a !== void 0 ? _a : DEFAULT_POLL_INTERVAL : DEFAULT_POLL_INTERVAL;
|
|
@@ -14887,7 +14887,7 @@ var require_queue = __commonJS({
|
|
|
14887
14887
|
}
|
|
14888
14888
|
if (requestStatus.status === "COMPLETED") {
|
|
14889
14889
|
clearScheduledTasks();
|
|
14890
|
-
|
|
14890
|
+
resolve87(requestStatus);
|
|
14891
14891
|
return;
|
|
14892
14892
|
}
|
|
14893
14893
|
pollingTimeoutId = setTimeout(poll, pollInterval);
|
|
@@ -16848,11 +16848,11 @@ var require_realtime = __commonJS({
|
|
|
16848
16848
|
"use strict";
|
|
16849
16849
|
var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
|
|
16850
16850
|
function adopt(value) {
|
|
16851
|
-
return value instanceof P ? value : new P(function(
|
|
16852
|
-
|
|
16851
|
+
return value instanceof P ? value : new P(function(resolve87) {
|
|
16852
|
+
resolve87(value);
|
|
16853
16853
|
});
|
|
16854
16854
|
}
|
|
16855
|
-
return new (P || (P = Promise))(function(
|
|
16855
|
+
return new (P || (P = Promise))(function(resolve87, reject) {
|
|
16856
16856
|
function fulfilled(value) {
|
|
16857
16857
|
try {
|
|
16858
16858
|
step(generator.next(value));
|
|
@@ -16868,7 +16868,7 @@ var require_realtime = __commonJS({
|
|
|
16868
16868
|
}
|
|
16869
16869
|
}
|
|
16870
16870
|
function step(result) {
|
|
16871
|
-
result.done ?
|
|
16871
|
+
result.done ? resolve87(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
16872
16872
|
}
|
|
16873
16873
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
16874
16874
|
});
|
|
@@ -17193,11 +17193,11 @@ var require_client = __commonJS({
|
|
|
17193
17193
|
"use strict";
|
|
17194
17194
|
var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
|
|
17195
17195
|
function adopt(value) {
|
|
17196
|
-
return value instanceof P ? value : new P(function(
|
|
17197
|
-
|
|
17196
|
+
return value instanceof P ? value : new P(function(resolve87) {
|
|
17197
|
+
resolve87(value);
|
|
17198
17198
|
});
|
|
17199
17199
|
}
|
|
17200
|
-
return new (P || (P = Promise))(function(
|
|
17200
|
+
return new (P || (P = Promise))(function(resolve87, reject) {
|
|
17201
17201
|
function fulfilled(value) {
|
|
17202
17202
|
try {
|
|
17203
17203
|
step(generator.next(value));
|
|
@@ -17213,7 +17213,7 @@ var require_client = __commonJS({
|
|
|
17213
17213
|
}
|
|
17214
17214
|
}
|
|
17215
17215
|
function step(result) {
|
|
17216
|
-
result.done ?
|
|
17216
|
+
result.done ? resolve87(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
17217
17217
|
}
|
|
17218
17218
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
17219
17219
|
});
|
|
@@ -17915,7 +17915,7 @@ var init_ReplicateProvider = __esm({
|
|
|
17915
17915
|
* Sleep helper
|
|
17916
17916
|
*/
|
|
17917
17917
|
sleep(ms) {
|
|
17918
|
-
return new Promise((
|
|
17918
|
+
return new Promise((resolve87) => setTimeout(resolve87, ms));
|
|
17919
17919
|
}
|
|
17920
17920
|
/**
|
|
17921
17921
|
* Generate music from text prompt using MusicGen
|
|
@@ -22744,10 +22744,10 @@ var require_resolve_block_map = __commonJS({
|
|
|
22744
22744
|
let offset = bm.offset;
|
|
22745
22745
|
let commentEnd = null;
|
|
22746
22746
|
for (const collItem of bm.items) {
|
|
22747
|
-
const { start, key, sep:
|
|
22747
|
+
const { start, key, sep: sep3, value } = collItem;
|
|
22748
22748
|
const keyProps = resolveProps.resolveProps(start, {
|
|
22749
22749
|
indicator: "explicit-key-ind",
|
|
22750
|
-
next: key ??
|
|
22750
|
+
next: key ?? sep3?.[0],
|
|
22751
22751
|
offset,
|
|
22752
22752
|
onError,
|
|
22753
22753
|
parentIndent: bm.indent,
|
|
@@ -22761,7 +22761,7 @@ var require_resolve_block_map = __commonJS({
|
|
|
22761
22761
|
else if ("indent" in key && key.indent !== bm.indent)
|
|
22762
22762
|
onError(offset, "BAD_INDENT", startColMsg);
|
|
22763
22763
|
}
|
|
22764
|
-
if (!keyProps.anchor && !keyProps.tag && !
|
|
22764
|
+
if (!keyProps.anchor && !keyProps.tag && !sep3) {
|
|
22765
22765
|
commentEnd = keyProps.end;
|
|
22766
22766
|
if (keyProps.comment) {
|
|
22767
22767
|
if (map.comment)
|
|
@@ -22785,7 +22785,7 @@ var require_resolve_block_map = __commonJS({
|
|
|
22785
22785
|
ctx.atKey = false;
|
|
22786
22786
|
if (utilMapIncludes.mapIncludes(ctx, map.items, keyNode))
|
|
22787
22787
|
onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
|
|
22788
|
-
const valueProps = resolveProps.resolveProps(
|
|
22788
|
+
const valueProps = resolveProps.resolveProps(sep3 ?? [], {
|
|
22789
22789
|
indicator: "map-value-ind",
|
|
22790
22790
|
next: value,
|
|
22791
22791
|
offset: keyNode.range[2],
|
|
@@ -22801,7 +22801,7 @@ var require_resolve_block_map = __commonJS({
|
|
|
22801
22801
|
if (ctx.options.strict && keyProps.start < valueProps.found.offset - 1024)
|
|
22802
22802
|
onError(keyNode.range, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit block mapping key");
|
|
22803
22803
|
}
|
|
22804
|
-
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset,
|
|
22804
|
+
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep3, null, valueProps, onError);
|
|
22805
22805
|
if (ctx.schema.compat)
|
|
22806
22806
|
utilFlowIndentCheck.flowIndentCheck(bm.indent, value, onError);
|
|
22807
22807
|
offset = valueNode.range[2];
|
|
@@ -22892,7 +22892,7 @@ var require_resolve_end = __commonJS({
|
|
|
22892
22892
|
let comment = "";
|
|
22893
22893
|
if (end) {
|
|
22894
22894
|
let hasSpace = false;
|
|
22895
|
-
let
|
|
22895
|
+
let sep3 = "";
|
|
22896
22896
|
for (const token of end) {
|
|
22897
22897
|
const { source, type } = token;
|
|
22898
22898
|
switch (type) {
|
|
@@ -22906,13 +22906,13 @@ var require_resolve_end = __commonJS({
|
|
|
22906
22906
|
if (!comment)
|
|
22907
22907
|
comment = cb;
|
|
22908
22908
|
else
|
|
22909
|
-
comment +=
|
|
22910
|
-
|
|
22909
|
+
comment += sep3 + cb;
|
|
22910
|
+
sep3 = "";
|
|
22911
22911
|
break;
|
|
22912
22912
|
}
|
|
22913
22913
|
case "newline":
|
|
22914
22914
|
if (comment)
|
|
22915
|
-
|
|
22915
|
+
sep3 += source;
|
|
22916
22916
|
hasSpace = true;
|
|
22917
22917
|
break;
|
|
22918
22918
|
default:
|
|
@@ -22955,18 +22955,18 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
22955
22955
|
let offset = fc.offset + fc.start.source.length;
|
|
22956
22956
|
for (let i = 0; i < fc.items.length; ++i) {
|
|
22957
22957
|
const collItem = fc.items[i];
|
|
22958
|
-
const { start, key, sep:
|
|
22958
|
+
const { start, key, sep: sep3, value } = collItem;
|
|
22959
22959
|
const props = resolveProps.resolveProps(start, {
|
|
22960
22960
|
flow: fcName,
|
|
22961
22961
|
indicator: "explicit-key-ind",
|
|
22962
|
-
next: key ??
|
|
22962
|
+
next: key ?? sep3?.[0],
|
|
22963
22963
|
offset,
|
|
22964
22964
|
onError,
|
|
22965
22965
|
parentIndent: fc.indent,
|
|
22966
22966
|
startOnNewline: false
|
|
22967
22967
|
});
|
|
22968
22968
|
if (!props.found) {
|
|
22969
|
-
if (!props.anchor && !props.tag && !
|
|
22969
|
+
if (!props.anchor && !props.tag && !sep3 && !value) {
|
|
22970
22970
|
if (i === 0 && props.comma)
|
|
22971
22971
|
onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`);
|
|
22972
22972
|
else if (i < fc.items.length - 1)
|
|
@@ -23020,8 +23020,8 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
23020
23020
|
}
|
|
23021
23021
|
}
|
|
23022
23022
|
}
|
|
23023
|
-
if (!isMap && !
|
|
23024
|
-
const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end,
|
|
23023
|
+
if (!isMap && !sep3 && !props.found) {
|
|
23024
|
+
const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep3, null, props, onError);
|
|
23025
23025
|
coll.items.push(valueNode);
|
|
23026
23026
|
offset = valueNode.range[2];
|
|
23027
23027
|
if (isBlock(value))
|
|
@@ -23033,7 +23033,7 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
23033
23033
|
if (isBlock(key))
|
|
23034
23034
|
onError(keyNode.range, "BLOCK_IN_FLOW", blockMsg);
|
|
23035
23035
|
ctx.atKey = false;
|
|
23036
|
-
const valueProps = resolveProps.resolveProps(
|
|
23036
|
+
const valueProps = resolveProps.resolveProps(sep3 ?? [], {
|
|
23037
23037
|
flow: fcName,
|
|
23038
23038
|
indicator: "map-value-ind",
|
|
23039
23039
|
next: value,
|
|
@@ -23044,8 +23044,8 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
23044
23044
|
});
|
|
23045
23045
|
if (valueProps.found) {
|
|
23046
23046
|
if (!isMap && !props.found && ctx.options.strict) {
|
|
23047
|
-
if (
|
|
23048
|
-
for (const st of
|
|
23047
|
+
if (sep3)
|
|
23048
|
+
for (const st of sep3) {
|
|
23049
23049
|
if (st === valueProps.found)
|
|
23050
23050
|
break;
|
|
23051
23051
|
if (st.type === "newline") {
|
|
@@ -23062,7 +23062,7 @@ var require_resolve_flow_collection = __commonJS({
|
|
|
23062
23062
|
else
|
|
23063
23063
|
onError(valueProps.start, "MISSING_CHAR", `Missing , or : between ${fcName} items`);
|
|
23064
23064
|
}
|
|
23065
|
-
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end,
|
|
23065
|
+
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep3, null, valueProps, onError) : null;
|
|
23066
23066
|
if (valueNode) {
|
|
23067
23067
|
if (isBlock(value))
|
|
23068
23068
|
onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
|
|
@@ -23242,7 +23242,7 @@ var require_resolve_block_scalar = __commonJS({
|
|
|
23242
23242
|
chompStart = i + 1;
|
|
23243
23243
|
}
|
|
23244
23244
|
let value = "";
|
|
23245
|
-
let
|
|
23245
|
+
let sep3 = "";
|
|
23246
23246
|
let prevMoreIndented = false;
|
|
23247
23247
|
for (let i = 0; i < contentStart; ++i)
|
|
23248
23248
|
value += lines[i][0].slice(trimIndent) + "\n";
|
|
@@ -23259,24 +23259,24 @@ var require_resolve_block_scalar = __commonJS({
|
|
|
23259
23259
|
indent = "";
|
|
23260
23260
|
}
|
|
23261
23261
|
if (type === Scalar.Scalar.BLOCK_LITERAL) {
|
|
23262
|
-
value +=
|
|
23263
|
-
|
|
23262
|
+
value += sep3 + indent.slice(trimIndent) + content;
|
|
23263
|
+
sep3 = "\n";
|
|
23264
23264
|
} else if (indent.length > trimIndent || content[0] === " ") {
|
|
23265
|
-
if (
|
|
23266
|
-
|
|
23267
|
-
else if (!prevMoreIndented &&
|
|
23268
|
-
|
|
23269
|
-
value +=
|
|
23270
|
-
|
|
23265
|
+
if (sep3 === " ")
|
|
23266
|
+
sep3 = "\n";
|
|
23267
|
+
else if (!prevMoreIndented && sep3 === "\n")
|
|
23268
|
+
sep3 = "\n\n";
|
|
23269
|
+
value += sep3 + indent.slice(trimIndent) + content;
|
|
23270
|
+
sep3 = "\n";
|
|
23271
23271
|
prevMoreIndented = true;
|
|
23272
23272
|
} else if (content === "") {
|
|
23273
|
-
if (
|
|
23273
|
+
if (sep3 === "\n")
|
|
23274
23274
|
value += "\n";
|
|
23275
23275
|
else
|
|
23276
|
-
|
|
23276
|
+
sep3 = "\n";
|
|
23277
23277
|
} else {
|
|
23278
|
-
value +=
|
|
23279
|
-
|
|
23278
|
+
value += sep3 + content;
|
|
23279
|
+
sep3 = " ";
|
|
23280
23280
|
prevMoreIndented = false;
|
|
23281
23281
|
}
|
|
23282
23282
|
}
|
|
@@ -23458,25 +23458,25 @@ var require_resolve_flow_scalar = __commonJS({
|
|
|
23458
23458
|
if (!match)
|
|
23459
23459
|
return source;
|
|
23460
23460
|
let res = match[1];
|
|
23461
|
-
let
|
|
23461
|
+
let sep3 = " ";
|
|
23462
23462
|
let pos = first.lastIndex;
|
|
23463
23463
|
line.lastIndex = pos;
|
|
23464
23464
|
while (match = line.exec(source)) {
|
|
23465
23465
|
if (match[1] === "") {
|
|
23466
|
-
if (
|
|
23467
|
-
res +=
|
|
23466
|
+
if (sep3 === "\n")
|
|
23467
|
+
res += sep3;
|
|
23468
23468
|
else
|
|
23469
|
-
|
|
23469
|
+
sep3 = "\n";
|
|
23470
23470
|
} else {
|
|
23471
|
-
res +=
|
|
23472
|
-
|
|
23471
|
+
res += sep3 + match[1];
|
|
23472
|
+
sep3 = " ";
|
|
23473
23473
|
}
|
|
23474
23474
|
pos = line.lastIndex;
|
|
23475
23475
|
}
|
|
23476
23476
|
const last = /[ \t]*(.*)/sy;
|
|
23477
23477
|
last.lastIndex = pos;
|
|
23478
23478
|
match = last.exec(source);
|
|
23479
|
-
return res +
|
|
23479
|
+
return res + sep3 + (match?.[1] ?? "");
|
|
23480
23480
|
}
|
|
23481
23481
|
function doubleQuotedValue(source, onError) {
|
|
23482
23482
|
let res = "";
|
|
@@ -24278,14 +24278,14 @@ var require_cst_stringify = __commonJS({
|
|
|
24278
24278
|
}
|
|
24279
24279
|
}
|
|
24280
24280
|
}
|
|
24281
|
-
function stringifyItem({ start, key, sep:
|
|
24281
|
+
function stringifyItem({ start, key, sep: sep3, value }) {
|
|
24282
24282
|
let res = "";
|
|
24283
24283
|
for (const st of start)
|
|
24284
24284
|
res += st.source;
|
|
24285
24285
|
if (key)
|
|
24286
24286
|
res += stringifyToken(key);
|
|
24287
|
-
if (
|
|
24288
|
-
for (const st of
|
|
24287
|
+
if (sep3)
|
|
24288
|
+
for (const st of sep3)
|
|
24289
24289
|
res += st.source;
|
|
24290
24290
|
if (value)
|
|
24291
24291
|
res += stringifyToken(value);
|
|
@@ -25435,18 +25435,18 @@ var require_parser = __commonJS({
|
|
|
25435
25435
|
if (this.type === "map-value-ind") {
|
|
25436
25436
|
const prev = getPrevProps(this.peek(2));
|
|
25437
25437
|
const start = getFirstKeyStartProps(prev);
|
|
25438
|
-
let
|
|
25438
|
+
let sep3;
|
|
25439
25439
|
if (scalar.end) {
|
|
25440
|
-
|
|
25441
|
-
|
|
25440
|
+
sep3 = scalar.end;
|
|
25441
|
+
sep3.push(this.sourceToken);
|
|
25442
25442
|
delete scalar.end;
|
|
25443
25443
|
} else
|
|
25444
|
-
|
|
25444
|
+
sep3 = [this.sourceToken];
|
|
25445
25445
|
const map = {
|
|
25446
25446
|
type: "block-map",
|
|
25447
25447
|
offset: scalar.offset,
|
|
25448
25448
|
indent: scalar.indent,
|
|
25449
|
-
items: [{ start, key: scalar, sep:
|
|
25449
|
+
items: [{ start, key: scalar, sep: sep3 }]
|
|
25450
25450
|
};
|
|
25451
25451
|
this.onKeyLine = true;
|
|
25452
25452
|
this.stack[this.stack.length - 1] = map;
|
|
@@ -25599,15 +25599,15 @@ var require_parser = __commonJS({
|
|
|
25599
25599
|
} else if (isFlowToken(it.key) && !includesToken(it.sep, "newline")) {
|
|
25600
25600
|
const start2 = getFirstKeyStartProps(it.start);
|
|
25601
25601
|
const key = it.key;
|
|
25602
|
-
const
|
|
25603
|
-
|
|
25602
|
+
const sep3 = it.sep;
|
|
25603
|
+
sep3.push(this.sourceToken);
|
|
25604
25604
|
delete it.key;
|
|
25605
25605
|
delete it.sep;
|
|
25606
25606
|
this.stack.push({
|
|
25607
25607
|
type: "block-map",
|
|
25608
25608
|
offset: this.offset,
|
|
25609
25609
|
indent: this.indent,
|
|
25610
|
-
items: [{ start: start2, key, sep:
|
|
25610
|
+
items: [{ start: start2, key, sep: sep3 }]
|
|
25611
25611
|
});
|
|
25612
25612
|
} else if (start.length > 0) {
|
|
25613
25613
|
it.sep = it.sep.concat(start, this.sourceToken);
|
|
@@ -25801,13 +25801,13 @@ var require_parser = __commonJS({
|
|
|
25801
25801
|
const prev = getPrevProps(parent);
|
|
25802
25802
|
const start = getFirstKeyStartProps(prev);
|
|
25803
25803
|
fixFlowSeqItems(fc);
|
|
25804
|
-
const
|
|
25805
|
-
|
|
25804
|
+
const sep3 = fc.end.splice(1, fc.end.length);
|
|
25805
|
+
sep3.push(this.sourceToken);
|
|
25806
25806
|
const map = {
|
|
25807
25807
|
type: "block-map",
|
|
25808
25808
|
offset: fc.offset,
|
|
25809
25809
|
indent: fc.indent,
|
|
25810
|
-
items: [{ start, key: fc, sep:
|
|
25810
|
+
items: [{ start, key: fc, sep: sep3 }]
|
|
25811
25811
|
};
|
|
25812
25812
|
this.onKeyLine = true;
|
|
25813
25813
|
this.stack[this.stack.length - 1] = map;
|
|
@@ -26399,7 +26399,7 @@ async function prompt(question, hidden = false) {
|
|
|
26399
26399
|
input: process.stdin,
|
|
26400
26400
|
output: process.stdout
|
|
26401
26401
|
});
|
|
26402
|
-
return new Promise((
|
|
26402
|
+
return new Promise((resolve87) => {
|
|
26403
26403
|
if (hidden && process.stdin.isTTY) {
|
|
26404
26404
|
process.stdout.write(question);
|
|
26405
26405
|
let input = "";
|
|
@@ -26413,7 +26413,7 @@ async function prompt(question, hidden = false) {
|
|
|
26413
26413
|
process.stdin.removeListener("data", onData);
|
|
26414
26414
|
process.stdout.write("\n");
|
|
26415
26415
|
rl.close();
|
|
26416
|
-
|
|
26416
|
+
resolve87(input);
|
|
26417
26417
|
} else if (char === "") {
|
|
26418
26418
|
process.exit(1);
|
|
26419
26419
|
} else if (char === "\x7F" || char === "\b") {
|
|
@@ -26428,7 +26428,7 @@ async function prompt(question, hidden = false) {
|
|
|
26428
26428
|
} else {
|
|
26429
26429
|
rl.question(question, (answer) => {
|
|
26430
26430
|
rl.close();
|
|
26431
|
-
|
|
26431
|
+
resolve87(answer);
|
|
26432
26432
|
});
|
|
26433
26433
|
}
|
|
26434
26434
|
});
|
|
@@ -26802,6 +26802,7 @@ var init_storyboard_parse = __esm({
|
|
|
26802
26802
|
"backdrop",
|
|
26803
26803
|
"video",
|
|
26804
26804
|
"keyframe",
|
|
26805
|
+
"provider",
|
|
26805
26806
|
"motion",
|
|
26806
26807
|
"voice",
|
|
26807
26808
|
"music",
|
|
@@ -27097,7 +27098,7 @@ var init_storyboard_edit = __esm({
|
|
|
27097
27098
|
HEADING_RE2 = /^##\s+(.+?)\s*$/gm;
|
|
27098
27099
|
LEADING_CUE_RE = /^(\s*)```ya?ml\s*\n([\s\S]*?)\n```\s*(?:\n|$)/;
|
|
27099
27100
|
ALLOWED_CUE_KEYS = new Set(STORYBOARD_CUE_KEYS);
|
|
27100
|
-
STRING_CUE_KEYS = /* @__PURE__ */ new Set(["narration", "backdrop", "video", "keyframe", "motion", "voice", "music", "asset", "eyebrow", "title", "caption", "kicker", "sub"]);
|
|
27101
|
+
STRING_CUE_KEYS = /* @__PURE__ */ new Set(["narration", "backdrop", "video", "keyframe", "provider", "motion", "voice", "music", "asset", "eyebrow", "title", "caption", "kicker", "sub"]);
|
|
27101
27102
|
MAX_RECOMMENDED_BEAT_SEC = 15;
|
|
27102
27103
|
}
|
|
27103
27104
|
});
|
|
@@ -33448,16 +33449,16 @@ async function prompt2(question) {
|
|
|
33448
33449
|
input,
|
|
33449
33450
|
output: process.stdout
|
|
33450
33451
|
});
|
|
33451
|
-
return new Promise((
|
|
33452
|
+
return new Promise((resolve87) => {
|
|
33452
33453
|
rl.question(question, (answer) => {
|
|
33453
33454
|
rl.close();
|
|
33454
|
-
|
|
33455
|
+
resolve87(answer);
|
|
33455
33456
|
});
|
|
33456
33457
|
});
|
|
33457
33458
|
}
|
|
33458
33459
|
async function promptHidden(question, opts = {}) {
|
|
33459
33460
|
const input = getTTYInputStream();
|
|
33460
|
-
return new Promise((
|
|
33461
|
+
return new Promise((resolve87) => {
|
|
33461
33462
|
let value = "";
|
|
33462
33463
|
if (typeof input.setRawMode === "function") {
|
|
33463
33464
|
input.setRawMode(true);
|
|
@@ -33471,7 +33472,7 @@ async function promptHidden(question, opts = {}) {
|
|
|
33471
33472
|
input.setRawMode(false);
|
|
33472
33473
|
input.removeListener("data", onData);
|
|
33473
33474
|
process.stdout.write("\n");
|
|
33474
|
-
|
|
33475
|
+
resolve87(value);
|
|
33475
33476
|
} else if (char === "") {
|
|
33476
33477
|
input.setRawMode(false);
|
|
33477
33478
|
process.stdout.write("\n");
|
|
@@ -33497,7 +33498,7 @@ async function promptHidden(question, opts = {}) {
|
|
|
33497
33498
|
const rl = createInterface2({ input, output: process.stdout });
|
|
33498
33499
|
rl.question(question, (answer) => {
|
|
33499
33500
|
rl.close();
|
|
33500
|
-
|
|
33501
|
+
resolve87(answer);
|
|
33501
33502
|
});
|
|
33502
33503
|
}
|
|
33503
33504
|
});
|
|
@@ -33505,7 +33506,7 @@ async function promptHidden(question, opts = {}) {
|
|
|
33505
33506
|
async function promptSelect(_question, options, defaultIndex = 0, opts = {}) {
|
|
33506
33507
|
const input = getTTYInputStream();
|
|
33507
33508
|
if (typeof input.setRawMode === "function") {
|
|
33508
|
-
return new Promise((
|
|
33509
|
+
return new Promise((resolve87) => {
|
|
33509
33510
|
let selected = defaultIndex;
|
|
33510
33511
|
const render = () => {
|
|
33511
33512
|
if (renderCount > 0) {
|
|
@@ -33533,7 +33534,7 @@ async function promptSelect(_question, options, defaultIndex = 0, opts = {}) {
|
|
|
33533
33534
|
input.setRawMode(false);
|
|
33534
33535
|
input.removeListener("data", onData);
|
|
33535
33536
|
process.stdout.write("\n");
|
|
33536
|
-
|
|
33537
|
+
resolve87(selected);
|
|
33537
33538
|
} else if (char === "") {
|
|
33538
33539
|
input.setRawMode(false);
|
|
33539
33540
|
process.stdout.write("\n");
|
|
@@ -33543,7 +33544,7 @@ async function promptSelect(_question, options, defaultIndex = 0, opts = {}) {
|
|
|
33543
33544
|
input.setRawMode(false);
|
|
33544
33545
|
input.removeListener("data", onData);
|
|
33545
33546
|
process.stdout.write("\n");
|
|
33546
|
-
|
|
33547
|
+
resolve87(opts.backIndex);
|
|
33547
33548
|
} else if (char === "\x1B[A" || char === "k") {
|
|
33548
33549
|
selected = (selected - 1 + options.length) % options.length;
|
|
33549
33550
|
render();
|
|
@@ -33557,7 +33558,7 @@ async function promptSelect(_question, options, defaultIndex = 0, opts = {}) {
|
|
|
33557
33558
|
input.removeListener("data", onData);
|
|
33558
33559
|
render();
|
|
33559
33560
|
process.stdout.write("\n");
|
|
33560
|
-
|
|
33561
|
+
resolve87(selected);
|
|
33561
33562
|
}
|
|
33562
33563
|
};
|
|
33563
33564
|
const onData = (chunk) => {
|
|
@@ -33581,7 +33582,7 @@ async function promptSelect(_question, options, defaultIndex = 0, opts = {}) {
|
|
|
33581
33582
|
async function promptConfirm(question, defaultYes = true) {
|
|
33582
33583
|
const input = getTTYInputStream();
|
|
33583
33584
|
if (typeof input.setRawMode === "function") {
|
|
33584
|
-
return new Promise((
|
|
33585
|
+
return new Promise((resolve87) => {
|
|
33585
33586
|
const options = ["Yes", "No"];
|
|
33586
33587
|
let selected = defaultYes ? 0 : 1;
|
|
33587
33588
|
let renderCount = 0;
|
|
@@ -33611,7 +33612,7 @@ async function promptConfirm(question, defaultYes = true) {
|
|
|
33611
33612
|
finished = true;
|
|
33612
33613
|
input.setRawMode(false);
|
|
33613
33614
|
input.removeListener("data", onData);
|
|
33614
|
-
|
|
33615
|
+
resolve87(selected === 0);
|
|
33615
33616
|
} else if (char === "") {
|
|
33616
33617
|
input.setRawMode(false);
|
|
33617
33618
|
process.stdout.write("\n");
|
|
@@ -33625,14 +33626,14 @@ async function promptConfirm(question, defaultYes = true) {
|
|
|
33625
33626
|
input.setRawMode(false);
|
|
33626
33627
|
input.removeListener("data", onData);
|
|
33627
33628
|
render();
|
|
33628
|
-
|
|
33629
|
+
resolve87(true);
|
|
33629
33630
|
} else if (char === "n" || char === "N") {
|
|
33630
33631
|
selected = 1;
|
|
33631
33632
|
finished = true;
|
|
33632
33633
|
input.setRawMode(false);
|
|
33633
33634
|
input.removeListener("data", onData);
|
|
33634
33635
|
render();
|
|
33635
|
-
|
|
33636
|
+
resolve87(false);
|
|
33636
33637
|
}
|
|
33637
33638
|
};
|
|
33638
33639
|
const onData = (chunk) => {
|
|
@@ -33651,7 +33652,7 @@ async function promptMultiSelect(_question, options, defaultSelected = [], opts
|
|
|
33651
33652
|
const input = getTTYInputStream();
|
|
33652
33653
|
const selected = options.map((_, i) => Boolean(defaultSelected[i]));
|
|
33653
33654
|
if (typeof input.setRawMode === "function") {
|
|
33654
|
-
return new Promise((
|
|
33655
|
+
return new Promise((resolve87) => {
|
|
33655
33656
|
let cursor = 0;
|
|
33656
33657
|
let renderCount = 0;
|
|
33657
33658
|
let userToggled = false;
|
|
@@ -33681,7 +33682,7 @@ async function promptMultiSelect(_question, options, defaultSelected = [], opts
|
|
|
33681
33682
|
for (let i = 0; i < selected.length; i++) {
|
|
33682
33683
|
if (selected[i]) result.push(i);
|
|
33683
33684
|
}
|
|
33684
|
-
|
|
33685
|
+
resolve87(result);
|
|
33685
33686
|
};
|
|
33686
33687
|
let finished = false;
|
|
33687
33688
|
const handleChar = (char) => {
|
|
@@ -35648,7 +35649,7 @@ function unique(items) {
|
|
|
35648
35649
|
];
|
|
35649
35650
|
}
|
|
35650
35651
|
function sleep2(ms) {
|
|
35651
|
-
return new Promise((
|
|
35652
|
+
return new Promise((resolve87) => setTimeout(resolve87, ms));
|
|
35652
35653
|
}
|
|
35653
35654
|
var LOCAL_JOB_ORPHAN_AFTER_MS;
|
|
35654
35655
|
var init_status_jobs = __esm({
|
|
@@ -38639,9 +38640,12 @@ Examples:
|
|
|
38639
38640
|
outputPath = resolve28(process.cwd(), options.output);
|
|
38640
38641
|
await writeFile25(outputPath, buffer);
|
|
38641
38642
|
}
|
|
38643
|
+
const cost = realRunCost(provider, options);
|
|
38642
38644
|
outputSuccess({
|
|
38643
38645
|
command: "generate video",
|
|
38644
38646
|
startedAt,
|
|
38647
|
+
costUsd: cost.costUsd,
|
|
38648
|
+
warnings: cost.warnings,
|
|
38645
38649
|
data: {
|
|
38646
38650
|
provider,
|
|
38647
38651
|
taskId: result?.id,
|
|
@@ -38678,6 +38682,26 @@ Examples:
|
|
|
38678
38682
|
}
|
|
38679
38683
|
});
|
|
38680
38684
|
}
|
|
38685
|
+
function realRunCost(provider, options) {
|
|
38686
|
+
if (provider === "seedance" || provider === "fal") {
|
|
38687
|
+
return {
|
|
38688
|
+
costUsd: estimateSeedanceVideoCostUsd({
|
|
38689
|
+
durationSec: Number(options.duration) || 5,
|
|
38690
|
+
resolution: options.resolution,
|
|
38691
|
+
aspectRatio: options.ratio,
|
|
38692
|
+
fast: options.seedanceModel === "fast",
|
|
38693
|
+
hasVideoReference: Boolean(options.refVideos)
|
|
38694
|
+
}),
|
|
38695
|
+
warnings: []
|
|
38696
|
+
};
|
|
38697
|
+
}
|
|
38698
|
+
return {
|
|
38699
|
+
costUsd: lookupCostEstimateUpperBound("generate video") ?? 5,
|
|
38700
|
+
warnings: [
|
|
38701
|
+
`costUsd is the tier upper bound for ${provider} - actual provider billing is typically lower and is not metered here.`
|
|
38702
|
+
]
|
|
38703
|
+
};
|
|
38704
|
+
}
|
|
38681
38705
|
async function prepareSeedanceReferences2(opts) {
|
|
38682
38706
|
const references = [];
|
|
38683
38707
|
for (const sourcePath of opts.refImages ?? []) {
|
|
@@ -58155,7 +58179,7 @@ var init_design_parse = __esm({
|
|
|
58155
58179
|
|
|
58156
58180
|
// src/commands/_shared/build-asset-reference.ts
|
|
58157
58181
|
import { existsSync as existsSync45 } from "node:fs";
|
|
58158
|
-
import { extname as extname12, isAbsolute as isAbsolute5, relative as relative9, resolve as resolve54, sep } from "node:path";
|
|
58182
|
+
import { extname as extname12, isAbsolute as isAbsolute5, relative as relative9, resolve as resolve54, sep as sep2 } from "node:path";
|
|
58159
58183
|
function resolveTypedAssetReference(projectDir, kind, value) {
|
|
58160
58184
|
const raw = stringOrUndefined2(value);
|
|
58161
58185
|
if (!raw || !looksLikeAssetPath(raw)) return null;
|
|
@@ -58202,7 +58226,7 @@ function resolveReference(projectDir, kind, raw, source, forcedError) {
|
|
|
58202
58226
|
return {
|
|
58203
58227
|
kind,
|
|
58204
58228
|
raw,
|
|
58205
|
-
relPath: withinProject ? rel.split(
|
|
58229
|
+
relPath: withinProject ? rel.split(sep2).join("/") : void 0,
|
|
58206
58230
|
absPath: withinProject ? absPath : void 0,
|
|
58207
58231
|
ext,
|
|
58208
58232
|
exists,
|
|
@@ -58268,6 +58292,7 @@ function backdropCacheDescriptor(opts) {
|
|
|
58268
58292
|
beatId: opts.beatId,
|
|
58269
58293
|
cue: opts.cue,
|
|
58270
58294
|
provider: opts.provider,
|
|
58295
|
+
model: opts.model,
|
|
58271
58296
|
quality: opts.quality,
|
|
58272
58297
|
size: opts.size,
|
|
58273
58298
|
ratio: opts.ratio,
|
|
@@ -58279,6 +58304,7 @@ function characterCacheDescriptor(opts) {
|
|
|
58279
58304
|
name: opts.name,
|
|
58280
58305
|
cue: opts.cue,
|
|
58281
58306
|
provider: opts.provider,
|
|
58307
|
+
model: opts.model,
|
|
58282
58308
|
quality: opts.quality,
|
|
58283
58309
|
size: opts.size,
|
|
58284
58310
|
ext: "png"
|
|
@@ -58288,6 +58314,7 @@ function keyframeCacheDescriptor(opts) {
|
|
|
58288
58314
|
return cacheAssetDescriptor("keyframe", {
|
|
58289
58315
|
beatId: opts.beatId,
|
|
58290
58316
|
cue: opts.cue,
|
|
58317
|
+
model: opts.model,
|
|
58291
58318
|
provider: opts.provider,
|
|
58292
58319
|
quality: opts.quality,
|
|
58293
58320
|
size: opts.size,
|
|
@@ -58388,7 +58415,8 @@ async function createBuildPlan(opts) {
|
|
|
58388
58415
|
const stage = opts.stage ?? "all";
|
|
58389
58416
|
const config2 = await readProjectConfig(projectDir);
|
|
58390
58417
|
const kindPolicy = kindAssetPolicy(config2.config.kind);
|
|
58391
|
-
const
|
|
58418
|
+
const composerIsFootage = stringOrUndefined3(opts.composer)?.toLowerCase() === "footage";
|
|
58419
|
+
const skipBackdrop = opts.skipBackdrop ?? (composerIsFootage ? true : kindPolicy.skipBackdrop ?? false);
|
|
58392
58420
|
const skipKeyframe = opts.skipKeyframe ?? kindPolicy.skipKeyframe ?? false;
|
|
58393
58421
|
const skipVideo = opts.skipVideo ?? kindPolicy.skipVideo ?? false;
|
|
58394
58422
|
const storyboardPath2 = join24(projectDir, "STORYBOARD.md");
|
|
@@ -58507,7 +58535,8 @@ async function createBuildPlan(opts) {
|
|
|
58507
58535
|
provider: resolved.image.resolved,
|
|
58508
58536
|
quality: imageQuality,
|
|
58509
58537
|
size: imageSize2,
|
|
58510
|
-
ratio: imageRatio
|
|
58538
|
+
ratio: imageRatio,
|
|
58539
|
+
model: opts.imageModel
|
|
58511
58540
|
}) : null;
|
|
58512
58541
|
const videoCache = (videoPrompt || keyframePrompt) && !videoReference ? videoCacheDescriptor({
|
|
58513
58542
|
beatId: beat.id,
|
|
@@ -58522,7 +58551,8 @@ async function createBuildPlan(opts) {
|
|
|
58522
58551
|
provider: resolved.image.resolved,
|
|
58523
58552
|
quality: imageQuality,
|
|
58524
58553
|
size: imageSize2,
|
|
58525
|
-
ratio: imageRatio
|
|
58554
|
+
ratio: imageRatio,
|
|
58555
|
+
model: opts.imageModel
|
|
58526
58556
|
}) : null;
|
|
58527
58557
|
const musicCache = musicPrompt && !musicReference ? musicCacheDescriptor({
|
|
58528
58558
|
beatId: beat.id,
|
|
@@ -58997,6 +59027,17 @@ async function keyedProviderResolution(opts, projectDir) {
|
|
|
58997
59027
|
}
|
|
58998
59028
|
async function resolveComposerProvider(input, projectDir) {
|
|
58999
59029
|
const requested = input.value.toLowerCase();
|
|
59030
|
+
if (requested === "template" || requested === "footage") {
|
|
59031
|
+
return {
|
|
59032
|
+
kind: "composer",
|
|
59033
|
+
requested: input.requested,
|
|
59034
|
+
resolved: requested,
|
|
59035
|
+
source: input.source,
|
|
59036
|
+
requiresKey: false,
|
|
59037
|
+
configured: true,
|
|
59038
|
+
retryWith: []
|
|
59039
|
+
};
|
|
59040
|
+
}
|
|
59000
59041
|
const explicit = isComposerProvider(requested) ? requested : void 0;
|
|
59001
59042
|
const resolved = explicit ?? await firstConfiguredComposer(projectDir) ?? "claude";
|
|
59002
59043
|
const configKey = composerConfigKey(resolved);
|
|
@@ -59471,9 +59512,422 @@ var init_compose_aivideo = __esm({
|
|
|
59471
59512
|
}
|
|
59472
59513
|
});
|
|
59473
59514
|
|
|
59515
|
+
// src/commands/_shared/footage-assemble.ts
|
|
59516
|
+
import { existsSync as existsSync48 } from "node:fs";
|
|
59517
|
+
import { mkdir as mkdir24, writeFile as writeFile44 } from "node:fs/promises";
|
|
59518
|
+
import { dirname as dirname19, isAbsolute as isAbsolute6, join as join26, resolve as resolve58 } from "node:path";
|
|
59519
|
+
function planFootageTimeline(inputs, opts = {}) {
|
|
59520
|
+
if (inputs.length === 0) {
|
|
59521
|
+
throw new Error("No clips to assemble.");
|
|
59522
|
+
}
|
|
59523
|
+
const fadeSec = opts.fadeSec ?? FOOTAGE_DEFAULTS.fadeSec;
|
|
59524
|
+
const narrationLeadSec = opts.narrationLeadSec ?? FOOTAGE_DEFAULTS.narrationLeadSec;
|
|
59525
|
+
const narrationTailSec = opts.narrationTailSec ?? FOOTAGE_DEFAULTS.narrationTailSec;
|
|
59526
|
+
const warnings = [];
|
|
59527
|
+
let transitionSec = opts.transitionSec ?? FOOTAGE_DEFAULTS.transitionSec;
|
|
59528
|
+
if (inputs.length > 1) {
|
|
59529
|
+
const shortest = Math.min(...inputs.map((c) => c.clipDurationSec));
|
|
59530
|
+
const maxTransition = round3(Math.max(0, shortest / 2 - 0.05));
|
|
59531
|
+
if (transitionSec > maxTransition) {
|
|
59532
|
+
warnings.push(
|
|
59533
|
+
`Transition ${transitionSec}s exceeds half the shortest clip (${shortest}s); clamped to ${maxTransition}s.`
|
|
59534
|
+
);
|
|
59535
|
+
transitionSec = maxTransition;
|
|
59536
|
+
}
|
|
59537
|
+
}
|
|
59538
|
+
const beats = [];
|
|
59539
|
+
let cursor = 0;
|
|
59540
|
+
for (let i = 0; i < inputs.length; i++) {
|
|
59541
|
+
const input = inputs[i];
|
|
59542
|
+
const isFirst = i === 0;
|
|
59543
|
+
const isLast = i === inputs.length - 1;
|
|
59544
|
+
const startSec = round3(cursor);
|
|
59545
|
+
const inSegmentOffset = (isFirst ? 0 : transitionSec / 2) + narrationLeadSec;
|
|
59546
|
+
let segmentDurationSec = input.clipDurationSec;
|
|
59547
|
+
let narrationStartSec;
|
|
59548
|
+
if (input.narrationDurationSec !== void 0) {
|
|
59549
|
+
narrationStartSec = round3(startSec + inSegmentOffset);
|
|
59550
|
+
const tail = isLast ? Math.max(narrationTailSec, fadeSec) : narrationTailSec;
|
|
59551
|
+
const required = inSegmentOffset + input.narrationDurationSec + tail;
|
|
59552
|
+
segmentDurationSec = Math.max(segmentDurationSec, required);
|
|
59553
|
+
}
|
|
59554
|
+
segmentDurationSec = round3(segmentDurationSec);
|
|
59555
|
+
const extendedSec = round3(segmentDurationSec - input.clipDurationSec);
|
|
59556
|
+
if (extendedSec > 0) {
|
|
59557
|
+
warnings.push(
|
|
59558
|
+
`Beat "${input.id}": narration outruns the clip; last frame held for ${extendedSec}s.`
|
|
59559
|
+
);
|
|
59560
|
+
}
|
|
59561
|
+
beats.push({
|
|
59562
|
+
id: input.id,
|
|
59563
|
+
clipDurationSec: input.clipDurationSec,
|
|
59564
|
+
narrationDurationSec: input.narrationDurationSec,
|
|
59565
|
+
segmentDurationSec,
|
|
59566
|
+
extendedSec,
|
|
59567
|
+
startSec,
|
|
59568
|
+
narrationStartSec
|
|
59569
|
+
});
|
|
59570
|
+
cursor = startSec + segmentDurationSec - (isLast ? 0 : transitionSec);
|
|
59571
|
+
}
|
|
59572
|
+
return {
|
|
59573
|
+
beats,
|
|
59574
|
+
transitionSec,
|
|
59575
|
+
fadeSec,
|
|
59576
|
+
totalDurationSec: round3(cursor),
|
|
59577
|
+
warnings
|
|
59578
|
+
};
|
|
59579
|
+
}
|
|
59580
|
+
function buildFootageAssembleArgs(opts) {
|
|
59581
|
+
const { plan, sources, narrationPaths, musicPath, outputPath } = opts;
|
|
59582
|
+
const width = opts.width ?? FOOTAGE_DEFAULTS.width;
|
|
59583
|
+
const height = opts.height ?? FOOTAGE_DEFAULTS.height;
|
|
59584
|
+
const fps = opts.fps ?? FOOTAGE_DEFAULTS.fps;
|
|
59585
|
+
const crf = opts.crf ?? (opts.finish ? FOOTAGE_DEFAULTS.finishCrf : FOOTAGE_DEFAULTS.crf);
|
|
59586
|
+
const musicVolume = opts.musicVolume ?? FOOTAGE_DEFAULTS.musicVolume;
|
|
59587
|
+
const total = plan.totalDurationSec;
|
|
59588
|
+
const fade = plan.fadeSec;
|
|
59589
|
+
const args = ["-y"];
|
|
59590
|
+
for (let i = 0; i < sources.length; i++) {
|
|
59591
|
+
const source = sources[i];
|
|
59592
|
+
if (source.kind === "image") {
|
|
59593
|
+
args.push(
|
|
59594
|
+
"-loop",
|
|
59595
|
+
"1",
|
|
59596
|
+
"-framerate",
|
|
59597
|
+
String(fps),
|
|
59598
|
+
"-t",
|
|
59599
|
+
String(plan.beats[i].segmentDurationSec),
|
|
59600
|
+
"-i",
|
|
59601
|
+
source.path
|
|
59602
|
+
);
|
|
59603
|
+
} else {
|
|
59604
|
+
args.push("-i", source.path);
|
|
59605
|
+
}
|
|
59606
|
+
}
|
|
59607
|
+
const narrationEntries = [...narrationPaths.entries()].sort(([a], [b]) => a - b);
|
|
59608
|
+
const narrationInputIndex = /* @__PURE__ */ new Map();
|
|
59609
|
+
for (const [beatIndex, path2] of narrationEntries) {
|
|
59610
|
+
narrationInputIndex.set(beatIndex, sources.length + narrationInputIndex.size);
|
|
59611
|
+
args.push("-i", path2);
|
|
59612
|
+
}
|
|
59613
|
+
let musicInputIndex;
|
|
59614
|
+
if (musicPath) {
|
|
59615
|
+
musicInputIndex = sources.length + narrationInputIndex.size;
|
|
59616
|
+
args.push("-stream_loop", "-1", "-i", musicPath);
|
|
59617
|
+
}
|
|
59618
|
+
const filters = [];
|
|
59619
|
+
for (let i = 0; i < sources.length; i++) {
|
|
59620
|
+
const seg = plan.beats[i].segmentDurationSec;
|
|
59621
|
+
if (sources[i].kind === "image") {
|
|
59622
|
+
const rate = round6((FOOTAGE_DEFAULTS.kenburnsMaxZoom - 1) / Math.max(1, seg * fps));
|
|
59623
|
+
filters.push(
|
|
59624
|
+
`[${i}:v]scale=${width * 2}:${height * 2}:force_original_aspect_ratio=increase,crop=${width * 2}:${height * 2},zoompan=z='min(pzoom+${rate},${FOOTAGE_DEFAULTS.kenburnsMaxZoom})':x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)':d=1:s=${width}x${height}:fps=${fps},setsar=1,settb=AVTB,format=yuv420p[v${i}]`
|
|
59625
|
+
);
|
|
59626
|
+
continue;
|
|
59627
|
+
}
|
|
59628
|
+
const extend = plan.beats[i].extendedSec;
|
|
59629
|
+
const tpad = extend > 0 ? `,tpad=stop_mode=clone:stop_duration=${extend}` : "";
|
|
59630
|
+
filters.push(
|
|
59631
|
+
`[${i}:v]scale=${width}:${height}:force_original_aspect_ratio=increase,crop=${width}:${height},setsar=1,fps=${fps},settb=AVTB,format=yuv420p${tpad}[v${i}]`
|
|
59632
|
+
);
|
|
59633
|
+
}
|
|
59634
|
+
let videoLabel = "[v0]";
|
|
59635
|
+
for (let i = 1; i < sources.length; i++) {
|
|
59636
|
+
const out = `[vx${i}]`;
|
|
59637
|
+
filters.push(
|
|
59638
|
+
`${videoLabel}[v${i}]xfade=transition=fade:duration=${plan.transitionSec}:offset=${plan.beats[i].startSec}${out}`
|
|
59639
|
+
);
|
|
59640
|
+
videoLabel = out;
|
|
59641
|
+
}
|
|
59642
|
+
const finishChain = opts.finish ? `${FOOTAGE_DEFAULTS.finish.join(",")},` : "";
|
|
59643
|
+
filters.push(
|
|
59644
|
+
`${videoLabel}${finishChain}fade=t=in:st=0:d=${fade},fade=t=out:st=${round3(Math.max(0, total - fade))}:d=${fade}[vout]`
|
|
59645
|
+
);
|
|
59646
|
+
let audioLabel;
|
|
59647
|
+
if (narrationInputIndex.size > 0) {
|
|
59648
|
+
const delayed = [];
|
|
59649
|
+
for (const [beatIndex, inputIndex] of narrationInputIndex) {
|
|
59650
|
+
const ms = Math.round((plan.beats[beatIndex].narrationStartSec ?? 0) * 1e3);
|
|
59651
|
+
const label = `[nd${beatIndex}]`;
|
|
59652
|
+
filters.push(`[${inputIndex}:a]adelay=${ms}:all=1${label}`);
|
|
59653
|
+
delayed.push(label);
|
|
59654
|
+
}
|
|
59655
|
+
if (delayed.length === 1) {
|
|
59656
|
+
filters.push(`${delayed[0]}anull[nar]`);
|
|
59657
|
+
} else {
|
|
59658
|
+
filters.push(`${delayed.join("")}amix=inputs=${delayed.length}:normalize=0[nar]`);
|
|
59659
|
+
}
|
|
59660
|
+
audioLabel = "[nar]";
|
|
59661
|
+
}
|
|
59662
|
+
if (musicInputIndex !== void 0) {
|
|
59663
|
+
filters.push(
|
|
59664
|
+
`[${musicInputIndex}:a]atrim=0:${total},asetpts=PTS-STARTPTS,volume=${musicVolume}[mb]`
|
|
59665
|
+
);
|
|
59666
|
+
if (audioLabel) {
|
|
59667
|
+
const { thresholdDb, ratio, attackMs, releaseMs } = FOOTAGE_DEFAULTS.duck;
|
|
59668
|
+
const thresholdLinear = round3(Math.pow(10, thresholdDb / 20));
|
|
59669
|
+
filters.push(
|
|
59670
|
+
`${audioLabel}asplit=2[narA][narSC]`,
|
|
59671
|
+
`[mb][narSC]sidechaincompress=threshold=${thresholdLinear}:ratio=${ratio}:attack=${attackMs}:release=${releaseMs}[mduck]`,
|
|
59672
|
+
`[mduck][narA]amix=inputs=2:normalize=0[mix]`
|
|
59673
|
+
);
|
|
59674
|
+
audioLabel = "[mix]";
|
|
59675
|
+
} else {
|
|
59676
|
+
audioLabel = "[mb]";
|
|
59677
|
+
}
|
|
59678
|
+
}
|
|
59679
|
+
if (audioLabel) {
|
|
59680
|
+
filters.push(
|
|
59681
|
+
`${audioLabel}apad,atrim=0:${total},afade=t=out:st=${round3(Math.max(0, total - fade))}:d=${fade}[aout]`
|
|
59682
|
+
);
|
|
59683
|
+
}
|
|
59684
|
+
args.push("-filter_complex", filters.join(";"), "-map", "[vout]");
|
|
59685
|
+
if (audioLabel) {
|
|
59686
|
+
args.push("-map", "[aout]", "-c:a", "aac", "-b:a", "192k");
|
|
59687
|
+
} else {
|
|
59688
|
+
args.push("-an");
|
|
59689
|
+
}
|
|
59690
|
+
args.push(
|
|
59691
|
+
"-c:v",
|
|
59692
|
+
"libx264",
|
|
59693
|
+
"-crf",
|
|
59694
|
+
String(crf),
|
|
59695
|
+
"-pix_fmt",
|
|
59696
|
+
"yuv420p",
|
|
59697
|
+
"-movflags",
|
|
59698
|
+
"+faststart",
|
|
59699
|
+
"-t",
|
|
59700
|
+
String(total),
|
|
59701
|
+
outputPath
|
|
59702
|
+
);
|
|
59703
|
+
return args;
|
|
59704
|
+
}
|
|
59705
|
+
async function executeFootageAssemble(opts) {
|
|
59706
|
+
const projectDir = resolve58(opts.projectDir);
|
|
59707
|
+
const outputRel = opts.output ?? DEFAULT_FOOTAGE_OUTPUT;
|
|
59708
|
+
const outputPath = isAbsolute6(outputRel) ? outputRel : resolve58(projectDir, outputRel);
|
|
59709
|
+
if (!ffmpegToolsAvailable()) {
|
|
59710
|
+
return {
|
|
59711
|
+
success: false,
|
|
59712
|
+
dryRun: Boolean(opts.dryRun),
|
|
59713
|
+
outputPath,
|
|
59714
|
+
error: "FFmpeg toolchain (ffmpeg + ffprobe) not found in PATH.",
|
|
59715
|
+
suggestion: "Install with: brew install ffmpeg (macOS) or apt install ffmpeg (Linux)."
|
|
59716
|
+
};
|
|
59717
|
+
}
|
|
59718
|
+
let beats;
|
|
59719
|
+
try {
|
|
59720
|
+
const md = await loadStoryboardMarkdown(projectDir);
|
|
59721
|
+
beats = parseStoryboard(md).beats;
|
|
59722
|
+
} catch (err) {
|
|
59723
|
+
return {
|
|
59724
|
+
success: false,
|
|
59725
|
+
dryRun: Boolean(opts.dryRun),
|
|
59726
|
+
outputPath,
|
|
59727
|
+
error: err instanceof Error ? err.message : String(err),
|
|
59728
|
+
suggestion: "Run inside a vibe scene project (needs STORYBOARD.md / scenes/)."
|
|
59729
|
+
};
|
|
59730
|
+
}
|
|
59731
|
+
if (beats.length === 0) {
|
|
59732
|
+
return {
|
|
59733
|
+
success: false,
|
|
59734
|
+
dryRun: Boolean(opts.dryRun),
|
|
59735
|
+
outputPath,
|
|
59736
|
+
error: "STORYBOARD.md has no beats to assemble."
|
|
59737
|
+
};
|
|
59738
|
+
}
|
|
59739
|
+
const missing = [];
|
|
59740
|
+
const sourceRels = [];
|
|
59741
|
+
const kenburnsBeatIds = [];
|
|
59742
|
+
for (const beat of beats) {
|
|
59743
|
+
const clipRel = `assets/video-${beat.id}.mp4`;
|
|
59744
|
+
if (existsSync48(join26(projectDir, clipRel))) {
|
|
59745
|
+
sourceRels.push({ rel: clipRel, kind: "video" });
|
|
59746
|
+
continue;
|
|
59747
|
+
}
|
|
59748
|
+
const keyframeRel = `assets/keyframe-${beat.id}.png`;
|
|
59749
|
+
if (existsSync48(join26(projectDir, keyframeRel))) {
|
|
59750
|
+
sourceRels.push({ rel: keyframeRel, kind: "image" });
|
|
59751
|
+
kenburnsBeatIds.push(beat.id);
|
|
59752
|
+
continue;
|
|
59753
|
+
}
|
|
59754
|
+
missing.push(`${beat.id} (${clipRel})`);
|
|
59755
|
+
sourceRels.push({ rel: clipRel, kind: "video" });
|
|
59756
|
+
}
|
|
59757
|
+
if (missing.length > 0) {
|
|
59758
|
+
return {
|
|
59759
|
+
success: false,
|
|
59760
|
+
dryRun: Boolean(opts.dryRun),
|
|
59761
|
+
outputPath,
|
|
59762
|
+
error: `No clip or keyframe for beat(s): ${missing.join(", ")}.`,
|
|
59763
|
+
suggestion: `Generate them first: vibe build ${projectDir} --stage assets --json`
|
|
59764
|
+
};
|
|
59765
|
+
}
|
|
59766
|
+
const narrationRels = /* @__PURE__ */ new Map();
|
|
59767
|
+
for (let i = 0; i < beats.length; i++) {
|
|
59768
|
+
const rel = ["mp3", "wav"].map((ext) => `assets/narration-${beats[i].id}.${ext}`).find((r) => existsSync48(join26(projectDir, r)));
|
|
59769
|
+
if (rel) narrationRels.set(i, rel);
|
|
59770
|
+
}
|
|
59771
|
+
const music = resolveMusicBed(projectDir, beats[0]?.id, opts.music);
|
|
59772
|
+
if (!music.ok) {
|
|
59773
|
+
return {
|
|
59774
|
+
success: false,
|
|
59775
|
+
dryRun: Boolean(opts.dryRun),
|
|
59776
|
+
outputPath,
|
|
59777
|
+
error: music.error
|
|
59778
|
+
};
|
|
59779
|
+
}
|
|
59780
|
+
const inputs = [];
|
|
59781
|
+
for (let i = 0; i < beats.length; i++) {
|
|
59782
|
+
const clipDurationSec = sourceRels[i].kind === "image" ? beats[i].duration ?? FOOTAGE_DEFAULTS.kenburnsSec : round3(await ffprobeDuration(join26(projectDir, sourceRels[i].rel)));
|
|
59783
|
+
const narrationRel = narrationRels.get(i);
|
|
59784
|
+
const narrationDurationSec = narrationRel ? round3(await ffprobeDuration(join26(projectDir, narrationRel))) : void 0;
|
|
59785
|
+
inputs.push({ id: beats[i].id, clipDurationSec, narrationDurationSec });
|
|
59786
|
+
}
|
|
59787
|
+
const plan = planFootageTimeline(inputs, {
|
|
59788
|
+
transitionSec: opts.transitionSec,
|
|
59789
|
+
fadeSec: opts.fadeSec
|
|
59790
|
+
});
|
|
59791
|
+
const musicVolume = opts.musicVolume ?? FOOTAGE_DEFAULTS.musicVolume;
|
|
59792
|
+
const report = {
|
|
59793
|
+
schemaVersion: "1",
|
|
59794
|
+
kind: "footage-assemble",
|
|
59795
|
+
project: projectDir,
|
|
59796
|
+
output: outputPath,
|
|
59797
|
+
totalDurationSec: plan.totalDurationSec,
|
|
59798
|
+
transitionSec: plan.transitionSec,
|
|
59799
|
+
fadeSec: plan.fadeSec,
|
|
59800
|
+
beats: plan.beats.map((b, i) => ({
|
|
59801
|
+
...b,
|
|
59802
|
+
clip: sourceRels[i].rel,
|
|
59803
|
+
source: sourceRels[i].kind === "image" ? "keyframe-kenburns" : "clip",
|
|
59804
|
+
narration: narrationRels.get(i)
|
|
59805
|
+
})),
|
|
59806
|
+
music: music.rel ? {
|
|
59807
|
+
path: music.rel,
|
|
59808
|
+
source: music.source,
|
|
59809
|
+
volume: musicVolume,
|
|
59810
|
+
ducked: narrationRels.size > 0
|
|
59811
|
+
} : null,
|
|
59812
|
+
finish: opts.finish ? { filters: [...FOOTAGE_DEFAULTS.finish] } : null,
|
|
59813
|
+
warnings: [
|
|
59814
|
+
...plan.warnings,
|
|
59815
|
+
...kenburnsBeatIds.map(
|
|
59816
|
+
(id) => `Beat "${id}": no generated clip; keyframe ken-burns fallback used.`
|
|
59817
|
+
)
|
|
59818
|
+
],
|
|
59819
|
+
nextActions: [
|
|
59820
|
+
{
|
|
59821
|
+
id: "inspect-footage-cut",
|
|
59822
|
+
kind: "command",
|
|
59823
|
+
label: "Inspect the assembled cut",
|
|
59824
|
+
command: `vibe inspect render ${outputPath} --cheap --json`,
|
|
59825
|
+
fixOwner: "vibe",
|
|
59826
|
+
costTier: "free",
|
|
59827
|
+
safeToAutoRun: true,
|
|
59828
|
+
requiresConfirmation: false,
|
|
59829
|
+
reason: "Verify duration, black frames, and audio coverage without watching the video."
|
|
59830
|
+
},
|
|
59831
|
+
...kenburnsBeatIds.map((id) => ({
|
|
59832
|
+
id: `regenerate-clip-${id}`,
|
|
59833
|
+
kind: "command",
|
|
59834
|
+
label: `Regenerate the missing clip for beat "${id}"`,
|
|
59835
|
+
command: `vibe build ${projectDir} --beat ${id} --stage assets --force --json`,
|
|
59836
|
+
fixOwner: "vibe",
|
|
59837
|
+
costTier: "very-high",
|
|
59838
|
+
safeToAutoRun: false,
|
|
59839
|
+
requiresConfirmation: true,
|
|
59840
|
+
reason: `Beat "${id}" shipped as a ken-burns still; regenerating the clip restores real motion.`
|
|
59841
|
+
}))
|
|
59842
|
+
]
|
|
59843
|
+
};
|
|
59844
|
+
if (opts.dryRun) {
|
|
59845
|
+
return { success: true, dryRun: true, outputPath, report };
|
|
59846
|
+
}
|
|
59847
|
+
await mkdir24(dirname19(outputPath), { recursive: true });
|
|
59848
|
+
const args = buildFootageAssembleArgs({
|
|
59849
|
+
sources: sourceRels.map((s) => ({ path: join26(projectDir, s.rel), kind: s.kind })),
|
|
59850
|
+
plan,
|
|
59851
|
+
narrationPaths: new Map(
|
|
59852
|
+
[...narrationRels.entries()].map(([i, rel]) => [i, join26(projectDir, rel)])
|
|
59853
|
+
),
|
|
59854
|
+
musicPath: music.rel ? isAbsolute6(music.rel) ? music.rel : join26(projectDir, music.rel) : void 0,
|
|
59855
|
+
outputPath,
|
|
59856
|
+
musicVolume,
|
|
59857
|
+
finish: opts.finish
|
|
59858
|
+
});
|
|
59859
|
+
try {
|
|
59860
|
+
await execSafe("ffmpeg", args, { timeout: 6e5 });
|
|
59861
|
+
} catch (err) {
|
|
59862
|
+
return {
|
|
59863
|
+
success: false,
|
|
59864
|
+
dryRun: false,
|
|
59865
|
+
outputPath,
|
|
59866
|
+
report,
|
|
59867
|
+
error: `FFmpeg assembly failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
59868
|
+
suggestion: "Re-run with --dry-run --json to inspect the planned timeline."
|
|
59869
|
+
};
|
|
59870
|
+
}
|
|
59871
|
+
const reportPath = join26(projectDir, "assemble-report.json");
|
|
59872
|
+
await writeFile44(reportPath, `${JSON.stringify(report, null, 2)}
|
|
59873
|
+
`, "utf-8");
|
|
59874
|
+
return { success: true, dryRun: false, outputPath, reportPath, report };
|
|
59875
|
+
}
|
|
59876
|
+
function resolveMusicBed(projectDir, firstBeatId, flag) {
|
|
59877
|
+
if (flag === "none") return { ok: true, source: "flag" };
|
|
59878
|
+
if (flag) {
|
|
59879
|
+
const abs = isAbsolute6(flag) ? flag : join26(projectDir, flag);
|
|
59880
|
+
if (!existsSync48(abs)) return { ok: false, error: `Music file not found: ${abs}` };
|
|
59881
|
+
return { ok: true, rel: flag, source: "flag" };
|
|
59882
|
+
}
|
|
59883
|
+
const candidates = ["assets/music.mp3", "assets/music.wav"];
|
|
59884
|
+
if (firstBeatId) {
|
|
59885
|
+
candidates.push(`assets/music-${firstBeatId}.mp3`, `assets/music-${firstBeatId}.wav`);
|
|
59886
|
+
}
|
|
59887
|
+
const rel = candidates.find((r) => existsSync48(join26(projectDir, r)));
|
|
59888
|
+
return { ok: true, rel, source: "auto" };
|
|
59889
|
+
}
|
|
59890
|
+
var FOOTAGE_DEFAULTS, round3, round6, DEFAULT_FOOTAGE_OUTPUT;
|
|
59891
|
+
var init_footage_assemble = __esm({
|
|
59892
|
+
"src/commands/_shared/footage-assemble.ts"() {
|
|
59893
|
+
"use strict";
|
|
59894
|
+
init_exec_safe();
|
|
59895
|
+
init_ffmpeg_gate();
|
|
59896
|
+
init_storyboard_parse();
|
|
59897
|
+
init_storyboard_source();
|
|
59898
|
+
FOOTAGE_DEFAULTS = {
|
|
59899
|
+
transitionSec: 0.5,
|
|
59900
|
+
fadeSec: 0.6,
|
|
59901
|
+
narrationLeadSec: 0.35,
|
|
59902
|
+
narrationTailSec: 0.4,
|
|
59903
|
+
width: 1920,
|
|
59904
|
+
height: 1080,
|
|
59905
|
+
fps: 30,
|
|
59906
|
+
crf: 18,
|
|
59907
|
+
finishCrf: 23,
|
|
59908
|
+
musicVolume: 0.35,
|
|
59909
|
+
duck: { thresholdDb: -30, ratio: 3, attackMs: 20, releaseMs: 200 },
|
|
59910
|
+
/**
|
|
59911
|
+
* The cinematic finish pass: subtle vignette + temporal film grain, applied
|
|
59912
|
+
* before the head/tail fades. These are the field-tested values that pull
|
|
59913
|
+
* provider clips away from the too-clean "AI look"; the fades multiply over
|
|
59914
|
+
* them so blacks stay black.
|
|
59915
|
+
*/
|
|
59916
|
+
finish: ["vignette=angle=PI/5", "noise=alls=7:allf=t"],
|
|
59917
|
+
/** Base segment length for a ken-burns keyframe fallback (no clip to probe). */
|
|
59918
|
+
kenburnsSec: 4,
|
|
59919
|
+
/** Slow-push ceiling for the ken-burns zoom. */
|
|
59920
|
+
kenburnsMaxZoom: 1.1
|
|
59921
|
+
};
|
|
59922
|
+
round3 = (n) => Math.round(n * 1e3) / 1e3;
|
|
59923
|
+
round6 = (n) => Math.round(n * 1e6) / 1e6;
|
|
59924
|
+
DEFAULT_FOOTAGE_OUTPUT = "renders/footage.mp4";
|
|
59925
|
+
}
|
|
59926
|
+
});
|
|
59927
|
+
|
|
59474
59928
|
// src/commands/_shared/scene-audio-scan.ts
|
|
59475
59929
|
import { readFile as readFile41 } from "node:fs/promises";
|
|
59476
|
-
import { resolve as
|
|
59930
|
+
import { resolve as resolve59 } from "node:path";
|
|
59477
59931
|
function parseRootClips(rootHtml) {
|
|
59478
59932
|
const clips = [];
|
|
59479
59933
|
const clipRegex = /<div\b[^>]*class="clip"[^>]*>/gi;
|
|
@@ -59511,7 +59965,7 @@ function parseSceneAudios(compositionHtml) {
|
|
|
59511
59965
|
}
|
|
59512
59966
|
function makeFsCompositionReader(projectDir) {
|
|
59513
59967
|
return async (compositionSrcRel) => {
|
|
59514
|
-
const abs =
|
|
59968
|
+
const abs = resolve59(projectDir, compositionSrcRel);
|
|
59515
59969
|
try {
|
|
59516
59970
|
return await readFile41(abs, "utf-8");
|
|
59517
59971
|
} catch {
|
|
@@ -59530,7 +59984,7 @@ async function scanSceneAudio(opts) {
|
|
|
59530
59984
|
for (const audio of audios) {
|
|
59531
59985
|
out.push({
|
|
59532
59986
|
srcRel: audio.srcRel,
|
|
59533
|
-
srcAbs:
|
|
59987
|
+
srcAbs: resolve59(opts.projectDir, audio.srcRel),
|
|
59534
59988
|
absoluteStart: clip.start + audio.localStart,
|
|
59535
59989
|
durationHint: audio.durationHint,
|
|
59536
59990
|
clipDurationCap: clip.duration - audio.localStart,
|
|
@@ -59545,7 +59999,7 @@ async function scanSceneAudio(opts) {
|
|
|
59545
59999
|
for (const audio of rootAudios) {
|
|
59546
60000
|
out.push({
|
|
59547
60001
|
srcRel: audio.srcRel,
|
|
59548
|
-
srcAbs:
|
|
60002
|
+
srcAbs: resolve59(opts.projectDir, audio.srcRel),
|
|
59549
60003
|
absoluteStart: audio.localStart,
|
|
59550
60004
|
durationHint: audio.durationHint,
|
|
59551
60005
|
clipDurationCap: Math.max(0, maxClipEnd - audio.localStart),
|
|
@@ -59580,7 +60034,7 @@ var init_scene_audio_scan = __esm({
|
|
|
59580
60034
|
|
|
59581
60035
|
// src/commands/_shared/scene-audio-mux.ts
|
|
59582
60036
|
import { rename as rename4, unlink } from "node:fs/promises";
|
|
59583
|
-
import { resolve as
|
|
60037
|
+
import { resolve as resolve60, dirname as dirname20, extname as extname13, basename as basename20 } from "node:path";
|
|
59584
60038
|
function buildAudioMuxFilter(audios) {
|
|
59585
60039
|
if (audios.length === 0) return null;
|
|
59586
60040
|
const labels = [];
|
|
@@ -59640,8 +60094,8 @@ async function muxAudioIntoVideo(opts) {
|
|
|
59640
60094
|
return { success: true, outputPath: opts.videoPath, audioCount: 0 };
|
|
59641
60095
|
}
|
|
59642
60096
|
const ext = extname13(opts.videoPath) || `.${opts.format}`;
|
|
59643
|
-
const tmpPath =
|
|
59644
|
-
|
|
60097
|
+
const tmpPath = resolve60(
|
|
60098
|
+
dirname20(opts.videoPath),
|
|
59645
60099
|
`.${basename20(opts.videoPath, ext)}.muxing${ext}`
|
|
59646
60100
|
);
|
|
59647
60101
|
const args = ["-y", "-loglevel", "error", "-i", opts.videoPath];
|
|
@@ -59703,15 +60157,15 @@ var init_scene_audio_mux = __esm({
|
|
|
59703
60157
|
});
|
|
59704
60158
|
|
|
59705
60159
|
// src/commands/_shared/scene-assemble.ts
|
|
59706
|
-
import { existsSync as
|
|
60160
|
+
import { existsSync as existsSync49 } from "node:fs";
|
|
59707
60161
|
import { readFile as readFile42 } from "node:fs/promises";
|
|
59708
|
-
import { resolve as
|
|
60162
|
+
import { resolve as resolve61, isAbsolute as isAbsolute7 } from "node:path";
|
|
59709
60163
|
async function executeSceneAssemble(opts) {
|
|
59710
|
-
const projectDir =
|
|
60164
|
+
const projectDir = resolve61(opts.projectDir);
|
|
59711
60165
|
const root = opts.root ?? "index.html";
|
|
59712
60166
|
const format = opts.format ?? "mp4";
|
|
59713
|
-
const videoPath =
|
|
59714
|
-
if (!
|
|
60167
|
+
const videoPath = isAbsolute7(opts.videoPath) ? opts.videoPath : resolve61(projectDir, opts.videoPath);
|
|
60168
|
+
if (!existsSync49(videoPath)) {
|
|
59715
60169
|
return {
|
|
59716
60170
|
success: false,
|
|
59717
60171
|
audioCount: 0,
|
|
@@ -59720,8 +60174,8 @@ async function executeSceneAssemble(opts) {
|
|
|
59720
60174
|
error: `Video not found: ${videoPath}. Render it first (e.g. \`vibe render --silent\`).`
|
|
59721
60175
|
};
|
|
59722
60176
|
}
|
|
59723
|
-
const rootPath =
|
|
59724
|
-
if (!
|
|
60177
|
+
const rootPath = resolve61(projectDir, root);
|
|
60178
|
+
if (!existsSync49(rootPath)) {
|
|
59725
60179
|
return {
|
|
59726
60180
|
success: false,
|
|
59727
60181
|
audioCount: 0,
|
|
@@ -59788,9 +60242,9 @@ __export(scene_render_exports, {
|
|
|
59788
60242
|
qualityToCrf: () => qualityToCrf2
|
|
59789
60243
|
});
|
|
59790
60244
|
import { execFile as execFile2 } from "node:child_process";
|
|
59791
|
-
import { existsSync as
|
|
59792
|
-
import { mkdir as
|
|
59793
|
-
import { resolve as
|
|
60245
|
+
import { existsSync as existsSync50 } from "node:fs";
|
|
60246
|
+
import { mkdir as mkdir25, readFile as readFile43, stat as stat8, writeFile as writeFile45 } from "node:fs/promises";
|
|
60247
|
+
import { resolve as resolve62, relative as relative10, dirname as dirname21, basename as basename21, join as join27, isAbsolute as isAbsolute8 } from "node:path";
|
|
59794
60248
|
import { promisify as promisify2 } from "node:util";
|
|
59795
60249
|
import {
|
|
59796
60250
|
createRenderJob,
|
|
@@ -59803,9 +60257,9 @@ function defaultOutputPath(opts) {
|
|
|
59803
60257
|
const fmt = opts.format ?? "mp4";
|
|
59804
60258
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
59805
60259
|
const stamp = now.toISOString().replace(/[:T]/g, "-").replace(/\..+$/, "");
|
|
59806
|
-
const name = (opts.projectName ?? basename21(
|
|
60260
|
+
const name = (opts.projectName ?? basename21(resolve62(opts.projectDir))) || "scene";
|
|
59807
60261
|
const beat = opts.beatId ? `-${sanitizeFileSegment2(opts.beatId)}` : "";
|
|
59808
|
-
return
|
|
60262
|
+
return resolve62(opts.projectDir, "renders", `${name}${beat}-${stamp}.${fmt}`);
|
|
59809
60263
|
}
|
|
59810
60264
|
function buildRenderConfig(opts) {
|
|
59811
60265
|
const quality = opts.quality ?? "standard";
|
|
@@ -59843,7 +60297,7 @@ function buildMediaOpenCommand(action, filePath, platform3 = process.platform) {
|
|
|
59843
60297
|
display: ["cmd", ...args].map(quoteCliArg).join(" ")
|
|
59844
60298
|
};
|
|
59845
60299
|
}
|
|
59846
|
-
const target = action === "reveal" ?
|
|
60300
|
+
const target = action === "reveal" ? dirname21(filePath) : filePath;
|
|
59847
60301
|
return {
|
|
59848
60302
|
command: "xdg-open",
|
|
59849
60303
|
args: [target],
|
|
@@ -59851,7 +60305,7 @@ function buildMediaOpenCommand(action, filePath, platform3 = process.platform) {
|
|
|
59851
60305
|
};
|
|
59852
60306
|
}
|
|
59853
60307
|
async function executeSceneRender(opts = {}) {
|
|
59854
|
-
const projectDir =
|
|
60308
|
+
const projectDir = resolve62(opts.projectDir ?? ".");
|
|
59855
60309
|
const projectConfig = await readProjectConfig(projectDir);
|
|
59856
60310
|
const engine = projectConfig.config.composition.engine;
|
|
59857
60311
|
if (engine !== "hyperframes") {
|
|
@@ -59882,7 +60336,7 @@ async function executeSceneRender(opts = {}) {
|
|
|
59882
60336
|
}
|
|
59883
60337
|
let autoSyncApplied = false;
|
|
59884
60338
|
let autoSyncWarning;
|
|
59885
|
-
if (!opts.beatId &&
|
|
60339
|
+
if (!opts.beatId && existsSync50(join27(projectDir, "STORYBOARD.md"))) {
|
|
59886
60340
|
try {
|
|
59887
60341
|
const rootPlan = await createProjectRootSyncPlan({ projectDir });
|
|
59888
60342
|
const subPlans = await createSubCompDurationSyncPlans({
|
|
@@ -59924,7 +60378,7 @@ async function executeSceneRender(opts = {}) {
|
|
|
59924
60378
|
kind: "render",
|
|
59925
60379
|
beat: opts.beatId ?? null,
|
|
59926
60380
|
root,
|
|
59927
|
-
error: `Root composition not found: ${
|
|
60381
|
+
error: `Root composition not found: ${resolve62(projectDir, root)}. Run \`vibe build ${projectDir}\` once to create the render scaffold, or scaffold it up front with \`vibe init <dir> --profile full\`.`
|
|
59928
60382
|
};
|
|
59929
60383
|
}
|
|
59930
60384
|
const chrome = await preflightChrome();
|
|
@@ -59938,8 +60392,8 @@ async function executeSceneRender(opts = {}) {
|
|
|
59938
60392
|
};
|
|
59939
60393
|
}
|
|
59940
60394
|
const projectName = projectConfig.config.name;
|
|
59941
|
-
const outputPath = opts.output ?
|
|
59942
|
-
await
|
|
60395
|
+
const outputPath = opts.output ? resolve62(projectDir, opts.output) : defaultOutputPath({ projectDir, projectName, format: opts.format, beatId: opts.beatId });
|
|
60396
|
+
await mkdir25(dirname21(outputPath), { recursive: true });
|
|
59943
60397
|
const config2 = buildRenderConfig({
|
|
59944
60398
|
fps: opts.fps,
|
|
59945
60399
|
quality: opts.quality,
|
|
@@ -60051,11 +60505,11 @@ async function safeStat(p) {
|
|
|
60051
60505
|
}
|
|
60052
60506
|
async function prepareBeatRenderRoot(opts) {
|
|
60053
60507
|
const root = `.vibeframe/tmp/render-beat-${sanitizeFileSegment2(opts.beatId)}.html`;
|
|
60054
|
-
const reportPath =
|
|
60508
|
+
const reportPath = join27(opts.projectDir, "build-report.json");
|
|
60055
60509
|
const retryWith = [
|
|
60056
60510
|
`vibe build ${opts.projectDir} --beat ${opts.beatId} --stage sync --json`
|
|
60057
60511
|
];
|
|
60058
|
-
if (!
|
|
60512
|
+
if (!existsSync50(reportPath)) {
|
|
60059
60513
|
return {
|
|
60060
60514
|
success: false,
|
|
60061
60515
|
root,
|
|
@@ -60135,8 +60589,8 @@ async function prepareBeatRenderRoot(opts) {
|
|
|
60135
60589
|
durationSec,
|
|
60136
60590
|
narrationPath
|
|
60137
60591
|
});
|
|
60138
|
-
await
|
|
60139
|
-
await
|
|
60592
|
+
await mkdir25(dirname21(join27(opts.projectDir, root)), { recursive: true });
|
|
60593
|
+
await writeFile45(join27(opts.projectDir, root), html, "utf-8");
|
|
60140
60594
|
return {
|
|
60141
60595
|
success: true,
|
|
60142
60596
|
root,
|
|
@@ -60200,9 +60654,9 @@ function reportedBeatAssetPaths(beat) {
|
|
|
60200
60654
|
]);
|
|
60201
60655
|
}
|
|
60202
60656
|
async function writeRenderReport(projectDir, result) {
|
|
60203
|
-
const reportPath =
|
|
60657
|
+
const reportPath = join27(projectDir, "render-report.json");
|
|
60204
60658
|
try {
|
|
60205
|
-
await
|
|
60659
|
+
await writeFile45(
|
|
60206
60660
|
reportPath,
|
|
60207
60661
|
JSON.stringify(
|
|
60208
60662
|
{
|
|
@@ -60241,8 +60695,8 @@ async function writeRenderReport(projectDir, result) {
|
|
|
60241
60695
|
}
|
|
60242
60696
|
}
|
|
60243
60697
|
function pathExists3(projectDir, value) {
|
|
60244
|
-
const abs =
|
|
60245
|
-
return
|
|
60698
|
+
const abs = isAbsolute8(value) ? value : resolve62(projectDir, value);
|
|
60699
|
+
return existsSync50(abs);
|
|
60246
60700
|
}
|
|
60247
60701
|
function stringValue(value) {
|
|
60248
60702
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
@@ -60295,14 +60749,15 @@ var init_scene_build_mode = __esm({
|
|
|
60295
60749
|
var scene_build_exports = {};
|
|
60296
60750
|
__export(scene_build_exports, {
|
|
60297
60751
|
executeSceneBuild: () => executeSceneBuild,
|
|
60752
|
+
isLikenessRejection: () => isLikenessRejection,
|
|
60298
60753
|
resolveSceneBuildMode: () => resolveSceneBuildMode
|
|
60299
60754
|
});
|
|
60300
|
-
import { existsSync as
|
|
60301
|
-
import { copyFile as copyFile5, mkdir as
|
|
60302
|
-
import { dirname as
|
|
60755
|
+
import { existsSync as existsSync51, readFileSync as readFileSync2 } from "node:fs";
|
|
60756
|
+
import { copyFile as copyFile5, mkdir as mkdir26, readFile as readFile44, rm as rm5, writeFile as writeFile46 } from "node:fs/promises";
|
|
60757
|
+
import { dirname as dirname22, join as join28, resolve as resolve63 } from "node:path";
|
|
60303
60758
|
function readProjectKindSync(projectDir) {
|
|
60304
60759
|
try {
|
|
60305
|
-
const raw = readFileSync2(
|
|
60760
|
+
const raw = readFileSync2(join28(projectDir, "vibe.config.json"), "utf-8");
|
|
60306
60761
|
const k = JSON.parse(raw).kind;
|
|
60307
60762
|
return typeof k === "string" && isSceneKind(k) ? k : "cinema";
|
|
60308
60763
|
} catch {
|
|
@@ -60311,16 +60766,17 @@ function readProjectKindSync(projectDir) {
|
|
|
60311
60766
|
}
|
|
60312
60767
|
async function executeSceneBuild(opts) {
|
|
60313
60768
|
const startedAt = Date.now();
|
|
60314
|
-
const projectDir =
|
|
60769
|
+
const projectDir = resolve63(opts.projectDir);
|
|
60315
60770
|
const onProgress = opts.onProgress ?? (() => {
|
|
60316
60771
|
});
|
|
60317
60772
|
const projectKind = readProjectKindSync(projectDir);
|
|
60318
60773
|
const kindPolicy = kindAssetPolicy(projectKind);
|
|
60319
60774
|
const composer = opts.composer ?? composerDefaultForKind(projectKind);
|
|
60320
|
-
const skipBackdrop = opts.skipBackdrop ?? kindPolicy.skipBackdrop ?? false;
|
|
60775
|
+
const skipBackdrop = opts.skipBackdrop ?? (composer === "footage" ? true : kindPolicy.skipBackdrop ?? false);
|
|
60321
60776
|
const skipKeyframe = opts.skipKeyframe ?? kindPolicy.skipKeyframe ?? false;
|
|
60322
60777
|
const skipVideoAssets = opts.skipVideo ?? kindPolicy.skipVideo ?? false;
|
|
60323
|
-
const
|
|
60778
|
+
const skipTranscript = opts.skipTranscript ?? composer === "footage";
|
|
60779
|
+
const mode = composer === "template" || composer === "footage" ? "batch" : resolveSceneBuildMode(opts);
|
|
60324
60780
|
const selectedStage = opts.stage ?? (opts.skipRender ? "sync" : "all");
|
|
60325
60781
|
const skipVideoStopsRender = (opts.skipVideo ?? false) && (selectedStage === "all" || selectedStage === "render");
|
|
60326
60782
|
const effectiveSkipRender = (opts.skipRender ?? false) || skipVideoStopsRender;
|
|
@@ -60333,7 +60789,7 @@ async function executeSceneBuild(opts) {
|
|
|
60333
60789
|
);
|
|
60334
60790
|
}
|
|
60335
60791
|
let sceneRepair = skippedSceneRepairSummary();
|
|
60336
|
-
const storyboardPath2 =
|
|
60792
|
+
const storyboardPath2 = join28(projectDir, "STORYBOARD.md");
|
|
60337
60793
|
const buildPlan = await createBuildPlan({
|
|
60338
60794
|
projectDir,
|
|
60339
60795
|
stage: selectedStage,
|
|
@@ -60349,17 +60805,38 @@ async function executeSceneBuild(opts) {
|
|
|
60349
60805
|
imageProvider: opts.imageProvider,
|
|
60350
60806
|
imageQuality: opts.imageQuality,
|
|
60351
60807
|
imageSize: opts.imageSize,
|
|
60808
|
+
imageModel: opts.imageModel,
|
|
60352
60809
|
videoProvider: opts.videoProvider,
|
|
60353
60810
|
musicProvider: opts.musicProvider,
|
|
60811
|
+
skipTranscript,
|
|
60354
60812
|
composer,
|
|
60355
60813
|
force: opts.force
|
|
60356
60814
|
});
|
|
60357
60815
|
warnings.push(...buildPlan.warnings);
|
|
60358
60816
|
retryWith.push(...buildPlan.retryWith);
|
|
60359
|
-
const finishBuildResult = (result) =>
|
|
60360
|
-
|
|
60361
|
-
|
|
60362
|
-
|
|
60817
|
+
const finishBuildResult = async (result) => {
|
|
60818
|
+
const withResolution = {
|
|
60819
|
+
providerResolution: buildPlan.providerResolution,
|
|
60820
|
+
...result
|
|
60821
|
+
};
|
|
60822
|
+
let reportResult = withResolution;
|
|
60823
|
+
if (opts.beatId && result.beats?.length) {
|
|
60824
|
+
try {
|
|
60825
|
+
const parsedAll = parseStoryboard(await loadStoryboardMarkdown(projectDir));
|
|
60826
|
+
reportResult = {
|
|
60827
|
+
...withResolution,
|
|
60828
|
+
beats: mergeBeatOutcomes(
|
|
60829
|
+
collectExistingBeatOutcomes(parsedAll.beats, projectDir),
|
|
60830
|
+
result.beats
|
|
60831
|
+
),
|
|
60832
|
+
beatSummary: void 0
|
|
60833
|
+
// recomputed from the merged beats
|
|
60834
|
+
};
|
|
60835
|
+
} catch {
|
|
60836
|
+
}
|
|
60837
|
+
}
|
|
60838
|
+
return finalizeBuildResult(projectDir, startedAt, withResolution, reportResult);
|
|
60839
|
+
};
|
|
60363
60840
|
if (shouldRunStage(selectedStage, "assets") || shouldRunStage(selectedStage, "sync")) {
|
|
60364
60841
|
if (!ffmpegToolsAvailable()) {
|
|
60365
60842
|
return finishBuildResult({
|
|
@@ -60384,7 +60861,7 @@ async function executeSceneBuild(opts) {
|
|
|
60384
60861
|
}
|
|
60385
60862
|
if (!buildPlan.validation.ok) {
|
|
60386
60863
|
let invalidBeats = [];
|
|
60387
|
-
if (
|
|
60864
|
+
if (existsSync51(storyboardPath2)) {
|
|
60388
60865
|
invalidBeats = parseStoryboard(await loadStoryboardMarkdown(projectDir)).beats;
|
|
60389
60866
|
}
|
|
60390
60867
|
return finishBuildResult({
|
|
@@ -60409,7 +60886,7 @@ async function executeSceneBuild(opts) {
|
|
|
60409
60886
|
totalLatencyMs: Date.now() - startedAt
|
|
60410
60887
|
});
|
|
60411
60888
|
}
|
|
60412
|
-
if (!
|
|
60889
|
+
if (!existsSync51(storyboardPath2)) {
|
|
60413
60890
|
return finishBuildResult({
|
|
60414
60891
|
success: false,
|
|
60415
60892
|
phase: "failed",
|
|
@@ -60504,6 +60981,7 @@ async function executeSceneBuild(opts) {
|
|
|
60504
60981
|
imageProvider,
|
|
60505
60982
|
imageSize: opts.imageSize ?? "1536x1024",
|
|
60506
60983
|
imageQuality: opts.imageQuality ?? "hd",
|
|
60984
|
+
imageModel: opts.imageModel,
|
|
60507
60985
|
force: opts.force ?? false,
|
|
60508
60986
|
onProgress
|
|
60509
60987
|
}
|
|
@@ -60525,6 +61003,7 @@ async function executeSceneBuild(opts) {
|
|
|
60525
61003
|
musicProvider,
|
|
60526
61004
|
imageQuality: opts.imageQuality ?? "hd",
|
|
60527
61005
|
imageSize: opts.imageSize ?? "1536x1024",
|
|
61006
|
+
imageModel: opts.imageModel,
|
|
60528
61007
|
skipNarration: opts.skipNarration ?? false,
|
|
60529
61008
|
skipBackdrop,
|
|
60530
61009
|
skipVideo: skipVideoAssets,
|
|
@@ -60614,7 +61093,7 @@ async function executeSceneBuild(opts) {
|
|
|
60614
61093
|
totalLatencyMs: Date.now() - startedAt
|
|
60615
61094
|
});
|
|
60616
61095
|
}
|
|
60617
|
-
if (shouldRunStage(selectedStage, "transcript") && !
|
|
61096
|
+
if (shouldRunStage(selectedStage, "transcript") && !skipTranscript) {
|
|
60618
61097
|
const { statuses } = await runTranscriptStage(activeBeats, beatOutcomes, {
|
|
60619
61098
|
projectDir,
|
|
60620
61099
|
force: opts.force ?? false,
|
|
@@ -60643,9 +61122,9 @@ async function executeSceneBuild(opts) {
|
|
|
60643
61122
|
}
|
|
60644
61123
|
if (shouldRunStage(selectedStage, "compose")) {
|
|
60645
61124
|
if (mode === "agent") {
|
|
60646
|
-
const compositionsDir =
|
|
61125
|
+
const compositionsDir = join28(projectDir, "compositions");
|
|
60647
61126
|
const missingBeats = activeBeats.filter(
|
|
60648
|
-
(b) => !
|
|
61127
|
+
(b) => !existsSync51(join28(compositionsDir, `scene-${b.id}.html`))
|
|
60649
61128
|
);
|
|
60650
61129
|
if (missingBeats.length > 0) {
|
|
60651
61130
|
const plan = await getComposePrompts({ projectDir, beatId: opts.beatId });
|
|
@@ -60679,6 +61158,8 @@ async function executeSceneBuild(opts) {
|
|
|
60679
61158
|
}
|
|
60680
61159
|
onProgress({ type: "phase-start", phase: "compose" });
|
|
60681
61160
|
stageReports.compose.status = "done";
|
|
61161
|
+
} else if (composer === "footage") {
|
|
61162
|
+
stageReports.compose.status = "skipped";
|
|
60682
61163
|
} else if (composer === "template") {
|
|
60683
61164
|
onProgress({ type: "phase-start", phase: "compose" });
|
|
60684
61165
|
try {
|
|
@@ -60718,8 +61199,8 @@ async function executeSceneBuild(opts) {
|
|
|
60718
61199
|
if (stageReports.compose.status === "done") {
|
|
60719
61200
|
for (const beat of composer === "template" ? [] : activeBeats) {
|
|
60720
61201
|
const videoRel = `assets/video-${beat.id}.mp4`;
|
|
60721
|
-
const compositionAbs =
|
|
60722
|
-
if (!
|
|
61202
|
+
const compositionAbs = join28(projectDir, "compositions", `scene-${beat.id}.html`);
|
|
61203
|
+
if (!existsSync51(join28(projectDir, videoRel)) || !existsSync51(compositionAbs)) continue;
|
|
60723
61204
|
const html = readFileSync2(compositionAbs, "utf-8");
|
|
60724
61205
|
if (!html.includes(videoRel)) {
|
|
60725
61206
|
warnings.push(
|
|
@@ -60774,8 +61255,8 @@ async function executeSceneBuild(opts) {
|
|
|
60774
61255
|
totalLatencyMs: Date.now() - startedAt
|
|
60775
61256
|
});
|
|
60776
61257
|
}
|
|
60777
|
-
if (shouldRunStage(selectedStage, "sync")) {
|
|
60778
|
-
if (!
|
|
61258
|
+
if (composer !== "footage" && shouldRunStage(selectedStage, "sync")) {
|
|
61259
|
+
if (!existsSync51(join28(projectDir, "index.html"))) {
|
|
60779
61260
|
await scaffoldSceneProject({
|
|
60780
61261
|
dir: projectDir,
|
|
60781
61262
|
name: projectDir.split(/[\\/]/).filter(Boolean).pop(),
|
|
@@ -60844,7 +61325,50 @@ async function executeSceneBuild(opts) {
|
|
|
60844
61325
|
}
|
|
60845
61326
|
let outputPath;
|
|
60846
61327
|
let renderResult;
|
|
60847
|
-
|
|
61328
|
+
let footageReport;
|
|
61329
|
+
if (composer === "footage" && shouldRunStage(selectedStage, "render")) {
|
|
61330
|
+
onProgress({ type: "phase-start", phase: "render" });
|
|
61331
|
+
onProgress({ type: "render-start" });
|
|
61332
|
+
const assembled = await executeFootageAssemble({ projectDir, finish: true });
|
|
61333
|
+
if (!assembled.success) {
|
|
61334
|
+
stageReports.render.status = "failed";
|
|
61335
|
+
const renderRetryWith = unique5([
|
|
61336
|
+
...retryWith,
|
|
61337
|
+
`vibe build ${projectDir} --stage assets --json`,
|
|
61338
|
+
`vibe assemble ${projectDir} --footage --dry-run --json`
|
|
61339
|
+
]);
|
|
61340
|
+
stageReports.render.retryWith = unique5([
|
|
61341
|
+
...stageReports.render.retryWith,
|
|
61342
|
+
...renderRetryWith
|
|
61343
|
+
]);
|
|
61344
|
+
return finishBuildResult({
|
|
61345
|
+
success: false,
|
|
61346
|
+
phase: "failed",
|
|
61347
|
+
mode,
|
|
61348
|
+
selectedStage,
|
|
61349
|
+
code: "FOOTAGE_ASSEMBLE_FAILED",
|
|
61350
|
+
error: `footage assemble failed: ${assembled.error ?? "unknown"}`,
|
|
61351
|
+
message: `footage assemble failed: ${assembled.error ?? "unknown"}`,
|
|
61352
|
+
suggestion: assembled.suggestion ?? "Ensure every beat has a generated clip (run --stage assets), then retry.",
|
|
61353
|
+
recoverable: true,
|
|
61354
|
+
beats: beatOutcomes,
|
|
61355
|
+
estimatedCostUsd: buildPlan.estimatedCostUsd,
|
|
61356
|
+
costUsd: stageReports.assets.costUsd + stageReports.compose.costUsd,
|
|
61357
|
+
stageReports,
|
|
61358
|
+
sceneRepair,
|
|
61359
|
+
warnings,
|
|
61360
|
+
retryWith: renderRetryWith,
|
|
61361
|
+
status: "failed",
|
|
61362
|
+
currentStage: "render",
|
|
61363
|
+
totalLatencyMs: Date.now() - startedAt
|
|
61364
|
+
});
|
|
61365
|
+
}
|
|
61366
|
+
outputPath = assembled.outputPath;
|
|
61367
|
+
footageReport = assembled.report;
|
|
61368
|
+
warnings.push(...assembled.report?.warnings ?? []);
|
|
61369
|
+
onProgress({ type: "render-done", outputPath });
|
|
61370
|
+
stageReports.render.status = "done";
|
|
61371
|
+
} else if (shouldRunStage(selectedStage, "render")) {
|
|
60848
61372
|
onProgress({ type: "phase-start", phase: "render" });
|
|
60849
61373
|
onProgress({ type: "render-start" });
|
|
60850
61374
|
renderResult = await executeSceneRender({ projectDir });
|
|
@@ -60899,6 +61423,7 @@ async function executeSceneBuild(opts) {
|
|
|
60899
61423
|
beats: beatOutcomes,
|
|
60900
61424
|
outputPath,
|
|
60901
61425
|
renderResult,
|
|
61426
|
+
footageReport,
|
|
60902
61427
|
estimatedCostUsd: buildPlan.estimatedCostUsd,
|
|
60903
61428
|
costUsd: stageReports.assets.costUsd + stageReports.compose.costUsd,
|
|
60904
61429
|
stageReports,
|
|
@@ -61033,7 +61558,7 @@ async function dispatchNarration(beat, ctx) {
|
|
|
61033
61558
|
return {
|
|
61034
61559
|
status: "cached",
|
|
61035
61560
|
path: existingRel,
|
|
61036
|
-
durationSec: await safeAudioDuration(
|
|
61561
|
+
durationSec: await safeAudioDuration(join28(ctx.projectDir, existingRel)),
|
|
61037
61562
|
provider: metadata?.provider,
|
|
61038
61563
|
cachePath: metadata?.cachePath,
|
|
61039
61564
|
cacheKey: metadata?.cacheKey,
|
|
@@ -61057,9 +61582,9 @@ async function dispatchNarration(beat, ctx) {
|
|
|
61057
61582
|
voice,
|
|
61058
61583
|
ext: resolution.audioExtension
|
|
61059
61584
|
});
|
|
61060
|
-
const cacheAbs =
|
|
61585
|
+
const cacheAbs = join28(ctx.projectDir, cache.path);
|
|
61061
61586
|
const rel = `assets/narration-${beat.id}.${resolution.audioExtension}`;
|
|
61062
|
-
const abs =
|
|
61587
|
+
const abs = join28(ctx.projectDir, rel);
|
|
61063
61588
|
if (existingRel && !ctx.force && isFreshCanonicalAsset({
|
|
61064
61589
|
projectDir: ctx.projectDir,
|
|
61065
61590
|
kind: "narration",
|
|
@@ -61073,7 +61598,7 @@ async function dispatchNarration(beat, ctx) {
|
|
|
61073
61598
|
return {
|
|
61074
61599
|
status: "cached",
|
|
61075
61600
|
path: existingRel,
|
|
61076
|
-
durationSec: await safeAudioDuration(
|
|
61601
|
+
durationSec: await safeAudioDuration(join28(ctx.projectDir, existingRel)),
|
|
61077
61602
|
provider: resolution.provider,
|
|
61078
61603
|
cachePath: cache.path,
|
|
61079
61604
|
cacheKey: cache.key,
|
|
@@ -61081,8 +61606,8 @@ async function dispatchNarration(beat, ctx) {
|
|
|
61081
61606
|
freshness: "fresh"
|
|
61082
61607
|
};
|
|
61083
61608
|
}
|
|
61084
|
-
if (
|
|
61085
|
-
await
|
|
61609
|
+
if (existsSync51(cacheAbs) && !ctx.force) {
|
|
61610
|
+
await mkdir26(dirname22(abs), { recursive: true });
|
|
61086
61611
|
await copyFile5(cacheAbs, abs);
|
|
61087
61612
|
await writeAssetMetadata({
|
|
61088
61613
|
projectDir: ctx.projectDir,
|
|
@@ -61113,14 +61638,14 @@ async function dispatchNarration(beat, ctx) {
|
|
|
61113
61638
|
ctx.onProgress({ type: "narration-failed", beatId: beat.id, error });
|
|
61114
61639
|
return { status: "failed", error };
|
|
61115
61640
|
}
|
|
61116
|
-
await
|
|
61117
|
-
await
|
|
61641
|
+
await mkdir26(dirname22(abs), { recursive: true });
|
|
61642
|
+
await writeFile46(abs, result.audioBuffer);
|
|
61118
61643
|
for (const otherExt of ["mp3", "wav"]) {
|
|
61119
|
-
const sibling =
|
|
61120
|
-
if (sibling !== abs &&
|
|
61644
|
+
const sibling = join28(ctx.projectDir, `assets/narration-${beat.id}.${otherExt}`);
|
|
61645
|
+
if (sibling !== abs && existsSync51(sibling)) await rm5(sibling, { force: true });
|
|
61121
61646
|
}
|
|
61122
|
-
await
|
|
61123
|
-
await
|
|
61647
|
+
await mkdir26(dirname22(cacheAbs), { recursive: true });
|
|
61648
|
+
await writeFile46(cacheAbs, result.audioBuffer);
|
|
61124
61649
|
await writeAssetMetadata({
|
|
61125
61650
|
projectDir: ctx.projectDir,
|
|
61126
61651
|
kind: "narration",
|
|
@@ -61152,8 +61677,8 @@ async function dispatchNarration(beat, ctx) {
|
|
|
61152
61677
|
async function dispatchTranscript(beat, narrationPath, narrationFresh, ctx) {
|
|
61153
61678
|
if (!narrationPath) return "skipped";
|
|
61154
61679
|
const relPath = beatTranscriptRelPath(beat.id);
|
|
61155
|
-
const abs =
|
|
61156
|
-
if (
|
|
61680
|
+
const abs = join28(ctx.projectDir, relPath);
|
|
61681
|
+
if (existsSync51(abs) && !ctx.force && !narrationFresh) {
|
|
61157
61682
|
ctx.onProgress({ type: "transcript-cached", beatId: beat.id, path: relPath });
|
|
61158
61683
|
return "cached";
|
|
61159
61684
|
}
|
|
@@ -61166,7 +61691,7 @@ async function dispatchTranscript(beat, narrationPath, narrationFresh, ctx) {
|
|
|
61166
61691
|
});
|
|
61167
61692
|
return "skipped";
|
|
61168
61693
|
}
|
|
61169
|
-
const words = await transcribeNarrationWords(
|
|
61694
|
+
const words = await transcribeNarrationWords(join28(ctx.projectDir, narrationPath), { apiKey });
|
|
61170
61695
|
if (words.length === 0) {
|
|
61171
61696
|
ctx.onProgress({
|
|
61172
61697
|
type: "transcript-skipped",
|
|
@@ -61176,8 +61701,8 @@ async function dispatchTranscript(beat, narrationPath, narrationFresh, ctx) {
|
|
|
61176
61701
|
return "skipped";
|
|
61177
61702
|
}
|
|
61178
61703
|
try {
|
|
61179
|
-
await
|
|
61180
|
-
await
|
|
61704
|
+
await mkdir26(dirname22(abs), { recursive: true });
|
|
61705
|
+
await writeFile46(abs, JSON.stringify(words, null, 2), "utf-8");
|
|
61181
61706
|
} catch (err) {
|
|
61182
61707
|
ctx.onProgress({
|
|
61183
61708
|
type: "transcript-skipped",
|
|
@@ -61224,7 +61749,7 @@ async function buildCharacters(characters, ctx) {
|
|
|
61224
61749
|
const size = ctx.imageSize ?? "1536x1024";
|
|
61225
61750
|
for (const character of characters) {
|
|
61226
61751
|
if (character.imagePath) {
|
|
61227
|
-
if (
|
|
61752
|
+
if (existsSync51(join28(ctx.projectDir, character.imagePath))) {
|
|
61228
61753
|
paths.set(character.name, character.imagePath);
|
|
61229
61754
|
ctx.onProgress({ type: "character-cached", name: character.name, path: character.imagePath });
|
|
61230
61755
|
} else {
|
|
@@ -61237,16 +61762,17 @@ async function buildCharacters(characters, ctx) {
|
|
|
61237
61762
|
if (!character.prompt) continue;
|
|
61238
61763
|
const prompt3 = characterSheetPrompt(character.name, character.prompt);
|
|
61239
61764
|
const rel = `assets/character-${character.name}.png`;
|
|
61240
|
-
const abs =
|
|
61765
|
+
const abs = join28(ctx.projectDir, rel);
|
|
61241
61766
|
const metadataOptions = { quality: ctx.imageQuality, size };
|
|
61242
61767
|
const cache = characterCacheDescriptor({
|
|
61243
61768
|
name: character.name,
|
|
61244
61769
|
cue: prompt3,
|
|
61245
61770
|
provider: ctx.imageProvider,
|
|
61246
61771
|
quality: ctx.imageQuality,
|
|
61247
|
-
size
|
|
61772
|
+
size,
|
|
61773
|
+
model: ctx.imageModel
|
|
61248
61774
|
});
|
|
61249
|
-
if (
|
|
61775
|
+
if (existsSync51(abs) && !ctx.force) {
|
|
61250
61776
|
const metadata = readAssetMetadata(ctx.projectDir, "character", character.name);
|
|
61251
61777
|
if (!metadata || isFreshCanonicalAsset({
|
|
61252
61778
|
projectDir: ctx.projectDir,
|
|
@@ -61262,9 +61788,9 @@ async function buildCharacters(characters, ctx) {
|
|
|
61262
61788
|
continue;
|
|
61263
61789
|
}
|
|
61264
61790
|
}
|
|
61265
|
-
const cacheAbs =
|
|
61266
|
-
if (
|
|
61267
|
-
await
|
|
61791
|
+
const cacheAbs = join28(ctx.projectDir, cache.path);
|
|
61792
|
+
if (existsSync51(cacheAbs) && !ctx.force) {
|
|
61793
|
+
await mkdir26(dirname22(abs), { recursive: true });
|
|
61268
61794
|
await copyFile5(cacheAbs, abs);
|
|
61269
61795
|
await writeAssetMetadata({
|
|
61270
61796
|
projectDir: ctx.projectDir,
|
|
@@ -61287,7 +61813,8 @@ async function buildCharacters(characters, ctx) {
|
|
|
61287
61813
|
projectDir: ctx.projectDir,
|
|
61288
61814
|
imageProvider: ctx.imageProvider,
|
|
61289
61815
|
imageSize: size,
|
|
61290
|
-
imageQuality: ctx.imageQuality
|
|
61816
|
+
imageQuality: ctx.imageQuality,
|
|
61817
|
+
imageModel: ctx.imageModel
|
|
61291
61818
|
},
|
|
61292
61819
|
imageRatioForSize(size)
|
|
61293
61820
|
);
|
|
@@ -61296,10 +61823,10 @@ async function buildCharacters(characters, ctx) {
|
|
|
61296
61823
|
ctx.onProgress({ type: "character-failed", name: character.name, error: generated.error });
|
|
61297
61824
|
continue;
|
|
61298
61825
|
}
|
|
61299
|
-
await
|
|
61300
|
-
await
|
|
61301
|
-
await
|
|
61302
|
-
await
|
|
61826
|
+
await mkdir26(dirname22(abs), { recursive: true });
|
|
61827
|
+
await writeFile46(abs, generated.buffer);
|
|
61828
|
+
await mkdir26(dirname22(cacheAbs), { recursive: true });
|
|
61829
|
+
await writeFile46(cacheAbs, generated.buffer);
|
|
61303
61830
|
await writeAssetMetadata({
|
|
61304
61831
|
projectDir: ctx.projectDir,
|
|
61305
61832
|
kind: "character",
|
|
@@ -61329,7 +61856,7 @@ async function dispatchBackdrop(beat, ctx) {
|
|
|
61329
61856
|
if (!cue) return { status: "no-cue" };
|
|
61330
61857
|
const prompt3 = augmentBackdropPrompt(cue);
|
|
61331
61858
|
const rel = `assets/backdrop-${beat.id}.png`;
|
|
61332
|
-
const abs =
|
|
61859
|
+
const abs = join28(ctx.projectDir, rel);
|
|
61333
61860
|
const size = ctx.imageSize ?? "1536x1024";
|
|
61334
61861
|
const ratio = imageRatioForSize(size);
|
|
61335
61862
|
const metadataOptions = { quality: ctx.imageQuality, size, ratio };
|
|
@@ -61339,10 +61866,11 @@ async function dispatchBackdrop(beat, ctx) {
|
|
|
61339
61866
|
provider: ctx.imageProvider,
|
|
61340
61867
|
quality: ctx.imageQuality,
|
|
61341
61868
|
size,
|
|
61342
|
-
ratio
|
|
61869
|
+
ratio,
|
|
61870
|
+
model: ctx.imageModel
|
|
61343
61871
|
});
|
|
61344
61872
|
const metadataPath = assetMetadataPath("backdrop", beat.id);
|
|
61345
|
-
if (
|
|
61873
|
+
if (existsSync51(abs) && !ctx.force) {
|
|
61346
61874
|
const metadata = readAssetMetadata(ctx.projectDir, "backdrop", beat.id);
|
|
61347
61875
|
if (!metadata || isFreshCanonicalAsset({
|
|
61348
61876
|
projectDir: ctx.projectDir,
|
|
@@ -61365,9 +61893,9 @@ async function dispatchBackdrop(beat, ctx) {
|
|
|
61365
61893
|
};
|
|
61366
61894
|
}
|
|
61367
61895
|
}
|
|
61368
|
-
const cacheAbs =
|
|
61369
|
-
if (
|
|
61370
|
-
await
|
|
61896
|
+
const cacheAbs = join28(ctx.projectDir, cache.path);
|
|
61897
|
+
if (existsSync51(cacheAbs) && !ctx.force) {
|
|
61898
|
+
await mkdir26(dirname22(abs), { recursive: true });
|
|
61371
61899
|
await copyFile5(cacheAbs, abs);
|
|
61372
61900
|
await writeAssetMetadata({
|
|
61373
61901
|
projectDir: ctx.projectDir,
|
|
@@ -61397,11 +61925,11 @@ async function dispatchBackdrop(beat, ctx) {
|
|
|
61397
61925
|
ctx.onProgress({ type: "backdrop-failed", beatId: beat.id, error });
|
|
61398
61926
|
return { status: "failed", error };
|
|
61399
61927
|
}
|
|
61400
|
-
await
|
|
61928
|
+
await mkdir26(dirname22(abs), { recursive: true });
|
|
61401
61929
|
const buffer = generated.buffer;
|
|
61402
|
-
await
|
|
61403
|
-
await
|
|
61404
|
-
await
|
|
61930
|
+
await writeFile46(abs, buffer);
|
|
61931
|
+
await mkdir26(dirname22(cacheAbs), { recursive: true });
|
|
61932
|
+
await writeFile46(cacheAbs, buffer);
|
|
61405
61933
|
await writeAssetMetadata({
|
|
61406
61934
|
projectDir: ctx.projectDir,
|
|
61407
61935
|
kind: "backdrop",
|
|
@@ -61443,7 +61971,9 @@ async function generateBackdropImage(prompt3, ctx, ratio) {
|
|
|
61443
61971
|
const provider2 = new OpenAIImageProvider();
|
|
61444
61972
|
await provider2.initialize({ apiKey });
|
|
61445
61973
|
const result2 = await provider2.generateImage(prompt3, {
|
|
61446
|
-
|
|
61974
|
+
// CLI input is free-form; an alias the provider doesn't know fails the
|
|
61975
|
+
// API call and surfaces as a beat-scoped backdrop/keyframe error.
|
|
61976
|
+
model: ctx.imageModel ?? "gpt-image-2",
|
|
61447
61977
|
size: ctx.imageSize,
|
|
61448
61978
|
quality: ctx.imageQuality
|
|
61449
61979
|
});
|
|
@@ -61453,7 +61983,7 @@ async function generateBackdropImage(prompt3, ctx, ratio) {
|
|
|
61453
61983
|
const provider2 = new GeminiProvider();
|
|
61454
61984
|
await provider2.initialize({ apiKey });
|
|
61455
61985
|
const result2 = await provider2.generateImage(prompt3, {
|
|
61456
|
-
model: "flash",
|
|
61986
|
+
model: ctx.imageModel ?? "flash",
|
|
61457
61987
|
aspectRatio: ratio
|
|
61458
61988
|
});
|
|
61459
61989
|
return imageBufferFromResult(result2);
|
|
@@ -61486,7 +62016,7 @@ async function editKeyframeImage(prompt3, sheetBuffers, ctx, ratio) {
|
|
|
61486
62016
|
const provider2 = new GeminiProvider();
|
|
61487
62017
|
await provider2.initialize({ apiKey });
|
|
61488
62018
|
const result2 = await provider2.editImage(sheetBuffers, prompt3, {
|
|
61489
|
-
model: "flash",
|
|
62019
|
+
model: ctx.imageModel ?? "flash",
|
|
61490
62020
|
aspectRatio: ratio
|
|
61491
62021
|
});
|
|
61492
62022
|
return imageBufferFromResult(result2);
|
|
@@ -61498,7 +62028,7 @@ async function editKeyframeImage(prompt3, sheetBuffers, ctx, ratio) {
|
|
|
61498
62028
|
}
|
|
61499
62029
|
async function ensureKeyframe(beat, ctx, keyframeCue, characterRefsRel) {
|
|
61500
62030
|
const rel = `assets/keyframe-${beat.id}.png`;
|
|
61501
|
-
const abs =
|
|
62031
|
+
const abs = join28(ctx.projectDir, rel);
|
|
61502
62032
|
const size = ctx.imageSize ?? "1536x1024";
|
|
61503
62033
|
const ratio = imageRatioForSize(size);
|
|
61504
62034
|
const metadataOptions = { quality: ctx.imageQuality, size, ratio };
|
|
@@ -61509,9 +62039,10 @@ async function ensureKeyframe(beat, ctx, keyframeCue, characterRefsRel) {
|
|
|
61509
62039
|
quality: ctx.imageQuality,
|
|
61510
62040
|
size,
|
|
61511
62041
|
ratio,
|
|
61512
|
-
characters: characterRefsRel
|
|
62042
|
+
characters: characterRefsRel,
|
|
62043
|
+
model: ctx.imageModel
|
|
61513
62044
|
});
|
|
61514
|
-
if (
|
|
62045
|
+
if (existsSync51(abs) && !ctx.force) {
|
|
61515
62046
|
const metadata = readAssetMetadata(ctx.projectDir, "keyframe", beat.id);
|
|
61516
62047
|
if (!metadata || isFreshCanonicalAsset({
|
|
61517
62048
|
projectDir: ctx.projectDir,
|
|
@@ -61525,9 +62056,9 @@ async function ensureKeyframe(beat, ctx, keyframeCue, characterRefsRel) {
|
|
|
61525
62056
|
return { status: "cached", rel };
|
|
61526
62057
|
}
|
|
61527
62058
|
}
|
|
61528
|
-
const cacheAbs =
|
|
61529
|
-
if (
|
|
61530
|
-
await
|
|
62059
|
+
const cacheAbs = join28(ctx.projectDir, cache.path);
|
|
62060
|
+
if (existsSync51(cacheAbs) && !ctx.force) {
|
|
62061
|
+
await mkdir26(dirname22(abs), { recursive: true });
|
|
61531
62062
|
await copyFile5(cacheAbs, abs);
|
|
61532
62063
|
await writeAssetMetadata({
|
|
61533
62064
|
projectDir: ctx.projectDir,
|
|
@@ -61544,22 +62075,23 @@ async function ensureKeyframe(beat, ctx, keyframeCue, characterRefsRel) {
|
|
|
61544
62075
|
}
|
|
61545
62076
|
const sheetBuffers = [];
|
|
61546
62077
|
for (const relPath of characterRefsRel) {
|
|
61547
|
-
const sheetAbs =
|
|
61548
|
-
if (
|
|
62078
|
+
const sheetAbs = join28(ctx.projectDir, relPath);
|
|
62079
|
+
if (existsSync51(sheetAbs)) sheetBuffers.push(await readFile44(sheetAbs));
|
|
61549
62080
|
}
|
|
61550
62081
|
const imgCtx = {
|
|
61551
62082
|
projectDir: ctx.projectDir,
|
|
61552
62083
|
imageProvider: ctx.imageProvider,
|
|
61553
62084
|
imageSize: size,
|
|
61554
|
-
imageQuality: ctx.imageQuality
|
|
62085
|
+
imageQuality: ctx.imageQuality,
|
|
62086
|
+
imageModel: ctx.imageModel
|
|
61555
62087
|
};
|
|
61556
62088
|
const identityLock = "Keep the EXACT same person and face as the reference image(s): identical facial features (eyes, nose shape, jawline), skin tone and complexion, hairstyle, hair color, and wardrobe. Do not restyle or change the face. Change only the scene, pose, framing, and lighting. ";
|
|
61557
62089
|
const generated = sheetBuffers.length > 0 ? await editKeyframeImage(`${identityLock}${keyframeCue}`, sheetBuffers, imgCtx, ratio) : await generateBackdropImage(keyframeCue, imgCtx, ratio);
|
|
61558
62090
|
if (!generated.success) return { status: "failed", error: generated.error };
|
|
61559
|
-
await
|
|
61560
|
-
await
|
|
61561
|
-
await
|
|
61562
|
-
await
|
|
62091
|
+
await mkdir26(dirname22(abs), { recursive: true });
|
|
62092
|
+
await writeFile46(abs, generated.buffer);
|
|
62093
|
+
await mkdir26(dirname22(cacheAbs), { recursive: true });
|
|
62094
|
+
await writeFile46(cacheAbs, generated.buffer);
|
|
61563
62095
|
await writeAssetMetadata({
|
|
61564
62096
|
projectDir: ctx.projectDir,
|
|
61565
62097
|
kind: "keyframe",
|
|
@@ -61613,14 +62145,16 @@ async function dispatchVideo(beat, ctx, keyframe) {
|
|
|
61613
62145
|
const keyframeCue = stringOrUndefined4(beat.cues?.keyframe);
|
|
61614
62146
|
const prompt3 = stringOrUndefined4(beat.cues?.video) ?? keyframeCue;
|
|
61615
62147
|
if (!prompt3) return { status: "no-cue" };
|
|
62148
|
+
const providerCue = stringOrUndefined4(beat.cues?.provider);
|
|
62149
|
+
const requestedProvider = providerCue ? resolveBuildVideoProvider(providerCue) : ctx.videoProvider;
|
|
61616
62150
|
const characterRefsRel = beatCharacterNames(beat.cues).map((name) => ctx.characterPaths?.get(name)).filter((p) => typeof p === "string");
|
|
61617
|
-
const characterRefsAbs = characterRefsRel.map((p) =>
|
|
62151
|
+
const characterRefsAbs = characterRefsRel.map((p) => join28(ctx.projectDir, p));
|
|
61618
62152
|
const rel = `assets/video-${beat.id}.mp4`;
|
|
61619
|
-
const abs =
|
|
62153
|
+
const abs = join28(ctx.projectDir, rel);
|
|
61620
62154
|
const cache = videoCacheDescriptor({
|
|
61621
62155
|
beatId: beat.id,
|
|
61622
62156
|
cue: prompt3,
|
|
61623
|
-
provider:
|
|
62157
|
+
provider: requestedProvider,
|
|
61624
62158
|
duration: normalizeVideoDuration(beat.duration),
|
|
61625
62159
|
// Keyframe mode keys the clip to the keyframe prompt; refs feed the keyframe,
|
|
61626
62160
|
// not the clip directly.
|
|
@@ -61628,14 +62162,14 @@ async function dispatchVideo(beat, ctx, keyframe) {
|
|
|
61628
62162
|
keyframe: keyframeCue
|
|
61629
62163
|
});
|
|
61630
62164
|
const metadataPath = assetMetadataPath("video", beat.id);
|
|
61631
|
-
if (
|
|
62165
|
+
if (existsSync51(abs) && !ctx.force) {
|
|
61632
62166
|
const metadata = readAssetMetadata(ctx.projectDir, "video", beat.id);
|
|
61633
62167
|
if (!metadata || isFreshCanonicalAsset({
|
|
61634
62168
|
projectDir: ctx.projectDir,
|
|
61635
62169
|
kind: "video",
|
|
61636
62170
|
beatId: beat.id,
|
|
61637
62171
|
cue: prompt3,
|
|
61638
|
-
provider:
|
|
62172
|
+
provider: requestedProvider,
|
|
61639
62173
|
options: { duration: normalizeVideoDuration(beat.duration), ratio: "16:9" },
|
|
61640
62174
|
cacheKey: cache.key
|
|
61641
62175
|
})) {
|
|
@@ -61643,7 +62177,7 @@ async function dispatchVideo(beat, ctx, keyframe) {
|
|
|
61643
62177
|
return {
|
|
61644
62178
|
status: "cached",
|
|
61645
62179
|
path: rel,
|
|
61646
|
-
provider: metadata?.provider ??
|
|
62180
|
+
provider: metadata?.provider ?? requestedProvider,
|
|
61647
62181
|
cachePath: metadata?.cachePath ?? cache.path,
|
|
61648
62182
|
cacheKey: metadata?.cacheKey ?? cache.key,
|
|
61649
62183
|
metadataPath,
|
|
@@ -61651,16 +62185,16 @@ async function dispatchVideo(beat, ctx, keyframe) {
|
|
|
61651
62185
|
};
|
|
61652
62186
|
}
|
|
61653
62187
|
}
|
|
61654
|
-
const cacheAbs =
|
|
61655
|
-
if (
|
|
61656
|
-
await
|
|
62188
|
+
const cacheAbs = join28(ctx.projectDir, cache.path);
|
|
62189
|
+
if (existsSync51(cacheAbs) && !ctx.force) {
|
|
62190
|
+
await mkdir26(dirname22(abs), { recursive: true });
|
|
61657
62191
|
await copyFile5(cacheAbs, abs);
|
|
61658
62192
|
await writeAssetMetadata({
|
|
61659
62193
|
projectDir: ctx.projectDir,
|
|
61660
62194
|
kind: "video",
|
|
61661
62195
|
beatId: beat.id,
|
|
61662
62196
|
cue: prompt3,
|
|
61663
|
-
provider:
|
|
62197
|
+
provider: requestedProvider,
|
|
61664
62198
|
options: { duration: normalizeVideoDuration(beat.duration), ratio: "16:9" },
|
|
61665
62199
|
cacheKey: cache.key,
|
|
61666
62200
|
canonicalPath: rel,
|
|
@@ -61670,7 +62204,7 @@ async function dispatchVideo(beat, ctx, keyframe) {
|
|
|
61670
62204
|
return {
|
|
61671
62205
|
status: "cached",
|
|
61672
62206
|
path: rel,
|
|
61673
|
-
provider:
|
|
62207
|
+
provider: requestedProvider,
|
|
61674
62208
|
cachePath: cache.path,
|
|
61675
62209
|
cacheKey: cache.key,
|
|
61676
62210
|
metadataPath,
|
|
@@ -61683,11 +62217,11 @@ async function dispatchVideo(beat, ctx, keyframe) {
|
|
|
61683
62217
|
ctx.onProgress({ type: "video-skipped", beatId: beat.id, reason });
|
|
61684
62218
|
return { status: "skipped" };
|
|
61685
62219
|
}
|
|
61686
|
-
const keyframeImageAbs = keyframeImageRel ?
|
|
62220
|
+
const keyframeImageAbs = keyframeImageRel ? join28(ctx.projectDir, keyframeImageRel) : void 0;
|
|
61687
62221
|
loadSceneBuildEnv(ctx.projectDir);
|
|
61688
|
-
const
|
|
62222
|
+
const generateWith = (provider, apiKey) => executeVideoGenerate({
|
|
61689
62223
|
prompt: prompt3,
|
|
61690
|
-
provider
|
|
62224
|
+
provider,
|
|
61691
62225
|
duration: normalizeVideoDuration(beat.duration),
|
|
61692
62226
|
ratio: "16:9",
|
|
61693
62227
|
output: abs,
|
|
@@ -61700,22 +62234,44 @@ async function dispatchVideo(beat, ctx, keyframe) {
|
|
|
61700
62234
|
// track carries audio), so the model's generated audio is never used. Disable
|
|
61701
62235
|
// it: it's wasted, and Seedance's audio moderation can spuriously fail a beat.
|
|
61702
62236
|
generateAudio: false,
|
|
61703
|
-
apiKey
|
|
62237
|
+
apiKey
|
|
61704
62238
|
});
|
|
62239
|
+
let activeProvider = requestedProvider;
|
|
62240
|
+
let result = await generateWith(
|
|
62241
|
+
activeProvider,
|
|
62242
|
+
await apiKeyForVideoProvider(activeProvider, ctx.projectDir)
|
|
62243
|
+
);
|
|
61705
62244
|
if (!result.success || !result.taskId) {
|
|
61706
62245
|
const error = result.error ?? "video generation did not return a task id";
|
|
61707
|
-
|
|
61708
|
-
|
|
62246
|
+
const runwayKey = isLikenessRejection(error) && activeProvider !== "runway" ? await apiKeyForVideoProvider("runway", ctx.projectDir) : void 0;
|
|
62247
|
+
if (!runwayKey) {
|
|
62248
|
+
ctx.onProgress({ type: "video-failed", beatId: beat.id, error });
|
|
62249
|
+
return { status: "failed", error };
|
|
62250
|
+
}
|
|
62251
|
+
ctx.onProgress({
|
|
62252
|
+
type: "video-fallback",
|
|
62253
|
+
beatId: beat.id,
|
|
62254
|
+
from: activeProvider,
|
|
62255
|
+
to: "runway",
|
|
62256
|
+
reason: error
|
|
62257
|
+
});
|
|
62258
|
+
activeProvider = "runway";
|
|
62259
|
+
result = await generateWith(activeProvider, runwayKey);
|
|
62260
|
+
if (!result.success || !result.taskId) {
|
|
62261
|
+
const fallbackError = result.error ?? "video generation did not return a task id";
|
|
62262
|
+
ctx.onProgress({ type: "video-failed", beatId: beat.id, error: fallbackError });
|
|
62263
|
+
return { status: "failed", error: fallbackError };
|
|
62264
|
+
}
|
|
61709
62265
|
}
|
|
61710
|
-
if (result.status === "completed" &&
|
|
61711
|
-
await
|
|
62266
|
+
if (result.status === "completed" && existsSync51(abs)) {
|
|
62267
|
+
await mkdir26(dirname22(cacheAbs), { recursive: true });
|
|
61712
62268
|
await copyFile5(abs, cacheAbs);
|
|
61713
62269
|
await writeAssetMetadata({
|
|
61714
62270
|
projectDir: ctx.projectDir,
|
|
61715
62271
|
kind: "video",
|
|
61716
62272
|
beatId: beat.id,
|
|
61717
62273
|
cue: prompt3,
|
|
61718
|
-
provider: result.provider ??
|
|
62274
|
+
provider: result.provider ?? activeProvider,
|
|
61719
62275
|
options: { duration: normalizeVideoDuration(beat.duration), ratio: "16:9" },
|
|
61720
62276
|
cacheKey: cache.key,
|
|
61721
62277
|
canonicalPath: rel,
|
|
@@ -61725,12 +62281,12 @@ async function dispatchVideo(beat, ctx, keyframe) {
|
|
|
61725
62281
|
type: "video-generated",
|
|
61726
62282
|
beatId: beat.id,
|
|
61727
62283
|
path: rel,
|
|
61728
|
-
provider: result.provider ??
|
|
62284
|
+
provider: result.provider ?? activeProvider
|
|
61729
62285
|
});
|
|
61730
62286
|
return {
|
|
61731
62287
|
status: "generated",
|
|
61732
62288
|
path: rel,
|
|
61733
|
-
provider: result.provider ??
|
|
62289
|
+
provider: result.provider ?? activeProvider,
|
|
61734
62290
|
cachePath: cache.path,
|
|
61735
62291
|
cacheKey: cache.key,
|
|
61736
62292
|
metadataPath,
|
|
@@ -61739,7 +62295,7 @@ async function dispatchVideo(beat, ctx, keyframe) {
|
|
|
61739
62295
|
}
|
|
61740
62296
|
const job = await createAndWriteJobRecord({
|
|
61741
62297
|
jobType: "generate-video",
|
|
61742
|
-
provider: result.provider ??
|
|
62298
|
+
provider: result.provider ?? activeProvider,
|
|
61743
62299
|
providerTaskId: result.taskId,
|
|
61744
62300
|
providerTaskType: keyframeImageAbs ? "image2video" : "text2video",
|
|
61745
62301
|
status: "running",
|
|
@@ -61775,7 +62331,7 @@ async function dispatchMusic(beat, ctx) {
|
|
|
61775
62331
|
const prompt3 = stringOrUndefined4(beat.cues?.music);
|
|
61776
62332
|
if (!prompt3) return { status: "no-cue" };
|
|
61777
62333
|
const rel = `assets/music-${beat.id}.mp3`;
|
|
61778
|
-
const abs =
|
|
62334
|
+
const abs = join28(ctx.projectDir, rel);
|
|
61779
62335
|
const duration = normalizeMusicDuration(beat.duration);
|
|
61780
62336
|
const cache = musicCacheDescriptor({
|
|
61781
62337
|
beatId: beat.id,
|
|
@@ -61784,7 +62340,7 @@ async function dispatchMusic(beat, ctx) {
|
|
|
61784
62340
|
duration
|
|
61785
62341
|
});
|
|
61786
62342
|
const metadataPath = assetMetadataPath("music", beat.id);
|
|
61787
|
-
if (
|
|
62343
|
+
if (existsSync51(abs) && !ctx.force) {
|
|
61788
62344
|
const metadata = readAssetMetadata(ctx.projectDir, "music", beat.id);
|
|
61789
62345
|
if (!metadata || isFreshCanonicalAsset({
|
|
61790
62346
|
projectDir: ctx.projectDir,
|
|
@@ -61808,9 +62364,9 @@ async function dispatchMusic(beat, ctx) {
|
|
|
61808
62364
|
};
|
|
61809
62365
|
}
|
|
61810
62366
|
}
|
|
61811
|
-
const cacheAbs =
|
|
61812
|
-
if (
|
|
61813
|
-
await
|
|
62367
|
+
const cacheAbs = join28(ctx.projectDir, cache.path);
|
|
62368
|
+
if (existsSync51(cacheAbs) && !ctx.force) {
|
|
62369
|
+
await mkdir26(dirname22(abs), { recursive: true });
|
|
61814
62370
|
await copyFile5(cacheAbs, abs);
|
|
61815
62371
|
await writeAssetMetadata({
|
|
61816
62372
|
projectDir: ctx.projectDir,
|
|
@@ -61883,12 +62439,12 @@ async function dispatchMusic(beat, ctx) {
|
|
|
61883
62439
|
metadataPath
|
|
61884
62440
|
};
|
|
61885
62441
|
}
|
|
61886
|
-
if (!
|
|
62442
|
+
if (!existsSync51(abs)) {
|
|
61887
62443
|
const error = result.outputPath ? `music output was not written at ${abs}` : "music generation did not return an output file";
|
|
61888
62444
|
ctx.onProgress({ type: "music-failed", beatId: beat.id, error });
|
|
61889
62445
|
return { status: "failed", error };
|
|
61890
62446
|
}
|
|
61891
|
-
await
|
|
62447
|
+
await mkdir26(dirname22(cacheAbs), { recursive: true });
|
|
61892
62448
|
await copyFile5(abs, cacheAbs);
|
|
61893
62449
|
await writeAssetMetadata({
|
|
61894
62450
|
projectDir: ctx.projectDir,
|
|
@@ -61919,15 +62475,15 @@ async function dispatchMusic(beat, ctx) {
|
|
|
61919
62475
|
};
|
|
61920
62476
|
}
|
|
61921
62477
|
function loadSceneBuildEnv(projectDir) {
|
|
61922
|
-
(0, import_dotenv4.config)({ path:
|
|
61923
|
-
(0, import_dotenv4.config)({ path:
|
|
62478
|
+
(0, import_dotenv4.config)({ path: join28(projectDir, ".env"), quiet: true });
|
|
62479
|
+
(0, import_dotenv4.config)({ path: resolve63(process.cwd(), ".env"), quiet: true });
|
|
61924
62480
|
let dir = process.cwd();
|
|
61925
|
-
while (dir !==
|
|
61926
|
-
if (
|
|
61927
|
-
(0, import_dotenv4.config)({ path:
|
|
62481
|
+
while (dir !== dirname22(dir)) {
|
|
62482
|
+
if (existsSync51(join28(dir, "pnpm-workspace.yaml"))) {
|
|
62483
|
+
(0, import_dotenv4.config)({ path: join28(dir, ".env"), quiet: true });
|
|
61928
62484
|
return;
|
|
61929
62485
|
}
|
|
61930
|
-
dir =
|
|
62486
|
+
dir = dirname22(dir);
|
|
61931
62487
|
}
|
|
61932
62488
|
}
|
|
61933
62489
|
async function skipped(kind, beatId, reason, ctx) {
|
|
@@ -62141,7 +62697,7 @@ function mergeBeatOutcomes(base, updates) {
|
|
|
62141
62697
|
}
|
|
62142
62698
|
function firstExisting3(projectDir, relPaths) {
|
|
62143
62699
|
for (const rel of relPaths) {
|
|
62144
|
-
if (
|
|
62700
|
+
if (existsSync51(join28(projectDir, rel))) return rel;
|
|
62145
62701
|
}
|
|
62146
62702
|
return null;
|
|
62147
62703
|
}
|
|
@@ -62164,6 +62720,9 @@ function resolveBuildMusicProvider(value) {
|
|
|
62164
62720
|
const provider = String(value ?? "elevenlabs").toLowerCase();
|
|
62165
62721
|
return provider === "replicate" ? "replicate" : "elevenlabs";
|
|
62166
62722
|
}
|
|
62723
|
+
function isLikenessRejection(error) {
|
|
62724
|
+
return typeof error === "string" && /likeness(es)? of real people/i.test(error);
|
|
62725
|
+
}
|
|
62167
62726
|
function stringOrUndefined4(value) {
|
|
62168
62727
|
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
62169
62728
|
}
|
|
@@ -62171,26 +62730,30 @@ async function apiKeyForVideoProvider(provider, projectDir) {
|
|
|
62171
62730
|
const providerKey = provider === "seedance" ? "fal" : provider === "grok" ? "xai" : provider === "veo" ? "google" : provider;
|
|
62172
62731
|
return getApiKeyFromConfig(providerKey, { cwd: projectDir });
|
|
62173
62732
|
}
|
|
62174
|
-
async function finalizeBuildResult(projectDir, startedAt, result) {
|
|
62175
|
-
const reportPath =
|
|
62176
|
-
|
|
62177
|
-
|
|
62178
|
-
|
|
62733
|
+
async function finalizeBuildResult(projectDir, startedAt, result, reportResult = result) {
|
|
62734
|
+
const reportPath = join28(projectDir, "build-report.json");
|
|
62735
|
+
for (const source of /* @__PURE__ */ new Set([result, reportResult])) {
|
|
62736
|
+
if (source.stageReports) {
|
|
62737
|
+
for (const report of Object.values(source.stageReports)) {
|
|
62738
|
+
if (report.status === "pending") report.status = "skipped";
|
|
62739
|
+
}
|
|
62179
62740
|
}
|
|
62180
62741
|
}
|
|
62181
|
-
const
|
|
62182
|
-
...
|
|
62183
|
-
status:
|
|
62184
|
-
currentStage:
|
|
62185
|
-
beatSummary:
|
|
62186
|
-
sceneRepair:
|
|
62742
|
+
const decorate = (base) => ({
|
|
62743
|
+
...base,
|
|
62744
|
+
status: base.status ?? buildWorkflowStatus(base),
|
|
62745
|
+
currentStage: base.currentStage ?? buildCurrentStage(base),
|
|
62746
|
+
beatSummary: base.beatSummary ?? summarizeBuildBeats(projectDir, base.beats),
|
|
62747
|
+
sceneRepair: base.sceneRepair ?? skippedSceneRepairSummary(),
|
|
62187
62748
|
reportPath,
|
|
62188
62749
|
totalLatencyMs: Date.now() - startedAt
|
|
62189
|
-
};
|
|
62750
|
+
});
|
|
62751
|
+
const withMeta = decorate(result);
|
|
62752
|
+
const reportMeta = reportResult === result ? withMeta : decorate(reportResult);
|
|
62190
62753
|
try {
|
|
62191
|
-
await
|
|
62754
|
+
await writeFile46(
|
|
62192
62755
|
reportPath,
|
|
62193
|
-
JSON.stringify(toBuildReport(projectDir,
|
|
62756
|
+
JSON.stringify(toBuildReport(projectDir, reportMeta), null, 2) + "\n",
|
|
62194
62757
|
"utf-8"
|
|
62195
62758
|
);
|
|
62196
62759
|
} catch {
|
|
@@ -62331,7 +62894,7 @@ function normalizeReportDuration(value) {
|
|
|
62331
62894
|
}
|
|
62332
62895
|
function buildReportComposition(projectDir, result, beatId) {
|
|
62333
62896
|
const path2 = `compositions/scene-${beatId}.html`;
|
|
62334
|
-
const exists =
|
|
62897
|
+
const exists = existsSync51(join28(projectDir, path2));
|
|
62335
62898
|
if (result.stageReports?.compose.status === "failed") return { path: path2, exists, status: "failed" };
|
|
62336
62899
|
if (result.phase === "needs-author" && !exists) return { path: path2, exists, status: "needs-author" };
|
|
62337
62900
|
if (exists) return { path: path2, exists, status: "exists" };
|
|
@@ -62378,8 +62941,8 @@ function summarizeBuildBeats(projectDir, beats) {
|
|
|
62378
62941
|
let compositionsReady = 0;
|
|
62379
62942
|
for (const beat of beats) {
|
|
62380
62943
|
if (beatAssetsReady(beat)) assetsReady += 1;
|
|
62381
|
-
const compositionPath =
|
|
62382
|
-
if (
|
|
62944
|
+
const compositionPath = join28(projectDir, "compositions", `scene-${beat.beatId}.html`);
|
|
62945
|
+
if (existsSync51(compositionPath)) {
|
|
62383
62946
|
compositionsReady += 1;
|
|
62384
62947
|
} else {
|
|
62385
62948
|
needsAuthor.push(beat.beatId);
|
|
@@ -62419,6 +62982,7 @@ var init_scene_build = __esm({
|
|
|
62419
62982
|
init_ffmpeg_gate();
|
|
62420
62983
|
init_concurrency();
|
|
62421
62984
|
init_compose_aivideo();
|
|
62985
|
+
init_footage_assemble();
|
|
62422
62986
|
init_scene_project();
|
|
62423
62987
|
init_compose_prompts();
|
|
62424
62988
|
init_config();
|
|
@@ -62514,16 +63078,16 @@ __export(ai_audio_exports, {
|
|
|
62514
63078
|
executeTranscribe: () => executeTranscribe,
|
|
62515
63079
|
executeVoiceClone: () => executeVoiceClone
|
|
62516
63080
|
});
|
|
62517
|
-
import { resolve as
|
|
62518
|
-
import { readFile as readFile46, writeFile as
|
|
62519
|
-
import { existsSync as
|
|
63081
|
+
import { resolve as resolve73, dirname as dirname24, basename as basename22, extname as extname14 } from "node:path";
|
|
63082
|
+
import { readFile as readFile46, writeFile as writeFile47 } from "node:fs/promises";
|
|
63083
|
+
import { existsSync as existsSync56 } from "node:fs";
|
|
62520
63084
|
async function executeTranscribe(options) {
|
|
62521
63085
|
const { audioPath, language, output, format, apiKey } = options;
|
|
62522
63086
|
try {
|
|
62523
63087
|
const key = apiKey || process.env.OPENAI_API_KEY;
|
|
62524
63088
|
if (!key) return { success: false, error: "OPENAI_API_KEY required" };
|
|
62525
|
-
const absPath =
|
|
62526
|
-
if (!
|
|
63089
|
+
const absPath = resolve73(process.cwd(), audioPath);
|
|
63090
|
+
if (!existsSync56(absPath)) return { success: false, error: `File not found: ${absPath}` };
|
|
62527
63091
|
const whisper = new WhisperProvider();
|
|
62528
63092
|
await whisper.initialize({ apiKey: key });
|
|
62529
63093
|
const audioBuffer = await readFile46(absPath);
|
|
@@ -62534,10 +63098,10 @@ async function executeTranscribe(options) {
|
|
|
62534
63098
|
}
|
|
62535
63099
|
let outputPath;
|
|
62536
63100
|
if (output) {
|
|
62537
|
-
outputPath =
|
|
63101
|
+
outputPath = resolve73(process.cwd(), output);
|
|
62538
63102
|
const fmt = detectFormat(output, format);
|
|
62539
63103
|
const content = formatTranscript(result, fmt);
|
|
62540
|
-
await
|
|
63104
|
+
await writeFile47(outputPath, content, "utf-8");
|
|
62541
63105
|
}
|
|
62542
63106
|
return {
|
|
62543
63107
|
success: true,
|
|
@@ -62555,8 +63119,8 @@ async function executeIsolate(options) {
|
|
|
62555
63119
|
try {
|
|
62556
63120
|
const key = apiKey || process.env.ELEVENLABS_API_KEY;
|
|
62557
63121
|
if (!key) return { success: false, error: "ELEVENLABS_API_KEY required" };
|
|
62558
|
-
const absPath =
|
|
62559
|
-
if (!
|
|
63122
|
+
const absPath = resolve73(process.cwd(), audioPath);
|
|
63123
|
+
if (!existsSync56(absPath)) return { success: false, error: `File not found: ${absPath}` };
|
|
62560
63124
|
const audioBuffer = await readFile46(absPath);
|
|
62561
63125
|
const elevenlabs = new ElevenLabsProvider();
|
|
62562
63126
|
await elevenlabs.initialize({ apiKey: key });
|
|
@@ -62564,8 +63128,8 @@ async function executeIsolate(options) {
|
|
|
62564
63128
|
if (!result.success || !result.audioBuffer) {
|
|
62565
63129
|
return { success: false, error: result.error || "Audio isolation failed" };
|
|
62566
63130
|
}
|
|
62567
|
-
const outputPath =
|
|
62568
|
-
await
|
|
63131
|
+
const outputPath = resolve73(process.cwd(), output);
|
|
63132
|
+
await writeFile47(outputPath, result.audioBuffer);
|
|
62569
63133
|
return { success: true, outputPath };
|
|
62570
63134
|
} catch (error) {
|
|
62571
63135
|
return { success: false, error: `Audio isolation failed: ${error instanceof Error ? error.message : String(error)}` };
|
|
@@ -62581,8 +63145,8 @@ async function executeVoiceClone(options) {
|
|
|
62581
63145
|
}
|
|
62582
63146
|
const audioBuffers = [];
|
|
62583
63147
|
for (const samplePath of samplePaths) {
|
|
62584
|
-
const absPath =
|
|
62585
|
-
if (!
|
|
63148
|
+
const absPath = resolve73(process.cwd(), samplePath);
|
|
63149
|
+
if (!existsSync56(absPath)) return { success: false, error: `File not found: ${samplePath}` };
|
|
62586
63150
|
const buffer = await readFile46(absPath);
|
|
62587
63151
|
audioBuffers.push(buffer);
|
|
62588
63152
|
}
|
|
@@ -62603,8 +63167,8 @@ async function executeVoiceClone(options) {
|
|
|
62603
63167
|
async function executeDub(options) {
|
|
62604
63168
|
const { mediaPath, language, source, voice, analyzeOnly, output } = options;
|
|
62605
63169
|
try {
|
|
62606
|
-
const absPath =
|
|
62607
|
-
if (!
|
|
63170
|
+
const absPath = resolve73(process.cwd(), mediaPath);
|
|
63171
|
+
if (!existsSync56(absPath)) return { success: false, error: `File not found: ${absPath}` };
|
|
62608
63172
|
const openaiKey = process.env.OPENAI_API_KEY;
|
|
62609
63173
|
const anthropicKey = process.env.ANTHROPIC_API_KEY;
|
|
62610
63174
|
const elevenlabsKey = process.env.ELEVENLABS_API_KEY;
|
|
@@ -62615,7 +63179,7 @@ async function executeDub(options) {
|
|
|
62615
63179
|
const isVideo = [".mp4", ".mov", ".avi", ".mkv", ".webm"].includes(ext);
|
|
62616
63180
|
let audioPath = absPath;
|
|
62617
63181
|
if (isVideo) {
|
|
62618
|
-
const tempAudioPath =
|
|
63182
|
+
const tempAudioPath = resolve73(dirname24(absPath), `temp-audio-${Date.now()}.mp3`);
|
|
62619
63183
|
execSafeSync("ffmpeg", ["-i", absPath, "-vn", "-acodec", "mp3", "-y", tempAudioPath]);
|
|
62620
63184
|
audioPath = tempAudioPath;
|
|
62621
63185
|
}
|
|
@@ -62664,7 +63228,7 @@ ${segmentTexts}`,
|
|
|
62664
63228
|
}
|
|
62665
63229
|
if (analyzeOnly) {
|
|
62666
63230
|
if (output) {
|
|
62667
|
-
const timingPath =
|
|
63231
|
+
const timingPath = resolve73(process.cwd(), output);
|
|
62668
63232
|
const timingData = {
|
|
62669
63233
|
sourcePath: absPath,
|
|
62670
63234
|
sourceLanguage: transcriptResult.detectedLanguage || source || "auto",
|
|
@@ -62676,14 +63240,14 @@ ${segmentTexts}`,
|
|
|
62676
63240
|
translated: translatedSegments[i]?.text || s.text
|
|
62677
63241
|
}))
|
|
62678
63242
|
};
|
|
62679
|
-
await
|
|
63243
|
+
await writeFile47(timingPath, JSON.stringify(timingData, null, 2));
|
|
62680
63244
|
}
|
|
62681
63245
|
return {
|
|
62682
63246
|
success: true,
|
|
62683
63247
|
sourceLanguage: transcriptResult.detectedLanguage || source || "auto",
|
|
62684
63248
|
targetLanguage: language,
|
|
62685
63249
|
segmentCount: segments.length,
|
|
62686
|
-
outputPath: output ?
|
|
63250
|
+
outputPath: output ? resolve73(process.cwd(), output) : void 0
|
|
62687
63251
|
};
|
|
62688
63252
|
}
|
|
62689
63253
|
const elevenlabs = new ElevenLabsProvider();
|
|
@@ -62697,9 +63261,9 @@ ${segmentTexts}`,
|
|
|
62697
63261
|
}
|
|
62698
63262
|
const combinedBuffer = Buffer.concat(dubbedBuffers);
|
|
62699
63263
|
const outputExt = isVideo ? ".mp3" : extname14(absPath);
|
|
62700
|
-
const defaultOutputPath2 =
|
|
62701
|
-
const finalOutputPath =
|
|
62702
|
-
await
|
|
63264
|
+
const defaultOutputPath2 = resolve73(dirname24(absPath), `${basename22(absPath, extname14(absPath))}-${language}${outputExt}`);
|
|
63265
|
+
const finalOutputPath = resolve73(process.cwd(), output || defaultOutputPath2);
|
|
63266
|
+
await writeFile47(finalOutputPath, combinedBuffer);
|
|
62703
63267
|
if (isVideo && audioPath !== absPath) {
|
|
62704
63268
|
try {
|
|
62705
63269
|
const { unlink: unlink3 } = await import("node:fs/promises");
|
|
@@ -62730,12 +63294,12 @@ async function executeDuck(options) {
|
|
|
62730
63294
|
} = options;
|
|
62731
63295
|
try {
|
|
62732
63296
|
if (!commandExists("ffmpeg")) return { success: false, error: "FFmpeg not found" };
|
|
62733
|
-
const absMusicPath =
|
|
62734
|
-
const absVoicePath =
|
|
62735
|
-
if (!
|
|
62736
|
-
if (!
|
|
62737
|
-
const defaultOutput =
|
|
62738
|
-
const outputPath =
|
|
63297
|
+
const absMusicPath = resolve73(process.cwd(), musicPath);
|
|
63298
|
+
const absVoicePath = resolve73(process.cwd(), voicePath);
|
|
63299
|
+
if (!existsSync56(absMusicPath)) return { success: false, error: `Music file not found: ${absMusicPath}` };
|
|
63300
|
+
if (!existsSync56(absVoicePath)) return { success: false, error: `Voice file not found: ${absVoicePath}` };
|
|
63301
|
+
const defaultOutput = resolve73(dirname24(absMusicPath), `${basename22(absMusicPath, extname14(absMusicPath))}-ducked${extname14(absMusicPath)}`);
|
|
63302
|
+
const outputPath = resolve73(process.cwd(), output || defaultOutput);
|
|
62739
63303
|
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`;
|
|
62740
63304
|
await execSafe("ffmpeg", [
|
|
62741
63305
|
"-i",
|
|
@@ -62747,7 +63311,7 @@ async function executeDuck(options) {
|
|
|
62747
63311
|
"-y",
|
|
62748
63312
|
outputPath
|
|
62749
63313
|
], { timeout: 12e4, maxBuffer: 50 * 1024 * 1024 });
|
|
62750
|
-
if (!
|
|
63314
|
+
if (!existsSync56(outputPath)) return { success: false, error: "FFmpeg failed to create output" };
|
|
62751
63315
|
return { success: true, outputPath };
|
|
62752
63316
|
} catch (error) {
|
|
62753
63317
|
return { success: false, error: `Audio ducking failed: ${error instanceof Error ? error.message : String(error)}` };
|
|
@@ -62763,9 +63327,9 @@ var init_ai_audio = __esm({
|
|
|
62763
63327
|
});
|
|
62764
63328
|
|
|
62765
63329
|
// src/pipeline/executor.ts
|
|
62766
|
-
import { resolve as
|
|
62767
|
-
import { readFile as readFile47, writeFile as
|
|
62768
|
-
import { existsSync as
|
|
63330
|
+
import { resolve as resolve74 } from "node:path";
|
|
63331
|
+
import { readFile as readFile47, writeFile as writeFile48, mkdir as mkdir28 } from "node:fs/promises";
|
|
63332
|
+
import { existsSync as existsSync57 } from "node:fs";
|
|
62769
63333
|
function maxCostFor(action) {
|
|
62770
63334
|
const cmd = ACTION_METADATA[action]?.command;
|
|
62771
63335
|
if (!cmd) return 0;
|
|
@@ -62776,9 +63340,9 @@ function registerAction(action, handler) {
|
|
|
62776
63340
|
}
|
|
62777
63341
|
function getOutput(params, outputDir, defaultName) {
|
|
62778
63342
|
if (params.output && typeof params.output === "string") {
|
|
62779
|
-
return
|
|
63343
|
+
return resolve74(outputDir, params.output);
|
|
62780
63344
|
}
|
|
62781
|
-
return
|
|
63345
|
+
return resolve74(outputDir, defaultName);
|
|
62782
63346
|
}
|
|
62783
63347
|
function stringParam(value) {
|
|
62784
63348
|
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
@@ -63008,7 +63572,7 @@ async function ensureActionsRegistered() {
|
|
|
63008
63572
|
const { executeSceneBuild: executeSceneBuild2 } = await Promise.resolve().then(() => (init_scene_build(), scene_build_exports));
|
|
63009
63573
|
const projectRel = params.project ?? ".";
|
|
63010
63574
|
const r = await executeSceneBuild2({
|
|
63011
|
-
projectDir:
|
|
63575
|
+
projectDir: resolve74(outputDir, projectRel),
|
|
63012
63576
|
mode: params.mode,
|
|
63013
63577
|
composer: params.composer,
|
|
63014
63578
|
skipNarration: params.skipNarration,
|
|
@@ -63018,6 +63582,7 @@ async function ensureActionsRegistered() {
|
|
|
63018
63582
|
voice: params.voice,
|
|
63019
63583
|
imageProvider: params.imageProvider,
|
|
63020
63584
|
imageQuality: params.quality,
|
|
63585
|
+
imageModel: params.imageModel,
|
|
63021
63586
|
force: params.force
|
|
63022
63587
|
});
|
|
63023
63588
|
return {
|
|
@@ -63033,7 +63598,7 @@ async function ensureActionsRegistered() {
|
|
|
63033
63598
|
const { executeSceneRender: executeSceneRender2 } = await Promise.resolve().then(() => (init_scene_render(), scene_render_exports));
|
|
63034
63599
|
const projectRel = params.project ?? ".";
|
|
63035
63600
|
const r = await executeSceneRender2({
|
|
63036
|
-
projectDir:
|
|
63601
|
+
projectDir: resolve74(outputDir, projectRel),
|
|
63037
63602
|
root: params.root,
|
|
63038
63603
|
output: params.output,
|
|
63039
63604
|
fps: params.fps,
|
|
@@ -63057,8 +63622,8 @@ async function ensureActionsRegistered() {
|
|
|
63057
63622
|
});
|
|
63058
63623
|
}
|
|
63059
63624
|
async function loadPipeline(filePath) {
|
|
63060
|
-
const absPath =
|
|
63061
|
-
if (!
|
|
63625
|
+
const absPath = resolve74(process.cwd(), filePath);
|
|
63626
|
+
if (!existsSync57(absPath)) {
|
|
63062
63627
|
throw new Error(`Pipeline file not found: ${absPath}`);
|
|
63063
63628
|
}
|
|
63064
63629
|
const content = await readFile47(absPath, "utf-8");
|
|
@@ -63076,14 +63641,14 @@ async function loadPipeline(filePath) {
|
|
|
63076
63641
|
}
|
|
63077
63642
|
async function executePipeline(manifest2, options = {}) {
|
|
63078
63643
|
await ensureActionsRegistered();
|
|
63079
|
-
const outputDir =
|
|
63080
|
-
await
|
|
63644
|
+
const outputDir = resolve74(process.cwd(), options.outputDir || `${manifest2.name}-output`);
|
|
63645
|
+
await mkdir28(outputDir, { recursive: true });
|
|
63081
63646
|
const completedSteps = /* @__PURE__ */ new Map();
|
|
63082
63647
|
const results = [];
|
|
63083
63648
|
const startTime = Date.now();
|
|
63084
63649
|
if (options.resume) {
|
|
63085
|
-
const checkpointPath =
|
|
63086
|
-
if (
|
|
63650
|
+
const checkpointPath = resolve74(outputDir, CHECKPOINT_FILE);
|
|
63651
|
+
if (existsSync57(checkpointPath)) {
|
|
63087
63652
|
const checkpointContent = await readFile47(checkpointPath, "utf-8");
|
|
63088
63653
|
const checkpoint = (0, import_yaml8.parse)(checkpointContent);
|
|
63089
63654
|
for (const cs of checkpoint.completedSteps) {
|
|
@@ -63202,8 +63767,8 @@ async function executePipeline(manifest2, options = {}) {
|
|
|
63202
63767
|
data: s.data
|
|
63203
63768
|
}))
|
|
63204
63769
|
};
|
|
63205
|
-
await
|
|
63206
|
-
|
|
63770
|
+
await writeFile48(
|
|
63771
|
+
resolve74(outputDir, CHECKPOINT_FILE),
|
|
63207
63772
|
(0, import_yaml8.stringify)(checkpoint, { indent: 2 }),
|
|
63208
63773
|
"utf-8"
|
|
63209
63774
|
);
|
|
@@ -67671,7 +68236,7 @@ var init_elicit = __esm({
|
|
|
67671
68236
|
});
|
|
67672
68237
|
|
|
67673
68238
|
// src/tools/manifest/scene.ts
|
|
67674
|
-
import { resolve as
|
|
68239
|
+
import { resolve as resolve75, relative as relative11 } from "node:path";
|
|
67675
68240
|
function summariseLint(result) {
|
|
67676
68241
|
return {
|
|
67677
68242
|
ok: result.ok,
|
|
@@ -67906,7 +68471,7 @@ var init_scene2 = __esm({
|
|
|
67906
68471
|
description: "Scaffold a new VibeFrame video scene project. Supports minimal, agent, and full profiles; full includes the current HTML render backend metadata. Idempotent: re-running keeps user-authored files and merges backend config instead of overwriting. No API keys required.",
|
|
67907
68472
|
schema: sceneInitSchema,
|
|
67908
68473
|
async execute(args, ctx) {
|
|
67909
|
-
const dir =
|
|
68474
|
+
const dir = resolve75(ctx.workingDirectory, args.dir);
|
|
67910
68475
|
const result = await scaffoldSceneProject({
|
|
67911
68476
|
dir,
|
|
67912
68477
|
name: args.name,
|
|
@@ -67961,7 +68526,7 @@ var init_scene2 = __esm({
|
|
|
67961
68526
|
description: "Add a single scene to an existing scene project. Optionally generates narration audio (ElevenLabs) and/or a backdrop image (Gemini/OpenAI), then emits compositions/scene-<id>.html with a paused GSAP timeline. By default, syncs STORYBOARD.md and rebuilds root refs from it; set syncStoryboard:false for root-only insertion. Use skipAudio:true and skipImage:true for text-only scenes that need no API calls.",
|
|
67962
68527
|
schema: sceneAddSchema,
|
|
67963
68528
|
async execute(args, ctx) {
|
|
67964
|
-
const projectDir = args.projectDir ?
|
|
68529
|
+
const projectDir = args.projectDir ? resolve75(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
|
|
67965
68530
|
const result = await executeSceneAdd({
|
|
67966
68531
|
name: args.name,
|
|
67967
68532
|
preset: args.preset ?? "simple",
|
|
@@ -68027,7 +68592,7 @@ var init_scene2 = __esm({
|
|
|
68027
68592
|
description: "Validate every scene file in a project against the public Hyperframes lint rules (in-process, no Chrome required). Returns errors, warnings, and info findings per file. Optional fix:true mechanically repairs `timed_element_missing_clip_class` only \u2014 other issues surface with fixHints.",
|
|
68028
68593
|
schema: sceneLintSchema,
|
|
68029
68594
|
async execute(args, ctx) {
|
|
68030
|
-
const projectDir = args.projectDir ?
|
|
68595
|
+
const projectDir = args.projectDir ? resolve75(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
|
|
68031
68596
|
const result = await runProjectLint({
|
|
68032
68597
|
projectDir,
|
|
68033
68598
|
rootRel: args.root,
|
|
@@ -68066,7 +68631,7 @@ var init_scene2 = __esm({
|
|
|
68066
68631
|
description: "Apply deterministic mechanical scene repairs. Currently uses the safe lint auto-fix allow-list and never performs semantic creative rewrites.",
|
|
68067
68632
|
schema: sceneRepairSchema,
|
|
68068
68633
|
async execute(args, ctx) {
|
|
68069
|
-
const projectDir = args.projectDir ?
|
|
68634
|
+
const projectDir = args.projectDir ? resolve75(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
|
|
68070
68635
|
const result = await executeSceneRepair({
|
|
68071
68636
|
projectDir,
|
|
68072
68637
|
rootRel: args.root,
|
|
@@ -68104,7 +68669,7 @@ var init_scene2 = __esm({
|
|
|
68104
68669
|
description: "Render a scene project to MP4/WebM/MOV via the Hyperframes producer. Requires Chrome installed locally. Output defaults to renders/<projectName>-<isoStamp>.<format>. Long runs: over MCP, calls exceeding ~45s return immediately with { promoted: true, jobId, status: 'running' } \u2014 poll status_job every 15-30s until completed/failed instead of re-invoking render. Emits MCP progress notifications when the client supplies a progressToken.",
|
|
68105
68670
|
schema: sceneRenderSchema,
|
|
68106
68671
|
async execute(args, ctx) {
|
|
68107
|
-
const projectDir = args.projectDir ?
|
|
68672
|
+
const projectDir = args.projectDir ? resolve75(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
|
|
68108
68673
|
const runRender = (report) => executeSceneRender({
|
|
68109
68674
|
projectDir,
|
|
68110
68675
|
root: args.root,
|
|
@@ -68157,6 +68722,9 @@ var init_scene2 = __esm({
|
|
|
68157
68722
|
videoProvider: external_exports.enum(["seedance", "grok", "kling", "runway", "veo"]).optional().describe("Video provider for per-beat video cues. Default seedance."),
|
|
68158
68723
|
musicProvider: external_exports.enum(["elevenlabs", "replicate"]).optional().describe("Music provider for per-beat music cues. Default elevenlabs."),
|
|
68159
68724
|
imageQuality: external_exports.enum(["standard", "hd"]).optional().describe("OpenAI image quality. Default 'standard'."),
|
|
68725
|
+
imageModel: external_exports.string().optional().describe(
|
|
68726
|
+
"Image model for keyframes/backdrops/character sheets (gemini: flash|pro, openai: gpt-image-2). Provider default when omitted."
|
|
68727
|
+
),
|
|
68160
68728
|
imageSize: external_exports.enum(["1024x1024", "1536x1024", "1024x1536"]).optional().describe("OpenAI image size. Default '1536x1024' (cinematic 16:9-ish)."),
|
|
68161
68729
|
maxCostUsd: external_exports.number().optional().describe("Fail before provider spend when estimated cost exceeds this USD cap."),
|
|
68162
68730
|
force: external_exports.boolean().optional().describe("Re-dispatch primitives even when cached assets exist.")
|
|
@@ -68193,7 +68761,7 @@ var init_scene2 = __esm({
|
|
|
68193
68761
|
}
|
|
68194
68762
|
}
|
|
68195
68763
|
}
|
|
68196
|
-
const projectDir = args.projectDir ?
|
|
68764
|
+
const projectDir = args.projectDir ? resolve75(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
|
|
68197
68765
|
const runBuild = (report) => executeSceneBuild({
|
|
68198
68766
|
projectDir,
|
|
68199
68767
|
stage: args.stage,
|
|
@@ -68211,6 +68779,7 @@ var init_scene2 = __esm({
|
|
|
68211
68779
|
videoProvider: args.videoProvider,
|
|
68212
68780
|
musicProvider: args.musicProvider,
|
|
68213
68781
|
imageQuality: args.imageQuality,
|
|
68782
|
+
imageModel: args.imageModel,
|
|
68214
68783
|
imageSize: args.imageSize,
|
|
68215
68784
|
maxCostUsd: args.maxCostUsd,
|
|
68216
68785
|
force: args.force,
|
|
@@ -68249,7 +68818,7 @@ var init_scene2 = __esm({
|
|
|
68249
68818
|
description: "Install the Hyperframes composition rules into a scene project by running upstream's installer (`npx skills add heygen-com/hyperframes`). Lands at .agents/skills/hyperframes/ and is picked up by ~19 agents, with symlinks for the ones that want their own directory. Skips when the rules are already available in the project or globally unless force is set. Needs network access. Build and render do not read these files - they exist so you can read the rules while authoring scene HTML.",
|
|
68250
68819
|
schema: sceneInstallSkillSchema,
|
|
68251
68820
|
async execute(args, ctx) {
|
|
68252
|
-
const projectDir =
|
|
68821
|
+
const projectDir = resolve75(ctx.workingDirectory, args.projectDir);
|
|
68253
68822
|
const result = await installHyperframesSkill({
|
|
68254
68823
|
projectDir,
|
|
68255
68824
|
global: args.global ?? false,
|
|
@@ -68294,7 +68863,7 @@ var init_scene2 = __esm({
|
|
|
68294
68863
|
description: "Emit the per-beat compose plan for the host agent to author scene HTML itself. Reads STORYBOARD.md + DESIGN.md and returns each beat's outputPath + userPrompt + cues + body, plus the path to the Hyperframes rules (skillReference) and DESIGN.md (visual identity). The host agent writes each compositions/scene-<id>.html file directly \u2014 VibeFrame makes NO LLM call here, and there is no internal-LLM fallback: authoring is always the host agent's job. Hosts that cannot write files (e.g. Claude Desktop) submit each authored beat with scene_submit instead. Pairs with scene_install_skill, which fetches the rules from upstream when the agent does not already have them.",
|
|
68295
68864
|
schema: sceneComposePromptsSchema,
|
|
68296
68865
|
async execute(args, ctx) {
|
|
68297
|
-
const projectDir =
|
|
68866
|
+
const projectDir = resolve75(ctx.workingDirectory, args.projectDir);
|
|
68298
68867
|
const result = await getComposePrompts({
|
|
68299
68868
|
projectDir,
|
|
68300
68869
|
beatId: args.beat
|
|
@@ -68338,7 +68907,7 @@ var init_scene2 = __esm({
|
|
|
68338
68907
|
description: "Submit host-authored Hyperframes scene HTML for one beat. Validates with the same lint as the batch composer and writes compositions/scene-<id>.html on pass; on lint errors it returns the findings WITHOUT writing so you can fix and resubmit. This completes agent-mode compose for hosts that cannot write files (e.g. Claude Desktop): build (mode agent) \u2192 needs-author plan \u2192 author each beat from its composePrompts userPrompt \u2192 scene_submit per beat \u2192 build (stage sync) \u2192 render. No internal LLM call \u2014 the submitting agent is the composer.",
|
|
68339
68908
|
schema: sceneSubmitSchema,
|
|
68340
68909
|
async execute(args, ctx) {
|
|
68341
|
-
const projectDir = args.projectDir ?
|
|
68910
|
+
const projectDir = args.projectDir ? resolve75(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
|
|
68342
68911
|
const result = await executeSceneSubmit({
|
|
68343
68912
|
projectDir,
|
|
68344
68913
|
beatId: args.beat,
|
|
@@ -69001,13 +69570,13 @@ var init_edit = __esm({
|
|
|
69001
69570
|
});
|
|
69002
69571
|
|
|
69003
69572
|
// src/commands/ai-suggest-edit.ts
|
|
69004
|
-
import { readFile as readFile48, writeFile as
|
|
69005
|
-
import { resolve as
|
|
69573
|
+
import { readFile as readFile48, writeFile as writeFile49 } from "node:fs/promises";
|
|
69574
|
+
import { resolve as resolve76 } from "node:path";
|
|
69006
69575
|
async function executeSuggestEdit(options) {
|
|
69007
69576
|
try {
|
|
69008
69577
|
const apiKey = options.apiKey ?? process.env.GOOGLE_API_KEY;
|
|
69009
69578
|
if (!apiKey) return { success: false, error: "GOOGLE_API_KEY required for suggest" };
|
|
69010
|
-
const filePath =
|
|
69579
|
+
const filePath = resolve76(process.cwd(), options.projectPath);
|
|
69011
69580
|
const content = await readFile48(filePath, "utf-8");
|
|
69012
69581
|
const data = JSON.parse(content);
|
|
69013
69582
|
const project = Project.fromJSON(data);
|
|
@@ -69019,7 +69588,7 @@ async function executeSuggestEdit(options) {
|
|
|
69019
69588
|
const first = suggestions[0];
|
|
69020
69589
|
const applied = applySuggestion(project, first);
|
|
69021
69590
|
if (applied) {
|
|
69022
|
-
await
|
|
69591
|
+
await writeFile49(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
69023
69592
|
return {
|
|
69024
69593
|
success: true,
|
|
69025
69594
|
suggestions,
|
|
@@ -69048,7 +69617,7 @@ var init_ai_suggest_edit = __esm({
|
|
|
69048
69617
|
});
|
|
69049
69618
|
|
|
69050
69619
|
// src/tools/manifest/inspect.ts
|
|
69051
|
-
import { resolve as
|
|
69620
|
+
import { resolve as resolve77 } from "node:path";
|
|
69052
69621
|
var PROJECT_DIR_DESCRIPTION2, inspectProjectTool, inspectRenderTool, analyzeMediaTool, analyzeSuggestTool, inspectTools;
|
|
69053
69622
|
var init_inspect = __esm({
|
|
69054
69623
|
"src/tools/manifest/inspect.ts"() {
|
|
@@ -69074,11 +69643,11 @@ var init_inspect = __esm({
|
|
|
69074
69643
|
report: external_exports.boolean().optional().describe("Write review-report.json. Default true.")
|
|
69075
69644
|
}),
|
|
69076
69645
|
async execute(args, ctx) {
|
|
69077
|
-
const projectDir = args.projectDir ?
|
|
69646
|
+
const projectDir = args.projectDir ? resolve77(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
|
|
69078
69647
|
const result = await inspectProject({
|
|
69079
69648
|
projectDir,
|
|
69080
69649
|
beatId: args.beat,
|
|
69081
|
-
outputPath: args.outputPath ?
|
|
69650
|
+
outputPath: args.outputPath ? resolve77(ctx.workingDirectory, args.outputPath) : void 0,
|
|
69082
69651
|
writeReport: args.report !== false
|
|
69083
69652
|
});
|
|
69084
69653
|
return {
|
|
@@ -69114,13 +69683,13 @@ var init_inspect = __esm({
|
|
|
69114
69683
|
dryRun: external_exports.boolean().optional().describe("Preview resolved inputs without probing video or calling Gemini.")
|
|
69115
69684
|
}),
|
|
69116
69685
|
async execute(args, ctx) {
|
|
69117
|
-
const projectDir = args.projectDir ?
|
|
69686
|
+
const projectDir = args.projectDir ? resolve77(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
|
|
69118
69687
|
if (args.dryRun) {
|
|
69119
69688
|
const result2 = await previewInspectRender({
|
|
69120
69689
|
projectDir,
|
|
69121
69690
|
beatId: args.beat,
|
|
69122
|
-
videoPath: args.videoPath ?
|
|
69123
|
-
outputPath: args.outputPath ?
|
|
69691
|
+
videoPath: args.videoPath ? resolve77(ctx.workingDirectory, args.videoPath) : void 0,
|
|
69692
|
+
outputPath: args.outputPath ? resolve77(ctx.workingDirectory, args.outputPath) : void 0,
|
|
69124
69693
|
writeReport: args.report !== false,
|
|
69125
69694
|
ai: args.ai === true,
|
|
69126
69695
|
model: args.model
|
|
@@ -69141,8 +69710,8 @@ var init_inspect = __esm({
|
|
|
69141
69710
|
const result = await inspectRender({
|
|
69142
69711
|
projectDir,
|
|
69143
69712
|
beatId: args.beat,
|
|
69144
|
-
videoPath: args.videoPath ?
|
|
69145
|
-
outputPath: args.outputPath ?
|
|
69713
|
+
videoPath: args.videoPath ? resolve77(ctx.workingDirectory, args.videoPath) : void 0,
|
|
69714
|
+
outputPath: args.outputPath ? resolve77(ctx.workingDirectory, args.outputPath) : void 0,
|
|
69146
69715
|
writeReport: args.report !== false,
|
|
69147
69716
|
ai: args.ai === true,
|
|
69148
69717
|
model: args.model
|
|
@@ -69575,12 +70144,12 @@ var init_generate2 = __esm({
|
|
|
69575
70144
|
});
|
|
69576
70145
|
|
|
69577
70146
|
// src/tools/manifest/storyboard.ts
|
|
69578
|
-
import { existsSync as
|
|
69579
|
-
import { readFile as readFile49, writeFile as
|
|
69580
|
-
import { resolve as
|
|
70147
|
+
import { existsSync as existsSync58 } from "node:fs";
|
|
70148
|
+
import { readFile as readFile49, writeFile as writeFile50 } from "node:fs/promises";
|
|
70149
|
+
import { resolve as resolve78 } from "node:path";
|
|
69581
70150
|
async function readStoryboard2(projectDir) {
|
|
69582
|
-
const path2 =
|
|
69583
|
-
if (!
|
|
70151
|
+
const path2 = resolve78(projectDir, "STORYBOARD.md");
|
|
70152
|
+
if (!existsSync58(path2)) return null;
|
|
69584
70153
|
return { path: path2, markdown: await readFile49(path2, "utf-8") };
|
|
69585
70154
|
}
|
|
69586
70155
|
var PROJECT_DIR_DESCRIPTION3, projectDirSchema, storyboardListTool, storyboardValidateTool, storyboardGetTool, storyboardSetTool, storyboardMoveTool, storyboardReviseTool, planTool, storyboardTools;
|
|
@@ -69606,7 +70175,7 @@ var init_storyboard2 = __esm({
|
|
|
69606
70175
|
description: "List beats, ids, durations, and cue blocks from a project's STORYBOARD.md.",
|
|
69607
70176
|
schema: projectDirSchema,
|
|
69608
70177
|
async execute(args, ctx) {
|
|
69609
|
-
const projectDir = args.projectDir ?
|
|
70178
|
+
const projectDir = args.projectDir ? resolve78(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
|
|
69610
70179
|
const file = await readStoryboard2(projectDir);
|
|
69611
70180
|
if (!file) return { success: false, error: `STORYBOARD.md not found in ${projectDir}` };
|
|
69612
70181
|
const parsed = parseStoryboard(file.markdown);
|
|
@@ -69634,7 +70203,7 @@ var init_storyboard2 = __esm({
|
|
|
69634
70203
|
description: "Validate STORYBOARD.md beat ids and cue blocks.",
|
|
69635
70204
|
schema: projectDirSchema,
|
|
69636
70205
|
async execute(args, ctx) {
|
|
69637
|
-
const projectDir = args.projectDir ?
|
|
70206
|
+
const projectDir = args.projectDir ? resolve78(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
|
|
69638
70207
|
const file = await readStoryboard2(projectDir);
|
|
69639
70208
|
if (!file) return { success: false, error: `STORYBOARD.md not found in ${projectDir}` };
|
|
69640
70209
|
const result = validateStoryboardMarkdown(file.markdown);
|
|
@@ -69669,7 +70238,7 @@ var init_storyboard2 = __esm({
|
|
|
69669
70238
|
beat: external_exports.string().describe("Beat id to return.")
|
|
69670
70239
|
}),
|
|
69671
70240
|
async execute(args, ctx) {
|
|
69672
|
-
const projectDir = args.projectDir ?
|
|
70241
|
+
const projectDir = args.projectDir ? resolve78(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
|
|
69673
70242
|
const file = await readStoryboard2(projectDir);
|
|
69674
70243
|
if (!file) return { success: false, error: `STORYBOARD.md not found in ${projectDir}` };
|
|
69675
70244
|
const beat = getStoryboardBeat(file.markdown, args.beat);
|
|
@@ -69697,7 +70266,7 @@ var init_storyboard2 = __esm({
|
|
|
69697
70266
|
unset: external_exports.boolean().optional().describe("Remove the cue key.")
|
|
69698
70267
|
}),
|
|
69699
70268
|
async execute(args, ctx) {
|
|
69700
|
-
const projectDir = args.projectDir ?
|
|
70269
|
+
const projectDir = args.projectDir ? resolve78(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
|
|
69701
70270
|
const file = await readStoryboard2(projectDir);
|
|
69702
70271
|
if (!file) return { success: false, error: `STORYBOARD.md not found in ${projectDir}` };
|
|
69703
70272
|
try {
|
|
@@ -69708,7 +70277,7 @@ var init_storyboard2 = __esm({
|
|
|
69708
70277
|
value,
|
|
69709
70278
|
unset: args.unset
|
|
69710
70279
|
});
|
|
69711
|
-
await
|
|
70280
|
+
await writeFile50(file.path, next, "utf-8");
|
|
69712
70281
|
return {
|
|
69713
70282
|
success: true,
|
|
69714
70283
|
data: { beat: args.beat, key: args.key },
|
|
@@ -69732,7 +70301,7 @@ var init_storyboard2 = __esm({
|
|
|
69732
70301
|
after: external_exports.string().describe("Beat id that should precede the moved beat.")
|
|
69733
70302
|
}),
|
|
69734
70303
|
async execute(args, ctx) {
|
|
69735
|
-
const projectDir = args.projectDir ?
|
|
70304
|
+
const projectDir = args.projectDir ? resolve78(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
|
|
69736
70305
|
const file = await readStoryboard2(projectDir);
|
|
69737
70306
|
if (!file) return { success: false, error: `STORYBOARD.md not found in ${projectDir}` };
|
|
69738
70307
|
try {
|
|
@@ -69740,7 +70309,7 @@ var init_storyboard2 = __esm({
|
|
|
69740
70309
|
beatId: args.beat,
|
|
69741
70310
|
afterBeatId: args.after
|
|
69742
70311
|
});
|
|
69743
|
-
await
|
|
70312
|
+
await writeFile50(file.path, next, "utf-8");
|
|
69744
70313
|
return {
|
|
69745
70314
|
success: true,
|
|
69746
70315
|
data: { beat: args.beat, after: args.after },
|
|
@@ -69766,7 +70335,7 @@ var init_storyboard2 = __esm({
|
|
|
69766
70335
|
dryRun: external_exports.boolean().optional().describe("Preview the revised storyboard without writing.")
|
|
69767
70336
|
}),
|
|
69768
70337
|
async execute(args, ctx) {
|
|
69769
|
-
const projectDir = args.projectDir ?
|
|
70338
|
+
const projectDir = args.projectDir ? resolve78(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
|
|
69770
70339
|
const result = await executeStoryboardRevision({
|
|
69771
70340
|
projectDir,
|
|
69772
70341
|
request: args.request,
|
|
@@ -69811,7 +70380,7 @@ var init_storyboard2 = __esm({
|
|
|
69811
70380
|
force: external_exports.boolean().optional().describe("Plan regeneration even when outputs exist.")
|
|
69812
70381
|
}),
|
|
69813
70382
|
async execute(args, ctx) {
|
|
69814
|
-
const projectDir = args.projectDir ?
|
|
70383
|
+
const projectDir = args.projectDir ? resolve78(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
|
|
69815
70384
|
const plan = await createBuildPlan({
|
|
69816
70385
|
projectDir,
|
|
69817
70386
|
stage: args.stage,
|
|
@@ -69854,9 +70423,9 @@ var init_storyboard2 = __esm({
|
|
|
69854
70423
|
});
|
|
69855
70424
|
|
|
69856
70425
|
// src/tools/manifest/design.ts
|
|
69857
|
-
import { existsSync as
|
|
70426
|
+
import { existsSync as existsSync59 } from "node:fs";
|
|
69858
70427
|
import { readFile as readFile50 } from "node:fs/promises";
|
|
69859
|
-
import { resolve as
|
|
70428
|
+
import { resolve as resolve79, join as join30 } from "node:path";
|
|
69860
70429
|
var PROJECT_DIR_DESCRIPTION4, projectDirSchema2, designValidateTool, designTools;
|
|
69861
70430
|
var init_design = __esm({
|
|
69862
70431
|
"src/tools/manifest/design.ts"() {
|
|
@@ -69877,9 +70446,9 @@ var init_design = __esm({
|
|
|
69877
70446
|
description: "Validate DESIGN.md front-matter color/typography tokens and sections (google-labs design.md format).",
|
|
69878
70447
|
schema: projectDirSchema2,
|
|
69879
70448
|
async execute(args, ctx) {
|
|
69880
|
-
const projectDir = args.projectDir ?
|
|
69881
|
-
const path2 =
|
|
69882
|
-
if (!
|
|
70449
|
+
const projectDir = args.projectDir ? resolve79(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
|
|
70450
|
+
const path2 = join30(projectDir, "DESIGN.md");
|
|
70451
|
+
if (!existsSync59(path2)) return { success: false, error: `DESIGN.md not found in ${projectDir}` };
|
|
69883
70452
|
const md = await readFile50(path2, "utf-8");
|
|
69884
70453
|
const issues = validateDesignMarkdown(md);
|
|
69885
70454
|
const design = parseDesign(md);
|
|
@@ -69903,9 +70472,9 @@ var init_design = __esm({
|
|
|
69903
70472
|
});
|
|
69904
70473
|
|
|
69905
70474
|
// src/tools/manifest/remix.ts
|
|
69906
|
-
import { writeFile as
|
|
70475
|
+
import { writeFile as writeFile51 } from "node:fs/promises";
|
|
69907
70476
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
69908
|
-
import { join as
|
|
70477
|
+
import { join as join31 } from "node:path";
|
|
69909
70478
|
var pipelineHighlightsTool, pipelineAutoShortsTool, pipelineRunTool, remixTools;
|
|
69910
70479
|
var init_remix = __esm({
|
|
69911
70480
|
"src/tools/manifest/remix.ts"() {
|
|
@@ -70018,8 +70587,8 @@ var init_remix = __esm({
|
|
|
70018
70587
|
let resolvedPath = args.pipelinePath;
|
|
70019
70588
|
let tempPath;
|
|
70020
70589
|
if (args.pipelineYaml) {
|
|
70021
|
-
tempPath =
|
|
70022
|
-
await
|
|
70590
|
+
tempPath = join31(tmpdir4(), `vibe-mcp-pipeline-${Date.now()}.yaml`);
|
|
70591
|
+
await writeFile51(tempPath, args.pipelineYaml, "utf-8");
|
|
70023
70592
|
resolvedPath = tempPath;
|
|
70024
70593
|
}
|
|
70025
70594
|
try {
|
|
@@ -70164,7 +70733,7 @@ var init_detect2 = __esm({
|
|
|
70164
70733
|
});
|
|
70165
70734
|
|
|
70166
70735
|
// src/tools/manifest/_project-io.ts
|
|
70167
|
-
import { readFile as readFile51, writeFile as
|
|
70736
|
+
import { readFile as readFile51, writeFile as writeFile52 } from "node:fs/promises";
|
|
70168
70737
|
async function loadProject2(projectPath, cwd) {
|
|
70169
70738
|
const absPath = await resolveTimelineFile(projectPath, cwd);
|
|
70170
70739
|
const content = await readFile51(absPath, "utf-8");
|
|
@@ -70172,7 +70741,7 @@ async function loadProject2(projectPath, cwd) {
|
|
|
70172
70741
|
return { project: Project.fromJSON(data), absPath };
|
|
70173
70742
|
}
|
|
70174
70743
|
async function saveProject(absPath, project) {
|
|
70175
|
-
await
|
|
70744
|
+
await writeFile52(absPath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
70176
70745
|
}
|
|
70177
70746
|
var init_project_io = __esm({
|
|
70178
70747
|
"src/tools/manifest/_project-io.ts"() {
|
|
@@ -70183,8 +70752,8 @@ var init_project_io = __esm({
|
|
|
70183
70752
|
});
|
|
70184
70753
|
|
|
70185
70754
|
// src/tools/manifest/timeline.ts
|
|
70186
|
-
import { mkdir as
|
|
70187
|
-
import { basename as basename23, resolve as
|
|
70755
|
+
import { mkdir as mkdir29, writeFile as writeFile53 } from "node:fs/promises";
|
|
70756
|
+
import { basename as basename23, resolve as resolve80 } from "node:path";
|
|
70188
70757
|
var MEDIA_TYPES, timelineCreateTool, timelineInfoTool, timelineAddSourceTool, timelineAddClipTool, timelineSplitClipTool, timelineTrimClipTool, timelineMoveClipTool, timelineDeleteClipTool, timelineDuplicateClipTool, timelineAddEffectTool, timelineAddTrackTool, timelineListTool, timelineTools;
|
|
70189
70758
|
var init_timeline = __esm({
|
|
70190
70759
|
"src/tools/manifest/timeline.ts"() {
|
|
@@ -70222,18 +70791,18 @@ var init_timeline = __esm({
|
|
|
70222
70791
|
fps: external_exports.number().optional().describe("Frames per second (default: 30)")
|
|
70223
70792
|
}),
|
|
70224
70793
|
async execute(args, ctx) {
|
|
70225
|
-
const projectName = args.name === "." ? basename23(ctx.workingDirectory) : basename23(
|
|
70794
|
+
const projectName = args.name === "." ? basename23(ctx.workingDirectory) : basename23(resolve80(ctx.workingDirectory, args.name));
|
|
70226
70795
|
const project = new Project(projectName);
|
|
70227
70796
|
if (args.fps) project.setFrameRate(args.fps);
|
|
70228
70797
|
let outputPath;
|
|
70229
70798
|
if (args.outputPath) {
|
|
70230
|
-
outputPath =
|
|
70799
|
+
outputPath = resolve80(ctx.workingDirectory, args.outputPath);
|
|
70231
70800
|
} else {
|
|
70232
|
-
const dirPath =
|
|
70233
|
-
await
|
|
70234
|
-
outputPath =
|
|
70801
|
+
const dirPath = resolve80(ctx.workingDirectory, args.name);
|
|
70802
|
+
await mkdir29(dirPath, { recursive: true });
|
|
70803
|
+
outputPath = resolve80(dirPath, TIMELINE_FILENAME);
|
|
70235
70804
|
}
|
|
70236
|
-
await
|
|
70805
|
+
await writeFile53(outputPath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
70237
70806
|
return {
|
|
70238
70807
|
success: true,
|
|
70239
70808
|
data: { name: projectName, outputPath },
|
|
@@ -70285,7 +70854,7 @@ var init_timeline = __esm({
|
|
|
70285
70854
|
}),
|
|
70286
70855
|
async execute(args, ctx) {
|
|
70287
70856
|
const { project, absPath } = await loadProject2(args.projectPath, ctx.workingDirectory);
|
|
70288
|
-
const mediaPath =
|
|
70857
|
+
const mediaPath = resolve80(ctx.workingDirectory, args.mediaPath);
|
|
70289
70858
|
const ext = mediaPath.split(".").pop()?.toLowerCase() ?? "";
|
|
70290
70859
|
const source = project.addSource({
|
|
70291
70860
|
name: args.name ?? mediaPath.split("/").pop() ?? "media",
|
|
@@ -70532,11 +71101,11 @@ var init_timeline = __esm({
|
|
|
70532
71101
|
|
|
70533
71102
|
// src/commands/_shared/project-list.ts
|
|
70534
71103
|
import { readdir as readdir8, readFile as readFile52, stat as stat9 } from "node:fs/promises";
|
|
70535
|
-
import { existsSync as
|
|
70536
|
-
import { join as
|
|
71104
|
+
import { existsSync as existsSync60 } from "node:fs";
|
|
71105
|
+
import { join as join32, resolve as resolve81 } from "node:path";
|
|
70537
71106
|
async function executeProjectList(opts = {}) {
|
|
70538
|
-
const workspaceDir =
|
|
70539
|
-
if (!
|
|
71107
|
+
const workspaceDir = resolve81(opts.workspaceDir ?? ".");
|
|
71108
|
+
if (!existsSync60(workspaceDir)) {
|
|
70540
71109
|
return {
|
|
70541
71110
|
success: false,
|
|
70542
71111
|
workspaceDir,
|
|
@@ -70553,11 +71122,11 @@ async function executeProjectList(opts = {}) {
|
|
|
70553
71122
|
if (entry.name === "node_modules") continue;
|
|
70554
71123
|
if (entry.name.startsWith(".")) continue;
|
|
70555
71124
|
if (entry.name.startsWith("_")) {
|
|
70556
|
-
archivedCount += await countProjects(
|
|
71125
|
+
archivedCount += await countProjects(join32(workspaceDir, entry.name));
|
|
70557
71126
|
continue;
|
|
70558
71127
|
}
|
|
70559
|
-
const projectDir =
|
|
70560
|
-
if (!
|
|
71128
|
+
const projectDir = join32(workspaceDir, entry.name);
|
|
71129
|
+
if (!existsSync60(join32(projectDir, "STORYBOARD.md"))) continue;
|
|
70561
71130
|
projects.push(await describeProject(entry.name, projectDir));
|
|
70562
71131
|
}
|
|
70563
71132
|
projects.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
@@ -70567,7 +71136,7 @@ async function countProjects(dir) {
|
|
|
70567
71136
|
try {
|
|
70568
71137
|
const entries = await readdir8(dir, { withFileTypes: true });
|
|
70569
71138
|
return entries.filter(
|
|
70570
|
-
(e) => e.isDirectory() &&
|
|
71139
|
+
(e) => e.isDirectory() && existsSync60(join32(dir, e.name, "STORYBOARD.md"))
|
|
70571
71140
|
).length;
|
|
70572
71141
|
} catch {
|
|
70573
71142
|
return 0;
|
|
@@ -70578,7 +71147,7 @@ async function describeProject(name, projectDir) {
|
|
|
70578
71147
|
let storyboardDurationSec = 0;
|
|
70579
71148
|
const timestamps = [];
|
|
70580
71149
|
try {
|
|
70581
|
-
const storyboardPath2 =
|
|
71150
|
+
const storyboardPath2 = join32(projectDir, "STORYBOARD.md");
|
|
70582
71151
|
const parsed = parseStoryboard(await loadStoryboardMarkdown(projectDir));
|
|
70583
71152
|
beats = parsed.beats.length;
|
|
70584
71153
|
storyboardDurationSec = Number(
|
|
@@ -70590,7 +71159,7 @@ async function describeProject(name, projectDir) {
|
|
|
70590
71159
|
let buildStatus;
|
|
70591
71160
|
let buildUpdatedAt;
|
|
70592
71161
|
try {
|
|
70593
|
-
const reportPath =
|
|
71162
|
+
const reportPath = join32(projectDir, "build-report.json");
|
|
70594
71163
|
const report = JSON.parse(await readFile52(reportPath, "utf-8"));
|
|
70595
71164
|
buildStatus = report.status ?? report.phase;
|
|
70596
71165
|
buildUpdatedAt = report.updatedAt;
|
|
@@ -70599,12 +71168,12 @@ async function describeProject(name, projectDir) {
|
|
|
70599
71168
|
}
|
|
70600
71169
|
let latestRender;
|
|
70601
71170
|
try {
|
|
70602
|
-
const rendersDir =
|
|
71171
|
+
const rendersDir = join32(projectDir, "renders");
|
|
70603
71172
|
const files = await readdir8(rendersDir);
|
|
70604
71173
|
let newest;
|
|
70605
71174
|
for (const file of files) {
|
|
70606
71175
|
if (!/\.(mp4|webm|mov)$/i.test(file)) continue;
|
|
70607
|
-
const { mtimeMs } = await stat9(
|
|
71176
|
+
const { mtimeMs } = await stat9(join32(rendersDir, file));
|
|
70608
71177
|
if (!newest || mtimeMs > newest.mtimeMs) newest = { file, mtimeMs };
|
|
70609
71178
|
}
|
|
70610
71179
|
if (newest) {
|
|
@@ -70636,8 +71205,8 @@ var init_project_list = __esm({
|
|
|
70636
71205
|
});
|
|
70637
71206
|
|
|
70638
71207
|
// src/tools/manifest/project.ts
|
|
70639
|
-
import { resolve as
|
|
70640
|
-
import { writeFile as
|
|
71208
|
+
import { resolve as resolve82 } from "node:path";
|
|
71209
|
+
import { writeFile as writeFile54 } from "node:fs/promises";
|
|
70641
71210
|
var projectListTool, projectCreateTool, projectInfoTool, projectTools;
|
|
70642
71211
|
var init_project2 = __esm({
|
|
70643
71212
|
"src/tools/manifest/project.ts"() {
|
|
@@ -70661,7 +71230,7 @@ var init_project2 = __esm({
|
|
|
70661
71230
|
}),
|
|
70662
71231
|
async execute(args, ctx) {
|
|
70663
71232
|
const result = await executeProjectList({
|
|
70664
|
-
workspaceDir: args.dir ?
|
|
71233
|
+
workspaceDir: args.dir ? resolve82(ctx.workingDirectory, args.dir) : ctx.workingDirectory
|
|
70665
71234
|
});
|
|
70666
71235
|
if (!result.success) {
|
|
70667
71236
|
return { success: false, error: result.error ?? "project list failed" };
|
|
@@ -70698,10 +71267,10 @@ var init_project2 = __esm({
|
|
|
70698
71267
|
fps: external_exports.number().optional().describe("Frames per second (default: 30)")
|
|
70699
71268
|
}),
|
|
70700
71269
|
async execute(args, ctx) {
|
|
70701
|
-
const outputPath =
|
|
71270
|
+
const outputPath = resolve82(ctx.workingDirectory, args.outputPath ?? `${args.name}.vibe.json`);
|
|
70702
71271
|
const project = new Project(args.name);
|
|
70703
71272
|
if (args.fps) project.setFrameRate(args.fps);
|
|
70704
|
-
await
|
|
71273
|
+
await writeFile54(outputPath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
70705
71274
|
return {
|
|
70706
71275
|
success: true,
|
|
70707
71276
|
data: { name: args.name, outputPath },
|
|
@@ -70748,7 +71317,7 @@ var init_project2 = __esm({
|
|
|
70748
71317
|
|
|
70749
71318
|
// src/commands/export.ts
|
|
70750
71319
|
import { readFile as readFile53, access as access7 } from "node:fs/promises";
|
|
70751
|
-
import { resolve as
|
|
71320
|
+
import { resolve as resolve83 } from "node:path";
|
|
70752
71321
|
import { spawn as spawn3 } from "node:child_process";
|
|
70753
71322
|
async function getMediaDuration(filePath, mediaType, defaultImageDuration = 5) {
|
|
70754
71323
|
if (mediaType === "image") {
|
|
@@ -70820,7 +71389,7 @@ async function runExport(projectPath, outputPath, options = {}) {
|
|
|
70820
71389
|
message: "Project has no clips to export"
|
|
70821
71390
|
};
|
|
70822
71391
|
}
|
|
70823
|
-
const finalOutputPath =
|
|
71392
|
+
const finalOutputPath = resolve83(process.cwd(), outputPath);
|
|
70824
71393
|
const basePresetSettings = getPresetSettings(preset, summary.aspectRatio);
|
|
70825
71394
|
const presetSettings = applyCustomOverrides(basePresetSettings, { bitrate, fps, resolution, codec });
|
|
70826
71395
|
const clips = project.getClips().sort((a, b) => a.startTime - b.startTime);
|
|
@@ -71216,7 +71785,7 @@ function buildFFmpegArgs(clips, sources, presetSettings, outputPath, options, so
|
|
|
71216
71785
|
return args;
|
|
71217
71786
|
}
|
|
71218
71787
|
function runFFmpegProcess(ffmpegPath, args, onProgress) {
|
|
71219
|
-
return new Promise((
|
|
71788
|
+
return new Promise((resolve87, reject) => {
|
|
71220
71789
|
const ffmpeg = spawn3(ffmpegPath, args, {
|
|
71221
71790
|
stdio: ["pipe", "pipe", "pipe"]
|
|
71222
71791
|
});
|
|
@@ -71240,7 +71809,7 @@ function runFFmpegProcess(ffmpegPath, args, onProgress) {
|
|
|
71240
71809
|
});
|
|
71241
71810
|
ffmpeg.on("close", (code) => {
|
|
71242
71811
|
if (code === 0) {
|
|
71243
|
-
|
|
71812
|
+
resolve87();
|
|
71244
71813
|
} else {
|
|
71245
71814
|
const errorMatch = stderr.match(/Error.*$/m);
|
|
71246
71815
|
const errorMsg = errorMatch ? errorMatch[0] : `FFmpeg exited with code ${code}`;
|
|
@@ -71393,7 +71962,7 @@ var init_export = __esm({
|
|
|
71393
71962
|
});
|
|
71394
71963
|
|
|
71395
71964
|
// src/tools/manifest/export.ts
|
|
71396
|
-
import { resolve as
|
|
71965
|
+
import { resolve as resolve84 } from "node:path";
|
|
71397
71966
|
var exportVideoTool, exportTools;
|
|
71398
71967
|
var init_export2 = __esm({
|
|
71399
71968
|
"src/tools/manifest/export.ts"() {
|
|
@@ -71416,8 +71985,8 @@ var init_export2 = __esm({
|
|
|
71416
71985
|
overwrite: external_exports.boolean().optional().describe("Overwrite existing output file (default: false)")
|
|
71417
71986
|
}),
|
|
71418
71987
|
async execute(args, ctx) {
|
|
71419
|
-
const projectPath =
|
|
71420
|
-
const outputPath =
|
|
71988
|
+
const projectPath = resolve84(ctx.workingDirectory, args.projectPath);
|
|
71989
|
+
const outputPath = resolve84(ctx.workingDirectory, args.outputPath);
|
|
71421
71990
|
const result = await runExport(projectPath, outputPath, {
|
|
71422
71991
|
preset: args.preset,
|
|
71423
71992
|
format: args.format,
|
|
@@ -71436,8 +72005,8 @@ var init_export2 = __esm({
|
|
|
71436
72005
|
});
|
|
71437
72006
|
|
|
71438
72007
|
// src/tools/manifest/agent-only.ts
|
|
71439
|
-
import { readFile as readFile54, writeFile as
|
|
71440
|
-
import { resolve as
|
|
72008
|
+
import { readFile as readFile54, writeFile as writeFile55, readdir as readdir9, stat as stat10, access as access8, unlink as unlink2 } from "node:fs/promises";
|
|
72009
|
+
import { resolve as resolve85, join as join33, basename as basename24, extname as extname15 } from "node:path";
|
|
71441
72010
|
function matchPattern(filename, pattern) {
|
|
71442
72011
|
const regex2 = new RegExp(
|
|
71443
72012
|
"^" + pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".") + "$",
|
|
@@ -71517,12 +72086,12 @@ var init_agent_only = __esm({
|
|
|
71517
72086
|
async execute(args, ctx) {
|
|
71518
72087
|
const dirPath = args.path ?? ".";
|
|
71519
72088
|
try {
|
|
71520
|
-
const absPath =
|
|
72089
|
+
const absPath = resolve85(ctx.workingDirectory, dirPath);
|
|
71521
72090
|
const entries = await readdir9(absPath, { withFileTypes: true });
|
|
71522
72091
|
const results = [];
|
|
71523
72092
|
for (const entry of entries) {
|
|
71524
72093
|
if (args.pattern && !matchPattern(entry.name, args.pattern)) continue;
|
|
71525
|
-
const fullPath =
|
|
72094
|
+
const fullPath = join33(absPath, entry.name);
|
|
71526
72095
|
const stats = await stat10(fullPath);
|
|
71527
72096
|
if (entry.isDirectory()) {
|
|
71528
72097
|
results.push(`[DIR] ${entry.name}/`);
|
|
@@ -71550,7 +72119,7 @@ var init_agent_only = __esm({
|
|
|
71550
72119
|
}),
|
|
71551
72120
|
async execute(args, ctx) {
|
|
71552
72121
|
try {
|
|
71553
|
-
const absPath =
|
|
72122
|
+
const absPath = resolve85(ctx.workingDirectory, args.path);
|
|
71554
72123
|
const content = await readFile54(absPath, "utf-8");
|
|
71555
72124
|
const maxLength = 4e3;
|
|
71556
72125
|
const truncated = content.length > maxLength;
|
|
@@ -71575,8 +72144,8 @@ var init_agent_only = __esm({
|
|
|
71575
72144
|
}),
|
|
71576
72145
|
async execute(args, ctx) {
|
|
71577
72146
|
try {
|
|
71578
|
-
const absPath =
|
|
71579
|
-
await
|
|
72147
|
+
const absPath = resolve85(ctx.workingDirectory, args.path);
|
|
72148
|
+
await writeFile55(absPath, args.content, "utf-8");
|
|
71580
72149
|
return { success: true, data: { bytes: args.content.length }, humanLines: [`File written: ${args.path} (${formatSize(args.content.length)})`] };
|
|
71581
72150
|
} catch (error) {
|
|
71582
72151
|
return { success: false, error: `Failed to write file: ${error instanceof Error ? error.message : String(error)}` };
|
|
@@ -71595,7 +72164,7 @@ var init_agent_only = __esm({
|
|
|
71595
72164
|
path: external_exports.string().describe("Path to check")
|
|
71596
72165
|
}),
|
|
71597
72166
|
async execute(args, ctx) {
|
|
71598
|
-
const absPath =
|
|
72167
|
+
const absPath = resolve85(ctx.workingDirectory, args.path);
|
|
71599
72168
|
try {
|
|
71600
72169
|
await access8(absPath);
|
|
71601
72170
|
const stats = await stat10(absPath);
|
|
@@ -71623,11 +72192,11 @@ var init_agent_only = __esm({
|
|
|
71623
72192
|
}),
|
|
71624
72193
|
async execute(args, ctx) {
|
|
71625
72194
|
try {
|
|
71626
|
-
const filePath =
|
|
72195
|
+
const filePath = resolve85(ctx.workingDirectory, args.project);
|
|
71627
72196
|
const content = await readFile54(filePath, "utf-8");
|
|
71628
72197
|
const data = JSON.parse(content);
|
|
71629
72198
|
const project = Project.fromJSON(data);
|
|
71630
|
-
const dirPath =
|
|
72199
|
+
const dirPath = resolve85(ctx.workingDirectory, args.directory);
|
|
71631
72200
|
const filterExts = args.filter ? args.filter.split(",").map((e) => e.trim().toLowerCase()) : null;
|
|
71632
72201
|
const imageDuration = args.imageDuration ?? 5;
|
|
71633
72202
|
const recursive = args.recursive ?? false;
|
|
@@ -71635,7 +72204,7 @@ var init_agent_only = __esm({
|
|
|
71635
72204
|
const scanDir = async (dir) => {
|
|
71636
72205
|
const entries = await readdir9(dir, { withFileTypes: true });
|
|
71637
72206
|
for (const entry of entries) {
|
|
71638
|
-
const entryPath =
|
|
72207
|
+
const entryPath = join33(dir, entry.name);
|
|
71639
72208
|
if (entry.isDirectory() && recursive) {
|
|
71640
72209
|
await scanDir(entryPath);
|
|
71641
72210
|
} else if (entry.isFile()) {
|
|
@@ -71662,7 +72231,7 @@ var init_agent_only = __esm({
|
|
|
71662
72231
|
const source = project.addSource({ name: mediaName, type: mediaType, url: mediaFile, duration });
|
|
71663
72232
|
addedSources.push({ id: source.id, name: mediaName, type: mediaType });
|
|
71664
72233
|
}
|
|
71665
|
-
await
|
|
72234
|
+
await writeFile55(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
71666
72235
|
return {
|
|
71667
72236
|
success: true,
|
|
71668
72237
|
data: { count: addedSources.length, sources: addedSources },
|
|
@@ -71695,7 +72264,7 @@ var init_agent_only = __esm({
|
|
|
71695
72264
|
}),
|
|
71696
72265
|
async execute(args, ctx) {
|
|
71697
72266
|
try {
|
|
71698
|
-
const filePath =
|
|
72267
|
+
const filePath = resolve85(ctx.workingDirectory, args.project);
|
|
71699
72268
|
const content = await readFile54(filePath, "utf-8");
|
|
71700
72269
|
const data = JSON.parse(content);
|
|
71701
72270
|
const project = Project.fromJSON(data);
|
|
@@ -71732,7 +72301,7 @@ var init_agent_only = __esm({
|
|
|
71732
72301
|
createdClips.push({ id: clip.id, sourceName: source.name, startTime: currentTime, duration: source.duration });
|
|
71733
72302
|
currentTime += source.duration + gap;
|
|
71734
72303
|
}
|
|
71735
|
-
await
|
|
72304
|
+
await writeFile55(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
71736
72305
|
const totalDuration = currentTime - gap - startTime;
|
|
71737
72306
|
return {
|
|
71738
72307
|
success: true,
|
|
@@ -71766,7 +72335,7 @@ var init_agent_only = __esm({
|
|
|
71766
72335
|
}),
|
|
71767
72336
|
async execute(args, ctx) {
|
|
71768
72337
|
try {
|
|
71769
|
-
const filePath =
|
|
72338
|
+
const filePath = resolve85(ctx.workingDirectory, args.project);
|
|
71770
72339
|
const content = await readFile54(filePath, "utf-8");
|
|
71771
72340
|
const data = JSON.parse(content);
|
|
71772
72341
|
const project = Project.fromJSON(data);
|
|
@@ -71795,7 +72364,7 @@ var init_agent_only = __esm({
|
|
|
71795
72364
|
});
|
|
71796
72365
|
if (effect) appliedEffects.push({ clipId: clip.id, effectId: effect.id });
|
|
71797
72366
|
}
|
|
71798
|
-
await
|
|
72367
|
+
await writeFile55(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
71799
72368
|
return {
|
|
71800
72369
|
success: true,
|
|
71801
72370
|
data: { applied: appliedEffects.length, effectType: args.effectType },
|
|
@@ -71864,7 +72433,7 @@ var init_agent_only = __esm({
|
|
|
71864
72433
|
removed.sources++;
|
|
71865
72434
|
}
|
|
71866
72435
|
}
|
|
71867
|
-
await
|
|
72436
|
+
await writeFile55(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
71868
72437
|
const parts = [];
|
|
71869
72438
|
if (removed.clips > 0) parts.push(`${removed.clips} clips`);
|
|
71870
72439
|
if (removed.tracks > 0) parts.push(`${removed.tracks} tracks`);
|
|
@@ -71915,7 +72484,7 @@ var init_agent_only = __esm({
|
|
|
71915
72484
|
project.setFrameRate(args.fps);
|
|
71916
72485
|
updates.push(`Frame Rate: ${args.fps} fps`);
|
|
71917
72486
|
}
|
|
71918
|
-
await
|
|
72487
|
+
await writeFile55(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
|
|
71919
72488
|
return {
|
|
71920
72489
|
success: true,
|
|
71921
72490
|
data: { updates },
|
|
@@ -72058,7 +72627,7 @@ var init_agent_only = __esm({
|
|
|
72058
72627
|
}),
|
|
72059
72628
|
async execute(args, ctx) {
|
|
72060
72629
|
try {
|
|
72061
|
-
const absPath =
|
|
72630
|
+
const absPath = resolve85(ctx.workingDirectory, args.path);
|
|
72062
72631
|
const { stdout } = await execSafe(
|
|
72063
72632
|
"ffprobe",
|
|
72064
72633
|
["-v", "quiet", "-print_format", "json", "-show_format", "-show_streams", absPath],
|
|
@@ -72147,10 +72716,10 @@ Audio:`);
|
|
|
72147
72716
|
}),
|
|
72148
72717
|
async execute(args, ctx) {
|
|
72149
72718
|
try {
|
|
72150
|
-
const absInput =
|
|
72719
|
+
const absInput = resolve85(ctx.workingDirectory, args.input);
|
|
72151
72720
|
const ext = args.input.split(".").pop() || "mp4";
|
|
72152
72721
|
const baseName = args.input.replace(/\.[^/.]+$/, "");
|
|
72153
|
-
const outputPath = args.output ?
|
|
72722
|
+
const outputPath = args.output ? resolve85(ctx.workingDirectory, args.output) : resolve85(ctx.workingDirectory, `${baseName}-compressed.${ext}`);
|
|
72154
72723
|
const crfValues = { low: 28, medium: 23, high: 18 };
|
|
72155
72724
|
const crf = crfValues[args.quality ?? "medium"];
|
|
72156
72725
|
await execSafe(
|
|
@@ -72210,8 +72779,8 @@ Audio:`);
|
|
|
72210
72779
|
}),
|
|
72211
72780
|
async execute(args, ctx) {
|
|
72212
72781
|
try {
|
|
72213
|
-
const absInput =
|
|
72214
|
-
const absOutput =
|
|
72782
|
+
const absInput = resolve85(ctx.workingDirectory, args.input);
|
|
72783
|
+
const absOutput = resolve85(ctx.workingDirectory, args.output);
|
|
72215
72784
|
const codecMap = {
|
|
72216
72785
|
h264: "libx264",
|
|
72217
72786
|
h265: "libx265",
|
|
@@ -72264,11 +72833,11 @@ Audio:`);
|
|
|
72264
72833
|
};
|
|
72265
72834
|
}
|
|
72266
72835
|
try {
|
|
72267
|
-
const absOutput =
|
|
72836
|
+
const absOutput = resolve85(ctx.workingDirectory, args.output);
|
|
72268
72837
|
if (args.reencode) {
|
|
72269
72838
|
const ffmpegArgs = [];
|
|
72270
72839
|
for (const i of args.inputs) {
|
|
72271
|
-
ffmpegArgs.push("-i",
|
|
72840
|
+
ffmpegArgs.push("-i", resolve85(ctx.workingDirectory, i));
|
|
72272
72841
|
}
|
|
72273
72842
|
const filterComplex = args.inputs.map((_, i) => `[${i}:v][${i}:a]`).join("");
|
|
72274
72843
|
ffmpegArgs.push(
|
|
@@ -72283,9 +72852,9 @@ Audio:`);
|
|
|
72283
72852
|
);
|
|
72284
72853
|
await execSafe("ffmpeg", ffmpegArgs, { maxBuffer: 100 * 1024 * 1024 });
|
|
72285
72854
|
} else {
|
|
72286
|
-
const tempList =
|
|
72287
|
-
const listContent = args.inputs.map((i) => `file '${
|
|
72288
|
-
await
|
|
72855
|
+
const tempList = resolve85(ctx.workingDirectory, `concat-list-${Date.now()}.txt`);
|
|
72856
|
+
const listContent = args.inputs.map((i) => `file '${resolve85(ctx.workingDirectory, i)}'`).join("\n");
|
|
72857
|
+
await writeFile55(tempList, listContent, "utf-8");
|
|
72289
72858
|
try {
|
|
72290
72859
|
await execSafe(
|
|
72291
72860
|
"ffmpeg",
|
|
@@ -72381,7 +72950,7 @@ var init_walkthrough = __esm({
|
|
|
72381
72950
|
});
|
|
72382
72951
|
|
|
72383
72952
|
// src/tools/manifest/status.ts
|
|
72384
|
-
import { resolve as
|
|
72953
|
+
import { resolve as resolve86 } from "node:path";
|
|
72385
72954
|
var PROJECT_DIR_DESCRIPTION5, statusJobTool, statusProjectTool, statusTools;
|
|
72386
72955
|
var init_status = __esm({
|
|
72387
72956
|
"src/tools/manifest/status.ts"() {
|
|
@@ -72405,7 +72974,7 @@ var init_status = __esm({
|
|
|
72405
72974
|
output: external_exports.string().optional().describe("Download result media to this path when complete.")
|
|
72406
72975
|
}),
|
|
72407
72976
|
async execute(args, ctx) {
|
|
72408
|
-
const projectDir = args.projectDir ?
|
|
72977
|
+
const projectDir = args.projectDir ? resolve86(ctx.workingDirectory, args.projectDir) : findProjectRoot(ctx.workingDirectory);
|
|
72409
72978
|
const record = await readJobRecord(args.jobId, projectDir);
|
|
72410
72979
|
if (!record) return { success: false, error: `Job not found: ${args.jobId}` };
|
|
72411
72980
|
const result = args.refresh === false ? makeJobStatusResult(record, {
|
|
@@ -72414,7 +72983,7 @@ var init_status = __esm({
|
|
|
72414
72983
|
warnings: []
|
|
72415
72984
|
}) : await refreshJobRecord(record, {
|
|
72416
72985
|
wait: args.wait,
|
|
72417
|
-
output: args.output ?
|
|
72986
|
+
output: args.output ? resolve86(ctx.workingDirectory, args.output) : void 0,
|
|
72418
72987
|
workingDirectory: ctx.workingDirectory
|
|
72419
72988
|
});
|
|
72420
72989
|
return {
|
|
@@ -72439,7 +73008,7 @@ var init_status = __esm({
|
|
|
72439
73008
|
refresh: external_exports.boolean().optional().describe("Refresh active supported jobs before summarizing. Default false.")
|
|
72440
73009
|
}),
|
|
72441
73010
|
async execute(args, ctx) {
|
|
72442
|
-
const projectDir = args.projectDir ?
|
|
73011
|
+
const projectDir = args.projectDir ? resolve86(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
|
|
72443
73012
|
const result = await inspectProjectStatus(projectDir, { refresh: args.refresh === true });
|
|
72444
73013
|
return {
|
|
72445
73014
|
success: true,
|
|
@@ -72728,7 +73297,7 @@ init_source();
|
|
|
72728
73297
|
// package.json
|
|
72729
73298
|
var package_default = {
|
|
72730
73299
|
name: "@vibeframe/cli",
|
|
72731
|
-
version: "0.115.
|
|
73300
|
+
version: "0.115.2",
|
|
72732
73301
|
description: "Frontier AI video generation for coding agents - Seedance, Runway, Veo, and Kling on your own keys, behind a hard cost cap",
|
|
72733
73302
|
private: false,
|
|
72734
73303
|
license: "MIT",
|
|
@@ -79603,12 +80172,12 @@ function resolveCopier() {
|
|
|
79603
80172
|
async function copyToClipboard(text) {
|
|
79604
80173
|
const opener = resolveCopier();
|
|
79605
80174
|
if (!opener) return false;
|
|
79606
|
-
return new Promise((
|
|
80175
|
+
return new Promise((resolve87) => {
|
|
79607
80176
|
let settled = false;
|
|
79608
80177
|
const finish = (ok) => {
|
|
79609
80178
|
if (settled) return;
|
|
79610
80179
|
settled = true;
|
|
79611
|
-
|
|
80180
|
+
resolve87(ok);
|
|
79612
80181
|
};
|
|
79613
80182
|
try {
|
|
79614
80183
|
const child = spawn2(opener.command, opener.args, {
|
|
@@ -79739,8 +80308,8 @@ var HOST_CONFIG_DIRS = {
|
|
|
79739
80308
|
};
|
|
79740
80309
|
function isOnPath(binary, env2) {
|
|
79741
80310
|
const path2 = env2.PATH ?? env2.Path ?? "";
|
|
79742
|
-
const
|
|
79743
|
-
for (const dir of path2.split(
|
|
80311
|
+
const sep3 = process.platform === "win32" ? ";" : ":";
|
|
80312
|
+
for (const dir of path2.split(sep3)) {
|
|
79744
80313
|
if (!dir) continue;
|
|
79745
80314
|
if (existsSync39(join20(dir, binary))) return true;
|
|
79746
80315
|
if (process.platform === "win32" && existsSync39(join20(dir, `${binary}.exe`))) return true;
|
|
@@ -80986,7 +81555,7 @@ init_esm();
|
|
|
80986
81555
|
init_source();
|
|
80987
81556
|
import { existsSync as existsSync41 } from "node:fs";
|
|
80988
81557
|
import { mkdir as mkdir22, readFile as readFile36, writeFile as writeFile40 } from "node:fs/promises";
|
|
80989
|
-
import { basename as basename19, dirname as dirname17, resolve as resolve50 } from "node:path";
|
|
81558
|
+
import { basename as basename19, dirname as dirname17, resolve as resolve50, sep } from "node:path";
|
|
80990
81559
|
init_scene_project();
|
|
80991
81560
|
init_visual_styles();
|
|
80992
81561
|
|
|
@@ -82166,10 +82735,14 @@ async function runSceneInit(projectDirArg, options, startedAt) {
|
|
|
82166
82735
|
const storyboardPath2 = resolve50(projectDir, "STORYBOARD.md");
|
|
82167
82736
|
const designPath = resolve50(projectDir, "DESIGN.md");
|
|
82168
82737
|
if (options.force || result.created.includes(storyboardPath2) || !existsSync41(storyboardPath2)) {
|
|
82169
|
-
const plan = await
|
|
82738
|
+
const plan = await rewriteBundleFromMarkdown(projectDir, draft.storyboardMd);
|
|
82170
82739
|
if (!result.created.includes(storyboardPath2)) result.created.push(storyboardPath2);
|
|
82171
|
-
|
|
82172
|
-
|
|
82740
|
+
const planScenePaths = new Set(plan.scenes.map((file) => resolve50(projectDir, file.path)));
|
|
82741
|
+
const scenesDir = resolve50(projectDir, "scenes") + sep;
|
|
82742
|
+
result.created = result.created.filter(
|
|
82743
|
+
(path2) => !path2.startsWith(scenesDir) || planScenePaths.has(path2)
|
|
82744
|
+
);
|
|
82745
|
+
for (const scenePath of planScenePaths) {
|
|
82173
82746
|
if (!result.created.includes(scenePath)) result.created.push(scenePath);
|
|
82174
82747
|
}
|
|
82175
82748
|
}
|
|
@@ -82941,8 +83514,8 @@ init_scene_build();
|
|
|
82941
83514
|
init_build_plan();
|
|
82942
83515
|
init_storyboard_parse();
|
|
82943
83516
|
init_output();
|
|
82944
|
-
import { resolve as
|
|
82945
|
-
import { readFileSync as readFileSync3, existsSync as
|
|
83517
|
+
import { resolve as resolve64, join as join29 } from "node:path";
|
|
83518
|
+
import { readFileSync as readFileSync3, existsSync as existsSync52 } from "node:fs";
|
|
82946
83519
|
var VALID_MODES2 = ["agent", "batch", "auto"];
|
|
82947
83520
|
var VALID_STAGES2 = ["assets", "transcript", "compose", "sync", "render", "all"];
|
|
82948
83521
|
var VALID_IMAGE_PROVIDERS2 = ["openai", "gemini", "grok"];
|
|
@@ -82950,14 +83523,17 @@ var VALID_VIDEO_PROVIDERS2 = ["seedance", "grok", "kling", "runway", "veo"];
|
|
|
82950
83523
|
var VALID_MUSIC_PROVIDERS2 = ["elevenlabs", "replicate"];
|
|
82951
83524
|
var buildCommand = new Command("build").description("Build a VibeFrame video project from STORYBOARD.md").argument("[project-dir]", "Video project directory", ".").option("--stage <stage>", `Build stage: ${VALID_STAGES2.join("|")}`, "all").option("--beat <id>", "Restrict asset/compose work to one beat id").option("--mode <mode>", "Retained for compatibility; scene HTML is always authored by your host agent unless --composer template is set", "auto").option(
|
|
82952
83525
|
"--composer <provider>",
|
|
82953
|
-
"Set to `template` for the deterministic AI-video composer (concat bg + lower-thirds, no model). Omit to let the host agent author each scene."
|
|
83526
|
+
"Set to `template` for the deterministic AI-video composer (concat bg + lower-thirds, no model) or `footage` for the crossfade footage cut (clips + narration + music, no HTML render). Omit to let the host agent author each scene."
|
|
82954
83527
|
).option("--max-cost <usd>", "Fail before provider spend when estimated cost exceeds this USD cap").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-video", "Don't dispatch video generation even when beats declare video cues").option(
|
|
82955
83528
|
"--skip-keyframe",
|
|
82956
83529
|
"Don't generate keyframe stills (review keyframes first with --skip-video, then build)"
|
|
82957
83530
|
).option("--skip-music", "Don't dispatch music generation even when beats declare music cues").option(
|
|
82958
83531
|
"--skip-transcript",
|
|
82959
83532
|
"Don't transcribe narration for word-sync (default: transcribe when narration + OpenAI key exist)"
|
|
82960
|
-
).option("--skip-render", "Compose only - don't render to MP4").option("--tts <provider>", "TTS provider: auto|elevenlabs|openai|kokoro").option("--voice <id>", "Voice id").option("--image-provider <name>", `Image provider: ${VALID_IMAGE_PROVIDERS2.join("|")}`).option(
|
|
83533
|
+
).option("--skip-render", "Compose only - don't render to MP4").option("--tts <provider>", "TTS provider: auto|elevenlabs|openai|kokoro").option("--voice <id>", "Voice id").option("--image-provider <name>", `Image provider: ${VALID_IMAGE_PROVIDERS2.join("|")}`).option(
|
|
83534
|
+
"--image-model <model>",
|
|
83535
|
+
"Image model for keyframes/backdrops/character sheets (gemini: flash|pro, openai: gpt-image-2). Provider default when omitted."
|
|
83536
|
+
).option("--video-provider <name>", `Video provider: ${VALID_VIDEO_PROVIDERS2.join("|")}`).option("--music-provider <name>", `Music provider: ${VALID_MUSIC_PROVIDERS2.join("|")}`).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(
|
|
82961
83537
|
"after",
|
|
82962
83538
|
`
|
|
82963
83539
|
Examples:
|
|
@@ -82968,7 +83544,7 @@ Examples:
|
|
|
82968
83544
|
Advanced equivalent: \`vibe scene build\`.`
|
|
82969
83545
|
).action(async (projectDirArg, options) => {
|
|
82970
83546
|
const startedAt = Date.now();
|
|
82971
|
-
const projectDir =
|
|
83547
|
+
const projectDir = resolve64(projectDirArg);
|
|
82972
83548
|
const mode = String(options.mode ?? "auto");
|
|
82973
83549
|
if (!VALID_MODES2.includes(mode)) {
|
|
82974
83550
|
exitWithError(
|
|
@@ -83025,6 +83601,7 @@ Advanced equivalent: \`vibe scene build\`.`
|
|
|
83025
83601
|
videoProvider,
|
|
83026
83602
|
musicProvider,
|
|
83027
83603
|
imageQuality: options.quality,
|
|
83604
|
+
imageModel: options.imageModel,
|
|
83028
83605
|
imageSize: options.imageSize,
|
|
83029
83606
|
force: options.force ?? false
|
|
83030
83607
|
};
|
|
@@ -83044,6 +83621,7 @@ Advanced equivalent: \`vibe scene build\`.`
|
|
|
83044
83621
|
voice: options.voice,
|
|
83045
83622
|
imageProvider,
|
|
83046
83623
|
imageQuality: options.quality,
|
|
83624
|
+
imageModel: options.imageModel,
|
|
83047
83625
|
imageSize: options.imageSize,
|
|
83048
83626
|
videoProvider,
|
|
83049
83627
|
musicProvider,
|
|
@@ -83118,6 +83696,7 @@ Advanced equivalent: \`vibe scene build\`.`
|
|
|
83118
83696
|
videoProvider,
|
|
83119
83697
|
musicProvider,
|
|
83120
83698
|
imageQuality: options.quality,
|
|
83699
|
+
imageModel: options.imageModel,
|
|
83121
83700
|
imageSize: options.imageSize,
|
|
83122
83701
|
force: options.force,
|
|
83123
83702
|
onProgress: (e) => {
|
|
@@ -83300,8 +83879,8 @@ function buildPlanValidationFailureData(plan) {
|
|
|
83300
83879
|
};
|
|
83301
83880
|
}
|
|
83302
83881
|
function estimateBuildCost(params) {
|
|
83303
|
-
const storyboardPath2 =
|
|
83304
|
-
if (!
|
|
83882
|
+
const storyboardPath2 = join29(params.projectDir, "STORYBOARD.md");
|
|
83883
|
+
if (!existsSync52(storyboardPath2)) return null;
|
|
83305
83884
|
let beats = 0;
|
|
83306
83885
|
try {
|
|
83307
83886
|
const md = readFileSync3(storyboardPath2, "utf-8");
|
|
@@ -83435,7 +84014,7 @@ init_source();
|
|
|
83435
84014
|
init_ora();
|
|
83436
84015
|
init_scene_render();
|
|
83437
84016
|
init_output();
|
|
83438
|
-
import { resolve as
|
|
84017
|
+
import { resolve as resolve65 } from "node:path";
|
|
83439
84018
|
var VALID_FPS = [24, 30, 60];
|
|
83440
84019
|
var VALID_QUALITIES = ["draft", "standard", "high"];
|
|
83441
84020
|
var VALID_FORMATS = ["mp4", "webm", "mov"];
|
|
@@ -83446,7 +84025,7 @@ Examples:
|
|
|
83446
84025
|
|
|
83447
84026
|
Alias note: this is the project-level entrypoint for \`vibe scene render\`.`).action(async (projectDirArg, options) => {
|
|
83448
84027
|
const startedAt = Date.now();
|
|
83449
|
-
const projectDir =
|
|
84028
|
+
const projectDir = resolve65(projectDirArg);
|
|
83450
84029
|
const fps = parseFps(String(options.fps));
|
|
83451
84030
|
const quality = parseQuality(String(options.quality));
|
|
83452
84031
|
const format = parseFormat(String(options.format));
|
|
@@ -83588,7 +84167,7 @@ init_source();
|
|
|
83588
84167
|
init_ora();
|
|
83589
84168
|
init_scene_render();
|
|
83590
84169
|
init_output();
|
|
83591
|
-
import { resolve as
|
|
84170
|
+
import { resolve as resolve66 } from "node:path";
|
|
83592
84171
|
var VALID_FPS2 = [24, 30, 60];
|
|
83593
84172
|
var VALID_QUALITIES2 = ["draft", "standard", "high"];
|
|
83594
84173
|
var VALID_FORMATS2 = ["mp4", "webm", "mov"];
|
|
@@ -83606,7 +84185,7 @@ Examples:
|
|
|
83606
84185
|
$ vibe preview my-video --beat hook
|
|
83607
84186
|
$ vibe preview my-video --fps 30 # override the cheap default`).action(async (projectDirArg, options) => {
|
|
83608
84187
|
const startedAt = Date.now();
|
|
83609
|
-
const projectDir =
|
|
84188
|
+
const projectDir = resolve66(projectDirArg);
|
|
83610
84189
|
const fps = parseFps2(String(options.fps));
|
|
83611
84190
|
const quality = parseQuality2(String(options.quality));
|
|
83612
84191
|
const format = parseFormat2(String(options.format));
|
|
@@ -83743,21 +84322,35 @@ init_esm();
|
|
|
83743
84322
|
init_source();
|
|
83744
84323
|
init_ora();
|
|
83745
84324
|
init_scene_assemble();
|
|
84325
|
+
init_footage_assemble();
|
|
83746
84326
|
init_output();
|
|
83747
|
-
import { resolve as
|
|
84327
|
+
import { resolve as resolve67 } from "node:path";
|
|
83748
84328
|
var VALID_FORMATS3 = ["mp4", "webm", "mov"];
|
|
83749
84329
|
var DEFAULT_VIDEO = "preview.mp4";
|
|
83750
|
-
var assembleCommand = new Command("assemble").description(
|
|
83751
|
-
|
|
83752
|
-
one
|
|
84330
|
+
var assembleCommand = new Command("assemble").description(
|
|
84331
|
+
"Mux a scene project's audio onto a rendered video, or crossfade-cut its generated clips (--footage)"
|
|
84332
|
+
).argument("[project-dir]", "Video project directory", ".").option("--video <path>", `Rendered video to add audio to (default: ${DEFAULT_VIDEO})`, DEFAULT_VIDEO).option("--root <file>", "Root composition file", "index.html").option("--format <f>", `Output container: ${VALID_FORMATS3.join("|")}`, "mp4").option("--footage", "Assemble assets/video-<beat>.mp4 clips into one cinematic cut (no HTML render)").option("-o, --output <path>", "Footage-cut output path (default: renders/footage.mp4)").option("--transition <sec>", "Footage crossfade length in seconds", "0.5").option("--fade <sec>", "Footage fade-from/to-black length in seconds", "0.6").option("--music <path>", 'Footage music bed: a file path or "none" (default: auto-detect assets/music*)').option("--music-volume <v>", "Footage music-bed volume before ducking (0-1)", "0.35").option("--finish", "Footage cinematic finish: vignette + film grain before the fades").option("--dry-run", "Preview parameters without muxing").addHelpText("after", `
|
|
84333
|
+
The default assemble stage lays the project's <audio> elements onto a silent
|
|
84334
|
+
video in one FFmpeg pass (-c:v copy, no re-encode). Pair it with \`vibe render
|
|
84335
|
+
--silent\`:
|
|
83753
84336
|
|
|
83754
84337
|
$ vibe render my-video --silent -o draft.mp4
|
|
83755
84338
|
$ vibe assemble my-video --video draft.mp4
|
|
83756
84339
|
|
|
83757
|
-
|
|
83758
|
-
|
|
84340
|
+
With --footage the project's generated clips become the picture: they are
|
|
84341
|
+
crossfade-concatenated in beat order, narration is laid at computed offsets,
|
|
84342
|
+
an optional music bed is ducked under it, and the head/tail fade to black -
|
|
84343
|
+
one FFmpeg pass, no HTML composition or browser capture. Timing comes from
|
|
84344
|
+
the real files (ffprobe), and assemble-report.json records every offset:
|
|
84345
|
+
|
|
84346
|
+
$ vibe build my-video --stage assets --json # clips + narration
|
|
84347
|
+
$ vibe assemble my-video --footage --json`).action(async (projectDirArg, options) => {
|
|
83759
84348
|
const startedAt = Date.now();
|
|
83760
|
-
const projectDir =
|
|
84349
|
+
const projectDir = resolve67(projectDirArg);
|
|
84350
|
+
if (options.footage) {
|
|
84351
|
+
await runFootageAssemble(projectDir, options, startedAt);
|
|
84352
|
+
return;
|
|
84353
|
+
}
|
|
83761
84354
|
const format = parseFormat3(String(options.format));
|
|
83762
84355
|
const video = String(options.video ?? DEFAULT_VIDEO);
|
|
83763
84356
|
const params = { projectDir, root: options.root, video, format };
|
|
@@ -83794,6 +84387,73 @@ you want the two steps separated (e.g. swap the audio bed without re-rendering).
|
|
|
83794
84387
|
}
|
|
83795
84388
|
printAssembleResult(spinner2, result);
|
|
83796
84389
|
});
|
|
84390
|
+
async function runFootageAssemble(projectDir, options, startedAt) {
|
|
84391
|
+
const transitionSec = parseSeconds("--transition", options.transition);
|
|
84392
|
+
const fadeSec = parseSeconds("--fade", options.fade);
|
|
84393
|
+
const musicVolume = parseSeconds("--music-volume", options.musicVolume);
|
|
84394
|
+
const spinner2 = isJsonMode() || isQuietMode() || options.dryRun ? null : ora("Assembling footage cut...").start();
|
|
84395
|
+
const result = await executeFootageAssemble({
|
|
84396
|
+
projectDir,
|
|
84397
|
+
output: options.output,
|
|
84398
|
+
transitionSec,
|
|
84399
|
+
fadeSec,
|
|
84400
|
+
music: options.music,
|
|
84401
|
+
musicVolume,
|
|
84402
|
+
finish: Boolean(options.finish),
|
|
84403
|
+
dryRun: Boolean(options.dryRun)
|
|
84404
|
+
});
|
|
84405
|
+
if (!result.success) {
|
|
84406
|
+
spinner2?.fail("Footage assemble failed");
|
|
84407
|
+
exitWithError(generalError(result.error ?? "Footage assemble failed", result.suggestion));
|
|
84408
|
+
}
|
|
84409
|
+
if (isJsonMode() || isQuietMode()) {
|
|
84410
|
+
outputSuccess({ command: "assemble", startedAt, dryRun: result.dryRun, data: { ...result } });
|
|
84411
|
+
return;
|
|
84412
|
+
}
|
|
84413
|
+
printFootageResult(spinner2, result);
|
|
84414
|
+
}
|
|
84415
|
+
function printFootageResult(spinner2, result) {
|
|
84416
|
+
const report = result.report;
|
|
84417
|
+
if (result.dryRun) {
|
|
84418
|
+
console.log();
|
|
84419
|
+
console.log(source_default.bold.cyan("VibeFrame Assemble - footage dry run"));
|
|
84420
|
+
} else {
|
|
84421
|
+
spinner2?.succeed(source_default.green(`Footage cut assembled: ${result.outputPath}`));
|
|
84422
|
+
console.log();
|
|
84423
|
+
console.log(source_default.bold.cyan("Footage cut"));
|
|
84424
|
+
}
|
|
84425
|
+
console.log(source_default.dim("-".repeat(60)));
|
|
84426
|
+
if (report) {
|
|
84427
|
+
console.log(` Output: ${source_default.bold(report.output)}`);
|
|
84428
|
+
console.log(` Duration: ${source_default.bold(`${report.totalDurationSec}s`)}`);
|
|
84429
|
+
console.log(` Transition: ${report.transitionSec}s crossfade, ${report.fadeSec}s head/tail fade`);
|
|
84430
|
+
console.log(
|
|
84431
|
+
` Music: ${report.music ? `${report.music.path}${report.music.ducked ? " (ducked)" : ""}` : source_default.dim("none")}`
|
|
84432
|
+
);
|
|
84433
|
+
for (const beat of report.beats) {
|
|
84434
|
+
const narration = beat.narrationStartSec !== void 0 ? ` nar@${beat.narrationStartSec}s` : "";
|
|
84435
|
+
const extended = beat.extendedSec > 0 ? source_default.yellow(` +${beat.extendedSec}s hold`) : "";
|
|
84436
|
+
console.log(
|
|
84437
|
+
` ${beat.id.padEnd(12)} ${String(beat.startSec).padStart(7)}s ${beat.segmentDurationSec}s${narration}${extended}`
|
|
84438
|
+
);
|
|
84439
|
+
}
|
|
84440
|
+
for (const warning of report.warnings) console.log(source_default.yellow(` Warning: ${warning}`));
|
|
84441
|
+
}
|
|
84442
|
+
if (result.dryRun) {
|
|
84443
|
+
console.log();
|
|
84444
|
+
console.log(source_default.dim("No FFmpeg pass ran; nothing was written."));
|
|
84445
|
+
} else if (result.reportPath) {
|
|
84446
|
+
console.log(` Report: ${result.reportPath}`);
|
|
84447
|
+
}
|
|
84448
|
+
}
|
|
84449
|
+
function parseSeconds(flag, value) {
|
|
84450
|
+
if (value === void 0) return void 0;
|
|
84451
|
+
const n = Number.parseFloat(String(value));
|
|
84452
|
+
if (!Number.isFinite(n) || n < 0) {
|
|
84453
|
+
exitWithError(usageError(`Invalid ${flag}: ${String(value)}`, "Expected a non-negative number."));
|
|
84454
|
+
}
|
|
84455
|
+
return n;
|
|
84456
|
+
}
|
|
83797
84457
|
function printAssembleDryRun(projectDirArg, params) {
|
|
83798
84458
|
console.log();
|
|
83799
84459
|
console.log(source_default.bold.cyan("VibeFrame Assemble - dry run"));
|
|
@@ -83829,7 +84489,7 @@ init_source();
|
|
|
83829
84489
|
init_cost_tier();
|
|
83830
84490
|
init_status_jobs();
|
|
83831
84491
|
init_output();
|
|
83832
|
-
import { resolve as
|
|
84492
|
+
import { resolve as resolve68 } from "node:path";
|
|
83833
84493
|
var statusCommand = new Command("status").description("Inspect local async jobs and project workflow status").addHelpText("after", `
|
|
83834
84494
|
Examples:
|
|
83835
84495
|
$ vibe status job job_abc123 --json
|
|
@@ -83840,7 +84500,7 @@ Examples:
|
|
|
83840
84500
|
statusCommand.command("job").description("Show one async job status").argument("<job-id>", "Local job id from a no-wait command").option("--project <dir>", "Project directory containing .vibeframe/jobs").option("--no-refresh", "Read local job record only; do not call provider APIs").option("--wait", "Wait for completion when the provider status helper supports it").option("-o, --output <path>", "Download result media when complete").action(async (jobId, options) => {
|
|
83841
84501
|
const startedAt = Date.now();
|
|
83842
84502
|
try {
|
|
83843
|
-
const projectDir = options.project ?
|
|
84503
|
+
const projectDir = options.project ? resolve68(options.project) : findProjectRoot();
|
|
83844
84504
|
const record = await readJobRecord(jobId, projectDir);
|
|
83845
84505
|
if (!record) {
|
|
83846
84506
|
exitWithError(generalError(`Job not found: ${jobId}`, `Run 'vibe status project ${projectDir} --json' to list known jobs.`));
|
|
@@ -83868,7 +84528,7 @@ applyTier(statusCommand.commands[statusCommand.commands.length - 1], "free");
|
|
|
83868
84528
|
statusCommand.command("project").description("Summarize build, review, and async job status for a project").argument("[project-dir]", "VibeFrame project directory", ".").option("--refresh", "Refresh active supported jobs before summarizing").action(async (projectDirArg, options) => {
|
|
83869
84529
|
const startedAt = Date.now();
|
|
83870
84530
|
try {
|
|
83871
|
-
const result = await inspectProjectStatus(
|
|
84531
|
+
const result = await inspectProjectStatus(resolve68(projectDirArg), {
|
|
83872
84532
|
refresh: options.refresh === true
|
|
83873
84533
|
});
|
|
83874
84534
|
if (isJsonMode()) {
|
|
@@ -83975,8 +84635,8 @@ init_dist2();
|
|
|
83975
84635
|
init_exec_safe();
|
|
83976
84636
|
init_exec_safe();
|
|
83977
84637
|
init_api_key();
|
|
83978
|
-
import { existsSync as
|
|
83979
|
-
import { resolve as
|
|
84638
|
+
import { existsSync as existsSync53 } from "node:fs";
|
|
84639
|
+
import { resolve as resolve69 } from "node:path";
|
|
83980
84640
|
init_composer_resolve();
|
|
83981
84641
|
init_cost_tier();
|
|
83982
84642
|
init_install_skill();
|
|
@@ -84107,13 +84767,13 @@ async function runDiagnostics() {
|
|
|
84107
84767
|
installed = false;
|
|
84108
84768
|
}
|
|
84109
84769
|
} else if (toolName === "chrome") {
|
|
84110
|
-
const { existsSync:
|
|
84770
|
+
const { existsSync: existsSync61 } = await import("node:fs");
|
|
84111
84771
|
const { homedir: homedir8 } = await import("node:os");
|
|
84112
|
-
const { join:
|
|
84772
|
+
const { join: join34 } = await import("node:path");
|
|
84113
84773
|
const chromePaths = [
|
|
84114
84774
|
process.env.HYPERFRAMES_CHROME_PATH,
|
|
84115
84775
|
process.env.CHROME_PATH,
|
|
84116
|
-
|
|
84776
|
+
join34(
|
|
84117
84777
|
homedir8(),
|
|
84118
84778
|
".cache",
|
|
84119
84779
|
"puppeteer",
|
|
@@ -84128,7 +84788,7 @@ async function runDiagnostics() {
|
|
|
84128
84788
|
"/usr/bin/chromium",
|
|
84129
84789
|
"/usr/bin/chromium-browser"
|
|
84130
84790
|
];
|
|
84131
|
-
installed = chromePaths.some((p) => p &&
|
|
84791
|
+
installed = chromePaths.some((p) => p && existsSync61(p));
|
|
84132
84792
|
} else {
|
|
84133
84793
|
installed = commandExists(toolName);
|
|
84134
84794
|
}
|
|
@@ -84168,7 +84828,7 @@ async function runDiagnostics() {
|
|
|
84168
84828
|
}
|
|
84169
84829
|
const projectFiles = ["AGENTS.md", "CLAUDE.md", "vibe.project.yaml"].map((rel) => ({
|
|
84170
84830
|
path: rel,
|
|
84171
|
-
exists:
|
|
84831
|
+
exists: existsSync53(resolve69(cwd, rel))
|
|
84172
84832
|
}));
|
|
84173
84833
|
const projectInitialized = projectFiles.some((f) => f.exists);
|
|
84174
84834
|
const nearestProjectConfigPath = await findProjectConfigPath(cwd);
|
|
@@ -84186,7 +84846,7 @@ async function runDiagnostics() {
|
|
|
84186
84846
|
} catch (err) {
|
|
84187
84847
|
if (!(err instanceof ComposerResolveError)) throw err;
|
|
84188
84848
|
}
|
|
84189
|
-
const sceneProjectInCwd =
|
|
84849
|
+
const sceneProjectInCwd = existsSync53(resolve69(cwd, "STORYBOARD.md"));
|
|
84190
84850
|
const skillInstalled = hyperframesSkillAvailable(cwd);
|
|
84191
84851
|
const skillPath = resolveSkillReference(cwd);
|
|
84192
84852
|
return {
|
|
@@ -84539,7 +85199,7 @@ init_esm();
|
|
|
84539
85199
|
init_source();
|
|
84540
85200
|
init_exec_safe();
|
|
84541
85201
|
init_cost_tier();
|
|
84542
|
-
import { resolve as
|
|
85202
|
+
import { resolve as resolve70 } from "node:path";
|
|
84543
85203
|
init_output();
|
|
84544
85204
|
var hostCommand = new Command("host").description("Set up Codex, Claude, and Cursor app integrations").addHelpText(
|
|
84545
85205
|
"after",
|
|
@@ -84553,7 +85213,7 @@ Examples:
|
|
|
84553
85213
|
);
|
|
84554
85214
|
hostCommand.command("list").description("List supported app hosts and integration surfaces").action(() => {
|
|
84555
85215
|
const startedAt = Date.now();
|
|
84556
|
-
const hosts = hostDefinitions(
|
|
85216
|
+
const hosts = hostDefinitions(resolve70(".")).map((host) => ({
|
|
84557
85217
|
id: host.id,
|
|
84558
85218
|
label: host.label,
|
|
84559
85219
|
surfaces: host.surfaces,
|
|
@@ -84580,7 +85240,7 @@ applyTier(hostCommand.commands[hostCommand.commands.length - 1], "free");
|
|
|
84580
85240
|
hostCommand.command("setup").description("Print or write Codex/Claude/Cursor MCP and project integration config").argument("[host]", `Host target: ${HOST_SELECTIONS.join(" | ")}`, "all").argument("[project-dir]", "Project directory for project-scoped config", ".").option("--write", "Write config files instead of printing snippets only").option("--dry-run", "Show file actions without writing").option("--force", "Replace an existing vibeframe MCP entry").action(async (hostArg, projectDirArg, options) => {
|
|
84581
85241
|
const startedAt = Date.now();
|
|
84582
85242
|
const selection = validateHostSelection(hostArg);
|
|
84583
|
-
const projectDir =
|
|
85243
|
+
const projectDir = resolve70(projectDirArg);
|
|
84584
85244
|
const ids = resolveHostSelection(selection);
|
|
84585
85245
|
const defs = hostDefinitions(projectDir).filter((host) => ids.includes(host.id));
|
|
84586
85246
|
const plans = [];
|
|
@@ -84614,7 +85274,7 @@ applyTier(hostCommand.commands[hostCommand.commands.length - 1], "free");
|
|
|
84614
85274
|
hostCommand.command("doctor").description("Check Codex/Claude/Cursor app integration readiness").argument("[host]", `Host target: ${HOST_SELECTIONS.join(" | ")}`, "all").argument("[project-dir]", "Project directory to inspect", ".").action(async (hostArg, projectDirArg) => {
|
|
84615
85275
|
const startedAt = Date.now();
|
|
84616
85276
|
const selection = validateHostSelection(hostArg);
|
|
84617
|
-
const projectDir =
|
|
85277
|
+
const projectDir = resolve70(projectDirArg);
|
|
84618
85278
|
const ids = resolveHostSelection(selection);
|
|
84619
85279
|
const defs = hostDefinitions(projectDir).filter((host) => ids.includes(host.id));
|
|
84620
85280
|
const hosts = await Promise.all(defs.map((host) => inspectHost(host, projectDir)));
|
|
@@ -84734,10 +85394,10 @@ init_exec_safe();
|
|
|
84734
85394
|
init_detect();
|
|
84735
85395
|
init_ai_edit();
|
|
84736
85396
|
init_output();
|
|
84737
|
-
import { resolve as
|
|
84738
|
-
import { existsSync as
|
|
84739
|
-
import { mkdir as
|
|
84740
|
-
var DEMO_DIR =
|
|
85397
|
+
import { resolve as resolve71 } from "node:path";
|
|
85398
|
+
import { existsSync as existsSync54 } from "node:fs";
|
|
85399
|
+
import { mkdir as mkdir27, rm as rm6 } from "node:fs/promises";
|
|
85400
|
+
var DEMO_DIR = resolve71(process.cwd(), ".vibeframe-demo");
|
|
84741
85401
|
async function generateTestVideo(outputPath) {
|
|
84742
85402
|
const filter = [
|
|
84743
85403
|
// Video: color bars with text
|
|
@@ -84766,7 +85426,7 @@ async function generateTestVideo(outputPath) {
|
|
|
84766
85426
|
"-y",
|
|
84767
85427
|
outputPath
|
|
84768
85428
|
], { timeout: 3e4, maxBuffer: 50 * 1024 * 1024 });
|
|
84769
|
-
return
|
|
85429
|
+
return existsSync54(outputPath);
|
|
84770
85430
|
} catch {
|
|
84771
85431
|
try {
|
|
84772
85432
|
await execSafe("ffmpeg", [
|
|
@@ -84792,7 +85452,7 @@ async function generateTestVideo(outputPath) {
|
|
|
84792
85452
|
"-y",
|
|
84793
85453
|
outputPath
|
|
84794
85454
|
], { timeout: 3e4, maxBuffer: 50 * 1024 * 1024 });
|
|
84795
|
-
return
|
|
85455
|
+
return existsSync54(outputPath);
|
|
84796
85456
|
} catch {
|
|
84797
85457
|
return false;
|
|
84798
85458
|
}
|
|
@@ -84816,8 +85476,8 @@ var demoCommand = new Command("demo").description("Run sample edits on a test vi
|
|
|
84816
85476
|
console.log(source_default.dim(" " + "\u2500".repeat(50)));
|
|
84817
85477
|
console.log();
|
|
84818
85478
|
}
|
|
84819
|
-
await
|
|
84820
|
-
const testVideo =
|
|
85479
|
+
await mkdir27(DEMO_DIR, { recursive: true });
|
|
85480
|
+
const testVideo = resolve71(DEMO_DIR, "test-input.mp4");
|
|
84821
85481
|
const genSpinner = !isJson ? ora("Generating test video...").start() : null;
|
|
84822
85482
|
const generated = await generateTestVideo(testVideo);
|
|
84823
85483
|
if (!generated) {
|
|
@@ -84846,7 +85506,7 @@ var demoCommand = new Command("demo").description("Run sample edits on a test vi
|
|
|
84846
85506
|
name: "Silence Cut",
|
|
84847
85507
|
description: "Removing silent segments",
|
|
84848
85508
|
run: async () => {
|
|
84849
|
-
const output =
|
|
85509
|
+
const output = resolve71(DEMO_DIR, "silence-cut.mp4");
|
|
84850
85510
|
const r = await executeSilenceCut({ videoPath: testVideo, outputPath: output, padding: 0.1 });
|
|
84851
85511
|
if (r.success && r.totalDuration && r.silentDuration) {
|
|
84852
85512
|
return { success: true, detail: `Removed ${r.silentDuration.toFixed(1)}s silence (${r.totalDuration.toFixed(1)}s \u2192 ${(r.totalDuration - r.silentDuration).toFixed(1)}s)` };
|
|
@@ -84858,7 +85518,7 @@ var demoCommand = new Command("demo").description("Run sample edits on a test vi
|
|
|
84858
85518
|
name: "Noise Reduce",
|
|
84859
85519
|
description: "Reducing background noise",
|
|
84860
85520
|
run: async () => {
|
|
84861
|
-
const output =
|
|
85521
|
+
const output = resolve71(DEMO_DIR, "noise-reduced.mp4");
|
|
84862
85522
|
const r = await executeNoiseReduce({ inputPath: testVideo, outputPath: output, strength: "medium" });
|
|
84863
85523
|
return { success: r.success, detail: r.success ? `Cleaned audio \u2192 ${output}` : r.error };
|
|
84864
85524
|
}
|
|
@@ -84867,7 +85527,7 @@ var demoCommand = new Command("demo").description("Run sample edits on a test vi
|
|
|
84867
85527
|
name: "Fade Effects",
|
|
84868
85528
|
description: "Adding fade in/out",
|
|
84869
85529
|
run: async () => {
|
|
84870
|
-
const output =
|
|
85530
|
+
const output = resolve71(DEMO_DIR, "faded.mp4");
|
|
84871
85531
|
const r = await executeFade({ videoPath: testVideo, outputPath: output, fadeIn: 1, fadeOut: 1 });
|
|
84872
85532
|
return { success: r.success, detail: r.success ? `1s fade in + 1s fade out \u2192 ${output}` : r.error };
|
|
84873
85533
|
}
|
|
@@ -84934,20 +85594,20 @@ var demoCommand = new Command("demo").description("Run sample edits on a test vi
|
|
|
84934
85594
|
|
|
84935
85595
|
// src/commands/context.ts
|
|
84936
85596
|
init_esm();
|
|
84937
|
-
import { existsSync as
|
|
85597
|
+
import { existsSync as existsSync55 } from "node:fs";
|
|
84938
85598
|
import { readFile as readFile45 } from "node:fs/promises";
|
|
84939
|
-
import { resolve as
|
|
85599
|
+
import { resolve as resolve72, dirname as dirname23 } from "node:path";
|
|
84940
85600
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
84941
85601
|
var __filename = fileURLToPath2(import.meta.url);
|
|
84942
|
-
var __dirname =
|
|
85602
|
+
var __dirname = dirname23(__filename);
|
|
84943
85603
|
function resolveContextPath(baseDir = __dirname) {
|
|
84944
85604
|
const candidates = [
|
|
84945
85605
|
// Bundled package layout: packages/cli/dist/index.js -> packages/cli/CONTEXT.md
|
|
84946
|
-
|
|
85606
|
+
resolve72(baseDir, "../CONTEXT.md"),
|
|
84947
85607
|
// Source/dev layout: packages/cli/src/commands/context.ts -> packages/cli/CONTEXT.md
|
|
84948
|
-
|
|
85608
|
+
resolve72(baseDir, "../../CONTEXT.md")
|
|
84949
85609
|
];
|
|
84950
|
-
return candidates.find((candidate) =>
|
|
85610
|
+
return candidates.find((candidate) => existsSync55(candidate)) ?? null;
|
|
84951
85611
|
}
|
|
84952
85612
|
var contextCommand = new Command("context").description("Print CLI context/guidelines for AI agent integration").option("--format <format>", "Output format: markdown | json", "markdown").action(async (_options, cmd) => {
|
|
84953
85613
|
const options = {
|
|
@@ -86002,7 +86662,7 @@ async function startAgent(options = {}) {
|
|
|
86002
86662
|
console.log();
|
|
86003
86663
|
console.log(source_default.dim(" Commands: exit \xB7 reset \xB7 tools \xB7 context"));
|
|
86004
86664
|
console.log();
|
|
86005
|
-
return new Promise((
|
|
86665
|
+
return new Promise((resolve87) => {
|
|
86006
86666
|
if (typeof process.stdin.ref === "function") {
|
|
86007
86667
|
process.stdin.ref();
|
|
86008
86668
|
}
|
|
@@ -86109,7 +86769,7 @@ async function startAgent(options = {}) {
|
|
|
86109
86769
|
clearInterval(keepalive);
|
|
86110
86770
|
console.log();
|
|
86111
86771
|
console.log(source_default.dim("Goodbye!"));
|
|
86112
|
-
|
|
86772
|
+
resolve87();
|
|
86113
86773
|
});
|
|
86114
86774
|
rl.prompt();
|
|
86115
86775
|
});
|
|
@@ -86383,8 +87043,8 @@ init_source();
|
|
|
86383
87043
|
init_config();
|
|
86384
87044
|
init_schema();
|
|
86385
87045
|
init_api_key();
|
|
86386
|
-
import { access as access9, writeFile as
|
|
86387
|
-
import { dirname as
|
|
87046
|
+
import { access as access9, writeFile as writeFile56, mkdir as mkdir30 } from "node:fs/promises";
|
|
87047
|
+
import { dirname as dirname25 } from "node:path";
|
|
86388
87048
|
var BANNER_SHOWN_PATH = `${USER_CONFIG_DIR}/.banner-shown`;
|
|
86389
87049
|
async function isFirstRun() {
|
|
86390
87050
|
try {
|
|
@@ -86403,8 +87063,8 @@ async function isFirstRun() {
|
|
|
86403
87063
|
}
|
|
86404
87064
|
async function markBannerShown() {
|
|
86405
87065
|
try {
|
|
86406
|
-
await
|
|
86407
|
-
await
|
|
87066
|
+
await mkdir30(dirname25(BANNER_SHOWN_PATH), { recursive: true });
|
|
87067
|
+
await writeFile56(BANNER_SHOWN_PATH, (/* @__PURE__ */ new Date()).toISOString());
|
|
86408
87068
|
} catch {
|
|
86409
87069
|
}
|
|
86410
87070
|
}
|