@vibeframe/mcp-server 0.113.0 → 0.113.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/README.md +131 -120
- package/dist/index.js +1687 -652
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -4742,14 +4742,14 @@ async function loadKokoroRuntime() {
|
|
|
4742
4742
|
async function loadKokoroFromWorkspace(baseDir = process.cwd()) {
|
|
4743
4743
|
try {
|
|
4744
4744
|
const { readFile: readFile46 } = await import("node:fs/promises");
|
|
4745
|
-
const { join:
|
|
4745
|
+
const { join: join44, resolve: resolve80 } = await import("node:path");
|
|
4746
4746
|
const { pathToFileURL } = await import("node:url");
|
|
4747
4747
|
const pkgDir = resolve80(baseDir, "node_modules", "kokoro-js");
|
|
4748
|
-
const pkg = JSON.parse(await readFile46(
|
|
4748
|
+
const pkg = JSON.parse(await readFile46(join44(pkgDir, "package.json"), "utf-8"));
|
|
4749
4749
|
const entry = pkg.exports?.node?.import ?? pkg.exports?.default ?? pkg.module ?? pkg.main;
|
|
4750
4750
|
if (!entry)
|
|
4751
4751
|
return null;
|
|
4752
|
-
const mod = await import(pathToFileURL(
|
|
4752
|
+
const mod = await import(pathToFileURL(join44(pkgDir, entry)).href);
|
|
4753
4753
|
return mod.KokoroTTS ?? null;
|
|
4754
4754
|
} catch {
|
|
4755
4755
|
return null;
|
|
@@ -4761,19 +4761,19 @@ async function loadBundledKokoroRuntime(runtimeDir = process.env.VIBE_KOKORO_RUN
|
|
|
4761
4761
|
return null;
|
|
4762
4762
|
try {
|
|
4763
4763
|
const { readFile: readFile46, writeFile: writeFile53, mkdir: mkdir30 } = await import("node:fs/promises");
|
|
4764
|
-
const { join:
|
|
4764
|
+
const { join: join44, resolve: resolve80 } = await import("node:path");
|
|
4765
4765
|
const { pathToFileURL } = await import("node:url");
|
|
4766
4766
|
const { homedir: homedir8 } = await import("node:os");
|
|
4767
4767
|
const transformersDir = resolve80(base, "node_modules", "@huggingface", "transformers");
|
|
4768
4768
|
const ortDistDir = resolve80(base, "node_modules", "onnxruntime-web", "dist");
|
|
4769
|
-
const transformers = await import(pathToFileURL(
|
|
4770
|
-
const cacheRoot =
|
|
4769
|
+
const transformers = await import(pathToFileURL(join44(transformersDir, "dist", "transformers.web.js")).href);
|
|
4770
|
+
const cacheRoot = join44(homedir8(), ".cache", "vibeframe", "models");
|
|
4771
4771
|
transformers.env.allowLocalModels = false;
|
|
4772
4772
|
transformers.env.useCustomCache = true;
|
|
4773
4773
|
transformers.env.customCache = {
|
|
4774
4774
|
async match(key2) {
|
|
4775
4775
|
try {
|
|
4776
|
-
return new Response(await readFile46(
|
|
4776
|
+
return new Response(await readFile46(join44(cacheRoot, encodeURIComponent(String(key2)))));
|
|
4777
4777
|
} catch {
|
|
4778
4778
|
return void 0;
|
|
4779
4779
|
}
|
|
@@ -4782,7 +4782,7 @@ async function loadBundledKokoroRuntime(runtimeDir = process.env.VIBE_KOKORO_RUN
|
|
|
4782
4782
|
try {
|
|
4783
4783
|
const buf = Buffer.from(await response.arrayBuffer());
|
|
4784
4784
|
await mkdir30(cacheRoot, { recursive: true });
|
|
4785
|
-
await writeFile53(
|
|
4785
|
+
await writeFile53(join44(cacheRoot, encodeURIComponent(String(key2))), buf);
|
|
4786
4786
|
} catch {
|
|
4787
4787
|
}
|
|
4788
4788
|
}
|
|
@@ -10460,6 +10460,19 @@ var require_src = __commonJS({
|
|
|
10460
10460
|
});
|
|
10461
10461
|
|
|
10462
10462
|
// ../ai-providers/dist/fal/FalProvider.js
|
|
10463
|
+
function estimateSeedanceVideoCostUsd(opts) {
|
|
10464
|
+
const shortSide = SEEDANCE_SHORT_SIDE[opts.resolution ?? "720p"] ?? 720;
|
|
10465
|
+
const [a2, b2] = (opts.aspectRatio ?? "16:9").split(":").map(Number);
|
|
10466
|
+
const ratioFactor = a2 > 0 && b2 > 0 ? Math.max(a2, b2) / Math.min(a2, b2) : 16 / 9;
|
|
10467
|
+
const longSide = Math.round(shortSide * ratioFactor);
|
|
10468
|
+
const tokensPerSecond = shortSide * longSide * 24 / 1024;
|
|
10469
|
+
let usdPerSecond = tokensPerSecond / 1e3 * SEEDANCE_USD_PER_1K_TOKENS;
|
|
10470
|
+
if (opts.fast && shortSide <= 720)
|
|
10471
|
+
usdPerSecond *= SEEDANCE_FAST_FACTOR;
|
|
10472
|
+
if (opts.hasVideoReference)
|
|
10473
|
+
usdPerSecond *= SEEDANCE_VIDEO_REF_FACTOR;
|
|
10474
|
+
return Number((usdPerSecond * Math.max(0, opts.durationSec)).toFixed(2));
|
|
10475
|
+
}
|
|
10463
10476
|
function formatFalError(error) {
|
|
10464
10477
|
if (!(error instanceof Error))
|
|
10465
10478
|
return String(error);
|
|
@@ -10569,7 +10582,7 @@ function normaliseDuration(value) {
|
|
|
10569
10582
|
return "auto";
|
|
10570
10583
|
return Math.max(4, Math.min(15, Math.round(value)));
|
|
10571
10584
|
}
|
|
10572
|
-
var import_client, ENDPOINT_TEXT_TO_VIDEO, ENDPOINT_IMAGE_TO_VIDEO, ENDPOINT_REFERENCE_TO_VIDEO, DEFAULT_VARIANT, VALID_RESOLUTIONS, VALID_ASPECTS, FalProvider, falProvider;
|
|
10585
|
+
var import_client, ENDPOINT_TEXT_TO_VIDEO, ENDPOINT_IMAGE_TO_VIDEO, ENDPOINT_REFERENCE_TO_VIDEO, DEFAULT_VARIANT, VALID_RESOLUTIONS, VALID_ASPECTS, SEEDANCE_USD_PER_1K_TOKENS, SEEDANCE_FAST_FACTOR, SEEDANCE_VIDEO_REF_FACTOR, SEEDANCE_SHORT_SIDE, FalProvider, falProvider;
|
|
10573
10586
|
var init_FalProvider = __esm({
|
|
10574
10587
|
"../ai-providers/dist/fal/FalProvider.js"() {
|
|
10575
10588
|
"use strict";
|
|
@@ -10589,6 +10602,10 @@ var init_FalProvider = __esm({
|
|
|
10589
10602
|
DEFAULT_VARIANT = "seedance-2.0";
|
|
10590
10603
|
VALID_RESOLUTIONS = ["480p", "720p", "1080p"];
|
|
10591
10604
|
VALID_ASPECTS = ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16", "auto"];
|
|
10605
|
+
SEEDANCE_USD_PER_1K_TOKENS = 0.014;
|
|
10606
|
+
SEEDANCE_FAST_FACTOR = 0.8;
|
|
10607
|
+
SEEDANCE_VIDEO_REF_FACTOR = 0.6;
|
|
10608
|
+
SEEDANCE_SHORT_SIDE = { "480p": 480, "720p": 720, "1080p": 1080 };
|
|
10592
10609
|
FalProvider = class {
|
|
10593
10610
|
constructor() {
|
|
10594
10611
|
this.id = "seedance";
|
|
@@ -11413,6 +11430,7 @@ __export(dist_exports, {
|
|
|
11413
11430
|
defineApiKey: () => defineApiKey,
|
|
11414
11431
|
defineProvider: () => defineProvider,
|
|
11415
11432
|
elevenLabsProvider: () => elevenLabsProvider,
|
|
11433
|
+
estimateSeedanceVideoCostUsd: () => estimateSeedanceVideoCostUsd,
|
|
11416
11434
|
falProvider: () => falProvider,
|
|
11417
11435
|
geminiProvider: () => geminiProvider,
|
|
11418
11436
|
getAllApiKeys: () => getAllApiKeys,
|
|
@@ -24219,7 +24237,534 @@ var init_build_asset_metadata = __esm({
|
|
|
24219
24237
|
}
|
|
24220
24238
|
});
|
|
24221
24239
|
|
|
24240
|
+
// ../cli/src/commands/_shared/review-report.ts
|
|
24241
|
+
import { writeFile as writeFile6 } from "node:fs/promises";
|
|
24242
|
+
import { join as join2, resolve as resolve5 } from "node:path";
|
|
24243
|
+
function statusFromIssues(issues) {
|
|
24244
|
+
if (issues.some((issue) => issue.severity === "error")) return "fail";
|
|
24245
|
+
if (issues.some((issue) => issue.severity === "warning")) return "warn";
|
|
24246
|
+
return "pass";
|
|
24247
|
+
}
|
|
24248
|
+
function scoreIssues(issues) {
|
|
24249
|
+
let score = 100;
|
|
24250
|
+
for (const issue of issues) {
|
|
24251
|
+
if (issue.severity === "error") score -= 25;
|
|
24252
|
+
else if (issue.severity === "warning") score -= 8;
|
|
24253
|
+
else score -= 2;
|
|
24254
|
+
}
|
|
24255
|
+
return Math.max(0, Math.min(100, score));
|
|
24256
|
+
}
|
|
24257
|
+
function uniqueRetryWith(items) {
|
|
24258
|
+
return [
|
|
24259
|
+
...new Set(items.filter((item) => typeof item === "string" && item.length > 0))
|
|
24260
|
+
];
|
|
24261
|
+
}
|
|
24262
|
+
function commandReviewAction(command3, opts) {
|
|
24263
|
+
const classified = classifyReviewCommand(command3);
|
|
24264
|
+
return stripUndefined({
|
|
24265
|
+
id: actionId("command", command3),
|
|
24266
|
+
kind: "command",
|
|
24267
|
+
label: opts.label ?? command3,
|
|
24268
|
+
command: command3,
|
|
24269
|
+
fixOwner: opts.fixOwner ?? classified.fixOwner,
|
|
24270
|
+
costTier: opts.costTier ?? classified.costTier,
|
|
24271
|
+
safeToAutoRun: opts.safeToAutoRun ?? classified.safeToAutoRun,
|
|
24272
|
+
requiresConfirmation: opts.requiresConfirmation ?? classified.requiresConfirmation,
|
|
24273
|
+
reason: opts.reason,
|
|
24274
|
+
sourceIssueCodes: uniqueStrings(opts.sourceIssueCodes ?? [])
|
|
24275
|
+
});
|
|
24276
|
+
}
|
|
24277
|
+
function agentReviewAction(opts) {
|
|
24278
|
+
return stripUndefined({
|
|
24279
|
+
id: actionId("agent", opts.agentPrompt),
|
|
24280
|
+
kind: "agent",
|
|
24281
|
+
label: opts.label,
|
|
24282
|
+
agentPrompt: opts.agentPrompt,
|
|
24283
|
+
fixOwner: "host-agent",
|
|
24284
|
+
costTier: "unknown",
|
|
24285
|
+
safeToAutoRun: false,
|
|
24286
|
+
requiresConfirmation: false,
|
|
24287
|
+
reason: opts.reason,
|
|
24288
|
+
sourceIssueCodes: uniqueStrings(opts.sourceIssueCodes ?? [])
|
|
24289
|
+
});
|
|
24290
|
+
}
|
|
24291
|
+
function manualReviewAction(opts) {
|
|
24292
|
+
return stripUndefined({
|
|
24293
|
+
id: actionId("manual", opts.label),
|
|
24294
|
+
kind: "manual",
|
|
24295
|
+
label: opts.label,
|
|
24296
|
+
fixOwner: opts.fixOwner ?? "host-agent",
|
|
24297
|
+
costTier: "unknown",
|
|
24298
|
+
safeToAutoRun: false,
|
|
24299
|
+
requiresConfirmation: false,
|
|
24300
|
+
reason: opts.reason,
|
|
24301
|
+
sourceIssueCodes: uniqueStrings(opts.sourceIssueCodes ?? [])
|
|
24302
|
+
});
|
|
24303
|
+
}
|
|
24304
|
+
function reviewActionsFromRetryWith(retryWith, sourceIssueCodes = []) {
|
|
24305
|
+
return normalizeReviewActions(
|
|
24306
|
+
retryWith.map((item) => {
|
|
24307
|
+
if (/^codex\s+/i.test(item)) {
|
|
24308
|
+
return agentReviewAction({
|
|
24309
|
+
label: "Ask the host agent to fix review issues",
|
|
24310
|
+
agentPrompt: item,
|
|
24311
|
+
reason: "The review report contains host-agent-owned issues.",
|
|
24312
|
+
sourceIssueCodes
|
|
24313
|
+
});
|
|
24314
|
+
}
|
|
24315
|
+
return commandReviewAction(item, {
|
|
24316
|
+
reason: "Backward-compatible retryWith command.",
|
|
24317
|
+
sourceIssueCodes
|
|
24318
|
+
});
|
|
24319
|
+
})
|
|
24320
|
+
);
|
|
24321
|
+
}
|
|
24322
|
+
function normalizeReviewActions(actions) {
|
|
24323
|
+
const merged = /* @__PURE__ */ new Map();
|
|
24324
|
+
for (const action of actions) {
|
|
24325
|
+
const key2 = [action.kind, action.command ?? action.agentPrompt ?? action.label].join("\0");
|
|
24326
|
+
const existing = merged.get(key2);
|
|
24327
|
+
if (!existing) {
|
|
24328
|
+
merged.set(key2, {
|
|
24329
|
+
...action,
|
|
24330
|
+
sourceIssueCodes: uniqueStrings(action.sourceIssueCodes ?? [])
|
|
24331
|
+
});
|
|
24332
|
+
continue;
|
|
24333
|
+
}
|
|
24334
|
+
merged.set(key2, {
|
|
24335
|
+
...existing,
|
|
24336
|
+
safeToAutoRun: existing.safeToAutoRun && action.safeToAutoRun,
|
|
24337
|
+
requiresConfirmation: existing.requiresConfirmation || action.requiresConfirmation,
|
|
24338
|
+
sourceIssueCodes: uniqueStrings([
|
|
24339
|
+
...existing.sourceIssueCodes ?? [],
|
|
24340
|
+
...action.sourceIssueCodes ?? []
|
|
24341
|
+
])
|
|
24342
|
+
});
|
|
24343
|
+
}
|
|
24344
|
+
return [...merged.values()].map(
|
|
24345
|
+
(action) => stripUndefined({
|
|
24346
|
+
...action,
|
|
24347
|
+
sourceIssueCodes: action.sourceIssueCodes && action.sourceIssueCodes.length > 0 ? action.sourceIssueCodes : void 0
|
|
24348
|
+
})
|
|
24349
|
+
);
|
|
24350
|
+
}
|
|
24351
|
+
function deriveNextReviewActions(opts) {
|
|
24352
|
+
return normalizeReviewActions([
|
|
24353
|
+
...opts.issues.flatMap((issue) => issue.actions ?? []),
|
|
24354
|
+
...reviewActionsFromRetryWith(opts.retryWith)
|
|
24355
|
+
]);
|
|
24356
|
+
}
|
|
24357
|
+
function fixOwnerForIssue(issue) {
|
|
24358
|
+
if (issue.fixOwner) return issue.fixOwner;
|
|
24359
|
+
if (issue.code.startsWith("AI_REVIEW_")) return "host-agent";
|
|
24360
|
+
if (issue.code.startsWith("STORYBOARD_")) return "host-agent";
|
|
24361
|
+
if (issue.code === "PROJECT_NOT_FOUND" || issue.code === "MISSING_STORYBOARD" || issue.code === "BEAT_NOT_FOUND" || issue.code === "MISSING_DESIGN") {
|
|
24362
|
+
return "host-agent";
|
|
24363
|
+
}
|
|
24364
|
+
return "vibe";
|
|
24365
|
+
}
|
|
24366
|
+
function normalizeReviewIssues(issues, opts) {
|
|
24367
|
+
const fallbackOwner = typeof opts === "string" ? opts : opts?.fallbackOwner;
|
|
24368
|
+
const projectDir = typeof opts === "string" ? void 0 : opts?.projectDir;
|
|
24369
|
+
return issues.map((issue) => {
|
|
24370
|
+
const normalized = {
|
|
24371
|
+
...issue,
|
|
24372
|
+
fixOwner: issue.fixOwner ?? fallbackOwner ?? fixOwnerForIssue(issue)
|
|
24373
|
+
};
|
|
24374
|
+
const actions = normalizeReviewActions([
|
|
24375
|
+
...issue.actions ?? [],
|
|
24376
|
+
...projectDir ? defaultActionsForIssue(normalized, projectDir) : []
|
|
24377
|
+
]);
|
|
24378
|
+
return stripUndefined({
|
|
24379
|
+
...normalized,
|
|
24380
|
+
actions: actions.length > 0 ? actions : void 0
|
|
24381
|
+
});
|
|
24382
|
+
});
|
|
24383
|
+
}
|
|
24384
|
+
function summarizeReviewIssues(issues) {
|
|
24385
|
+
const normalized = normalizeReviewIssues(issues);
|
|
24386
|
+
return {
|
|
24387
|
+
issueCount: normalized.length,
|
|
24388
|
+
errorCount: normalized.filter((issue) => issue.severity === "error").length,
|
|
24389
|
+
warningCount: normalized.filter((issue) => issue.severity === "warning").length,
|
|
24390
|
+
infoCount: normalized.filter((issue) => issue.severity === "info").length,
|
|
24391
|
+
fixOwners: {
|
|
24392
|
+
vibe: normalized.filter((issue) => issue.fixOwner === "vibe").length,
|
|
24393
|
+
hostAgent: normalized.filter((issue) => issue.fixOwner === "host-agent").length
|
|
24394
|
+
}
|
|
24395
|
+
};
|
|
24396
|
+
}
|
|
24397
|
+
function buildReviewReport(opts) {
|
|
24398
|
+
const retryWith = uniqueRetryWith(opts.retryWith);
|
|
24399
|
+
const issues = normalizeReviewIssues(opts.issues, {
|
|
24400
|
+
projectDir: opts.project,
|
|
24401
|
+
retryWith
|
|
24402
|
+
});
|
|
24403
|
+
return stripUndefined({
|
|
24404
|
+
schemaVersion: "1",
|
|
24405
|
+
kind: "review",
|
|
24406
|
+
project: resolve5(opts.project),
|
|
24407
|
+
mode: opts.mode,
|
|
24408
|
+
beat: opts.beat,
|
|
24409
|
+
status: opts.status,
|
|
24410
|
+
score: opts.score,
|
|
24411
|
+
issues,
|
|
24412
|
+
summary: summarizeReviewIssues(issues),
|
|
24413
|
+
nextActions: deriveNextReviewActions({ issues, retryWith, projectDir: opts.project }),
|
|
24414
|
+
retryWith,
|
|
24415
|
+
sourceReports: opts.sourceReports ?? [],
|
|
24416
|
+
reportPath: opts.reportPath
|
|
24417
|
+
});
|
|
24418
|
+
}
|
|
24419
|
+
function defaultReviewReportPath(projectDir) {
|
|
24420
|
+
return join2(resolve5(projectDir), "review-report.json");
|
|
24421
|
+
}
|
|
24422
|
+
async function writeReviewReport(path14, report) {
|
|
24423
|
+
await writeFile6(path14, JSON.stringify(report, null, 2) + "\n", "utf-8");
|
|
24424
|
+
}
|
|
24425
|
+
function stripUndefined(value) {
|
|
24426
|
+
return Object.fromEntries(Object.entries(value).filter(([, v2]) => v2 !== void 0));
|
|
24427
|
+
}
|
|
24428
|
+
function defaultActionsForIssue(issue, projectDir) {
|
|
24429
|
+
const code = issue.code;
|
|
24430
|
+
const beat = issue.beatId ?? issue.scene;
|
|
24431
|
+
const beatFlag = beat ? ` --beat ${beat}` : "";
|
|
24432
|
+
const sourceIssueCodes = [code];
|
|
24433
|
+
if (code === "PROJECT_NOT_FOUND" || code === "MISSING_STORYBOARD") {
|
|
24434
|
+
return [
|
|
24435
|
+
commandReviewAction(`vibe init ${projectDir} --from "<brief>" --json`, {
|
|
24436
|
+
label: "Initialize the project from a brief",
|
|
24437
|
+
fixOwner: "host-agent",
|
|
24438
|
+
reason: "The project cannot be inspected until the core project files exist.",
|
|
24439
|
+
sourceIssueCodes
|
|
24440
|
+
})
|
|
24441
|
+
];
|
|
24442
|
+
}
|
|
24443
|
+
if (code === "MISSING_DESIGN" || code === "DESIGN_PLACEHOLDER_FIELD") {
|
|
24444
|
+
return [
|
|
24445
|
+
manualReviewAction({
|
|
24446
|
+
label: "Create or complete DESIGN.md",
|
|
24447
|
+
reason: "Visual direction needs host-agent or human input before VibeFrame can repair it.",
|
|
24448
|
+
sourceIssueCodes
|
|
24449
|
+
})
|
|
24450
|
+
];
|
|
24451
|
+
}
|
|
24452
|
+
if (code === "BEAT_NOT_FOUND" || code.startsWith("STORYBOARD_")) {
|
|
24453
|
+
const actions = [
|
|
24454
|
+
commandReviewAction(`vibe storyboard validate ${projectDir} --json`, {
|
|
24455
|
+
label: "Validate the storyboard",
|
|
24456
|
+
fixOwner: "host-agent",
|
|
24457
|
+
reason: "The storyboard issue needs structured validation before editing.",
|
|
24458
|
+
sourceIssueCodes
|
|
24459
|
+
})
|
|
24460
|
+
];
|
|
24461
|
+
if (code === "STORYBOARD_PLACEHOLDER_CUE") {
|
|
24462
|
+
actions.push(
|
|
24463
|
+
commandReviewAction(
|
|
24464
|
+
`vibe storyboard revise ${projectDir} --from "<make cues concrete>" --dry-run --json`,
|
|
24465
|
+
{
|
|
24466
|
+
label: "Preview a storyboard revision",
|
|
24467
|
+
fixOwner: "host-agent",
|
|
24468
|
+
reason: "Placeholder cues should be revised into concrete video intent.",
|
|
24469
|
+
sourceIssueCodes
|
|
24470
|
+
}
|
|
24471
|
+
)
|
|
24472
|
+
);
|
|
24473
|
+
}
|
|
24474
|
+
return actions;
|
|
24475
|
+
}
|
|
24476
|
+
if (code === "MISSING_ROOT_COMPOSITION" || code === "ROOT_SYNC_CHECK_FAILED") {
|
|
24477
|
+
return [
|
|
24478
|
+
commandReviewAction(`vibe build ${projectDir} --stage sync --json`, {
|
|
24479
|
+
label: "Sync the project root composition",
|
|
24480
|
+
reason: "The root composition is missing or could not be verified.",
|
|
24481
|
+
sourceIssueCodes
|
|
24482
|
+
})
|
|
24483
|
+
];
|
|
24484
|
+
}
|
|
24485
|
+
if (code.startsWith("ROOT_")) {
|
|
24486
|
+
return issue.fixOwner === "host-agent" ? [
|
|
24487
|
+
agentReviewAction({
|
|
24488
|
+
label: "Repair the root composition shell",
|
|
24489
|
+
agentPrompt: "Fix host-agent-owned root composition issues from review-report.json",
|
|
24490
|
+
reason: "The root composition cannot be repaired deterministically.",
|
|
24491
|
+
sourceIssueCodes
|
|
24492
|
+
})
|
|
24493
|
+
] : [
|
|
24494
|
+
commandReviewAction(`vibe scene repair ${projectDir} --json`, {
|
|
24495
|
+
label: "Repair deterministic scene/root issues",
|
|
24496
|
+
reason: "The root composition has deterministic sync issues.",
|
|
24497
|
+
sourceIssueCodes
|
|
24498
|
+
}),
|
|
24499
|
+
commandReviewAction(`vibe build ${projectDir} --stage sync --json`, {
|
|
24500
|
+
label: "Resync root composition after repair",
|
|
24501
|
+
reason: "The root composition should be synced after deterministic repair.",
|
|
24502
|
+
sourceIssueCodes
|
|
24503
|
+
})
|
|
24504
|
+
];
|
|
24505
|
+
}
|
|
24506
|
+
if (code === "MISSING_COMPOSITION") {
|
|
24507
|
+
return [
|
|
24508
|
+
commandReviewAction(`vibe build ${projectDir}${beatFlag} --stage compose --json`, {
|
|
24509
|
+
label: beat ? `Compose beat ${beat}` : "Compose missing scenes",
|
|
24510
|
+
reason: "Missing scene compositions must be generated or authored before render.",
|
|
24511
|
+
sourceIssueCodes
|
|
24512
|
+
})
|
|
24513
|
+
];
|
|
24514
|
+
}
|
|
24515
|
+
if (code === "MISSING_BUILD_REPORT") {
|
|
24516
|
+
return [
|
|
24517
|
+
commandReviewAction(`vibe build ${projectDir} --dry-run --json`, {
|
|
24518
|
+
label: "Preview the build plan",
|
|
24519
|
+
reason: "A dry-run build report is needed before choosing a paid or mutating build step.",
|
|
24520
|
+
sourceIssueCodes
|
|
24521
|
+
})
|
|
24522
|
+
];
|
|
24523
|
+
}
|
|
24524
|
+
if (code === "BUILD_REPORT_BEAT_MISSING") {
|
|
24525
|
+
return [
|
|
24526
|
+
commandReviewAction(`vibe build ${projectDir}${beatFlag} --stage sync --json`, {
|
|
24527
|
+
label: beat ? `Sync build report for beat ${beat}` : "Sync the build report",
|
|
24528
|
+
reason: "The build report does not include the inspected beat.",
|
|
24529
|
+
sourceIssueCodes
|
|
24530
|
+
})
|
|
24531
|
+
];
|
|
24532
|
+
}
|
|
24533
|
+
if (code === "MALFORMED_BUILD_REPORT") {
|
|
24534
|
+
return [
|
|
24535
|
+
commandReviewAction(`vibe build ${projectDir} --json`, {
|
|
24536
|
+
label: "Regenerate the build report",
|
|
24537
|
+
reason: "The existing build report cannot be parsed.",
|
|
24538
|
+
sourceIssueCodes
|
|
24539
|
+
})
|
|
24540
|
+
];
|
|
24541
|
+
}
|
|
24542
|
+
if (code === "MISSING_REPORTED_ASSET" || code === "STALE_ASSET" || code === "UNKNOWN_ASSET_FRESHNESS") {
|
|
24543
|
+
return [
|
|
24544
|
+
commandReviewAction(`vibe build ${projectDir}${beatFlag} --stage assets --force --json`, {
|
|
24545
|
+
label: beat ? `Regenerate assets for beat ${beat}` : "Regenerate stale or missing assets",
|
|
24546
|
+
reason: "Asset generation may call providers, so the host should confirm first.",
|
|
24547
|
+
sourceIssueCodes
|
|
24548
|
+
})
|
|
24549
|
+
];
|
|
24550
|
+
}
|
|
24551
|
+
if (code === "MUSIC_CUE_NOT_READY") {
|
|
24552
|
+
return [
|
|
24553
|
+
commandReviewAction(`vibe build ${projectDir}${beatFlag} --stage assets --json`, {
|
|
24554
|
+
label: beat ? `Generate music for beat ${beat}` : "Generate missing music assets",
|
|
24555
|
+
reason: "Music generation may call providers, so the host should confirm first.",
|
|
24556
|
+
sourceIssueCodes
|
|
24557
|
+
}),
|
|
24558
|
+
commandReviewAction(`vibe build ${projectDir} --stage sync --json`, {
|
|
24559
|
+
label: "Sync music into the root composition",
|
|
24560
|
+
reason: "Generated music needs root composition wiring.",
|
|
24561
|
+
sourceIssueCodes
|
|
24562
|
+
})
|
|
24563
|
+
];
|
|
24564
|
+
}
|
|
24565
|
+
if (code.startsWith("SCENE_LINT_")) {
|
|
24566
|
+
return [
|
|
24567
|
+
commandReviewAction(`vibe scene repair ${projectDir} --json`, {
|
|
24568
|
+
label: "Repair deterministic scene lint issues",
|
|
24569
|
+
reason: "Scene lint reported an issue VibeFrame may be able to repair mechanically.",
|
|
24570
|
+
sourceIssueCodes
|
|
24571
|
+
})
|
|
24572
|
+
];
|
|
24573
|
+
}
|
|
24574
|
+
if (code === "RENDER_NOT_FOUND" || code === "EMPTY_RENDER") {
|
|
24575
|
+
return [
|
|
24576
|
+
commandReviewAction(
|
|
24577
|
+
beat ? `vibe render ${projectDir} --beat ${beat} --json` : `vibe render ${projectDir} --json`,
|
|
24578
|
+
{
|
|
24579
|
+
label: beat ? `Render beat ${beat}` : "Render the project",
|
|
24580
|
+
reason: "A render file is required before render inspection can pass.",
|
|
24581
|
+
sourceIssueCodes
|
|
24582
|
+
}
|
|
24583
|
+
)
|
|
24584
|
+
];
|
|
24585
|
+
}
|
|
24586
|
+
if (code === "NO_AUDIO_STREAM" || code === "DURATION_DRIFT") {
|
|
24587
|
+
return [
|
|
24588
|
+
commandReviewAction(`vibe build ${projectDir}${beatFlag} --stage sync --json`, {
|
|
24589
|
+
label: beat ? `Sync timing/audio for beat ${beat}` : "Sync timing and audio wiring",
|
|
24590
|
+
reason: "The render output no longer matches synced project state.",
|
|
24591
|
+
sourceIssueCodes
|
|
24592
|
+
}),
|
|
24593
|
+
commandReviewAction(
|
|
24594
|
+
beat ? `vibe render ${projectDir} --beat ${beat} --json` : `vibe render ${projectDir} --json`,
|
|
24595
|
+
{
|
|
24596
|
+
label: beat ? `Rerender beat ${beat}` : "Rerender the project",
|
|
24597
|
+
reason: "The render should be regenerated after sync repair.",
|
|
24598
|
+
sourceIssueCodes
|
|
24599
|
+
}
|
|
24600
|
+
)
|
|
24601
|
+
];
|
|
24602
|
+
}
|
|
24603
|
+
if (code === "BLACK_FRAME_SEGMENT") {
|
|
24604
|
+
return issue.fixOwner === "host-agent" ? [
|
|
24605
|
+
agentReviewAction({
|
|
24606
|
+
label: beat ? `Fix black frames in beat ${beat}` : "Fix black frame segment",
|
|
24607
|
+
agentPrompt: "Fix black-frame issues from review-report.json, then rerender.",
|
|
24608
|
+
reason: "The issue likely needs scene, storyboard, or visual cue changes.",
|
|
24609
|
+
sourceIssueCodes
|
|
24610
|
+
})
|
|
24611
|
+
] : [
|
|
24612
|
+
commandReviewAction(`vibe scene repair ${projectDir} --json`, {
|
|
24613
|
+
label: "Repair deterministic scene timing",
|
|
24614
|
+
reason: "Black frames outside a specific beat may be recoverable with scene repair.",
|
|
24615
|
+
sourceIssueCodes
|
|
24616
|
+
})
|
|
24617
|
+
];
|
|
24618
|
+
}
|
|
24619
|
+
if (code === "STATIC_FRAME_SEGMENT") {
|
|
24620
|
+
return [
|
|
24621
|
+
agentReviewAction({
|
|
24622
|
+
label: beat ? `Add motion to beat ${beat}` : "Fix static visual hold",
|
|
24623
|
+
agentPrompt: "Fix static-frame issues from review-report.json, then rerender.",
|
|
24624
|
+
reason: "Static segments usually need creative scene, storyboard, or asset changes.",
|
|
24625
|
+
sourceIssueCodes
|
|
24626
|
+
})
|
|
24627
|
+
];
|
|
24628
|
+
}
|
|
24629
|
+
if (code === "LONG_SILENCE") {
|
|
24630
|
+
return issue.fixOwner === "host-agent" ? [
|
|
24631
|
+
agentReviewAction({
|
|
24632
|
+
label: beat ? `Fix long silence in beat ${beat}` : "Fix long silence",
|
|
24633
|
+
agentPrompt: "Fix long-silence issues from review-report.json, then rerender.",
|
|
24634
|
+
reason: "The beat duration, narration, or music cue needs host-agent judgment.",
|
|
24635
|
+
sourceIssueCodes
|
|
24636
|
+
})
|
|
24637
|
+
] : [
|
|
24638
|
+
commandReviewAction(`vibe build ${projectDir}${beatFlag} --stage sync --json`, {
|
|
24639
|
+
label: beat ? `Sync audio for beat ${beat}` : "Sync audio wiring",
|
|
24640
|
+
reason: "The silence may be caused by stale narration or music wiring.",
|
|
24641
|
+
sourceIssueCodes
|
|
24642
|
+
})
|
|
24643
|
+
];
|
|
24644
|
+
}
|
|
24645
|
+
if (code.startsWith("AI_REVIEW_")) {
|
|
24646
|
+
return [
|
|
24647
|
+
agentReviewAction({
|
|
24648
|
+
label: "Fix AI review findings",
|
|
24649
|
+
agentPrompt: "Fix host-agent-owned AI review issues from review-report.json, then rerender.",
|
|
24650
|
+
reason: "AI review findings require storyboard, design, or composition judgment.",
|
|
24651
|
+
sourceIssueCodes
|
|
24652
|
+
})
|
|
24653
|
+
];
|
|
24654
|
+
}
|
|
24655
|
+
if (code === "FFPROBE_UNAVAILABLE" || code === "FFMPEG_UNAVAILABLE") {
|
|
24656
|
+
return [
|
|
24657
|
+
manualReviewAction({
|
|
24658
|
+
label: "Install FFmpeg and rerun inspection",
|
|
24659
|
+
reason: "Local media inspection depends on ffmpeg/ffprobe being available.",
|
|
24660
|
+
fixOwner: "host-agent",
|
|
24661
|
+
sourceIssueCodes
|
|
24662
|
+
})
|
|
24663
|
+
];
|
|
24664
|
+
}
|
|
24665
|
+
if (code === "FFPROBE_FAILED" || code === "NO_VIDEO_STREAM") {
|
|
24666
|
+
return [
|
|
24667
|
+
commandReviewAction(
|
|
24668
|
+
beat ? `vibe render ${projectDir} --beat ${beat} --json` : `vibe render ${projectDir} --json`,
|
|
24669
|
+
{
|
|
24670
|
+
label: beat ? `Rerender beat ${beat}` : "Rerender the project",
|
|
24671
|
+
reason: "The rendered media could not be probed as a valid video.",
|
|
24672
|
+
sourceIssueCodes
|
|
24673
|
+
}
|
|
24674
|
+
)
|
|
24675
|
+
];
|
|
24676
|
+
}
|
|
24677
|
+
if (code === "ASPECT_MISMATCH") {
|
|
24678
|
+
return [
|
|
24679
|
+
manualReviewAction({
|
|
24680
|
+
label: "Check project aspect and render settings",
|
|
24681
|
+
reason: "Aspect mismatches can come from either config intent or render settings.",
|
|
24682
|
+
fixOwner: issue.fixOwner,
|
|
24683
|
+
sourceIssueCodes
|
|
24684
|
+
})
|
|
24685
|
+
];
|
|
24686
|
+
}
|
|
24687
|
+
return [];
|
|
24688
|
+
}
|
|
24689
|
+
function classifyReviewCommand(command3) {
|
|
24690
|
+
const lower = command3.trim().toLowerCase();
|
|
24691
|
+
if (lower.startsWith("vibe status ")) return safe("free");
|
|
24692
|
+
if (lower.startsWith("vibe scene repair")) return safe("free");
|
|
24693
|
+
if (lower.startsWith("vibe storyboard validate") || lower.startsWith("vibe storyboard get") || lower.startsWith("vibe storyboard list")) {
|
|
24694
|
+
return safe("free", "host-agent");
|
|
24695
|
+
}
|
|
24696
|
+
if (lower.startsWith("vibe inspect project")) return safe("free");
|
|
24697
|
+
if (lower.startsWith("vibe inspect render")) {
|
|
24698
|
+
if (lower.includes("--ai")) return unsafe("low");
|
|
24699
|
+
return safe("free");
|
|
24700
|
+
}
|
|
24701
|
+
if (lower.startsWith("vibe render ")) return safe("free");
|
|
24702
|
+
if (lower.startsWith("vibe build ")) {
|
|
24703
|
+
if (lower.includes("--dry-run")) return safe("free");
|
|
24704
|
+
if (lower.includes("--stage sync") || lower.includes("--stage render")) return safe("free");
|
|
24705
|
+
return unsafe("unknown");
|
|
24706
|
+
}
|
|
24707
|
+
if (lower.startsWith("vibe generate video") || lower.startsWith("vibe edit fill-gaps") || lower.startsWith("vibe remix ")) {
|
|
24708
|
+
return unsafe("very-high");
|
|
24709
|
+
}
|
|
24710
|
+
if (lower.startsWith("vibe storyboard revise")) return unsafe("unknown", "host-agent");
|
|
24711
|
+
return unsafe("unknown");
|
|
24712
|
+
}
|
|
24713
|
+
function safe(costTier, fixOwner = "vibe") {
|
|
24714
|
+
return { fixOwner, costTier, safeToAutoRun: true, requiresConfirmation: false };
|
|
24715
|
+
}
|
|
24716
|
+
function unsafe(costTier, fixOwner = "vibe") {
|
|
24717
|
+
return { fixOwner, costTier, safeToAutoRun: false, requiresConfirmation: true };
|
|
24718
|
+
}
|
|
24719
|
+
function actionId(kind3, value) {
|
|
24720
|
+
const slug = value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 80);
|
|
24721
|
+
return `${kind3}:${slug || "action"}`;
|
|
24722
|
+
}
|
|
24723
|
+
function uniqueStrings(items) {
|
|
24724
|
+
return [
|
|
24725
|
+
...new Set(items.filter((item) => typeof item === "string" && item.length > 0))
|
|
24726
|
+
];
|
|
24727
|
+
}
|
|
24728
|
+
var init_review_report = __esm({
|
|
24729
|
+
"../cli/src/commands/_shared/review-report.ts"() {
|
|
24730
|
+
"use strict";
|
|
24731
|
+
}
|
|
24732
|
+
});
|
|
24733
|
+
|
|
24222
24734
|
// ../cli/src/commands/_shared/storyboard-parse.ts
|
|
24735
|
+
function resolveCharacters(frontmatter) {
|
|
24736
|
+
const pool = frontmatter?.characters;
|
|
24737
|
+
if (!pool || typeof pool !== "object") return [];
|
|
24738
|
+
const resolved = [];
|
|
24739
|
+
for (const [name, spec] of Object.entries(pool)) {
|
|
24740
|
+
if (typeof spec === "string") {
|
|
24741
|
+
const prompt3 = spec.trim();
|
|
24742
|
+
if (prompt3) resolved.push({ name, prompt: prompt3 });
|
|
24743
|
+
continue;
|
|
24744
|
+
}
|
|
24745
|
+
if (spec && typeof spec === "object") {
|
|
24746
|
+
const image = typeof spec.image === "string" ? spec.image.trim() : "";
|
|
24747
|
+
if (image) {
|
|
24748
|
+
resolved.push({ name, imagePath: image });
|
|
24749
|
+
continue;
|
|
24750
|
+
}
|
|
24751
|
+
const description = typeof spec.description === "string" ? spec.description.trim() : "";
|
|
24752
|
+
if (description) resolved.push({ name, prompt: description });
|
|
24753
|
+
}
|
|
24754
|
+
}
|
|
24755
|
+
return resolved;
|
|
24756
|
+
}
|
|
24757
|
+
function beatCharacterNames(cues) {
|
|
24758
|
+
const raw2 = cues?.characters;
|
|
24759
|
+
if (typeof raw2 === "string") {
|
|
24760
|
+
const name = raw2.trim();
|
|
24761
|
+
return name ? [name] : [];
|
|
24762
|
+
}
|
|
24763
|
+
if (Array.isArray(raw2)) {
|
|
24764
|
+
return raw2.filter((v2) => typeof v2 === "string" && v2.trim().length > 0).map((v2) => v2.trim());
|
|
24765
|
+
}
|
|
24766
|
+
return [];
|
|
24767
|
+
}
|
|
24223
24768
|
function parseStoryboard(md) {
|
|
24224
24769
|
const normalized = md.replace(/\r\n/g, "\n");
|
|
24225
24770
|
const { frontmatter, remaining } = extractProjectFrontmatter(normalized);
|
|
@@ -24332,28 +24877,28 @@ var init_storyboard_parse = __esm({
|
|
|
24332
24877
|
// ../cli/src/commands/_shared/status-jobs.ts
|
|
24333
24878
|
import { createHash as createHash2, randomUUID as randomUUID2 } from "node:crypto";
|
|
24334
24879
|
import { existsSync as existsSync2, statSync } from "node:fs";
|
|
24335
|
-
import { copyFile, mkdir as mkdir3, readFile as readFile4, readdir, stat, writeFile as
|
|
24336
|
-
import { dirname as dirname3, join as
|
|
24880
|
+
import { copyFile, mkdir as mkdir3, readFile as readFile4, readdir, stat, writeFile as writeFile7 } from "node:fs/promises";
|
|
24881
|
+
import { dirname as dirname3, join as join3, parse as parse2, relative, resolve as resolve6 } from "node:path";
|
|
24337
24882
|
function isLocalJob(record) {
|
|
24338
24883
|
return record.jobType === "build" || record.jobType === "render";
|
|
24339
24884
|
}
|
|
24340
24885
|
function findProjectRoot(start = process.cwd()) {
|
|
24341
|
-
let dir =
|
|
24886
|
+
let dir = resolve6(start);
|
|
24342
24887
|
try {
|
|
24343
24888
|
if (existsSync2(dir) && statSync(dir).isFile()) dir = dirname3(dir);
|
|
24344
24889
|
} catch {
|
|
24345
24890
|
}
|
|
24346
24891
|
for (; ; ) {
|
|
24347
|
-
if (existsSync2(
|
|
24892
|
+
if (existsSync2(join3(dir, "vibe.config.json")) || existsSync2(join3(dir, "STORYBOARD.md"))) {
|
|
24348
24893
|
return dir;
|
|
24349
24894
|
}
|
|
24350
24895
|
const parent = dirname3(dir);
|
|
24351
|
-
if (parent === dir) return
|
|
24896
|
+
if (parent === dir) return resolve6(start);
|
|
24352
24897
|
dir = parent;
|
|
24353
24898
|
}
|
|
24354
24899
|
}
|
|
24355
24900
|
function jobsDir(projectDir) {
|
|
24356
|
-
return
|
|
24901
|
+
return join3(resolve6(projectDir), ".vibeframe", "jobs");
|
|
24357
24902
|
}
|
|
24358
24903
|
function normalizeJobStatus(status) {
|
|
24359
24904
|
const value = String(status ?? "").toLowerCase();
|
|
@@ -24367,10 +24912,10 @@ function normalizeJobStatus(status) {
|
|
|
24367
24912
|
}
|
|
24368
24913
|
function createJobRecord(opts) {
|
|
24369
24914
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
24370
|
-
const projectDir =
|
|
24915
|
+
const projectDir = resolve6(
|
|
24371
24916
|
opts.projectDir ?? findProjectRoot(opts.workingDirectory ?? process.cwd())
|
|
24372
24917
|
);
|
|
24373
|
-
const workingDirectory =
|
|
24918
|
+
const workingDirectory = resolve6(opts.workingDirectory ?? process.cwd());
|
|
24374
24919
|
const id = opts.id ?? makeJobId(opts.providerTaskId, now);
|
|
24375
24920
|
const base = {
|
|
24376
24921
|
schemaVersion: "1",
|
|
@@ -24405,7 +24950,7 @@ function createJobRecord(opts) {
|
|
|
24405
24950
|
message: opts.message
|
|
24406
24951
|
};
|
|
24407
24952
|
base.retryWith = retryWithForJob(base);
|
|
24408
|
-
return
|
|
24953
|
+
return stripUndefined2(base);
|
|
24409
24954
|
}
|
|
24410
24955
|
async function createAndWriteJobRecord(opts) {
|
|
24411
24956
|
const record = createJobRecord(opts);
|
|
@@ -24415,15 +24960,15 @@ async function createAndWriteJobRecord(opts) {
|
|
|
24415
24960
|
async function writeJobRecord(record) {
|
|
24416
24961
|
const dir = jobsDir(record.projectDir);
|
|
24417
24962
|
await mkdir3(dir, { recursive: true });
|
|
24418
|
-
await
|
|
24963
|
+
await writeFile7(
|
|
24419
24964
|
jobRecordPath(record.id, record.projectDir),
|
|
24420
|
-
JSON.stringify(
|
|
24965
|
+
JSON.stringify(stripUndefined2(record), null, 2) + "\n",
|
|
24421
24966
|
"utf-8"
|
|
24422
24967
|
);
|
|
24423
24968
|
}
|
|
24424
24969
|
async function readJobRecord(jobId, projectDir) {
|
|
24425
24970
|
const id = normalizeJobId(jobId);
|
|
24426
|
-
const project =
|
|
24971
|
+
const project = resolve6(projectDir ?? findProjectRoot());
|
|
24427
24972
|
const path14 = jobRecordPath(id, project);
|
|
24428
24973
|
if (!existsSync2(path14)) return null;
|
|
24429
24974
|
return parseJobRecord(await readFile4(path14, "utf-8"));
|
|
@@ -24436,7 +24981,7 @@ async function listJobRecords(projectDir) {
|
|
|
24436
24981
|
for (const entry of entries2) {
|
|
24437
24982
|
if (!entry.isFile() || !entry.name.endsWith(".json")) continue;
|
|
24438
24983
|
try {
|
|
24439
|
-
const parsed = parseJobRecord(await readFile4(
|
|
24984
|
+
const parsed = parseJobRecord(await readFile4(join3(dir, entry.name), "utf-8"));
|
|
24440
24985
|
if (parsed) records.push(parsed);
|
|
24441
24986
|
} catch {
|
|
24442
24987
|
}
|
|
@@ -24530,9 +25075,9 @@ async function refreshLocalJobRecord(record, opts) {
|
|
|
24530
25075
|
const heartbeatAge = record.heartbeatAt ? Date.now() - new Date(record.heartbeatAt).getTime() : Number.POSITIVE_INFINITY;
|
|
24531
25076
|
const orphaned = !isPidAlive(record.pid) || heartbeatAge > LOCAL_JOB_ORPHAN_AFTER_MS;
|
|
24532
25077
|
if (orphaned) {
|
|
24533
|
-
const hint = `The process that ran this ${record.jobType} job is gone. Check ${
|
|
25078
|
+
const hint = `The process that ran this ${record.jobType} job is gone. Check ${join3(record.projectDir, record.jobType === "render" ? "render-report.json" : "build-report.json")} \u2014 the work may have completed before the process exited.`;
|
|
24534
25079
|
warnings.push(hint);
|
|
24535
|
-
updated =
|
|
25080
|
+
updated = stripUndefined2({
|
|
24536
25081
|
...record,
|
|
24537
25082
|
status: "unknown",
|
|
24538
25083
|
error: record.error ?? hint,
|
|
@@ -24549,7 +25094,7 @@ async function refreshLocalJobRecord(record, opts) {
|
|
|
24549
25094
|
});
|
|
24550
25095
|
}
|
|
24551
25096
|
async function inspectProjectStatus(projectDirArg, opts = {}) {
|
|
24552
|
-
const project =
|
|
25097
|
+
const project = resolve6(projectDirArg);
|
|
24553
25098
|
const warnings = [];
|
|
24554
25099
|
let records = await listJobRecords(project);
|
|
24555
25100
|
if (opts.refresh) {
|
|
@@ -24579,6 +25124,10 @@ async function inspectProjectStatus(projectDirArg, opts = {}) {
|
|
|
24579
25124
|
...review?.retryWith ?? [],
|
|
24580
25125
|
...workflow.retryWith
|
|
24581
25126
|
];
|
|
25127
|
+
const nextActions = normalizeReviewActions([
|
|
25128
|
+
...review?.nextActions ?? [],
|
|
25129
|
+
...reviewActionsFromRetryWith([...build?.retryWith ?? [], ...workflow.retryWith])
|
|
25130
|
+
]);
|
|
24582
25131
|
return {
|
|
24583
25132
|
schemaVersion: "1",
|
|
24584
25133
|
kind: "project",
|
|
@@ -24590,11 +25139,12 @@ async function inspectProjectStatus(projectDirArg, opts = {}) {
|
|
|
24590
25139
|
review,
|
|
24591
25140
|
jobs,
|
|
24592
25141
|
warnings,
|
|
25142
|
+
nextActions,
|
|
24593
25143
|
retryWith: unique(retryWith)
|
|
24594
25144
|
};
|
|
24595
25145
|
}
|
|
24596
25146
|
function summarizeJob(record) {
|
|
24597
|
-
return
|
|
25147
|
+
return stripUndefined2({
|
|
24598
25148
|
id: record.id,
|
|
24599
25149
|
jobType: record.jobType,
|
|
24600
25150
|
status: record.status,
|
|
@@ -24618,7 +25168,7 @@ function retryWithForJob(record) {
|
|
|
24618
25168
|
]);
|
|
24619
25169
|
}
|
|
24620
25170
|
function makeJobStatusResult(record, opts) {
|
|
24621
|
-
return
|
|
25171
|
+
return stripUndefined2({
|
|
24622
25172
|
schemaVersion: "1",
|
|
24623
25173
|
kind: "job",
|
|
24624
25174
|
id: record.id,
|
|
@@ -24642,7 +25192,7 @@ function jobProgress(record) {
|
|
|
24642
25192
|
if (record.status === "completed" || record.status === "failed" || record.status === "cancelled") {
|
|
24643
25193
|
if (record.progress === void 0 && !record.providerStatus) return void 0;
|
|
24644
25194
|
}
|
|
24645
|
-
return
|
|
25195
|
+
return stripUndefined2({
|
|
24646
25196
|
percent: record.progress,
|
|
24647
25197
|
phase: record.stage ?? record.providerStatus ?? statusPhase(record.status),
|
|
24648
25198
|
providerStatus: record.providerStatus ?? record.message
|
|
@@ -24652,7 +25202,7 @@ function jobResult(record) {
|
|
|
24652
25202
|
if (!record.resultUrl && !record.outputPath && !record.cachePath && !record.error && !record.resultPayload) {
|
|
24653
25203
|
return null;
|
|
24654
25204
|
}
|
|
24655
|
-
return
|
|
25205
|
+
return stripUndefined2({
|
|
24656
25206
|
url: record.resultUrl,
|
|
24657
25207
|
outputPath: record.outputPath,
|
|
24658
25208
|
cachePath: record.cachePath,
|
|
@@ -24688,7 +25238,7 @@ function normalizeJobId(jobId) {
|
|
|
24688
25238
|
return id;
|
|
24689
25239
|
}
|
|
24690
25240
|
function jobRecordPath(jobId, projectDir) {
|
|
24691
|
-
return
|
|
25241
|
+
return join3(jobsDir(projectDir), `${normalizeJobId(jobId)}.json`);
|
|
24692
25242
|
}
|
|
24693
25243
|
function parseJobRecord(raw2) {
|
|
24694
25244
|
const parsed = JSON.parse(raw2);
|
|
@@ -24713,11 +25263,11 @@ function updateRecordFromProvider(record, result) {
|
|
|
24713
25263
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
24714
25264
|
};
|
|
24715
25265
|
next.retryWith = retryWithForJob(next);
|
|
24716
|
-
return
|
|
25266
|
+
return stripUndefined2(next);
|
|
24717
25267
|
}
|
|
24718
25268
|
function resolveRefreshOutput(record, opts) {
|
|
24719
|
-
if (opts.output) return
|
|
24720
|
-
return record.outputPath ?
|
|
25269
|
+
if (opts.output) return resolve6(opts.workingDirectory ?? process.cwd(), opts.output);
|
|
25270
|
+
return record.outputPath ? resolve6(record.outputPath) : void 0;
|
|
24721
25271
|
}
|
|
24722
25272
|
function liveSupport(record) {
|
|
24723
25273
|
if (record.jobType === "generate-video" && (record.provider === "grok" || record.provider === "runway" || record.provider === "kling" || record.provider === "veo")) {
|
|
@@ -24742,7 +25292,7 @@ async function downloadUrl(url, outputPath) {
|
|
|
24742
25292
|
if (!response.ok) throw new Error(`Download failed: HTTP ${response.status}`);
|
|
24743
25293
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
24744
25294
|
await mkdir3(dirname3(outputPath), { recursive: true });
|
|
24745
|
-
await
|
|
25295
|
+
await writeFile7(outputPath, buffer);
|
|
24746
25296
|
return outputPath;
|
|
24747
25297
|
}
|
|
24748
25298
|
async function maybeCacheOutput(record) {
|
|
@@ -24774,7 +25324,7 @@ async function maybeWriteCompletedAssetMetadata(record) {
|
|
|
24774
25324
|
}
|
|
24775
25325
|
}
|
|
24776
25326
|
async function refreshBuildReportFromJobs(projectDir, records) {
|
|
24777
|
-
const reportPath =
|
|
25327
|
+
const reportPath = join3(projectDir, "build-report.json");
|
|
24778
25328
|
const report = await readJson(reportPath);
|
|
24779
25329
|
if (!report || !Array.isArray(report.beats)) return;
|
|
24780
25330
|
let changed = false;
|
|
@@ -24802,7 +25352,7 @@ async function refreshBuildReportFromJobs(projectDir, records) {
|
|
|
24802
25352
|
if (kind3 === "music" && record.assetOptions && typeof record.assetOptions.duration === "number") {
|
|
24803
25353
|
nested.durationSec = record.assetOptions.duration;
|
|
24804
25354
|
}
|
|
24805
|
-
beatRecord[kind3] =
|
|
25355
|
+
beatRecord[kind3] = stripUndefined2(nested);
|
|
24806
25356
|
beatRecord[`${kind3}Path`] = outputPath;
|
|
24807
25357
|
beatRecord[`${kind3}Status`] = "generated";
|
|
24808
25358
|
beatRecord[`${kind3}JobId`] = record.id;
|
|
@@ -24822,17 +25372,17 @@ async function refreshBuildReportFromJobs(projectDir, records) {
|
|
|
24822
25372
|
}
|
|
24823
25373
|
if (!changed) return;
|
|
24824
25374
|
try {
|
|
24825
|
-
await
|
|
25375
|
+
await writeFile7(reportPath, JSON.stringify(stripUndefined2(report), null, 2) + "\n", "utf-8");
|
|
24826
25376
|
} catch {
|
|
24827
25377
|
}
|
|
24828
25378
|
}
|
|
24829
25379
|
async function readBuildSummary(projectDir) {
|
|
24830
|
-
const reportPath =
|
|
25380
|
+
const reportPath = join3(projectDir, "build-report.json");
|
|
24831
25381
|
const report = await readJson(reportPath);
|
|
24832
25382
|
if (!report) return null;
|
|
24833
25383
|
const info = await statOrNull(reportPath);
|
|
24834
25384
|
const beatSummary = projectBeatReadinessFromUnknown(report.beatSummary);
|
|
24835
|
-
return
|
|
25385
|
+
return stripUndefined2({
|
|
24836
25386
|
reportPath,
|
|
24837
25387
|
kind: typeof report.kind === "string" ? report.kind : void 0,
|
|
24838
25388
|
success: typeof report.success === "boolean" ? report.success : void 0,
|
|
@@ -24850,7 +25400,7 @@ async function readBuildSummary(projectDir) {
|
|
|
24850
25400
|
});
|
|
24851
25401
|
}
|
|
24852
25402
|
async function readReviewSummary(projectDir) {
|
|
24853
|
-
const reportPath =
|
|
25403
|
+
const reportPath = join3(projectDir, "review-report.json");
|
|
24854
25404
|
const report = await readJson(reportPath);
|
|
24855
25405
|
if (!report) return null;
|
|
24856
25406
|
const info = await statOrNull(reportPath);
|
|
@@ -24858,7 +25408,7 @@ async function readReviewSummary(projectDir) {
|
|
|
24858
25408
|
const summary = report.summary && typeof report.summary === "object" ? report.summary : {};
|
|
24859
25409
|
const fixOwners = summary.fixOwners && typeof summary.fixOwners === "object" ? summary.fixOwners : {};
|
|
24860
25410
|
const computedFixOwners = countIssueFixOwners(issues);
|
|
24861
|
-
return
|
|
25411
|
+
return stripUndefined2({
|
|
24862
25412
|
reportPath,
|
|
24863
25413
|
kind: typeof report.kind === "string" ? report.kind : void 0,
|
|
24864
25414
|
mode: typeof report.mode === "string" ? report.mode : void 0,
|
|
@@ -24883,9 +25433,44 @@ async function readReviewSummary(projectDir) {
|
|
|
24883
25433
|
},
|
|
24884
25434
|
sourceReports: stringArray(report.sourceReports),
|
|
24885
25435
|
updatedAt: info?.mtime.toISOString(),
|
|
25436
|
+
nextActions: reviewActionsFromUnknown(report.nextActions),
|
|
24886
25437
|
retryWith: stringArray(report.retryWith)
|
|
24887
25438
|
});
|
|
24888
25439
|
}
|
|
25440
|
+
function reviewActionsFromUnknown(value) {
|
|
25441
|
+
if (!Array.isArray(value)) return [];
|
|
25442
|
+
return value.flatMap((item) => {
|
|
25443
|
+
if (!item || typeof item !== "object") return [];
|
|
25444
|
+
const record = item;
|
|
25445
|
+
const kind3 = stringEnum(record.kind, ["command", "agent", "manual"]);
|
|
25446
|
+
const fixOwner = stringEnum(record.fixOwner, ["vibe", "host-agent"]);
|
|
25447
|
+
const costTier = stringEnum(record.costTier, [
|
|
25448
|
+
"free",
|
|
25449
|
+
"low",
|
|
25450
|
+
"high",
|
|
25451
|
+
"very-high",
|
|
25452
|
+
"unknown"
|
|
25453
|
+
]);
|
|
25454
|
+
if (!kind3 || !fixOwner || !costTier || typeof record.id !== "string" || typeof record.label !== "string" || typeof record.safeToAutoRun !== "boolean" || typeof record.requiresConfirmation !== "boolean" || typeof record.reason !== "string") {
|
|
25455
|
+
return [];
|
|
25456
|
+
}
|
|
25457
|
+
return [
|
|
25458
|
+
stripUndefined2({
|
|
25459
|
+
id: record.id,
|
|
25460
|
+
kind: kind3,
|
|
25461
|
+
label: record.label,
|
|
25462
|
+
command: typeof record.command === "string" ? record.command : void 0,
|
|
25463
|
+
agentPrompt: typeof record.agentPrompt === "string" ? record.agentPrompt : void 0,
|
|
25464
|
+
fixOwner,
|
|
25465
|
+
costTier,
|
|
25466
|
+
safeToAutoRun: record.safeToAutoRun,
|
|
25467
|
+
requiresConfirmation: record.requiresConfirmation,
|
|
25468
|
+
reason: record.reason,
|
|
25469
|
+
sourceIssueCodes: stringArray(record.sourceIssueCodes)
|
|
25470
|
+
})
|
|
25471
|
+
];
|
|
25472
|
+
});
|
|
25473
|
+
}
|
|
24889
25474
|
function summarizeJobs(records) {
|
|
24890
25475
|
return {
|
|
24891
25476
|
total: records.length,
|
|
@@ -24904,7 +25489,7 @@ async function readProjectBeatReadiness(projectDir, build, records) {
|
|
|
24904
25489
|
if (fromBeats) return fromBeats;
|
|
24905
25490
|
if (build.beats) return augmentBeatReadinessFromJobs(build.beats, records, report?.jobs);
|
|
24906
25491
|
}
|
|
24907
|
-
const storyboardPath =
|
|
25492
|
+
const storyboardPath = join3(projectDir, "STORYBOARD.md");
|
|
24908
25493
|
if (!existsSync2(storyboardPath)) {
|
|
24909
25494
|
return { total: 0, assetsReady: 0, compositionsReady: 0, needsAuthor: [] };
|
|
24910
25495
|
}
|
|
@@ -24913,7 +25498,7 @@ async function readProjectBeatReadiness(projectDir, build, records) {
|
|
|
24913
25498
|
const needsAuthor = [];
|
|
24914
25499
|
let compositionsReady = 0;
|
|
24915
25500
|
for (const beat of parsed.beats) {
|
|
24916
|
-
if (existsSync2(
|
|
25501
|
+
if (existsSync2(join3(projectDir, "compositions", `scene-${beat.id}.html`))) {
|
|
24917
25502
|
compositionsReady += 1;
|
|
24918
25503
|
} else {
|
|
24919
25504
|
needsAuthor.push(beat.id);
|
|
@@ -24931,7 +25516,7 @@ async function readProjectBeatReadiness(projectDir, build, records) {
|
|
|
24931
25516
|
}
|
|
24932
25517
|
function deriveProjectWorkflow(opts) {
|
|
24933
25518
|
const retryWith = [];
|
|
24934
|
-
const hasStoryboard = existsSync2(
|
|
25519
|
+
const hasStoryboard = existsSync2(join3(opts.project, "STORYBOARD.md"));
|
|
24935
25520
|
if (!hasStoryboard && !opts.build) {
|
|
24936
25521
|
retryWith.push(`vibe init ${opts.project} --from "<brief>" --json`);
|
|
24937
25522
|
return { status: "empty", currentStage: "init", retryWith };
|
|
@@ -25027,7 +25612,7 @@ function beatReadinessFromBuildBeats(projectDir, beats, records = [], reportJobs
|
|
|
25027
25612
|
if (buildBeatAssetsReady(record) || (id ? buildBeatJobsReady(id, records, reportJobs) : false))
|
|
25028
25613
|
assetsReady += 1;
|
|
25029
25614
|
const compositionPath = typeof record.compositionPath === "string" ? record.compositionPath : id ? `compositions/scene-${id}.html` : void 0;
|
|
25030
|
-
if (compositionPath && existsSync2(
|
|
25615
|
+
if (compositionPath && existsSync2(resolve6(projectDir, compositionPath))) {
|
|
25031
25616
|
compositionsReady += 1;
|
|
25032
25617
|
} else if (id) {
|
|
25033
25618
|
needsAuthor.push(id);
|
|
@@ -25097,6 +25682,9 @@ function numberOr(fallback2, value) {
|
|
|
25097
25682
|
function stringArray(value) {
|
|
25098
25683
|
return Array.isArray(value) ? value.filter((item) => typeof item === "string" && item.length > 0) : [];
|
|
25099
25684
|
}
|
|
25685
|
+
function stringEnum(value, allowed) {
|
|
25686
|
+
return typeof value === "string" && allowed.includes(value) ? value : void 0;
|
|
25687
|
+
}
|
|
25100
25688
|
function isActiveStatus(status) {
|
|
25101
25689
|
return status === "queued" || status === "running";
|
|
25102
25690
|
}
|
|
@@ -25126,7 +25714,7 @@ function assetKindForJob(record) {
|
|
|
25126
25714
|
return void 0;
|
|
25127
25715
|
}
|
|
25128
25716
|
function projectRelativePath(projectDir, path14) {
|
|
25129
|
-
const rel = relative(
|
|
25717
|
+
const rel = relative(resolve6(projectDir), resolve6(path14));
|
|
25130
25718
|
if (!rel || rel.startsWith("..")) return path14;
|
|
25131
25719
|
return rel.replace(/\\/g, "/");
|
|
25132
25720
|
}
|
|
@@ -25144,7 +25732,7 @@ async function statOrNull(path14) {
|
|
|
25144
25732
|
return null;
|
|
25145
25733
|
}
|
|
25146
25734
|
}
|
|
25147
|
-
function
|
|
25735
|
+
function stripUndefined2(value) {
|
|
25148
25736
|
return Object.fromEntries(Object.entries(value).filter(([, v2]) => v2 !== void 0));
|
|
25149
25737
|
}
|
|
25150
25738
|
function unique(items) {
|
|
@@ -25162,6 +25750,7 @@ var init_status_jobs = __esm({
|
|
|
25162
25750
|
init_ai_video();
|
|
25163
25751
|
init_music_status();
|
|
25164
25752
|
init_build_asset_metadata();
|
|
25753
|
+
init_review_report();
|
|
25165
25754
|
init_storyboard_parse();
|
|
25166
25755
|
LOCAL_JOB_ORPHAN_AFTER_MS = 9e4;
|
|
25167
25756
|
}
|
|
@@ -25170,7 +25759,7 @@ var init_status_jobs = __esm({
|
|
|
25170
25759
|
// ../cli/src/commands/_shared/project-config.ts
|
|
25171
25760
|
import { existsSync as existsSync3 } from "node:fs";
|
|
25172
25761
|
import { readFile as readFile5 } from "node:fs/promises";
|
|
25173
|
-
import { resolve as
|
|
25762
|
+
import { resolve as resolve7 } from "node:path";
|
|
25174
25763
|
function defaultProjectConfig(opts) {
|
|
25175
25764
|
return {
|
|
25176
25765
|
schemaVersion: "1",
|
|
@@ -25221,9 +25810,9 @@ function projectConfigJson(opts) {
|
|
|
25221
25810
|
return JSON.stringify(defaultProjectConfig(opts), null, 2) + "\n";
|
|
25222
25811
|
}
|
|
25223
25812
|
async function readProjectConfig(projectDir) {
|
|
25224
|
-
const dir =
|
|
25225
|
-
const canonicalPath =
|
|
25226
|
-
const legacyPath =
|
|
25813
|
+
const dir = resolve7(projectDir);
|
|
25814
|
+
const canonicalPath = resolve7(dir, VIBE_CONFIG_FILENAME);
|
|
25815
|
+
const legacyPath = resolve7(dir, LEGACY_VIBE_PROJECT_FILENAME);
|
|
25227
25816
|
if (existsSync3(canonicalPath)) {
|
|
25228
25817
|
try {
|
|
25229
25818
|
const raw2 = await readFile5(canonicalPath, "utf-8");
|
|
@@ -25286,8 +25875,8 @@ var init_project_config = __esm({
|
|
|
25286
25875
|
});
|
|
25287
25876
|
|
|
25288
25877
|
// ../cli/src/commands/_shared/scene-project.ts
|
|
25289
|
-
import { mkdir as mkdir4, readFile as readFile6, writeFile as
|
|
25290
|
-
import { resolve as
|
|
25878
|
+
import { mkdir as mkdir4, readFile as readFile6, writeFile as writeFile8, access as access3 } from "node:fs/promises";
|
|
25879
|
+
import { resolve as resolve8, basename as basename2 } from "node:path";
|
|
25291
25880
|
function aspectToDims(aspect) {
|
|
25292
25881
|
return ASPECT_DIMS[aspect];
|
|
25293
25882
|
}
|
|
@@ -25585,6 +26174,43 @@ vibe host setup all --write # write project/app config
|
|
|
25585
26174
|
vibe host doctor all --json # verify readiness
|
|
25586
26175
|
\`\`\`
|
|
25587
26176
|
|
|
26177
|
+
## Native host goal loop
|
|
26178
|
+
|
|
26179
|
+
For long-running work, use Codex Goal mode, Claude Code \`/goal\`, or the
|
|
26180
|
+
host's equivalent as the outer loop. VibeFrame should not run a competing
|
|
26181
|
+
project-level goal loop; it provides \`--json\` commands, dry runs, cost caps,
|
|
26182
|
+
\`build-report.json\`, \`review-report.json\`, \`nextActions\`, \`safeToAutoRun\`,
|
|
26183
|
+
\`requiresConfirmation\`, \`fixOwner\`, deterministic repair, and render
|
|
26184
|
+
inspection for the host agent to reason over.
|
|
26185
|
+
|
|
26186
|
+
Copy-paste examples:
|
|
26187
|
+
|
|
26188
|
+
\`\`\`text
|
|
26189
|
+
/goal Build this VibeFrame project into renders/final.mp4. Use --json for every
|
|
26190
|
+
vibe command, run --dry-run before paid operations, use --max-cost 5 for builds
|
|
26191
|
+
unless the user sets another budget, read build-report.json and
|
|
26192
|
+
review-report.json before deciding the next action, prefer nextActions before
|
|
26193
|
+
guessing, run only safeToAutoRun:true actions automatically, and ask before
|
|
26194
|
+
requiresConfirmation:true actions. Treat retryWith as the compatibility
|
|
26195
|
+
fallback, fixOwner:"vibe" as CLI repair work, and fixOwner:"host-agent" as
|
|
26196
|
+
STORYBOARD.md, DESIGN.md, or composition edits.
|
|
26197
|
+
Stop only when renders/final.mp4 exists, duration and aspect ratio match the
|
|
26198
|
+
brief, inspect render --cheap has no errors, any AI review score is >= 90 when AI review is requested, and every
|
|
26199
|
+
remaining host-agent issue is fixed, accepted with rationale, or reported as
|
|
26200
|
+
blocked.
|
|
26201
|
+
\`\`\`
|
|
26202
|
+
|
|
26203
|
+
\`\`\`text
|
|
26204
|
+
/goal Finish this VibeFrame render using Claude Code goal mode as the outer
|
|
26205
|
+
loop. Use vibe context/schema when unsure, --json everywhere, dry-run before
|
|
26206
|
+
paid operations, budget cap via --max-cost 5, nextActions before guessing,
|
|
26207
|
+
build-report.json/review-report.json as loop state, and safeToAutoRun,
|
|
26208
|
+
requiresConfirmation, and fixOwner to decide between vibe scene repair and
|
|
26209
|
+
host-agent edits. Stop only after final MP4,
|
|
26210
|
+
target duration/aspect ratio, clean render inspection, any AI review score >= 90 when AI review is requested, and
|
|
26211
|
+
no unresolved unacknowledged host-agent issues.
|
|
26212
|
+
\`\`\`
|
|
26213
|
+
|
|
25588
26214
|
## Skills \u2014 USE THESE FIRST
|
|
25589
26215
|
|
|
25590
26216
|
@SKILL.md
|
|
@@ -25688,35 +26314,35 @@ tmp/
|
|
|
25688
26314
|
`;
|
|
25689
26315
|
}
|
|
25690
26316
|
function describeSceneScaffold(opts) {
|
|
25691
|
-
const dir =
|
|
26317
|
+
const dir = resolve8(opts.dir);
|
|
25692
26318
|
const profile = opts.profile ?? "full";
|
|
25693
26319
|
const groups = {
|
|
25694
26320
|
authoring: [
|
|
25695
|
-
|
|
25696
|
-
|
|
25697
|
-
|
|
25698
|
-
|
|
25699
|
-
|
|
26321
|
+
resolve8(dir, "STORYBOARD.md"),
|
|
26322
|
+
resolve8(dir, "DESIGN.md"),
|
|
26323
|
+
resolve8(dir, VIBE_CONFIG_FILENAME),
|
|
26324
|
+
resolve8(dir, "vibe.project.yaml"),
|
|
26325
|
+
resolve8(dir, ".gitignore")
|
|
25700
26326
|
],
|
|
25701
26327
|
render: [],
|
|
25702
26328
|
agent: []
|
|
25703
26329
|
};
|
|
25704
26330
|
if (profile === "full") {
|
|
25705
26331
|
groups.render = [
|
|
25706
|
-
|
|
25707
|
-
|
|
25708
|
-
|
|
25709
|
-
|
|
25710
|
-
|
|
25711
|
-
|
|
26332
|
+
resolve8(dir, "index.html"),
|
|
26333
|
+
resolve8(dir, "compositions"),
|
|
26334
|
+
resolve8(dir, "assets"),
|
|
26335
|
+
resolve8(dir, "renders"),
|
|
26336
|
+
resolve8(dir, "hyperframes.json"),
|
|
26337
|
+
resolve8(dir, "meta.json")
|
|
25712
26338
|
];
|
|
25713
26339
|
}
|
|
25714
26340
|
if (profile === "agent" || profile === "full") {
|
|
25715
26341
|
groups.agent = [
|
|
25716
|
-
|
|
25717
|
-
|
|
25718
|
-
|
|
25719
|
-
|
|
26342
|
+
resolve8(dir, "AGENTS.md"),
|
|
26343
|
+
resolve8(dir, "SKILL.md"),
|
|
26344
|
+
resolve8(dir, "references"),
|
|
26345
|
+
resolve8(dir, "CLAUDE.md")
|
|
25720
26346
|
];
|
|
25721
26347
|
}
|
|
25722
26348
|
return groups;
|
|
@@ -25730,7 +26356,7 @@ async function pathExists(p2) {
|
|
|
25730
26356
|
}
|
|
25731
26357
|
}
|
|
25732
26358
|
async function scaffoldSceneProject(opts) {
|
|
25733
|
-
const dir =
|
|
26359
|
+
const dir = resolve8(opts.dir);
|
|
25734
26360
|
const name = opts.name ?? basename2(dir);
|
|
25735
26361
|
const aspect = opts.aspect ?? "16:9";
|
|
25736
26362
|
const duration = opts.duration ?? 10;
|
|
@@ -25738,103 +26364,103 @@ async function scaffoldSceneProject(opts) {
|
|
|
25738
26364
|
const profile = opts.profile ?? "full";
|
|
25739
26365
|
await mkdir4(dir, { recursive: true });
|
|
25740
26366
|
if (profile === "full") {
|
|
25741
|
-
await mkdir4(
|
|
25742
|
-
await mkdir4(
|
|
25743
|
-
await mkdir4(
|
|
26367
|
+
await mkdir4(resolve8(dir, "compositions"), { recursive: true });
|
|
26368
|
+
await mkdir4(resolve8(dir, "assets"), { recursive: true });
|
|
26369
|
+
await mkdir4(resolve8(dir, "renders"), { recursive: true });
|
|
25744
26370
|
}
|
|
25745
26371
|
const created = [];
|
|
25746
26372
|
const skipped2 = [];
|
|
25747
26373
|
const merged = [];
|
|
25748
26374
|
if (profile === "full") {
|
|
25749
|
-
const hfPath =
|
|
26375
|
+
const hfPath = resolve8(dir, "hyperframes.json");
|
|
25750
26376
|
const hfDefaults = buildHyperframesConfig();
|
|
25751
26377
|
if (await pathExists(hfPath)) {
|
|
25752
26378
|
const existingRaw = await readFile6(hfPath, "utf-8");
|
|
25753
26379
|
const existing = JSON.parse(existingRaw);
|
|
25754
26380
|
const mergedConfig = mergeHyperframesConfig(existing, hfDefaults);
|
|
25755
|
-
await
|
|
26381
|
+
await writeFile8(hfPath, JSON.stringify(mergedConfig, null, 2) + "\n", "utf-8");
|
|
25756
26382
|
merged.push(hfPath);
|
|
25757
26383
|
} else {
|
|
25758
|
-
await
|
|
26384
|
+
await writeFile8(hfPath, JSON.stringify(hfDefaults, null, 2) + "\n", "utf-8");
|
|
25759
26385
|
created.push(hfPath);
|
|
25760
26386
|
}
|
|
25761
|
-
const metaPath =
|
|
26387
|
+
const metaPath = resolve8(dir, "meta.json");
|
|
25762
26388
|
if (await pathExists(metaPath)) {
|
|
25763
26389
|
skipped2.push(metaPath);
|
|
25764
26390
|
} else {
|
|
25765
|
-
await
|
|
26391
|
+
await writeFile8(
|
|
25766
26392
|
metaPath,
|
|
25767
26393
|
JSON.stringify(buildHyperframesMeta(name, now), null, 2) + "\n",
|
|
25768
26394
|
"utf-8"
|
|
25769
26395
|
);
|
|
25770
26396
|
created.push(metaPath);
|
|
25771
26397
|
}
|
|
25772
|
-
const rootPath =
|
|
26398
|
+
const rootPath = resolve8(dir, "index.html");
|
|
25773
26399
|
if (await pathExists(rootPath)) {
|
|
25774
26400
|
skipped2.push(rootPath);
|
|
25775
26401
|
} else {
|
|
25776
|
-
await
|
|
26402
|
+
await writeFile8(rootPath, buildEmptyRootHtml({ aspect, duration }), "utf-8");
|
|
25777
26403
|
created.push(rootPath);
|
|
25778
26404
|
}
|
|
25779
26405
|
}
|
|
25780
|
-
const vibeConfigJsonPath =
|
|
26406
|
+
const vibeConfigJsonPath = resolve8(dir, VIBE_CONFIG_FILENAME);
|
|
25781
26407
|
if (await pathExists(vibeConfigJsonPath)) {
|
|
25782
26408
|
skipped2.push(vibeConfigJsonPath);
|
|
25783
26409
|
} else {
|
|
25784
|
-
await
|
|
26410
|
+
await writeFile8(vibeConfigJsonPath, projectConfigJson({ name, aspect }), "utf-8");
|
|
25785
26411
|
created.push(vibeConfigJsonPath);
|
|
25786
26412
|
}
|
|
25787
|
-
const vibePath =
|
|
26413
|
+
const vibePath = resolve8(dir, "vibe.project.yaml");
|
|
25788
26414
|
if (await pathExists(vibePath)) {
|
|
25789
26415
|
skipped2.push(vibePath);
|
|
25790
26416
|
} else {
|
|
25791
26417
|
const cfg = { ...defaultVibeProjectConfig(name), aspect };
|
|
25792
|
-
await
|
|
26418
|
+
await writeFile8(vibePath, (0, import_yaml4.stringify)(cfg), "utf-8");
|
|
25793
26419
|
created.push(vibePath);
|
|
25794
26420
|
}
|
|
25795
26421
|
if (profile === "agent" || profile === "full") {
|
|
25796
|
-
const agentsPath =
|
|
26422
|
+
const agentsPath = resolve8(dir, "AGENTS.md");
|
|
25797
26423
|
if (await pathExists(agentsPath)) {
|
|
25798
26424
|
skipped2.push(agentsPath);
|
|
25799
26425
|
} else {
|
|
25800
|
-
await
|
|
26426
|
+
await writeFile8(agentsPath, buildProjectAgentsMd(name), "utf-8");
|
|
25801
26427
|
created.push(agentsPath);
|
|
25802
26428
|
}
|
|
25803
|
-
const claudePath =
|
|
26429
|
+
const claudePath = resolve8(dir, "CLAUDE.md");
|
|
25804
26430
|
if (await pathExists(claudePath)) {
|
|
25805
26431
|
const existing = await readFile6(claudePath, "utf-8");
|
|
25806
26432
|
if (existing.includes("@AGENTS.md")) {
|
|
25807
26433
|
skipped2.push(claudePath);
|
|
25808
26434
|
} else {
|
|
25809
|
-
await
|
|
26435
|
+
await writeFile8(claudePath, `@AGENTS.md
|
|
25810
26436
|
|
|
25811
26437
|
${existing}`, "utf-8");
|
|
25812
26438
|
merged.push(claudePath);
|
|
25813
26439
|
}
|
|
25814
26440
|
} else {
|
|
25815
|
-
await
|
|
26441
|
+
await writeFile8(claudePath, buildProjectClaudeMd(name), "utf-8");
|
|
25816
26442
|
created.push(claudePath);
|
|
25817
26443
|
}
|
|
25818
26444
|
}
|
|
25819
|
-
const designPath =
|
|
26445
|
+
const designPath = resolve8(dir, "DESIGN.md");
|
|
25820
26446
|
if (await pathExists(designPath)) {
|
|
25821
26447
|
skipped2.push(designPath);
|
|
25822
26448
|
} else {
|
|
25823
|
-
await
|
|
26449
|
+
await writeFile8(designPath, buildDesignMd({ name, style: opts.visualStyle }), "utf-8");
|
|
25824
26450
|
created.push(designPath);
|
|
25825
26451
|
}
|
|
25826
|
-
const storyboardPath =
|
|
26452
|
+
const storyboardPath = resolve8(dir, "STORYBOARD.md");
|
|
25827
26453
|
if (await pathExists(storyboardPath)) {
|
|
25828
26454
|
skipped2.push(storyboardPath);
|
|
25829
26455
|
} else {
|
|
25830
|
-
await
|
|
26456
|
+
await writeFile8(storyboardPath, buildStoryboardMd(name, duration), "utf-8");
|
|
25831
26457
|
created.push(storyboardPath);
|
|
25832
26458
|
}
|
|
25833
|
-
const gitignorePath =
|
|
26459
|
+
const gitignorePath = resolve8(dir, ".gitignore");
|
|
25834
26460
|
if (await pathExists(gitignorePath)) {
|
|
25835
26461
|
skipped2.push(gitignorePath);
|
|
25836
26462
|
} else {
|
|
25837
|
-
await
|
|
26463
|
+
await writeFile8(gitignorePath, buildSceneGitignore(), "utf-8");
|
|
25838
26464
|
created.push(gitignorePath);
|
|
25839
26465
|
}
|
|
25840
26466
|
return { created, skipped: skipped2, merged, groups: describeSceneScaffold({ dir, profile }) };
|
|
@@ -33084,7 +33710,7 @@ var require_util = __commonJS({
|
|
|
33084
33710
|
return path14;
|
|
33085
33711
|
});
|
|
33086
33712
|
exports.normalize = normalize3;
|
|
33087
|
-
function
|
|
33713
|
+
function join44(aRoot, aPath) {
|
|
33088
33714
|
if (aRoot === "") {
|
|
33089
33715
|
aRoot = ".";
|
|
33090
33716
|
}
|
|
@@ -33116,7 +33742,7 @@ var require_util = __commonJS({
|
|
|
33116
33742
|
}
|
|
33117
33743
|
return joined;
|
|
33118
33744
|
}
|
|
33119
|
-
exports.join =
|
|
33745
|
+
exports.join = join44;
|
|
33120
33746
|
exports.isAbsolute = function(aPath) {
|
|
33121
33747
|
return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
|
|
33122
33748
|
};
|
|
@@ -33330,7 +33956,7 @@ var require_util = __commonJS({
|
|
|
33330
33956
|
parsed.path = parsed.path.substring(0, index + 1);
|
|
33331
33957
|
}
|
|
33332
33958
|
}
|
|
33333
|
-
sourceURL =
|
|
33959
|
+
sourceURL = join44(urlGenerate(parsed), sourceURL);
|
|
33334
33960
|
}
|
|
33335
33961
|
return normalize3(sourceURL);
|
|
33336
33962
|
}
|
|
@@ -34770,8 +35396,8 @@ var require_source_map = __commonJS({
|
|
|
34770
35396
|
var require_previous_map = __commonJS({
|
|
34771
35397
|
"../../node_modules/.pnpm/postcss@8.5.6/node_modules/postcss/lib/previous-map.js"(exports, module) {
|
|
34772
35398
|
"use strict";
|
|
34773
|
-
var { existsSync: existsSync67, readFileSync:
|
|
34774
|
-
var { dirname: dirname33, join:
|
|
35399
|
+
var { existsSync: existsSync67, readFileSync: readFileSync13 } = __require("fs");
|
|
35400
|
+
var { dirname: dirname33, join: join44 } = __require("path");
|
|
34775
35401
|
var { SourceMapConsumer, SourceMapGenerator } = require_source_map();
|
|
34776
35402
|
function fromBase64(str2) {
|
|
34777
35403
|
if (Buffer) {
|
|
@@ -34835,7 +35461,7 @@ var require_previous_map = __commonJS({
|
|
|
34835
35461
|
this.root = dirname33(path14);
|
|
34836
35462
|
if (existsSync67(path14)) {
|
|
34837
35463
|
this.mapFile = path14;
|
|
34838
|
-
return
|
|
35464
|
+
return readFileSync13(path14, "utf-8").toString().trim();
|
|
34839
35465
|
}
|
|
34840
35466
|
}
|
|
34841
35467
|
loadMap(file, prev) {
|
|
@@ -34869,7 +35495,7 @@ var require_previous_map = __commonJS({
|
|
|
34869
35495
|
return this.decodeInline(this.annotation);
|
|
34870
35496
|
} else if (this.annotation) {
|
|
34871
35497
|
let map3 = this.annotation;
|
|
34872
|
-
if (file) map3 =
|
|
35498
|
+
if (file) map3 = join44(dirname33(file), map3);
|
|
34873
35499
|
return this.loadFile(map3);
|
|
34874
35500
|
}
|
|
34875
35501
|
}
|
|
@@ -82324,14 +82950,14 @@ var require_re = __commonJS({
|
|
|
82324
82950
|
return value;
|
|
82325
82951
|
};
|
|
82326
82952
|
var createToken = (name, value, isGlobal) => {
|
|
82327
|
-
const
|
|
82953
|
+
const safe2 = makeSafeRegex(value);
|
|
82328
82954
|
const index = R2++;
|
|
82329
82955
|
debug9(name, index, value);
|
|
82330
82956
|
t2[name] = index;
|
|
82331
82957
|
src[index] = value;
|
|
82332
|
-
safeSrc[index] =
|
|
82958
|
+
safeSrc[index] = safe2;
|
|
82333
82959
|
re2[index] = new RegExp(value, isGlobal ? "g" : void 0);
|
|
82334
|
-
safeRe[index] = new RegExp(
|
|
82960
|
+
safeRe[index] = new RegExp(safe2, isGlobal ? "g" : void 0);
|
|
82335
82961
|
};
|
|
82336
82962
|
createToken("NUMERICIDENTIFIER", "0|[1-9]\\d*");
|
|
82337
82963
|
createToken("NUMERICIDENTIFIERLOOSE", "\\d+");
|
|
@@ -93498,7 +94124,7 @@ var require_util3 = __commonJS({
|
|
|
93498
94124
|
return path14;
|
|
93499
94125
|
}
|
|
93500
94126
|
exports.normalize = normalize3;
|
|
93501
|
-
function
|
|
94127
|
+
function join44(aRoot, aPath) {
|
|
93502
94128
|
if (aRoot === "") {
|
|
93503
94129
|
aRoot = ".";
|
|
93504
94130
|
}
|
|
@@ -93530,7 +94156,7 @@ var require_util3 = __commonJS({
|
|
|
93530
94156
|
}
|
|
93531
94157
|
return joined;
|
|
93532
94158
|
}
|
|
93533
|
-
exports.join =
|
|
94159
|
+
exports.join = join44;
|
|
93534
94160
|
exports.isAbsolute = function(aPath) {
|
|
93535
94161
|
return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
|
|
93536
94162
|
};
|
|
@@ -93703,7 +94329,7 @@ var require_util3 = __commonJS({
|
|
|
93703
94329
|
parsed.path = parsed.path.substring(0, index + 1);
|
|
93704
94330
|
}
|
|
93705
94331
|
}
|
|
93706
|
-
sourceURL =
|
|
94332
|
+
sourceURL = join44(urlGenerate(parsed), sourceURL);
|
|
93707
94333
|
}
|
|
93708
94334
|
return normalize3(sourceURL);
|
|
93709
94335
|
}
|
|
@@ -95505,7 +96131,7 @@ var require_escodegen = __commonJS({
|
|
|
95505
96131
|
function noEmptySpace() {
|
|
95506
96132
|
return space ? space : " ";
|
|
95507
96133
|
}
|
|
95508
|
-
function
|
|
96134
|
+
function join44(left3, right3) {
|
|
95509
96135
|
var leftSource, rightSource, leftCharCode, rightCharCode;
|
|
95510
96136
|
leftSource = toSourceNodeWhenNeeded(left3).toString();
|
|
95511
96137
|
if (leftSource.length === 0) {
|
|
@@ -95836,8 +96462,8 @@ var require_escodegen = __commonJS({
|
|
|
95836
96462
|
} else {
|
|
95837
96463
|
result.push(that.generateExpression(stmt.left, Precedence.Call, E_TTT));
|
|
95838
96464
|
}
|
|
95839
|
-
result =
|
|
95840
|
-
result = [
|
|
96465
|
+
result = join44(result, operator);
|
|
96466
|
+
result = [join44(
|
|
95841
96467
|
result,
|
|
95842
96468
|
that.generateExpression(stmt.right, Precedence.Assignment, E_TTT)
|
|
95843
96469
|
), ")"];
|
|
@@ -95980,11 +96606,11 @@ var require_escodegen = __commonJS({
|
|
|
95980
96606
|
var result, fragment;
|
|
95981
96607
|
result = ["class"];
|
|
95982
96608
|
if (stmt.id) {
|
|
95983
|
-
result =
|
|
96609
|
+
result = join44(result, this.generateExpression(stmt.id, Precedence.Sequence, E_TTT));
|
|
95984
96610
|
}
|
|
95985
96611
|
if (stmt.superClass) {
|
|
95986
|
-
fragment =
|
|
95987
|
-
result =
|
|
96612
|
+
fragment = join44("extends", this.generateExpression(stmt.superClass, Precedence.Unary, E_TTT));
|
|
96613
|
+
result = join44(result, fragment);
|
|
95988
96614
|
}
|
|
95989
96615
|
result.push(space);
|
|
95990
96616
|
result.push(this.generateStatement(stmt.body, S_TFFT));
|
|
@@ -95997,9 +96623,9 @@ var require_escodegen = __commonJS({
|
|
|
95997
96623
|
return escapeDirective(stmt.directive) + this.semicolon(flags);
|
|
95998
96624
|
},
|
|
95999
96625
|
DoWhileStatement: function(stmt, flags) {
|
|
96000
|
-
var result =
|
|
96626
|
+
var result = join44("do", this.maybeBlock(stmt.body, S_TFFF));
|
|
96001
96627
|
result = this.maybeBlockSuffix(stmt.body, result);
|
|
96002
|
-
return
|
|
96628
|
+
return join44(result, [
|
|
96003
96629
|
"while" + space + "(",
|
|
96004
96630
|
this.generateExpression(stmt.test, Precedence.Sequence, E_TTT),
|
|
96005
96631
|
")" + this.semicolon(flags)
|
|
@@ -96035,11 +96661,11 @@ var require_escodegen = __commonJS({
|
|
|
96035
96661
|
ExportDefaultDeclaration: function(stmt, flags) {
|
|
96036
96662
|
var result = ["export"], bodyFlags;
|
|
96037
96663
|
bodyFlags = flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF;
|
|
96038
|
-
result =
|
|
96664
|
+
result = join44(result, "default");
|
|
96039
96665
|
if (isStatement(stmt.declaration)) {
|
|
96040
|
-
result =
|
|
96666
|
+
result = join44(result, this.generateStatement(stmt.declaration, bodyFlags));
|
|
96041
96667
|
} else {
|
|
96042
|
-
result =
|
|
96668
|
+
result = join44(result, this.generateExpression(stmt.declaration, Precedence.Assignment, E_TTT) + this.semicolon(flags));
|
|
96043
96669
|
}
|
|
96044
96670
|
return result;
|
|
96045
96671
|
},
|
|
@@ -96047,15 +96673,15 @@ var require_escodegen = __commonJS({
|
|
|
96047
96673
|
var result = ["export"], bodyFlags, that = this;
|
|
96048
96674
|
bodyFlags = flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF;
|
|
96049
96675
|
if (stmt.declaration) {
|
|
96050
|
-
return
|
|
96676
|
+
return join44(result, this.generateStatement(stmt.declaration, bodyFlags));
|
|
96051
96677
|
}
|
|
96052
96678
|
if (stmt.specifiers) {
|
|
96053
96679
|
if (stmt.specifiers.length === 0) {
|
|
96054
|
-
result =
|
|
96680
|
+
result = join44(result, "{" + space + "}");
|
|
96055
96681
|
} else if (stmt.specifiers[0].type === Syntax.ExportBatchSpecifier) {
|
|
96056
|
-
result =
|
|
96682
|
+
result = join44(result, this.generateExpression(stmt.specifiers[0], Precedence.Sequence, E_TTT));
|
|
96057
96683
|
} else {
|
|
96058
|
-
result =
|
|
96684
|
+
result = join44(result, "{");
|
|
96059
96685
|
withIndent(function(indent2) {
|
|
96060
96686
|
var i2, iz;
|
|
96061
96687
|
result.push(newline);
|
|
@@ -96073,7 +96699,7 @@ var require_escodegen = __commonJS({
|
|
|
96073
96699
|
result.push(base + "}");
|
|
96074
96700
|
}
|
|
96075
96701
|
if (stmt.source) {
|
|
96076
|
-
result =
|
|
96702
|
+
result = join44(result, [
|
|
96077
96703
|
"from" + space,
|
|
96078
96704
|
// ModuleSpecifier
|
|
96079
96705
|
this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),
|
|
@@ -96161,7 +96787,7 @@ var require_escodegen = __commonJS({
|
|
|
96161
96787
|
];
|
|
96162
96788
|
cursor = 0;
|
|
96163
96789
|
if (stmt.specifiers[cursor].type === Syntax.ImportDefaultSpecifier) {
|
|
96164
|
-
result =
|
|
96790
|
+
result = join44(result, [
|
|
96165
96791
|
this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT)
|
|
96166
96792
|
]);
|
|
96167
96793
|
++cursor;
|
|
@@ -96171,7 +96797,7 @@ var require_escodegen = __commonJS({
|
|
|
96171
96797
|
result.push(",");
|
|
96172
96798
|
}
|
|
96173
96799
|
if (stmt.specifiers[cursor].type === Syntax.ImportNamespaceSpecifier) {
|
|
96174
|
-
result =
|
|
96800
|
+
result = join44(result, [
|
|
96175
96801
|
space,
|
|
96176
96802
|
this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT)
|
|
96177
96803
|
]);
|
|
@@ -96200,7 +96826,7 @@ var require_escodegen = __commonJS({
|
|
|
96200
96826
|
}
|
|
96201
96827
|
}
|
|
96202
96828
|
}
|
|
96203
|
-
result =
|
|
96829
|
+
result = join44(result, [
|
|
96204
96830
|
"from" + space,
|
|
96205
96831
|
// ModuleSpecifier
|
|
96206
96832
|
this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),
|
|
@@ -96254,7 +96880,7 @@ var require_escodegen = __commonJS({
|
|
|
96254
96880
|
return result;
|
|
96255
96881
|
},
|
|
96256
96882
|
ThrowStatement: function(stmt, flags) {
|
|
96257
|
-
return [
|
|
96883
|
+
return [join44(
|
|
96258
96884
|
"throw",
|
|
96259
96885
|
this.generateExpression(stmt.argument, Precedence.Sequence, E_TTT)
|
|
96260
96886
|
), this.semicolon(flags)];
|
|
@@ -96265,7 +96891,7 @@ var require_escodegen = __commonJS({
|
|
|
96265
96891
|
result = this.maybeBlockSuffix(stmt.block, result);
|
|
96266
96892
|
if (stmt.handlers) {
|
|
96267
96893
|
for (i2 = 0, iz = stmt.handlers.length; i2 < iz; ++i2) {
|
|
96268
|
-
result =
|
|
96894
|
+
result = join44(result, this.generateStatement(stmt.handlers[i2], S_TFFF));
|
|
96269
96895
|
if (stmt.finalizer || i2 + 1 !== iz) {
|
|
96270
96896
|
result = this.maybeBlockSuffix(stmt.handlers[i2].body, result);
|
|
96271
96897
|
}
|
|
@@ -96273,7 +96899,7 @@ var require_escodegen = __commonJS({
|
|
|
96273
96899
|
} else {
|
|
96274
96900
|
guardedHandlers = stmt.guardedHandlers || [];
|
|
96275
96901
|
for (i2 = 0, iz = guardedHandlers.length; i2 < iz; ++i2) {
|
|
96276
|
-
result =
|
|
96902
|
+
result = join44(result, this.generateStatement(guardedHandlers[i2], S_TFFF));
|
|
96277
96903
|
if (stmt.finalizer || i2 + 1 !== iz) {
|
|
96278
96904
|
result = this.maybeBlockSuffix(guardedHandlers[i2].body, result);
|
|
96279
96905
|
}
|
|
@@ -96281,13 +96907,13 @@ var require_escodegen = __commonJS({
|
|
|
96281
96907
|
if (stmt.handler) {
|
|
96282
96908
|
if (Array.isArray(stmt.handler)) {
|
|
96283
96909
|
for (i2 = 0, iz = stmt.handler.length; i2 < iz; ++i2) {
|
|
96284
|
-
result =
|
|
96910
|
+
result = join44(result, this.generateStatement(stmt.handler[i2], S_TFFF));
|
|
96285
96911
|
if (stmt.finalizer || i2 + 1 !== iz) {
|
|
96286
96912
|
result = this.maybeBlockSuffix(stmt.handler[i2].body, result);
|
|
96287
96913
|
}
|
|
96288
96914
|
}
|
|
96289
96915
|
} else {
|
|
96290
|
-
result =
|
|
96916
|
+
result = join44(result, this.generateStatement(stmt.handler, S_TFFF));
|
|
96291
96917
|
if (stmt.finalizer) {
|
|
96292
96918
|
result = this.maybeBlockSuffix(stmt.handler.body, result);
|
|
96293
96919
|
}
|
|
@@ -96295,7 +96921,7 @@ var require_escodegen = __commonJS({
|
|
|
96295
96921
|
}
|
|
96296
96922
|
}
|
|
96297
96923
|
if (stmt.finalizer) {
|
|
96298
|
-
result =
|
|
96924
|
+
result = join44(result, ["finally", this.maybeBlock(stmt.finalizer, S_TFFF)]);
|
|
96299
96925
|
}
|
|
96300
96926
|
return result;
|
|
96301
96927
|
},
|
|
@@ -96329,7 +96955,7 @@ var require_escodegen = __commonJS({
|
|
|
96329
96955
|
withIndent(function() {
|
|
96330
96956
|
if (stmt.test) {
|
|
96331
96957
|
result = [
|
|
96332
|
-
|
|
96958
|
+
join44("case", that.generateExpression(stmt.test, Precedence.Sequence, E_TTT)),
|
|
96333
96959
|
":"
|
|
96334
96960
|
];
|
|
96335
96961
|
} else {
|
|
@@ -96377,9 +97003,9 @@ var require_escodegen = __commonJS({
|
|
|
96377
97003
|
result.push(this.maybeBlock(stmt.consequent, S_TFFF));
|
|
96378
97004
|
result = this.maybeBlockSuffix(stmt.consequent, result);
|
|
96379
97005
|
if (stmt.alternate.type === Syntax.IfStatement) {
|
|
96380
|
-
result =
|
|
97006
|
+
result = join44(result, ["else ", this.generateStatement(stmt.alternate, bodyFlags)]);
|
|
96381
97007
|
} else {
|
|
96382
|
-
result =
|
|
97008
|
+
result = join44(result, join44("else", this.maybeBlock(stmt.alternate, bodyFlags)));
|
|
96383
97009
|
}
|
|
96384
97010
|
} else {
|
|
96385
97011
|
result.push(this.maybeBlock(stmt.consequent, bodyFlags));
|
|
@@ -96480,7 +97106,7 @@ var require_escodegen = __commonJS({
|
|
|
96480
97106
|
},
|
|
96481
97107
|
ReturnStatement: function(stmt, flags) {
|
|
96482
97108
|
if (stmt.argument) {
|
|
96483
|
-
return [
|
|
97109
|
+
return [join44(
|
|
96484
97110
|
"return",
|
|
96485
97111
|
this.generateExpression(stmt.argument, Precedence.Sequence, E_TTT)
|
|
96486
97112
|
), this.semicolon(flags)];
|
|
@@ -96569,14 +97195,14 @@ var require_escodegen = __commonJS({
|
|
|
96569
97195
|
if (leftSource.charCodeAt(leftSource.length - 1) === 47 && esutils.code.isIdentifierPartES5(expr.operator.charCodeAt(0))) {
|
|
96570
97196
|
result = [fragment, noEmptySpace(), expr.operator];
|
|
96571
97197
|
} else {
|
|
96572
|
-
result =
|
|
97198
|
+
result = join44(fragment, expr.operator);
|
|
96573
97199
|
}
|
|
96574
97200
|
fragment = this.generateExpression(expr.right, rightPrecedence, flags);
|
|
96575
97201
|
if (expr.operator === "/" && fragment.toString().charAt(0) === "/" || expr.operator.slice(-1) === "<" && fragment.toString().slice(0, 3) === "!--") {
|
|
96576
97202
|
result.push(noEmptySpace());
|
|
96577
97203
|
result.push(fragment);
|
|
96578
97204
|
} else {
|
|
96579
|
-
result =
|
|
97205
|
+
result = join44(result, fragment);
|
|
96580
97206
|
}
|
|
96581
97207
|
if (expr.operator === "in" && !(flags & F_ALLOW_IN)) {
|
|
96582
97208
|
return ["(", result, ")"];
|
|
@@ -96616,7 +97242,7 @@ var require_escodegen = __commonJS({
|
|
|
96616
97242
|
var result, length, i2, iz, itemFlags;
|
|
96617
97243
|
length = expr["arguments"].length;
|
|
96618
97244
|
itemFlags = flags & F_ALLOW_UNPARATH_NEW && !parentheses && length === 0 ? E_TFT : E_TFF;
|
|
96619
|
-
result =
|
|
97245
|
+
result = join44(
|
|
96620
97246
|
"new",
|
|
96621
97247
|
this.generateExpression(expr.callee, Precedence.New, itemFlags)
|
|
96622
97248
|
);
|
|
@@ -96666,11 +97292,11 @@ var require_escodegen = __commonJS({
|
|
|
96666
97292
|
var result, fragment, rightCharCode, leftSource, leftCharCode;
|
|
96667
97293
|
fragment = this.generateExpression(expr.argument, Precedence.Unary, E_TTT);
|
|
96668
97294
|
if (space === "") {
|
|
96669
|
-
result =
|
|
97295
|
+
result = join44(expr.operator, fragment);
|
|
96670
97296
|
} else {
|
|
96671
97297
|
result = [expr.operator];
|
|
96672
97298
|
if (expr.operator.length > 2) {
|
|
96673
|
-
result =
|
|
97299
|
+
result = join44(result, fragment);
|
|
96674
97300
|
} else {
|
|
96675
97301
|
leftSource = toSourceNodeWhenNeeded(result).toString();
|
|
96676
97302
|
leftCharCode = leftSource.charCodeAt(leftSource.length - 1);
|
|
@@ -96693,7 +97319,7 @@ var require_escodegen = __commonJS({
|
|
|
96693
97319
|
result = "yield";
|
|
96694
97320
|
}
|
|
96695
97321
|
if (expr.argument) {
|
|
96696
|
-
result =
|
|
97322
|
+
result = join44(
|
|
96697
97323
|
result,
|
|
96698
97324
|
this.generateExpression(expr.argument, Precedence.Yield, E_TTT)
|
|
96699
97325
|
);
|
|
@@ -96701,7 +97327,7 @@ var require_escodegen = __commonJS({
|
|
|
96701
97327
|
return parenthesize(result, Precedence.Yield, precedence);
|
|
96702
97328
|
},
|
|
96703
97329
|
AwaitExpression: function(expr, precedence, flags) {
|
|
96704
|
-
var result =
|
|
97330
|
+
var result = join44(
|
|
96705
97331
|
expr.all ? "await*" : "await",
|
|
96706
97332
|
this.generateExpression(expr.argument, Precedence.Await, E_TTT)
|
|
96707
97333
|
);
|
|
@@ -96784,11 +97410,11 @@ var require_escodegen = __commonJS({
|
|
|
96784
97410
|
var result, fragment;
|
|
96785
97411
|
result = ["class"];
|
|
96786
97412
|
if (expr.id) {
|
|
96787
|
-
result =
|
|
97413
|
+
result = join44(result, this.generateExpression(expr.id, Precedence.Sequence, E_TTT));
|
|
96788
97414
|
}
|
|
96789
97415
|
if (expr.superClass) {
|
|
96790
|
-
fragment =
|
|
96791
|
-
result =
|
|
97416
|
+
fragment = join44("extends", this.generateExpression(expr.superClass, Precedence.Unary, E_TTT));
|
|
97417
|
+
result = join44(result, fragment);
|
|
96792
97418
|
}
|
|
96793
97419
|
result.push(space);
|
|
96794
97420
|
result.push(this.generateStatement(expr.body, S_TFFT));
|
|
@@ -96803,7 +97429,7 @@ var require_escodegen = __commonJS({
|
|
|
96803
97429
|
}
|
|
96804
97430
|
if (expr.kind === "get" || expr.kind === "set") {
|
|
96805
97431
|
fragment = [
|
|
96806
|
-
|
|
97432
|
+
join44(expr.kind, this.generatePropertyKey(expr.key, expr.computed)),
|
|
96807
97433
|
this.generateFunctionBody(expr.value)
|
|
96808
97434
|
];
|
|
96809
97435
|
} else {
|
|
@@ -96813,7 +97439,7 @@ var require_escodegen = __commonJS({
|
|
|
96813
97439
|
this.generateFunctionBody(expr.value)
|
|
96814
97440
|
];
|
|
96815
97441
|
}
|
|
96816
|
-
return
|
|
97442
|
+
return join44(result, fragment);
|
|
96817
97443
|
},
|
|
96818
97444
|
Property: function(expr, precedence, flags) {
|
|
96819
97445
|
if (expr.kind === "get" || expr.kind === "set") {
|
|
@@ -97008,7 +97634,7 @@ var require_escodegen = __commonJS({
|
|
|
97008
97634
|
for (i2 = 0, iz = expr.blocks.length; i2 < iz; ++i2) {
|
|
97009
97635
|
fragment = that.generateExpression(expr.blocks[i2], Precedence.Sequence, E_TTT);
|
|
97010
97636
|
if (i2 > 0 || extra.moz.comprehensionExpressionStartsWithAssignment) {
|
|
97011
|
-
result =
|
|
97637
|
+
result = join44(result, fragment);
|
|
97012
97638
|
} else {
|
|
97013
97639
|
result.push(fragment);
|
|
97014
97640
|
}
|
|
@@ -97016,13 +97642,13 @@ var require_escodegen = __commonJS({
|
|
|
97016
97642
|
});
|
|
97017
97643
|
}
|
|
97018
97644
|
if (expr.filter) {
|
|
97019
|
-
result =
|
|
97645
|
+
result = join44(result, "if" + space);
|
|
97020
97646
|
fragment = this.generateExpression(expr.filter, Precedence.Sequence, E_TTT);
|
|
97021
|
-
result =
|
|
97647
|
+
result = join44(result, ["(", fragment, ")"]);
|
|
97022
97648
|
}
|
|
97023
97649
|
if (!extra.moz.comprehensionExpressionStartsWithAssignment) {
|
|
97024
97650
|
fragment = this.generateExpression(expr.body, Precedence.Assignment, E_TTT);
|
|
97025
|
-
result =
|
|
97651
|
+
result = join44(result, fragment);
|
|
97026
97652
|
}
|
|
97027
97653
|
result.push(expr.type === Syntax.GeneratorExpression ? ")" : "]");
|
|
97028
97654
|
return result;
|
|
@@ -97038,8 +97664,8 @@ var require_escodegen = __commonJS({
|
|
|
97038
97664
|
} else {
|
|
97039
97665
|
fragment = this.generateExpression(expr.left, Precedence.Call, E_TTT);
|
|
97040
97666
|
}
|
|
97041
|
-
fragment =
|
|
97042
|
-
fragment =
|
|
97667
|
+
fragment = join44(fragment, expr.of ? "of" : "in");
|
|
97668
|
+
fragment = join44(fragment, this.generateExpression(expr.right, Precedence.Sequence, E_TTT));
|
|
97043
97669
|
return ["for" + space + "(", fragment, ")"];
|
|
97044
97670
|
},
|
|
97045
97671
|
SpreadElement: function(expr, precedence, flags) {
|
|
@@ -118330,17 +118956,17 @@ var init_cliui = __esm({
|
|
|
118330
118956
|
});
|
|
118331
118957
|
|
|
118332
118958
|
// ../../node_modules/.pnpm/escalade@3.2.0/node_modules/escalade/sync/index.mjs
|
|
118333
|
-
import { dirname as dirname4, resolve as
|
|
118959
|
+
import { dirname as dirname4, resolve as resolve10 } from "path";
|
|
118334
118960
|
import { readdirSync, statSync as statSync2 } from "fs";
|
|
118335
118961
|
function sync_default(start, callback) {
|
|
118336
|
-
let dir =
|
|
118962
|
+
let dir = resolve10(".", start);
|
|
118337
118963
|
let tmp, stats = statSync2(dir);
|
|
118338
118964
|
if (!stats.isDirectory()) {
|
|
118339
118965
|
dir = dirname4(dir);
|
|
118340
118966
|
}
|
|
118341
118967
|
while (true) {
|
|
118342
118968
|
tmp = callback(dir, readdirSync(dir));
|
|
118343
|
-
if (tmp) return
|
|
118969
|
+
if (tmp) return resolve10(dir, tmp);
|
|
118344
118970
|
dir = dirname4(tmp = dir);
|
|
118345
118971
|
if (tmp === dir) break;
|
|
118346
118972
|
}
|
|
@@ -119306,7 +119932,7 @@ var init_yargs_parser = __esm({
|
|
|
119306
119932
|
|
|
119307
119933
|
// ../../node_modules/.pnpm/yargs-parser@21.1.1/node_modules/yargs-parser/build/lib/index.js
|
|
119308
119934
|
import { format } from "util";
|
|
119309
|
-
import { normalize, resolve as
|
|
119935
|
+
import { normalize, resolve as resolve11 } from "path";
|
|
119310
119936
|
import { readFileSync as readFileSync3 } from "fs";
|
|
119311
119937
|
var _a3, _b, _c, minNodeVersion, nodeVersion, env2, parser, yargsParser, lib_default;
|
|
119312
119938
|
var init_lib2 = __esm({
|
|
@@ -119329,7 +119955,7 @@ var init_lib2 = __esm({
|
|
|
119329
119955
|
},
|
|
119330
119956
|
format,
|
|
119331
119957
|
normalize,
|
|
119332
|
-
resolve:
|
|
119958
|
+
resolve: resolve11,
|
|
119333
119959
|
// TODO: figure out a way to combine ESM and CJS coverage, such that
|
|
119334
119960
|
// we can exercise all the lines below:
|
|
119335
119961
|
require: (path14) => {
|
|
@@ -119396,19 +120022,19 @@ var init_yerror = __esm({
|
|
|
119396
120022
|
});
|
|
119397
120023
|
|
|
119398
120024
|
// ../../node_modules/.pnpm/y18n@5.0.8/node_modules/y18n/build/lib/platform-shims/node.js
|
|
119399
|
-
import { readFileSync as readFileSync4, statSync as statSync3, writeFile as
|
|
120025
|
+
import { readFileSync as readFileSync4, statSync as statSync3, writeFile as writeFile9 } from "fs";
|
|
119400
120026
|
import { format as format2 } from "util";
|
|
119401
|
-
import { resolve as
|
|
120027
|
+
import { resolve as resolve12 } from "path";
|
|
119402
120028
|
var node_default;
|
|
119403
120029
|
var init_node = __esm({
|
|
119404
120030
|
"../../node_modules/.pnpm/y18n@5.0.8/node_modules/y18n/build/lib/platform-shims/node.js"() {
|
|
119405
120031
|
node_default = {
|
|
119406
120032
|
fs: {
|
|
119407
120033
|
readFileSync: readFileSync4,
|
|
119408
|
-
writeFile:
|
|
120034
|
+
writeFile: writeFile9
|
|
119409
120035
|
},
|
|
119410
120036
|
format: format2,
|
|
119411
|
-
resolve:
|
|
120037
|
+
resolve: resolve12,
|
|
119412
120038
|
exists: (file) => {
|
|
119413
120039
|
try {
|
|
119414
120040
|
return statSync3(file).isFile();
|
|
@@ -119603,7 +120229,7 @@ import { notStrictEqual, strictEqual } from "assert";
|
|
|
119603
120229
|
import { inspect } from "util";
|
|
119604
120230
|
import { readFileSync as readFileSync5 } from "fs";
|
|
119605
120231
|
import { fileURLToPath } from "url";
|
|
119606
|
-
import { basename as basename3, dirname as dirname5, extname as extname2, relative as relative2, resolve as
|
|
120232
|
+
import { basename as basename3, dirname as dirname5, extname as extname2, relative as relative2, resolve as resolve13 } from "path";
|
|
119607
120233
|
var REQUIRE_ERROR, REQUIRE_DIRECTORY_ERROR, __dirname2, mainFilename, esm_default;
|
|
119608
120234
|
var init_esm2 = __esm({
|
|
119609
120235
|
"../../node_modules/.pnpm/yargs@17.7.2/node_modules/yargs/lib/platform-shims/esm.mjs"() {
|
|
@@ -119644,7 +120270,7 @@ var init_esm2 = __esm({
|
|
|
119644
120270
|
dirname: dirname5,
|
|
119645
120271
|
extname: extname2,
|
|
119646
120272
|
relative: relative2,
|
|
119647
|
-
resolve:
|
|
120273
|
+
resolve: resolve13
|
|
119648
120274
|
},
|
|
119649
120275
|
process: {
|
|
119650
120276
|
argv: () => process.argv,
|
|
@@ -119666,7 +120292,7 @@ var init_esm2 = __esm({
|
|
|
119666
120292
|
return [...str2].length;
|
|
119667
120293
|
},
|
|
119668
120294
|
y18n: y18n_default({
|
|
119669
|
-
directory:
|
|
120295
|
+
directory: resolve13(__dirname2, "../../../locales"),
|
|
119670
120296
|
updateFiles: false
|
|
119671
120297
|
})
|
|
119672
120298
|
};
|
|
@@ -123441,9 +124067,9 @@ async function getConnectionTransport(options) {
|
|
|
123441
124067
|
throw new Error("Could not detect required browser platform");
|
|
123442
124068
|
}
|
|
123443
124069
|
const { convertPuppeteerChannelToBrowsersChannel: convertPuppeteerChannelToBrowsersChannel3 } = await Promise.resolve().then(() => (init_LaunchOptions(), LaunchOptions_exports));
|
|
123444
|
-
const { join:
|
|
124070
|
+
const { join: join44 } = await import("node:path");
|
|
123445
124071
|
const userDataDir = resolveDefaultUserDataDir4(Browser5.CHROME, platform, convertPuppeteerChannelToBrowsersChannel3(options.channel));
|
|
123446
|
-
const portPath =
|
|
124072
|
+
const portPath = join44(userDataDir, "DevToolsActivePort");
|
|
123447
124073
|
try {
|
|
123448
124074
|
const fileContent = await environment.value.fs.promises.readFile(portPath, "ascii");
|
|
123449
124075
|
const [rawPort, rawPath] = fileContent.split("\n").map((line) => {
|
|
@@ -123766,7 +124392,7 @@ var init_PipeTransport = __esm({
|
|
|
123766
124392
|
// ../../node_modules/.pnpm/puppeteer-core@24.41.0/node_modules/puppeteer-core/lib/esm/puppeteer/node/BrowserLauncher.js
|
|
123767
124393
|
import { existsSync as existsSync5 } from "node:fs";
|
|
123768
124394
|
import { tmpdir } from "node:os";
|
|
123769
|
-
import { join as
|
|
124395
|
+
import { join as join5 } from "node:path";
|
|
123770
124396
|
var BrowserLauncher;
|
|
123771
124397
|
var init_BrowserLauncher = __esm({
|
|
123772
124398
|
"../../node_modules/.pnpm/puppeteer-core@24.41.0/node_modules/puppeteer-core/lib/esm/puppeteer/node/BrowserLauncher.js"() {
|
|
@@ -123886,7 +124512,7 @@ var init_BrowserLauncher = __esm({
|
|
|
123886
124512
|
if (logs.includes("Failed to create a ProcessSingleton for your profile directory") || // On Windows we will not get logs due to the singleton process
|
|
123887
124513
|
// handover. See
|
|
123888
124514
|
// https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/process_singleton_win.cc;l=46;drc=fc7952f0422b5073515a205a04ec9c3a1ae81658
|
|
123889
|
-
process.platform === "win32" && existsSync5(
|
|
124515
|
+
process.platform === "win32" && existsSync5(join5(launchArgs.userDataDir, "lockfile"))) {
|
|
123890
124516
|
throw new Error(`The browser is already running for ${launchArgs.userDataDir}. Use a different \`userDataDir\` or stop the running browser first.`);
|
|
123891
124517
|
}
|
|
123892
124518
|
if (logs.includes("Missing X server") && options.headless === false) {
|
|
@@ -124017,7 +124643,7 @@ var init_BrowserLauncher = __esm({
|
|
|
124017
124643
|
* @internal
|
|
124018
124644
|
*/
|
|
124019
124645
|
getProfilePath() {
|
|
124020
|
-
return
|
|
124646
|
+
return join5(this.puppeteer.configuration.temporaryDirectory ?? tmpdir(), `puppeteer_dev_${this.browser}_profile-`);
|
|
124021
124647
|
}
|
|
124022
124648
|
/**
|
|
124023
124649
|
* @internal
|
|
@@ -292672,7 +293298,7 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
|
|
|
292672
293298
|
}
|
|
292673
293299
|
}
|
|
292674
293300
|
return result;
|
|
292675
|
-
function
|
|
293301
|
+
function escapeRegExp5(str2) {
|
|
292676
293302
|
return str2.replace(/[-[\]/{}()*+?.\\^$|]/g, "\\$&");
|
|
292677
293303
|
}
|
|
292678
293304
|
function getTodoCommentsRegExp() {
|
|
@@ -292680,7 +293306,7 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
|
|
|
292680
293306
|
const multiLineCommentStart = /(?:\/\*+\s*)/.source;
|
|
292681
293307
|
const anyNumberOfSpacesAndAsterisksAtStartOfLine = /(?:^(?:\s|\*)*)/.source;
|
|
292682
293308
|
const preamble = "(" + anyNumberOfSpacesAndAsterisksAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")";
|
|
292683
|
-
const literals = "(?:" + map3(descriptors, (d2) => "(" +
|
|
293309
|
+
const literals = "(?:" + map3(descriptors, (d2) => "(" + escapeRegExp5(d2.text) + ")").join("|") + ")";
|
|
292684
293310
|
const endOfLineOrEndOfComment = /(?:$|\*\/)/.source;
|
|
292685
293311
|
const messageRemainder = /(?:.*?)/.source;
|
|
292686
293312
|
const messagePortion = "(" + literals + messageRemainder + ")";
|
|
@@ -340513,7 +341139,7 @@ var require_dist15 = __commonJS({
|
|
|
340513
341139
|
|
|
340514
341140
|
// ../../node_modules/.pnpm/puppeteer@24.41.0_typescript@5.9.3/node_modules/puppeteer/lib/esm/puppeteer/getConfiguration.js
|
|
340515
341141
|
import { homedir as homedir3 } from "node:os";
|
|
340516
|
-
import { join as
|
|
341142
|
+
import { join as join6 } from "node:path";
|
|
340517
341143
|
function getBooleanEnvVar(name) {
|
|
340518
341144
|
const env4 = process.env[name];
|
|
340519
341145
|
if (env4 === void 0) {
|
|
@@ -340593,7 +341219,7 @@ var init_getConfiguration = __esm({
|
|
|
340593
341219
|
configuration2.firefox = getBrowserSetting("firefox", configuration2, {
|
|
340594
341220
|
skipDownload: true
|
|
340595
341221
|
});
|
|
340596
|
-
configuration2.cacheDirectory = process.env["PUPPETEER_CACHE_DIR"] ?? configuration2.cacheDirectory ??
|
|
341222
|
+
configuration2.cacheDirectory = process.env["PUPPETEER_CACHE_DIR"] ?? configuration2.cacheDirectory ?? join6(homedir3(), ".cache", "puppeteer");
|
|
340597
341223
|
configuration2.temporaryDirectory = process.env["PUPPETEER_TMP_DIR"] ?? configuration2.temporaryDirectory;
|
|
340598
341224
|
configuration2.experiments ??= {};
|
|
340599
341225
|
return configuration2;
|
|
@@ -340921,7 +341547,7 @@ import { readdirSync as readdirSync2, statSync as statSync4 } from "fs";
|
|
|
340921
341547
|
import { format as format3 } from "util";
|
|
340922
341548
|
import { normalize as normalize2, resolve as resolve32 } from "path";
|
|
340923
341549
|
import { readFileSync as readFileSync22 } from "fs";
|
|
340924
|
-
import { readFileSync as readFileSync32, statSync as statSync22, writeFile as
|
|
341550
|
+
import { readFileSync as readFileSync32, statSync as statSync22, writeFile as writeFile10 } from "fs";
|
|
340925
341551
|
import { format as format22 } from "util";
|
|
340926
341552
|
import { resolve as resolve42 } from "path";
|
|
340927
341553
|
import { notStrictEqual as notStrictEqual2, strictEqual as strictEqual2 } from "assert";
|
|
@@ -340979,7 +341605,7 @@ import { join as join8 } from "path";
|
|
|
340979
341605
|
import { spawn as spawn7 } from "child_process";
|
|
340980
341606
|
import { createWriteStream as createWriteStream22, existsSync as existsSync7, mkdirSync as mkdirSync4 } from "fs";
|
|
340981
341607
|
import { createHash as createHash3 } from "crypto";
|
|
340982
|
-
import { join as
|
|
341608
|
+
import { join as join72, extname as extname22 } from "path";
|
|
340983
341609
|
import { Readable } from "stream";
|
|
340984
341610
|
import { finished } from "stream/promises";
|
|
340985
341611
|
import { promises as fs72 } from "fs";
|
|
@@ -351067,7 +351693,7 @@ async function downloadToTemp(url, destDir, timeoutMs = 3e5) {
|
|
|
351067
351693
|
mkdirSync4(destDir, { recursive: true });
|
|
351068
351694
|
}
|
|
351069
351695
|
const filename = getFilenameFromUrl(url);
|
|
351070
|
-
const localPath =
|
|
351696
|
+
const localPath = join72(destDir, filename);
|
|
351071
351697
|
if (existsSync7(localPath)) {
|
|
351072
351698
|
downloadPathCache.set(url, localPath);
|
|
351073
351699
|
return localPath;
|
|
@@ -399082,14 +399708,14 @@ ${sourceUrlComment}
|
|
|
399082
399708
|
return value;
|
|
399083
399709
|
};
|
|
399084
399710
|
var createToken = (name, value, isGlobal) => {
|
|
399085
|
-
const
|
|
399711
|
+
const safe2 = makeSafeRegex(value);
|
|
399086
399712
|
const index = R2++;
|
|
399087
399713
|
debug62(name, index, value);
|
|
399088
399714
|
t2[name] = index;
|
|
399089
399715
|
src[index] = value;
|
|
399090
|
-
safeSrc[index] =
|
|
399716
|
+
safeSrc[index] = safe2;
|
|
399091
399717
|
re2[index] = new RegExp(value, isGlobal ? "g" : void 0);
|
|
399092
|
-
safeRe[index] = new RegExp(
|
|
399718
|
+
safeRe[index] = new RegExp(safe2, isGlobal ? "g" : void 0);
|
|
399093
399719
|
};
|
|
399094
399720
|
createToken("NUMERICIDENTIFIER", "0|[1-9]\\d*");
|
|
399095
399721
|
createToken("NUMERICIDENTIFIERLOOSE", "\\d+");
|
|
@@ -433316,7 +433942,7 @@ If you think this is a bug, please report it on the Puppeteer issue tracker.`;
|
|
|
433316
433942
|
node_default2 = {
|
|
433317
433943
|
fs: {
|
|
433318
433944
|
readFileSync: readFileSync32,
|
|
433319
|
-
writeFile:
|
|
433945
|
+
writeFile: writeFile10
|
|
433320
433946
|
},
|
|
433321
433947
|
format: format22,
|
|
433322
433948
|
resolve: resolve42,
|
|
@@ -450239,14 +450865,14 @@ ${right22.raw}`)
|
|
|
450239
450865
|
});
|
|
450240
450866
|
|
|
450241
450867
|
// ../cli/src/commands/_shared/scene-lint.ts
|
|
450242
|
-
import { readdir as readdir4, readFile as readFile7, writeFile as
|
|
450868
|
+
import { readdir as readdir4, readFile as readFile7, writeFile as writeFile11, stat as stat2 } from "node:fs/promises";
|
|
450243
450869
|
import { existsSync as existsSync18 } from "node:fs";
|
|
450244
|
-
import { resolve as
|
|
450870
|
+
import { resolve as resolve15, relative as relative4, join as join18 } from "node:path";
|
|
450245
450871
|
async function discoverSceneFiles(opts) {
|
|
450246
|
-
const projectDir =
|
|
450247
|
-
const rootAbs =
|
|
450872
|
+
const projectDir = resolve15(opts.projectDir);
|
|
450873
|
+
const rootAbs = resolve15(projectDir, opts.rootRel ?? "index.html");
|
|
450248
450874
|
const root2 = existsSync18(rootAbs) ? rootAbs : null;
|
|
450249
|
-
const compsDir =
|
|
450875
|
+
const compsDir = resolve15(projectDir, "compositions");
|
|
450250
450876
|
const subs = [];
|
|
450251
450877
|
if (existsSync18(compsDir)) {
|
|
450252
450878
|
await collectHtmlRecursive(compsDir, subs);
|
|
@@ -450332,7 +450958,7 @@ function addClipClassToTimedElements(html) {
|
|
|
450332
450958
|
});
|
|
450333
450959
|
}
|
|
450334
450960
|
async function runProjectLint(opts) {
|
|
450335
|
-
const projectDir =
|
|
450961
|
+
const projectDir = resolve15(opts.projectDir);
|
|
450336
450962
|
const { root: root2, subs } = await discoverSceneFiles({ projectDir, rootRel: opts.rootRel });
|
|
450337
450963
|
const files = [];
|
|
450338
450964
|
const fixed = [];
|
|
@@ -450356,7 +450982,7 @@ async function runProjectLint(opts) {
|
|
|
450356
450982
|
if (opts.fix && findings.length > 0) {
|
|
450357
450983
|
const { html: nextHtml, fixedCodes } = applyMechanicalFixes(html, findings);
|
|
450358
450984
|
if (fixedCodes.length > 0) {
|
|
450359
|
-
await
|
|
450985
|
+
await writeFile11(abs, nextHtml, "utf-8");
|
|
450360
450986
|
fixed.push({ file: rel, codes: fixedCodes });
|
|
450361
450987
|
const reLinted = runHyperframeLint({ ...prepared, html: nextHtml });
|
|
450362
450988
|
files.push({
|
|
@@ -450393,7 +451019,7 @@ async function runProjectLint(opts) {
|
|
|
450393
451019
|
};
|
|
450394
451020
|
}
|
|
450395
451021
|
async function rootExists(projectDir, rootRel = "index.html") {
|
|
450396
|
-
const abs =
|
|
451022
|
+
const abs = resolve15(projectDir, rootRel);
|
|
450397
451023
|
try {
|
|
450398
451024
|
const s2 = await stat2(abs);
|
|
450399
451025
|
return s2.isFile();
|
|
@@ -469393,12 +470019,12 @@ var init_dist3 = __esm({
|
|
|
469393
470019
|
|
|
469394
470020
|
// ../cli/src/commands/_shared/root-sync.ts
|
|
469395
470021
|
import { existsSync as existsSync23 } from "node:fs";
|
|
469396
|
-
import { readFile as readFile8, writeFile as
|
|
469397
|
-
import { join as join23, resolve as
|
|
470022
|
+
import { readFile as readFile8, writeFile as writeFile13 } from "node:fs/promises";
|
|
470023
|
+
import { join as join23, resolve as resolve17 } from "node:path";
|
|
469398
470024
|
async function createRootSyncPlan(opts) {
|
|
469399
|
-
const projectDir =
|
|
470025
|
+
const projectDir = resolve17(opts.projectDir);
|
|
469400
470026
|
const rootRel = opts.rootRel ?? "index.html";
|
|
469401
|
-
const rootPath =
|
|
470027
|
+
const rootPath = resolve17(projectDir, rootRel);
|
|
469402
470028
|
if (!existsSync23(rootPath)) {
|
|
469403
470029
|
return { rootPath, rootRel, exists: false, changed: false, fixCodes: [], issues: [] };
|
|
469404
470030
|
}
|
|
@@ -469456,11 +470082,11 @@ async function createProjectRootSyncPlan(opts) {
|
|
|
469456
470082
|
}
|
|
469457
470083
|
async function syncRootComposition(opts) {
|
|
469458
470084
|
const plan = await createRootSyncPlan(opts);
|
|
469459
|
-
if (plan.nextHtml) await
|
|
470085
|
+
if (plan.nextHtml) await writeFile13(plan.rootPath, plan.nextHtml, "utf-8");
|
|
469460
470086
|
return plan;
|
|
469461
470087
|
}
|
|
469462
470088
|
async function loadProjectRootSyncBeats(projectDir) {
|
|
469463
|
-
const root2 =
|
|
470089
|
+
const root2 = resolve17(projectDir);
|
|
469464
470090
|
const storyboardPath = join23(root2, "STORYBOARD.md");
|
|
469465
470091
|
if (!existsSync23(storyboardPath)) return [];
|
|
469466
470092
|
const parsed = parseStoryboard(await readFile8(storyboardPath, "utf-8"));
|
|
@@ -469537,7 +470163,7 @@ async function resolveSyncedBeatDuration(opts) {
|
|
|
469537
470163
|
}
|
|
469538
470164
|
}
|
|
469539
470165
|
async function resolveProjectBeatDurations(projectDir) {
|
|
469540
|
-
const root2 =
|
|
470166
|
+
const root2 = resolve17(projectDir);
|
|
469541
470167
|
const beats = await loadProjectRootSyncBeats(root2);
|
|
469542
470168
|
const durations = /* @__PURE__ */ new Map();
|
|
469543
470169
|
for (const beat of beats) {
|
|
@@ -469786,8 +470412,8 @@ __export(compose_scenes_skills_exports, {
|
|
|
469786
470412
|
});
|
|
469787
470413
|
import { createHash as createHash5 } from "node:crypto";
|
|
469788
470414
|
import { existsSync as existsSync24, mkdirSync as mkdirSync12 } from "node:fs";
|
|
469789
|
-
import { mkdir as mkdir9, readFile as readFile9, writeFile as
|
|
469790
|
-
import { dirname as dirname13, join as join24, resolve as
|
|
470415
|
+
import { mkdir as mkdir9, readFile as readFile9, writeFile as writeFile14 } from "node:fs/promises";
|
|
470416
|
+
import { dirname as dirname13, join as join24, resolve as resolve18 } from "node:path";
|
|
469791
470417
|
function buildSystemPrompt(ctx) {
|
|
469792
470418
|
return `You are a Hyperframes composition author. The skill content below
|
|
469793
470419
|
defines the framework rules, motion principles, and quality standards.
|
|
@@ -469880,7 +470506,15 @@ ${finalDurationBullet}
|
|
|
469880
470506
|
itself. For multi-phase beats, drive phase changes with GSAP \`autoAlpha\`
|
|
469881
470507
|
inside full-window clips: animate phase A out (\`autoAlpha: 0\`), then
|
|
469882
470508
|
phase B in, on the same timeline.
|
|
469883
|
-
- If \`assets/
|
|
470509
|
+
- If \`assets/video-${ctx.beat.id}.mp4\` exists, it is an AI-generated clip for
|
|
470510
|
+
this beat \u2014 use it as the FULL-FRAME visual and prefer it over any backdrop
|
|
470511
|
+
image or CSS. Put one full-bleed \`<video>\` inside a full-window \`.clip\`:
|
|
470512
|
+
\`<video src="assets/video-${ctx.beat.id}.mp4" data-start="0" data-duration="${BEAT_DURATION}" data-media-start="0" muted playsinline style="width:100%;height:100%;object-fit:cover"></video>\`
|
|
470513
|
+
Use the exact path (no \`./\` or \`../\`). The framework seeks the clip to each
|
|
470514
|
+
timeline frame, so do NOT add transform tweens to the \`<video>\` or its
|
|
470515
|
+
ancestors; layer text/motion graphics on top instead.
|
|
470516
|
+
- If \`assets/backdrop-${ctx.beat.id}.png\` exists (and no video clip above),
|
|
470517
|
+
use that local file as the
|
|
469884
470518
|
full-frame visual backdrop. The exact path string is
|
|
469885
470519
|
\`assets/backdrop-${ctx.beat.id}.png\`; do NOT prefix it with \`../\` or \`./\`
|
|
469886
470520
|
because fragments are mounted from the project root.
|
|
@@ -470047,7 +470681,7 @@ async function composeBeatHtml(ctx, overrides) {
|
|
|
470047
470681
|
const html = extractHtml(result.text);
|
|
470048
470682
|
try {
|
|
470049
470683
|
mkdirSync12(cacheDir, { recursive: true });
|
|
470050
|
-
await
|
|
470684
|
+
await writeFile14(cachePath, html, "utf-8");
|
|
470051
470685
|
} catch {
|
|
470052
470686
|
}
|
|
470053
470687
|
const costUsd = result.inputTokens / 1e6 * settings.costPerMTokIn + result.outputTokens / 1e6 * settings.costPerMTokOut;
|
|
@@ -470146,9 +470780,9 @@ async function resolveComposerConfigAware(explicit, cwd) {
|
|
|
470146
470780
|
return resolveComposer();
|
|
470147
470781
|
}
|
|
470148
470782
|
async function executeComposeScenesWithSkills(params, outputDir, overrides) {
|
|
470149
|
-
const projectRoot = params.project ?
|
|
470150
|
-
const designPath =
|
|
470151
|
-
const storyboardPath =
|
|
470783
|
+
const projectRoot = params.project ? resolve18(outputDir, params.project) : resolve18(outputDir);
|
|
470784
|
+
const designPath = resolve18(projectRoot, params.design ?? "DESIGN.md");
|
|
470785
|
+
const storyboardPath = resolve18(projectRoot, params.storyboard ?? "STORYBOARD.md");
|
|
470152
470786
|
if (!existsSync24(designPath)) {
|
|
470153
470787
|
return { success: false, error: `DESIGN.md not found at ${designPath}` };
|
|
470154
470788
|
}
|
|
@@ -470206,7 +470840,7 @@ async function executeComposeScenesWithSkills(params, outputDir, overrides) {
|
|
|
470206
470840
|
);
|
|
470207
470841
|
const compositionPath = join24(compositionsDir, `scene-${beat.id}.html`);
|
|
470208
470842
|
await mkdir9(dirname13(compositionPath), { recursive: true });
|
|
470209
|
-
await
|
|
470843
|
+
await writeFile14(compositionPath, result.html, "utf-8");
|
|
470210
470844
|
if (result.cached) {
|
|
470211
470845
|
onProgress({
|
|
470212
470846
|
type: "beat-cached",
|
|
@@ -470409,9 +471043,9 @@ var init_compose_scenes_skills = __esm({
|
|
|
470409
471043
|
// ../cli/src/commands/_shared/compose-prompts.ts
|
|
470410
471044
|
import { existsSync as existsSync25 } from "node:fs";
|
|
470411
471045
|
import { readFile as readFile10 } from "node:fs/promises";
|
|
470412
|
-
import { join as join25, relative as relative6, resolve as
|
|
471046
|
+
import { join as join25, relative as relative6, resolve as resolve19 } from "node:path";
|
|
470413
471047
|
async function getComposePrompts(opts) {
|
|
470414
|
-
const projectDir =
|
|
471048
|
+
const projectDir = resolve19(opts.projectDir);
|
|
470415
471049
|
const designPath = join25(projectDir, "DESIGN.md");
|
|
470416
471050
|
const storyboardPath = join25(projectDir, "STORYBOARD.md");
|
|
470417
471051
|
const skillPath = join25(projectDir, "SKILL.md");
|
|
@@ -470538,7 +471172,7 @@ var init_compose_prompts = __esm({
|
|
|
470538
471172
|
// ../cli/src/commands/_shared/sub-comp-duration-sync.ts
|
|
470539
471173
|
import { existsSync as existsSync27 } from "node:fs";
|
|
470540
471174
|
import { readFile as readFile12 } from "node:fs/promises";
|
|
470541
|
-
import { join as join27, resolve as
|
|
471175
|
+
import { join as join27, resolve as resolve21 } from "node:path";
|
|
470542
471176
|
function syncSubCompositionDurationHtml(html, beatId, newDurationSec, fileRel) {
|
|
470543
471177
|
const compositionId = `scene-${beatId}`;
|
|
470544
471178
|
const file = fileRel ?? `compositions/${compositionId}.html`;
|
|
@@ -470626,7 +471260,7 @@ function rewriteTimelineConst(html, oldDurationSec, newDurationSec) {
|
|
|
470626
471260
|
return { html, rewritten: false, needsManualFix };
|
|
470627
471261
|
}
|
|
470628
471262
|
async function createSubCompDurationSyncPlans(opts) {
|
|
470629
|
-
const projectDir =
|
|
471263
|
+
const projectDir = resolve21(opts.projectDir);
|
|
470630
471264
|
const results = [];
|
|
470631
471265
|
for (const beat of opts.beats) {
|
|
470632
471266
|
const fileRel = `compositions/scene-${beat.id}.html`;
|
|
@@ -470661,88 +471295,6 @@ var init_sub_comp_duration_sync = __esm({
|
|
|
470661
471295
|
}
|
|
470662
471296
|
});
|
|
470663
471297
|
|
|
470664
|
-
// ../cli/src/commands/_shared/review-report.ts
|
|
470665
|
-
import { writeFile as writeFile15 } from "node:fs/promises";
|
|
470666
|
-
import { join as join28, resolve as resolve21 } from "node:path";
|
|
470667
|
-
function statusFromIssues(issues) {
|
|
470668
|
-
if (issues.some((issue) => issue.severity === "error")) return "fail";
|
|
470669
|
-
if (issues.some((issue) => issue.severity === "warning")) return "warn";
|
|
470670
|
-
return "pass";
|
|
470671
|
-
}
|
|
470672
|
-
function scoreIssues(issues) {
|
|
470673
|
-
let score = 100;
|
|
470674
|
-
for (const issue of issues) {
|
|
470675
|
-
if (issue.severity === "error") score -= 25;
|
|
470676
|
-
else if (issue.severity === "warning") score -= 8;
|
|
470677
|
-
else score -= 2;
|
|
470678
|
-
}
|
|
470679
|
-
return Math.max(0, Math.min(100, score));
|
|
470680
|
-
}
|
|
470681
|
-
function uniqueRetryWith(items) {
|
|
470682
|
-
return [
|
|
470683
|
-
...new Set(items.filter((item) => typeof item === "string" && item.length > 0))
|
|
470684
|
-
];
|
|
470685
|
-
}
|
|
470686
|
-
function fixOwnerForIssue(issue) {
|
|
470687
|
-
if (issue.fixOwner) return issue.fixOwner;
|
|
470688
|
-
if (issue.code.startsWith("AI_REVIEW_")) return "host-agent";
|
|
470689
|
-
if (issue.code.startsWith("STORYBOARD_")) return "host-agent";
|
|
470690
|
-
if (issue.code === "PROJECT_NOT_FOUND" || issue.code === "MISSING_STORYBOARD" || issue.code === "BEAT_NOT_FOUND" || issue.code === "MISSING_DESIGN") {
|
|
470691
|
-
return "host-agent";
|
|
470692
|
-
}
|
|
470693
|
-
return "vibe";
|
|
470694
|
-
}
|
|
470695
|
-
function normalizeReviewIssues(issues, fallbackOwner) {
|
|
470696
|
-
return issues.map((issue) => ({
|
|
470697
|
-
...issue,
|
|
470698
|
-
fixOwner: issue.fixOwner ?? fallbackOwner ?? fixOwnerForIssue(issue)
|
|
470699
|
-
}));
|
|
470700
|
-
}
|
|
470701
|
-
function summarizeReviewIssues(issues) {
|
|
470702
|
-
const normalized = normalizeReviewIssues(issues);
|
|
470703
|
-
return {
|
|
470704
|
-
issueCount: normalized.length,
|
|
470705
|
-
errorCount: normalized.filter((issue) => issue.severity === "error").length,
|
|
470706
|
-
warningCount: normalized.filter((issue) => issue.severity === "warning").length,
|
|
470707
|
-
infoCount: normalized.filter((issue) => issue.severity === "info").length,
|
|
470708
|
-
fixOwners: {
|
|
470709
|
-
vibe: normalized.filter((issue) => issue.fixOwner === "vibe").length,
|
|
470710
|
-
hostAgent: normalized.filter((issue) => issue.fixOwner === "host-agent").length
|
|
470711
|
-
}
|
|
470712
|
-
};
|
|
470713
|
-
}
|
|
470714
|
-
function buildReviewReport(opts) {
|
|
470715
|
-
const issues = normalizeReviewIssues(opts.issues);
|
|
470716
|
-
return stripUndefined2({
|
|
470717
|
-
schemaVersion: "1",
|
|
470718
|
-
kind: "review",
|
|
470719
|
-
project: resolve21(opts.project),
|
|
470720
|
-
mode: opts.mode,
|
|
470721
|
-
beat: opts.beat,
|
|
470722
|
-
status: opts.status,
|
|
470723
|
-
score: opts.score,
|
|
470724
|
-
issues,
|
|
470725
|
-
summary: summarizeReviewIssues(issues),
|
|
470726
|
-
retryWith: uniqueRetryWith(opts.retryWith),
|
|
470727
|
-
sourceReports: opts.sourceReports ?? [],
|
|
470728
|
-
reportPath: opts.reportPath
|
|
470729
|
-
});
|
|
470730
|
-
}
|
|
470731
|
-
function defaultReviewReportPath(projectDir) {
|
|
470732
|
-
return join28(resolve21(projectDir), "review-report.json");
|
|
470733
|
-
}
|
|
470734
|
-
async function writeReviewReport(path14, report) {
|
|
470735
|
-
await writeFile15(path14, JSON.stringify(report, null, 2) + "\n", "utf-8");
|
|
470736
|
-
}
|
|
470737
|
-
function stripUndefined2(value) {
|
|
470738
|
-
return Object.fromEntries(Object.entries(value).filter(([, v2]) => v2 !== void 0));
|
|
470739
|
-
}
|
|
470740
|
-
var init_review_report = __esm({
|
|
470741
|
-
"../cli/src/commands/_shared/review-report.ts"() {
|
|
470742
|
-
"use strict";
|
|
470743
|
-
}
|
|
470744
|
-
});
|
|
470745
|
-
|
|
470746
471298
|
// ../cli/src/commands/_shared/scene-repair.ts
|
|
470747
471299
|
import { readFile as readFile13, writeFile as writeFile16 } from "node:fs/promises";
|
|
470748
471300
|
import { relative as relative7, resolve as resolve23 } from "node:path";
|
|
@@ -470869,16 +471421,307 @@ var init_scene_repair = __esm({
|
|
|
470869
471421
|
}
|
|
470870
471422
|
});
|
|
470871
471423
|
|
|
471424
|
+
// ../cli/src/commands/_shared/storyboard-edit.ts
|
|
471425
|
+
function validateStoryboardMarkdown(markdown) {
|
|
471426
|
+
const parsed = parseStoryboard(markdown);
|
|
471427
|
+
const sections = splitBeatSections(markdown);
|
|
471428
|
+
const issues = [];
|
|
471429
|
+
if (parsed.beats.length === 0) {
|
|
471430
|
+
issues.push({
|
|
471431
|
+
severity: "error",
|
|
471432
|
+
code: "NO_BEATS",
|
|
471433
|
+
message: "STORYBOARD.md must contain at least one `## Beat ...` heading."
|
|
471434
|
+
});
|
|
471435
|
+
}
|
|
471436
|
+
const seen = /* @__PURE__ */ new Map();
|
|
471437
|
+
for (const beat of parsed.beats) {
|
|
471438
|
+
seen.set(beat.id, (seen.get(beat.id) ?? 0) + 1);
|
|
471439
|
+
}
|
|
471440
|
+
for (const [id, count] of seen.entries()) {
|
|
471441
|
+
if (count > 1) {
|
|
471442
|
+
issues.push({
|
|
471443
|
+
severity: "error",
|
|
471444
|
+
code: "DUPLICATE_BEAT_ID",
|
|
471445
|
+
beatId: id,
|
|
471446
|
+
message: `Beat id "${id}" appears ${count} times. Beat ids must be unique.`
|
|
471447
|
+
});
|
|
471448
|
+
}
|
|
471449
|
+
}
|
|
471450
|
+
for (const section of sections) {
|
|
471451
|
+
const cueBlock = readLeadingCueBlock(section.body);
|
|
471452
|
+
if (cueBlock?.error) {
|
|
471453
|
+
issues.push({
|
|
471454
|
+
severity: "error",
|
|
471455
|
+
code: "MALFORMED_CUE_YAML",
|
|
471456
|
+
beatId: section.id,
|
|
471457
|
+
message: `Beat "${section.id}" has malformed YAML cues: ${cueBlock.error}`
|
|
471458
|
+
});
|
|
471459
|
+
}
|
|
471460
|
+
}
|
|
471461
|
+
const characterPool = new Set(
|
|
471462
|
+
Object.keys(
|
|
471463
|
+
parsed.frontmatter?.characters ?? {}
|
|
471464
|
+
)
|
|
471465
|
+
);
|
|
471466
|
+
for (const beat of parsed.beats) {
|
|
471467
|
+
const cues = beat.cues ?? {};
|
|
471468
|
+
for (const [key2, value] of Object.entries(cues)) {
|
|
471469
|
+
if (!ALLOWED_CUE_KEYS.has(key2)) {
|
|
471470
|
+
issues.push({
|
|
471471
|
+
severity: "warning",
|
|
471472
|
+
code: "UNKNOWN_CUE",
|
|
471473
|
+
beatId: beat.id,
|
|
471474
|
+
message: `Beat "${beat.id}" uses unknown cue "${key2}". Supported cues: ${STORYBOARD_CUE_KEYS.join(", ")}.`
|
|
471475
|
+
});
|
|
471476
|
+
continue;
|
|
471477
|
+
}
|
|
471478
|
+
if (key2 === "characters") {
|
|
471479
|
+
const validShape = typeof value === "string" || Array.isArray(value) && value.every((v2) => typeof v2 === "string");
|
|
471480
|
+
if (!validShape) {
|
|
471481
|
+
issues.push({
|
|
471482
|
+
severity: "error",
|
|
471483
|
+
code: "INVALID_CHARACTERS_VALUE",
|
|
471484
|
+
beatId: beat.id,
|
|
471485
|
+
message: `Beat "${beat.id}" cue "characters" must be a character name or a list of names.`
|
|
471486
|
+
});
|
|
471487
|
+
continue;
|
|
471488
|
+
}
|
|
471489
|
+
for (const name of beatCharacterNames({ characters: value })) {
|
|
471490
|
+
if (!characterPool.has(name)) {
|
|
471491
|
+
issues.push({
|
|
471492
|
+
severity: "warning",
|
|
471493
|
+
code: "UNKNOWN_CHARACTER",
|
|
471494
|
+
beatId: beat.id,
|
|
471495
|
+
message: `Beat "${beat.id}" references character "${name}" not defined in the frontmatter \`characters:\` pool.`
|
|
471496
|
+
});
|
|
471497
|
+
}
|
|
471498
|
+
}
|
|
471499
|
+
continue;
|
|
471500
|
+
}
|
|
471501
|
+
if (key2 === "duration") {
|
|
471502
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
471503
|
+
issues.push({
|
|
471504
|
+
severity: "error",
|
|
471505
|
+
code: "INVALID_DURATION",
|
|
471506
|
+
beatId: beat.id,
|
|
471507
|
+
message: `Beat "${beat.id}" cue "duration" must be a positive number of seconds.`
|
|
471508
|
+
});
|
|
471509
|
+
}
|
|
471510
|
+
continue;
|
|
471511
|
+
}
|
|
471512
|
+
if (STRING_CUE_KEYS.has(key2) && typeof value !== "string") {
|
|
471513
|
+
issues.push({
|
|
471514
|
+
severity: "error",
|
|
471515
|
+
code: "INVALID_CUE_VALUE",
|
|
471516
|
+
beatId: beat.id,
|
|
471517
|
+
message: `Beat "${beat.id}" cue "${key2}" must be a string.`
|
|
471518
|
+
});
|
|
471519
|
+
}
|
|
471520
|
+
}
|
|
471521
|
+
}
|
|
471522
|
+
for (const beat of parsed.beats) {
|
|
471523
|
+
if (beat.duration !== void 0 && beat.duration > MAX_RECOMMENDED_BEAT_SEC) {
|
|
471524
|
+
issues.push({
|
|
471525
|
+
severity: "warning",
|
|
471526
|
+
code: "BEAT_DURATION_TOO_LONG",
|
|
471527
|
+
beatId: beat.id,
|
|
471528
|
+
message: `Beat "${beat.id}" is ${beat.duration}s \u2014 beats longer than ${MAX_RECOMMENDED_BEAT_SEC}s render static and overstuffed. Split it into 6-15s beats (a 90s video should have 6-8 beats).`
|
|
471529
|
+
});
|
|
471530
|
+
}
|
|
471531
|
+
}
|
|
471532
|
+
return {
|
|
471533
|
+
ok: !issues.some((i2) => i2.severity === "error"),
|
|
471534
|
+
beats: parsed.beats,
|
|
471535
|
+
issues
|
|
471536
|
+
};
|
|
471537
|
+
}
|
|
471538
|
+
function getStoryboardBeat(markdown, beatId) {
|
|
471539
|
+
return parseStoryboard(markdown).beats.find((beat) => beat.id === beatId) ?? null;
|
|
471540
|
+
}
|
|
471541
|
+
function upsertStoryboardBeat(markdown, opts) {
|
|
471542
|
+
const beatId = normalizeBeatId(opts.beatId);
|
|
471543
|
+
const sections = splitBeatSections(markdown);
|
|
471544
|
+
const existing = sections.find((section2) => section2.id === beatId);
|
|
471545
|
+
const cues = storyboardCuesFromInput(opts);
|
|
471546
|
+
if (existing) {
|
|
471547
|
+
let next = markdown;
|
|
471548
|
+
for (const [key2, value] of Object.entries(cues)) {
|
|
471549
|
+
next = setStoryboardCue(next, { beatId, key: key2, value });
|
|
471550
|
+
}
|
|
471551
|
+
return { markdown: next, action: "updated" };
|
|
471552
|
+
}
|
|
471553
|
+
const section = buildStoryboardBeatSection({ ...opts, beatId, cues });
|
|
471554
|
+
if (sections.length > 0 && isStarterStoryboard(markdown)) {
|
|
471555
|
+
const global3 = markdown.slice(0, sections[0].start).trimEnd();
|
|
471556
|
+
return {
|
|
471557
|
+
markdown: `${global3}
|
|
471558
|
+
|
|
471559
|
+
${section}`,
|
|
471560
|
+
action: "replaced-starter"
|
|
471561
|
+
};
|
|
471562
|
+
}
|
|
471563
|
+
const prefix = markdown.trimEnd();
|
|
471564
|
+
return {
|
|
471565
|
+
markdown: `${prefix}${prefix ? "\n\n" : ""}${section}`,
|
|
471566
|
+
action: "appended"
|
|
471567
|
+
};
|
|
471568
|
+
}
|
|
471569
|
+
function setStoryboardCue(markdown, opts) {
|
|
471570
|
+
const section = findBeatSection(markdown, opts.beatId);
|
|
471571
|
+
if (!section) {
|
|
471572
|
+
throw new Error(`Beat "${opts.beatId}" not found.`);
|
|
471573
|
+
}
|
|
471574
|
+
if (!ALLOWED_CUE_KEYS.has(opts.key)) {
|
|
471575
|
+
throw new Error(`Unsupported cue "${opts.key}". Supported cues: ${STORYBOARD_CUE_KEYS.join(", ")}.`);
|
|
471576
|
+
}
|
|
471577
|
+
const cue = readLeadingCueBlock(section.body);
|
|
471578
|
+
if (cue?.error) {
|
|
471579
|
+
throw new Error(`Cannot edit malformed YAML cues for beat "${opts.beatId}": ${cue.error}`);
|
|
471580
|
+
}
|
|
471581
|
+
const cues = cue?.value ? { ...cue.value } : {};
|
|
471582
|
+
if (opts.unset) {
|
|
471583
|
+
delete cues[opts.key];
|
|
471584
|
+
} else {
|
|
471585
|
+
cues[opts.key] = normalizeCueValue(opts.key, opts.value);
|
|
471586
|
+
}
|
|
471587
|
+
const remainingBody = cue ? section.body.slice(cue.full.length).replace(/^\s*\n/, "") : section.body.replace(/^\s*\n/, "");
|
|
471588
|
+
const cueBlock = Object.keys(cues).length > 0 ? "```yaml\n" + (0, import_yaml5.stringify)(cues, { lineWidth: 0 }).trimEnd() + "\n```\n\n" : "";
|
|
471589
|
+
const nextBody = cueBlock + remainingBody.trimStart();
|
|
471590
|
+
const nextSection = section.raw.slice(0, section.headingEnd - section.start) + "\n\n" + nextBody.trimEnd() + "\n";
|
|
471591
|
+
return markdown.slice(0, section.start) + nextSection + markdown.slice(section.end);
|
|
471592
|
+
}
|
|
471593
|
+
function moveStoryboardBeat(markdown, opts) {
|
|
471594
|
+
if (opts.beatId === opts.afterBeatId) return markdown;
|
|
471595
|
+
const sections = splitBeatSections(markdown);
|
|
471596
|
+
const movingIndex = sections.findIndex((section) => section.id === opts.beatId);
|
|
471597
|
+
if (movingIndex === -1) throw new Error(`Beat "${opts.beatId}" not found.`);
|
|
471598
|
+
const afterIndex = sections.findIndex((section) => section.id === opts.afterBeatId);
|
|
471599
|
+
if (afterIndex === -1) throw new Error(`Beat "${opts.afterBeatId}" not found.`);
|
|
471600
|
+
const global3 = sections.length > 0 ? markdown.slice(0, sections[0].start) : markdown;
|
|
471601
|
+
const chunks = sections.map((section) => section.raw);
|
|
471602
|
+
const [moving] = chunks.splice(movingIndex, 1);
|
|
471603
|
+
const adjustedAfterIndex = movingIndex < afterIndex ? afterIndex - 1 : afterIndex;
|
|
471604
|
+
chunks.splice(adjustedAfterIndex + 1, 0, moving);
|
|
471605
|
+
return global3 + normalizeBeatChunks(chunks);
|
|
471606
|
+
}
|
|
471607
|
+
function normalizeBeatChunks(chunks) {
|
|
471608
|
+
return chunks.map((chunk) => chunk.trim()).filter(Boolean).join("\n\n") + "\n";
|
|
471609
|
+
}
|
|
471610
|
+
function normalizeBeatId(id) {
|
|
471611
|
+
return deriveBeatId(id);
|
|
471612
|
+
}
|
|
471613
|
+
function storyboardCuesFromInput(opts) {
|
|
471614
|
+
const cues = {};
|
|
471615
|
+
if (opts.duration !== void 0) cues.duration = opts.duration;
|
|
471616
|
+
if (opts.narration && opts.narration.trim()) cues.narration = opts.narration.trim();
|
|
471617
|
+
if (opts.backdrop && opts.backdrop.trim()) cues.backdrop = opts.backdrop.trim();
|
|
471618
|
+
return cues;
|
|
471619
|
+
}
|
|
471620
|
+
function buildStoryboardBeatSection(opts) {
|
|
471621
|
+
const title = normalizeTitle(opts.title ?? humanizeBeatId(opts.beatId));
|
|
471622
|
+
const cueBlock = Object.keys(opts.cues).length > 0 ? "```yaml\n" + (0, import_yaml5.stringify)(opts.cues, { lineWidth: 0 }).trimEnd() + "\n```\n\n" : "";
|
|
471623
|
+
const body = opts.body?.trim() || "Scene created with `vibe scene add`. Edit this body if the build flow should recompose it.";
|
|
471624
|
+
return `## Beat ${opts.beatId} - ${title}
|
|
471625
|
+
|
|
471626
|
+
${cueBlock}${body.trimEnd()}
|
|
471627
|
+
`;
|
|
471628
|
+
}
|
|
471629
|
+
function normalizeTitle(value) {
|
|
471630
|
+
return value.replace(/\s+/g, " ").trim() || "Scene";
|
|
471631
|
+
}
|
|
471632
|
+
function humanizeBeatId(id) {
|
|
471633
|
+
return id.split(/[-_]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ") || "Scene";
|
|
471634
|
+
}
|
|
471635
|
+
function isStarterStoryboard(markdown) {
|
|
471636
|
+
const parsed = parseStoryboard(markdown);
|
|
471637
|
+
if (parsed.beats.length !== 3) return false;
|
|
471638
|
+
const ids = parsed.beats.map((beat) => beat.id);
|
|
471639
|
+
if (ids.join(",") !== "hook,proof,close") return false;
|
|
471640
|
+
return markdown.includes("Introduce the promise in one crisp sentence.") && markdown.includes("Show the mechanism or proof point that makes the promise believable.") && markdown.includes("Close with the action the viewer should remember.");
|
|
471641
|
+
}
|
|
471642
|
+
function normalizeCueValue(key2, value) {
|
|
471643
|
+
if (key2 === "duration") {
|
|
471644
|
+
const n2 = typeof value === "number" ? value : Number.parseFloat(String(value ?? ""));
|
|
471645
|
+
if (!Number.isFinite(n2) || n2 <= 0) {
|
|
471646
|
+
throw new Error("Cue duration must be a positive number.");
|
|
471647
|
+
}
|
|
471648
|
+
return n2;
|
|
471649
|
+
}
|
|
471650
|
+
if (typeof value !== "string") return value;
|
|
471651
|
+
return value.trim();
|
|
471652
|
+
}
|
|
471653
|
+
function splitBeatSections(markdown) {
|
|
471654
|
+
const normalized = markdown.replace(/\r\n/g, "\n");
|
|
471655
|
+
const headings = [];
|
|
471656
|
+
HEADING_RE2.lastIndex = 0;
|
|
471657
|
+
let match2;
|
|
471658
|
+
while ((match2 = HEADING_RE2.exec(normalized)) !== null) {
|
|
471659
|
+
headings.push({ start: match2.index, end: match2.index + match2[0].length, line: match2[1].trim() });
|
|
471660
|
+
}
|
|
471661
|
+
return headings.map((heading, index) => {
|
|
471662
|
+
const end = index + 1 < headings.length ? headings[index + 1].start : normalized.length;
|
|
471663
|
+
return {
|
|
471664
|
+
id: deriveBeatId(heading.line),
|
|
471665
|
+
heading: heading.line,
|
|
471666
|
+
start: heading.start,
|
|
471667
|
+
headingEnd: heading.end,
|
|
471668
|
+
end,
|
|
471669
|
+
raw: normalized.slice(heading.start, end),
|
|
471670
|
+
body: normalized.slice(heading.end, end).trim()
|
|
471671
|
+
};
|
|
471672
|
+
});
|
|
471673
|
+
}
|
|
471674
|
+
function findBeatSection(markdown, beatId) {
|
|
471675
|
+
return splitBeatSections(markdown).find((section) => section.id === beatId) ?? null;
|
|
471676
|
+
}
|
|
471677
|
+
function readLeadingCueBlock(body) {
|
|
471678
|
+
const match2 = body.match(LEADING_CUE_RE);
|
|
471679
|
+
if (!match2) return null;
|
|
471680
|
+
try {
|
|
471681
|
+
const parsed = (0, import_yaml5.parse)(match2[2]);
|
|
471682
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
471683
|
+
return { full: match2[0], error: "cue block must parse to a YAML object" };
|
|
471684
|
+
}
|
|
471685
|
+
return { full: match2[0], value: parsed };
|
|
471686
|
+
} catch (error) {
|
|
471687
|
+
return { full: match2[0], error: error instanceof Error ? error.message : String(error) };
|
|
471688
|
+
}
|
|
471689
|
+
}
|
|
471690
|
+
var import_yaml5, STORYBOARD_CUE_KEYS, HEADING_RE2, LEADING_CUE_RE, ALLOWED_CUE_KEYS, STRING_CUE_KEYS, MAX_RECOMMENDED_BEAT_SEC;
|
|
471691
|
+
var init_storyboard_edit = __esm({
|
|
471692
|
+
"../cli/src/commands/_shared/storyboard-edit.ts"() {
|
|
471693
|
+
"use strict";
|
|
471694
|
+
import_yaml5 = __toESM(require_dist3(), 1);
|
|
471695
|
+
init_storyboard_parse();
|
|
471696
|
+
STORYBOARD_CUE_KEYS = [
|
|
471697
|
+
"duration",
|
|
471698
|
+
"narration",
|
|
471699
|
+
"backdrop",
|
|
471700
|
+
"video",
|
|
471701
|
+
"motion",
|
|
471702
|
+
"voice",
|
|
471703
|
+
"music",
|
|
471704
|
+
"asset",
|
|
471705
|
+
"characters"
|
|
471706
|
+
];
|
|
471707
|
+
HEADING_RE2 = /^##\s+(.+?)\s*$/gm;
|
|
471708
|
+
LEADING_CUE_RE = /^(\s*)```ya?ml\s*\n([\s\S]*?)\n```\s*(?:\n|$)/;
|
|
471709
|
+
ALLOWED_CUE_KEYS = new Set(STORYBOARD_CUE_KEYS);
|
|
471710
|
+
STRING_CUE_KEYS = /* @__PURE__ */ new Set(["narration", "backdrop", "video", "motion", "voice", "music", "asset"]);
|
|
471711
|
+
MAX_RECOMMENDED_BEAT_SEC = 15;
|
|
471712
|
+
}
|
|
471713
|
+
});
|
|
471714
|
+
|
|
470872
471715
|
// ../cli/src/pipeline/renderers/chrome.ts
|
|
470873
471716
|
import { existsSync as existsSync29 } from "node:fs";
|
|
470874
471717
|
import { homedir as homedir7 } from "node:os";
|
|
470875
|
-
import { join as
|
|
471718
|
+
import { join as join28 } from "node:path";
|
|
470876
471719
|
function findChrome() {
|
|
470877
471720
|
const candidates = [
|
|
470878
471721
|
process.env.HYPERFRAMES_CHROME_PATH,
|
|
470879
471722
|
process.env.CHROME_PATH,
|
|
470880
471723
|
// puppeteer auto-downloaded headless shell
|
|
470881
|
-
|
|
471724
|
+
join28(
|
|
470882
471725
|
homedir7(),
|
|
470883
471726
|
".cache",
|
|
470884
471727
|
"puppeteer",
|
|
@@ -471171,7 +472014,7 @@ __export(scene_render_exports, {
|
|
|
471171
472014
|
import { execFile as execFile2 } from "node:child_process";
|
|
471172
472015
|
import { existsSync as existsSync30 } from "node:fs";
|
|
471173
472016
|
import { mkdir as mkdir12, readFile as readFile16, stat as stat3, writeFile as writeFile18 } from "node:fs/promises";
|
|
471174
|
-
import { resolve as resolve27, relative as relative9, dirname as dirname16, basename as basename7, join as
|
|
472017
|
+
import { resolve as resolve27, relative as relative9, dirname as dirname16, basename as basename7, join as join29, isAbsolute as isAbsolute3 } from "node:path";
|
|
471175
472018
|
import { promisify as promisify2 } from "node:util";
|
|
471176
472019
|
function qualityToCrf(quality = "standard") {
|
|
471177
472020
|
return quality === "draft" ? 28 : quality === "high" ? 18 : 23;
|
|
@@ -471259,7 +472102,7 @@ async function executeSceneRender(opts = {}) {
|
|
|
471259
472102
|
}
|
|
471260
472103
|
let autoSyncApplied = false;
|
|
471261
472104
|
let autoSyncWarning;
|
|
471262
|
-
if (!opts.beatId && existsSync30(
|
|
472105
|
+
if (!opts.beatId && existsSync30(join29(projectDir, "STORYBOARD.md"))) {
|
|
471263
472106
|
try {
|
|
471264
472107
|
const rootPlan = await createProjectRootSyncPlan({ projectDir });
|
|
471265
472108
|
const subPlans = await createSubCompDurationSyncPlans({
|
|
@@ -471436,7 +472279,7 @@ async function safeStat(p2) {
|
|
|
471436
472279
|
}
|
|
471437
472280
|
async function prepareBeatRenderRoot(opts) {
|
|
471438
472281
|
const root2 = `.vibeframe/tmp/render-beat-${sanitizeFileSegment(opts.beatId)}.html`;
|
|
471439
|
-
const reportPath =
|
|
472282
|
+
const reportPath = join29(opts.projectDir, "build-report.json");
|
|
471440
472283
|
const retryWith = [
|
|
471441
472284
|
`vibe build ${opts.projectDir} --beat ${opts.beatId} --stage sync --json`
|
|
471442
472285
|
];
|
|
@@ -471520,8 +472363,8 @@ async function prepareBeatRenderRoot(opts) {
|
|
|
471520
472363
|
durationSec,
|
|
471521
472364
|
narrationPath
|
|
471522
472365
|
});
|
|
471523
|
-
await mkdir12(dirname16(
|
|
471524
|
-
await writeFile18(
|
|
472366
|
+
await mkdir12(dirname16(join29(opts.projectDir, root2)), { recursive: true });
|
|
472367
|
+
await writeFile18(join29(opts.projectDir, root2), html, "utf-8");
|
|
471525
472368
|
return {
|
|
471526
472369
|
success: true,
|
|
471527
472370
|
root: root2,
|
|
@@ -471585,7 +472428,7 @@ function reportedBeatAssetPaths(beat) {
|
|
|
471585
472428
|
]);
|
|
471586
472429
|
}
|
|
471587
472430
|
async function writeRenderReport(projectDir, result) {
|
|
471588
|
-
const reportPath =
|
|
472431
|
+
const reportPath = join29(projectDir, "render-report.json");
|
|
471589
472432
|
try {
|
|
471590
472433
|
await writeFile18(
|
|
471591
472434
|
reportPath,
|
|
@@ -471782,6 +472625,7 @@ var init_build_asset_reference = __esm({
|
|
|
471782
472625
|
EXTENSIONS = {
|
|
471783
472626
|
narration: [".mp3", ".wav", ".m4a"],
|
|
471784
472627
|
backdrop: [".png", ".jpg", ".jpeg", ".webp"],
|
|
472628
|
+
character: [".png", ".jpg", ".jpeg", ".webp"],
|
|
471785
472629
|
video: [".mp4", ".mov", ".webm"],
|
|
471786
472630
|
music: [".mp3", ".wav", ".m4a"]
|
|
471787
472631
|
};
|
|
@@ -471819,6 +472663,16 @@ function backdropCacheDescriptor(opts) {
|
|
|
471819
472663
|
ext: "png"
|
|
471820
472664
|
});
|
|
471821
472665
|
}
|
|
472666
|
+
function characterCacheDescriptor(opts) {
|
|
472667
|
+
return cacheAssetDescriptor("character", {
|
|
472668
|
+
name: opts.name,
|
|
472669
|
+
cue: opts.cue,
|
|
472670
|
+
provider: opts.provider,
|
|
472671
|
+
quality: opts.quality,
|
|
472672
|
+
size: opts.size,
|
|
472673
|
+
ext: "png"
|
|
472674
|
+
});
|
|
472675
|
+
}
|
|
471822
472676
|
function imageRatioForSize(size) {
|
|
471823
472677
|
switch (size) {
|
|
471824
472678
|
case "1024x1024":
|
|
@@ -471838,6 +472692,8 @@ function videoCacheDescriptor(opts) {
|
|
|
471838
472692
|
provider: opts.provider,
|
|
471839
472693
|
duration: normalizeVideoDuration(opts.duration),
|
|
471840
472694
|
ratio: "16:9",
|
|
472695
|
+
// Omit when empty so existing (character-less) clips keep their cache key.
|
|
472696
|
+
characters: opts.characters && opts.characters.length > 0 ? opts.characters : void 0,
|
|
471841
472697
|
ext: "mp4"
|
|
471842
472698
|
});
|
|
471843
472699
|
}
|
|
@@ -471890,212 +472746,10 @@ var init_build_backdrop_prompt = __esm({
|
|
|
471890
472746
|
}
|
|
471891
472747
|
});
|
|
471892
472748
|
|
|
471893
|
-
// ../cli/src/commands/_shared/storyboard-edit.ts
|
|
471894
|
-
function validateStoryboardMarkdown(markdown) {
|
|
471895
|
-
const parsed = parseStoryboard(markdown);
|
|
471896
|
-
const sections = splitBeatSections(markdown);
|
|
471897
|
-
const issues = [];
|
|
471898
|
-
if (parsed.beats.length === 0) {
|
|
471899
|
-
issues.push({
|
|
471900
|
-
severity: "error",
|
|
471901
|
-
code: "NO_BEATS",
|
|
471902
|
-
message: "STORYBOARD.md must contain at least one `## Beat ...` heading."
|
|
471903
|
-
});
|
|
471904
|
-
}
|
|
471905
|
-
const seen = /* @__PURE__ */ new Map();
|
|
471906
|
-
for (const beat of parsed.beats) {
|
|
471907
|
-
seen.set(beat.id, (seen.get(beat.id) ?? 0) + 1);
|
|
471908
|
-
}
|
|
471909
|
-
for (const [id, count] of seen.entries()) {
|
|
471910
|
-
if (count > 1) {
|
|
471911
|
-
issues.push({
|
|
471912
|
-
severity: "error",
|
|
471913
|
-
code: "DUPLICATE_BEAT_ID",
|
|
471914
|
-
beatId: id,
|
|
471915
|
-
message: `Beat id "${id}" appears ${count} times. Beat ids must be unique.`
|
|
471916
|
-
});
|
|
471917
|
-
}
|
|
471918
|
-
}
|
|
471919
|
-
for (const section of sections) {
|
|
471920
|
-
const cueBlock = readLeadingCueBlock(section.body);
|
|
471921
|
-
if (cueBlock?.error) {
|
|
471922
|
-
issues.push({
|
|
471923
|
-
severity: "error",
|
|
471924
|
-
code: "MALFORMED_CUE_YAML",
|
|
471925
|
-
beatId: section.id,
|
|
471926
|
-
message: `Beat "${section.id}" has malformed YAML cues: ${cueBlock.error}`
|
|
471927
|
-
});
|
|
471928
|
-
}
|
|
471929
|
-
}
|
|
471930
|
-
for (const beat of parsed.beats) {
|
|
471931
|
-
const cues = beat.cues ?? {};
|
|
471932
|
-
for (const [key2, value] of Object.entries(cues)) {
|
|
471933
|
-
if (!ALLOWED_CUE_KEYS.has(key2)) {
|
|
471934
|
-
issues.push({
|
|
471935
|
-
severity: "warning",
|
|
471936
|
-
code: "UNKNOWN_CUE",
|
|
471937
|
-
beatId: beat.id,
|
|
471938
|
-
message: `Beat "${beat.id}" uses unknown cue "${key2}". Supported cues: ${STORYBOARD_CUE_KEYS.join(", ")}.`
|
|
471939
|
-
});
|
|
471940
|
-
continue;
|
|
471941
|
-
}
|
|
471942
|
-
if (key2 === "duration") {
|
|
471943
|
-
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
471944
|
-
issues.push({
|
|
471945
|
-
severity: "error",
|
|
471946
|
-
code: "INVALID_DURATION",
|
|
471947
|
-
beatId: beat.id,
|
|
471948
|
-
message: `Beat "${beat.id}" cue "duration" must be a positive number of seconds.`
|
|
471949
|
-
});
|
|
471950
|
-
}
|
|
471951
|
-
continue;
|
|
471952
|
-
}
|
|
471953
|
-
if (STRING_CUE_KEYS.has(key2) && typeof value !== "string") {
|
|
471954
|
-
issues.push({
|
|
471955
|
-
severity: "error",
|
|
471956
|
-
code: "INVALID_CUE_VALUE",
|
|
471957
|
-
beatId: beat.id,
|
|
471958
|
-
message: `Beat "${beat.id}" cue "${key2}" must be a string.`
|
|
471959
|
-
});
|
|
471960
|
-
}
|
|
471961
|
-
}
|
|
471962
|
-
}
|
|
471963
|
-
for (const beat of parsed.beats) {
|
|
471964
|
-
if (beat.duration !== void 0 && beat.duration > MAX_RECOMMENDED_BEAT_SEC) {
|
|
471965
|
-
issues.push({
|
|
471966
|
-
severity: "warning",
|
|
471967
|
-
code: "BEAT_DURATION_TOO_LONG",
|
|
471968
|
-
beatId: beat.id,
|
|
471969
|
-
message: `Beat "${beat.id}" is ${beat.duration}s \u2014 beats longer than ${MAX_RECOMMENDED_BEAT_SEC}s render static and overstuffed. Split it into 6-15s beats (a 90s video should have 6-8 beats).`
|
|
471970
|
-
});
|
|
471971
|
-
}
|
|
471972
|
-
}
|
|
471973
|
-
return {
|
|
471974
|
-
ok: !issues.some((i2) => i2.severity === "error"),
|
|
471975
|
-
beats: parsed.beats,
|
|
471976
|
-
issues
|
|
471977
|
-
};
|
|
471978
|
-
}
|
|
471979
|
-
function getStoryboardBeat(markdown, beatId) {
|
|
471980
|
-
return parseStoryboard(markdown).beats.find((beat) => beat.id === beatId) ?? null;
|
|
471981
|
-
}
|
|
471982
|
-
function setStoryboardCue(markdown, opts) {
|
|
471983
|
-
const section = findBeatSection(markdown, opts.beatId);
|
|
471984
|
-
if (!section) {
|
|
471985
|
-
throw new Error(`Beat "${opts.beatId}" not found.`);
|
|
471986
|
-
}
|
|
471987
|
-
if (!ALLOWED_CUE_KEYS.has(opts.key)) {
|
|
471988
|
-
throw new Error(`Unsupported cue "${opts.key}". Supported cues: ${STORYBOARD_CUE_KEYS.join(", ")}.`);
|
|
471989
|
-
}
|
|
471990
|
-
const cue = readLeadingCueBlock(section.body);
|
|
471991
|
-
if (cue?.error) {
|
|
471992
|
-
throw new Error(`Cannot edit malformed YAML cues for beat "${opts.beatId}": ${cue.error}`);
|
|
471993
|
-
}
|
|
471994
|
-
const cues = cue?.value ? { ...cue.value } : {};
|
|
471995
|
-
if (opts.unset) {
|
|
471996
|
-
delete cues[opts.key];
|
|
471997
|
-
} else {
|
|
471998
|
-
cues[opts.key] = normalizeCueValue(opts.key, opts.value);
|
|
471999
|
-
}
|
|
472000
|
-
const remainingBody = cue ? section.body.slice(cue.full.length).replace(/^\s*\n/, "") : section.body.replace(/^\s*\n/, "");
|
|
472001
|
-
const cueBlock = Object.keys(cues).length > 0 ? "```yaml\n" + (0, import_yaml5.stringify)(cues, { lineWidth: 0 }).trimEnd() + "\n```\n\n" : "";
|
|
472002
|
-
const nextBody = cueBlock + remainingBody.trimStart();
|
|
472003
|
-
const nextSection = section.raw.slice(0, section.headingEnd - section.start) + "\n\n" + nextBody.trimEnd() + "\n";
|
|
472004
|
-
return markdown.slice(0, section.start) + nextSection + markdown.slice(section.end);
|
|
472005
|
-
}
|
|
472006
|
-
function moveStoryboardBeat(markdown, opts) {
|
|
472007
|
-
if (opts.beatId === opts.afterBeatId) return markdown;
|
|
472008
|
-
const sections = splitBeatSections(markdown);
|
|
472009
|
-
const movingIndex = sections.findIndex((section) => section.id === opts.beatId);
|
|
472010
|
-
if (movingIndex === -1) throw new Error(`Beat "${opts.beatId}" not found.`);
|
|
472011
|
-
const afterIndex = sections.findIndex((section) => section.id === opts.afterBeatId);
|
|
472012
|
-
if (afterIndex === -1) throw new Error(`Beat "${opts.afterBeatId}" not found.`);
|
|
472013
|
-
const global3 = sections.length > 0 ? markdown.slice(0, sections[0].start) : markdown;
|
|
472014
|
-
const chunks = sections.map((section) => section.raw);
|
|
472015
|
-
const [moving] = chunks.splice(movingIndex, 1);
|
|
472016
|
-
const adjustedAfterIndex = movingIndex < afterIndex ? afterIndex - 1 : afterIndex;
|
|
472017
|
-
chunks.splice(adjustedAfterIndex + 1, 0, moving);
|
|
472018
|
-
return global3 + normalizeBeatChunks(chunks);
|
|
472019
|
-
}
|
|
472020
|
-
function normalizeBeatChunks(chunks) {
|
|
472021
|
-
return chunks.map((chunk) => chunk.trim()).filter(Boolean).join("\n\n") + "\n";
|
|
472022
|
-
}
|
|
472023
|
-
function normalizeCueValue(key2, value) {
|
|
472024
|
-
if (key2 === "duration") {
|
|
472025
|
-
const n2 = typeof value === "number" ? value : Number.parseFloat(String(value ?? ""));
|
|
472026
|
-
if (!Number.isFinite(n2) || n2 <= 0) {
|
|
472027
|
-
throw new Error("Cue duration must be a positive number.");
|
|
472028
|
-
}
|
|
472029
|
-
return n2;
|
|
472030
|
-
}
|
|
472031
|
-
if (typeof value !== "string") return value;
|
|
472032
|
-
return value.trim();
|
|
472033
|
-
}
|
|
472034
|
-
function splitBeatSections(markdown) {
|
|
472035
|
-
const normalized = markdown.replace(/\r\n/g, "\n");
|
|
472036
|
-
const headings = [];
|
|
472037
|
-
HEADING_RE2.lastIndex = 0;
|
|
472038
|
-
let match2;
|
|
472039
|
-
while ((match2 = HEADING_RE2.exec(normalized)) !== null) {
|
|
472040
|
-
headings.push({ start: match2.index, end: match2.index + match2[0].length, line: match2[1].trim() });
|
|
472041
|
-
}
|
|
472042
|
-
return headings.map((heading, index) => {
|
|
472043
|
-
const end = index + 1 < headings.length ? headings[index + 1].start : normalized.length;
|
|
472044
|
-
return {
|
|
472045
|
-
id: deriveBeatId(heading.line),
|
|
472046
|
-
heading: heading.line,
|
|
472047
|
-
start: heading.start,
|
|
472048
|
-
headingEnd: heading.end,
|
|
472049
|
-
end,
|
|
472050
|
-
raw: normalized.slice(heading.start, end),
|
|
472051
|
-
body: normalized.slice(heading.end, end).trim()
|
|
472052
|
-
};
|
|
472053
|
-
});
|
|
472054
|
-
}
|
|
472055
|
-
function findBeatSection(markdown, beatId) {
|
|
472056
|
-
return splitBeatSections(markdown).find((section) => section.id === beatId) ?? null;
|
|
472057
|
-
}
|
|
472058
|
-
function readLeadingCueBlock(body) {
|
|
472059
|
-
const match2 = body.match(LEADING_CUE_RE);
|
|
472060
|
-
if (!match2) return null;
|
|
472061
|
-
try {
|
|
472062
|
-
const parsed = (0, import_yaml5.parse)(match2[2]);
|
|
472063
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
472064
|
-
return { full: match2[0], error: "cue block must parse to a YAML object" };
|
|
472065
|
-
}
|
|
472066
|
-
return { full: match2[0], value: parsed };
|
|
472067
|
-
} catch (error) {
|
|
472068
|
-
return { full: match2[0], error: error instanceof Error ? error.message : String(error) };
|
|
472069
|
-
}
|
|
472070
|
-
}
|
|
472071
|
-
var import_yaml5, STORYBOARD_CUE_KEYS, HEADING_RE2, LEADING_CUE_RE, ALLOWED_CUE_KEYS, STRING_CUE_KEYS, MAX_RECOMMENDED_BEAT_SEC;
|
|
472072
|
-
var init_storyboard_edit = __esm({
|
|
472073
|
-
"../cli/src/commands/_shared/storyboard-edit.ts"() {
|
|
472074
|
-
"use strict";
|
|
472075
|
-
import_yaml5 = __toESM(require_dist3(), 1);
|
|
472076
|
-
init_storyboard_parse();
|
|
472077
|
-
STORYBOARD_CUE_KEYS = [
|
|
472078
|
-
"duration",
|
|
472079
|
-
"narration",
|
|
472080
|
-
"backdrop",
|
|
472081
|
-
"video",
|
|
472082
|
-
"motion",
|
|
472083
|
-
"voice",
|
|
472084
|
-
"music",
|
|
472085
|
-
"asset"
|
|
472086
|
-
];
|
|
472087
|
-
HEADING_RE2 = /^##\s+(.+?)\s*$/gm;
|
|
472088
|
-
LEADING_CUE_RE = /^(\s*)```ya?ml\s*\n([\s\S]*?)\n```\s*(?:\n|$)/;
|
|
472089
|
-
ALLOWED_CUE_KEYS = new Set(STORYBOARD_CUE_KEYS);
|
|
472090
|
-
STRING_CUE_KEYS = /* @__PURE__ */ new Set(["narration", "backdrop", "video", "motion", "voice", "music", "asset"]);
|
|
472091
|
-
MAX_RECOMMENDED_BEAT_SEC = 15;
|
|
472092
|
-
}
|
|
472093
|
-
});
|
|
472094
|
-
|
|
472095
472749
|
// ../cli/src/commands/_shared/build-plan.ts
|
|
472096
472750
|
import { existsSync as existsSync33 } from "node:fs";
|
|
472097
472751
|
import { readFile as readFile17 } from "node:fs/promises";
|
|
472098
|
-
import { dirname as dirname17, join as
|
|
472752
|
+
import { dirname as dirname17, join as join30, resolve as resolve29 } from "node:path";
|
|
472099
472753
|
function backdropCostUsd(quality) {
|
|
472100
472754
|
return quality === "hd" ? 0.2 : 0.05;
|
|
472101
472755
|
}
|
|
@@ -472104,7 +472758,7 @@ async function createBuildPlan(opts) {
|
|
|
472104
472758
|
loadPlanEnv(projectDir);
|
|
472105
472759
|
const stage = opts.stage ?? "all";
|
|
472106
472760
|
const config4 = await readProjectConfig(projectDir);
|
|
472107
|
-
const storyboardPath =
|
|
472761
|
+
const storyboardPath = join30(projectDir, "STORYBOARD.md");
|
|
472108
472762
|
const warnings = [];
|
|
472109
472763
|
const retryWith = [];
|
|
472110
472764
|
const providerResolution = [];
|
|
@@ -472163,7 +472817,7 @@ async function createBuildPlan(opts) {
|
|
|
472163
472817
|
const imageQuality = opts.imageQuality ?? config4.config.build.imageQuality ?? "hd";
|
|
472164
472818
|
const imageSize2 = opts.imageSize ?? config4.config.build.imageSize ?? "1536x1024";
|
|
472165
472819
|
const imageRatio = imageRatioForSize(imageSize2);
|
|
472166
|
-
const needsComposer = includeCompose && mode !== "agent" && sourceBeats.some((beat) => !existsSync33(
|
|
472820
|
+
const needsComposer = includeCompose && mode !== "agent" && sourceBeats.some((beat) => !existsSync33(join30(projectDir, `compositions/scene-${beat.id}.html`)));
|
|
472167
472821
|
const resolved = await resolvePlanProviders({
|
|
472168
472822
|
projectDir,
|
|
472169
472823
|
config: config4,
|
|
@@ -472267,7 +472921,11 @@ async function createBuildPlan(opts) {
|
|
|
472267
472921
|
reference: videoReference,
|
|
472268
472922
|
projectDir,
|
|
472269
472923
|
force: opts.force,
|
|
472270
|
-
cost:
|
|
472924
|
+
cost: resolved.video.resolved === "seedance" || resolved.video.resolved === "fal" ? estimateSeedanceVideoCostUsd({
|
|
472925
|
+
durationSec: normalizeVideoDuration(beat.duration),
|
|
472926
|
+
resolution: "720p",
|
|
472927
|
+
aspectRatio: "16:9"
|
|
472928
|
+
}) : VIDEO_COST_USD,
|
|
472271
472929
|
active: includeAssets
|
|
472272
472930
|
}) : null;
|
|
472273
472931
|
const music = musicCue && !opts.skipMusic ? assetPlan({
|
|
@@ -472284,7 +472942,7 @@ async function createBuildPlan(opts) {
|
|
|
472284
472942
|
active: includeAssets
|
|
472285
472943
|
}) : null;
|
|
472286
472944
|
const compositionPath = `compositions/scene-${beat.id}.html`;
|
|
472287
|
-
const compositionExists = existsSync33(
|
|
472945
|
+
const compositionExists = existsSync33(join30(projectDir, compositionPath));
|
|
472288
472946
|
for (const asset of [narration, backdrop, video, music]) {
|
|
472289
472947
|
if (!asset) continue;
|
|
472290
472948
|
if (asset.referenceError) {
|
|
@@ -472351,7 +473009,7 @@ async function createBuildPlan(opts) {
|
|
|
472351
473009
|
}
|
|
472352
473010
|
}
|
|
472353
473011
|
const validationOk = !validationIssues.some((issue) => issue.severity === "error");
|
|
472354
|
-
if (!existsSync33(
|
|
473012
|
+
if (!existsSync33(join30(projectDir, config4.config.composition.entry))) {
|
|
472355
473013
|
missing.add("root-composition");
|
|
472356
473014
|
if (validationOk) retryWith.push(`vibe build ${projectDir} --stage sync --json`);
|
|
472357
473015
|
}
|
|
@@ -472378,6 +473036,21 @@ async function createBuildPlan(opts) {
|
|
|
472378
473036
|
retryWith.push(skipCommand);
|
|
472379
473037
|
}
|
|
472380
473038
|
}
|
|
473039
|
+
if (validationOk && includeAssets && !opts.skipVideo) {
|
|
473040
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
473041
|
+
for (const beat of sourceBeats) {
|
|
473042
|
+
for (const name of beatCharacterNames(beat.cues)) referenced.add(name);
|
|
473043
|
+
}
|
|
473044
|
+
if (referenced.size > 0) {
|
|
473045
|
+
const toGenerate = resolveCharacters(parsed.frontmatter).filter(
|
|
473046
|
+
(c2) => referenced.has(c2.name) && c2.prompt && (opts.force || !existsSync33(join30(projectDir, `assets/character-${c2.name}.png`)))
|
|
473047
|
+
);
|
|
473048
|
+
if (toGenerate.length > 0) {
|
|
473049
|
+
estimatedCostUsd += toGenerate.length * backdropCostUsd(opts.imageQuality ?? "hd");
|
|
473050
|
+
missing.add("assets");
|
|
473051
|
+
}
|
|
473052
|
+
}
|
|
473053
|
+
}
|
|
472381
473054
|
return finalizeBuildPlan({
|
|
472382
473055
|
projectDir,
|
|
472383
473056
|
config: config4,
|
|
@@ -472483,8 +473156,8 @@ function assetPlan(opts) {
|
|
|
472483
473156
|
reason: ready ? "referenced-asset" : "invalid-reference"
|
|
472484
473157
|
};
|
|
472485
473158
|
}
|
|
472486
|
-
const canonicalExists = existsSync33(
|
|
472487
|
-
const cacheHit = opts.cache ? existsSync33(
|
|
473159
|
+
const canonicalExists = existsSync33(join30(opts.projectDir, opts.path));
|
|
473160
|
+
const cacheHit = opts.cache ? existsSync33(join30(opts.projectDir, opts.cache.path)) : false;
|
|
472488
473161
|
const freshness = assetFreshnessFromMetadata({
|
|
472489
473162
|
projectDir: opts.projectDir,
|
|
472490
473163
|
kind: opts.kind,
|
|
@@ -472681,7 +473354,7 @@ async function firstConfiguredComposer(projectDir) {
|
|
|
472681
473354
|
}
|
|
472682
473355
|
function firstExisting2(projectDir, paths) {
|
|
472683
473356
|
for (const path14 of paths) {
|
|
472684
|
-
if (existsSync33(
|
|
473357
|
+
if (existsSync33(join30(projectDir, path14))) return path14;
|
|
472685
473358
|
}
|
|
472686
473359
|
return null;
|
|
472687
473360
|
}
|
|
@@ -472722,12 +473395,12 @@ function unique3(items) {
|
|
|
472722
473395
|
return [...new Set(items.filter((item) => item.length > 0))];
|
|
472723
473396
|
}
|
|
472724
473397
|
function loadPlanEnv(projectDir) {
|
|
472725
|
-
(0, import_dotenv2.config)({ path:
|
|
473398
|
+
(0, import_dotenv2.config)({ path: join30(projectDir, ".env"), quiet: true });
|
|
472726
473399
|
(0, import_dotenv2.config)({ path: resolve29(process.cwd(), ".env"), quiet: true });
|
|
472727
473400
|
let dir = process.cwd();
|
|
472728
473401
|
while (dir !== dirname17(dir)) {
|
|
472729
|
-
if (existsSync33(
|
|
472730
|
-
(0, import_dotenv2.config)({ path:
|
|
473402
|
+
if (existsSync33(join30(dir, "pnpm-workspace.yaml"))) {
|
|
473403
|
+
(0, import_dotenv2.config)({ path: join30(dir, ".env"), quiet: true });
|
|
472731
473404
|
return;
|
|
472732
473405
|
}
|
|
472733
473406
|
dir = dirname17(dir);
|
|
@@ -472742,6 +473415,7 @@ var init_build_plan = __esm({
|
|
|
472742
473415
|
init_schema();
|
|
472743
473416
|
init_build_asset_reference();
|
|
472744
473417
|
init_build_cache();
|
|
473418
|
+
init_dist();
|
|
472745
473419
|
init_build_asset_metadata();
|
|
472746
473420
|
init_build_backdrop_prompt();
|
|
472747
473421
|
init_composer_resolve();
|
|
@@ -473074,9 +473748,9 @@ __export(scene_build_exports, {
|
|
|
473074
473748
|
executeSceneBuild: () => executeSceneBuild,
|
|
473075
473749
|
resolveSceneBuildMode: () => resolveSceneBuildMode
|
|
473076
473750
|
});
|
|
473077
|
-
import { existsSync as existsSync35 } from "node:fs";
|
|
473751
|
+
import { existsSync as existsSync35, readFileSync as readFileSync12 } from "node:fs";
|
|
473078
473752
|
import { copyFile as copyFile4, mkdir as mkdir13, readFile as readFile18, writeFile as writeFile20 } from "node:fs/promises";
|
|
473079
|
-
import { dirname as dirname18, join as
|
|
473753
|
+
import { dirname as dirname18, join as join31, resolve as resolve33 } from "node:path";
|
|
473080
473754
|
async function executeSceneBuild(opts) {
|
|
473081
473755
|
const startedAt = Date.now();
|
|
473082
473756
|
const projectDir = resolve33(opts.projectDir);
|
|
@@ -473088,7 +473762,7 @@ async function executeSceneBuild(opts) {
|
|
|
473088
473762
|
const warnings = [];
|
|
473089
473763
|
const retryWith = [];
|
|
473090
473764
|
let sceneRepair = skippedSceneRepairSummary();
|
|
473091
|
-
const storyboardPath =
|
|
473765
|
+
const storyboardPath = join31(projectDir, "STORYBOARD.md");
|
|
473092
473766
|
const buildPlan = await createBuildPlan({
|
|
473093
473767
|
projectDir,
|
|
473094
473768
|
stage: selectedStage,
|
|
@@ -473241,8 +473915,32 @@ async function executeSceneBuild(opts) {
|
|
|
473241
473915
|
const voice = opts.voice ?? parsed.frontmatter?.voice;
|
|
473242
473916
|
let beatOutcomes = collectExistingBeatOutcomes(parsed.beats, projectDir);
|
|
473243
473917
|
let pendingJobs = [];
|
|
473918
|
+
let characterCostUsd = 0;
|
|
473244
473919
|
if (shouldRunStage(selectedStage, "assets")) {
|
|
473245
473920
|
onProgress({ type: "phase-start", phase: "primitives" });
|
|
473921
|
+
const characterPaths = /* @__PURE__ */ new Map();
|
|
473922
|
+
if (!(opts.skipVideo ?? false)) {
|
|
473923
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
473924
|
+
for (const beat of activeBeats) {
|
|
473925
|
+
for (const name of beatCharacterNames(beat.cues)) referenced.add(name);
|
|
473926
|
+
}
|
|
473927
|
+
if (referenced.size > 0) {
|
|
473928
|
+
const charResult = await buildCharacters(
|
|
473929
|
+
resolveCharacters(parsed.frontmatter).filter((c2) => referenced.has(c2.name)),
|
|
473930
|
+
{
|
|
473931
|
+
projectDir,
|
|
473932
|
+
imageProvider,
|
|
473933
|
+
imageSize: opts.imageSize ?? "1536x1024",
|
|
473934
|
+
imageQuality: opts.imageQuality ?? "hd",
|
|
473935
|
+
force: opts.force ?? false,
|
|
473936
|
+
onProgress
|
|
473937
|
+
}
|
|
473938
|
+
);
|
|
473939
|
+
for (const [name, path14] of charResult.paths) characterPaths.set(name, path14);
|
|
473940
|
+
characterCostUsd = charResult.costUsd;
|
|
473941
|
+
warnings.push(...charResult.failures);
|
|
473942
|
+
}
|
|
473943
|
+
}
|
|
473246
473944
|
const primitiveResults = await mapWithConcurrency(
|
|
473247
473945
|
activeBeats,
|
|
473248
473946
|
BEAT_PRIMITIVES_CONCURRENCY,
|
|
@@ -473260,7 +473958,8 @@ async function executeSceneBuild(opts) {
|
|
|
473260
473958
|
skipVideo: opts.skipVideo ?? false,
|
|
473261
473959
|
skipMusic: opts.skipMusic ?? false,
|
|
473262
473960
|
force: opts.force ?? false,
|
|
473263
|
-
onProgress
|
|
473961
|
+
onProgress,
|
|
473962
|
+
characterPaths
|
|
473264
473963
|
})
|
|
473265
473964
|
);
|
|
473266
473965
|
beatOutcomes = primitiveResults.map((result) => result.outcome);
|
|
@@ -473269,10 +473968,7 @@ async function executeSceneBuild(opts) {
|
|
|
473269
473968
|
(beat) => beat.narrationStatus === "failed" || beat.backdropStatus === "failed" || beat.videoStatus === "failed" || beat.musicStatus === "failed"
|
|
473270
473969
|
);
|
|
473271
473970
|
stageReports.assets.status = assetFailed ? "failed" : pendingJobs.length > 0 ? "pending-jobs" : "done";
|
|
473272
|
-
stageReports.assets.costUsd = estimateActualAssetCost(
|
|
473273
|
-
beatOutcomes,
|
|
473274
|
-
opts.imageQuality ?? "hd"
|
|
473275
|
-
);
|
|
473971
|
+
stageReports.assets.costUsd = estimateActualAssetCost(beatOutcomes, opts.imageQuality ?? "hd") + characterCostUsd;
|
|
473276
473972
|
stageReports.assets.retryWith = pendingJobs.map(
|
|
473277
473973
|
(job) => `vibe status job ${job.id} --project ${projectDir} --json`
|
|
473278
473974
|
);
|
|
@@ -473348,9 +474044,9 @@ async function executeSceneBuild(opts) {
|
|
|
473348
474044
|
let composeData;
|
|
473349
474045
|
if (shouldRunStage(selectedStage, "compose")) {
|
|
473350
474046
|
if (mode === "agent") {
|
|
473351
|
-
const compositionsDir =
|
|
474047
|
+
const compositionsDir = join31(projectDir, "compositions");
|
|
473352
474048
|
const missingBeats = activeBeats.filter(
|
|
473353
|
-
(b2) => !existsSync35(
|
|
474049
|
+
(b2) => !existsSync35(join31(compositionsDir, `scene-${b2.id}.html`))
|
|
473354
474050
|
);
|
|
473355
474051
|
if (missingBeats.length > 0) {
|
|
473356
474052
|
const plan = await getComposePrompts({ projectDir, beatId: opts.beatId });
|
|
@@ -473437,6 +474133,18 @@ async function executeSceneBuild(opts) {
|
|
|
473437
474133
|
stageReports.compose.status = "skipped";
|
|
473438
474134
|
}
|
|
473439
474135
|
if (stageReports.compose.status === "done") {
|
|
474136
|
+
for (const beat of activeBeats) {
|
|
474137
|
+
const videoRel = `assets/video-${beat.id}.mp4`;
|
|
474138
|
+
const compositionAbs = join31(projectDir, "compositions", `scene-${beat.id}.html`);
|
|
474139
|
+
if (!existsSync35(join31(projectDir, videoRel)) || !existsSync35(compositionAbs)) continue;
|
|
474140
|
+
const html = readFileSync12(compositionAbs, "utf-8");
|
|
474141
|
+
if (!html.includes(videoRel)) {
|
|
474142
|
+
warnings.push(
|
|
474143
|
+
`Beat "${beat.id}" has a generated clip (${videoRel}) but its composition does not reference it, so the clip will not appear. Recompose the beat.`
|
|
474144
|
+
);
|
|
474145
|
+
retryWith.push(`vibe build ${projectDir} --beat ${beat.id} --stage compose --force --json`);
|
|
474146
|
+
}
|
|
474147
|
+
}
|
|
473440
474148
|
const repair = await runBuildSceneRepair(projectDir, "compose", false);
|
|
473441
474149
|
sceneRepair = mergeSceneRepairSummaries(sceneRepair, repair);
|
|
473442
474150
|
applySceneRepairToStage(stageReports.compose, repair);
|
|
@@ -473486,7 +474194,7 @@ async function executeSceneBuild(opts) {
|
|
|
473486
474194
|
});
|
|
473487
474195
|
}
|
|
473488
474196
|
if (shouldRunStage(selectedStage, "sync")) {
|
|
473489
|
-
if (!existsSync35(
|
|
474197
|
+
if (!existsSync35(join31(projectDir, "index.html"))) {
|
|
473490
474198
|
await scaffoldSceneProject({
|
|
473491
474199
|
dir: projectDir,
|
|
473492
474200
|
name: projectDir.split(/[\\/]/).filter(Boolean).pop(),
|
|
@@ -473745,7 +474453,7 @@ async function dispatchNarration(beat, ctx) {
|
|
|
473745
474453
|
return {
|
|
473746
474454
|
status: "cached",
|
|
473747
474455
|
path: existingRel,
|
|
473748
|
-
durationSec: await safeAudioDuration(
|
|
474456
|
+
durationSec: await safeAudioDuration(join31(ctx.projectDir, existingRel)),
|
|
473749
474457
|
provider: metadata?.provider,
|
|
473750
474458
|
cachePath: metadata?.cachePath,
|
|
473751
474459
|
cacheKey: metadata?.cacheKey,
|
|
@@ -473769,9 +474477,9 @@ async function dispatchNarration(beat, ctx) {
|
|
|
473769
474477
|
voice,
|
|
473770
474478
|
ext: resolution.audioExtension
|
|
473771
474479
|
});
|
|
473772
|
-
const cacheAbs =
|
|
474480
|
+
const cacheAbs = join31(ctx.projectDir, cache.path);
|
|
473773
474481
|
const rel = `assets/narration-${beat.id}.${resolution.audioExtension}`;
|
|
473774
|
-
const abs =
|
|
474482
|
+
const abs = join31(ctx.projectDir, rel);
|
|
473775
474483
|
if (existingRel && !ctx.force && isFreshCanonicalAsset({
|
|
473776
474484
|
projectDir: ctx.projectDir,
|
|
473777
474485
|
kind: "narration",
|
|
@@ -473785,7 +474493,7 @@ async function dispatchNarration(beat, ctx) {
|
|
|
473785
474493
|
return {
|
|
473786
474494
|
status: "cached",
|
|
473787
474495
|
path: existingRel,
|
|
473788
|
-
durationSec: await safeAudioDuration(
|
|
474496
|
+
durationSec: await safeAudioDuration(join31(ctx.projectDir, existingRel)),
|
|
473789
474497
|
provider: resolution.provider,
|
|
473790
474498
|
cachePath: cache.path,
|
|
473791
474499
|
cacheKey: cache.key,
|
|
@@ -473857,6 +474565,120 @@ async function dispatchNarration(beat, ctx) {
|
|
|
473857
474565
|
freshness: "fresh"
|
|
473858
474566
|
};
|
|
473859
474567
|
}
|
|
474568
|
+
function characterSheetPrompt(name, description) {
|
|
474569
|
+
return [
|
|
474570
|
+
`Character turnaround reference sheet of an original fictional character named ${name}: ${description}.`,
|
|
474571
|
+
"Show three full-body views side by side on one clean canvas \u2014 front view, side profile, and back view \u2014",
|
|
474572
|
+
"with identical outfit, hairstyle, hair color, and body proportions across all three views.",
|
|
474573
|
+
"Plain light-grey studio background, even neutral lighting, no props.",
|
|
474574
|
+
"Photorealistic digital character, professional concept-art character sheet layout."
|
|
474575
|
+
].join(" ");
|
|
474576
|
+
}
|
|
474577
|
+
async function buildCharacters(characters, ctx) {
|
|
474578
|
+
const paths = /* @__PURE__ */ new Map();
|
|
474579
|
+
const failures = [];
|
|
474580
|
+
let costUsd = 0;
|
|
474581
|
+
const size = ctx.imageSize ?? "1536x1024";
|
|
474582
|
+
for (const character of characters) {
|
|
474583
|
+
if (character.imagePath) {
|
|
474584
|
+
if (existsSync35(join31(ctx.projectDir, character.imagePath))) {
|
|
474585
|
+
paths.set(character.name, character.imagePath);
|
|
474586
|
+
ctx.onProgress({ type: "character-cached", name: character.name, path: character.imagePath });
|
|
474587
|
+
} else {
|
|
474588
|
+
const error = `character "${character.name}" image not found: ${character.imagePath}`;
|
|
474589
|
+
failures.push(error);
|
|
474590
|
+
ctx.onProgress({ type: "character-failed", name: character.name, error });
|
|
474591
|
+
}
|
|
474592
|
+
continue;
|
|
474593
|
+
}
|
|
474594
|
+
if (!character.prompt) continue;
|
|
474595
|
+
const prompt3 = characterSheetPrompt(character.name, character.prompt);
|
|
474596
|
+
const rel = `assets/character-${character.name}.png`;
|
|
474597
|
+
const abs = join31(ctx.projectDir, rel);
|
|
474598
|
+
const metadataOptions = { quality: ctx.imageQuality, size };
|
|
474599
|
+
const cache = characterCacheDescriptor({
|
|
474600
|
+
name: character.name,
|
|
474601
|
+
cue: prompt3,
|
|
474602
|
+
provider: ctx.imageProvider,
|
|
474603
|
+
quality: ctx.imageQuality,
|
|
474604
|
+
size
|
|
474605
|
+
});
|
|
474606
|
+
if (existsSync35(abs) && !ctx.force) {
|
|
474607
|
+
const metadata = readAssetMetadata(ctx.projectDir, "character", character.name);
|
|
474608
|
+
if (!metadata || isFreshCanonicalAsset({
|
|
474609
|
+
projectDir: ctx.projectDir,
|
|
474610
|
+
kind: "character",
|
|
474611
|
+
beatId: character.name,
|
|
474612
|
+
cue: prompt3,
|
|
474613
|
+
provider: ctx.imageProvider,
|
|
474614
|
+
options: metadataOptions,
|
|
474615
|
+
cacheKey: cache.key
|
|
474616
|
+
})) {
|
|
474617
|
+
paths.set(character.name, rel);
|
|
474618
|
+
ctx.onProgress({ type: "character-cached", name: character.name, path: rel });
|
|
474619
|
+
continue;
|
|
474620
|
+
}
|
|
474621
|
+
}
|
|
474622
|
+
const cacheAbs = join31(ctx.projectDir, cache.path);
|
|
474623
|
+
if (existsSync35(cacheAbs) && !ctx.force) {
|
|
474624
|
+
await mkdir13(dirname18(abs), { recursive: true });
|
|
474625
|
+
await copyFile4(cacheAbs, abs);
|
|
474626
|
+
await writeAssetMetadata({
|
|
474627
|
+
projectDir: ctx.projectDir,
|
|
474628
|
+
kind: "character",
|
|
474629
|
+
beatId: character.name,
|
|
474630
|
+
cue: prompt3,
|
|
474631
|
+
provider: ctx.imageProvider,
|
|
474632
|
+
options: metadataOptions,
|
|
474633
|
+
cacheKey: cache.key,
|
|
474634
|
+
canonicalPath: rel,
|
|
474635
|
+
cachePath: cache.path
|
|
474636
|
+
});
|
|
474637
|
+
paths.set(character.name, rel);
|
|
474638
|
+
ctx.onProgress({ type: "character-cached", name: character.name, path: rel });
|
|
474639
|
+
continue;
|
|
474640
|
+
}
|
|
474641
|
+
const generated = await generateBackdropImage(
|
|
474642
|
+
prompt3,
|
|
474643
|
+
{
|
|
474644
|
+
projectDir: ctx.projectDir,
|
|
474645
|
+
imageProvider: ctx.imageProvider,
|
|
474646
|
+
imageSize: size,
|
|
474647
|
+
imageQuality: ctx.imageQuality
|
|
474648
|
+
},
|
|
474649
|
+
imageRatioForSize(size)
|
|
474650
|
+
);
|
|
474651
|
+
if (!generated.success) {
|
|
474652
|
+
failures.push(`character "${character.name}": ${generated.error}`);
|
|
474653
|
+
ctx.onProgress({ type: "character-failed", name: character.name, error: generated.error });
|
|
474654
|
+
continue;
|
|
474655
|
+
}
|
|
474656
|
+
await mkdir13(dirname18(abs), { recursive: true });
|
|
474657
|
+
await writeFile20(abs, generated.buffer);
|
|
474658
|
+
await mkdir13(dirname18(cacheAbs), { recursive: true });
|
|
474659
|
+
await writeFile20(cacheAbs, generated.buffer);
|
|
474660
|
+
await writeAssetMetadata({
|
|
474661
|
+
projectDir: ctx.projectDir,
|
|
474662
|
+
kind: "character",
|
|
474663
|
+
beatId: character.name,
|
|
474664
|
+
cue: prompt3,
|
|
474665
|
+
provider: ctx.imageProvider,
|
|
474666
|
+
options: metadataOptions,
|
|
474667
|
+
cacheKey: cache.key,
|
|
474668
|
+
canonicalPath: rel,
|
|
474669
|
+
cachePath: cache.path
|
|
474670
|
+
});
|
|
474671
|
+
costUsd += backdropCostUsd(ctx.imageQuality);
|
|
474672
|
+
paths.set(character.name, rel);
|
|
474673
|
+
ctx.onProgress({
|
|
474674
|
+
type: "character-generated",
|
|
474675
|
+
name: character.name,
|
|
474676
|
+
path: rel,
|
|
474677
|
+
provider: ctx.imageProvider
|
|
474678
|
+
});
|
|
474679
|
+
}
|
|
474680
|
+
return { paths, costUsd: Number(costUsd.toFixed(2)), failures };
|
|
474681
|
+
}
|
|
473860
474682
|
async function dispatchBackdrop(beat, ctx) {
|
|
473861
474683
|
const reference = assetReferenceForBeat(ctx.projectDir, "backdrop", beat);
|
|
473862
474684
|
if (reference) return referencePrimitiveOutcome("backdrop", beat, ctx, reference);
|
|
@@ -473864,7 +474686,7 @@ async function dispatchBackdrop(beat, ctx) {
|
|
|
473864
474686
|
if (!cue) return { status: "no-cue" };
|
|
473865
474687
|
const prompt3 = augmentBackdropPrompt(cue);
|
|
473866
474688
|
const rel = `assets/backdrop-${beat.id}.png`;
|
|
473867
|
-
const abs =
|
|
474689
|
+
const abs = join31(ctx.projectDir, rel);
|
|
473868
474690
|
const size = ctx.imageSize ?? "1536x1024";
|
|
473869
474691
|
const ratio = imageRatioForSize(size);
|
|
473870
474692
|
const metadataOptions = { quality: ctx.imageQuality, size, ratio };
|
|
@@ -473900,7 +474722,7 @@ async function dispatchBackdrop(beat, ctx) {
|
|
|
473900
474722
|
};
|
|
473901
474723
|
}
|
|
473902
474724
|
}
|
|
473903
|
-
const cacheAbs =
|
|
474725
|
+
const cacheAbs = join31(ctx.projectDir, cache.path);
|
|
473904
474726
|
if (existsSync35(cacheAbs) && !ctx.force) {
|
|
473905
474727
|
await mkdir13(dirname18(abs), { recursive: true });
|
|
473906
474728
|
await copyFile4(cacheAbs, abs);
|
|
@@ -474026,13 +474848,16 @@ async function dispatchVideo(beat, ctx) {
|
|
|
474026
474848
|
if (reference) return referencePrimitiveOutcome("video", beat, ctx, reference);
|
|
474027
474849
|
const prompt3 = stringOrUndefined4(beat.cues?.video);
|
|
474028
474850
|
if (!prompt3) return { status: "no-cue" };
|
|
474851
|
+
const characterRefsRel = beatCharacterNames(beat.cues).map((name) => ctx.characterPaths?.get(name)).filter((p2) => typeof p2 === "string");
|
|
474852
|
+
const characterRefsAbs = characterRefsRel.map((p2) => join31(ctx.projectDir, p2));
|
|
474029
474853
|
const rel = `assets/video-${beat.id}.mp4`;
|
|
474030
|
-
const abs =
|
|
474854
|
+
const abs = join31(ctx.projectDir, rel);
|
|
474031
474855
|
const cache = videoCacheDescriptor({
|
|
474032
474856
|
beatId: beat.id,
|
|
474033
474857
|
cue: prompt3,
|
|
474034
474858
|
provider: ctx.videoProvider,
|
|
474035
|
-
duration: normalizeVideoDuration(beat.duration)
|
|
474859
|
+
duration: normalizeVideoDuration(beat.duration),
|
|
474860
|
+
characters: characterRefsRel
|
|
474036
474861
|
});
|
|
474037
474862
|
const metadataPath = assetMetadataPath("video", beat.id);
|
|
474038
474863
|
if (existsSync35(abs) && !ctx.force) {
|
|
@@ -474058,7 +474883,7 @@ async function dispatchVideo(beat, ctx) {
|
|
|
474058
474883
|
};
|
|
474059
474884
|
}
|
|
474060
474885
|
}
|
|
474061
|
-
const cacheAbs =
|
|
474886
|
+
const cacheAbs = join31(ctx.projectDir, cache.path);
|
|
474062
474887
|
if (existsSync35(cacheAbs) && !ctx.force) {
|
|
474063
474888
|
await mkdir13(dirname18(abs), { recursive: true });
|
|
474064
474889
|
await copyFile4(cacheAbs, abs);
|
|
@@ -474092,6 +474917,7 @@ async function dispatchVideo(beat, ctx) {
|
|
|
474092
474917
|
ratio: "16:9",
|
|
474093
474918
|
output: abs,
|
|
474094
474919
|
wait: false,
|
|
474920
|
+
refImages: characterRefsAbs.length > 0 ? characterRefsAbs : void 0,
|
|
474095
474921
|
apiKey: await apiKeyForVideoProvider(ctx.videoProvider, ctx.projectDir)
|
|
474096
474922
|
});
|
|
474097
474923
|
if (!result.success || !result.taskId) {
|
|
@@ -474167,7 +474993,7 @@ async function dispatchMusic(beat, ctx) {
|
|
|
474167
474993
|
const prompt3 = stringOrUndefined4(beat.cues?.music);
|
|
474168
474994
|
if (!prompt3) return { status: "no-cue" };
|
|
474169
474995
|
const rel = `assets/music-${beat.id}.mp3`;
|
|
474170
|
-
const abs =
|
|
474996
|
+
const abs = join31(ctx.projectDir, rel);
|
|
474171
474997
|
const duration = normalizeMusicDuration(beat.duration);
|
|
474172
474998
|
const cache = musicCacheDescriptor({
|
|
474173
474999
|
beatId: beat.id,
|
|
@@ -474200,7 +475026,7 @@ async function dispatchMusic(beat, ctx) {
|
|
|
474200
475026
|
};
|
|
474201
475027
|
}
|
|
474202
475028
|
}
|
|
474203
|
-
const cacheAbs =
|
|
475029
|
+
const cacheAbs = join31(ctx.projectDir, cache.path);
|
|
474204
475030
|
if (existsSync35(cacheAbs) && !ctx.force) {
|
|
474205
475031
|
await mkdir13(dirname18(abs), { recursive: true });
|
|
474206
475032
|
await copyFile4(cacheAbs, abs);
|
|
@@ -474311,12 +475137,12 @@ async function dispatchMusic(beat, ctx) {
|
|
|
474311
475137
|
};
|
|
474312
475138
|
}
|
|
474313
475139
|
function loadSceneBuildEnv(projectDir) {
|
|
474314
|
-
(0, import_dotenv3.config)({ path:
|
|
475140
|
+
(0, import_dotenv3.config)({ path: join31(projectDir, ".env"), quiet: true });
|
|
474315
475141
|
(0, import_dotenv3.config)({ path: resolve33(process.cwd(), ".env"), quiet: true });
|
|
474316
475142
|
let dir = process.cwd();
|
|
474317
475143
|
while (dir !== dirname18(dir)) {
|
|
474318
|
-
if (existsSync35(
|
|
474319
|
-
(0, import_dotenv3.config)({ path:
|
|
475144
|
+
if (existsSync35(join31(dir, "pnpm-workspace.yaml"))) {
|
|
475145
|
+
(0, import_dotenv3.config)({ path: join31(dir, ".env"), quiet: true });
|
|
474320
475146
|
return;
|
|
474321
475147
|
}
|
|
474322
475148
|
dir = dirname18(dir);
|
|
@@ -474460,7 +475286,13 @@ function estimateActualAssetCost(outcomes, imageQuality) {
|
|
|
474460
475286
|
for (const outcome of outcomes) {
|
|
474461
475287
|
if (outcome.narrationStatus === "generated") cost += 0.05;
|
|
474462
475288
|
if (outcome.backdropStatus === "generated") cost += backdropCostUsd(imageQuality);
|
|
474463
|
-
if (outcome.videoStatus === "generated" || outcome.videoStatus === "pending")
|
|
475289
|
+
if (outcome.videoStatus === "generated" || outcome.videoStatus === "pending") {
|
|
475290
|
+
cost += outcome.videoProvider === "seedance" || outcome.videoProvider === "fal" ? estimateSeedanceVideoCostUsd({
|
|
475291
|
+
durationSec: normalizeVideoDuration(outcome.sceneDurationSec),
|
|
475292
|
+
resolution: "720p",
|
|
475293
|
+
aspectRatio: "16:9"
|
|
475294
|
+
}) : 5;
|
|
475295
|
+
}
|
|
474464
475296
|
if (outcome.musicStatus === "generated" || outcome.musicStatus === "pending") cost += 0.5;
|
|
474465
475297
|
}
|
|
474466
475298
|
return Number(cost.toFixed(2));
|
|
@@ -474525,7 +475357,7 @@ function mergeBeatOutcomes(base, updates) {
|
|
|
474525
475357
|
}
|
|
474526
475358
|
function firstExisting3(projectDir, relPaths) {
|
|
474527
475359
|
for (const rel of relPaths) {
|
|
474528
|
-
if (existsSync35(
|
|
475360
|
+
if (existsSync35(join31(projectDir, rel))) return rel;
|
|
474529
475361
|
}
|
|
474530
475362
|
return null;
|
|
474531
475363
|
}
|
|
@@ -474556,7 +475388,7 @@ async function apiKeyForVideoProvider(provider, projectDir) {
|
|
|
474556
475388
|
return getApiKeyFromConfig(providerKey, { cwd: projectDir });
|
|
474557
475389
|
}
|
|
474558
475390
|
async function finalizeBuildResult(projectDir, startedAt, result) {
|
|
474559
|
-
const reportPath =
|
|
475391
|
+
const reportPath = join31(projectDir, "build-report.json");
|
|
474560
475392
|
if (result.stageReports) {
|
|
474561
475393
|
for (const report of Object.values(result.stageReports)) {
|
|
474562
475394
|
if (report.status === "pending") report.status = "skipped";
|
|
@@ -474715,7 +475547,7 @@ function normalizeReportDuration(value) {
|
|
|
474715
475547
|
}
|
|
474716
475548
|
function buildReportComposition(projectDir, result, beatId) {
|
|
474717
475549
|
const path14 = `compositions/scene-${beatId}.html`;
|
|
474718
|
-
const exists = existsSync35(
|
|
475550
|
+
const exists = existsSync35(join31(projectDir, path14));
|
|
474719
475551
|
const written = composeWrittenEntry(result, beatId);
|
|
474720
475552
|
if (written) {
|
|
474721
475553
|
return {
|
|
@@ -474772,7 +475604,7 @@ function summarizeBuildBeats(projectDir, beats) {
|
|
|
474772
475604
|
let compositionsReady = 0;
|
|
474773
475605
|
for (const beat of beats) {
|
|
474774
475606
|
if (beatAssetsReady(beat)) assetsReady += 1;
|
|
474775
|
-
const compositionPath =
|
|
475607
|
+
const compositionPath = join31(projectDir, "compositions", `scene-${beat.beatId}.html`);
|
|
474776
475608
|
if (existsSync35(compositionPath)) {
|
|
474777
475609
|
compositionsReady += 1;
|
|
474778
475610
|
} else {
|
|
@@ -475428,7 +476260,7 @@ var init_silence_cut = __esm({
|
|
|
475428
476260
|
// ../cli/src/commands/_shared/edit/jump-cut.ts
|
|
475429
476261
|
import { existsSync as existsSync38 } from "node:fs";
|
|
475430
476262
|
import { readFile as readFile21, writeFile as writeFile22, mkdir as mkdir14 } from "node:fs/promises";
|
|
475431
|
-
import { join as
|
|
476263
|
+
import { join as join33 } from "node:path";
|
|
475432
476264
|
async function transcribeWithWords(audioPath, apiKey, language) {
|
|
475433
476265
|
const audioBuffer = await readFile21(audioPath);
|
|
475434
476266
|
const audioBlob = new Blob([audioBuffer]);
|
|
@@ -475508,7 +476340,7 @@ async function executeJumpCut(options) {
|
|
|
475508
476340
|
try {
|
|
475509
476341
|
const tmpDir = `/tmp/vibe_jumpcut_${Date.now()}`;
|
|
475510
476342
|
await mkdir14(tmpDir, { recursive: true });
|
|
475511
|
-
const audioPath =
|
|
476343
|
+
const audioPath = join33(tmpDir, "audio.wav");
|
|
475512
476344
|
try {
|
|
475513
476345
|
await execSafe(
|
|
475514
476346
|
"ffmpeg",
|
|
@@ -475562,7 +476394,7 @@ async function executeJumpCut(options) {
|
|
|
475562
476394
|
const segmentPaths = [];
|
|
475563
476395
|
for (let i2 = 0; i2 < segments.length; i2++) {
|
|
475564
476396
|
const seg = segments[i2];
|
|
475565
|
-
const segPath =
|
|
476397
|
+
const segPath = join33(tmpDir, `seg-${i2.toString().padStart(4, "0")}.ts`);
|
|
475566
476398
|
const duration = seg.end - seg.start;
|
|
475567
476399
|
await execSafe(
|
|
475568
476400
|
"ffmpeg",
|
|
@@ -475585,7 +476417,7 @@ async function executeJumpCut(options) {
|
|
|
475585
476417
|
segmentPaths.push(segPath);
|
|
475586
476418
|
}
|
|
475587
476419
|
const concatList = segmentPaths.map((p2) => `file '${p2}'`).join("\n");
|
|
475588
|
-
const listPath =
|
|
476420
|
+
const listPath = join33(tmpDir, "concat.txt");
|
|
475589
476421
|
await writeFile22(listPath, concatList);
|
|
475590
476422
|
await execSafe(
|
|
475591
476423
|
"ffmpeg",
|
|
@@ -475693,7 +476525,7 @@ __export(remotion_exports, {
|
|
|
475693
476525
|
});
|
|
475694
476526
|
import { writeFile as writeFile23, mkdir as mkdir15, rm as rm3, copyFile as copyFile5 } from "node:fs/promises";
|
|
475695
476527
|
import { existsSync as existsSync39 } from "node:fs";
|
|
475696
|
-
import { join as
|
|
476528
|
+
import { join as join34 } from "node:path";
|
|
475697
476529
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
475698
476530
|
import { createHash as createHash7 } from "node:crypto";
|
|
475699
476531
|
async function ensureRemotionInstalled() {
|
|
@@ -475712,7 +476544,7 @@ async function ensureRemotionInstalled() {
|
|
|
475712
476544
|
}
|
|
475713
476545
|
}
|
|
475714
476546
|
async function scaffoldRemotionProject(componentCode, componentName, opts) {
|
|
475715
|
-
const dir =
|
|
476547
|
+
const dir = join34(tmpdir3(), `vibe_motion_${Date.now()}`);
|
|
475716
476548
|
await mkdir15(dir, { recursive: true });
|
|
475717
476549
|
const deps = {
|
|
475718
476550
|
remotion: REMOTION_VERSION,
|
|
@@ -475731,7 +476563,7 @@ async function scaffoldRemotionProject(componentCode, componentName, opts) {
|
|
|
475731
476563
|
dependencies: deps
|
|
475732
476564
|
};
|
|
475733
476565
|
const packageJsonStr = JSON.stringify(packageJson, null, 2);
|
|
475734
|
-
await writeFile23(
|
|
476566
|
+
await writeFile23(join34(dir, "package.json"), packageJsonStr);
|
|
475735
476567
|
const tsconfig = {
|
|
475736
476568
|
compilerOptions: {
|
|
475737
476569
|
target: "ES2020",
|
|
@@ -475743,8 +476575,8 @@ async function scaffoldRemotionProject(componentCode, componentName, opts) {
|
|
|
475743
476575
|
skipLibCheck: true
|
|
475744
476576
|
}
|
|
475745
476577
|
};
|
|
475746
|
-
await writeFile23(
|
|
475747
|
-
await writeFile23(
|
|
476578
|
+
await writeFile23(join34(dir, "tsconfig.json"), JSON.stringify(tsconfig, null, 2));
|
|
476579
|
+
await writeFile23(join34(dir, "Component.tsx"), componentCode);
|
|
475748
476580
|
const rootCode = `import { registerRoot, Composition } from "remotion";
|
|
475749
476581
|
import { ${componentName} } from "./Component";
|
|
475750
476582
|
|
|
@@ -475763,14 +476595,14 @@ const Root = () => {
|
|
|
475763
476595
|
|
|
475764
476596
|
registerRoot(Root);
|
|
475765
476597
|
`;
|
|
475766
|
-
await writeFile23(
|
|
476598
|
+
await writeFile23(join34(dir, "Root.tsx"), rootCode);
|
|
475767
476599
|
const depsHash = createHash7("md5").update(packageJsonStr).digest("hex").slice(0, 12);
|
|
475768
|
-
const cacheMarker =
|
|
475769
|
-
const cachedModules =
|
|
476600
|
+
const cacheMarker = join34(REMOTION_CACHE_DIR, `.deps-${depsHash}`);
|
|
476601
|
+
const cachedModules = join34(REMOTION_CACHE_DIR, "node_modules");
|
|
475770
476602
|
if (existsSync39(cacheMarker) && existsSync39(cachedModules)) {
|
|
475771
476603
|
const { symlink } = await import("node:fs/promises");
|
|
475772
476604
|
try {
|
|
475773
|
-
await symlink(cachedModules,
|
|
476605
|
+
await symlink(cachedModules, join34(dir, "node_modules"), "dir");
|
|
475774
476606
|
} catch {
|
|
475775
476607
|
await this_npmInstall(dir);
|
|
475776
476608
|
}
|
|
@@ -475778,12 +476610,12 @@ registerRoot(Root);
|
|
|
475778
476610
|
await this_npmInstall(dir);
|
|
475779
476611
|
try {
|
|
475780
476612
|
await mkdir15(REMOTION_CACHE_DIR, { recursive: true });
|
|
475781
|
-
await writeFile23(
|
|
475782
|
-
if (existsSync39(
|
|
476613
|
+
await writeFile23(join34(REMOTION_CACHE_DIR, "package.json"), packageJsonStr);
|
|
476614
|
+
if (existsSync39(join34(dir, "node_modules"))) {
|
|
475783
476615
|
const { rename: rename7, symlink } = await import("node:fs/promises");
|
|
475784
|
-
await rename7(
|
|
476616
|
+
await rename7(join34(dir, "node_modules"), cachedModules).catch(() => {
|
|
475785
476617
|
});
|
|
475786
|
-
await symlink(cachedModules,
|
|
476618
|
+
await symlink(cachedModules, join34(dir, "node_modules"), "dir").catch(() => {
|
|
475787
476619
|
});
|
|
475788
476620
|
await writeFile23(cacheMarker, depsHash);
|
|
475789
476621
|
}
|
|
@@ -475820,7 +476652,7 @@ async function renderMotion(options) {
|
|
|
475820
476652
|
}
|
|
475821
476653
|
);
|
|
475822
476654
|
try {
|
|
475823
|
-
const entryPoint =
|
|
476655
|
+
const entryPoint = join34(dir, "Root.tsx");
|
|
475824
476656
|
const { execFile: execFile3 } = await import("node:child_process");
|
|
475825
476657
|
const { promisify: promisify3 } = await import("node:util");
|
|
475826
476658
|
const execFileAsync3 = promisify3(execFile3);
|
|
@@ -475953,10 +476785,10 @@ async function renderWithEmbeddedImage(options) {
|
|
|
475953
476785
|
}
|
|
475954
476786
|
);
|
|
475955
476787
|
try {
|
|
475956
|
-
const publicDir =
|
|
476788
|
+
const publicDir = join34(dir, "public");
|
|
475957
476789
|
await mkdir15(publicDir, { recursive: true });
|
|
475958
|
-
await copyFile5(options.imagePath,
|
|
475959
|
-
const entryPoint =
|
|
476790
|
+
await copyFile5(options.imagePath, join34(publicDir, options.imageFileName));
|
|
476791
|
+
const entryPoint = join34(dir, "Root.tsx");
|
|
475960
476792
|
const mp4Out = options.outputPath.replace(/\.\w+$/, ".mp4");
|
|
475961
476793
|
const { execFile: execFileImg } = await import("node:child_process");
|
|
475962
476794
|
const { promisify: promisifyImg } = await import("node:util");
|
|
@@ -476017,10 +476849,10 @@ async function renderWithEmbeddedVideo(options) {
|
|
|
476017
476849
|
}
|
|
476018
476850
|
);
|
|
476019
476851
|
try {
|
|
476020
|
-
const publicDir =
|
|
476852
|
+
const publicDir = join34(dir, "public");
|
|
476021
476853
|
await mkdir15(publicDir, { recursive: true });
|
|
476022
|
-
await copyFile5(options.videoPath,
|
|
476023
|
-
const entryPoint =
|
|
476854
|
+
await copyFile5(options.videoPath, join34(publicDir, options.videoFileName));
|
|
476855
|
+
const entryPoint = join34(dir, "Root.tsx");
|
|
476024
476856
|
const mp4VideoOnly = options.outputPath.replace(/\.\w+$/, "_video_only.mp4");
|
|
476025
476857
|
const { execFile: execFileVid } = await import("node:child_process");
|
|
476026
476858
|
const { promisify: promisifyVid } = await import("node:util");
|
|
@@ -476436,14 +477268,14 @@ var init_remotion = __esm({
|
|
|
476436
477268
|
"use strict";
|
|
476437
477269
|
init_exec_safe();
|
|
476438
477270
|
REMOTION_VERSION = "4.0.447";
|
|
476439
|
-
REMOTION_CACHE_DIR =
|
|
477271
|
+
REMOTION_CACHE_DIR = join34(tmpdir3(), "vibe_remotion_cache");
|
|
476440
477272
|
}
|
|
476441
477273
|
});
|
|
476442
477274
|
|
|
476443
477275
|
// ../cli/src/commands/_shared/edit/caption.ts
|
|
476444
477276
|
import { existsSync as existsSync40 } from "node:fs";
|
|
476445
477277
|
import { readFile as readFile22, writeFile as writeFile24, mkdir as mkdir16 } from "node:fs/promises";
|
|
476446
|
-
import { dirname as dirname20, basename as basename9, extname as extname7, join as
|
|
477278
|
+
import { dirname as dirname20, basename as basename9, extname as extname7, join as join35 } from "node:path";
|
|
476447
477279
|
function getCaptionForceStyle(style, fontSize, fontColor, position) {
|
|
476448
477280
|
const alignment = position === "top" ? 8 : position === "center" ? 5 : 2;
|
|
476449
477281
|
const marginV = position === "center" ? 0 : 30;
|
|
@@ -476490,8 +477322,8 @@ async function executeCaption(options) {
|
|
|
476490
477322
|
try {
|
|
476491
477323
|
const tmpDir = `/tmp/vibe_caption_${Date.now()}`;
|
|
476492
477324
|
await mkdir16(tmpDir, { recursive: true });
|
|
476493
|
-
const audioPath =
|
|
476494
|
-
const srtPath =
|
|
477325
|
+
const audioPath = join35(tmpDir, "audio.wav");
|
|
477326
|
+
const srtPath = join35(tmpDir, "captions.srt");
|
|
476495
477327
|
try {
|
|
476496
477328
|
await execSafe(
|
|
476497
477329
|
"ffmpeg",
|
|
@@ -476560,7 +477392,7 @@ async function executeCaption(options) {
|
|
|
476560
477392
|
const remotionErr = await ensureRemotionInstalled2();
|
|
476561
477393
|
if (remotionErr) {
|
|
476562
477394
|
const outputDir2 = dirname20(outputPath);
|
|
476563
|
-
const outputSrtPath2 =
|
|
477395
|
+
const outputSrtPath2 = join35(
|
|
476564
477396
|
outputDir2,
|
|
476565
477397
|
basename9(outputPath, extname7(outputPath)) + ".srt"
|
|
476566
477398
|
);
|
|
@@ -476599,7 +477431,7 @@ SRT saved to: ${outputSrtPath2}` };
|
|
|
476599
477431
|
});
|
|
476600
477432
|
if (!renderResult.success) {
|
|
476601
477433
|
const outputDir2 = dirname20(outputPath);
|
|
476602
|
-
const outputSrtPath2 =
|
|
477434
|
+
const outputSrtPath2 = join35(
|
|
476603
477435
|
outputDir2,
|
|
476604
477436
|
basename9(outputPath, extname7(outputPath)) + ".srt"
|
|
476605
477437
|
);
|
|
@@ -476612,7 +477444,7 @@ SRT saved to: ${outputSrtPath2}`
|
|
|
476612
477444
|
}
|
|
476613
477445
|
}
|
|
476614
477446
|
const outputDir = dirname20(outputPath);
|
|
476615
|
-
const outputSrtPath =
|
|
477447
|
+
const outputSrtPath = join35(
|
|
476616
477448
|
outputDir,
|
|
476617
477449
|
basename9(outputPath, extname7(outputPath)) + ".srt"
|
|
476618
477450
|
);
|
|
@@ -484580,10 +485412,18 @@ Examples:
|
|
|
484580
485412
|
options.ratio = "16:9";
|
|
484581
485413
|
}
|
|
484582
485414
|
if (options.dryRun) {
|
|
485415
|
+
const costUsd = provider === "seedance" || provider === "fal" ? estimateSeedanceVideoCostUsd({
|
|
485416
|
+
durationSec: Number(options.duration) || 5,
|
|
485417
|
+
resolution: options.resolution,
|
|
485418
|
+
aspectRatio: options.ratio,
|
|
485419
|
+
fast: options.seedanceModel === "fast",
|
|
485420
|
+
hasVideoReference: Boolean(options.refVideos)
|
|
485421
|
+
}) : void 0;
|
|
484583
485422
|
outputSuccess({
|
|
484584
485423
|
command: "generate video",
|
|
484585
485424
|
startedAt,
|
|
484586
485425
|
dryRun: true,
|
|
485426
|
+
costUsd,
|
|
484587
485427
|
data: {
|
|
484588
485428
|
params: {
|
|
484589
485429
|
prompt: prompt3,
|
|
@@ -487033,6 +487873,9 @@ function clean(text) {
|
|
|
487033
487873
|
function humanise(id) {
|
|
487034
487874
|
return id.split(/[-_]+/).filter(Boolean).map((w2) => w2.charAt(0).toUpperCase() + w2.slice(1)).join(" ");
|
|
487035
487875
|
}
|
|
487876
|
+
function sceneCompositionId(beatId) {
|
|
487877
|
+
return `scene-${beatId}`;
|
|
487878
|
+
}
|
|
487036
487879
|
function slugifySceneName(name) {
|
|
487037
487880
|
const normalised = name.normalize("NFKD").replace(/[̀-ͯ]/g, "");
|
|
487038
487881
|
const slug = normalised.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
@@ -487070,10 +487913,16 @@ function fitKineticFontSize(words) {
|
|
|
487070
487913
|
function kenBurnsTween(scope, dur, endScale = 1.08) {
|
|
487071
487914
|
return `tl.fromTo('${scope} .backdrop', { scale: 1.0 }, { scale: ${endScale}, duration: ${dur.toFixed(2)}, ease: 'none' }, 0);`;
|
|
487072
487915
|
}
|
|
487916
|
+
function backdropMotionTweens(scope, dur, hasImage, endScale = 1.08) {
|
|
487917
|
+
const sweep = hasImage ? "" : `
|
|
487918
|
+
tl.fromTo('${scope} .ambient-sweep', { xPercent: -75, opacity: 0.18 }, { xPercent: 75, opacity: 0.62, duration: ${dur.toFixed(2)}, ease: 'sine.inOut' }, 0);`;
|
|
487919
|
+
return `${kenBurnsTween(scope, dur, endScale)}${sweep}`;
|
|
487920
|
+
}
|
|
487073
487921
|
function buildPreset(input3) {
|
|
487074
487922
|
const id = input3.id;
|
|
487075
487923
|
const scope = `[data-composition-id="${id}"]`;
|
|
487076
|
-
const
|
|
487924
|
+
const displayId = input3.beatId ?? id;
|
|
487925
|
+
const headline = clean(input3.headline) || humanise(displayId);
|
|
487077
487926
|
const subhead = clean(input3.subhead);
|
|
487078
487927
|
const kicker = clean(input3.kicker);
|
|
487079
487928
|
const dur = input3.duration;
|
|
@@ -487096,8 +487945,17 @@ function buildPreset(input3) {
|
|
|
487096
487945
|
position: absolute;
|
|
487097
487946
|
inset: 0;
|
|
487098
487947
|
background: radial-gradient(ellipse at center, #1a1a2e 0%, #000 70%);
|
|
487948
|
+
overflow: hidden;
|
|
487949
|
+
}
|
|
487950
|
+
${scope} .ambient-sweep {
|
|
487951
|
+
position: absolute;
|
|
487952
|
+
inset: -22%;
|
|
487953
|
+
display: block;
|
|
487954
|
+
background: linear-gradient(115deg, rgba(255,255,255,0) 20%, rgba(0,201,255,0.34) 48%, rgba(142,45,226,0.26) 58%, rgba(255,255,255,0) 78%);
|
|
487955
|
+
filter: blur(12px);
|
|
487956
|
+
transform: rotate(8deg);
|
|
487099
487957
|
}`;
|
|
487100
|
-
const backdropMarkup = `<div class="backdrop"></div>`;
|
|
487958
|
+
const backdropMarkup = hasImage ? `<div class="backdrop"></div>` : `<div class="backdrop"><div class="ambient-sweep"></div></div>`;
|
|
487101
487959
|
switch (input3.preset) {
|
|
487102
487960
|
case "simple": {
|
|
487103
487961
|
const transcript = input3.transcript;
|
|
@@ -487129,7 +487987,7 @@ function buildPreset(input3) {
|
|
|
487129
487987
|
body: `${backdropMarkup}
|
|
487130
487988
|
<div class="caption" id="caption">${captionInner}</div>`,
|
|
487131
487989
|
timeline: `${crossfadeTweens(scope, dur)}
|
|
487132
|
-
${
|
|
487990
|
+
${backdropMotionTweens(scope, dur, hasImage)}
|
|
487133
487991
|
${captionTween}`
|
|
487134
487992
|
};
|
|
487135
487993
|
}
|
|
@@ -487168,12 +488026,12 @@ function buildPreset(input3) {
|
|
|
487168
488026
|
// scene's own fade-in handles the visual transition. Backdrop
|
|
487169
488027
|
// Ken-Burns fills what used to be 80% dead static frame.
|
|
487170
488028
|
timeline: `${crossfadeTweens(scope, dur)}
|
|
487171
|
-
${
|
|
488029
|
+
${backdropMotionTweens(scope, dur, hasImage)}
|
|
487172
488030
|
tl.from('${scope} #headline', { opacity: 0, scale: 0.92, duration: 0.55, ease: 'power3.out' }, 0.05);`
|
|
487173
488031
|
};
|
|
487174
488032
|
}
|
|
487175
488033
|
case "explainer": {
|
|
487176
|
-
const k2 = kicker || humanise(
|
|
488034
|
+
const k2 = kicker || humanise(displayId).toUpperCase();
|
|
487177
488035
|
const sub = subhead || "";
|
|
487178
488036
|
const transcript = input3.transcript;
|
|
487179
488037
|
const useWordSync = !!(transcript && transcript.length > 0 && sub);
|
|
@@ -487215,7 +488073,7 @@ function buildPreset(input3) {
|
|
|
487215
488073
|
<div class="subtitle" id="subtitle">${subtitleInner}</div>` : ""}
|
|
487216
488074
|
</div>`,
|
|
487217
488075
|
timeline: `${crossfadeTweens(scope, dur)}
|
|
487218
|
-
${
|
|
488076
|
+
${backdropMotionTweens(scope, dur, hasImage)}
|
|
487219
488077
|
tl.from('${scope} #kicker', { opacity: 0, y: 16, duration: 0.4, ease: 'power2.out' }, 0.1);
|
|
487220
488078
|
tl.from('${scope} #title', { opacity: 0, y: 60, duration: 0.7, ease: 'power3.out' }, 0.25);
|
|
487221
488079
|
${subtitleTween}`
|
|
@@ -487256,12 +488114,12 @@ function buildPreset(input3) {
|
|
|
487256
488114
|
body: `${backdropMarkup}
|
|
487257
488115
|
<div class="kinetic">${wordSpans}</div>`,
|
|
487258
488116
|
timeline: `${crossfadeTweens(scope, dur)}
|
|
487259
|
-
${
|
|
488117
|
+
${backdropMotionTweens(scope, dur, hasImage)}
|
|
487260
488118
|
${tweens}`
|
|
487261
488119
|
};
|
|
487262
488120
|
}
|
|
487263
488121
|
case "product-shot": {
|
|
487264
|
-
const label = kicker || humanise(
|
|
488122
|
+
const label = kicker || humanise(displayId);
|
|
487265
488123
|
const headlineFontPx = fitFontSize(headline, 72, 40, 50);
|
|
487266
488124
|
return {
|
|
487267
488125
|
css: `${scope} {
|
|
@@ -487295,7 +488153,7 @@ function buildPreset(input3) {
|
|
|
487295
488153
|
<div class="product-headline" id="headline">${esc(headline)}</div>${subhead ? `
|
|
487296
488154
|
<div class="product-sub" id="subhead">${esc(subhead)}</div>` : ""}`,
|
|
487297
488155
|
timeline: `${crossfadeTweens(scope, dur)}
|
|
487298
|
-
|
|
488156
|
+
${backdropMotionTweens(scope, dur, hasImage, 1.12)}
|
|
487299
488157
|
tl.from('${scope} #label', { opacity: 0, x: -30, duration: 0.5, ease: 'power3.out' }, 0.2);
|
|
487300
488158
|
tl.from('${scope} #headline', { opacity: 0, y: 40, duration: 0.6, ease: 'power3.out' }, 0.4);${subhead ? `
|
|
487301
488159
|
tl.from('${scope} #subhead', { opacity: 0, y: 20, duration: 0.5, ease: 'power3.out' }, 0.65);` : ""}`
|
|
@@ -487360,9 +488218,10 @@ function emitSceneHtml(input3) {
|
|
|
487360
488218
|
if (input3.width <= 0 || input3.height <= 0) {
|
|
487361
488219
|
throw new Error(`Invalid canvas dims: ${input3.width}x${input3.height}`);
|
|
487362
488220
|
}
|
|
487363
|
-
const
|
|
488221
|
+
const beatId = input3.id;
|
|
488222
|
+
const id = sceneCompositionId(beatId);
|
|
487364
488223
|
const dur = Number(input3.duration.toFixed(3));
|
|
487365
|
-
const parts = buildPreset({ ...input3, id, duration: dur });
|
|
488224
|
+
const parts = buildPreset({ ...input3, id, beatId, duration: dur });
|
|
487366
488225
|
const audioBlock = input3.audioPath ? `
|
|
487367
488226
|
<audio
|
|
487368
488227
|
id="narration"
|
|
@@ -487378,7 +488237,7 @@ function emitSceneHtml(input3) {
|
|
|
487378
488237
|
${lottieLayer.markup}` : "";
|
|
487379
488238
|
const lottieScript = lottieLayer ? `
|
|
487380
488239
|
${lottieLayer.script}` : "";
|
|
487381
|
-
return `<template id="
|
|
488240
|
+
return `<template id="${id}-template">
|
|
487382
488241
|
<div data-composition-id="${id}" data-start="0" data-duration="${dur}" data-width="${input3.width}" data-height="${input3.height}">
|
|
487383
488242
|
<style>
|
|
487384
488243
|
${parts.css}
|
|
@@ -487414,8 +488273,9 @@ function buildClipReference(opts) {
|
|
|
487414
488273
|
const duration = Number(opts.duration.toFixed(3));
|
|
487415
488274
|
const track = opts.trackIndex ?? 1;
|
|
487416
488275
|
const src = opts.src ?? `compositions/scene-${opts.id}.html`;
|
|
488276
|
+
const compositionId = sceneCompositionId(opts.id);
|
|
487417
488277
|
const zIndex = Math.max(1, 1e6 - Math.floor(start * 1e3));
|
|
487418
|
-
return `<div class="clip" data-composition-id="${esc(
|
|
488278
|
+
return `<div class="clip" data-composition-id="${esc(compositionId)}" data-composition-src="${esc(src)}" data-start="${start}" data-duration="${duration}" data-track-index="${track}" style="z-index: ${zIndex};"></div>`;
|
|
487419
488279
|
}
|
|
487420
488280
|
function insertClipIntoRoot(rootHtml, clip) {
|
|
487421
488281
|
const clipDiv = buildClipReference(clip);
|
|
@@ -487459,9 +488319,9 @@ init_agent_host_detect();
|
|
|
487459
488319
|
// ../cli/src/commands/_shared/install-skill.ts
|
|
487460
488320
|
init_bundle_content();
|
|
487461
488321
|
init_bundle();
|
|
487462
|
-
import { mkdir as mkdir8, writeFile as
|
|
488322
|
+
import { mkdir as mkdir8, writeFile as writeFile12 } from "node:fs/promises";
|
|
487463
488323
|
import { existsSync as existsSync21 } from "node:fs";
|
|
487464
|
-
import { dirname as dirname12, join as join21, relative as relative5, resolve as
|
|
488324
|
+
import { dirname as dirname12, join as join21, relative as relative5, resolve as resolve16 } from "node:path";
|
|
487465
488325
|
function universalFiles() {
|
|
487466
488326
|
return [
|
|
487467
488327
|
{ relPath: "SKILL.md", content: SKILL_MD },
|
|
@@ -487511,7 +488371,7 @@ function selectHostFiles(hosts) {
|
|
|
487511
488371
|
return out;
|
|
487512
488372
|
}
|
|
487513
488373
|
async function installHyperframesSkill(opts) {
|
|
487514
|
-
const projectDir =
|
|
488374
|
+
const projectDir = resolve16(opts.projectDir);
|
|
487515
488375
|
const force = opts.force ?? false;
|
|
487516
488376
|
const dryRun = opts.dryRun ?? false;
|
|
487517
488377
|
const files = [...universalFiles(), ...selectHostFiles(opts.hosts)];
|
|
@@ -487536,7 +488396,7 @@ async function installHyperframesSkill(opts) {
|
|
|
487536
488396
|
continue;
|
|
487537
488397
|
}
|
|
487538
488398
|
await mkdir8(dirname12(absPath), { recursive: true });
|
|
487539
|
-
await
|
|
488399
|
+
await writeFile12(absPath, file.content, "utf-8");
|
|
487540
488400
|
actions.push({ path: file.relPath, status: "wrote", bytes });
|
|
487541
488401
|
}
|
|
487542
488402
|
return {
|
|
@@ -487561,10 +488421,10 @@ init_scene_lint();
|
|
|
487561
488421
|
init_storyboard_parse();
|
|
487562
488422
|
init_root_sync();
|
|
487563
488423
|
import { existsSync as existsSync26 } from "node:fs";
|
|
487564
|
-
import { mkdir as mkdir10, readFile as readFile11, writeFile as
|
|
487565
|
-
import { join as join26, resolve as
|
|
488424
|
+
import { mkdir as mkdir10, readFile as readFile11, writeFile as writeFile15 } from "node:fs/promises";
|
|
488425
|
+
import { join as join26, resolve as resolve20 } from "node:path";
|
|
487566
488426
|
async function executeSceneSubmit(opts) {
|
|
487567
|
-
const projectDir =
|
|
488427
|
+
const projectDir = resolve20(opts.projectDir);
|
|
487568
488428
|
const beatId = opts.beatId.trim();
|
|
487569
488429
|
const scenePath = `compositions/scene-${beatId}.html`;
|
|
487570
488430
|
const base = {
|
|
@@ -487656,7 +488516,7 @@ async function executeSceneSubmit(opts) {
|
|
|
487656
488516
|
}
|
|
487657
488517
|
const absPath = join26(projectDir, scenePath);
|
|
487658
488518
|
await mkdir10(join26(projectDir, "compositions"), { recursive: true });
|
|
487659
|
-
await
|
|
488519
|
+
await writeFile15(absPath, html.endsWith("\n") ? html : `${html}
|
|
487660
488520
|
`, "utf-8");
|
|
487661
488521
|
return {
|
|
487662
488522
|
...base,
|
|
@@ -487671,6 +488531,8 @@ async function executeSceneSubmit(opts) {
|
|
|
487671
488531
|
|
|
487672
488532
|
// ../cli/src/commands/scene.ts
|
|
487673
488533
|
init_scene_repair();
|
|
488534
|
+
init_root_sync();
|
|
488535
|
+
init_storyboard_edit();
|
|
487674
488536
|
function validateDuration(value) {
|
|
487675
488537
|
const n2 = parseFloat(value);
|
|
487676
488538
|
if (!Number.isFinite(n2) || n2 <= 0 || n2 > 3600) {
|
|
@@ -487973,7 +488835,10 @@ sceneCommand.command("add").description("Add a new scene to a project: AI narrat
|
|
|
487973
488835
|
).option("-d, --duration <sec>", "Explicit scene duration in seconds (overrides narration audio)").option(
|
|
487974
488836
|
"--visuals <prompt>",
|
|
487975
488837
|
"Image prompt \u2014 generates assets/scene-<id>.png via the configured image provider"
|
|
487976
|
-
).option("--headline <text>", "Visible headline (defaults to the humanised scene name)").option("--kicker <text>", "Small label above the headline (explainer / product-shot)").option("--insert-into <path>", "Root composition file to update", "index.html").option("--project <dir>", "Project directory", ".").option(
|
|
488838
|
+
).option("--headline <text>", "Visible headline (defaults to the humanised scene name)").option("--kicker <text>", "Small label above the headline (explainer / product-shot)").option("--insert-into <path>", "Root composition file to update", "index.html").option("--project <dir>", "Project directory", ".").option(
|
|
488839
|
+
"--no-storyboard",
|
|
488840
|
+
"Do not sync STORYBOARD.md; insert this scene directly into the root composition only"
|
|
488841
|
+
).option("--image-provider <name>", "Image provider: gemini, openai", "gemini").option(
|
|
487977
488842
|
"--tts <provider>",
|
|
487978
488843
|
"TTS provider: auto, elevenlabs, openai, kokoro (default auto \u2014 ElevenLabs key > OpenAI key > Kokoro local)",
|
|
487979
488844
|
"auto"
|
|
@@ -488042,6 +488907,7 @@ sceneCommand.command("add").description("Add a new scene to a project: AI narrat
|
|
|
488042
488907
|
kicker: options.kicker,
|
|
488043
488908
|
project: options.project,
|
|
488044
488909
|
insertInto: options.insertInto,
|
|
488910
|
+
syncStoryboard: options.storyboard !== false,
|
|
488045
488911
|
imageProvider: options.imageProvider,
|
|
488046
488912
|
tts,
|
|
488047
488913
|
audio: options.audio,
|
|
@@ -488069,6 +488935,7 @@ sceneCommand.command("add").description("Add a new scene to a project: AI narrat
|
|
|
488069
488935
|
kicker: options.kicker,
|
|
488070
488936
|
projectDir: options.project,
|
|
488071
488937
|
insertInto: options.insertInto,
|
|
488938
|
+
syncStoryboard: options.storyboard !== false,
|
|
488072
488939
|
imageProvider: options.imageProvider,
|
|
488073
488940
|
tts,
|
|
488074
488941
|
voice: options.voice,
|
|
@@ -488108,6 +488975,13 @@ sceneCommand.command("add").description("Add a new scene to a project: AI narrat
|
|
|
488108
488975
|
if (result.audioPath) console.log(source_default.green(" +"), result.audioPath);
|
|
488109
488976
|
if (result.imagePath) console.log(source_default.green(" +"), result.imagePath);
|
|
488110
488977
|
if (result.transcriptPath) console.log(source_default.green(" +"), result.transcriptPath);
|
|
488978
|
+
if (result.storyboardPath && result.storyboardSynced) {
|
|
488979
|
+
console.log(
|
|
488980
|
+
result.storyboardAction === "updated" ? source_default.yellow(" ~") : source_default.green(" +"),
|
|
488981
|
+
result.storyboardPath,
|
|
488982
|
+
source_default.dim(`(${result.storyboardAction})`)
|
|
488983
|
+
);
|
|
488984
|
+
}
|
|
488111
488985
|
console.log(source_default.yellow(" ~"), result.rootPath, source_default.dim("(updated)"));
|
|
488112
488986
|
console.log();
|
|
488113
488987
|
console.log(source_default.bold.cyan("Composition"));
|
|
@@ -488154,6 +489028,21 @@ async function loadVibeProjectConfig(projectDir) {
|
|
|
488154
489028
|
}
|
|
488155
489029
|
};
|
|
488156
489030
|
}
|
|
489031
|
+
function escapeRegExp3(value) {
|
|
489032
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
489033
|
+
}
|
|
489034
|
+
function readClipStart(rootHtml, beatId) {
|
|
489035
|
+
const compositionId = sceneCompositionId(beatId);
|
|
489036
|
+
const match2 = rootHtml.match(
|
|
489037
|
+
new RegExp(
|
|
489038
|
+
`<div\\s+class="clip"[^>]*\\bdata-composition-id="${escapeRegExp3(compositionId)}"[^>]*\\bdata-start="([\\d.]+)"`,
|
|
489039
|
+
"i"
|
|
489040
|
+
)
|
|
489041
|
+
);
|
|
489042
|
+
if (!match2) return void 0;
|
|
489043
|
+
const start = Number.parseFloat(match2[1]);
|
|
489044
|
+
return Number.isFinite(start) ? start : void 0;
|
|
489045
|
+
}
|
|
488157
489046
|
async function resolveNarrationText(value) {
|
|
488158
489047
|
if (!value) return void 0;
|
|
488159
489048
|
const looksLikePath = /\.[a-z]{2,4}$/i.test(value) || value.includes("/") || value.includes("\\");
|
|
@@ -488180,6 +489069,7 @@ async function executeSceneAdd(opts) {
|
|
|
488180
489069
|
const id = slugifySceneName(opts.name);
|
|
488181
489070
|
const sceneRel = `compositions/scene-${id}.html`;
|
|
488182
489071
|
const scenePath = resolve24(projectDir, sceneRel);
|
|
489072
|
+
const storyboardAbsPath = resolve24(projectDir, "STORYBOARD.md");
|
|
488183
489073
|
const errResult = (error) => ({
|
|
488184
489074
|
success: false,
|
|
488185
489075
|
id,
|
|
@@ -488399,6 +489289,27 @@ async function executeSceneAdd(opts) {
|
|
|
488399
489289
|
duration = fallback2;
|
|
488400
489290
|
}
|
|
488401
489291
|
duration = Number(duration.toFixed(2));
|
|
489292
|
+
let storyboardPath;
|
|
489293
|
+
let storyboardSynced = false;
|
|
489294
|
+
let storyboardAction = "skipped";
|
|
489295
|
+
const shouldSyncStoryboard = opts.syncStoryboard !== false && await pathExists2(storyboardAbsPath);
|
|
489296
|
+
if (shouldSyncStoryboard) {
|
|
489297
|
+
opts.onProgress?.("Syncing STORYBOARD.md...");
|
|
489298
|
+
const before2 = await readFile14(storyboardAbsPath, "utf-8");
|
|
489299
|
+
const synced = upsertStoryboardBeat(before2, {
|
|
489300
|
+
beatId: id,
|
|
489301
|
+
title: opts.headline,
|
|
489302
|
+
duration,
|
|
489303
|
+
narration: narrationText && !opts.skipAudio ? narrationText : void 0,
|
|
489304
|
+
backdrop: opts.visuals && !opts.skipImage ? opts.visuals : void 0
|
|
489305
|
+
});
|
|
489306
|
+
if (synced.markdown !== before2) {
|
|
489307
|
+
await writeFile17(storyboardAbsPath, synced.markdown, "utf-8");
|
|
489308
|
+
}
|
|
489309
|
+
storyboardPath = relative8(process.cwd(), storyboardAbsPath) || storyboardAbsPath;
|
|
489310
|
+
storyboardSynced = true;
|
|
489311
|
+
storyboardAction = synced.action;
|
|
489312
|
+
}
|
|
488402
489313
|
opts.onProgress?.("Emitting scene HTML...");
|
|
488403
489314
|
const sceneHtml = emitSceneHtml({
|
|
488404
489315
|
id,
|
|
@@ -488417,11 +489328,24 @@ async function executeSceneAdd(opts) {
|
|
|
488417
489328
|
await mkdir11(dirname14(scenePath), { recursive: true });
|
|
488418
489329
|
await writeFile17(scenePath, sceneHtml, "utf-8");
|
|
488419
489330
|
opts.onProgress?.("Updating root composition...");
|
|
488420
|
-
|
|
488421
|
-
|
|
488422
|
-
|
|
488423
|
-
|
|
488424
|
-
|
|
489331
|
+
let start = 0;
|
|
489332
|
+
if (storyboardSynced) {
|
|
489333
|
+
const syncPlan = await syncRootComposition({
|
|
489334
|
+
projectDir,
|
|
489335
|
+
rootRel,
|
|
489336
|
+
beats: await loadProjectRootSyncBeats(projectDir)
|
|
489337
|
+
});
|
|
489338
|
+
const blockingIssue = syncPlan.issues.find((issue) => issue.severity === "error");
|
|
489339
|
+
if (blockingIssue) return errResult(blockingIssue.message);
|
|
489340
|
+
const rootHtmlAfterSync = await readFile14(rootPath, "utf-8");
|
|
489341
|
+
start = readClipStart(rootHtmlAfterSync, id) ?? 0;
|
|
489342
|
+
} else {
|
|
489343
|
+
start = nextSceneStart(rootHtmlBefore, SCENE_OVERLAP_SECONDS);
|
|
489344
|
+
const existingClipCount = (rootHtmlBefore.match(/<div\s+class="clip"/g) || []).length;
|
|
489345
|
+
const trackIndex = existingClipCount % 2 + 1;
|
|
489346
|
+
const updated = insertClipIntoRoot(rootHtmlBefore, { id, start, duration, trackIndex });
|
|
489347
|
+
await writeFile17(rootPath, updated, "utf-8");
|
|
489348
|
+
}
|
|
488425
489349
|
const transcriptAbsPath = transcriptRelPath ? resolve24(projectDir, transcriptRelPath) : void 0;
|
|
488426
489350
|
return {
|
|
488427
489351
|
success: true,
|
|
@@ -488434,6 +489358,9 @@ async function executeSceneAdd(opts) {
|
|
|
488434
489358
|
audioPath: audioAbsPath ? relative8(process.cwd(), audioAbsPath) || audioAbsPath : void 0,
|
|
488435
489359
|
imagePath: imageAbsPath ? relative8(process.cwd(), imageAbsPath) || imageAbsPath : void 0,
|
|
488436
489360
|
lottiePath: lottieAbsPath ? relative8(process.cwd(), lottieAbsPath) || lottieAbsPath : void 0,
|
|
489361
|
+
storyboardPath,
|
|
489362
|
+
storyboardSynced,
|
|
489363
|
+
storyboardAction,
|
|
488437
489364
|
transcriptPath: transcriptAbsPath ? relative8(process.cwd(), transcriptAbsPath) || transcriptAbsPath : void 0,
|
|
488438
489365
|
transcriptWordCount
|
|
488439
489366
|
};
|
|
@@ -488731,6 +489658,9 @@ var sceneAddSchema = z2.object({
|
|
|
488731
489658
|
kicker: z2.string().optional().describe("Small label above the headline (used by 'explainer' and 'product-shot' presets)."),
|
|
488732
489659
|
projectDir: z2.string().optional().describe(PROJECT_DIR_DESCRIPTION),
|
|
488733
489660
|
insertInto: z2.string().optional().describe("Root composition file (relative to projectDir). Default 'index.html'."),
|
|
489661
|
+
syncStoryboard: z2.boolean().optional().describe(
|
|
489662
|
+
"Sync STORYBOARD.md when present, then rebuild root refs from it. Default true; set false for root-only insertion."
|
|
489663
|
+
),
|
|
488734
489664
|
imageProvider: z2.enum(["gemini", "openai"]).optional().describe("Image provider for visuals. Default 'gemini'."),
|
|
488735
489665
|
voice: z2.string().optional().describe("ElevenLabs voice id or name."),
|
|
488736
489666
|
skipAudio: z2.boolean().optional().describe("Skip TTS even if narration is provided."),
|
|
@@ -488743,7 +489673,7 @@ var sceneAddTool = defineTool({
|
|
|
488743
489673
|
cost: "low",
|
|
488744
489674
|
title: "Add Scene from Preset",
|
|
488745
489675
|
annotations: { readOnly: false, openWorld: true },
|
|
488746
|
-
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 and
|
|
489676
|
+
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.",
|
|
488747
489677
|
schema: sceneAddSchema,
|
|
488748
489678
|
async execute(args, ctx) {
|
|
488749
489679
|
const projectDir = args.projectDir ? resolve34(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
|
|
@@ -488757,6 +489687,7 @@ var sceneAddTool = defineTool({
|
|
|
488757
489687
|
kicker: args.kicker,
|
|
488758
489688
|
projectDir,
|
|
488759
489689
|
insertInto: args.insertInto,
|
|
489690
|
+
syncStoryboard: args.syncStoryboard,
|
|
488760
489691
|
imageProvider: args.imageProvider,
|
|
488761
489692
|
voice: args.voice,
|
|
488762
489693
|
skipAudio: args.skipAudio,
|
|
@@ -488775,6 +489706,9 @@ var sceneAddTool = defineTool({
|
|
|
488775
489706
|
];
|
|
488776
489707
|
if (result.audioPath) lines.push(` audio: ${result.audioPath}`);
|
|
488777
489708
|
if (result.imagePath) lines.push(` image: ${result.imagePath}`);
|
|
489709
|
+
if (result.storyboardPath && result.storyboardSynced) {
|
|
489710
|
+
lines.push(` story: ${result.storyboardPath} (${result.storyboardAction})`);
|
|
489711
|
+
}
|
|
488778
489712
|
return {
|
|
488779
489713
|
success: true,
|
|
488780
489714
|
data: {
|
|
@@ -488785,7 +489719,10 @@ var sceneAddTool = defineTool({
|
|
|
488785
489719
|
scenePath: result.scenePath,
|
|
488786
489720
|
rootPath: result.rootPath,
|
|
488787
489721
|
audioPath: result.audioPath,
|
|
488788
|
-
imagePath: result.imagePath
|
|
489722
|
+
imagePath: result.imagePath,
|
|
489723
|
+
storyboardPath: result.storyboardPath,
|
|
489724
|
+
storyboardSynced: result.storyboardSynced,
|
|
489725
|
+
storyboardAction: result.storyboardAction
|
|
488789
489726
|
},
|
|
488790
489727
|
humanLines: lines
|
|
488791
489728
|
};
|
|
@@ -490220,7 +491157,7 @@ init_root_sync();
|
|
|
490220
491157
|
init_review_report();
|
|
490221
491158
|
import { existsSync as existsSync56 } from "node:fs";
|
|
490222
491159
|
import { readdir as readdir6, readFile as readFile31, stat as stat5 } from "node:fs/promises";
|
|
490223
|
-
import { basename as basename14, isAbsolute as isAbsolute7, join as
|
|
491160
|
+
import { basename as basename14, isAbsolute as isAbsolute7, join as join37, relative as relative13, resolve as resolve50 } from "node:path";
|
|
490224
491161
|
async function inspectProject(opts) {
|
|
490225
491162
|
const projectDir = resolve50(opts.projectDir);
|
|
490226
491163
|
const issues = [];
|
|
@@ -490249,12 +491186,12 @@ async function inspectProject(opts) {
|
|
|
490249
491186
|
);
|
|
490250
491187
|
}
|
|
490251
491188
|
const coreFiles = {
|
|
490252
|
-
storyboard:
|
|
490253
|
-
design:
|
|
490254
|
-
config:
|
|
490255
|
-
legacyConfig:
|
|
490256
|
-
buildReport:
|
|
490257
|
-
root:
|
|
491189
|
+
storyboard: join37(projectDir, "STORYBOARD.md"),
|
|
491190
|
+
design: join37(projectDir, "DESIGN.md"),
|
|
491191
|
+
config: join37(projectDir, "vibe.config.json"),
|
|
491192
|
+
legacyConfig: join37(projectDir, "vibe.project.yaml"),
|
|
491193
|
+
buildReport: join37(projectDir, "build-report.json"),
|
|
491194
|
+
root: join37(projectDir, "index.html")
|
|
490258
491195
|
};
|
|
490259
491196
|
for (const [name, path14] of Object.entries(coreFiles)) {
|
|
490260
491197
|
checks.files[name] = existsSync56(path14);
|
|
@@ -490338,7 +491275,7 @@ async function inspectProject(opts) {
|
|
|
490338
491275
|
});
|
|
490339
491276
|
retryWith.push(`vibe build ${projectDir} --stage sync --json`);
|
|
490340
491277
|
}
|
|
490341
|
-
const compositionsDir =
|
|
491278
|
+
const compositionsDir = join37(projectDir, "compositions");
|
|
490342
491279
|
const existingComps = existsSync56(compositionsDir) ? new Set(await listHtmlBasenames(compositionsDir)) : /* @__PURE__ */ new Set();
|
|
490343
491280
|
checks.compositions.expected = inspectedBeatIds.length;
|
|
490344
491281
|
for (const beatId of inspectedBeatIds) {
|
|
@@ -490346,12 +491283,12 @@ async function inspectProject(opts) {
|
|
|
490346
491283
|
if (existingComps.has(file)) {
|
|
490347
491284
|
checks.compositions.found++;
|
|
490348
491285
|
} else {
|
|
490349
|
-
checks.compositions.missing.push(
|
|
491286
|
+
checks.compositions.missing.push(join37("compositions", file));
|
|
490350
491287
|
issues.push({
|
|
490351
491288
|
severity: "error",
|
|
490352
491289
|
code: "MISSING_COMPOSITION",
|
|
490353
491290
|
message: `Composition for beat "${beatId}" is missing.`,
|
|
490354
|
-
file:
|
|
491291
|
+
file: join37("compositions", file),
|
|
490355
491292
|
scene: beatId,
|
|
490356
491293
|
beatId,
|
|
490357
491294
|
suggestedFix: "Run `vibe build --stage compose --json`."
|
|
@@ -490413,7 +491350,7 @@ async function inspectProject(opts) {
|
|
|
490413
491350
|
try {
|
|
490414
491351
|
const lint = await runProjectLint({ projectDir });
|
|
490415
491352
|
const lintFiles = opts.beatId ? lint.files.filter(
|
|
490416
|
-
(file) => file.file === "index.html" || file.file ===
|
|
491353
|
+
(file) => file.file === "index.html" || file.file === join37("compositions", `scene-${opts.beatId}.html`)
|
|
490417
491354
|
) : lint.files;
|
|
490418
491355
|
const lintCounts = countLintFindings(lintFiles);
|
|
490419
491356
|
checks.lint = {
|
|
@@ -490449,7 +491386,11 @@ async function inspectProject(opts) {
|
|
|
490449
491386
|
);
|
|
490450
491387
|
}
|
|
490451
491388
|
function makeProjectResult(projectDir, issues, checks, retryWith, beatId) {
|
|
490452
|
-
const
|
|
491389
|
+
const normalizedRetryWith = uniqueRetryWith(retryWith);
|
|
491390
|
+
const normalizedIssues = normalizeReviewIssues(issues, {
|
|
491391
|
+
projectDir,
|
|
491392
|
+
retryWith: normalizedRetryWith
|
|
491393
|
+
});
|
|
490453
491394
|
const status = statusFromIssues(normalizedIssues);
|
|
490454
491395
|
return {
|
|
490455
491396
|
schemaVersion: "1",
|
|
@@ -490461,9 +491402,14 @@ function makeProjectResult(projectDir, issues, checks, retryWith, beatId) {
|
|
|
490461
491402
|
score: scoreIssues(normalizedIssues),
|
|
490462
491403
|
issues: normalizedIssues,
|
|
490463
491404
|
summary: summarizeReviewIssues(normalizedIssues),
|
|
491405
|
+
nextActions: deriveNextReviewActions({
|
|
491406
|
+
issues: normalizedIssues,
|
|
491407
|
+
retryWith: normalizedRetryWith,
|
|
491408
|
+
projectDir
|
|
491409
|
+
}),
|
|
490464
491410
|
sourceReports: projectSourceReports(checks),
|
|
490465
491411
|
checks,
|
|
490466
|
-
retryWith:
|
|
491412
|
+
retryWith: normalizedRetryWith
|
|
490467
491413
|
};
|
|
490468
491414
|
}
|
|
490469
491415
|
function storyboardPlaceholderIssues(storyboard) {
|
|
@@ -490783,7 +491729,7 @@ init_storyboard_parse();
|
|
|
490783
491729
|
init_review_report();
|
|
490784
491730
|
import { existsSync as existsSync57 } from "node:fs";
|
|
490785
491731
|
import { readdir as readdir7, readFile as readFile32, stat as stat6 } from "node:fs/promises";
|
|
490786
|
-
import { basename as basename15, isAbsolute as isAbsolute8, join as
|
|
491732
|
+
import { basename as basename15, isAbsolute as isAbsolute8, join as join38, relative as relative14, resolve as resolve51 } from "node:path";
|
|
490787
491733
|
var VIDEO_EXTENSIONS = /* @__PURE__ */ new Set([".mp4", ".mov", ".webm", ".m4v"]);
|
|
490788
491734
|
var DEFAULT_AI_MODEL = "flash";
|
|
490789
491735
|
var BLACK_FRAME_MIN_DURATION_SEC = 1;
|
|
@@ -491015,6 +491961,8 @@ async function inspectRender(opts) {
|
|
|
491015
491961
|
severity: "error",
|
|
491016
491962
|
code: "RENDER_NOT_FOUND",
|
|
491017
491963
|
message: opts.beatId ? `No rendered video was found for beat "${opts.beatId}". Pass --video or render the beat first.` : "No rendered video was found. Pass --video or render the project first.",
|
|
491964
|
+
beatId: opts.beatId,
|
|
491965
|
+
scene: opts.beatId,
|
|
491018
491966
|
suggestedFix: opts.beatId ? "Run `vibe render <project> --beat <id> --json`." : "Run `vibe build --stage render --json` or `vibe render --json`."
|
|
491019
491967
|
});
|
|
491020
491968
|
retryWith.push(
|
|
@@ -491037,6 +491985,8 @@ async function inspectRender(opts) {
|
|
|
491037
491985
|
code: "EMPTY_RENDER",
|
|
491038
491986
|
message: "Rendered video file is empty.",
|
|
491039
491987
|
file: displayPath(videoPath),
|
|
491988
|
+
beatId: opts.beatId,
|
|
491989
|
+
scene: opts.beatId,
|
|
491040
491990
|
suggestedFix: opts.beatId ? "Render again with `vibe render --beat <id> --json`." : "Render again with `vibe render --json`."
|
|
491041
491991
|
});
|
|
491042
491992
|
retryWith.push(
|
|
@@ -491046,6 +491996,8 @@ async function inspectRender(opts) {
|
|
|
491046
491996
|
const beatTimings = await beatTimingsFromBuildReport(projectDir, opts.beatId);
|
|
491047
491997
|
const expectedDurationSec = beatTimings.length > 0 ? Number(beatTimings.reduce((sum, beat) => sum + beat.sceneDurationSec, 0).toFixed(3)) : await expectedDurationFromBuildReport(projectDir, opts.beatId);
|
|
491048
491998
|
if (expectedDurationSec !== void 0) checks.expectedDurationSec = expectedDurationSec;
|
|
491999
|
+
const expectedAudio = await renderExpectsAudio(projectDir, opts.beatId);
|
|
492000
|
+
checks.expectedAudio = expectedAudio;
|
|
491049
492001
|
if (!commandExists("ffprobe")) {
|
|
491050
492002
|
issues.push({
|
|
491051
492003
|
severity: "error",
|
|
@@ -491071,7 +492023,7 @@ async function inspectRender(opts) {
|
|
|
491071
492023
|
file: displayPath(videoPath)
|
|
491072
492024
|
});
|
|
491073
492025
|
}
|
|
491074
|
-
if (!audioStream) {
|
|
492026
|
+
if (!audioStream && expectedAudio) {
|
|
491075
492027
|
issues.push({
|
|
491076
492028
|
severity: "warning",
|
|
491077
492029
|
code: "NO_AUDIO_STREAM",
|
|
@@ -491276,8 +492228,86 @@ async function inspectRender(opts) {
|
|
|
491276
492228
|
);
|
|
491277
492229
|
return maybeWriteRenderReport(projectDir, opts, result);
|
|
491278
492230
|
}
|
|
492231
|
+
async function renderExpectsAudio(projectDir, beatId) {
|
|
492232
|
+
const root2 = resolve51(projectDir);
|
|
492233
|
+
const rootHtml = await readTextIfExists(join38(root2, "index.html"));
|
|
492234
|
+
if (rootHtml && rootHtmlExpectsAudio(rootHtml, beatId)) return true;
|
|
492235
|
+
const buildReport = await readJsonIfExists(join38(root2, "build-report.json"));
|
|
492236
|
+
if (buildReportExpectsAudio(buildReport, beatId)) return true;
|
|
492237
|
+
const storyboard = await readTextIfExists(join38(root2, "STORYBOARD.md"));
|
|
492238
|
+
if (!storyboard) return false;
|
|
492239
|
+
try {
|
|
492240
|
+
const parsed = parseStoryboard(storyboard);
|
|
492241
|
+
const beats = beatId ? parsed.beats.filter((beat) => beat.id === beatId) : parsed.beats;
|
|
492242
|
+
return beats.some(
|
|
492243
|
+
(beat) => [
|
|
492244
|
+
`assets/narration-${beat.id}.mp3`,
|
|
492245
|
+
`assets/narration-${beat.id}.wav`,
|
|
492246
|
+
`assets/music-${beat.id}.mp3`,
|
|
492247
|
+
`assets/music-${beat.id}.wav`
|
|
492248
|
+
].some((asset) => existsSync57(join38(root2, asset)))
|
|
492249
|
+
);
|
|
492250
|
+
} catch {
|
|
492251
|
+
return false;
|
|
492252
|
+
}
|
|
492253
|
+
}
|
|
492254
|
+
function rootHtmlExpectsAudio(html, beatId) {
|
|
492255
|
+
const audioTags = html.match(/<audio\b[^>]*>/gi) ?? [];
|
|
492256
|
+
if (!beatId) return audioTags.length > 0;
|
|
492257
|
+
const escaped = escapeRegExp4(beatId);
|
|
492258
|
+
const beatAudioRe = new RegExp(
|
|
492259
|
+
`(id="(?:narration|music)-${escaped}"|src="[^"]*(?:narration|music)-${escaped}\\.(?:mp3|wav)")`,
|
|
492260
|
+
"i"
|
|
492261
|
+
);
|
|
492262
|
+
return audioTags.some((tag) => beatAudioRe.test(tag));
|
|
492263
|
+
}
|
|
492264
|
+
function buildReportExpectsAudio(report, beatId) {
|
|
492265
|
+
if (!report || typeof report !== "object") return false;
|
|
492266
|
+
const beats = Array.isArray(report.beats) ? report.beats ?? [] : [];
|
|
492267
|
+
const selected = beatId === void 0 ? beats : beats.filter((beat) => {
|
|
492268
|
+
if (!beat || typeof beat !== "object") return false;
|
|
492269
|
+
return beat.id === beatId;
|
|
492270
|
+
});
|
|
492271
|
+
return selected.some((beat) => beatReportExpectsAudio(beat));
|
|
492272
|
+
}
|
|
492273
|
+
function beatReportExpectsAudio(beat) {
|
|
492274
|
+
if (!beat || typeof beat !== "object") return false;
|
|
492275
|
+
const record = beat;
|
|
492276
|
+
if (typeof record.narrationPath === "string" && record.narrationPath.length > 0) return true;
|
|
492277
|
+
if (typeof record.musicPath === "string" && record.musicPath.length > 0) return true;
|
|
492278
|
+
if (parseOptionalNumber2(record.narrationDurationSec) !== void 0) return true;
|
|
492279
|
+
const narration = record.narration;
|
|
492280
|
+
if (narration && typeof narration === "object") {
|
|
492281
|
+
const n2 = narration;
|
|
492282
|
+
if (typeof n2.path === "string" && n2.path.length > 0) return true;
|
|
492283
|
+
if (parseOptionalNumber2(n2.durationSec) !== void 0) return true;
|
|
492284
|
+
}
|
|
492285
|
+
const music = record.music;
|
|
492286
|
+
if (music && typeof music === "object") {
|
|
492287
|
+
const m2 = music;
|
|
492288
|
+
if (typeof m2.path === "string" && m2.path.length > 0) return true;
|
|
492289
|
+
if (parseOptionalNumber2(m2.durationSec) !== void 0) return true;
|
|
492290
|
+
}
|
|
492291
|
+
return false;
|
|
492292
|
+
}
|
|
492293
|
+
async function readJsonIfExists(path14) {
|
|
492294
|
+
const text = await readTextIfExists(path14);
|
|
492295
|
+
if (!text) return null;
|
|
492296
|
+
try {
|
|
492297
|
+
return JSON.parse(text);
|
|
492298
|
+
} catch {
|
|
492299
|
+
return null;
|
|
492300
|
+
}
|
|
492301
|
+
}
|
|
492302
|
+
function escapeRegExp4(value) {
|
|
492303
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
492304
|
+
}
|
|
491279
492305
|
function makeRenderResult(projectDir, opts, videoPath, issues, checks, retryWith, score) {
|
|
491280
|
-
const
|
|
492306
|
+
const normalizedRetryWith = uniqueRetryWith(retryWith);
|
|
492307
|
+
const normalizedIssues = normalizeReviewIssues(issues, {
|
|
492308
|
+
projectDir,
|
|
492309
|
+
retryWith: normalizedRetryWith
|
|
492310
|
+
});
|
|
491281
492311
|
const status = statusFromIssues(normalizedIssues);
|
|
491282
492312
|
return {
|
|
491283
492313
|
schemaVersion: "1",
|
|
@@ -491290,9 +492320,14 @@ function makeRenderResult(projectDir, opts, videoPath, issues, checks, retryWith
|
|
|
491290
492320
|
score,
|
|
491291
492321
|
issues: normalizedIssues,
|
|
491292
492322
|
summary: summarizeReviewIssues(normalizedIssues),
|
|
492323
|
+
nextActions: deriveNextReviewActions({
|
|
492324
|
+
issues: normalizedIssues,
|
|
492325
|
+
retryWith: normalizedRetryWith,
|
|
492326
|
+
projectDir
|
|
492327
|
+
}),
|
|
491293
492328
|
sourceReports: renderSourceReports(projectDir, videoPath, checks),
|
|
491294
492329
|
checks,
|
|
491295
|
-
retryWith:
|
|
492330
|
+
retryWith: normalizedRetryWith
|
|
491296
492331
|
};
|
|
491297
492332
|
}
|
|
491298
492333
|
async function maybeWriteRenderReport(projectDir, opts, result) {
|
|
@@ -491318,8 +492353,8 @@ async function maybeWriteRenderReport(projectDir, opts, result) {
|
|
|
491318
492353
|
}
|
|
491319
492354
|
function renderSourceReports(projectDir, videoPath, checks) {
|
|
491320
492355
|
const reports = [];
|
|
491321
|
-
if (existsSync57(
|
|
491322
|
-
if (existsSync57(
|
|
492356
|
+
if (existsSync57(join38(projectDir, "build-report.json"))) reports.push("build-report.json");
|
|
492357
|
+
if (existsSync57(join38(projectDir, "render-report.json"))) reports.push("render-report.json");
|
|
491323
492358
|
if (videoPath) reports.push(displayPath(videoPath));
|
|
491324
492359
|
if (checks.durationSec !== void 0 || checks.width !== void 0 || checks.height !== void 0) {
|
|
491325
492360
|
reports.push("ffprobe");
|
|
@@ -491334,7 +492369,7 @@ async function resolveRenderVideoPath(projectDir, explicit, beatId) {
|
|
|
491334
492369
|
const candidate = resolve51(process.cwd(), explicit);
|
|
491335
492370
|
return existsSync57(candidate) ? candidate : null;
|
|
491336
492371
|
}
|
|
491337
|
-
const renderReportPath =
|
|
492372
|
+
const renderReportPath = join38(projectDir, "render-report.json");
|
|
491338
492373
|
if (existsSync57(renderReportPath)) {
|
|
491339
492374
|
try {
|
|
491340
492375
|
const report = JSON.parse(await readFile32(renderReportPath, "utf-8"));
|
|
@@ -491346,7 +492381,7 @@ async function resolveRenderVideoPath(projectDir, explicit, beatId) {
|
|
|
491346
492381
|
} catch {
|
|
491347
492382
|
}
|
|
491348
492383
|
}
|
|
491349
|
-
const reportPath =
|
|
492384
|
+
const reportPath = join38(projectDir, "build-report.json");
|
|
491350
492385
|
if (!beatId && existsSync57(reportPath)) {
|
|
491351
492386
|
try {
|
|
491352
492387
|
const report = JSON.parse(await readFile32(reportPath, "utf-8"));
|
|
@@ -491355,7 +492390,7 @@ async function resolveRenderVideoPath(projectDir, explicit, beatId) {
|
|
|
491355
492390
|
} catch {
|
|
491356
492391
|
}
|
|
491357
492392
|
}
|
|
491358
|
-
const rendersDir =
|
|
492393
|
+
const rendersDir = join38(projectDir, "renders");
|
|
491359
492394
|
if (!existsSync57(rendersDir)) return null;
|
|
491360
492395
|
const entries2 = await readdir7(rendersDir, { withFileTypes: true });
|
|
491361
492396
|
const candidates = [];
|
|
@@ -491364,7 +492399,7 @@ async function resolveRenderVideoPath(projectDir, explicit, beatId) {
|
|
|
491364
492399
|
const ext = entry.name.slice(entry.name.lastIndexOf(".")).toLowerCase();
|
|
491365
492400
|
if (!VIDEO_EXTENSIONS.has(ext)) continue;
|
|
491366
492401
|
if (beatId && !entry.name.includes(sanitizeFileSegment2(beatId))) continue;
|
|
491367
|
-
const full =
|
|
492402
|
+
const full = join38(rendersDir, entry.name);
|
|
491368
492403
|
const info = await stat6(full);
|
|
491369
492404
|
candidates.push({ path: full, mtimeMs: info.mtimeMs });
|
|
491370
492405
|
}
|
|
@@ -491382,11 +492417,11 @@ async function runAiRenderReview(projectDir, videoPath, model) {
|
|
|
491382
492417
|
});
|
|
491383
492418
|
}
|
|
491384
492419
|
function resolveStoryboardPath(projectDir) {
|
|
491385
|
-
const storyboardPath =
|
|
492420
|
+
const storyboardPath = join38(projectDir, "STORYBOARD.md");
|
|
491386
492421
|
return existsSync57(storyboardPath) ? storyboardPath : null;
|
|
491387
492422
|
}
|
|
491388
492423
|
async function expectedDurationFromBuildReport(projectDir, beatId) {
|
|
491389
|
-
const reportPath =
|
|
492424
|
+
const reportPath = join38(projectDir, "build-report.json");
|
|
491390
492425
|
if (!existsSync57(reportPath)) return void 0;
|
|
491391
492426
|
try {
|
|
491392
492427
|
const report = JSON.parse(await readFile32(reportPath, "utf-8"));
|
|
@@ -491401,7 +492436,7 @@ async function expectedDurationFromBuildReport(projectDir, beatId) {
|
|
|
491401
492436
|
}
|
|
491402
492437
|
}
|
|
491403
492438
|
async function beatTimingsFromBuildReport(projectDir, beatId) {
|
|
491404
|
-
const reportPath =
|
|
492439
|
+
const reportPath = join38(projectDir, "build-report.json");
|
|
491405
492440
|
if (!existsSync57(reportPath)) return [];
|
|
491406
492441
|
try {
|
|
491407
492442
|
const report = JSON.parse(await readFile32(reportPath, "utf-8"));
|
|
@@ -491430,17 +492465,17 @@ async function beatTimingsFromBuildReport(projectDir, beatId) {
|
|
|
491430
492465
|
}
|
|
491431
492466
|
async function buildRenderReviewProjectContext(projectDir) {
|
|
491432
492467
|
const parts = [];
|
|
491433
|
-
const storyboard = await readTextIfExists(
|
|
492468
|
+
const storyboard = await readTextIfExists(join38(projectDir, "STORYBOARD.md"));
|
|
491434
492469
|
if (storyboard) {
|
|
491435
492470
|
parts.push(`STORYBOARD.md:
|
|
491436
492471
|
${truncateText(storyboard, 4e3)}`);
|
|
491437
492472
|
parts.push(`Storyboard beat cue summary:
|
|
491438
492473
|
${storyboardBeatCueSummary(storyboard)}`);
|
|
491439
492474
|
}
|
|
491440
|
-
const design = await readTextIfExists(
|
|
492475
|
+
const design = await readTextIfExists(join38(projectDir, "DESIGN.md"));
|
|
491441
492476
|
if (design) parts.push(`DESIGN.md:
|
|
491442
492477
|
${truncateText(design, 4e3)}`);
|
|
491443
|
-
const buildReport = await readTextIfExists(
|
|
492478
|
+
const buildReport = await readTextIfExists(join38(projectDir, "build-report.json"));
|
|
491444
492479
|
if (buildReport) parts.push(`build-report.json:
|
|
491445
492480
|
${truncateText(buildReport, 6e3)}`);
|
|
491446
492481
|
const timings = await beatTimingsFromBuildReport(projectDir);
|
|
@@ -492299,7 +493334,7 @@ init_storyboard_edit();
|
|
|
492299
493334
|
// ../cli/src/commands/_shared/storyboard-revise.ts
|
|
492300
493335
|
import { existsSync as existsSync59 } from "node:fs";
|
|
492301
493336
|
import { readFile as readFile35, writeFile as writeFile42 } from "node:fs/promises";
|
|
492302
|
-
import { join as
|
|
493337
|
+
import { join as join39, resolve as resolve64 } from "node:path";
|
|
492303
493338
|
|
|
492304
493339
|
// ../cli/src/agent/adapters/index.ts
|
|
492305
493340
|
init_openai3();
|
|
@@ -492346,7 +493381,7 @@ init_storyboard_parse();
|
|
|
492346
493381
|
init_storyboard_edit();
|
|
492347
493382
|
async function executeStoryboardRevision(opts) {
|
|
492348
493383
|
const projectDir = resolve64(opts.projectDir);
|
|
492349
|
-
const storyboardPath =
|
|
493384
|
+
const storyboardPath = join39(projectDir, "STORYBOARD.md");
|
|
492350
493385
|
const retryWith = [`vibe storyboard revise ${projectDir} --from "<request>" --dry-run --json`];
|
|
492351
493386
|
if (!existsSync59(storyboardPath)) {
|
|
492352
493387
|
return failureResult({
|
|
@@ -492581,8 +493616,8 @@ function diffChangedBeats(before2, after2) {
|
|
|
492581
493616
|
return ids.filter((id) => JSON.stringify(beforeBeats.get(id) ?? null) !== JSON.stringify(afterBeats.get(id) ?? null));
|
|
492582
493617
|
}
|
|
492583
493618
|
async function readRevisionContext(projectDir) {
|
|
492584
|
-
const designMd = await readOptionalText(
|
|
492585
|
-
const buildReportJson = await readOptionalJsonText(
|
|
493619
|
+
const designMd = await readOptionalText(join39(projectDir, "DESIGN.md"));
|
|
493620
|
+
const buildReportJson = await readOptionalJsonText(join39(projectDir, "build-report.json"));
|
|
492586
493621
|
return { designMd, buildReportJson };
|
|
492587
493622
|
}
|
|
492588
493623
|
async function readOptionalText(path14) {
|
|
@@ -492897,7 +493932,7 @@ var storyboardTools = [
|
|
|
492897
493932
|
// ../cli/src/tools/manifest/remix.ts
|
|
492898
493933
|
import { writeFile as writeFile48 } from "node:fs/promises";
|
|
492899
493934
|
import { tmpdir as tmpdir6 } from "node:os";
|
|
492900
|
-
import { join as
|
|
493935
|
+
import { join as join40 } from "node:path";
|
|
492901
493936
|
import { z as z8 } from "zod";
|
|
492902
493937
|
|
|
492903
493938
|
// ../cli/src/commands/ai-script-pipeline.ts
|
|
@@ -494631,7 +495666,7 @@ var pipelineRunTool = defineTool({
|
|
|
494631
495666
|
let resolvedPath = args.pipelinePath;
|
|
494632
495667
|
let tempPath;
|
|
494633
495668
|
if (args.pipelineYaml) {
|
|
494634
|
-
tempPath =
|
|
495669
|
+
tempPath = join40(tmpdir6(), `vibe-mcp-pipeline-${Date.now()}.yaml`);
|
|
494635
495670
|
await writeFile48(tempPath, args.pipelineYaml, "utf-8");
|
|
494636
495671
|
resolvedPath = tempPath;
|
|
494637
495672
|
}
|
|
@@ -495163,7 +496198,7 @@ init_engine();
|
|
|
495163
496198
|
init_storyboard_parse();
|
|
495164
496199
|
import { readdir as readdir8, readFile as readFile42, stat as stat7 } from "node:fs/promises";
|
|
495165
496200
|
import { existsSync as existsSync65 } from "node:fs";
|
|
495166
|
-
import { join as
|
|
496201
|
+
import { join as join41, resolve as resolve71 } from "node:path";
|
|
495167
496202
|
async function executeProjectList(opts = {}) {
|
|
495168
496203
|
const workspaceDir = resolve71(opts.workspaceDir ?? ".");
|
|
495169
496204
|
if (!existsSync65(workspaceDir)) {
|
|
@@ -495183,11 +496218,11 @@ async function executeProjectList(opts = {}) {
|
|
|
495183
496218
|
if (entry.name === "node_modules") continue;
|
|
495184
496219
|
if (entry.name.startsWith(".")) continue;
|
|
495185
496220
|
if (entry.name.startsWith("_")) {
|
|
495186
|
-
archivedCount += await countProjects(
|
|
496221
|
+
archivedCount += await countProjects(join41(workspaceDir, entry.name));
|
|
495187
496222
|
continue;
|
|
495188
496223
|
}
|
|
495189
|
-
const projectDir =
|
|
495190
|
-
if (!existsSync65(
|
|
496224
|
+
const projectDir = join41(workspaceDir, entry.name);
|
|
496225
|
+
if (!existsSync65(join41(projectDir, "STORYBOARD.md"))) continue;
|
|
495191
496226
|
projects.push(await describeProject(entry.name, projectDir));
|
|
495192
496227
|
}
|
|
495193
496228
|
projects.sort((a2, b2) => b2.updatedAt.localeCompare(a2.updatedAt));
|
|
@@ -495197,7 +496232,7 @@ async function countProjects(dir) {
|
|
|
495197
496232
|
try {
|
|
495198
496233
|
const entries2 = await readdir8(dir, { withFileTypes: true });
|
|
495199
496234
|
return entries2.filter(
|
|
495200
|
-
(e2) => e2.isDirectory() && existsSync65(
|
|
496235
|
+
(e2) => e2.isDirectory() && existsSync65(join41(dir, e2.name, "STORYBOARD.md"))
|
|
495201
496236
|
).length;
|
|
495202
496237
|
} catch {
|
|
495203
496238
|
return 0;
|
|
@@ -495208,7 +496243,7 @@ async function describeProject(name, projectDir) {
|
|
|
495208
496243
|
let storyboardDurationSec = 0;
|
|
495209
496244
|
const timestamps = [];
|
|
495210
496245
|
try {
|
|
495211
|
-
const storyboardPath =
|
|
496246
|
+
const storyboardPath = join41(projectDir, "STORYBOARD.md");
|
|
495212
496247
|
const parsed = parseStoryboard(await readFile42(storyboardPath, "utf-8"));
|
|
495213
496248
|
beats = parsed.beats.length;
|
|
495214
496249
|
storyboardDurationSec = Number(
|
|
@@ -495220,7 +496255,7 @@ async function describeProject(name, projectDir) {
|
|
|
495220
496255
|
let buildStatus;
|
|
495221
496256
|
let buildUpdatedAt;
|
|
495222
496257
|
try {
|
|
495223
|
-
const reportPath =
|
|
496258
|
+
const reportPath = join41(projectDir, "build-report.json");
|
|
495224
496259
|
const report = JSON.parse(await readFile42(reportPath, "utf-8"));
|
|
495225
496260
|
buildStatus = report.status ?? report.phase;
|
|
495226
496261
|
buildUpdatedAt = report.updatedAt;
|
|
@@ -495229,12 +496264,12 @@ async function describeProject(name, projectDir) {
|
|
|
495229
496264
|
}
|
|
495230
496265
|
let latestRender;
|
|
495231
496266
|
try {
|
|
495232
|
-
const rendersDir =
|
|
496267
|
+
const rendersDir = join41(projectDir, "renders");
|
|
495233
496268
|
const files = await readdir8(rendersDir);
|
|
495234
496269
|
let newest;
|
|
495235
496270
|
for (const file of files) {
|
|
495236
496271
|
if (!/\.(mp4|webm|mov)$/i.test(file)) continue;
|
|
495237
|
-
const { mtimeMs } = await stat7(
|
|
496272
|
+
const { mtimeMs } = await stat7(join41(rendersDir, file));
|
|
495238
496273
|
if (!newest || mtimeMs > newest.mtimeMs) newest = { file, mtimeMs };
|
|
495239
496274
|
}
|
|
495240
496275
|
if (newest) {
|
|
@@ -496245,7 +497280,7 @@ var exportTools = [exportVideoTool];
|
|
|
496245
497280
|
|
|
496246
497281
|
// ../cli/src/tools/manifest/agent-only.ts
|
|
496247
497282
|
import { readFile as readFile44, writeFile as writeFile52, readdir as readdir9, stat as stat8, access as access7, unlink as unlink7 } from "node:fs/promises";
|
|
496248
|
-
import { resolve as resolve76, join as
|
|
497283
|
+
import { resolve as resolve76, join as join43, basename as basename21, extname as extname14 } from "node:path";
|
|
496249
497284
|
import { z as z13 } from "zod";
|
|
496250
497285
|
init_engine();
|
|
496251
497286
|
init_exec_safe();
|
|
@@ -496324,7 +497359,7 @@ var fsListTool = defineTool({
|
|
|
496324
497359
|
const results = [];
|
|
496325
497360
|
for (const entry of entries2) {
|
|
496326
497361
|
if (args.pattern && !matchPattern(entry.name, args.pattern)) continue;
|
|
496327
|
-
const fullPath =
|
|
497362
|
+
const fullPath = join43(absPath, entry.name);
|
|
496328
497363
|
const stats = await stat8(fullPath);
|
|
496329
497364
|
if (entry.isDirectory()) {
|
|
496330
497365
|
results.push(`[DIR] ${entry.name}/`);
|
|
@@ -496437,7 +497472,7 @@ var batchImportTool = defineTool({
|
|
|
496437
497472
|
const scanDir = async (dir) => {
|
|
496438
497473
|
const entries2 = await readdir9(dir, { withFileTypes: true });
|
|
496439
497474
|
for (const entry of entries2) {
|
|
496440
|
-
const entryPath =
|
|
497475
|
+
const entryPath = join43(dir, entry.name);
|
|
496441
497476
|
if (entry.isDirectory() && recursive) {
|
|
496442
497477
|
await scanDir(entryPath);
|
|
496443
497478
|
} else if (entry.isFile()) {
|
|
@@ -498507,7 +499542,7 @@ var server2 = new Server(
|
|
|
498507
499542
|
{
|
|
498508
499543
|
name: "vibeframe",
|
|
498509
499544
|
// Stamped with the package version by build.js at bundle time.
|
|
498510
|
-
version: "0.113.
|
|
499545
|
+
version: "0.113.2"
|
|
498511
499546
|
},
|
|
498512
499547
|
{
|
|
498513
499548
|
capabilities: {
|