@vibeframe/mcp-server 0.113.10 → 0.113.11

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.
Files changed (2) hide show
  1. package/dist/index.js +684 -554
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -4757,15 +4757,15 @@ async function loadKokoroRuntime() {
4757
4757
  }
4758
4758
  async function loadKokoroFromWorkspace(baseDir = process.cwd()) {
4759
4759
  try {
4760
- const { readFile: readFile46 } = await import("node:fs/promises");
4761
- const { join: join44, resolve: resolve80 } = await import("node:path");
4760
+ const { readFile: readFile47 } = await import("node:fs/promises");
4761
+ const { join: join45, resolve: resolve80 } = await import("node:path");
4762
4762
  const { pathToFileURL } = await import("node:url");
4763
4763
  const pkgDir = resolve80(baseDir, "node_modules", "kokoro-js");
4764
- const pkg = JSON.parse(await readFile46(join44(pkgDir, "package.json"), "utf-8"));
4764
+ const pkg = JSON.parse(await readFile47(join45(pkgDir, "package.json"), "utf-8"));
4765
4765
  const entry = pkg.exports?.node?.import ?? pkg.exports?.default ?? pkg.module ?? pkg.main;
4766
4766
  if (!entry)
4767
4767
  return null;
4768
- const mod = await import(pathToFileURL(join44(pkgDir, entry)).href);
4768
+ const mod = await import(pathToFileURL(join45(pkgDir, entry)).href);
4769
4769
  return mod.KokoroTTS ?? null;
4770
4770
  } catch {
4771
4771
  return null;
@@ -4776,20 +4776,20 @@ async function loadBundledKokoroRuntime(runtimeDir = process.env.VIBE_KOKORO_RUN
4776
4776
  if (!base)
4777
4777
  return null;
4778
4778
  try {
4779
- const { readFile: readFile46, writeFile: writeFile53, mkdir: mkdir30 } = await import("node:fs/promises");
4780
- const { join: join44, resolve: resolve80 } = await import("node:path");
4779
+ const { readFile: readFile47, writeFile: writeFile53, mkdir: mkdir30 } = await import("node:fs/promises");
4780
+ const { join: join45, resolve: resolve80 } = await import("node:path");
4781
4781
  const { pathToFileURL } = await import("node:url");
4782
4782
  const { homedir: homedir8 } = await import("node:os");
4783
4783
  const transformersDir = resolve80(base, "node_modules", "@huggingface", "transformers");
4784
4784
  const ortDistDir = resolve80(base, "node_modules", "onnxruntime-web", "dist");
4785
- const transformers = await import(pathToFileURL(join44(transformersDir, "dist", "transformers.web.js")).href);
4786
- const cacheRoot = join44(homedir8(), ".cache", "vibeframe", "models");
4785
+ const transformers = await import(pathToFileURL(join45(transformersDir, "dist", "transformers.web.js")).href);
4786
+ const cacheRoot = join45(homedir8(), ".cache", "vibeframe", "models");
4787
4787
  transformers.env.allowLocalModels = false;
4788
4788
  transformers.env.useCustomCache = true;
4789
4789
  transformers.env.customCache = {
4790
4790
  async match(key2) {
4791
4791
  try {
4792
- return new Response(await readFile46(join44(cacheRoot, encodeURIComponent(String(key2)))));
4792
+ return new Response(await readFile47(join45(cacheRoot, encodeURIComponent(String(key2)))));
4793
4793
  } catch {
4794
4794
  return void 0;
4795
4795
  }
@@ -4798,7 +4798,7 @@ async function loadBundledKokoroRuntime(runtimeDir = process.env.VIBE_KOKORO_RUN
4798
4798
  try {
4799
4799
  const buf = Buffer.from(await response.arrayBuffer());
4800
4800
  await mkdir30(cacheRoot, { recursive: true });
4801
- await writeFile53(join44(cacheRoot, encodeURIComponent(String(key2))), buf);
4801
+ await writeFile53(join45(cacheRoot, encodeURIComponent(String(key2))), buf);
4802
4802
  } catch {
4803
4803
  }
4804
4804
  }
@@ -33729,7 +33729,7 @@ var require_util = __commonJS({
33729
33729
  return path14;
33730
33730
  });
33731
33731
  exports.normalize = normalize3;
33732
- function join44(aRoot, aPath) {
33732
+ function join45(aRoot, aPath) {
33733
33733
  if (aRoot === "") {
33734
33734
  aRoot = ".";
33735
33735
  }
@@ -33761,7 +33761,7 @@ var require_util = __commonJS({
33761
33761
  }
33762
33762
  return joined;
33763
33763
  }
33764
- exports.join = join44;
33764
+ exports.join = join45;
33765
33765
  exports.isAbsolute = function(aPath) {
33766
33766
  return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
33767
33767
  };
@@ -33975,7 +33975,7 @@ var require_util = __commonJS({
33975
33975
  parsed.path = parsed.path.substring(0, index + 1);
33976
33976
  }
33977
33977
  }
33978
- sourceURL = join44(urlGenerate(parsed), sourceURL);
33978
+ sourceURL = join45(urlGenerate(parsed), sourceURL);
33979
33979
  }
33980
33980
  return normalize3(sourceURL);
33981
33981
  }
@@ -35415,8 +35415,8 @@ var require_source_map = __commonJS({
35415
35415
  var require_previous_map = __commonJS({
35416
35416
  "../../node_modules/.pnpm/postcss@8.5.6/node_modules/postcss/lib/previous-map.js"(exports, module) {
35417
35417
  "use strict";
35418
- var { existsSync: existsSync67, readFileSync: readFileSync13 } = __require("fs");
35419
- var { dirname: dirname33, join: join44 } = __require("path");
35418
+ var { existsSync: existsSync68, readFileSync: readFileSync13 } = __require("fs");
35419
+ var { dirname: dirname33, join: join45 } = __require("path");
35420
35420
  var { SourceMapConsumer, SourceMapGenerator } = require_source_map();
35421
35421
  function fromBase64(str2) {
35422
35422
  if (Buffer) {
@@ -35478,7 +35478,7 @@ var require_previous_map = __commonJS({
35478
35478
  }
35479
35479
  loadFile(path14) {
35480
35480
  this.root = dirname33(path14);
35481
- if (existsSync67(path14)) {
35481
+ if (existsSync68(path14)) {
35482
35482
  this.mapFile = path14;
35483
35483
  return readFileSync13(path14, "utf-8").toString().trim();
35484
35484
  }
@@ -35514,7 +35514,7 @@ var require_previous_map = __commonJS({
35514
35514
  return this.decodeInline(this.annotation);
35515
35515
  } else if (this.annotation) {
35516
35516
  let map3 = this.annotation;
35517
- if (file) map3 = join44(dirname33(file), map3);
35517
+ if (file) map3 = join45(dirname33(file), map3);
35518
35518
  return this.loadFile(map3);
35519
35519
  }
35520
35520
  }
@@ -94143,7 +94143,7 @@ var require_util3 = __commonJS({
94143
94143
  return path14;
94144
94144
  }
94145
94145
  exports.normalize = normalize3;
94146
- function join44(aRoot, aPath) {
94146
+ function join45(aRoot, aPath) {
94147
94147
  if (aRoot === "") {
94148
94148
  aRoot = ".";
94149
94149
  }
@@ -94175,7 +94175,7 @@ var require_util3 = __commonJS({
94175
94175
  }
94176
94176
  return joined;
94177
94177
  }
94178
- exports.join = join44;
94178
+ exports.join = join45;
94179
94179
  exports.isAbsolute = function(aPath) {
94180
94180
  return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
94181
94181
  };
@@ -94348,7 +94348,7 @@ var require_util3 = __commonJS({
94348
94348
  parsed.path = parsed.path.substring(0, index + 1);
94349
94349
  }
94350
94350
  }
94351
- sourceURL = join44(urlGenerate(parsed), sourceURL);
94351
+ sourceURL = join45(urlGenerate(parsed), sourceURL);
94352
94352
  }
94353
94353
  return normalize3(sourceURL);
94354
94354
  }
@@ -96150,7 +96150,7 @@ var require_escodegen = __commonJS({
96150
96150
  function noEmptySpace() {
96151
96151
  return space ? space : " ";
96152
96152
  }
96153
- function join44(left3, right3) {
96153
+ function join45(left3, right3) {
96154
96154
  var leftSource, rightSource, leftCharCode, rightCharCode;
96155
96155
  leftSource = toSourceNodeWhenNeeded(left3).toString();
96156
96156
  if (leftSource.length === 0) {
@@ -96481,8 +96481,8 @@ var require_escodegen = __commonJS({
96481
96481
  } else {
96482
96482
  result.push(that.generateExpression(stmt.left, Precedence.Call, E_TTT));
96483
96483
  }
96484
- result = join44(result, operator);
96485
- result = [join44(
96484
+ result = join45(result, operator);
96485
+ result = [join45(
96486
96486
  result,
96487
96487
  that.generateExpression(stmt.right, Precedence.Assignment, E_TTT)
96488
96488
  ), ")"];
@@ -96625,11 +96625,11 @@ var require_escodegen = __commonJS({
96625
96625
  var result, fragment;
96626
96626
  result = ["class"];
96627
96627
  if (stmt.id) {
96628
- result = join44(result, this.generateExpression(stmt.id, Precedence.Sequence, E_TTT));
96628
+ result = join45(result, this.generateExpression(stmt.id, Precedence.Sequence, E_TTT));
96629
96629
  }
96630
96630
  if (stmt.superClass) {
96631
- fragment = join44("extends", this.generateExpression(stmt.superClass, Precedence.Unary, E_TTT));
96632
- result = join44(result, fragment);
96631
+ fragment = join45("extends", this.generateExpression(stmt.superClass, Precedence.Unary, E_TTT));
96632
+ result = join45(result, fragment);
96633
96633
  }
96634
96634
  result.push(space);
96635
96635
  result.push(this.generateStatement(stmt.body, S_TFFT));
@@ -96642,9 +96642,9 @@ var require_escodegen = __commonJS({
96642
96642
  return escapeDirective(stmt.directive) + this.semicolon(flags);
96643
96643
  },
96644
96644
  DoWhileStatement: function(stmt, flags) {
96645
- var result = join44("do", this.maybeBlock(stmt.body, S_TFFF));
96645
+ var result = join45("do", this.maybeBlock(stmt.body, S_TFFF));
96646
96646
  result = this.maybeBlockSuffix(stmt.body, result);
96647
- return join44(result, [
96647
+ return join45(result, [
96648
96648
  "while" + space + "(",
96649
96649
  this.generateExpression(stmt.test, Precedence.Sequence, E_TTT),
96650
96650
  ")" + this.semicolon(flags)
@@ -96680,11 +96680,11 @@ var require_escodegen = __commonJS({
96680
96680
  ExportDefaultDeclaration: function(stmt, flags) {
96681
96681
  var result = ["export"], bodyFlags;
96682
96682
  bodyFlags = flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF;
96683
- result = join44(result, "default");
96683
+ result = join45(result, "default");
96684
96684
  if (isStatement(stmt.declaration)) {
96685
- result = join44(result, this.generateStatement(stmt.declaration, bodyFlags));
96685
+ result = join45(result, this.generateStatement(stmt.declaration, bodyFlags));
96686
96686
  } else {
96687
- result = join44(result, this.generateExpression(stmt.declaration, Precedence.Assignment, E_TTT) + this.semicolon(flags));
96687
+ result = join45(result, this.generateExpression(stmt.declaration, Precedence.Assignment, E_TTT) + this.semicolon(flags));
96688
96688
  }
96689
96689
  return result;
96690
96690
  },
@@ -96692,15 +96692,15 @@ var require_escodegen = __commonJS({
96692
96692
  var result = ["export"], bodyFlags, that = this;
96693
96693
  bodyFlags = flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF;
96694
96694
  if (stmt.declaration) {
96695
- return join44(result, this.generateStatement(stmt.declaration, bodyFlags));
96695
+ return join45(result, this.generateStatement(stmt.declaration, bodyFlags));
96696
96696
  }
96697
96697
  if (stmt.specifiers) {
96698
96698
  if (stmt.specifiers.length === 0) {
96699
- result = join44(result, "{" + space + "}");
96699
+ result = join45(result, "{" + space + "}");
96700
96700
  } else if (stmt.specifiers[0].type === Syntax.ExportBatchSpecifier) {
96701
- result = join44(result, this.generateExpression(stmt.specifiers[0], Precedence.Sequence, E_TTT));
96701
+ result = join45(result, this.generateExpression(stmt.specifiers[0], Precedence.Sequence, E_TTT));
96702
96702
  } else {
96703
- result = join44(result, "{");
96703
+ result = join45(result, "{");
96704
96704
  withIndent(function(indent2) {
96705
96705
  var i2, iz;
96706
96706
  result.push(newline);
@@ -96718,7 +96718,7 @@ var require_escodegen = __commonJS({
96718
96718
  result.push(base + "}");
96719
96719
  }
96720
96720
  if (stmt.source) {
96721
- result = join44(result, [
96721
+ result = join45(result, [
96722
96722
  "from" + space,
96723
96723
  // ModuleSpecifier
96724
96724
  this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),
@@ -96806,7 +96806,7 @@ var require_escodegen = __commonJS({
96806
96806
  ];
96807
96807
  cursor = 0;
96808
96808
  if (stmt.specifiers[cursor].type === Syntax.ImportDefaultSpecifier) {
96809
- result = join44(result, [
96809
+ result = join45(result, [
96810
96810
  this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT)
96811
96811
  ]);
96812
96812
  ++cursor;
@@ -96816,7 +96816,7 @@ var require_escodegen = __commonJS({
96816
96816
  result.push(",");
96817
96817
  }
96818
96818
  if (stmt.specifiers[cursor].type === Syntax.ImportNamespaceSpecifier) {
96819
- result = join44(result, [
96819
+ result = join45(result, [
96820
96820
  space,
96821
96821
  this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT)
96822
96822
  ]);
@@ -96845,7 +96845,7 @@ var require_escodegen = __commonJS({
96845
96845
  }
96846
96846
  }
96847
96847
  }
96848
- result = join44(result, [
96848
+ result = join45(result, [
96849
96849
  "from" + space,
96850
96850
  // ModuleSpecifier
96851
96851
  this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),
@@ -96899,7 +96899,7 @@ var require_escodegen = __commonJS({
96899
96899
  return result;
96900
96900
  },
96901
96901
  ThrowStatement: function(stmt, flags) {
96902
- return [join44(
96902
+ return [join45(
96903
96903
  "throw",
96904
96904
  this.generateExpression(stmt.argument, Precedence.Sequence, E_TTT)
96905
96905
  ), this.semicolon(flags)];
@@ -96910,7 +96910,7 @@ var require_escodegen = __commonJS({
96910
96910
  result = this.maybeBlockSuffix(stmt.block, result);
96911
96911
  if (stmt.handlers) {
96912
96912
  for (i2 = 0, iz = stmt.handlers.length; i2 < iz; ++i2) {
96913
- result = join44(result, this.generateStatement(stmt.handlers[i2], S_TFFF));
96913
+ result = join45(result, this.generateStatement(stmt.handlers[i2], S_TFFF));
96914
96914
  if (stmt.finalizer || i2 + 1 !== iz) {
96915
96915
  result = this.maybeBlockSuffix(stmt.handlers[i2].body, result);
96916
96916
  }
@@ -96918,7 +96918,7 @@ var require_escodegen = __commonJS({
96918
96918
  } else {
96919
96919
  guardedHandlers = stmt.guardedHandlers || [];
96920
96920
  for (i2 = 0, iz = guardedHandlers.length; i2 < iz; ++i2) {
96921
- result = join44(result, this.generateStatement(guardedHandlers[i2], S_TFFF));
96921
+ result = join45(result, this.generateStatement(guardedHandlers[i2], S_TFFF));
96922
96922
  if (stmt.finalizer || i2 + 1 !== iz) {
96923
96923
  result = this.maybeBlockSuffix(guardedHandlers[i2].body, result);
96924
96924
  }
@@ -96926,13 +96926,13 @@ var require_escodegen = __commonJS({
96926
96926
  if (stmt.handler) {
96927
96927
  if (Array.isArray(stmt.handler)) {
96928
96928
  for (i2 = 0, iz = stmt.handler.length; i2 < iz; ++i2) {
96929
- result = join44(result, this.generateStatement(stmt.handler[i2], S_TFFF));
96929
+ result = join45(result, this.generateStatement(stmt.handler[i2], S_TFFF));
96930
96930
  if (stmt.finalizer || i2 + 1 !== iz) {
96931
96931
  result = this.maybeBlockSuffix(stmt.handler[i2].body, result);
96932
96932
  }
96933
96933
  }
96934
96934
  } else {
96935
- result = join44(result, this.generateStatement(stmt.handler, S_TFFF));
96935
+ result = join45(result, this.generateStatement(stmt.handler, S_TFFF));
96936
96936
  if (stmt.finalizer) {
96937
96937
  result = this.maybeBlockSuffix(stmt.handler.body, result);
96938
96938
  }
@@ -96940,7 +96940,7 @@ var require_escodegen = __commonJS({
96940
96940
  }
96941
96941
  }
96942
96942
  if (stmt.finalizer) {
96943
- result = join44(result, ["finally", this.maybeBlock(stmt.finalizer, S_TFFF)]);
96943
+ result = join45(result, ["finally", this.maybeBlock(stmt.finalizer, S_TFFF)]);
96944
96944
  }
96945
96945
  return result;
96946
96946
  },
@@ -96974,7 +96974,7 @@ var require_escodegen = __commonJS({
96974
96974
  withIndent(function() {
96975
96975
  if (stmt.test) {
96976
96976
  result = [
96977
- join44("case", that.generateExpression(stmt.test, Precedence.Sequence, E_TTT)),
96977
+ join45("case", that.generateExpression(stmt.test, Precedence.Sequence, E_TTT)),
96978
96978
  ":"
96979
96979
  ];
96980
96980
  } else {
@@ -97022,9 +97022,9 @@ var require_escodegen = __commonJS({
97022
97022
  result.push(this.maybeBlock(stmt.consequent, S_TFFF));
97023
97023
  result = this.maybeBlockSuffix(stmt.consequent, result);
97024
97024
  if (stmt.alternate.type === Syntax.IfStatement) {
97025
- result = join44(result, ["else ", this.generateStatement(stmt.alternate, bodyFlags)]);
97025
+ result = join45(result, ["else ", this.generateStatement(stmt.alternate, bodyFlags)]);
97026
97026
  } else {
97027
- result = join44(result, join44("else", this.maybeBlock(stmt.alternate, bodyFlags)));
97027
+ result = join45(result, join45("else", this.maybeBlock(stmt.alternate, bodyFlags)));
97028
97028
  }
97029
97029
  } else {
97030
97030
  result.push(this.maybeBlock(stmt.consequent, bodyFlags));
@@ -97125,7 +97125,7 @@ var require_escodegen = __commonJS({
97125
97125
  },
97126
97126
  ReturnStatement: function(stmt, flags) {
97127
97127
  if (stmt.argument) {
97128
- return [join44(
97128
+ return [join45(
97129
97129
  "return",
97130
97130
  this.generateExpression(stmt.argument, Precedence.Sequence, E_TTT)
97131
97131
  ), this.semicolon(flags)];
@@ -97214,14 +97214,14 @@ var require_escodegen = __commonJS({
97214
97214
  if (leftSource.charCodeAt(leftSource.length - 1) === 47 && esutils.code.isIdentifierPartES5(expr.operator.charCodeAt(0))) {
97215
97215
  result = [fragment, noEmptySpace(), expr.operator];
97216
97216
  } else {
97217
- result = join44(fragment, expr.operator);
97217
+ result = join45(fragment, expr.operator);
97218
97218
  }
97219
97219
  fragment = this.generateExpression(expr.right, rightPrecedence, flags);
97220
97220
  if (expr.operator === "/" && fragment.toString().charAt(0) === "/" || expr.operator.slice(-1) === "<" && fragment.toString().slice(0, 3) === "!--") {
97221
97221
  result.push(noEmptySpace());
97222
97222
  result.push(fragment);
97223
97223
  } else {
97224
- result = join44(result, fragment);
97224
+ result = join45(result, fragment);
97225
97225
  }
97226
97226
  if (expr.operator === "in" && !(flags & F_ALLOW_IN)) {
97227
97227
  return ["(", result, ")"];
@@ -97261,7 +97261,7 @@ var require_escodegen = __commonJS({
97261
97261
  var result, length, i2, iz, itemFlags;
97262
97262
  length = expr["arguments"].length;
97263
97263
  itemFlags = flags & F_ALLOW_UNPARATH_NEW && !parentheses && length === 0 ? E_TFT : E_TFF;
97264
- result = join44(
97264
+ result = join45(
97265
97265
  "new",
97266
97266
  this.generateExpression(expr.callee, Precedence.New, itemFlags)
97267
97267
  );
@@ -97311,11 +97311,11 @@ var require_escodegen = __commonJS({
97311
97311
  var result, fragment, rightCharCode, leftSource, leftCharCode;
97312
97312
  fragment = this.generateExpression(expr.argument, Precedence.Unary, E_TTT);
97313
97313
  if (space === "") {
97314
- result = join44(expr.operator, fragment);
97314
+ result = join45(expr.operator, fragment);
97315
97315
  } else {
97316
97316
  result = [expr.operator];
97317
97317
  if (expr.operator.length > 2) {
97318
- result = join44(result, fragment);
97318
+ result = join45(result, fragment);
97319
97319
  } else {
97320
97320
  leftSource = toSourceNodeWhenNeeded(result).toString();
97321
97321
  leftCharCode = leftSource.charCodeAt(leftSource.length - 1);
@@ -97338,7 +97338,7 @@ var require_escodegen = __commonJS({
97338
97338
  result = "yield";
97339
97339
  }
97340
97340
  if (expr.argument) {
97341
- result = join44(
97341
+ result = join45(
97342
97342
  result,
97343
97343
  this.generateExpression(expr.argument, Precedence.Yield, E_TTT)
97344
97344
  );
@@ -97346,7 +97346,7 @@ var require_escodegen = __commonJS({
97346
97346
  return parenthesize(result, Precedence.Yield, precedence);
97347
97347
  },
97348
97348
  AwaitExpression: function(expr, precedence, flags) {
97349
- var result = join44(
97349
+ var result = join45(
97350
97350
  expr.all ? "await*" : "await",
97351
97351
  this.generateExpression(expr.argument, Precedence.Await, E_TTT)
97352
97352
  );
@@ -97429,11 +97429,11 @@ var require_escodegen = __commonJS({
97429
97429
  var result, fragment;
97430
97430
  result = ["class"];
97431
97431
  if (expr.id) {
97432
- result = join44(result, this.generateExpression(expr.id, Precedence.Sequence, E_TTT));
97432
+ result = join45(result, this.generateExpression(expr.id, Precedence.Sequence, E_TTT));
97433
97433
  }
97434
97434
  if (expr.superClass) {
97435
- fragment = join44("extends", this.generateExpression(expr.superClass, Precedence.Unary, E_TTT));
97436
- result = join44(result, fragment);
97435
+ fragment = join45("extends", this.generateExpression(expr.superClass, Precedence.Unary, E_TTT));
97436
+ result = join45(result, fragment);
97437
97437
  }
97438
97438
  result.push(space);
97439
97439
  result.push(this.generateStatement(expr.body, S_TFFT));
@@ -97448,7 +97448,7 @@ var require_escodegen = __commonJS({
97448
97448
  }
97449
97449
  if (expr.kind === "get" || expr.kind === "set") {
97450
97450
  fragment = [
97451
- join44(expr.kind, this.generatePropertyKey(expr.key, expr.computed)),
97451
+ join45(expr.kind, this.generatePropertyKey(expr.key, expr.computed)),
97452
97452
  this.generateFunctionBody(expr.value)
97453
97453
  ];
97454
97454
  } else {
@@ -97458,7 +97458,7 @@ var require_escodegen = __commonJS({
97458
97458
  this.generateFunctionBody(expr.value)
97459
97459
  ];
97460
97460
  }
97461
- return join44(result, fragment);
97461
+ return join45(result, fragment);
97462
97462
  },
97463
97463
  Property: function(expr, precedence, flags) {
97464
97464
  if (expr.kind === "get" || expr.kind === "set") {
@@ -97653,7 +97653,7 @@ var require_escodegen = __commonJS({
97653
97653
  for (i2 = 0, iz = expr.blocks.length; i2 < iz; ++i2) {
97654
97654
  fragment = that.generateExpression(expr.blocks[i2], Precedence.Sequence, E_TTT);
97655
97655
  if (i2 > 0 || extra.moz.comprehensionExpressionStartsWithAssignment) {
97656
- result = join44(result, fragment);
97656
+ result = join45(result, fragment);
97657
97657
  } else {
97658
97658
  result.push(fragment);
97659
97659
  }
@@ -97661,13 +97661,13 @@ var require_escodegen = __commonJS({
97661
97661
  });
97662
97662
  }
97663
97663
  if (expr.filter) {
97664
- result = join44(result, "if" + space);
97664
+ result = join45(result, "if" + space);
97665
97665
  fragment = this.generateExpression(expr.filter, Precedence.Sequence, E_TTT);
97666
- result = join44(result, ["(", fragment, ")"]);
97666
+ result = join45(result, ["(", fragment, ")"]);
97667
97667
  }
97668
97668
  if (!extra.moz.comprehensionExpressionStartsWithAssignment) {
97669
97669
  fragment = this.generateExpression(expr.body, Precedence.Assignment, E_TTT);
97670
- result = join44(result, fragment);
97670
+ result = join45(result, fragment);
97671
97671
  }
97672
97672
  result.push(expr.type === Syntax.GeneratorExpression ? ")" : "]");
97673
97673
  return result;
@@ -97683,8 +97683,8 @@ var require_escodegen = __commonJS({
97683
97683
  } else {
97684
97684
  fragment = this.generateExpression(expr.left, Precedence.Call, E_TTT);
97685
97685
  }
97686
- fragment = join44(fragment, expr.of ? "of" : "in");
97687
- fragment = join44(fragment, this.generateExpression(expr.right, Precedence.Sequence, E_TTT));
97686
+ fragment = join45(fragment, expr.of ? "of" : "in");
97687
+ fragment = join45(fragment, this.generateExpression(expr.right, Precedence.Sequence, E_TTT));
97688
97688
  return ["for" + space + "(", fragment, ")"];
97689
97689
  },
97690
97690
  SpreadElement: function(expr, precedence, flags) {
@@ -124086,9 +124086,9 @@ async function getConnectionTransport(options) {
124086
124086
  throw new Error("Could not detect required browser platform");
124087
124087
  }
124088
124088
  const { convertPuppeteerChannelToBrowsersChannel: convertPuppeteerChannelToBrowsersChannel3 } = await Promise.resolve().then(() => (init_LaunchOptions(), LaunchOptions_exports));
124089
- const { join: join44 } = await import("node:path");
124089
+ const { join: join45 } = await import("node:path");
124090
124090
  const userDataDir = resolveDefaultUserDataDir4(Browser5.CHROME, platform, convertPuppeteerChannelToBrowsersChannel3(options.channel));
124091
- const portPath = join44(userDataDir, "DevToolsActivePort");
124091
+ const portPath = join45(userDataDir, "DevToolsActivePort");
124092
124092
  try {
124093
124093
  const fileContent = await environment.value.fs.promises.readFile(portPath, "ascii");
124094
124094
  const [rawPort, rawPath] = fileContent.split("\n").map((line) => {
@@ -137965,7 +137965,7 @@ ${lanes.join("\n")}
137965
137965
  writeOutputIsTTY() {
137966
137966
  return process.stdout.isTTY;
137967
137967
  },
137968
- readFile: readFile46,
137968
+ readFile: readFile47,
137969
137969
  writeFile: writeFile210,
137970
137970
  watchFile: watchFile2,
137971
137971
  watchDirectory,
@@ -138171,7 +138171,7 @@ ${lanes.join("\n")}
138171
138171
  callback
138172
138172
  );
138173
138173
  }
138174
- function readFile46(fileName, _encoding) {
138174
+ function readFile47(fileName, _encoding) {
138175
138175
  let buffer;
138176
138176
  try {
138177
138177
  buffer = _fs.readFileSync(fileName);
@@ -174727,7 +174727,7 @@ ${lanes.join("\n")}
174727
174727
  const possibleOption = getSpellingSuggestion(unknownOption, diagnostics.optionDeclarations, getOptionName);
174728
174728
  return possibleOption ? createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, node, diagnostics.unknownDidYouMeanDiagnostic, unknownOptionErrorText || unknownOption, possibleOption.name) : createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, node, diagnostics.unknownOptionDiagnostic, unknownOptionErrorText || unknownOption);
174729
174729
  }
174730
- function parseCommandLineWorker(diagnostics, commandLine, readFile46) {
174730
+ function parseCommandLineWorker(diagnostics, commandLine, readFile47) {
174731
174731
  const options = {};
174732
174732
  let watchOptions;
174733
174733
  const fileNames = [];
@@ -174775,7 +174775,7 @@ ${lanes.join("\n")}
174775
174775
  }
174776
174776
  }
174777
174777
  function parseResponseFile(fileName) {
174778
- const text = tryReadFile(fileName, readFile46 || ((fileName2) => sys.readFile(fileName2)));
174778
+ const text = tryReadFile(fileName, readFile47 || ((fileName2) => sys.readFile(fileName2)));
174779
174779
  if (!isString3(text)) {
174780
174780
  errors.push(text);
174781
174781
  return;
@@ -174878,8 +174878,8 @@ ${lanes.join("\n")}
174878
174878
  unknownDidYouMeanDiagnostic: Diagnostics.Unknown_compiler_option_0_Did_you_mean_1,
174879
174879
  optionTypeMismatchDiagnostic: Diagnostics.Compiler_option_0_expects_an_argument
174880
174880
  };
174881
- function parseCommandLine(commandLine, readFile46) {
174882
- return parseCommandLineWorker(compilerOptionsDidYouMeanDiagnostics, commandLine, readFile46);
174881
+ function parseCommandLine(commandLine, readFile47) {
174882
+ return parseCommandLineWorker(compilerOptionsDidYouMeanDiagnostics, commandLine, readFile47);
174883
174883
  }
174884
174884
  function getOptionFromName(optionName, allowShort) {
174885
174885
  return getOptionDeclarationFromName(getOptionsNameMap, optionName, allowShort);
@@ -174961,8 +174961,8 @@ ${lanes.join("\n")}
174961
174961
  watchOptionsToExtend
174962
174962
  );
174963
174963
  }
174964
- function readConfigFile2(fileName, readFile46) {
174965
- const textOrDiagnostic = tryReadFile(fileName, readFile46);
174964
+ function readConfigFile2(fileName, readFile47) {
174965
+ const textOrDiagnostic = tryReadFile(fileName, readFile47);
174966
174966
  return isString3(textOrDiagnostic) ? parseConfigFileTextToJson(fileName, textOrDiagnostic) : { config: {}, error: textOrDiagnostic };
174967
174967
  }
174968
174968
  function parseConfigFileTextToJson(fileName, jsonText) {
@@ -174977,14 +174977,14 @@ ${lanes.join("\n")}
174977
174977
  error: jsonSourceFile.parseDiagnostics.length ? jsonSourceFile.parseDiagnostics[0] : void 0
174978
174978
  };
174979
174979
  }
174980
- function readJsonConfigFile(fileName, readFile46) {
174981
- const textOrDiagnostic = tryReadFile(fileName, readFile46);
174980
+ function readJsonConfigFile(fileName, readFile47) {
174981
+ const textOrDiagnostic = tryReadFile(fileName, readFile47);
174982
174982
  return isString3(textOrDiagnostic) ? parseJsonText(fileName, textOrDiagnostic) : { fileName, parseDiagnostics: [textOrDiagnostic] };
174983
174983
  }
174984
- function tryReadFile(fileName, readFile46) {
174984
+ function tryReadFile(fileName, readFile47) {
174985
174985
  let text;
174986
174986
  try {
174987
- text = readFile46(fileName);
174987
+ text = readFile47(fileName);
174988
174988
  } catch (e2) {
174989
174989
  return createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e2.message);
174990
174990
  }
@@ -264642,12 +264642,12 @@ ${lanes.join("\n")}
264642
264642
  function createCompilerHost(options, setParentNodes) {
264643
264643
  return createCompilerHostWorker(options, setParentNodes);
264644
264644
  }
264645
- function createGetSourceFile(readFile46, setParentNodes) {
264645
+ function createGetSourceFile(readFile47, setParentNodes) {
264646
264646
  return (fileName, languageVersionOrOptions, onError) => {
264647
264647
  let text;
264648
264648
  try {
264649
264649
  mark("beforeIORead");
264650
- text = readFile46(fileName);
264650
+ text = readFile47(fileName);
264651
264651
  mark("afterIORead");
264652
264652
  measure("I/O Read", "beforeIORead", "afterIORead");
264653
264653
  } catch (e2) {
@@ -265551,7 +265551,7 @@ ${lanes.join("\n")}
265551
265551
  getRedirectFromOutput,
265552
265552
  forEachResolvedProjectReference: forEachResolvedProjectReference2
265553
265553
  });
265554
- const readFile46 = host.readFile.bind(host);
265554
+ const readFile47 = host.readFile.bind(host);
265555
265555
  (_e2 = tracing) == null ? void 0 : _e2.push(tracing.Phase.Program, "shouldProgramCreateNewSourceFiles", { hasOldProgram: !!oldProgram });
265556
265556
  const shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles(oldProgram, options);
265557
265557
  (_f = tracing) == null ? void 0 : _f.pop();
@@ -265777,7 +265777,7 @@ ${lanes.join("\n")}
265777
265777
  shouldTransformImportCall,
265778
265778
  emitBuildInfo,
265779
265779
  fileExists: fileExists2,
265780
- readFile: readFile46,
265780
+ readFile: readFile47,
265781
265781
  directoryExists,
265782
265782
  getSymlinkCache,
265783
265783
  realpath: (_o = host.realpath) == null ? void 0 : _o.bind(host),
@@ -470414,10 +470414,57 @@ var init_composer_resolve = __esm({
470414
470414
  }
470415
470415
  });
470416
470416
 
470417
+ // ../cli/src/commands/_shared/transcribe-narration.ts
470418
+ import { existsSync as existsSync24 } from "node:fs";
470419
+ import { readFile as readFile9 } from "node:fs/promises";
470420
+ import { join as join24 } from "node:path";
470421
+ async function transcribeNarrationWords(audioAbsPath, opts) {
470422
+ try {
470423
+ const whisper = new WhisperProvider();
470424
+ await whisper.initialize({ apiKey: opts.apiKey });
470425
+ const audioBytes = await readFile9(audioAbsPath);
470426
+ const audioBlob = new Blob([new Uint8Array(audioBytes)]);
470427
+ const transcript = await whisper.transcribe(audioBlob, void 0, {
470428
+ granularity: "word",
470429
+ language: opts.language
470430
+ });
470431
+ if (transcript.status === "completed" && transcript.words?.length) {
470432
+ return transcript.words.map((w2) => ({ text: w2.text, start: w2.start, end: w2.end }));
470433
+ }
470434
+ return [];
470435
+ } catch {
470436
+ return [];
470437
+ }
470438
+ }
470439
+ function beatTranscriptRelPath(beatId) {
470440
+ return `assets/transcript-${beatId}.json`;
470441
+ }
470442
+ async function readBeatTranscript(projectDir, beatId) {
470443
+ const abs = join24(projectDir, beatTranscriptRelPath(beatId));
470444
+ if (!existsSync24(abs)) return void 0;
470445
+ try {
470446
+ const parsed = JSON.parse(await readFile9(abs, "utf-8"));
470447
+ if (!Array.isArray(parsed)) return void 0;
470448
+ const words = parsed.filter(
470449
+ (w2) => typeof w2 === "object" && w2 !== null && typeof w2.text === "string" && Number.isFinite(w2.start) && Number.isFinite(w2.end)
470450
+ ).map((w2) => ({ text: w2.text, start: w2.start, end: w2.end }));
470451
+ return words.length > 0 ? words : void 0;
470452
+ } catch {
470453
+ return void 0;
470454
+ }
470455
+ }
470456
+ var init_transcribe_narration = __esm({
470457
+ "../cli/src/commands/_shared/transcribe-narration.ts"() {
470458
+ "use strict";
470459
+ init_dist();
470460
+ }
470461
+ });
470462
+
470417
470463
  // ../cli/src/commands/_shared/compose-scenes-skills.ts
470418
470464
  var compose_scenes_skills_exports = {};
470419
470465
  __export(compose_scenes_skills_exports, {
470420
470466
  ComposeBeatError: () => ComposeBeatError,
470467
+ TRANSCRIPT_PROMPT_MAX_WORDS: () => TRANSCRIPT_PROMPT_MAX_WORDS,
470421
470468
  buildSystemPrompt: () => buildSystemPrompt,
470422
470469
  buildUserPrompt: () => buildUserPrompt,
470423
470470
  composeBeatHtml: () => composeBeatHtml,
@@ -470427,12 +470474,13 @@ __export(compose_scenes_skills_exports, {
470427
470474
  executeComposeScenesWithSkills: () => executeComposeScenesWithSkills,
470428
470475
  extractHtml: () => extractHtml,
470429
470476
  formatLintFeedback: () => formatLintFeedback,
470477
+ formatTranscriptSection: () => formatTranscriptSection,
470430
470478
  lintBeatHtml: () => lintBeatHtml
470431
470479
  });
470432
470480
  import { createHash as createHash5 } from "node:crypto";
470433
- import { existsSync as existsSync24, mkdirSync as mkdirSync12 } from "node:fs";
470434
- import { mkdir as mkdir9, readFile as readFile9, writeFile as writeFile14 } from "node:fs/promises";
470435
- import { dirname as dirname13, join as join24, resolve as resolve18 } from "node:path";
470481
+ import { existsSync as existsSync25, mkdirSync as mkdirSync12 } from "node:fs";
470482
+ import { mkdir as mkdir9, readFile as readFile10, writeFile as writeFile14 } from "node:fs/promises";
470483
+ import { dirname as dirname13, join as join25, resolve as resolve18 } from "node:path";
470436
470484
  function buildSystemPrompt(ctx) {
470437
470485
  return `You are a Hyperframes composition author. The skill content below
470438
470486
  defines the framework rules, motion principles, and quality standards.
@@ -470465,6 +470513,46 @@ function formatBeatCues(cues) {
470465
470513
  }
470466
470514
  return lines.join("\n") + "\n";
470467
470515
  }
470516
+ function formatTranscriptSection(transcript, maxWords = TRANSCRIPT_PROMPT_MAX_WORDS) {
470517
+ if (!transcript || transcript.length === 0) return "";
470518
+ const round = (n2) => Number(Math.max(0, n2).toFixed(2));
470519
+ const noAudioRule = "This is for VISUAL sync only \u2014 do NOT add an `<audio>` tag or invent SFX; the narration audio is wired separately by the root timeline. If this beat is visual-only (no on-screen text), you may ignore these timings.";
470520
+ if (transcript.length <= maxWords) {
470521
+ const pairs = transcript.map((w2) => `[${round(w2.start)}, ${JSON.stringify(w2.text)}]`).join(", ");
470522
+ return `
470523
+
470524
+ === Narration word timings (seconds) ===
470525
+
470526
+ Whisper word-level start times for this beat's narration. If you author captions
470527
+ or kinetic typography, reveal each word at its start time with absolute-time
470528
+ GSAP tweens, e.g.
470529
+ \`tl.fromTo('.caption .word[data-i="0"]', { opacity: 0, y: 10 }, { opacity: 1, y: 0, duration: 0.18 }, ${round(
470530
+ transcript[0].start
470531
+ )});\`
470532
+ ${noAudioRule}
470533
+
470534
+ word starts (word-level): ${pairs}`;
470535
+ }
470536
+ const phraseCount = Math.max(1, Math.floor(maxWords / 2));
470537
+ const chunkSize = Math.ceil(transcript.length / phraseCount);
470538
+ const anchors = [];
470539
+ for (let i2 = 0; i2 < transcript.length; i2 += chunkSize) {
470540
+ const chunk = transcript.slice(i2, i2 + chunkSize);
470541
+ const text = chunk.map((w2) => w2.text).join(" ");
470542
+ anchors.push(`[${round(chunk[0].start)}, ${JSON.stringify(text)}]`);
470543
+ }
470544
+ return `
470545
+
470546
+ === Narration timings (approximate, phrase-level) ===
470547
+
470548
+ This beat's narration is long (${transcript.length} words), so timings are
470549
+ grouped into phrase-level anchors (start time of each phrase). Use them to PACE
470550
+ caption / kinetic-type reveals across the beat \u2014 they are approximate, not
470551
+ per-word truth.
470552
+ ${noAudioRule}
470553
+
470554
+ phrase starts (approximate): ${anchors.join(", ")}`;
470555
+ }
470468
470556
  function buildUserPrompt(ctx) {
470469
470557
  const compositionId = `scene-${ctx.beat.id}`;
470470
470558
  const durLiteral = ctx.finalDurationSec !== void 0 ? String(ctx.finalDurationSec) : void 0;
@@ -470627,7 +470715,7 @@ ${ctx.storyboardGlobal || "(no global direction)"}
470627
470715
 
470628
470716
  ## ${ctx.beat.heading}
470629
470717
  ${formatBeatCues(ctx.beat.cues)}${cueDurationNote}
470630
- ${ctx.beat.body}
470718
+ ${ctx.beat.body}${formatTranscriptSection(ctx.transcript)}
470631
470719
 
470632
470720
  === Output format ===
470633
470721
 
@@ -470647,7 +470735,7 @@ function computeCacheKey(parts) {
470647
470735
  return createHash5("sha256").update(parts.provider).update("\u241E").update(parts.model).update("\u241E").update(parts.systemPrompt).update("\u241E").update(parts.userPrompt).digest("hex");
470648
470736
  }
470649
470737
  function defaultCacheDir() {
470650
- return join24(USER_CACHE_DIR, "compose-scenes");
470738
+ return join25(USER_CACHE_DIR, "compose-scenes");
470651
470739
  }
470652
470740
  function extractHtml(responseText) {
470653
470741
  const fenced = responseText.match(/```html\s*\n([\s\S]*?)\n```/);
@@ -470671,9 +470759,9 @@ async function composeBeatHtml(ctx, overrides) {
470671
470759
  model: settings.model
470672
470760
  });
470673
470761
  const cacheDir = ctx.cacheDir ?? defaultCacheDir();
470674
- const cachePath = join24(cacheDir, `${cacheKey2}.html`);
470675
- if (existsSync24(cachePath)) {
470676
- const html2 = await readFile9(cachePath, "utf-8");
470762
+ const cachePath = join25(cacheDir, `${cacheKey2}.html`);
470763
+ if (existsSync25(cachePath)) {
470764
+ const html2 = await readFile10(cachePath, "utf-8");
470677
470765
  return { html: html2, cached: true, cacheKey: cacheKey2, model: settings.model, provider: ctx.provider };
470678
470766
  }
470679
470767
  if (!ctx.apiKey) {
@@ -470809,14 +470897,14 @@ async function executeComposeScenesWithSkills(params, outputDir, overrides) {
470809
470897
  const projectRoot = params.project ? resolve18(outputDir, params.project) : resolve18(outputDir);
470810
470898
  const designPath = resolve18(projectRoot, params.design ?? "DESIGN.md");
470811
470899
  const storyboardPath = resolve18(projectRoot, params.storyboard ?? "STORYBOARD.md");
470812
- if (!existsSync24(designPath)) {
470900
+ if (!existsSync25(designPath)) {
470813
470901
  return { success: false, error: `DESIGN.md not found at ${designPath}` };
470814
470902
  }
470815
- if (!existsSync24(storyboardPath)) {
470903
+ if (!existsSync25(storyboardPath)) {
470816
470904
  return { success: false, error: `STORYBOARD.md not found at ${storyboardPath}` };
470817
470905
  }
470818
- const designMd = await readFile9(designPath, "utf-8");
470819
- const storyboardMd = await readFile9(storyboardPath, "utf-8");
470906
+ const designMd = await readFile10(designPath, "utf-8");
470907
+ const storyboardMd = await readFile10(storyboardPath, "utf-8");
470820
470908
  const { global: storyboardGlobal, beats } = parseStoryboard(storyboardMd);
470821
470909
  if (beats.length === 0) {
470822
470910
  return {
@@ -470836,7 +470924,7 @@ async function executeComposeScenesWithSkills(params, outputDir, overrides) {
470836
470924
  provider = params.composer ?? "claude";
470837
470925
  apiKey = "";
470838
470926
  }
470839
- const compositionsDir = join24(projectRoot, "compositions");
470927
+ const compositionsDir = join25(projectRoot, "compositions");
470840
470928
  await mkdir9(compositionsDir, { recursive: true });
470841
470929
  let finalDurations = /* @__PURE__ */ new Map();
470842
470930
  try {
@@ -470850,6 +470938,7 @@ async function executeComposeScenesWithSkills(params, outputDir, overrides) {
470850
470938
  async (beat, beatIndex) => {
470851
470939
  onProgress({ type: "beat-start", beatId: beat.id, beatIndex, totalBeats });
470852
470940
  try {
470941
+ const transcript = await readBeatTranscript(projectRoot, beat.id);
470853
470942
  const result = await composeBeatWithRetry(
470854
470943
  {
470855
470944
  beat,
@@ -470860,11 +470949,12 @@ async function executeComposeScenesWithSkills(params, outputDir, overrides) {
470860
470949
  apiKey,
470861
470950
  effort: params.effort,
470862
470951
  cacheDir: params.cacheDir,
470863
- finalDurationSec: finalDurations.get(beat.id)
470952
+ finalDurationSec: finalDurations.get(beat.id),
470953
+ transcript
470864
470954
  },
470865
470955
  overrides
470866
470956
  );
470867
- const compositionPath = join24(compositionsDir, `scene-${beat.id}.html`);
470957
+ const compositionPath = join25(compositionsDir, `scene-${beat.id}.html`);
470868
470958
  await mkdir9(dirname13(compositionPath), { recursive: true });
470869
470959
  await writeFile14(compositionPath, result.html, "utf-8");
470870
470960
  if (result.cached) {
@@ -470943,7 +471033,7 @@ ${failures.map((f2) => ` - ${f2.beatId}: ${f2.error}`).join("\n")}`,
470943
471033
  data: aggregateData
470944
471034
  };
470945
471035
  }
470946
- var MODEL_SETTINGS_BY_PROVIDER, ComposeBeatError, defaultCallLLM, CONFIG_PROVIDER_BY_COMPOSER;
471036
+ var MODEL_SETTINGS_BY_PROVIDER, TRANSCRIPT_PROMPT_MAX_WORDS, ComposeBeatError, defaultCallLLM, CONFIG_PROVIDER_BY_COMPOSER;
470947
471037
  var init_compose_scenes_skills = __esm({
470948
471038
  "../cli/src/commands/_shared/compose-scenes-skills.ts"() {
470949
471039
  "use strict";
@@ -470959,6 +471049,7 @@ var init_compose_scenes_skills = __esm({
470959
471049
  init_root_sync();
470960
471050
  init_composer_resolve();
470961
471051
  init_config();
471052
+ init_transcribe_narration();
470962
471053
  MODEL_SETTINGS_BY_PROVIDER = {
470963
471054
  // Anthropic Claude Sonnet 4.6 — v0.69 baseline. ~9 s/beat, $3/$15 per MTok.
470964
471055
  claude: {
@@ -470982,6 +471073,7 @@ var init_compose_scenes_skills = __esm({
470982
471073
  high: { model: GEMINI_DEFAULT_TEXT_MODEL, maxTokens: 8e3, costPerMTokIn: 1.5, costPerMTokOut: 9 }
470983
471074
  }
470984
471075
  };
471076
+ TRANSCRIPT_PROMPT_MAX_WORDS = 120;
470985
471077
  ComposeBeatError = class extends Error {
470986
471078
  constructor(code, message, cause) {
470987
471079
  super(message);
@@ -471067,22 +471159,22 @@ var init_compose_scenes_skills = __esm({
471067
471159
  });
471068
471160
 
471069
471161
  // ../cli/src/commands/_shared/compose-prompts.ts
471070
- import { existsSync as existsSync25 } from "node:fs";
471071
- import { readFile as readFile10 } from "node:fs/promises";
471072
- import { join as join25, relative as relative6, resolve as resolve19 } from "node:path";
471162
+ import { existsSync as existsSync26 } from "node:fs";
471163
+ import { readFile as readFile11 } from "node:fs/promises";
471164
+ import { join as join26, relative as relative6, resolve as resolve19 } from "node:path";
471073
471165
  async function getComposePrompts(opts) {
471074
471166
  const projectDir = resolve19(opts.projectDir);
471075
- const designPath = join25(projectDir, "DESIGN.md");
471076
- const storyboardPath = join25(projectDir, "STORYBOARD.md");
471077
- const skillPath = join25(projectDir, "SKILL.md");
471078
- const compositionsDir = join25(projectDir, "compositions");
471167
+ const designPath = join26(projectDir, "DESIGN.md");
471168
+ const storyboardPath = join26(projectDir, "STORYBOARD.md");
471169
+ const skillPath = join26(projectDir, "SKILL.md");
471170
+ const compositionsDir = join26(projectDir, "compositions");
471079
471171
  const warnings = [];
471080
471172
  const baseError = (msg) => ({
471081
471173
  success: false,
471082
471174
  projectDir,
471083
471175
  designReference: "DESIGN.md",
471084
471176
  storyboardReference: "STORYBOARD.md",
471085
- skillReference: existsSync25(skillPath) ? "SKILL.md" : null,
471177
+ skillReference: existsSync26(skillPath) ? "SKILL.md" : null,
471086
471178
  compositionsDir: "compositions",
471087
471179
  beats: [],
471088
471180
  instructions: [],
@@ -471090,18 +471182,18 @@ async function getComposePrompts(opts) {
471090
471182
  warnings,
471091
471183
  error: msg
471092
471184
  });
471093
- if (!existsSync25(designPath)) {
471185
+ if (!existsSync26(designPath)) {
471094
471186
  return baseError(`DESIGN.md not found at ${designPath}. Run \`vibe scene init <dir>\` first.`);
471095
471187
  }
471096
- if (!existsSync25(storyboardPath)) {
471188
+ if (!existsSync26(storyboardPath)) {
471097
471189
  return baseError(`STORYBOARD.md not found at ${storyboardPath}. Run \`vibe scene init <dir>\` to create a starter, or add STORYBOARD.md with per-beat cues.`);
471098
471190
  }
471099
- if (!existsSync25(skillPath)) {
471191
+ if (!existsSync26(skillPath)) {
471100
471192
  warnings.push(
471101
471193
  "SKILL.md not installed \u2014 host agent won't have Hyperframes rules in context. Run `vibe scene install-skill` to install it."
471102
471194
  );
471103
471195
  }
471104
- const storyboardMd = await readFile10(storyboardPath, "utf-8");
471196
+ const storyboardMd = await readFile11(storyboardPath, "utf-8");
471105
471197
  const parsed = parseStoryboard(storyboardMd);
471106
471198
  if (parsed.beats.length === 0) {
471107
471199
  return baseError(`STORYBOARD.md has no \`## Beat \u2026\` headings.`);
@@ -471123,28 +471215,33 @@ async function getComposePrompts(opts) {
471123
471215
  finalDurations = await resolveProjectBeatDurations(projectDir);
471124
471216
  } catch {
471125
471217
  }
471126
- const result = beats.map((beat) => {
471127
- const outputPathAbs = join25(compositionsDir, `scene-${beat.id}.html`);
471128
- const outputPathRel = relative6(projectDir, outputPathAbs);
471129
- const finalDurationSec = finalDurations.get(beat.id);
471130
- const userPrompt = buildUserPrompt({
471131
- beat,
471132
- storyboardGlobal: parsed.global,
471133
- finalDurationSec
471134
- });
471135
- return {
471136
- id: beat.id,
471137
- heading: beat.heading,
471138
- outputPath: outputPathRel,
471139
- duration: beat.duration,
471140
- finalDurationSec,
471141
- cues: beat.cues,
471142
- body: beat.body,
471143
- userPrompt,
471144
- exists: existsSync25(outputPathAbs)
471145
- };
471146
- });
471147
- const skillRef = existsSync25(skillPath) ? "SKILL.md" : null;
471218
+ const result = await Promise.all(
471219
+ beats.map(async (beat) => {
471220
+ const outputPathAbs = join26(compositionsDir, `scene-${beat.id}.html`);
471221
+ const outputPathRel = relative6(projectDir, outputPathAbs);
471222
+ const finalDurationSec = finalDurations.get(beat.id);
471223
+ const transcript = await readBeatTranscript(projectDir, beat.id);
471224
+ const userPrompt = buildUserPrompt({
471225
+ beat,
471226
+ storyboardGlobal: parsed.global,
471227
+ finalDurationSec,
471228
+ transcript
471229
+ });
471230
+ return {
471231
+ id: beat.id,
471232
+ heading: beat.heading,
471233
+ outputPath: outputPathRel,
471234
+ duration: beat.duration,
471235
+ finalDurationSec,
471236
+ cues: beat.cues,
471237
+ body: beat.body,
471238
+ userPrompt,
471239
+ transcriptPath: transcript ? beatTranscriptRelPath(beat.id) : void 0,
471240
+ exists: existsSync26(outputPathAbs)
471241
+ };
471242
+ })
471243
+ );
471244
+ const skillRef = existsSync26(skillPath) ? "SKILL.md" : null;
471148
471245
  const instructions = buildInstructions({
471149
471246
  skillRef,
471150
471247
  beatCount: result.length,
@@ -471192,13 +471289,14 @@ var init_compose_prompts = __esm({
471192
471289
  init_compose_scenes_skills();
471193
471290
  init_root_sync();
471194
471291
  init_bundle();
471292
+ init_transcribe_narration();
471195
471293
  }
471196
471294
  });
471197
471295
 
471198
471296
  // ../cli/src/commands/_shared/sub-comp-duration-sync.ts
471199
- import { existsSync as existsSync27 } from "node:fs";
471200
- import { readFile as readFile12 } from "node:fs/promises";
471201
- import { join as join27, resolve as resolve21 } from "node:path";
471297
+ import { existsSync as existsSync28 } from "node:fs";
471298
+ import { readFile as readFile13 } from "node:fs/promises";
471299
+ import { join as join28, resolve as resolve21 } from "node:path";
471202
471300
  function syncSubCompositionDurationHtml(html, beatId, newDurationSec, fileRel) {
471203
471301
  const compositionId = `scene-${beatId}`;
471204
471302
  const file = fileRel ?? `compositions/${compositionId}.html`;
@@ -471290,15 +471388,15 @@ async function createSubCompDurationSyncPlans(opts) {
471290
471388
  const results = [];
471291
471389
  for (const beat of opts.beats) {
471292
471390
  const fileRel = `compositions/scene-${beat.id}.html`;
471293
- const filePath = join27(projectDir, fileRel);
471294
- if (!existsSync27(filePath)) continue;
471391
+ const filePath = join28(projectDir, fileRel);
471392
+ if (!existsSync28(filePath)) continue;
471295
471393
  const newDurationSec = await resolveSyncedBeatDuration({
471296
471394
  projectDir,
471297
471395
  beatDuration: beat.duration,
471298
471396
  narrationPath: beat.narrationPath,
471299
471397
  sceneDurationSec: beat.sceneDurationSec
471300
471398
  });
471301
- const html = await readFile12(filePath, "utf-8");
471399
+ const html = await readFile13(filePath, "utf-8");
471302
471400
  const outcome = syncSubCompositionDurationHtml(html, beat.id, newDurationSec, fileRel);
471303
471401
  results.push({ ...outcome, file: fileRel, beatId: beat.id });
471304
471402
  }
@@ -471322,7 +471420,7 @@ var init_sub_comp_duration_sync = __esm({
471322
471420
  });
471323
471421
 
471324
471422
  // ../cli/src/commands/_shared/scene-repair.ts
471325
- import { readFile as readFile13, writeFile as writeFile16 } from "node:fs/promises";
471423
+ import { readFile as readFile14, writeFile as writeFile16 } from "node:fs/promises";
471326
471424
  import { relative as relative7, resolve as resolve23 } from "node:path";
471327
471425
  async function executeSceneRepair(opts) {
471328
471426
  const projectDir = resolve23(opts.projectDir);
@@ -471367,7 +471465,7 @@ async function executeSceneRepair(opts) {
471367
471465
  }
471368
471466
  for (const target of targets) {
471369
471467
  const rel = relative7(projectDir, target.abs) || target.abs;
471370
- const html = await readFile13(target.abs, "utf-8");
471468
+ const html = await readFile14(target.abs, "utf-8");
471371
471469
  const findings = lintHtml(html, rel, target.isSub);
471372
471470
  const { html: nextHtml, fixedCodes } = applyMechanicalFixes(html, findings);
471373
471471
  if (fixedCodes.length > 0) {
@@ -471740,15 +471838,15 @@ var init_storyboard_edit = __esm({
471740
471838
  });
471741
471839
 
471742
471840
  // ../cli/src/pipeline/renderers/chrome.ts
471743
- import { existsSync as existsSync29 } from "node:fs";
471841
+ import { existsSync as existsSync30 } from "node:fs";
471744
471842
  import { homedir as homedir7 } from "node:os";
471745
- import { join as join28 } from "node:path";
471843
+ import { join as join29 } from "node:path";
471746
471844
  function findChrome() {
471747
471845
  const candidates = [
471748
471846
  process.env.HYPERFRAMES_CHROME_PATH,
471749
471847
  process.env.CHROME_PATH,
471750
471848
  // puppeteer auto-downloaded headless shell
471751
- join28(
471849
+ join29(
471752
471850
  homedir7(),
471753
471851
  ".cache",
471754
471852
  "puppeteer",
@@ -471766,7 +471864,7 @@ function findChrome() {
471766
471864
  "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe"
471767
471865
  ];
471768
471866
  for (const c2 of candidates) {
471769
- if (c2 && existsSync29(c2)) return c2;
471867
+ if (c2 && existsSync30(c2)) return c2;
471770
471868
  }
471771
471869
  return void 0;
471772
471870
  }
@@ -471798,7 +471896,7 @@ var init_ffmpeg_gate = __esm({
471798
471896
  });
471799
471897
 
471800
471898
  // ../cli/src/commands/_shared/scene-audio-scan.ts
471801
- import { readFile as readFile15 } from "node:fs/promises";
471899
+ import { readFile as readFile16 } from "node:fs/promises";
471802
471900
  import { resolve as resolve25 } from "node:path";
471803
471901
  function parseRootClips(rootHtml) {
471804
471902
  const clips = [];
@@ -471839,7 +471937,7 @@ function makeFsCompositionReader(projectDir) {
471839
471937
  return async (compositionSrcRel) => {
471840
471938
  const abs = resolve25(projectDir, compositionSrcRel);
471841
471939
  try {
471842
- return await readFile15(abs, "utf-8");
471940
+ return await readFile16(abs, "utf-8");
471843
471941
  } catch {
471844
471942
  return null;
471845
471943
  }
@@ -472039,9 +472137,9 @@ __export(scene_render_exports, {
472039
472137
  qualityToCrf: () => qualityToCrf
472040
472138
  });
472041
472139
  import { execFile as execFile2 } from "node:child_process";
472042
- import { existsSync as existsSync30 } from "node:fs";
472043
- import { mkdir as mkdir12, readFile as readFile16, stat as stat3, writeFile as writeFile18 } from "node:fs/promises";
472044
- import { resolve as resolve27, relative as relative9, dirname as dirname16, basename as basename7, join as join29, isAbsolute as isAbsolute3 } from "node:path";
472140
+ import { existsSync as existsSync31 } from "node:fs";
472141
+ import { mkdir as mkdir12, readFile as readFile17, stat as stat3, writeFile as writeFile18 } from "node:fs/promises";
472142
+ import { resolve as resolve27, relative as relative9, dirname as dirname16, basename as basename7, join as join30, isAbsolute as isAbsolute3 } from "node:path";
472045
472143
  import { promisify as promisify2 } from "node:util";
472046
472144
  function qualityToCrf(quality = "standard") {
472047
472145
  return quality === "draft" ? 28 : quality === "high" ? 18 : 23;
@@ -472129,7 +472227,7 @@ async function executeSceneRender(opts = {}) {
472129
472227
  }
472130
472228
  let autoSyncApplied = false;
472131
472229
  let autoSyncWarning;
472132
- if (!opts.beatId && existsSync30(join29(projectDir, "STORYBOARD.md"))) {
472230
+ if (!opts.beatId && existsSync31(join30(projectDir, "STORYBOARD.md"))) {
472133
472231
  try {
472134
472232
  const rootPlan = await createProjectRootSyncPlan({ projectDir });
472135
472233
  const subPlans = await createSubCompDurationSyncPlans({
@@ -472221,7 +472319,7 @@ async function executeSceneRender(opts = {}) {
472221
472319
  let audioMuxWarning;
472222
472320
  try {
472223
472321
  opts.onProgress?.(0.95, "Mixing audio");
472224
- const rootHtml = await readFile16(resolve27(projectDir, root2), "utf-8");
472322
+ const rootHtml = await readFile17(resolve27(projectDir, root2), "utf-8");
472225
472323
  const audios = await scanSceneAudio({ projectDir, rootHtml });
472226
472324
  audioCount = audios.length;
472227
472325
  if (audios.length > 0) {
@@ -472306,11 +472404,11 @@ async function safeStat(p2) {
472306
472404
  }
472307
472405
  async function prepareBeatRenderRoot(opts) {
472308
472406
  const root2 = `.vibeframe/tmp/render-beat-${sanitizeFileSegment(opts.beatId)}.html`;
472309
- const reportPath = join29(opts.projectDir, "build-report.json");
472407
+ const reportPath = join30(opts.projectDir, "build-report.json");
472310
472408
  const retryWith = [
472311
472409
  `vibe build ${opts.projectDir} --beat ${opts.beatId} --stage sync --json`
472312
472410
  ];
472313
- if (!existsSync30(reportPath)) {
472411
+ if (!existsSync31(reportPath)) {
472314
472412
  return {
472315
472413
  success: false,
472316
472414
  root: root2,
@@ -472321,7 +472419,7 @@ async function prepareBeatRenderRoot(opts) {
472321
472419
  }
472322
472420
  let report;
472323
472421
  try {
472324
- report = JSON.parse(await readFile16(reportPath, "utf-8"));
472422
+ report = JSON.parse(await readFile17(reportPath, "utf-8"));
472325
472423
  } catch (error) {
472326
472424
  return {
472327
472425
  success: false,
@@ -472390,8 +472488,8 @@ async function prepareBeatRenderRoot(opts) {
472390
472488
  durationSec,
472391
472489
  narrationPath
472392
472490
  });
472393
- await mkdir12(dirname16(join29(opts.projectDir, root2)), { recursive: true });
472394
- await writeFile18(join29(opts.projectDir, root2), html, "utf-8");
472491
+ await mkdir12(dirname16(join30(opts.projectDir, root2)), { recursive: true });
472492
+ await writeFile18(join30(opts.projectDir, root2), html, "utf-8");
472395
472493
  return {
472396
472494
  success: true,
472397
472495
  root: root2,
@@ -472455,7 +472553,7 @@ function reportedBeatAssetPaths(beat) {
472455
472553
  ]);
472456
472554
  }
472457
472555
  async function writeRenderReport(projectDir, result) {
472458
- const reportPath = join29(projectDir, "render-report.json");
472556
+ const reportPath = join30(projectDir, "render-report.json");
472459
472557
  try {
472460
472558
  await writeFile18(
472461
472559
  reportPath,
@@ -472497,7 +472595,7 @@ async function writeRenderReport(projectDir, result) {
472497
472595
  }
472498
472596
  function pathExists3(projectDir, value) {
472499
472597
  const abs = isAbsolute3(value) ? value : resolve27(projectDir, value);
472500
- return existsSync30(abs);
472598
+ return existsSync31(abs);
472501
472599
  }
472502
472600
  function stringValue2(value) {
472503
472601
  return typeof value === "string" && value.length > 0 ? value : void 0;
@@ -472571,7 +472669,7 @@ var init_concurrency = __esm({
472571
472669
  });
472572
472670
 
472573
472671
  // ../cli/src/commands/_shared/build-asset-reference.ts
472574
- import { existsSync as existsSync31 } from "node:fs";
472672
+ import { existsSync as existsSync33 } from "node:fs";
472575
472673
  import { extname as extname5, isAbsolute as isAbsolute4, relative as relative10, resolve as resolve28, sep } from "node:path";
472576
472674
  function resolveTypedAssetReference(projectDir, kind3, value) {
472577
472675
  const raw2 = stringOrUndefined2(value);
@@ -472602,7 +472700,7 @@ function resolveReference(projectDir, kind3, raw2, source3, forcedError) {
472602
472700
  const absPath = isAbsolute4(raw2) ? resolve28(raw2) : resolve28(projectDir, raw2);
472603
472701
  const rel = relative10(resolve28(projectDir), absPath);
472604
472702
  const withinProject = rel.length > 0 && !rel.startsWith("..") && !isAbsolute4(rel);
472605
- const exists = withinProject && existsSync31(absPath);
472703
+ const exists = withinProject && existsSync33(absPath);
472606
472704
  let error = forcedError;
472607
472705
  if (!error && inferred && inferred !== kind3 && !isNarrationAudioReference(kind3, ext)) {
472608
472706
  error = `Asset reference "${raw2}" is a ${inferred} asset, not ${kind3}.`;
@@ -472789,9 +472887,9 @@ var init_build_backdrop_prompt = __esm({
472789
472887
  });
472790
472888
 
472791
472889
  // ../cli/src/commands/_shared/build-plan.ts
472792
- import { existsSync as existsSync33 } from "node:fs";
472793
- import { readFile as readFile17 } from "node:fs/promises";
472794
- import { dirname as dirname17, join as join30, resolve as resolve29 } from "node:path";
472890
+ import { existsSync as existsSync34 } from "node:fs";
472891
+ import { readFile as readFile18 } from "node:fs/promises";
472892
+ import { dirname as dirname17, join as join31, resolve as resolve29 } from "node:path";
472795
472893
  function backdropCostUsd(quality) {
472796
472894
  return quality === "hd" ? 0.2 : 0.05;
472797
472895
  }
@@ -472800,11 +472898,11 @@ async function createBuildPlan(opts) {
472800
472898
  loadPlanEnv(projectDir);
472801
472899
  const stage = opts.stage ?? "all";
472802
472900
  const config4 = await readProjectConfig(projectDir);
472803
- const storyboardPath = join30(projectDir, "STORYBOARD.md");
472901
+ const storyboardPath = join31(projectDir, "STORYBOARD.md");
472804
472902
  const warnings = [];
472805
472903
  const retryWith = [];
472806
472904
  const providerResolution = [];
472807
- if (!existsSync33(storyboardPath)) {
472905
+ if (!existsSync34(storyboardPath)) {
472808
472906
  const validation4 = {
472809
472907
  ok: false,
472810
472908
  issues: [
@@ -472833,7 +472931,7 @@ async function createBuildPlan(opts) {
472833
472931
  validation: validation4
472834
472932
  });
472835
472933
  }
472836
- const storyboardMd = await readFile17(storyboardPath, "utf-8");
472934
+ const storyboardMd = await readFile18(storyboardPath, "utf-8");
472837
472935
  const validation3 = validateStoryboardMarkdown(storyboardMd);
472838
472936
  const validationIssues = [...validation3.issues];
472839
472937
  const parsed = parseStoryboard(storyboardMd);
@@ -472859,7 +472957,7 @@ async function createBuildPlan(opts) {
472859
472957
  const imageQuality = opts.imageQuality ?? config4.config.build.imageQuality ?? "hd";
472860
472958
  const imageSize2 = opts.imageSize ?? config4.config.build.imageSize ?? "1536x1024";
472861
472959
  const imageRatio = imageRatioForSize(imageSize2);
472862
- const needsComposer = includeCompose && mode !== "agent" && sourceBeats.some((beat) => !existsSync33(join30(projectDir, `compositions/scene-${beat.id}.html`)));
472960
+ const needsComposer = includeCompose && mode !== "agent" && sourceBeats.some((beat) => !existsSync34(join31(projectDir, `compositions/scene-${beat.id}.html`)));
472863
472961
  const resolved = await resolvePlanProviders({
472864
472962
  projectDir,
472865
472963
  config: config4,
@@ -473007,7 +473105,7 @@ async function createBuildPlan(opts) {
473007
473105
  active: includeAssets
473008
473106
  }) : null;
473009
473107
  const compositionPath = `compositions/scene-${beat.id}.html`;
473010
- const compositionExists = existsSync33(join30(projectDir, compositionPath));
473108
+ const compositionExists = existsSync34(join31(projectDir, compositionPath));
473011
473109
  for (const asset of [narration, backdrop, keyframe, video, music]) {
473012
473110
  if (!asset) continue;
473013
473111
  if (asset.referenceError) {
@@ -473076,7 +473174,7 @@ async function createBuildPlan(opts) {
473076
473174
  }
473077
473175
  }
473078
473176
  const validationOk = !validationIssues.some((issue) => issue.severity === "error");
473079
- if (!existsSync33(join30(projectDir, config4.config.composition.entry))) {
473177
+ if (!existsSync34(join31(projectDir, config4.config.composition.entry))) {
473080
473178
  missing.add("root-composition");
473081
473179
  if (validationOk) retryWith.push(`vibe build ${projectDir} --stage sync --json`);
473082
473180
  }
@@ -473110,7 +473208,7 @@ async function createBuildPlan(opts) {
473110
473208
  }
473111
473209
  if (referenced.size > 0) {
473112
473210
  const toGenerate = resolveCharacters(parsed.frontmatter).filter(
473113
- (c2) => referenced.has(c2.name) && c2.prompt && (opts.force || !existsSync33(join30(projectDir, `assets/character-${c2.name}.png`)))
473211
+ (c2) => referenced.has(c2.name) && c2.prompt && (opts.force || !existsSync34(join31(projectDir, `assets/character-${c2.name}.png`)))
473114
473212
  );
473115
473213
  if (toGenerate.length > 0) {
473116
473214
  estimatedCostUsd += toGenerate.length * backdropCostUsd(opts.imageQuality ?? "hd");
@@ -473223,8 +473321,8 @@ function assetPlan(opts) {
473223
473321
  reason: ready ? "referenced-asset" : "invalid-reference"
473224
473322
  };
473225
473323
  }
473226
- const canonicalExists = existsSync33(join30(opts.projectDir, opts.path));
473227
- const cacheHit = opts.cache ? existsSync33(join30(opts.projectDir, opts.cache.path)) : false;
473324
+ const canonicalExists = existsSync34(join31(opts.projectDir, opts.path));
473325
+ const cacheHit = opts.cache ? existsSync34(join31(opts.projectDir, opts.cache.path)) : false;
473228
473326
  const freshness = assetFreshnessFromMetadata({
473229
473327
  projectDir: opts.projectDir,
473230
473328
  kind: opts.kind,
@@ -473422,7 +473520,7 @@ async function firstConfiguredComposer(projectDir) {
473422
473520
  }
473423
473521
  function firstExisting2(projectDir, paths) {
473424
473522
  for (const path14 of paths) {
473425
- if (existsSync33(join30(projectDir, path14))) return path14;
473523
+ if (existsSync34(join31(projectDir, path14))) return path14;
473426
473524
  }
473427
473525
  return null;
473428
473526
  }
@@ -473463,12 +473561,12 @@ function unique3(items) {
473463
473561
  return [...new Set(items.filter((item) => item.length > 0))];
473464
473562
  }
473465
473563
  function loadPlanEnv(projectDir) {
473466
- (0, import_dotenv2.config)({ path: join30(projectDir, ".env"), quiet: true });
473564
+ (0, import_dotenv2.config)({ path: join31(projectDir, ".env"), quiet: true });
473467
473565
  (0, import_dotenv2.config)({ path: resolve29(process.cwd(), ".env"), quiet: true });
473468
473566
  let dir = process.cwd();
473469
473567
  while (dir !== dirname17(dir)) {
473470
- if (existsSync33(join30(dir, "pnpm-workspace.yaml"))) {
473471
- (0, import_dotenv2.config)({ path: join30(dir, ".env"), quiet: true });
473568
+ if (existsSync34(join31(dir, "pnpm-workspace.yaml"))) {
473569
+ (0, import_dotenv2.config)({ path: join31(dir, ".env"), quiet: true });
473472
473570
  return;
473473
473571
  }
473474
473572
  dir = dirname17(dir);
@@ -473530,7 +473628,7 @@ var init_validate = __esm({
473530
473628
  // ../cli/src/commands/generate/music.ts
473531
473629
  import { resolve as resolve31 } from "node:path";
473532
473630
  import { writeFile as writeFile19 } from "node:fs/promises";
473533
- import { existsSync as existsSync34 } from "node:fs";
473631
+ import { existsSync as existsSync35 } from "node:fs";
473534
473632
  async function executeMusic(options) {
473535
473633
  try {
473536
473634
  const provider = options.provider || "elevenlabs";
@@ -473683,7 +473781,7 @@ function registerMusicCommand(parent) {
473683
473781
  if (options.melody) {
473684
473782
  spinner2.text = "Uploading melody reference...";
473685
473783
  const absPath = resolve31(process.cwd(), options.melody);
473686
- if (!existsSync34(absPath)) {
473784
+ if (!existsSync35(absPath)) {
473687
473785
  spinner2.fail(`Melody file not found: ${options.melody}`);
473688
473786
  exitWithError(notFoundError(options.melody));
473689
473787
  }
@@ -473816,9 +473914,9 @@ __export(scene_build_exports, {
473816
473914
  executeSceneBuild: () => executeSceneBuild,
473817
473915
  resolveSceneBuildMode: () => resolveSceneBuildMode
473818
473916
  });
473819
- import { existsSync as existsSync35, readFileSync as readFileSync12 } from "node:fs";
473820
- import { copyFile as copyFile4, mkdir as mkdir13, readFile as readFile18, rm as rm3, writeFile as writeFile20 } from "node:fs/promises";
473821
- import { dirname as dirname18, join as join31, resolve as resolve33 } from "node:path";
473917
+ import { existsSync as existsSync36, readFileSync as readFileSync12 } from "node:fs";
473918
+ import { copyFile as copyFile4, mkdir as mkdir13, readFile as readFile19, rm as rm3, writeFile as writeFile20 } from "node:fs/promises";
473919
+ import { dirname as dirname18, join as join33, resolve as resolve33 } from "node:path";
473822
473920
  async function executeSceneBuild(opts) {
473823
473921
  const startedAt = Date.now();
473824
473922
  const projectDir = resolve33(opts.projectDir);
@@ -473837,7 +473935,7 @@ async function executeSceneBuild(opts) {
473837
473935
  );
473838
473936
  }
473839
473937
  let sceneRepair = skippedSceneRepairSummary();
473840
- const storyboardPath = join31(projectDir, "STORYBOARD.md");
473938
+ const storyboardPath = join33(projectDir, "STORYBOARD.md");
473841
473939
  const buildPlan = await createBuildPlan({
473842
473940
  projectDir,
473843
473941
  stage: selectedStage,
@@ -473888,8 +473986,8 @@ async function executeSceneBuild(opts) {
473888
473986
  }
473889
473987
  if (!buildPlan.validation.ok) {
473890
473988
  let invalidBeats = [];
473891
- if (existsSync35(storyboardPath)) {
473892
- invalidBeats = parseStoryboard(await readFile18(storyboardPath, "utf-8")).beats;
473989
+ if (existsSync36(storyboardPath)) {
473990
+ invalidBeats = parseStoryboard(await readFile19(storyboardPath, "utf-8")).beats;
473893
473991
  }
473894
473992
  return finishBuildResult({
473895
473993
  success: false,
@@ -473913,7 +474011,7 @@ async function executeSceneBuild(opts) {
473913
474011
  totalLatencyMs: Date.now() - startedAt
473914
474012
  });
473915
474013
  }
473916
- if (!existsSync35(storyboardPath)) {
474014
+ if (!existsSync36(storyboardPath)) {
473917
474015
  return finishBuildResult({
473918
474016
  success: false,
473919
474017
  phase: "failed",
@@ -473927,7 +474025,7 @@ async function executeSceneBuild(opts) {
473927
474025
  totalLatencyMs: Date.now() - startedAt
473928
474026
  });
473929
474027
  }
473930
- const storyboardMd = await readFile18(storyboardPath, "utf-8");
474028
+ const storyboardMd = await readFile19(storyboardPath, "utf-8");
473931
474029
  const parsed = parseStoryboard(storyboardMd);
473932
474030
  if (parsed.beats.length === 0) {
473933
474031
  return finishBuildResult({
@@ -474034,6 +474132,7 @@ async function executeSceneBuild(opts) {
474034
474132
  skipVideo: opts.skipVideo ?? false,
474035
474133
  skipKeyframe: opts.skipKeyframe ?? false,
474036
474134
  skipMusic: opts.skipMusic ?? false,
474135
+ skipTranscript: opts.skipTranscript ?? false,
474037
474136
  force: opts.force ?? false,
474038
474137
  onProgress,
474039
474138
  characterPaths
@@ -474121,9 +474220,9 @@ async function executeSceneBuild(opts) {
474121
474220
  let composeData;
474122
474221
  if (shouldRunStage(selectedStage, "compose")) {
474123
474222
  if (mode === "agent") {
474124
- const compositionsDir = join31(projectDir, "compositions");
474223
+ const compositionsDir = join33(projectDir, "compositions");
474125
474224
  const missingBeats = activeBeats.filter(
474126
- (b2) => !existsSync35(join31(compositionsDir, `scene-${b2.id}.html`))
474225
+ (b2) => !existsSync36(join33(compositionsDir, `scene-${b2.id}.html`))
474127
474226
  );
474128
474227
  if (missingBeats.length > 0) {
474129
474228
  const plan = await getComposePrompts({ projectDir, beatId: opts.beatId });
@@ -474212,8 +474311,8 @@ async function executeSceneBuild(opts) {
474212
474311
  if (stageReports.compose.status === "done") {
474213
474312
  for (const beat of activeBeats) {
474214
474313
  const videoRel = `assets/video-${beat.id}.mp4`;
474215
- const compositionAbs = join31(projectDir, "compositions", `scene-${beat.id}.html`);
474216
- if (!existsSync35(join31(projectDir, videoRel)) || !existsSync35(compositionAbs)) continue;
474314
+ const compositionAbs = join33(projectDir, "compositions", `scene-${beat.id}.html`);
474315
+ if (!existsSync36(join33(projectDir, videoRel)) || !existsSync36(compositionAbs)) continue;
474217
474316
  const html = readFileSync12(compositionAbs, "utf-8");
474218
474317
  if (!html.includes(videoRel)) {
474219
474318
  warnings.push(
@@ -474271,7 +474370,7 @@ async function executeSceneBuild(opts) {
474271
474370
  });
474272
474371
  }
474273
474372
  if (shouldRunStage(selectedStage, "sync")) {
474274
- if (!existsSync35(join31(projectDir, "index.html"))) {
474373
+ if (!existsSync36(join33(projectDir, "index.html"))) {
474275
474374
  await scaffoldSceneProject({
474276
474375
  dir: projectDir,
474277
474376
  name: projectDir.split(/[\\/]/).filter(Boolean).pop(),
@@ -474416,6 +474515,9 @@ async function buildBeatPrimitives(beat, ctx) {
474416
474515
  ctx.skipVideo ? skipped("video", beat.id, "--skip-video", ctx) : dispatchVideo(beat, ctx, keyframe),
474417
474516
  ctx.skipMusic ? skipped("music", beat.id, "--skip-music", ctx) : dispatchMusic(beat, ctx)
474418
474517
  ]);
474518
+ if (!ctx.skipTranscript) {
474519
+ await dispatchTranscript(beat, narration, ctx);
474520
+ }
474419
474521
  return {
474420
474522
  outcome: {
474421
474523
  beatId: beat.id,
@@ -474533,7 +474635,7 @@ async function dispatchNarration(beat, ctx) {
474533
474635
  return {
474534
474636
  status: "cached",
474535
474637
  path: existingRel,
474536
- durationSec: await safeAudioDuration(join31(ctx.projectDir, existingRel)),
474638
+ durationSec: await safeAudioDuration(join33(ctx.projectDir, existingRel)),
474537
474639
  provider: metadata?.provider,
474538
474640
  cachePath: metadata?.cachePath,
474539
474641
  cacheKey: metadata?.cacheKey,
@@ -474557,9 +474659,9 @@ async function dispatchNarration(beat, ctx) {
474557
474659
  voice,
474558
474660
  ext: resolution.audioExtension
474559
474661
  });
474560
- const cacheAbs = join31(ctx.projectDir, cache.path);
474662
+ const cacheAbs = join33(ctx.projectDir, cache.path);
474561
474663
  const rel = `assets/narration-${beat.id}.${resolution.audioExtension}`;
474562
- const abs = join31(ctx.projectDir, rel);
474664
+ const abs = join33(ctx.projectDir, rel);
474563
474665
  if (existingRel && !ctx.force && isFreshCanonicalAsset({
474564
474666
  projectDir: ctx.projectDir,
474565
474667
  kind: "narration",
@@ -474573,7 +474675,7 @@ async function dispatchNarration(beat, ctx) {
474573
474675
  return {
474574
474676
  status: "cached",
474575
474677
  path: existingRel,
474576
- durationSec: await safeAudioDuration(join31(ctx.projectDir, existingRel)),
474678
+ durationSec: await safeAudioDuration(join33(ctx.projectDir, existingRel)),
474577
474679
  provider: resolution.provider,
474578
474680
  cachePath: cache.path,
474579
474681
  cacheKey: cache.key,
@@ -474581,7 +474683,7 @@ async function dispatchNarration(beat, ctx) {
474581
474683
  freshness: "fresh"
474582
474684
  };
474583
474685
  }
474584
- if (existsSync35(cacheAbs) && !ctx.force) {
474686
+ if (existsSync36(cacheAbs) && !ctx.force) {
474585
474687
  await mkdir13(dirname18(abs), { recursive: true });
474586
474688
  await copyFile4(cacheAbs, abs);
474587
474689
  await writeAssetMetadata({
@@ -474616,8 +474718,8 @@ async function dispatchNarration(beat, ctx) {
474616
474718
  await mkdir13(dirname18(abs), { recursive: true });
474617
474719
  await writeFile20(abs, result.audioBuffer);
474618
474720
  for (const otherExt of ["mp3", "wav"]) {
474619
- const sibling = join31(ctx.projectDir, `assets/narration-${beat.id}.${otherExt}`);
474620
- if (sibling !== abs && existsSync35(sibling)) await rm3(sibling, { force: true });
474721
+ const sibling = join33(ctx.projectDir, `assets/narration-${beat.id}.${otherExt}`);
474722
+ if (sibling !== abs && existsSync36(sibling)) await rm3(sibling, { force: true });
474621
474723
  }
474622
474724
  await mkdir13(dirname18(cacheAbs), { recursive: true });
474623
474725
  await writeFile20(cacheAbs, result.audioBuffer);
@@ -474649,6 +474751,42 @@ async function dispatchNarration(beat, ctx) {
474649
474751
  freshness: "fresh"
474650
474752
  };
474651
474753
  }
474754
+ async function dispatchTranscript(beat, narration, ctx) {
474755
+ if (!narration.path) return;
474756
+ const relPath = beatTranscriptRelPath(beat.id);
474757
+ const abs = join33(ctx.projectDir, relPath);
474758
+ const narrationFresh = narration.status === "generated";
474759
+ if (existsSync36(abs) && !ctx.force && !narrationFresh) {
474760
+ ctx.onProgress({ type: "transcript-cached", beatId: beat.id, path: relPath });
474761
+ return;
474762
+ }
474763
+ const apiKey = await getConfiguredApiKey("OPENAI_API_KEY", void 0, { cwd: ctx.projectDir });
474764
+ if (!apiKey) {
474765
+ ctx.onProgress({
474766
+ type: "transcript-skipped",
474767
+ beatId: beat.id,
474768
+ reason: "OPENAI_API_KEY not set \u2014 narration plays but word-sync timings unavailable"
474769
+ });
474770
+ return;
474771
+ }
474772
+ const words = await transcribeNarrationWords(join33(ctx.projectDir, narration.path), { apiKey });
474773
+ if (words.length === 0) {
474774
+ ctx.onProgress({
474775
+ type: "transcript-skipped",
474776
+ beatId: beat.id,
474777
+ reason: "transcription returned no word timings"
474778
+ });
474779
+ return;
474780
+ }
474781
+ await mkdir13(dirname18(abs), { recursive: true });
474782
+ await writeFile20(abs, JSON.stringify(words, null, 2), "utf-8");
474783
+ ctx.onProgress({
474784
+ type: "transcript-generated",
474785
+ beatId: beat.id,
474786
+ path: relPath,
474787
+ wordCount: words.length
474788
+ });
474789
+ }
474652
474790
  function characterSheetPrompt(name, description) {
474653
474791
  return [
474654
474792
  `Character reference sheet of an original fictional character named ${name}: ${description}.`,
@@ -474666,7 +474804,7 @@ async function buildCharacters(characters, ctx) {
474666
474804
  const size = ctx.imageSize ?? "1536x1024";
474667
474805
  for (const character of characters) {
474668
474806
  if (character.imagePath) {
474669
- if (existsSync35(join31(ctx.projectDir, character.imagePath))) {
474807
+ if (existsSync36(join33(ctx.projectDir, character.imagePath))) {
474670
474808
  paths.set(character.name, character.imagePath);
474671
474809
  ctx.onProgress({ type: "character-cached", name: character.name, path: character.imagePath });
474672
474810
  } else {
@@ -474679,7 +474817,7 @@ async function buildCharacters(characters, ctx) {
474679
474817
  if (!character.prompt) continue;
474680
474818
  const prompt3 = characterSheetPrompt(character.name, character.prompt);
474681
474819
  const rel = `assets/character-${character.name}.png`;
474682
- const abs = join31(ctx.projectDir, rel);
474820
+ const abs = join33(ctx.projectDir, rel);
474683
474821
  const metadataOptions = { quality: ctx.imageQuality, size };
474684
474822
  const cache = characterCacheDescriptor({
474685
474823
  name: character.name,
@@ -474688,7 +474826,7 @@ async function buildCharacters(characters, ctx) {
474688
474826
  quality: ctx.imageQuality,
474689
474827
  size
474690
474828
  });
474691
- if (existsSync35(abs) && !ctx.force) {
474829
+ if (existsSync36(abs) && !ctx.force) {
474692
474830
  const metadata = readAssetMetadata(ctx.projectDir, "character", character.name);
474693
474831
  if (!metadata || isFreshCanonicalAsset({
474694
474832
  projectDir: ctx.projectDir,
@@ -474704,8 +474842,8 @@ async function buildCharacters(characters, ctx) {
474704
474842
  continue;
474705
474843
  }
474706
474844
  }
474707
- const cacheAbs = join31(ctx.projectDir, cache.path);
474708
- if (existsSync35(cacheAbs) && !ctx.force) {
474845
+ const cacheAbs = join33(ctx.projectDir, cache.path);
474846
+ if (existsSync36(cacheAbs) && !ctx.force) {
474709
474847
  await mkdir13(dirname18(abs), { recursive: true });
474710
474848
  await copyFile4(cacheAbs, abs);
474711
474849
  await writeAssetMetadata({
@@ -474771,7 +474909,7 @@ async function dispatchBackdrop(beat, ctx) {
474771
474909
  if (!cue) return { status: "no-cue" };
474772
474910
  const prompt3 = augmentBackdropPrompt(cue);
474773
474911
  const rel = `assets/backdrop-${beat.id}.png`;
474774
- const abs = join31(ctx.projectDir, rel);
474912
+ const abs = join33(ctx.projectDir, rel);
474775
474913
  const size = ctx.imageSize ?? "1536x1024";
474776
474914
  const ratio = imageRatioForSize(size);
474777
474915
  const metadataOptions = { quality: ctx.imageQuality, size, ratio };
@@ -474784,7 +474922,7 @@ async function dispatchBackdrop(beat, ctx) {
474784
474922
  ratio
474785
474923
  });
474786
474924
  const metadataPath = assetMetadataPath("backdrop", beat.id);
474787
- if (existsSync35(abs) && !ctx.force) {
474925
+ if (existsSync36(abs) && !ctx.force) {
474788
474926
  const metadata = readAssetMetadata(ctx.projectDir, "backdrop", beat.id);
474789
474927
  if (!metadata || isFreshCanonicalAsset({
474790
474928
  projectDir: ctx.projectDir,
@@ -474807,8 +474945,8 @@ async function dispatchBackdrop(beat, ctx) {
474807
474945
  };
474808
474946
  }
474809
474947
  }
474810
- const cacheAbs = join31(ctx.projectDir, cache.path);
474811
- if (existsSync35(cacheAbs) && !ctx.force) {
474948
+ const cacheAbs = join33(ctx.projectDir, cache.path);
474949
+ if (existsSync36(cacheAbs) && !ctx.force) {
474812
474950
  await mkdir13(dirname18(abs), { recursive: true });
474813
474951
  await copyFile4(cacheAbs, abs);
474814
474952
  await writeAssetMetadata({
@@ -474940,7 +475078,7 @@ async function editKeyframeImage(prompt3, sheetBuffers, ctx, ratio) {
474940
475078
  }
474941
475079
  async function ensureKeyframe(beat, ctx, keyframeCue, characterRefsRel) {
474942
475080
  const rel = `assets/keyframe-${beat.id}.png`;
474943
- const abs = join31(ctx.projectDir, rel);
475081
+ const abs = join33(ctx.projectDir, rel);
474944
475082
  const size = ctx.imageSize ?? "1536x1024";
474945
475083
  const ratio = imageRatioForSize(size);
474946
475084
  const metadataOptions = { quality: ctx.imageQuality, size, ratio };
@@ -474953,7 +475091,7 @@ async function ensureKeyframe(beat, ctx, keyframeCue, characterRefsRel) {
474953
475091
  ratio,
474954
475092
  characters: characterRefsRel
474955
475093
  });
474956
- if (existsSync35(abs) && !ctx.force) {
475094
+ if (existsSync36(abs) && !ctx.force) {
474957
475095
  const metadata = readAssetMetadata(ctx.projectDir, "keyframe", beat.id);
474958
475096
  if (!metadata || isFreshCanonicalAsset({
474959
475097
  projectDir: ctx.projectDir,
@@ -474967,8 +475105,8 @@ async function ensureKeyframe(beat, ctx, keyframeCue, characterRefsRel) {
474967
475105
  return { status: "cached", rel };
474968
475106
  }
474969
475107
  }
474970
- const cacheAbs = join31(ctx.projectDir, cache.path);
474971
- if (existsSync35(cacheAbs) && !ctx.force) {
475108
+ const cacheAbs = join33(ctx.projectDir, cache.path);
475109
+ if (existsSync36(cacheAbs) && !ctx.force) {
474972
475110
  await mkdir13(dirname18(abs), { recursive: true });
474973
475111
  await copyFile4(cacheAbs, abs);
474974
475112
  await writeAssetMetadata({
@@ -474986,8 +475124,8 @@ async function ensureKeyframe(beat, ctx, keyframeCue, characterRefsRel) {
474986
475124
  }
474987
475125
  const sheetBuffers = [];
474988
475126
  for (const relPath of characterRefsRel) {
474989
- const sheetAbs = join31(ctx.projectDir, relPath);
474990
- if (existsSync35(sheetAbs)) sheetBuffers.push(await readFile18(sheetAbs));
475127
+ const sheetAbs = join33(ctx.projectDir, relPath);
475128
+ if (existsSync36(sheetAbs)) sheetBuffers.push(await readFile19(sheetAbs));
474991
475129
  }
474992
475130
  const imgCtx = {
474993
475131
  projectDir: ctx.projectDir,
@@ -475056,9 +475194,9 @@ async function dispatchVideo(beat, ctx, keyframe) {
475056
475194
  const prompt3 = stringOrUndefined4(beat.cues?.video) ?? keyframeCue;
475057
475195
  if (!prompt3) return { status: "no-cue" };
475058
475196
  const characterRefsRel = beatCharacterNames(beat.cues).map((name) => ctx.characterPaths?.get(name)).filter((p2) => typeof p2 === "string");
475059
- const characterRefsAbs = characterRefsRel.map((p2) => join31(ctx.projectDir, p2));
475197
+ const characterRefsAbs = characterRefsRel.map((p2) => join33(ctx.projectDir, p2));
475060
475198
  const rel = `assets/video-${beat.id}.mp4`;
475061
- const abs = join31(ctx.projectDir, rel);
475199
+ const abs = join33(ctx.projectDir, rel);
475062
475200
  const cache = videoCacheDescriptor({
475063
475201
  beatId: beat.id,
475064
475202
  cue: prompt3,
@@ -475070,7 +475208,7 @@ async function dispatchVideo(beat, ctx, keyframe) {
475070
475208
  keyframe: keyframeCue
475071
475209
  });
475072
475210
  const metadataPath = assetMetadataPath("video", beat.id);
475073
- if (existsSync35(abs) && !ctx.force) {
475211
+ if (existsSync36(abs) && !ctx.force) {
475074
475212
  const metadata = readAssetMetadata(ctx.projectDir, "video", beat.id);
475075
475213
  if (!metadata || isFreshCanonicalAsset({
475076
475214
  projectDir: ctx.projectDir,
@@ -475093,8 +475231,8 @@ async function dispatchVideo(beat, ctx, keyframe) {
475093
475231
  };
475094
475232
  }
475095
475233
  }
475096
- const cacheAbs = join31(ctx.projectDir, cache.path);
475097
- if (existsSync35(cacheAbs) && !ctx.force) {
475234
+ const cacheAbs = join33(ctx.projectDir, cache.path);
475235
+ if (existsSync36(cacheAbs) && !ctx.force) {
475098
475236
  await mkdir13(dirname18(abs), { recursive: true });
475099
475237
  await copyFile4(cacheAbs, abs);
475100
475238
  await writeAssetMetadata({
@@ -475125,7 +475263,7 @@ async function dispatchVideo(beat, ctx, keyframe) {
475125
475263
  ctx.onProgress({ type: "video-skipped", beatId: beat.id, reason });
475126
475264
  return { status: "skipped" };
475127
475265
  }
475128
- const keyframeImageAbs = keyframeImageRel ? join31(ctx.projectDir, keyframeImageRel) : void 0;
475266
+ const keyframeImageAbs = keyframeImageRel ? join33(ctx.projectDir, keyframeImageRel) : void 0;
475129
475267
  loadSceneBuildEnv(ctx.projectDir);
475130
475268
  const result = await executeVideoGenerate({
475131
475269
  prompt: prompt3,
@@ -475149,7 +475287,7 @@ async function dispatchVideo(beat, ctx, keyframe) {
475149
475287
  ctx.onProgress({ type: "video-failed", beatId: beat.id, error });
475150
475288
  return { status: "failed", error };
475151
475289
  }
475152
- if (result.status === "completed" && existsSync35(abs)) {
475290
+ if (result.status === "completed" && existsSync36(abs)) {
475153
475291
  await mkdir13(dirname18(cacheAbs), { recursive: true });
475154
475292
  await copyFile4(abs, cacheAbs);
475155
475293
  await writeAssetMetadata({
@@ -475217,7 +475355,7 @@ async function dispatchMusic(beat, ctx) {
475217
475355
  const prompt3 = stringOrUndefined4(beat.cues?.music);
475218
475356
  if (!prompt3) return { status: "no-cue" };
475219
475357
  const rel = `assets/music-${beat.id}.mp3`;
475220
- const abs = join31(ctx.projectDir, rel);
475358
+ const abs = join33(ctx.projectDir, rel);
475221
475359
  const duration = normalizeMusicDuration(beat.duration);
475222
475360
  const cache = musicCacheDescriptor({
475223
475361
  beatId: beat.id,
@@ -475226,7 +475364,7 @@ async function dispatchMusic(beat, ctx) {
475226
475364
  duration
475227
475365
  });
475228
475366
  const metadataPath = assetMetadataPath("music", beat.id);
475229
- if (existsSync35(abs) && !ctx.force) {
475367
+ if (existsSync36(abs) && !ctx.force) {
475230
475368
  const metadata = readAssetMetadata(ctx.projectDir, "music", beat.id);
475231
475369
  if (!metadata || isFreshCanonicalAsset({
475232
475370
  projectDir: ctx.projectDir,
@@ -475250,8 +475388,8 @@ async function dispatchMusic(beat, ctx) {
475250
475388
  };
475251
475389
  }
475252
475390
  }
475253
- const cacheAbs = join31(ctx.projectDir, cache.path);
475254
- if (existsSync35(cacheAbs) && !ctx.force) {
475391
+ const cacheAbs = join33(ctx.projectDir, cache.path);
475392
+ if (existsSync36(cacheAbs) && !ctx.force) {
475255
475393
  await mkdir13(dirname18(abs), { recursive: true });
475256
475394
  await copyFile4(cacheAbs, abs);
475257
475395
  await writeAssetMetadata({
@@ -475325,7 +475463,7 @@ async function dispatchMusic(beat, ctx) {
475325
475463
  metadataPath
475326
475464
  };
475327
475465
  }
475328
- if (!existsSync35(abs)) {
475466
+ if (!existsSync36(abs)) {
475329
475467
  const error = result.outputPath ? `music output was not written at ${abs}` : "music generation did not return an output file";
475330
475468
  ctx.onProgress({ type: "music-failed", beatId: beat.id, error });
475331
475469
  return { status: "failed", error };
@@ -475361,12 +475499,12 @@ async function dispatchMusic(beat, ctx) {
475361
475499
  };
475362
475500
  }
475363
475501
  function loadSceneBuildEnv(projectDir) {
475364
- (0, import_dotenv3.config)({ path: join31(projectDir, ".env"), quiet: true });
475502
+ (0, import_dotenv3.config)({ path: join33(projectDir, ".env"), quiet: true });
475365
475503
  (0, import_dotenv3.config)({ path: resolve33(process.cwd(), ".env"), quiet: true });
475366
475504
  let dir = process.cwd();
475367
475505
  while (dir !== dirname18(dir)) {
475368
- if (existsSync35(join31(dir, "pnpm-workspace.yaml"))) {
475369
- (0, import_dotenv3.config)({ path: join31(dir, ".env"), quiet: true });
475506
+ if (existsSync36(join33(dir, "pnpm-workspace.yaml"))) {
475507
+ (0, import_dotenv3.config)({ path: join33(dir, ".env"), quiet: true });
475370
475508
  return;
475371
475509
  }
475372
475510
  dir = dirname18(dir);
@@ -475582,7 +475720,7 @@ function mergeBeatOutcomes(base, updates) {
475582
475720
  }
475583
475721
  function firstExisting3(projectDir, relPaths) {
475584
475722
  for (const rel of relPaths) {
475585
- if (existsSync35(join31(projectDir, rel))) return rel;
475723
+ if (existsSync36(join33(projectDir, rel))) return rel;
475586
475724
  }
475587
475725
  return null;
475588
475726
  }
@@ -475613,7 +475751,7 @@ async function apiKeyForVideoProvider(provider, projectDir) {
475613
475751
  return getApiKeyFromConfig(providerKey, { cwd: projectDir });
475614
475752
  }
475615
475753
  async function finalizeBuildResult(projectDir, startedAt, result) {
475616
- const reportPath = join31(projectDir, "build-report.json");
475754
+ const reportPath = join33(projectDir, "build-report.json");
475617
475755
  if (result.stageReports) {
475618
475756
  for (const report of Object.values(result.stageReports)) {
475619
475757
  if (report.status === "pending") report.status = "skipped";
@@ -475772,7 +475910,7 @@ function normalizeReportDuration(value) {
475772
475910
  }
475773
475911
  function buildReportComposition(projectDir, result, beatId) {
475774
475912
  const path14 = `compositions/scene-${beatId}.html`;
475775
- const exists = existsSync35(join31(projectDir, path14));
475913
+ const exists = existsSync36(join33(projectDir, path14));
475776
475914
  const written = composeWrittenEntry(result, beatId);
475777
475915
  if (written) {
475778
475916
  return {
@@ -475829,8 +475967,8 @@ function summarizeBuildBeats(projectDir, beats) {
475829
475967
  let compositionsReady = 0;
475830
475968
  for (const beat of beats) {
475831
475969
  if (beatAssetsReady(beat)) assetsReady += 1;
475832
- const compositionPath = join31(projectDir, "compositions", `scene-${beat.beatId}.html`);
475833
- if (existsSync35(compositionPath)) {
475970
+ const compositionPath = join33(projectDir, "compositions", `scene-${beat.beatId}.html`);
475971
+ if (existsSync36(compositionPath)) {
475834
475972
  compositionsReady += 1;
475835
475973
  } else {
475836
475974
  needsAuthor.push(beat.beatId);
@@ -475872,6 +476010,8 @@ var init_scene_build = __esm({
475872
476010
  init_compose_scenes_skills();
475873
476011
  init_compose_prompts();
475874
476012
  init_config();
476013
+ init_api_key();
476014
+ init_transcribe_narration();
475875
476015
  init_scene_render();
475876
476016
  init_storyboard_parse();
475877
476017
  init_scene_project();
@@ -476000,18 +476140,18 @@ __export(ai_audio_exports, {
476000
476140
  executeVoiceClone: () => executeVoiceClone
476001
476141
  });
476002
476142
  import { resolve as resolve35, dirname as dirname19, basename as basename8, extname as extname6 } from "node:path";
476003
- import { readFile as readFile19, writeFile as writeFile21 } from "node:fs/promises";
476004
- import { existsSync as existsSync36 } from "node:fs";
476143
+ import { readFile as readFile20, writeFile as writeFile21 } from "node:fs/promises";
476144
+ import { existsSync as existsSync37 } from "node:fs";
476005
476145
  async function executeTranscribe(options) {
476006
476146
  const { audioPath, language, output: output3, format: format4, apiKey } = options;
476007
476147
  try {
476008
476148
  const key2 = apiKey || process.env.OPENAI_API_KEY;
476009
476149
  if (!key2) return { success: false, error: "OPENAI_API_KEY required" };
476010
476150
  const absPath = resolve35(process.cwd(), audioPath);
476011
- if (!existsSync36(absPath)) return { success: false, error: `File not found: ${absPath}` };
476151
+ if (!existsSync37(absPath)) return { success: false, error: `File not found: ${absPath}` };
476012
476152
  const whisper = new WhisperProvider();
476013
476153
  await whisper.initialize({ apiKey: key2 });
476014
- const audioBuffer = await readFile19(absPath);
476154
+ const audioBuffer = await readFile20(absPath);
476015
476155
  const audioBlob = new Blob([audioBuffer]);
476016
476156
  const result = await whisper.transcribe(audioBlob, language);
476017
476157
  if (result.status === "failed") {
@@ -476041,8 +476181,8 @@ async function executeIsolate(options) {
476041
476181
  const key2 = apiKey || process.env.ELEVENLABS_API_KEY;
476042
476182
  if (!key2) return { success: false, error: "ELEVENLABS_API_KEY required" };
476043
476183
  const absPath = resolve35(process.cwd(), audioPath);
476044
- if (!existsSync36(absPath)) return { success: false, error: `File not found: ${absPath}` };
476045
- const audioBuffer = await readFile19(absPath);
476184
+ if (!existsSync37(absPath)) return { success: false, error: `File not found: ${absPath}` };
476185
+ const audioBuffer = await readFile20(absPath);
476046
476186
  const elevenlabs = new ElevenLabsProvider();
476047
476187
  await elevenlabs.initialize({ apiKey: key2 });
476048
476188
  const result = await elevenlabs.isolateVocals(audioBuffer);
@@ -476067,8 +476207,8 @@ async function executeVoiceClone(options) {
476067
476207
  const audioBuffers = [];
476068
476208
  for (const samplePath of samplePaths) {
476069
476209
  const absPath = resolve35(process.cwd(), samplePath);
476070
- if (!existsSync36(absPath)) return { success: false, error: `File not found: ${samplePath}` };
476071
- const buffer = await readFile19(absPath);
476210
+ if (!existsSync37(absPath)) return { success: false, error: `File not found: ${samplePath}` };
476211
+ const buffer = await readFile20(absPath);
476072
476212
  audioBuffers.push(buffer);
476073
476213
  }
476074
476214
  const elevenlabs = new ElevenLabsProvider();
@@ -476089,7 +476229,7 @@ async function executeDub(options) {
476089
476229
  const { mediaPath, language, source: source3, voice, analyzeOnly, output: output3 } = options;
476090
476230
  try {
476091
476231
  const absPath = resolve35(process.cwd(), mediaPath);
476092
- if (!existsSync36(absPath)) return { success: false, error: `File not found: ${absPath}` };
476232
+ if (!existsSync37(absPath)) return { success: false, error: `File not found: ${absPath}` };
476093
476233
  const openaiKey = process.env.OPENAI_API_KEY;
476094
476234
  const anthropicKey = process.env.ANTHROPIC_API_KEY;
476095
476235
  const elevenlabsKey = process.env.ELEVENLABS_API_KEY;
@@ -476106,7 +476246,7 @@ async function executeDub(options) {
476106
476246
  }
476107
476247
  const whisper = new WhisperProvider();
476108
476248
  await whisper.initialize({ apiKey: openaiKey });
476109
- const audioBuffer = await readFile19(audioPath);
476249
+ const audioBuffer = await readFile20(audioPath);
476110
476250
  const audioBlob = new Blob([audioBuffer]);
476111
476251
  const transcriptResult = await whisper.transcribe(audioBlob, source3);
476112
476252
  if (transcriptResult.status === "failed" || !transcriptResult.segments) {
@@ -476217,8 +476357,8 @@ async function executeDuck(options) {
476217
476357
  if (!commandExists("ffmpeg")) return { success: false, error: "FFmpeg not found" };
476218
476358
  const absMusicPath = resolve35(process.cwd(), musicPath);
476219
476359
  const absVoicePath = resolve35(process.cwd(), voicePath);
476220
- if (!existsSync36(absMusicPath)) return { success: false, error: `Music file not found: ${absMusicPath}` };
476221
- if (!existsSync36(absVoicePath)) return { success: false, error: `Voice file not found: ${absVoicePath}` };
476360
+ if (!existsSync37(absMusicPath)) return { success: false, error: `Music file not found: ${absMusicPath}` };
476361
+ if (!existsSync37(absVoicePath)) return { success: false, error: `Voice file not found: ${absVoicePath}` };
476222
476362
  const defaultOutput = resolve35(dirname19(absMusicPath), `${basename8(absMusicPath, extname6(absMusicPath))}-ducked${extname6(absMusicPath)}`);
476223
476363
  const outputPath = resolve35(process.cwd(), output3 || defaultOutput);
476224
476364
  const filter4 = `[1:a]asplit=2[sc][mix];[0:a][sc]sidechaincompress=threshold=${threshold}dB:ratio=${ratio}:attack=${attack}:release=${release}[ducked];[ducked][mix]amix=inputs=2:duration=longest`;
@@ -476232,7 +476372,7 @@ async function executeDuck(options) {
476232
476372
  "-y",
476233
476373
  outputPath
476234
476374
  ], { timeout: 12e4, maxBuffer: 50 * 1024 * 1024 });
476235
- if (!existsSync36(outputPath)) return { success: false, error: "FFmpeg failed to create output" };
476375
+ if (!existsSync37(outputPath)) return { success: false, error: "FFmpeg failed to create output" };
476236
476376
  return { success: true, outputPath };
476237
476377
  } catch (error) {
476238
476378
  return { success: false, error: `Audio ducking failed: ${error instanceof Error ? error.message : String(error)}` };
@@ -476248,8 +476388,8 @@ var init_ai_audio = __esm({
476248
476388
  });
476249
476389
 
476250
476390
  // ../cli/src/commands/_shared/edit/silence-cut.ts
476251
- import { existsSync as existsSync37 } from "node:fs";
476252
- import { readFile as readFile20 } from "node:fs/promises";
476391
+ import { existsSync as existsSync38 } from "node:fs";
476392
+ import { readFile as readFile21 } from "node:fs/promises";
476253
476393
  async function detectSilencePeriods(videoPath, noiseThreshold, minDuration) {
476254
476394
  const totalDuration = await getVideoDuration(videoPath);
476255
476395
  const { stdout, stderr } = await execSafe(
@@ -476299,7 +476439,7 @@ async function detectSilencePeriodsWithGemini(videoPath, minDuration, options) {
476299
476439
  }
476300
476440
  const gemini = new GeminiProvider();
476301
476441
  await gemini.initialize({ apiKey: geminiApiKey });
476302
- const videoBuffer = await readFile20(videoPath);
476442
+ const videoBuffer = await readFile21(videoPath);
476303
476443
  const modelId = options.model ? resolveGeminiTextModel(options.model) : void 0;
476304
476444
  const prompt3 = `Analyze this video and identify all silent or dead segments where there is NO meaningful content.
476305
476445
 
@@ -476375,7 +476515,7 @@ async function executeSilenceCut(options) {
476375
476515
  analyzeOnly = false,
476376
476516
  useGemini = false
476377
476517
  } = options;
476378
- if (!existsSync37(videoPath)) {
476518
+ if (!existsSync38(videoPath)) {
476379
476519
  return { success: false, error: `Video not found: ${videoPath}` };
476380
476520
  }
476381
476521
  if (!commandExists("ffmpeg")) {
@@ -476483,11 +476623,11 @@ var init_silence_cut = __esm({
476483
476623
  });
476484
476624
 
476485
476625
  // ../cli/src/commands/_shared/edit/jump-cut.ts
476486
- import { existsSync as existsSync38 } from "node:fs";
476487
- import { readFile as readFile21, writeFile as writeFile22, mkdir as mkdir14 } from "node:fs/promises";
476488
- import { join as join33 } from "node:path";
476626
+ import { existsSync as existsSync39 } from "node:fs";
476627
+ import { readFile as readFile22, writeFile as writeFile22, mkdir as mkdir14 } from "node:fs/promises";
476628
+ import { join as join34 } from "node:path";
476489
476629
  async function transcribeWithWords(audioPath, apiKey, language) {
476490
- const audioBuffer = await readFile21(audioPath);
476630
+ const audioBuffer = await readFile22(audioPath);
476491
476631
  const audioBlob = new Blob([audioBuffer]);
476492
476632
  const formData = new FormData();
476493
476633
  formData.append("file", audioBlob, "audio.wav");
@@ -476546,7 +476686,7 @@ async function executeJumpCut(options) {
476546
476686
  analyzeOnly = false,
476547
476687
  apiKey
476548
476688
  } = options;
476549
- if (!existsSync38(videoPath)) {
476689
+ if (!existsSync39(videoPath)) {
476550
476690
  return { success: false, error: `Video not found: ${videoPath}` };
476551
476691
  }
476552
476692
  if (!commandExists("ffmpeg")) {
@@ -476565,7 +476705,7 @@ async function executeJumpCut(options) {
476565
476705
  try {
476566
476706
  const tmpDir = `/tmp/vibe_jumpcut_${Date.now()}`;
476567
476707
  await mkdir14(tmpDir, { recursive: true });
476568
- const audioPath = join33(tmpDir, "audio.wav");
476708
+ const audioPath = join34(tmpDir, "audio.wav");
476569
476709
  try {
476570
476710
  await execSafe(
476571
476711
  "ffmpeg",
@@ -476619,7 +476759,7 @@ async function executeJumpCut(options) {
476619
476759
  const segmentPaths = [];
476620
476760
  for (let i2 = 0; i2 < segments.length; i2++) {
476621
476761
  const seg = segments[i2];
476622
- const segPath = join33(tmpDir, `seg-${i2.toString().padStart(4, "0")}.ts`);
476762
+ const segPath = join34(tmpDir, `seg-${i2.toString().padStart(4, "0")}.ts`);
476623
476763
  const duration = seg.end - seg.start;
476624
476764
  await execSafe(
476625
476765
  "ffmpeg",
@@ -476642,7 +476782,7 @@ async function executeJumpCut(options) {
476642
476782
  segmentPaths.push(segPath);
476643
476783
  }
476644
476784
  const concatList = segmentPaths.map((p2) => `file '${p2}'`).join("\n");
476645
- const listPath = join33(tmpDir, "concat.txt");
476785
+ const listPath = join34(tmpDir, "concat.txt");
476646
476786
  await writeFile22(listPath, concatList);
476647
476787
  await execSafe(
476648
476788
  "ffmpeg",
@@ -476749,8 +476889,8 @@ __export(remotion_exports, {
476749
476889
  wrapComponentWithVideo: () => wrapComponentWithVideo
476750
476890
  });
476751
476891
  import { writeFile as writeFile23, mkdir as mkdir15, rm as rm4, copyFile as copyFile5 } from "node:fs/promises";
476752
- import { existsSync as existsSync39 } from "node:fs";
476753
- import { join as join34 } from "node:path";
476892
+ import { existsSync as existsSync40 } from "node:fs";
476893
+ import { join as join35 } from "node:path";
476754
476894
  import { tmpdir as tmpdir3 } from "node:os";
476755
476895
  import { createHash as createHash7 } from "node:crypto";
476756
476896
  async function ensureRemotionInstalled() {
@@ -476769,7 +476909,7 @@ async function ensureRemotionInstalled() {
476769
476909
  }
476770
476910
  }
476771
476911
  async function scaffoldRemotionProject(componentCode, componentName, opts) {
476772
- const dir = join34(tmpdir3(), `vibe_motion_${Date.now()}`);
476912
+ const dir = join35(tmpdir3(), `vibe_motion_${Date.now()}`);
476773
476913
  await mkdir15(dir, { recursive: true });
476774
476914
  const deps = {
476775
476915
  remotion: REMOTION_VERSION,
@@ -476788,7 +476928,7 @@ async function scaffoldRemotionProject(componentCode, componentName, opts) {
476788
476928
  dependencies: deps
476789
476929
  };
476790
476930
  const packageJsonStr = JSON.stringify(packageJson, null, 2);
476791
- await writeFile23(join34(dir, "package.json"), packageJsonStr);
476931
+ await writeFile23(join35(dir, "package.json"), packageJsonStr);
476792
476932
  const tsconfig = {
476793
476933
  compilerOptions: {
476794
476934
  target: "ES2020",
@@ -476800,8 +476940,8 @@ async function scaffoldRemotionProject(componentCode, componentName, opts) {
476800
476940
  skipLibCheck: true
476801
476941
  }
476802
476942
  };
476803
- await writeFile23(join34(dir, "tsconfig.json"), JSON.stringify(tsconfig, null, 2));
476804
- await writeFile23(join34(dir, "Component.tsx"), componentCode);
476943
+ await writeFile23(join35(dir, "tsconfig.json"), JSON.stringify(tsconfig, null, 2));
476944
+ await writeFile23(join35(dir, "Component.tsx"), componentCode);
476805
476945
  const rootCode = `import { registerRoot, Composition } from "remotion";
476806
476946
  import { ${componentName} } from "./Component";
476807
476947
 
@@ -476820,14 +476960,14 @@ const Root = () => {
476820
476960
 
476821
476961
  registerRoot(Root);
476822
476962
  `;
476823
- await writeFile23(join34(dir, "Root.tsx"), rootCode);
476963
+ await writeFile23(join35(dir, "Root.tsx"), rootCode);
476824
476964
  const depsHash = createHash7("md5").update(packageJsonStr).digest("hex").slice(0, 12);
476825
- const cacheMarker = join34(REMOTION_CACHE_DIR, `.deps-${depsHash}`);
476826
- const cachedModules = join34(REMOTION_CACHE_DIR, "node_modules");
476827
- if (existsSync39(cacheMarker) && existsSync39(cachedModules)) {
476965
+ const cacheMarker = join35(REMOTION_CACHE_DIR, `.deps-${depsHash}`);
476966
+ const cachedModules = join35(REMOTION_CACHE_DIR, "node_modules");
476967
+ if (existsSync40(cacheMarker) && existsSync40(cachedModules)) {
476828
476968
  const { symlink } = await import("node:fs/promises");
476829
476969
  try {
476830
- await symlink(cachedModules, join34(dir, "node_modules"), "dir");
476970
+ await symlink(cachedModules, join35(dir, "node_modules"), "dir");
476831
476971
  } catch {
476832
476972
  await this_npmInstall(dir);
476833
476973
  }
@@ -476835,12 +476975,12 @@ registerRoot(Root);
476835
476975
  await this_npmInstall(dir);
476836
476976
  try {
476837
476977
  await mkdir15(REMOTION_CACHE_DIR, { recursive: true });
476838
- await writeFile23(join34(REMOTION_CACHE_DIR, "package.json"), packageJsonStr);
476839
- if (existsSync39(join34(dir, "node_modules"))) {
476978
+ await writeFile23(join35(REMOTION_CACHE_DIR, "package.json"), packageJsonStr);
476979
+ if (existsSync40(join35(dir, "node_modules"))) {
476840
476980
  const { rename: rename7, symlink } = await import("node:fs/promises");
476841
- await rename7(join34(dir, "node_modules"), cachedModules).catch(() => {
476981
+ await rename7(join35(dir, "node_modules"), cachedModules).catch(() => {
476842
476982
  });
476843
- await symlink(cachedModules, join34(dir, "node_modules"), "dir").catch(() => {
476983
+ await symlink(cachedModules, join35(dir, "node_modules"), "dir").catch(() => {
476844
476984
  });
476845
476985
  await writeFile23(cacheMarker, depsHash);
476846
476986
  }
@@ -476877,7 +477017,7 @@ async function renderMotion(options) {
476877
477017
  }
476878
477018
  );
476879
477019
  try {
476880
- const entryPoint = join34(dir, "Root.tsx");
477020
+ const entryPoint = join35(dir, "Root.tsx");
476881
477021
  const { execFile: execFile3 } = await import("node:child_process");
476882
477022
  const { promisify: promisify3 } = await import("node:util");
476883
477023
  const execFileAsync3 = promisify3(execFile3);
@@ -477010,10 +477150,10 @@ async function renderWithEmbeddedImage(options) {
477010
477150
  }
477011
477151
  );
477012
477152
  try {
477013
- const publicDir = join34(dir, "public");
477153
+ const publicDir = join35(dir, "public");
477014
477154
  await mkdir15(publicDir, { recursive: true });
477015
- await copyFile5(options.imagePath, join34(publicDir, options.imageFileName));
477016
- const entryPoint = join34(dir, "Root.tsx");
477155
+ await copyFile5(options.imagePath, join35(publicDir, options.imageFileName));
477156
+ const entryPoint = join35(dir, "Root.tsx");
477017
477157
  const mp4Out = options.outputPath.replace(/\.\w+$/, ".mp4");
477018
477158
  const { execFile: execFileImg } = await import("node:child_process");
477019
477159
  const { promisify: promisifyImg } = await import("node:util");
@@ -477074,10 +477214,10 @@ async function renderWithEmbeddedVideo(options) {
477074
477214
  }
477075
477215
  );
477076
477216
  try {
477077
- const publicDir = join34(dir, "public");
477217
+ const publicDir = join35(dir, "public");
477078
477218
  await mkdir15(publicDir, { recursive: true });
477079
- await copyFile5(options.videoPath, join34(publicDir, options.videoFileName));
477080
- const entryPoint = join34(dir, "Root.tsx");
477219
+ await copyFile5(options.videoPath, join35(publicDir, options.videoFileName));
477220
+ const entryPoint = join35(dir, "Root.tsx");
477081
477221
  const mp4VideoOnly = options.outputPath.replace(/\.\w+$/, "_video_only.mp4");
477082
477222
  const { execFile: execFileVid } = await import("node:child_process");
477083
477223
  const { promisify: promisifyVid } = await import("node:util");
@@ -477493,14 +477633,14 @@ var init_remotion = __esm({
477493
477633
  "use strict";
477494
477634
  init_exec_safe();
477495
477635
  REMOTION_VERSION = "4.0.447";
477496
- REMOTION_CACHE_DIR = join34(tmpdir3(), "vibe_remotion_cache");
477636
+ REMOTION_CACHE_DIR = join35(tmpdir3(), "vibe_remotion_cache");
477497
477637
  }
477498
477638
  });
477499
477639
 
477500
477640
  // ../cli/src/commands/_shared/edit/caption.ts
477501
- import { existsSync as existsSync40 } from "node:fs";
477502
- import { readFile as readFile22, writeFile as writeFile24, mkdir as mkdir16 } from "node:fs/promises";
477503
- import { dirname as dirname20, basename as basename9, extname as extname7, join as join35 } from "node:path";
477641
+ import { existsSync as existsSync41 } from "node:fs";
477642
+ import { readFile as readFile23, writeFile as writeFile24, mkdir as mkdir16 } from "node:fs/promises";
477643
+ import { dirname as dirname20, basename as basename9, extname as extname7, join as join36 } from "node:path";
477504
477644
  function getCaptionForceStyle(style, fontSize, fontColor, position) {
477505
477645
  const alignment = position === "top" ? 8 : position === "center" ? 5 : 2;
477506
477646
  const marginV = position === "center" ? 0 : 30;
@@ -477528,7 +477668,7 @@ async function executeCaption(options) {
477528
477668
  position = "bottom",
477529
477669
  apiKey
477530
477670
  } = options;
477531
- if (!existsSync40(videoPath)) {
477671
+ if (!existsSync41(videoPath)) {
477532
477672
  return { success: false, error: `Video not found: ${videoPath}` };
477533
477673
  }
477534
477674
  if (!commandExists("ffmpeg")) {
@@ -477547,8 +477687,8 @@ async function executeCaption(options) {
477547
477687
  try {
477548
477688
  const tmpDir = `/tmp/vibe_caption_${Date.now()}`;
477549
477689
  await mkdir16(tmpDir, { recursive: true });
477550
- const audioPath = join35(tmpDir, "audio.wav");
477551
- const srtPath = join35(tmpDir, "captions.srt");
477690
+ const audioPath = join36(tmpDir, "audio.wav");
477691
+ const srtPath = join36(tmpDir, "captions.srt");
477552
477692
  try {
477553
477693
  await execSafe(
477554
477694
  "ffmpeg",
@@ -477569,7 +477709,7 @@ async function executeCaption(options) {
477569
477709
  );
477570
477710
  const whisper = new WhisperProvider();
477571
477711
  await whisper.initialize({ apiKey: openaiKey });
477572
- const audioBuffer = await readFile22(audioPath);
477712
+ const audioBuffer = await readFile23(audioPath);
477573
477713
  const audioBlob = new Blob([audioBuffer]);
477574
477714
  const transcriptResult = await whisper.transcribe(audioBlob, language);
477575
477715
  if (transcriptResult.status === "failed" || !transcriptResult.segments || transcriptResult.segments.length === 0) {
@@ -477617,7 +477757,7 @@ async function executeCaption(options) {
477617
477757
  const remotionErr = await ensureRemotionInstalled2();
477618
477758
  if (remotionErr) {
477619
477759
  const outputDir2 = dirname20(outputPath);
477620
- const outputSrtPath2 = join35(
477760
+ const outputSrtPath2 = join36(
477621
477761
  outputDir2,
477622
477762
  basename9(outputPath, extname7(outputPath)) + ".srt"
477623
477763
  );
@@ -477656,7 +477796,7 @@ SRT saved to: ${outputSrtPath2}` };
477656
477796
  });
477657
477797
  if (!renderResult.success) {
477658
477798
  const outputDir2 = dirname20(outputPath);
477659
- const outputSrtPath2 = join35(
477799
+ const outputSrtPath2 = join36(
477660
477800
  outputDir2,
477661
477801
  basename9(outputPath, extname7(outputPath)) + ".srt"
477662
477802
  );
@@ -477669,7 +477809,7 @@ SRT saved to: ${outputSrtPath2}`
477669
477809
  }
477670
477810
  }
477671
477811
  const outputDir = dirname20(outputPath);
477672
- const outputSrtPath = join35(
477812
+ const outputSrtPath = join36(
477673
477813
  outputDir,
477674
477814
  basename9(outputPath, extname7(outputPath)) + ".srt"
477675
477815
  );
@@ -477706,10 +477846,10 @@ var init_caption = __esm({
477706
477846
  });
477707
477847
 
477708
477848
  // ../cli/src/commands/_shared/edit/noise-reduce.ts
477709
- import { existsSync as existsSync41 } from "node:fs";
477849
+ import { existsSync as existsSync43 } from "node:fs";
477710
477850
  async function executeNoiseReduce(options) {
477711
477851
  const { inputPath, outputPath, strength = "medium", noiseFloor } = options;
477712
- if (!existsSync41(inputPath)) {
477852
+ if (!existsSync43(inputPath)) {
477713
477853
  return { success: false, error: `File not found: ${inputPath}` };
477714
477854
  }
477715
477855
  if (!commandExists("ffmpeg")) {
@@ -477766,7 +477906,7 @@ var init_noise_reduce = __esm({
477766
477906
  });
477767
477907
 
477768
477908
  // ../cli/src/commands/_shared/edit/fade.ts
477769
- import { existsSync as existsSync43 } from "node:fs";
477909
+ import { existsSync as existsSync44 } from "node:fs";
477770
477910
  async function executeFade(options) {
477771
477911
  const {
477772
477912
  videoPath,
@@ -477776,7 +477916,7 @@ async function executeFade(options) {
477776
477916
  audioOnly = false,
477777
477917
  videoOnly = false
477778
477918
  } = options;
477779
- if (!existsSync43(videoPath)) {
477919
+ if (!existsSync44(videoPath)) {
477780
477920
  return { success: false, error: `Video not found: ${videoPath}` };
477781
477921
  }
477782
477922
  if (!commandExists("ffmpeg")) {
@@ -477843,8 +477983,8 @@ var init_fade = __esm({
477843
477983
  });
477844
477984
 
477845
477985
  // ../cli/src/commands/_shared/edit/translate-srt.ts
477846
- import { existsSync as existsSync44 } from "node:fs";
477847
- import { readFile as readFile23, writeFile as writeFile25 } from "node:fs/promises";
477986
+ import { existsSync as existsSync45 } from "node:fs";
477987
+ import { readFile as readFile24, writeFile as writeFile25 } from "node:fs/promises";
477848
477988
  async function executeTranslateSrt(options) {
477849
477989
  const {
477850
477990
  srtPath,
@@ -477854,11 +477994,11 @@ async function executeTranslateSrt(options) {
477854
477994
  sourceLanguage,
477855
477995
  apiKey
477856
477996
  } = options;
477857
- if (!existsSync44(srtPath)) {
477997
+ if (!existsSync45(srtPath)) {
477858
477998
  return { success: false, error: `SRT file not found: ${srtPath}` };
477859
477999
  }
477860
478000
  try {
477861
- const srtContent = await readFile23(srtPath, "utf-8");
478001
+ const srtContent = await readFile24(srtPath, "utf-8");
477862
478002
  const segments = parseSRT(srtContent);
477863
478003
  if (segments.length === 0) {
477864
478004
  return { success: false, error: "No subtitle segments found in SRT file" };
@@ -477971,7 +478111,7 @@ var init_translate_srt = __esm({
477971
478111
  });
477972
478112
 
477973
478113
  // ../cli/src/commands/_shared/edit/text-overlay.ts
477974
- import { existsSync as existsSync45 } from "node:fs";
478114
+ import { existsSync as existsSync46 } from "node:fs";
477975
478115
  import { resolve as resolve36 } from "node:path";
477976
478116
  function detectSystemFont() {
477977
478117
  const platform = process.platform;
@@ -477982,7 +478122,7 @@ function detectSystemFont() {
477982
478122
  "/Library/Fonts/Arial.ttf"
477983
478123
  ];
477984
478124
  for (const f2 of candidates) {
477985
- if (existsSync45(f2)) return f2;
478125
+ if (existsSync46(f2)) return f2;
477986
478126
  }
477987
478127
  } else if (platform === "linux") {
477988
478128
  const candidates = [
@@ -477991,7 +478131,7 @@ function detectSystemFont() {
477991
478131
  "/usr/share/fonts/TTF/DejaVuSans-Bold.ttf"
477992
478132
  ];
477993
478133
  for (const f2 of candidates) {
477994
- if (existsSync45(f2)) return f2;
478134
+ if (existsSync46(f2)) return f2;
477995
478135
  }
477996
478136
  } else if (platform === "win32") {
477997
478137
  const candidates = [
@@ -477999,7 +478139,7 @@ function detectSystemFont() {
477999
478139
  "C:\\Windows\\Fonts\\segoeui.ttf"
478000
478140
  ];
478001
478141
  for (const f2 of candidates) {
478002
- if (existsSync45(f2)) return f2;
478142
+ if (existsSync46(f2)) return f2;
478003
478143
  }
478004
478144
  }
478005
478145
  return null;
@@ -478020,7 +478160,7 @@ async function applyTextOverlays(options) {
478020
478160
  }
478021
478161
  const absVideoPath = resolve36(process.cwd(), videoPath);
478022
478162
  const absOutputPath = resolve36(process.cwd(), outputPath);
478023
- if (!existsSync45(absVideoPath)) {
478163
+ if (!existsSync46(absVideoPath)) {
478024
478164
  return { success: false, error: `Video not found: ${absVideoPath}` };
478025
478165
  }
478026
478166
  if (!commandExists("ffmpeg")) {
@@ -478201,7 +478341,7 @@ var init_ai_edit = __esm({
478201
478341
 
478202
478342
  // ../cli/src/commands/ai-edit-cli.ts
478203
478343
  import { resolve as resolve37, extname as extname8, basename as basename10 } from "node:path";
478204
- import { existsSync as existsSync46 } from "node:fs";
478344
+ import { existsSync as existsSync47 } from "node:fs";
478205
478345
  function registerEditCommands(aiCommand) {
478206
478346
  aiCommand.command("silence-cut").alias("sc").description("Remove silent segments from video (FFmpeg default, or Gemini for smart detection)").argument("<video>", "Video file path").option("-o, --output <path>", "Output file path (default: <name>-cut.<ext>)").option("--noise <dB>", "Silence threshold in dB (default: -30)", "-30").option("-d, --min-duration <seconds>", "Minimum silence duration to cut (default: 0.5)", "0.5").option("--padding <seconds>", "Padding around non-silent segments (default: 0.1)", "0.1").option("--analyze-only", "(deprecated \u2014 use `vibe detect silence`) Only detect silence, don't cut").option("--use-gemini", "Use Gemini Video Understanding for context-aware silence detection").option("-m, --model <model>", "Gemini model (default: flash)").option("--low-res", "Low resolution mode for longer videos (Gemini only)").option("-k, --api-key <key>", "Google API key override (or set GOOGLE_API_KEY env)").option("--dry-run", "Preview parameters without executing").addHelpText("after", `
478207
478347
  Examples:
@@ -478218,7 +478358,7 @@ No API key needed (FFmpeg only). Use --use-gemini for smart detection (requires
478218
478358
  validateOutputPath(options.output);
478219
478359
  }
478220
478360
  const absVideoPath = resolve37(process.cwd(), videoPath);
478221
- if (!existsSync46(absVideoPath)) {
478361
+ if (!existsSync47(absVideoPath)) {
478222
478362
  exitWithError(notFoundError(absVideoPath));
478223
478363
  }
478224
478364
  if (!commandExists("ffmpeg")) {
@@ -478326,7 +478466,7 @@ Requires: OPENAI_API_KEY (Whisper transcription) + FFmpeg`).action(async (videoP
478326
478466
  validateOutputPath(options.output);
478327
478467
  }
478328
478468
  const absVideoPath = resolve37(process.cwd(), videoPath);
478329
- if (!existsSync46(absVideoPath)) {
478469
+ if (!existsSync47(absVideoPath)) {
478330
478470
  exitWithError(notFoundError(absVideoPath));
478331
478471
  }
478332
478472
  if (!commandExists("ffmpeg")) {
@@ -478407,7 +478547,7 @@ Requires: OPENAI_API_KEY (Whisper transcription) + FFmpeg`).action(async (videoP
478407
478547
  validateOutputPath(options.output);
478408
478548
  }
478409
478549
  const absInputPath = resolve37(process.cwd(), inputPath);
478410
- if (!existsSync46(absInputPath)) {
478550
+ if (!existsSync47(absInputPath)) {
478411
478551
  exitWithError(notFoundError(absInputPath));
478412
478552
  }
478413
478553
  if (!commandExists("ffmpeg")) {
@@ -478473,7 +478613,7 @@ Requires: OPENAI_API_KEY (Whisper transcription) + FFmpeg`).action(async (videoP
478473
478613
  validateOutputPath(options.output);
478474
478614
  }
478475
478615
  const absVideoPath = resolve37(process.cwd(), videoPath);
478476
- if (!existsSync46(absVideoPath)) {
478616
+ if (!existsSync47(absVideoPath)) {
478477
478617
  exitWithError(notFoundError(absVideoPath));
478478
478618
  }
478479
478619
  if (!commandExists("ffmpeg")) {
@@ -478548,7 +478688,7 @@ Requires: OPENAI_API_KEY (Whisper transcription) + FFmpeg`).action(async (videoP
478548
478688
  exitWithError(usageError("Target language required. Use -t or --target"));
478549
478689
  }
478550
478690
  const absSrtPath = resolve37(process.cwd(), srtPath);
478551
- if (!existsSync46(absSrtPath)) {
478691
+ if (!existsSync47(absSrtPath)) {
478552
478692
  exitWithError(notFoundError(absSrtPath));
478553
478693
  }
478554
478694
  if (options.dryRun) {
@@ -478624,7 +478764,7 @@ Requires: OPENAI_API_KEY (Whisper transcription) + FFmpeg`).action(async (videoP
478624
478764
  }
478625
478765
  if (options.fillers) rejectControlChars(options.fillers);
478626
478766
  const absVideoPath = resolve37(process.cwd(), videoPath);
478627
- if (!existsSync46(absVideoPath)) {
478767
+ if (!existsSync47(absVideoPath)) {
478628
478768
  exitWithError(notFoundError(absVideoPath));
478629
478769
  }
478630
478770
  if (!commandExists("ffmpeg")) {
@@ -479116,8 +479256,8 @@ var init_project_resolver = __esm({
479116
479256
  });
479117
479257
 
479118
479258
  // ../cli/src/commands/_shared/execute-fill-gaps.ts
479119
- import { existsSync as existsSync47 } from "node:fs";
479120
- import { readFile as readFile24, writeFile as writeFile26, mkdir as mkdir17, rename as renameFs } from "node:fs/promises";
479259
+ import { existsSync as existsSync48 } from "node:fs";
479260
+ import { readFile as readFile25, writeFile as writeFile26, mkdir as mkdir17, rename as renameFs } from "node:fs/promises";
479121
479261
  import { resolve as resolve39, dirname as dirname21 } from "node:path";
479122
479262
  function detectVideoGaps(videoClips, totalDuration) {
479123
479263
  const gaps = [];
@@ -479174,7 +479314,7 @@ function analyzeGapFillability(gaps, videoClips, sources) {
479174
479314
  }
479175
479315
  async function uploadFrameToImgbb(framePath, imgbbApiKey) {
479176
479316
  try {
479177
- const frameBuffer = await readFile24(framePath);
479317
+ const frameBuffer = await readFile25(framePath);
479178
479318
  const frameBase64 = frameBuffer.toString("base64");
479179
479319
  const formData = new FormData();
479180
479320
  formData.append("key", imgbbApiKey);
@@ -479199,14 +479339,14 @@ async function executeFillGaps(options) {
479199
479339
  try {
479200
479340
  onProgress("Loading timeline...");
479201
479341
  const filePath = await resolveTimelineFile(options.projectPath);
479202
- if (!existsSync47(filePath)) {
479342
+ if (!existsSync48(filePath)) {
479203
479343
  return {
479204
479344
  success: false,
479205
479345
  error: `Timeline file not found: ${filePath}`,
479206
479346
  humanLines
479207
479347
  };
479208
479348
  }
479209
- const content = await readFile24(filePath, "utf-8");
479349
+ const content = await readFile25(filePath, "utf-8");
479210
479350
  const data = JSON.parse(content);
479211
479351
  const project = Project.fromJSON(data);
479212
479352
  const clips = project.getClips().sort((a2, b2) => a2.startTime - b2.startTime);
@@ -479334,7 +479474,7 @@ async function executeFillGaps(options) {
479334
479474
  }
479335
479475
  const projectDir = dirname21(filePath);
479336
479476
  const footageDir = options.dir ? resolve39(process.cwd(), options.dir) : resolve39(projectDir, "footage");
479337
- if (!existsSync47(footageDir)) {
479477
+ if (!existsSync48(footageDir)) {
479338
479478
  await mkdir17(footageDir, { recursive: true });
479339
479479
  }
479340
479480
  humanLines.push("Generating AI Videos");
@@ -479654,8 +479794,8 @@ __export(ai_motion_exports, {
479654
479794
  registerMotionCommand: () => registerMotionCommand
479655
479795
  });
479656
479796
  import { resolve as resolve40 } from "node:path";
479657
- import { existsSync as existsSync48 } from "node:fs";
479658
- import { readFile as readFile25, writeFile as writeFile27 } from "node:fs/promises";
479797
+ import { existsSync as existsSync49 } from "node:fs";
479798
+ import { readFile as readFile26, writeFile as writeFile27 } from "node:fs/promises";
479659
479799
  async function getOptionalGoogleApiKey() {
479660
479800
  const configKey = await getApiKeyFromConfig("google");
479661
479801
  if (configKey) return configKey;
@@ -479702,7 +479842,7 @@ async function executeMotion(options) {
479702
479842
  };
479703
479843
  }
479704
479844
  const imagePath = resolve40(process.cwd(), options.image);
479705
- const imageBuffer = await readFile25(imagePath);
479845
+ const imageBuffer = await readFile26(imagePath);
479706
479846
  const gemini = new GeminiProvider();
479707
479847
  await gemini.initialize({ apiKey: geminiApiKey });
479708
479848
  const analysisResult = await gemini.analyzeImage(
@@ -479739,7 +479879,7 @@ Use this image analysis to inform the color palette, typography placement, and o
479739
479879
  }
479740
479880
  if (geminiApiKey) {
479741
479881
  const videoPath = resolve40(process.cwd(), options.video);
479742
- const videoBuffer = await readFile25(videoPath);
479882
+ const videoBuffer = await readFile26(videoPath);
479743
479883
  const gemini = new GeminiProvider();
479744
479884
  await gemini.initialize({ apiKey: geminiApiKey });
479745
479885
  const analysisPrompt = options.understandingPrompt || `Analyze this video for motion graphics composition. Return concise production guidance:
@@ -479770,10 +479910,10 @@ Use this video understanding to place motion graphics in safe zones, match the c
479770
479910
  let result;
479771
479911
  if (options.fromTsx) {
479772
479912
  const tsxPath = resolve40(process.cwd(), options.fromTsx);
479773
- if (!existsSync48(tsxPath)) {
479913
+ if (!existsSync49(tsxPath)) {
479774
479914
  return { success: false, error: `TSX file not found: ${tsxPath}` };
479775
479915
  }
479776
- const existingCode = await readFile25(tsxPath, "utf-8");
479916
+ const existingCode = await readFile26(tsxPath, "utf-8");
479777
479917
  if (useGemini) {
479778
479918
  const gemini = new GeminiProvider();
479779
479919
  await gemini.initialize({ apiKey });
@@ -480302,7 +480442,7 @@ __export(project_builder_exports, {
480302
480442
  resolveSourceUrl: () => resolveSourceUrl
480303
480443
  });
480304
480444
  import { mkdtemp as mkdtemp4, mkdir as mkdir18, copyFile as copyFile6, writeFile as writeFile28, rm as rm5, readdir as readdir5 } from "node:fs/promises";
480305
- import { existsSync as existsSync49 } from "node:fs";
480445
+ import { existsSync as existsSync50 } from "node:fs";
480306
480446
  import { tmpdir as tmpdir4 } from "node:os";
480307
480447
  import { createRequire } from "node:module";
480308
480448
  import * as path13 from "node:path";
@@ -480314,7 +480454,7 @@ async function buildTempProject(state, projectFileDir) {
480314
480454
  for (const source3 of state.sources) {
480315
480455
  if (copied.has(source3.id)) continue;
480316
480456
  const resolved = resolveSourceUrl(source3.url, projectFileDir);
480317
- if (!existsSync49(resolved)) {
480457
+ if (!existsSync50(resolved)) {
480318
480458
  throw new Error(`Source file not found: ${resolved} (from source id=${source3.id})`);
480319
480459
  }
480320
480460
  const dest = path13.join(assetsDir, path13.basename(resolved));
@@ -480451,7 +480591,7 @@ __export(motion_overlay_exports, {
480451
480591
  registerMotionOverlayCommand: () => registerMotionOverlayCommand
480452
480592
  });
480453
480593
  import { mkdir as mkdir19 } from "node:fs/promises";
480454
- import { existsSync as existsSync50 } from "node:fs";
480594
+ import { existsSync as existsSync51 } from "node:fs";
480455
480595
  import { basename as basename12, dirname as dirname24, extname as extname9, resolve as resolve43 } from "node:path";
480456
480596
  function normalizeUnderstand2(value) {
480457
480597
  return value === "off" || value === "required" || value === "auto" ? value : "auto";
@@ -480582,11 +480722,11 @@ async function executeMotionOverlay(options) {
480582
480722
  const validationError = assertValidRequest(options);
480583
480723
  if (validationError) return { success: false, error: validationError };
480584
480724
  const absVideo = resolve43(process.cwd(), options.videoPath);
480585
- if (!existsSync50(absVideo)) return { success: false, error: `Video file not found: ${absVideo}` };
480725
+ if (!existsSync51(absVideo)) return { success: false, error: `Video file not found: ${absVideo}` };
480586
480726
  const outputPath = options.output ? resolve43(process.cwd(), options.output) : defaultOverlayOutput(options.videoPath);
480587
480727
  if (options.asset) {
480588
480728
  const absAsset = resolve43(process.cwd(), options.asset);
480589
- if (!existsSync50(absAsset)) return { success: false, error: `Lottie asset not found: ${absAsset}` };
480729
+ if (!existsSync51(absAsset)) return { success: false, error: `Lottie asset not found: ${absAsset}` };
480590
480730
  const [videoDuration, size] = await Promise.all([
480591
480731
  ffprobeDuration(absVideo),
480592
480732
  ffprobeVideoSize(absVideo)
@@ -480753,7 +480893,7 @@ __export(edit_cmd_exports, {
480753
480893
  executeUpscale: () => executeUpscale
480754
480894
  });
480755
480895
  import { resolve as resolve44, dirname as dirname25 } from "node:path";
480756
- import { readFile as readFile26, writeFile as writeFile29, mkdir as mkdir20 } from "node:fs/promises";
480896
+ import { readFile as readFile27, writeFile as writeFile29, mkdir as mkdir20 } from "node:fs/promises";
480757
480897
  async function executeGrade(options) {
480758
480898
  const { videoPath, style, preset, output: output3, analyzeOnly, apiKey } = options;
480759
480899
  try {
@@ -480794,7 +480934,7 @@ async function executeSpeedRamp(options) {
480794
480934
  await execSafe("ffmpeg", ["-i", absPath, "-vn", "-acodec", "libmp3lame", "-q:a", "2", tempAudio, "-y"]);
480795
480935
  const whisper = new WhisperProvider();
480796
480936
  await whisper.initialize({ apiKey: openaiKey });
480797
- const audioBuffer = await readFile26(tempAudio);
480937
+ const audioBuffer = await readFile27(tempAudio);
480798
480938
  const transcript = await whisper.transcribe(new Blob([audioBuffer]), language);
480799
480939
  try {
480800
480940
  const { unlink: unlink8 } = await import("node:fs/promises");
@@ -481188,7 +481328,7 @@ Run 'vibe schema edit.<command>' for structured parameter info.
481188
481328
  spinner2.text = "Transcribing audio...";
481189
481329
  const whisper = new WhisperProvider();
481190
481330
  await whisper.initialize({ apiKey: openaiApiKey });
481191
- const audioBuffer = await readFile26(tempAudio);
481331
+ const audioBuffer = await readFile27(tempAudio);
481192
481332
  const audioBlob = new Blob([audioBuffer]);
481193
481333
  const transcript = await whisper.transcribe(audioBlob, options.language);
481194
481334
  if (!transcript.segments || transcript.segments.length === 0) {
@@ -481321,7 +481461,7 @@ Run 'vibe schema edit.<command>' for structured parameter info.
481321
481461
  for (let i2 = 1; i2 <= numKeyframes && i2 <= 30; i2++) {
481322
481462
  const framePath = `${tempDir}/frame-${i2.toString().padStart(4, "0")}.jpg`;
481323
481463
  try {
481324
- const frameBuffer = await readFile26(framePath);
481464
+ const frameBuffer = await readFile27(framePath);
481325
481465
  const frameBase64 = frameBuffer.toString("base64");
481326
481466
  const result = await claude.analyzeFrameForReframe(frameBase64, options.aspect, {
481327
481467
  focusMode: options.focus,
@@ -481450,7 +481590,7 @@ Run 'vibe schema edit.<command>' for structured parameter info.
481450
481590
  const imageBuffers = [];
481451
481591
  for (const imagePath of imagePaths) {
481452
481592
  const absPath = resolve44(process.cwd(), imagePath);
481453
- const buffer = await readFile26(absPath);
481593
+ const buffer = await readFile27(absPath);
481454
481594
  imageBuffers.push(buffer);
481455
481595
  }
481456
481596
  let result;
@@ -481727,8 +481867,8 @@ __export(ai_image_exports, {
481727
481867
  executeThumbnailBestFrame: () => executeThumbnailBestFrame
481728
481868
  });
481729
481869
  import { resolve as resolve46, dirname as dirname27 } from "node:path";
481730
- import { readFile as readFile27, writeFile as writeFile31, mkdir as mkdir23 } from "node:fs/promises";
481731
- import { existsSync as existsSync53 } from "node:fs";
481870
+ import { readFile as readFile28, writeFile as writeFile31, mkdir as mkdir23 } from "node:fs/promises";
481871
+ import { existsSync as existsSync54 } from "node:fs";
481732
481872
  async function executeImageGenerate(options) {
481733
481873
  const {
481734
481874
  prompt: prompt3,
@@ -481872,10 +482012,10 @@ async function executeGeminiEdit(options) {
481872
482012
  const imageBuffers = [];
481873
482013
  for (const imagePath of imagePaths) {
481874
482014
  const absPath = resolve46(process.cwd(), imagePath);
481875
- if (!existsSync53(absPath)) {
482015
+ if (!existsSync54(absPath)) {
481876
482016
  return { success: false, error: `Image not found: ${absPath}` };
481877
482017
  }
481878
- const buffer = await readFile27(absPath);
482018
+ const buffer = await readFile28(absPath);
481879
482019
  imageBuffers.push(buffer);
481880
482020
  }
481881
482021
  const gemini = new GeminiProvider();
@@ -481920,7 +482060,7 @@ async function executeThumbnailBestFrame(options) {
481920
482060
  model = "flash",
481921
482061
  apiKey
481922
482062
  } = options;
481923
- if (!existsSync53(videoPath)) {
482063
+ if (!existsSync54(videoPath)) {
481924
482064
  return { success: false, error: `Video not found: ${videoPath}` };
481925
482065
  }
481926
482066
  if (!commandExists("ffmpeg")) {
@@ -481933,7 +482073,7 @@ async function executeThumbnailBestFrame(options) {
481933
482073
  try {
481934
482074
  const gemini = new GeminiProvider();
481935
482075
  await gemini.initialize({ apiKey: googleKey });
481936
- const videoData = await readFile27(videoPath);
482076
+ const videoData = await readFile28(videoPath);
481937
482077
  const analysisPrompt = prompt3 || 'Analyze this video and find the single best frame for a thumbnail. Look for frames that are visually striking, well-composed, emotionally engaging, and representative of the video content. Avoid blurry frames, transitions, or dark scenes. Return ONLY a JSON object: {"timestamp": <seconds as number>, "reason": "<brief explanation>"}';
481938
482078
  const modelId = resolveGeminiTextModel(model);
481939
482079
  const result = await gemini.analyzeVideo(videoData, analysisPrompt, {
@@ -481954,7 +482094,7 @@ async function executeThumbnailBestFrame(options) {
481954
482094
  reason = reasonMatch[1];
481955
482095
  }
481956
482096
  await execSafe("ffmpeg", ["-ss", String(timestamp), "-i", videoPath, "-frames:v", "1", "-q:v", "2", outputPath, "-y"], { timeout: 6e4, maxBuffer: 50 * 1024 * 1024 });
481957
- if (!existsSync53(outputPath)) {
482097
+ if (!existsSync54(outputPath)) {
481958
482098
  return { success: false, error: "FFmpeg failed to extract frame" };
481959
482099
  }
481960
482100
  return {
@@ -481985,9 +482125,9 @@ __export(ai_analyze_exports, {
481985
482125
  executeGeminiVideo: () => executeGeminiVideo,
481986
482126
  registerAnalyzeCommands: () => registerAnalyzeCommands
481987
482127
  });
481988
- import { readFile as readFile28 } from "node:fs/promises";
482128
+ import { readFile as readFile29 } from "node:fs/promises";
481989
482129
  import { extname as extname10, resolve as resolve47 } from "node:path";
481990
- import { existsSync as existsSync54 } from "node:fs";
482130
+ import { existsSync as existsSync55 } from "node:fs";
481991
482131
  async function executeGeminiVideo(options) {
481992
482132
  try {
481993
482133
  const apiKey = await getApiKey("GOOGLE_API_KEY", "Google");
@@ -482001,10 +482141,10 @@ async function executeGeminiVideo(options) {
482001
482141
  videoData = options.source;
482002
482142
  } else {
482003
482143
  const absPath = resolve47(process.cwd(), options.source);
482004
- if (!existsSync54(absPath)) {
482144
+ if (!existsSync55(absPath)) {
482005
482145
  return { success: false, error: `File not found: ${absPath}` };
482006
482146
  }
482007
- videoData = await readFile28(absPath);
482147
+ videoData = await readFile29(absPath);
482008
482148
  }
482009
482149
  const gemini = new GeminiProvider();
482010
482150
  await gemini.initialize({ apiKey });
@@ -482069,10 +482209,10 @@ async function executeAnalyze(options) {
482069
482209
  imageBuffer = Buffer.from(await response.arrayBuffer());
482070
482210
  } else {
482071
482211
  const absPath = resolve47(process.cwd(), source3);
482072
- if (!existsSync54(absPath)) {
482212
+ if (!existsSync55(absPath)) {
482073
482213
  return { success: false, error: `File not found: ${absPath}` };
482074
482214
  }
482075
- imageBuffer = await readFile28(absPath);
482215
+ imageBuffer = await readFile29(absPath);
482076
482216
  }
482077
482217
  const result2 = await gemini.analyzeImage(imageBuffer, options.prompt, {
482078
482218
  model: modelId,
@@ -482104,10 +482244,10 @@ async function executeAnalyze(options) {
482104
482244
  videoData = Buffer.from(await response.arrayBuffer());
482105
482245
  } else {
482106
482246
  const absPath = resolve47(process.cwd(), source3);
482107
- if (!existsSync54(absPath)) {
482247
+ if (!existsSync55(absPath)) {
482108
482248
  return { success: false, error: `File not found: ${absPath}` };
482109
482249
  }
482110
- videoData = await readFile28(absPath);
482250
+ videoData = await readFile29(absPath);
482111
482251
  }
482112
482252
  const result = await gemini.analyzeVideo(videoData, options.prompt, {
482113
482253
  model: modelId,
@@ -482241,9 +482381,9 @@ __export(ai_review_exports, {
482241
482381
  executeReview: () => executeReview,
482242
482382
  registerReviewCommand: () => registerReviewCommand
482243
482383
  });
482244
- import { readFile as readFile29, rename as rename5 } from "node:fs/promises";
482384
+ import { readFile as readFile30, rename as rename5 } from "node:fs/promises";
482245
482385
  import { resolve as resolve48 } from "node:path";
482246
- import { existsSync as existsSync55 } from "node:fs";
482386
+ import { existsSync as existsSync56 } from "node:fs";
482247
482387
  function parseReviewFeedback(response) {
482248
482388
  let cleaned = response.trim();
482249
482389
  if (cleaned.startsWith("```json")) {
@@ -482275,7 +482415,7 @@ async function executeReview(options) {
482275
482415
  model = "flash"
482276
482416
  } = options;
482277
482417
  const absVideoPath = resolve48(process.cwd(), videoPath);
482278
- if (!existsSync55(absVideoPath)) {
482418
+ if (!existsSync56(absVideoPath)) {
482279
482419
  return { success: false, error: `Video not found: ${absVideoPath}` };
482280
482420
  }
482281
482421
  const apiKey = process.env.GOOGLE_API_KEY || await getApiKey("GOOGLE_API_KEY", "Google");
@@ -482288,8 +482428,8 @@ async function executeReview(options) {
482288
482428
  let storyboardContext = "";
482289
482429
  if (storyboardPath) {
482290
482430
  const absStoryboardPath = resolve48(process.cwd(), storyboardPath);
482291
- if (existsSync55(absStoryboardPath)) {
482292
- const content = await readFile29(absStoryboardPath, "utf-8");
482431
+ if (existsSync56(absStoryboardPath)) {
482432
+ const content = await readFile30(absStoryboardPath, "utf-8");
482293
482433
  storyboardContext = `
482294
482434
 
482295
482435
  Original storyboard for reference:
@@ -482331,7 +482471,7 @@ ${projectContext}` : "";
482331
482471
  Score each category 1-10. Prefer beatIssues when you can map a problem to a storyboard beat or timestamp. Use the exact beatId values from the storyboard or beat timing summary, and include timeRange in seconds for every localized finding. In particular, flag narration/visual mismatches, overly static holds, and audio-visual sync problems as beatIssues. Use category issue arrays only for problems that cannot be localized to a beat. For fixable issues, provide an FFmpeg filter in autoFixable. Be specific and practical.${storyboardContext}${extraProjectContext}`;
482332
482472
  const gemini = new GeminiProvider();
482333
482473
  await gemini.initialize({ apiKey });
482334
- const videoData = await readFile29(absVideoPath);
482474
+ const videoData = await readFile30(absVideoPath);
482335
482475
  const analysisResult = await gemini.analyzeVideo(videoData, reviewPrompt, {
482336
482476
  model: modelId
482337
482477
  });
@@ -482386,7 +482526,7 @@ Score each category 1-10. Prefer beatIssues when you can map a problem to a stor
482386
482526
  }
482387
482527
  }
482388
482528
  if (verify && result.outputPath) {
482389
- const verifyVideoData = await readFile29(result.outputPath);
482529
+ const verifyVideoData = await readFile30(result.outputPath);
482390
482530
  const verifyResult = await gemini.analyzeVideo(
482391
482531
  verifyVideoData,
482392
482532
  'Rate this video overall quality on a scale of 1-10. Return ONLY a JSON object: {"score": <number>}',
@@ -482850,7 +482990,7 @@ var init_sanitize = __esm({
482850
482990
 
482851
482991
  // ../cli/src/commands/generate/storyboard.ts
482852
482992
  import { resolve as resolve56 } from "node:path";
482853
- import { readFile as readFile33, writeFile as writeFile35 } from "node:fs/promises";
482993
+ import { readFile as readFile34, writeFile as writeFile35 } from "node:fs/promises";
482854
482994
  async function executeStoryboard(options) {
482855
482995
  const { content, duration, creativity = "low", output: output3, apiKey } = options;
482856
482996
  try {
@@ -482898,7 +483038,7 @@ function registerStoryboardCommand(parent) {
482898
483038
  let textContent2 = content;
482899
483039
  if (options.file) {
482900
483040
  const filePath = resolve56(process.cwd(), content);
482901
- textContent2 = await readFile33(filePath, "utf-8");
483041
+ textContent2 = await readFile34(filePath, "utf-8");
482902
483042
  }
482903
483043
  if (options.dryRun) {
482904
483044
  outputSuccess({
@@ -483291,7 +483431,7 @@ var init_speech2 = __esm({
483291
483431
 
483292
483432
  // ../cli/src/commands/generate/thumbnail.ts
483293
483433
  import { resolve as resolve58, dirname as dirname29, basename as basename16, extname as extname11 } from "node:path";
483294
- import { existsSync as existsSync58 } from "node:fs";
483434
+ import { existsSync as existsSync59 } from "node:fs";
483295
483435
  import { writeFile as writeFile37, mkdir as mkdir25 } from "node:fs/promises";
483296
483436
  function registerThumbnailCommand(parent) {
483297
483437
  parent.command("thumbnail").description("Generate video thumbnail (DALL-E) or extract best frame from video (Gemini)").argument("[description]", "Thumbnail description (for DALL-E generation)").option("-k, --api-key <key>", "API key (OpenAI for generation, Google for best-frame)").option("-o, --output <path>", "Output file path").option("--style <style>", "Platform style: youtube, instagram, tiktok, twitter").option("--best-frame <video>", "Extract best thumbnail frame from video using Gemini AI").option("--prompt <prompt>", "Custom prompt for best-frame analysis").option("--model <model>", `Gemini model: ${GEMINI_TEXT_MODEL_HELP}`, "flash").action(async (description, options) => {
@@ -483303,7 +483443,7 @@ function registerThumbnailCommand(parent) {
483303
483443
  }
483304
483444
  if (options.bestFrame) {
483305
483445
  const absVideoPath = resolve58(process.cwd(), options.bestFrame);
483306
- if (!existsSync58(absVideoPath)) {
483446
+ if (!existsSync59(absVideoPath)) {
483307
483447
  exitWithError(notFoundError(absVideoPath));
483308
483448
  }
483309
483449
  if (!commandExists("ffmpeg")) {
@@ -485487,7 +485627,7 @@ var init_dist4 = __esm({
485487
485627
 
485488
485628
  // ../cli/src/commands/generate/video.ts
485489
485629
  import { resolve as resolve63 } from "node:path";
485490
- import { readFile as readFile34, writeFile as writeFile41 } from "node:fs/promises";
485630
+ import { readFile as readFile35, writeFile as writeFile41 } from "node:fs/promises";
485491
485631
  function registerVideoCommand(parent) {
485492
485632
  parent.command("video").alias("vid").description("Generate video using AI (Seedance, Grok, Kling, Runway, or Veo)").argument("[prompt]", "Text prompt describing the video (interactive if omitted)").option(
485493
485633
  "-p, --provider <provider>",
@@ -485598,7 +485738,7 @@ Examples:
485598
485738
  let isImageToVideo = false;
485599
485739
  if (options.image) {
485600
485740
  const imagePath = resolve63(process.cwd(), options.image);
485601
- const imageBuffer = await readFile34(imagePath);
485741
+ const imageBuffer = await readFile35(imagePath);
485602
485742
  const ext = options.image.toLowerCase().split(".").pop();
485603
485743
  const mimeTypes = {
485604
485744
  jpg: "image/jpeg",
@@ -485838,7 +485978,7 @@ Examples:
485838
485978
  let lastFrame;
485839
485979
  if (options.lastFrame) {
485840
485980
  const lastFramePath = resolve63(process.cwd(), options.lastFrame);
485841
- const lastFrameBuffer = await readFile34(lastFramePath);
485981
+ const lastFrameBuffer = await readFile35(lastFramePath);
485842
485982
  const ext = options.lastFrame.toLowerCase().split(".").pop();
485843
485983
  const mimeType = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : `image/${ext || "png"}`;
485844
485984
  lastFrame = `data:${mimeType};base64,${lastFrameBuffer.toString("base64")}`;
@@ -485848,7 +485988,7 @@ Examples:
485848
485988
  refImages = [];
485849
485989
  for (const refPath of options.refImages.slice(0, 3)) {
485850
485990
  const absRefPath = resolve63(process.cwd(), refPath);
485851
- const refBuffer = await readFile34(absRefPath);
485991
+ const refBuffer = await readFile35(absRefPath);
485852
485992
  const ext = refPath.toLowerCase().split(".").pop();
485853
485993
  const mimeType = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : `image/${ext || "png"}`;
485854
485994
  refImages.push({ base64: refBuffer.toString("base64"), mimeType });
@@ -485980,7 +486120,7 @@ Examples:
485980
486120
  if (seedanceEndImagePath && seedanceReferences.length === 0) {
485981
486121
  try {
485982
486122
  const absEndImagePath = resolve63(process.cwd(), seedanceEndImagePath);
485983
- const endImageBuffer = await readFile34(absEndImagePath);
486123
+ const endImageBuffer = await readFile35(absEndImagePath);
485984
486124
  const ext = seedanceEndImagePath.toLowerCase().split(".").pop();
485985
486125
  const mimeType = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : `image/${ext || "png"}`;
485986
486126
  const uploadHost = await resolveUploadHost();
@@ -486097,7 +486237,7 @@ async function fileInputToUrlOrDataUri2(input3, fallbackMimeType) {
486097
486237
  return input3;
486098
486238
  }
486099
486239
  const absPath = resolve63(process.cwd(), input3);
486100
- const buffer = await readFile34(absPath);
486240
+ const buffer = await readFile35(absPath);
486101
486241
  return `data:${mimeTypeForPath2(input3, fallbackMimeType)};base64,${buffer.toString("base64")}`;
486102
486242
  }
486103
486243
  function mimeTypeForPath2(path14, fallback2) {
@@ -487105,7 +487245,7 @@ __export(detect_exports, {
487105
487245
  executeDetectScenes: () => executeDetectScenes,
487106
487246
  executeDetectSilence: () => executeDetectSilence
487107
487247
  });
487108
- import { readFile as readFile39, writeFile as writeFile46 } from "node:fs/promises";
487248
+ import { readFile as readFile40, writeFile as writeFile46 } from "node:fs/promises";
487109
487249
  import { resolve as resolve68, basename as basename18 } from "node:path";
487110
487250
  async function executeDetectScenes(options) {
487111
487251
  try {
@@ -487349,7 +487489,7 @@ var init_detect = __esm({
487349
487489
  }
487350
487490
  if (options.project) {
487351
487491
  const projectPath = resolve68(process.cwd(), options.project);
487352
- const content = await readFile39(projectPath, "utf-8");
487492
+ const content = await readFile40(projectPath, "utf-8");
487353
487493
  const data = JSON.parse(content);
487354
487494
  const project = Project.fromJSON(data);
487355
487495
  let source3 = project.getSources().find((s2) => s2.url === absPath);
@@ -488172,8 +488312,8 @@ init_scene_project();
488172
488312
  init_project_config();
488173
488313
  init_cost_tier();
488174
488314
  import { resolve as resolve24, relative as relative8, dirname as dirname14 } from "node:path";
488175
- import { mkdir as mkdir11, readFile as readFile14, writeFile as writeFile17, access as access4, copyFile as copyFile3 } from "node:fs/promises";
488176
- import { existsSync as existsSync28 } from "node:fs";
488315
+ import { mkdir as mkdir11, readFile as readFile15, writeFile as writeFile17, access as access4, copyFile as copyFile3 } from "node:fs/promises";
488316
+ import { existsSync as existsSync29 } from "node:fs";
488177
488317
 
488178
488318
  // ../cli/src/commands/_shared/scene-html-emit.ts
488179
488319
  var SCENE_PRESETS = [
@@ -488742,15 +488882,16 @@ function deriveInstallHosts(detected) {
488742
488882
 
488743
488883
  // ../cli/src/commands/scene.ts
488744
488884
  init_compose_prompts();
488885
+ init_transcribe_narration();
488745
488886
 
488746
488887
  // ../cli/src/commands/_shared/scene-submit.ts
488747
488888
  init_compose_scenes_skills();
488748
488889
  init_scene_lint();
488749
488890
  init_storyboard_parse();
488750
488891
  init_root_sync();
488751
- import { existsSync as existsSync26 } from "node:fs";
488752
- import { mkdir as mkdir10, readFile as readFile11, writeFile as writeFile15 } from "node:fs/promises";
488753
- import { join as join26, resolve as resolve20 } from "node:path";
488892
+ import { existsSync as existsSync27 } from "node:fs";
488893
+ import { mkdir as mkdir10, readFile as readFile12, writeFile as writeFile15 } from "node:fs/promises";
488894
+ import { join as join27, resolve as resolve20 } from "node:path";
488754
488895
  async function executeSceneSubmit(opts) {
488755
488896
  const projectDir = resolve20(opts.projectDir);
488756
488897
  const beatId = opts.beatId.trim();
@@ -488764,15 +488905,15 @@ async function executeSceneSubmit(opts) {
488764
488905
  warnings: [],
488765
488906
  retryWith: []
488766
488907
  };
488767
- const storyboardPath = join26(projectDir, "STORYBOARD.md");
488768
- if (!existsSync26(storyboardPath)) {
488908
+ const storyboardPath = join27(projectDir, "STORYBOARD.md");
488909
+ if (!existsSync27(storyboardPath)) {
488769
488910
  return {
488770
488911
  ...base,
488771
488912
  success: false,
488772
488913
  error: `STORYBOARD.md not found at ${storyboardPath}. Run \`vibe init <dir>\` first.`
488773
488914
  };
488774
488915
  }
488775
- const parsed = parseStoryboard(await readFile11(storyboardPath, "utf-8"));
488916
+ const parsed = parseStoryboard(await readFile12(storyboardPath, "utf-8"));
488776
488917
  const beat = parsed.beats.find((b2) => b2.id === beatId);
488777
488918
  if (!beat) {
488778
488919
  const available = parsed.beats.map((b2) => b2.id).join(", ") || "(none)";
@@ -488842,8 +488983,8 @@ async function executeSceneSubmit(opts) {
488842
488983
  if (opts.validateOnly) {
488843
488984
  return { ...base, success: true };
488844
488985
  }
488845
- const absPath = join26(projectDir, scenePath);
488846
- await mkdir10(join26(projectDir, "compositions"), { recursive: true });
488986
+ const absPath = join27(projectDir, scenePath);
488987
+ await mkdir10(join27(projectDir, "compositions"), { recursive: true });
488847
488988
  await writeFile15(absPath, html.endsWith("\n") ? html : `${html}
488848
488989
  `, "utf-8");
488849
488990
  return {
@@ -489044,7 +489185,7 @@ sceneCommand.command("submit").description(
489044
489185
  }
489045
489186
  html = Buffer.concat(chunks).toString("utf-8");
489046
489187
  } else if (options.file) {
489047
- html = await readFile14(resolve24(String(options.file)), "utf-8");
489188
+ html = await readFile15(resolve24(String(options.file)), "utf-8");
489048
489189
  } else {
489049
489190
  exitWithError(
489050
489191
  usageError(
@@ -489374,8 +489515,8 @@ function readClipStart(rootHtml, beatId) {
489374
489515
  async function resolveNarrationText(value) {
489375
489516
  if (!value) return void 0;
489376
489517
  const looksLikePath = /\.[a-z]{2,4}$/i.test(value) || value.includes("/") || value.includes("\\");
489377
- if (looksLikePath && existsSync28(value)) {
489378
- return (await readFile14(value, "utf-8")).trim();
489518
+ if (looksLikePath && existsSync29(value)) {
489519
+ return (await readFile15(value, "utf-8")).trim();
489379
489520
  }
489380
489521
  return value.trim();
489381
489522
  }
@@ -489414,7 +489555,7 @@ async function executeSceneAdd(opts) {
489414
489555
  if (!opts.force && await pathExists2(scenePath)) {
489415
489556
  return errResult(`Scene already exists: ${sceneRel}. Re-run with --force to overwrite.`);
489416
489557
  }
489417
- const rootHtmlBefore = await readFile14(rootPath, "utf-8");
489558
+ const rootHtmlBefore = await readFile15(rootPath, "utf-8");
489418
489559
  let dims = readRootDims(rootHtmlBefore);
489419
489560
  if (!dims) {
489420
489561
  const cfg2 = await loadVibeProjectConfig(projectDir);
@@ -489490,31 +489631,20 @@ async function executeSceneAdd(opts) {
489490
489631
  );
489491
489632
  } else {
489492
489633
  opts.onProgress?.("Transcribing narration (Whisper word-level)...");
489493
- try {
489494
- const whisper = new WhisperProvider();
489495
- await whisper.initialize({ apiKey: whisperKey });
489496
- const audioBytes = await readFile14(audioAbsPath);
489497
- const audioBlob = new Blob([new Uint8Array(audioBytes)]);
489498
- const transcript = await whisper.transcribe(audioBlob, void 0, {
489499
- granularity: "word",
489500
- language: opts.transcribeLanguage
489501
- });
489502
- if (transcript.status === "completed" && transcript.words?.length) {
489503
- transcriptRelPath = `assets/transcript-${id}.json`;
489504
- const transcriptAbs = resolve24(projectDir, transcriptRelPath);
489505
- await writeFile17(transcriptAbs, JSON.stringify(transcript.words, null, 2), "utf-8");
489506
- transcriptWordCount = transcript.words.length;
489507
- transcriptWords = transcript.words.map((w2) => ({
489508
- text: w2.text,
489509
- start: w2.start,
489510
- end: w2.end
489511
- }));
489512
- } else if (transcript.status === "failed") {
489513
- opts.onProgress?.(`Transcribe failed: ${transcript.error ?? "unknown error"}`);
489514
- }
489515
- } catch (error) {
489516
- const msg = error instanceof Error ? error.message : String(error);
489517
- opts.onProgress?.(`Transcribe failed: ${msg}`);
489634
+ const words = await transcribeNarrationWords(audioAbsPath, {
489635
+ apiKey: whisperKey,
489636
+ language: opts.transcribeLanguage
489637
+ });
489638
+ if (words.length > 0) {
489639
+ transcriptRelPath = beatTranscriptRelPath(id);
489640
+ const transcriptAbs = resolve24(projectDir, transcriptRelPath);
489641
+ await writeFile17(transcriptAbs, JSON.stringify(words, null, 2), "utf-8");
489642
+ transcriptWordCount = words.length;
489643
+ transcriptWords = words;
489644
+ } else {
489645
+ opts.onProgress?.(
489646
+ "Transcribe produced no word timings \u2014 narration plays without word-sync"
489647
+ );
489518
489648
  }
489519
489649
  }
489520
489650
  }
@@ -489623,7 +489753,7 @@ async function executeSceneAdd(opts) {
489623
489753
  const shouldSyncStoryboard = opts.syncStoryboard !== false && await pathExists2(storyboardAbsPath);
489624
489754
  if (shouldSyncStoryboard) {
489625
489755
  opts.onProgress?.("Syncing STORYBOARD.md...");
489626
- const before2 = await readFile14(storyboardAbsPath, "utf-8");
489756
+ const before2 = await readFile15(storyboardAbsPath, "utf-8");
489627
489757
  const synced = upsertStoryboardBeat(before2, {
489628
489758
  beatId: id,
489629
489759
  title: opts.headline,
@@ -489665,7 +489795,7 @@ async function executeSceneAdd(opts) {
489665
489795
  });
489666
489796
  const blockingIssue = syncPlan.issues.find((issue) => issue.severity === "error");
489667
489797
  if (blockingIssue) return errResult(blockingIssue.message);
489668
- const rootHtmlAfterSync = await readFile14(rootPath, "utf-8");
489798
+ const rootHtmlAfterSync = await readFile15(rootPath, "utf-8");
489669
489799
  start = readClipStart(rootHtmlAfterSync, id) ?? 0;
489670
489800
  } else {
489671
489801
  start = nextSceneStart(rootHtmlBefore, SCENE_OVERLAP_SECONDS);
@@ -489839,7 +489969,7 @@ async function resolveSceneRepairTarget(rootArg = "index.html", projectArg = "."
489839
489969
  const root2 = rootArg || "index.html";
489840
489970
  const project = projectArg || ".";
489841
489971
  const defaultProject = project === ".";
489842
- if (defaultProject && root2 !== "index.html" && !root2.toLowerCase().endsWith(".html") && existsSync28(resolve24(root2, "index.html"))) {
489972
+ if (defaultProject && root2 !== "index.html" && !root2.toLowerCase().endsWith(".html") && existsSync29(resolve24(root2, "index.html"))) {
489843
489973
  return { projectDir: resolve24(root2), rootRel: "index.html" };
489844
489974
  }
489845
489975
  return { projectDir: resolve24(project), rootRel: root2 };
@@ -490710,7 +490840,7 @@ init_exec_safe();
490710
490840
  init_remotion();
490711
490841
  import { resolve as resolve45, dirname as dirname26, basename as basename13 } from "node:path";
490712
490842
  import { writeFile as writeFile30, mkdir as mkdir21, rm as rm6 } from "node:fs/promises";
490713
- import { existsSync as existsSync51 } from "node:fs";
490843
+ import { existsSync as existsSync53 } from "node:fs";
490714
490844
  import { tmpdir as tmpdir5 } from "node:os";
490715
490845
  var ASS_STYLES = ["karaoke-sweep", "typewriter"];
490716
490846
  var SENTENCE_BREAKS = /[.!?]/;
@@ -490891,7 +491021,7 @@ async function executeAnimatedCaption(options) {
490891
491021
  const groups = groupWords(transcript.words, { wordsPerGroup, maxChars });
490892
491022
  const absOutputPath = resolve45(process.cwd(), outputPath);
490893
491023
  const outDir = dirname26(absOutputPath);
490894
- if (!existsSync51(outDir)) {
491024
+ if (!existsSync53(outDir)) {
490895
491025
  await mkdir21(outDir, { recursive: true });
490896
491026
  }
490897
491027
  if (tier === "ass") {
@@ -491439,14 +491569,14 @@ init_ai_review();
491439
491569
  init_dist();
491440
491570
  init_engine();
491441
491571
  init_ai_helpers();
491442
- import { readFile as readFile30, writeFile as writeFile32 } from "node:fs/promises";
491572
+ import { readFile as readFile31, writeFile as writeFile32 } from "node:fs/promises";
491443
491573
  import { resolve as resolve49 } from "node:path";
491444
491574
  async function executeSuggestEdit(options) {
491445
491575
  try {
491446
491576
  const apiKey = options.apiKey ?? process.env.GOOGLE_API_KEY;
491447
491577
  if (!apiKey) return { success: false, error: "GOOGLE_API_KEY required for suggest" };
491448
491578
  const filePath = resolve49(process.cwd(), options.projectPath);
491449
- const content = await readFile30(filePath, "utf-8");
491579
+ const content = await readFile31(filePath, "utf-8");
491450
491580
  const data = JSON.parse(content);
491451
491581
  const project = Project.fromJSON(data);
491452
491582
  const gemini = new GeminiProvider();
@@ -491483,9 +491613,9 @@ init_project_config();
491483
491613
  init_scene_lint();
491484
491614
  init_root_sync();
491485
491615
  init_review_report();
491486
- import { existsSync as existsSync56 } from "node:fs";
491487
- import { readdir as readdir6, readFile as readFile31, stat as stat5 } from "node:fs/promises";
491488
- import { basename as basename14, isAbsolute as isAbsolute7, join as join37, relative as relative13, resolve as resolve50 } from "node:path";
491616
+ import { existsSync as existsSync57 } from "node:fs";
491617
+ import { readdir as readdir6, readFile as readFile32, stat as stat5 } from "node:fs/promises";
491618
+ import { basename as basename14, isAbsolute as isAbsolute7, join as join38, relative as relative13, resolve as resolve50 } from "node:path";
491489
491619
  async function inspectProject(opts) {
491490
491620
  const projectDir = resolve50(opts.projectDir);
491491
491621
  const issues = [];
@@ -491499,7 +491629,7 @@ async function inspectProject(opts) {
491499
491629
  assets: { checked: 0, missing: [], stale: [], unknownFreshness: [] },
491500
491630
  rootSync: { ok: null, issueCount: 0, issues: [] }
491501
491631
  };
491502
- if (!existsSync56(projectDir) || !await isDirectory(projectDir)) {
491632
+ if (!existsSync57(projectDir) || !await isDirectory(projectDir)) {
491503
491633
  issues.push({
491504
491634
  severity: "error",
491505
491635
  code: "PROJECT_NOT_FOUND",
@@ -491514,15 +491644,15 @@ async function inspectProject(opts) {
491514
491644
  );
491515
491645
  }
491516
491646
  const coreFiles = {
491517
- storyboard: join37(projectDir, "STORYBOARD.md"),
491518
- design: join37(projectDir, "DESIGN.md"),
491519
- config: join37(projectDir, "vibe.config.json"),
491520
- legacyConfig: join37(projectDir, "vibe.project.yaml"),
491521
- buildReport: join37(projectDir, "build-report.json"),
491522
- root: join37(projectDir, "index.html")
491647
+ storyboard: join38(projectDir, "STORYBOARD.md"),
491648
+ design: join38(projectDir, "DESIGN.md"),
491649
+ config: join38(projectDir, "vibe.config.json"),
491650
+ legacyConfig: join38(projectDir, "vibe.project.yaml"),
491651
+ buildReport: join38(projectDir, "build-report.json"),
491652
+ root: join38(projectDir, "index.html")
491523
491653
  };
491524
491654
  for (const [name, path14] of Object.entries(coreFiles)) {
491525
- checks.files[name] = existsSync56(path14);
491655
+ checks.files[name] = existsSync57(path14);
491526
491656
  }
491527
491657
  let beatIds = [];
491528
491658
  let inspectedBeatIds = [];
@@ -491536,7 +491666,7 @@ async function inspectProject(opts) {
491536
491666
  });
491537
491667
  retryWith.push(`vibe init ${projectDir} --from "<brief>" --json`);
491538
491668
  } else {
491539
- const storyboard = await readFile31(coreFiles.storyboard, "utf-8");
491669
+ const storyboard = await readFile32(coreFiles.storyboard, "utf-8");
491540
491670
  const validation3 = validateStoryboardMarkdown(storyboard);
491541
491671
  storyboardBeats = validation3.beats;
491542
491672
  beatIds = validation3.beats.map((beat) => beat.id);
@@ -491578,7 +491708,7 @@ async function inspectProject(opts) {
491578
491708
  suggestedFix: "Create DESIGN.md or rerun `vibe init --from` in a new project."
491579
491709
  });
491580
491710
  } else {
491581
- const design = await readFile31(coreFiles.design, "utf-8");
491711
+ const design = await readFile32(coreFiles.design, "utf-8");
491582
491712
  for (const issue of designPlaceholderIssues(design)) {
491583
491713
  issues.push(issue);
491584
491714
  }
@@ -491603,20 +491733,20 @@ async function inspectProject(opts) {
491603
491733
  });
491604
491734
  retryWith.push(`vibe build ${projectDir} --stage sync --json`);
491605
491735
  }
491606
- const compositionsDir = join37(projectDir, "compositions");
491607
- const existingComps = existsSync56(compositionsDir) ? new Set(await listHtmlBasenames(compositionsDir)) : /* @__PURE__ */ new Set();
491736
+ const compositionsDir = join38(projectDir, "compositions");
491737
+ const existingComps = existsSync57(compositionsDir) ? new Set(await listHtmlBasenames(compositionsDir)) : /* @__PURE__ */ new Set();
491608
491738
  checks.compositions.expected = inspectedBeatIds.length;
491609
491739
  for (const beatId of inspectedBeatIds) {
491610
491740
  const file = `scene-${beatId}.html`;
491611
491741
  if (existingComps.has(file)) {
491612
491742
  checks.compositions.found++;
491613
491743
  } else {
491614
- checks.compositions.missing.push(join37("compositions", file));
491744
+ checks.compositions.missing.push(join38("compositions", file));
491615
491745
  issues.push({
491616
491746
  severity: "error",
491617
491747
  code: "MISSING_COMPOSITION",
491618
491748
  message: `Composition for beat "${beatId}" is missing.`,
491619
- file: join37("compositions", file),
491749
+ file: join38("compositions", file),
491620
491750
  scene: beatId,
491621
491751
  beatId,
491622
491752
  suggestedFix: "Run `vibe build --stage compose --json`."
@@ -491678,7 +491808,7 @@ async function inspectProject(opts) {
491678
491808
  try {
491679
491809
  const lint = await runProjectLint({ projectDir });
491680
491810
  const lintFiles = opts.beatId ? lint.files.filter(
491681
- (file) => file.file === "index.html" || file.file === join37("compositions", `scene-${opts.beatId}.html`)
491811
+ (file) => file.file === "index.html" || file.file === join38("compositions", `scene-${opts.beatId}.html`)
491682
491812
  ) : lint.files;
491683
491813
  const lintCounts = countLintFindings(lintFiles);
491684
491814
  checks.lint = {
@@ -491824,7 +491954,7 @@ function projectSourceReports(checks) {
491824
491954
  async function inspectBuildReport(projectDir, reportPath, beatId, checks, issues, retryWith, storyboardBeats) {
491825
491955
  checks.buildReport.exists = true;
491826
491956
  try {
491827
- const report = JSON.parse(await readFile31(reportPath, "utf-8"));
491957
+ const report = JSON.parse(await readFile32(reportPath, "utf-8"));
491828
491958
  if (typeof report.outputPath === "string") checks.buildReport.outputPath = report.outputPath;
491829
491959
  const reportBeats = report.beats ?? [];
491830
491960
  const selectedReportBeats = reportBeats.filter((item) => !beatId || item.id === beatId);
@@ -491961,7 +492091,7 @@ function inspectReportedAsset(opts) {
491961
492091
  opts.checks.assets.checked++;
491962
492092
  if (isExternalRef2(opts.value)) return;
491963
492093
  const abs = isAbsolute7(opts.value) ? opts.value : resolve50(opts.projectDir, opts.value);
491964
- if (existsSync56(abs)) return;
492094
+ if (existsSync57(abs)) return;
491965
492095
  opts.checks.assets.missing.push(opts.value);
491966
492096
  opts.issues.push({
491967
492097
  severity: "warning",
@@ -492055,9 +492185,9 @@ init_exec_safe();
492055
492185
  init_project_config();
492056
492186
  init_storyboard_parse();
492057
492187
  init_review_report();
492058
- import { existsSync as existsSync57 } from "node:fs";
492059
- import { readdir as readdir7, readFile as readFile32, stat as stat6 } from "node:fs/promises";
492060
- import { basename as basename15, isAbsolute as isAbsolute8, join as join38, relative as relative14, resolve as resolve51 } from "node:path";
492188
+ import { existsSync as existsSync58 } from "node:fs";
492189
+ import { readdir as readdir7, readFile as readFile33, stat as stat6 } from "node:fs/promises";
492190
+ import { basename as basename15, isAbsolute as isAbsolute8, join as join39, relative as relative14, resolve as resolve51 } from "node:path";
492061
492191
  var VIDEO_EXTENSIONS = /* @__PURE__ */ new Set([".mp4", ".mov", ".webm", ".m4v"]);
492062
492192
  var DEFAULT_AI_MODEL = "flash";
492063
492193
  var BLACK_FRAME_MIN_DURATION_SEC = 1;
@@ -492558,11 +492688,11 @@ async function inspectRender(opts) {
492558
492688
  }
492559
492689
  async function renderExpectsAudio(projectDir, beatId) {
492560
492690
  const root2 = resolve51(projectDir);
492561
- const rootHtml = await readTextIfExists(join38(root2, "index.html"));
492691
+ const rootHtml = await readTextIfExists(join39(root2, "index.html"));
492562
492692
  if (rootHtml && rootHtmlExpectsAudio(rootHtml, beatId)) return true;
492563
- const buildReport = await readJsonIfExists(join38(root2, "build-report.json"));
492693
+ const buildReport = await readJsonIfExists(join39(root2, "build-report.json"));
492564
492694
  if (buildReportExpectsAudio(buildReport, beatId)) return true;
492565
- const storyboard = await readTextIfExists(join38(root2, "STORYBOARD.md"));
492695
+ const storyboard = await readTextIfExists(join39(root2, "STORYBOARD.md"));
492566
492696
  if (!storyboard) return false;
492567
492697
  try {
492568
492698
  const parsed = parseStoryboard(storyboard);
@@ -492573,7 +492703,7 @@ async function renderExpectsAudio(projectDir, beatId) {
492573
492703
  `assets/narration-${beat.id}.wav`,
492574
492704
  `assets/music-${beat.id}.mp3`,
492575
492705
  `assets/music-${beat.id}.wav`
492576
- ].some((asset) => existsSync57(join38(root2, asset)))
492706
+ ].some((asset) => existsSync58(join39(root2, asset)))
492577
492707
  );
492578
492708
  } catch {
492579
492709
  return false;
@@ -492681,8 +492811,8 @@ async function maybeWriteRenderReport(projectDir, opts, result) {
492681
492811
  }
492682
492812
  function renderSourceReports(projectDir, videoPath, checks) {
492683
492813
  const reports = [];
492684
- if (existsSync57(join38(projectDir, "build-report.json"))) reports.push("build-report.json");
492685
- if (existsSync57(join38(projectDir, "render-report.json"))) reports.push("render-report.json");
492814
+ if (existsSync58(join39(projectDir, "build-report.json"))) reports.push("build-report.json");
492815
+ if (existsSync58(join39(projectDir, "render-report.json"))) reports.push("render-report.json");
492686
492816
  if (videoPath) reports.push(displayPath(videoPath));
492687
492817
  if (checks.durationSec !== void 0 || checks.width !== void 0 || checks.height !== void 0) {
492688
492818
  reports.push("ffprobe");
@@ -492695,31 +492825,31 @@ function renderSourceReports(projectDir, videoPath, checks) {
492695
492825
  async function resolveRenderVideoPath(projectDir, explicit, beatId) {
492696
492826
  if (explicit) {
492697
492827
  const candidate = resolve51(process.cwd(), explicit);
492698
- return existsSync57(candidate) ? candidate : null;
492828
+ return existsSync58(candidate) ? candidate : null;
492699
492829
  }
492700
- const renderReportPath = join38(projectDir, "render-report.json");
492701
- if (existsSync57(renderReportPath)) {
492830
+ const renderReportPath = join39(projectDir, "render-report.json");
492831
+ if (existsSync58(renderReportPath)) {
492702
492832
  try {
492703
- const report = JSON.parse(await readFile32(renderReportPath, "utf-8"));
492833
+ const report = JSON.parse(await readFile33(renderReportPath, "utf-8"));
492704
492834
  const reportBeat = typeof report.beat === "string" ? report.beat : null;
492705
492835
  if (!beatId && reportBeat === null || beatId && reportBeat === beatId) {
492706
492836
  const candidate = resolveReportedPath(projectDir, report.outputPath);
492707
- if (candidate && existsSync57(candidate)) return candidate;
492837
+ if (candidate && existsSync58(candidate)) return candidate;
492708
492838
  }
492709
492839
  } catch {
492710
492840
  }
492711
492841
  }
492712
- const reportPath = join38(projectDir, "build-report.json");
492713
- if (!beatId && existsSync57(reportPath)) {
492842
+ const reportPath = join39(projectDir, "build-report.json");
492843
+ if (!beatId && existsSync58(reportPath)) {
492714
492844
  try {
492715
- const report = JSON.parse(await readFile32(reportPath, "utf-8"));
492845
+ const report = JSON.parse(await readFile33(reportPath, "utf-8"));
492716
492846
  const candidate = resolveReportedPath(projectDir, report.outputPath);
492717
- if (candidate && existsSync57(candidate)) return candidate;
492847
+ if (candidate && existsSync58(candidate)) return candidate;
492718
492848
  } catch {
492719
492849
  }
492720
492850
  }
492721
- const rendersDir = join38(projectDir, "renders");
492722
- if (!existsSync57(rendersDir)) return null;
492851
+ const rendersDir = join39(projectDir, "renders");
492852
+ if (!existsSync58(rendersDir)) return null;
492723
492853
  const entries2 = await readdir7(rendersDir, { withFileTypes: true });
492724
492854
  const candidates = [];
492725
492855
  for (const entry of entries2) {
@@ -492727,7 +492857,7 @@ async function resolveRenderVideoPath(projectDir, explicit, beatId) {
492727
492857
  const ext = entry.name.slice(entry.name.lastIndexOf(".")).toLowerCase();
492728
492858
  if (!VIDEO_EXTENSIONS.has(ext)) continue;
492729
492859
  if (beatId && !entry.name.includes(sanitizeFileSegment2(beatId))) continue;
492730
- const full = join38(rendersDir, entry.name);
492860
+ const full = join39(rendersDir, entry.name);
492731
492861
  const info = await stat6(full);
492732
492862
  candidates.push({ path: full, mtimeMs: info.mtimeMs });
492733
492863
  }
@@ -492745,14 +492875,14 @@ async function runAiRenderReview(projectDir, videoPath, model) {
492745
492875
  });
492746
492876
  }
492747
492877
  function resolveStoryboardPath(projectDir) {
492748
- const storyboardPath = join38(projectDir, "STORYBOARD.md");
492749
- return existsSync57(storyboardPath) ? storyboardPath : null;
492878
+ const storyboardPath = join39(projectDir, "STORYBOARD.md");
492879
+ return existsSync58(storyboardPath) ? storyboardPath : null;
492750
492880
  }
492751
492881
  async function expectedDurationFromBuildReport(projectDir, beatId) {
492752
- const reportPath = join38(projectDir, "build-report.json");
492753
- if (!existsSync57(reportPath)) return void 0;
492882
+ const reportPath = join39(projectDir, "build-report.json");
492883
+ if (!existsSync58(reportPath)) return void 0;
492754
492884
  try {
492755
- const report = JSON.parse(await readFile32(reportPath, "utf-8"));
492885
+ const report = JSON.parse(await readFile33(reportPath, "utf-8"));
492756
492886
  const beats = beatId ? (report.beats ?? []).filter((beat) => beat.id === beatId) : report.beats ?? [];
492757
492887
  const durations = beats.map(
492758
492888
  (beat) => parseOptionalNumber2(beat.sceneDurationSec) ?? parseOptionalNumber2(beat.narration?.sceneDurationSec)
@@ -492764,10 +492894,10 @@ async function expectedDurationFromBuildReport(projectDir, beatId) {
492764
492894
  }
492765
492895
  }
492766
492896
  async function beatTimingsFromBuildReport(projectDir, beatId) {
492767
- const reportPath = join38(projectDir, "build-report.json");
492768
- if (!existsSync57(reportPath)) return [];
492897
+ const reportPath = join39(projectDir, "build-report.json");
492898
+ if (!existsSync58(reportPath)) return [];
492769
492899
  try {
492770
- const report = JSON.parse(await readFile32(reportPath, "utf-8"));
492900
+ const report = JSON.parse(await readFile33(reportPath, "utf-8"));
492771
492901
  const source3 = report.beats ?? [];
492772
492902
  const selected = beatId ? source3.filter((beat) => beat.id === beatId) : source3;
492773
492903
  let cursor = 0;
@@ -492793,17 +492923,17 @@ async function beatTimingsFromBuildReport(projectDir, beatId) {
492793
492923
  }
492794
492924
  async function buildRenderReviewProjectContext(projectDir) {
492795
492925
  const parts = [];
492796
- const storyboard = await readTextIfExists(join38(projectDir, "STORYBOARD.md"));
492926
+ const storyboard = await readTextIfExists(join39(projectDir, "STORYBOARD.md"));
492797
492927
  if (storyboard) {
492798
492928
  parts.push(`STORYBOARD.md:
492799
492929
  ${truncateText(storyboard, 4e3)}`);
492800
492930
  parts.push(`Storyboard beat cue summary:
492801
492931
  ${storyboardBeatCueSummary(storyboard)}`);
492802
492932
  }
492803
- const design = await readTextIfExists(join38(projectDir, "DESIGN.md"));
492933
+ const design = await readTextIfExists(join39(projectDir, "DESIGN.md"));
492804
492934
  if (design) parts.push(`DESIGN.md:
492805
492935
  ${truncateText(design, 4e3)}`);
492806
- const buildReport = await readTextIfExists(join38(projectDir, "build-report.json"));
492936
+ const buildReport = await readTextIfExists(join39(projectDir, "build-report.json"));
492807
492937
  if (buildReport) parts.push(`build-report.json:
492808
492938
  ${truncateText(buildReport, 6e3)}`);
492809
492939
  const timings = await beatTimingsFromBuildReport(projectDir);
@@ -492831,9 +492961,9 @@ function storyboardBeatCueSummary(storyboard) {
492831
492961
  }
492832
492962
  }
492833
492963
  async function readTextIfExists(path14) {
492834
- if (!existsSync57(path14)) return null;
492964
+ if (!existsSync58(path14)) return null;
492835
492965
  try {
492836
- return await readFile32(path14, "utf-8");
492966
+ return await readFile33(path14, "utf-8");
492837
492967
  } catch {
492838
492968
  return null;
492839
492969
  }
@@ -493652,17 +493782,17 @@ var generateTools = [
493652
493782
  ];
493653
493783
 
493654
493784
  // ../cli/src/tools/manifest/storyboard.ts
493655
- import { existsSync as existsSync60 } from "node:fs";
493656
- import { readFile as readFile36, writeFile as writeFile43 } from "node:fs/promises";
493785
+ import { existsSync as existsSync61 } from "node:fs";
493786
+ import { readFile as readFile37, writeFile as writeFile43 } from "node:fs/promises";
493657
493787
  import { resolve as resolve65 } from "node:path";
493658
493788
  import { z as z7 } from "zod";
493659
493789
  init_storyboard_parse();
493660
493790
  init_storyboard_edit();
493661
493791
 
493662
493792
  // ../cli/src/commands/_shared/storyboard-revise.ts
493663
- import { existsSync as existsSync59 } from "node:fs";
493664
- import { readFile as readFile35, writeFile as writeFile42 } from "node:fs/promises";
493665
- import { join as join39, resolve as resolve64 } from "node:path";
493793
+ import { existsSync as existsSync60 } from "node:fs";
493794
+ import { readFile as readFile36, writeFile as writeFile42 } from "node:fs/promises";
493795
+ import { join as join40, resolve as resolve64 } from "node:path";
493666
493796
 
493667
493797
  // ../cli/src/agent/adapters/index.ts
493668
493798
  init_openai3();
@@ -493714,9 +493844,9 @@ init_storyboard_parse();
493714
493844
  init_storyboard_edit();
493715
493845
  async function executeStoryboardRevision(opts) {
493716
493846
  const projectDir = resolve64(opts.projectDir);
493717
- const storyboardPath = join39(projectDir, "STORYBOARD.md");
493847
+ const storyboardPath = join40(projectDir, "STORYBOARD.md");
493718
493848
  const retryWith = [`vibe storyboard revise ${projectDir} --from "<request>" --dry-run --json`];
493719
- if (!existsSync59(storyboardPath)) {
493849
+ if (!existsSync60(storyboardPath)) {
493720
493850
  return failureResult({
493721
493851
  projectDir,
493722
493852
  storyboardPath,
@@ -493726,7 +493856,7 @@ async function executeStoryboardRevision(opts) {
493726
493856
  retryWith: [`vibe init ${projectDir} --from "<brief>" --json`]
493727
493857
  });
493728
493858
  }
493729
- const currentStoryboard = await readFile35(storyboardPath, "utf-8");
493859
+ const currentStoryboard = await readFile36(storyboardPath, "utf-8");
493730
493860
  const projectConfig = await readProjectConfig(projectDir);
493731
493861
  const explicitComposer = opts.composer ?? projectConfig.config.providers.composer ?? void 0;
493732
493862
  let provider = explicitComposer ?? "claude";
@@ -493949,18 +494079,18 @@ function diffChangedBeats(before2, after2) {
493949
494079
  return ids.filter((id) => JSON.stringify(beforeBeats.get(id) ?? null) !== JSON.stringify(afterBeats.get(id) ?? null));
493950
494080
  }
493951
494081
  async function readRevisionContext(projectDir) {
493952
- const designMd = await readOptionalText(join39(projectDir, "DESIGN.md"));
493953
- const buildReportJson = await readOptionalJsonText(join39(projectDir, "build-report.json"));
494082
+ const designMd = await readOptionalText(join40(projectDir, "DESIGN.md"));
494083
+ const buildReportJson = await readOptionalJsonText(join40(projectDir, "build-report.json"));
493954
494084
  return { designMd, buildReportJson };
493955
494085
  }
493956
494086
  async function readOptionalText(path14) {
493957
- if (!existsSync59(path14)) return null;
493958
- return readFile35(path14, "utf-8");
494087
+ if (!existsSync60(path14)) return null;
494088
+ return readFile36(path14, "utf-8");
493959
494089
  }
493960
494090
  async function readOptionalJsonText(path14) {
493961
- if (!existsSync59(path14)) return null;
494091
+ if (!existsSync60(path14)) return null;
493962
494092
  try {
493963
- const parsed = JSON.parse(await readFile35(path14, "utf-8"));
494093
+ const parsed = JSON.parse(await readFile36(path14, "utf-8"));
493964
494094
  return JSON.stringify(parsed, null, 2);
493965
494095
  } catch {
493966
494096
  return null;
@@ -494005,8 +494135,8 @@ var projectDirSchema = z7.object({
494005
494135
  });
494006
494136
  async function readStoryboard(projectDir) {
494007
494137
  const path14 = resolve65(projectDir, "STORYBOARD.md");
494008
- if (!existsSync60(path14)) return null;
494009
- return { path: path14, markdown: await readFile36(path14, "utf-8") };
494138
+ if (!existsSync61(path14)) return null;
494139
+ return { path: path14, markdown: await readFile37(path14, "utf-8") };
494010
494140
  }
494011
494141
  var storyboardListTool = defineTool({
494012
494142
  name: "storyboard_list",
@@ -494265,7 +494395,7 @@ var storyboardTools = [
494265
494395
  // ../cli/src/tools/manifest/remix.ts
494266
494396
  import { writeFile as writeFile48 } from "node:fs/promises";
494267
494397
  import { tmpdir as tmpdir6 } from "node:os";
494268
- import { join as join40 } from "node:path";
494398
+ import { join as join41 } from "node:path";
494269
494399
  import { z as z8 } from "zod";
494270
494400
 
494271
494401
  // ../cli/src/commands/ai-script-pipeline.ts
@@ -494276,9 +494406,9 @@ init_config();
494276
494406
  init_audio();
494277
494407
  init_ai_helpers();
494278
494408
  init_video_utils();
494279
- import { readFile as readFile37, writeFile as writeFile44, unlink as unlink6, rename as rename6 } from "node:fs/promises";
494409
+ import { readFile as readFile38, writeFile as writeFile44, unlink as unlink6, rename as rename6 } from "node:fs/promises";
494280
494410
  import { resolve as resolve66, extname as extname12 } from "node:path";
494281
- import { existsSync as existsSync61 } from "node:fs";
494411
+ import { existsSync as existsSync63 } from "node:fs";
494282
494412
 
494283
494413
  // ../cli/src/commands/_shared/video-providers.ts
494284
494414
  init_source();
@@ -494437,16 +494567,16 @@ async function executeRegenerateScene(options) {
494437
494567
  };
494438
494568
  try {
494439
494569
  const outputDir = resolve66(process.cwd(), options.projectDir);
494440
- if (!existsSync61(outputDir)) {
494570
+ if (!existsSync63(outputDir)) {
494441
494571
  return { ...result, error: `Project directory not found: ${outputDir}` };
494442
494572
  }
494443
494573
  const yamlPath = resolve66(outputDir, "storyboard.yaml");
494444
494574
  const jsonPath = resolve66(outputDir, "storyboard.json");
494445
- const storyboardPath = existsSync61(yamlPath) ? yamlPath : existsSync61(jsonPath) ? jsonPath : null;
494575
+ const storyboardPath = existsSync63(yamlPath) ? yamlPath : existsSync63(jsonPath) ? jsonPath : null;
494446
494576
  if (!storyboardPath) {
494447
494577
  return { ...result, error: `Storyboard not found in: ${outputDir} (expected storyboard.yaml or storyboard.json)` };
494448
494578
  }
494449
- const storyboardContent = await readFile37(storyboardPath, "utf-8");
494579
+ const storyboardContent = await readFile38(storyboardPath, "utf-8");
494450
494580
  const segments = storyboardPath.endsWith(".yaml") ? (0, import_yaml6.parse)(storyboardContent).scenes : JSON.parse(storyboardContent);
494451
494581
  for (const sceneNum of options.scenes) {
494452
494582
  if (sceneNum < 1 || sceneNum > segments.length) {
@@ -494535,15 +494665,15 @@ IMPORTANT - Character appearance must match exactly: ${characterDesc}`;
494535
494665
  const refSceneNum = options.referenceScene;
494536
494666
  if (refSceneNum && refSceneNum >= 1 && refSceneNum <= segments.length && refSceneNum !== sceneNum) {
494537
494667
  const refImagePath = resolve66(outputDir, `scene-${refSceneNum}.png`);
494538
- if (existsSync61(refImagePath)) {
494539
- referenceImageBuffer = await readFile37(refImagePath);
494668
+ if (existsSync63(refImagePath)) {
494669
+ referenceImageBuffer = await readFile38(refImagePath);
494540
494670
  }
494541
494671
  } else if (!refSceneNum) {
494542
494672
  for (let i2 = 1; i2 <= segments.length; i2++) {
494543
494673
  if (i2 !== sceneNum) {
494544
494674
  const otherImagePath = resolve66(outputDir, `scene-${i2}.png`);
494545
- if (existsSync61(otherImagePath)) {
494546
- referenceImageBuffer = await readFile37(otherImagePath);
494675
+ if (existsSync63(otherImagePath)) {
494676
+ referenceImageBuffer = await readFile38(otherImagePath);
494547
494677
  break;
494548
494678
  }
494549
494679
  }
@@ -494631,11 +494761,11 @@ Generate the single-person scene image now.`;
494631
494761
  }
494632
494762
  if (regenerateVideo && videoApiKey) {
494633
494763
  options.onProgress?.(`Scene ${sceneNum}: regenerating video (${options.generator || "grok"})...`);
494634
- if (!existsSync61(imagePath)) {
494764
+ if (!existsSync63(imagePath)) {
494635
494765
  result.failedScenes.push(sceneNum);
494636
494766
  continue;
494637
494767
  }
494638
- const imageBuffer = await readFile37(imagePath);
494768
+ const imageBuffer = await readFile38(imagePath);
494639
494769
  const videoDuration = segment.duration > 5 ? 10 : 5;
494640
494770
  const maxRetries = options.retries ?? DEFAULT_VIDEO_RETRIES;
494641
494771
  if (options.generator === "grok") {
@@ -494843,9 +494973,9 @@ Generate the single-person scene image now.`;
494843
494973
  }
494844
494974
 
494845
494975
  // ../cli/src/commands/ai-highlights.ts
494846
- import { readFile as readFile38, writeFile as writeFile45, mkdir as mkdir27 } from "node:fs/promises";
494976
+ import { readFile as readFile39, writeFile as writeFile45, mkdir as mkdir27 } from "node:fs/promises";
494847
494977
  import { resolve as resolve67, dirname as dirname31, basename as basename17, extname as extname13 } from "node:path";
494848
- import { existsSync as existsSync63 } from "node:fs";
494978
+ import { existsSync as existsSync64 } from "node:fs";
494849
494979
  init_dist();
494850
494980
  init_engine();
494851
494981
  init_api_key();
@@ -494876,7 +495006,7 @@ function filterHighlights(highlights, options) {
494876
495006
  async function executeHighlights(options) {
494877
495007
  try {
494878
495008
  const absPath = resolve67(process.cwd(), options.media);
494879
- if (!existsSync63(absPath)) {
495009
+ if (!existsSync64(absPath)) {
494880
495010
  return { success: false, highlights: [], totalDuration: 0, totalHighlightDuration: 0, error: `File not found: ${absPath}` };
494881
495011
  }
494882
495012
  const ext = extname13(absPath).toLowerCase();
@@ -494895,7 +495025,7 @@ async function executeHighlights(options) {
494895
495025
  sourceDuration = await ffprobeDuration(absPath);
494896
495026
  const gemini = new GeminiProvider();
494897
495027
  await gemini.initialize({ apiKey: geminiApiKey });
494898
- const videoBuffer = await readFile38(absPath);
495028
+ const videoBuffer = await readFile39(absPath);
494899
495029
  const criteriaText = options.criteria === "all" || !options.criteria ? "emotional, informative, and funny moments" : `${options.criteria} moments`;
494900
495030
  const durationText = targetDuration ? `Target a total highlight duration of ${targetDuration} seconds.` : "";
494901
495031
  const countText = maxCount ? `Find up to ${maxCount} highlights.` : "";
@@ -494989,10 +495119,10 @@ Analyze both what is SHOWN (visual cues, actions, expressions) and what is SAID
494989
495119
  }
494990
495120
  const whisper = new WhisperProvider();
494991
495121
  await whisper.initialize({ apiKey: openaiApiKey });
494992
- const audioBuffer = await readFile38(audioPath);
495122
+ const audioBuffer = await readFile39(audioPath);
494993
495123
  const audioBlob = new Blob([audioBuffer]);
494994
495124
  const transcriptResult = await whisper.transcribe(audioBlob, options.language);
494995
- if (tempAudioPath && existsSync63(tempAudioPath)) {
495125
+ if (tempAudioPath && existsSync64(tempAudioPath)) {
494996
495126
  const { unlink: unlinkFile } = await import("node:fs/promises");
494997
495127
  await unlinkFile(tempAudioPath).catch(() => {
494998
495128
  });
@@ -495079,7 +495209,7 @@ async function executeAutoShorts(options) {
495079
495209
  return { success: false, shorts: [], error: "FFmpeg not found" };
495080
495210
  }
495081
495211
  const absPath = resolve67(process.cwd(), options.video);
495082
- if (!existsSync63(absPath)) {
495212
+ if (!existsSync64(absPath)) {
495083
495213
  return { success: false, shorts: [], error: `File not found: ${absPath}` };
495084
495214
  }
495085
495215
  const targetDuration = options.duration ?? 60;
@@ -495092,7 +495222,7 @@ async function executeAutoShorts(options) {
495092
495222
  }
495093
495223
  const gemini = new GeminiProvider();
495094
495224
  await gemini.initialize({ apiKey: geminiApiKey });
495095
- const videoBuffer = await readFile38(absPath);
495225
+ const videoBuffer = await readFile39(absPath);
495096
495226
  const geminiPrompt = `Analyze this video to find the BEST moments for short-form vertical video content (TikTok, YouTube Shorts, Instagram Reels).
495097
495227
 
495098
495228
  Find ${shortCount * 3} potential clips that are ${targetDuration} seconds or shorter each.
@@ -495169,7 +495299,7 @@ Analyze both VISUALS (expressions, actions, scene changes) and AUDIO (speech, re
495169
495299
  await execSafe("ffmpeg", ["-i", absPath, "-vn", "-acodec", "libmp3lame", "-q:a", "2", tempAudio, "-y"]);
495170
495300
  const whisper = new WhisperProvider();
495171
495301
  await whisper.initialize({ apiKey: openaiApiKey });
495172
- const audioBuffer = await readFile38(tempAudio);
495302
+ const audioBuffer = await readFile39(tempAudio);
495173
495303
  const audioBlob = new Blob([audioBuffer]);
495174
495304
  const transcript = await whisper.transcribe(audioBlob, options.language);
495175
495305
  try {
@@ -495207,7 +495337,7 @@ Analyze both VISUALS (expressions, actions, scene changes) and AUDIO (speech, re
495207
495337
  };
495208
495338
  }
495209
495339
  const outputDir = options.outputDir ? resolve67(process.cwd(), options.outputDir) : dirname31(absPath);
495210
- if (options.outputDir && !existsSync63(outputDir)) {
495340
+ if (options.outputDir && !existsSync64(outputDir)) {
495211
495341
  await mkdir27(outputDir, { recursive: true });
495212
495342
  }
495213
495343
  const result = {
@@ -495286,8 +495416,8 @@ Analyze both VISUALS (expressions, actions, scene changes) and AUDIO (speech, re
495286
495416
  // ../cli/src/pipeline/executor.ts
495287
495417
  var import_yaml7 = __toESM(require_dist3(), 1);
495288
495418
  import { resolve as resolve69 } from "node:path";
495289
- import { readFile as readFile40, writeFile as writeFile47, mkdir as mkdir28 } from "node:fs/promises";
495290
- import { existsSync as existsSync64 } from "node:fs";
495419
+ import { readFile as readFile41, writeFile as writeFile47, mkdir as mkdir28 } from "node:fs/promises";
495420
+ import { existsSync as existsSync65 } from "node:fs";
495291
495421
 
495292
495422
  // ../cli/src/pipeline/resolver.ts
495293
495423
  function resolveStepParams(params, completedSteps) {
@@ -495700,10 +495830,10 @@ async function ensureActionsRegistered() {
495700
495830
  }
495701
495831
  async function loadPipeline(filePath) {
495702
495832
  const absPath = resolve69(process.cwd(), filePath);
495703
- if (!existsSync64(absPath)) {
495833
+ if (!existsSync65(absPath)) {
495704
495834
  throw new Error(`Pipeline file not found: ${absPath}`);
495705
495835
  }
495706
- const content = await readFile40(absPath, "utf-8");
495836
+ const content = await readFile41(absPath, "utf-8");
495707
495837
  const manifest2 = (0, import_yaml7.parse)(content);
495708
495838
  if (!manifest2.name) throw new Error("Pipeline missing 'name' field");
495709
495839
  if (!manifest2.steps || !Array.isArray(manifest2.steps)) throw new Error("Pipeline missing 'steps' array");
@@ -495726,8 +495856,8 @@ async function executePipeline(manifest2, options = {}) {
495726
495856
  const startTime = Date.now();
495727
495857
  if (options.resume) {
495728
495858
  const checkpointPath = resolve69(outputDir, CHECKPOINT_FILE);
495729
- if (existsSync64(checkpointPath)) {
495730
- const checkpointContent = await readFile40(checkpointPath, "utf-8");
495859
+ if (existsSync65(checkpointPath)) {
495860
+ const checkpointContent = await readFile41(checkpointPath, "utf-8");
495731
495861
  const checkpoint = (0, import_yaml7.parse)(checkpointContent);
495732
495862
  for (const cs of checkpoint.completedSteps) {
495733
495863
  completedSteps.set(cs.id, {
@@ -495999,7 +496129,7 @@ var pipelineRunTool = defineTool({
495999
496129
  let resolvedPath = args.pipelinePath;
496000
496130
  let tempPath;
496001
496131
  if (args.pipelineYaml) {
496002
- tempPath = join40(tmpdir6(), `vibe-mcp-pipeline-${Date.now()}.yaml`);
496132
+ tempPath = join41(tmpdir6(), `vibe-mcp-pipeline-${Date.now()}.yaml`);
496003
496133
  await writeFile48(tempPath, args.pipelineYaml, "utf-8");
496004
496134
  resolvedPath = tempPath;
496005
496135
  }
@@ -496175,10 +496305,10 @@ init_project_resolver();
496175
496305
  // ../cli/src/tools/manifest/_project-io.ts
496176
496306
  init_engine();
496177
496307
  init_project_resolver();
496178
- import { readFile as readFile41, writeFile as writeFile49 } from "node:fs/promises";
496308
+ import { readFile as readFile42, writeFile as writeFile49 } from "node:fs/promises";
496179
496309
  async function loadProject(projectPath, cwd) {
496180
496310
  const absPath = await resolveTimelineFile(projectPath, cwd);
496181
- const content = await readFile41(absPath, "utf-8");
496311
+ const content = await readFile42(absPath, "utf-8");
496182
496312
  const data = JSON.parse(content);
496183
496313
  return { project: Project.fromJSON(data), absPath };
496184
496314
  }
@@ -496529,12 +496659,12 @@ init_engine();
496529
496659
 
496530
496660
  // ../cli/src/commands/_shared/project-list.ts
496531
496661
  init_storyboard_parse();
496532
- import { readdir as readdir8, readFile as readFile42, stat as stat7 } from "node:fs/promises";
496533
- import { existsSync as existsSync65 } from "node:fs";
496534
- import { join as join41, resolve as resolve71 } from "node:path";
496662
+ import { readdir as readdir8, readFile as readFile43, stat as stat7 } from "node:fs/promises";
496663
+ import { existsSync as existsSync66 } from "node:fs";
496664
+ import { join as join43, resolve as resolve71 } from "node:path";
496535
496665
  async function executeProjectList(opts = {}) {
496536
496666
  const workspaceDir = resolve71(opts.workspaceDir ?? ".");
496537
- if (!existsSync65(workspaceDir)) {
496667
+ if (!existsSync66(workspaceDir)) {
496538
496668
  return {
496539
496669
  success: false,
496540
496670
  workspaceDir,
@@ -496551,11 +496681,11 @@ async function executeProjectList(opts = {}) {
496551
496681
  if (entry.name === "node_modules") continue;
496552
496682
  if (entry.name.startsWith(".")) continue;
496553
496683
  if (entry.name.startsWith("_")) {
496554
- archivedCount += await countProjects(join41(workspaceDir, entry.name));
496684
+ archivedCount += await countProjects(join43(workspaceDir, entry.name));
496555
496685
  continue;
496556
496686
  }
496557
- const projectDir = join41(workspaceDir, entry.name);
496558
- if (!existsSync65(join41(projectDir, "STORYBOARD.md"))) continue;
496687
+ const projectDir = join43(workspaceDir, entry.name);
496688
+ if (!existsSync66(join43(projectDir, "STORYBOARD.md"))) continue;
496559
496689
  projects.push(await describeProject(entry.name, projectDir));
496560
496690
  }
496561
496691
  projects.sort((a2, b2) => b2.updatedAt.localeCompare(a2.updatedAt));
@@ -496565,7 +496695,7 @@ async function countProjects(dir) {
496565
496695
  try {
496566
496696
  const entries2 = await readdir8(dir, { withFileTypes: true });
496567
496697
  return entries2.filter(
496568
- (e2) => e2.isDirectory() && existsSync65(join41(dir, e2.name, "STORYBOARD.md"))
496698
+ (e2) => e2.isDirectory() && existsSync66(join43(dir, e2.name, "STORYBOARD.md"))
496569
496699
  ).length;
496570
496700
  } catch {
496571
496701
  return 0;
@@ -496576,8 +496706,8 @@ async function describeProject(name, projectDir) {
496576
496706
  let storyboardDurationSec = 0;
496577
496707
  const timestamps = [];
496578
496708
  try {
496579
- const storyboardPath = join41(projectDir, "STORYBOARD.md");
496580
- const parsed = parseStoryboard(await readFile42(storyboardPath, "utf-8"));
496709
+ const storyboardPath = join43(projectDir, "STORYBOARD.md");
496710
+ const parsed = parseStoryboard(await readFile43(storyboardPath, "utf-8"));
496581
496711
  beats = parsed.beats.length;
496582
496712
  storyboardDurationSec = Number(
496583
496713
  parsed.beats.reduce((sum, beat) => sum + (beat.duration ?? 0), 0).toFixed(2)
@@ -496588,8 +496718,8 @@ async function describeProject(name, projectDir) {
496588
496718
  let buildStatus;
496589
496719
  let buildUpdatedAt;
496590
496720
  try {
496591
- const reportPath = join41(projectDir, "build-report.json");
496592
- const report = JSON.parse(await readFile42(reportPath, "utf-8"));
496721
+ const reportPath = join43(projectDir, "build-report.json");
496722
+ const report = JSON.parse(await readFile43(reportPath, "utf-8"));
496593
496723
  buildStatus = report.status ?? report.phase;
496594
496724
  buildUpdatedAt = report.updatedAt;
496595
496725
  timestamps.push((await stat7(reportPath)).mtimeMs);
@@ -496597,12 +496727,12 @@ async function describeProject(name, projectDir) {
496597
496727
  }
496598
496728
  let latestRender;
496599
496729
  try {
496600
- const rendersDir = join41(projectDir, "renders");
496730
+ const rendersDir = join43(projectDir, "renders");
496601
496731
  const files = await readdir8(rendersDir);
496602
496732
  let newest;
496603
496733
  for (const file of files) {
496604
496734
  if (!/\.(mp4|webm|mov)$/i.test(file)) continue;
496605
- const { mtimeMs } = await stat7(join41(rendersDir, file));
496735
+ const { mtimeMs } = await stat7(join43(rendersDir, file));
496606
496736
  if (!newest || mtimeMs > newest.mtimeMs) newest = { file, mtimeMs };
496607
496737
  }
496608
496738
  if (newest) {
@@ -496737,7 +496867,7 @@ init_exec_safe();
496737
496867
  init_output();
496738
496868
  init_validate();
496739
496869
  init_project_resolver();
496740
- import { readFile as readFile43, access as access6 } from "node:fs/promises";
496870
+ import { readFile as readFile44, access as access6 } from "node:fs/promises";
496741
496871
  import { resolve as resolve74, basename as basename20 } from "node:path";
496742
496872
  import { spawn as spawn9 } from "node:child_process";
496743
496873
  function timelineBaseName(path14) {
@@ -496814,7 +496944,7 @@ async function runExport(projectPath, outputPath, options = {}) {
496814
496944
  };
496815
496945
  }
496816
496946
  const filePath = await resolveTimelineFile(projectPath);
496817
- const content = await readFile43(filePath, "utf-8");
496947
+ const content = await readFile44(filePath, "utf-8");
496818
496948
  const data = JSON.parse(content);
496819
496949
  const project = Project.fromJSON(data);
496820
496950
  const summary = project.getSummary();
@@ -496938,7 +497068,7 @@ Run 'vibe schema export' for structured parameter info.`).action(async (projectP
496938
497068
  }
496939
497069
  spinner2.text = "Loading project...";
496940
497070
  const filePath = await resolveTimelineFile(projectPath);
496941
- const content = await readFile43(filePath, "utf-8");
497071
+ const content = await readFile44(filePath, "utf-8");
496942
497072
  const data = JSON.parse(content);
496943
497073
  const project = Project.fromJSON(data);
496944
497074
  const summary = project.getSummary();
@@ -497536,14 +497666,14 @@ function getPresetSettings(preset, aspectRatio2) {
497536
497666
  }
497537
497667
  async function runHyperframesExport(projectPath, options, spinner2, startedAt) {
497538
497668
  spinner2.text = "Loading project...";
497539
- const { readFile: readFile46 } = await import("node:fs/promises");
497669
+ const { readFile: readFile47 } = await import("node:fs/promises");
497540
497670
  const { resolve: resolve80 } = await import("node:path");
497541
497671
  const { Project: Project2 } = await Promise.resolve().then(() => (init_engine(), engine_exports));
497542
497672
  const { createHyperframesBackend: createHyperframesBackend2 } = await Promise.resolve().then(() => (init_hyperframes(), hyperframes_exports));
497543
497673
  const { exitWithError: exitWithError2, generalError: generalError2, outputSuccess: outputSuccess2 } = await Promise.resolve().then(() => (init_output(), output_exports));
497544
497674
  const chalk2 = (await Promise.resolve().then(() => (init_source(), source_exports))).default;
497545
497675
  const filePath = await resolveTimelineFile(projectPath);
497546
- const content = await readFile46(filePath, "utf-8");
497676
+ const content = await readFile47(filePath, "utf-8");
497547
497677
  const project = Project2.fromJSON(JSON.parse(content));
497548
497678
  const state = project.getState();
497549
497679
  const outputPath = options.output ? resolve80(process.cwd(), options.output) : resolve80(process.cwd(), `${timelineBaseName(projectPath)}.${options.format ?? "mp4"}`);
@@ -497612,8 +497742,8 @@ var exportVideoTool = defineTool({
497612
497742
  var exportTools = [exportVideoTool];
497613
497743
 
497614
497744
  // ../cli/src/tools/manifest/agent-only.ts
497615
- import { readFile as readFile44, writeFile as writeFile52, readdir as readdir9, stat as stat8, access as access7, unlink as unlink7 } from "node:fs/promises";
497616
- import { resolve as resolve76, join as join43, basename as basename21, extname as extname14 } from "node:path";
497745
+ import { readFile as readFile45, writeFile as writeFile52, readdir as readdir9, stat as stat8, access as access7, unlink as unlink7 } from "node:fs/promises";
497746
+ import { resolve as resolve76, join as join44, basename as basename21, extname as extname14 } from "node:path";
497617
497747
  import { z as z13 } from "zod";
497618
497748
  init_engine();
497619
497749
  init_exec_safe();
@@ -497692,7 +497822,7 @@ var fsListTool = defineTool({
497692
497822
  const results = [];
497693
497823
  for (const entry of entries2) {
497694
497824
  if (args.pattern && !matchPattern(entry.name, args.pattern)) continue;
497695
- const fullPath = join43(absPath, entry.name);
497825
+ const fullPath = join44(absPath, entry.name);
497696
497826
  const stats = await stat8(fullPath);
497697
497827
  if (entry.isDirectory()) {
497698
497828
  results.push(`[DIR] ${entry.name}/`);
@@ -497721,7 +497851,7 @@ var fsReadTool = defineTool({
497721
497851
  async execute(args, ctx) {
497722
497852
  try {
497723
497853
  const absPath = resolve76(ctx.workingDirectory, args.path);
497724
- const content = await readFile44(absPath, "utf-8");
497854
+ const content = await readFile45(absPath, "utf-8");
497725
497855
  const maxLength = 4e3;
497726
497856
  const truncated = content.length > maxLength;
497727
497857
  const output3 = truncated ? content.substring(0, maxLength) + "\n... (truncated)" : content;
@@ -497794,7 +497924,7 @@ var batchImportTool = defineTool({
497794
497924
  async execute(args, ctx) {
497795
497925
  try {
497796
497926
  const filePath = resolve76(ctx.workingDirectory, args.project);
497797
- const content = await readFile44(filePath, "utf-8");
497927
+ const content = await readFile45(filePath, "utf-8");
497798
497928
  const data = JSON.parse(content);
497799
497929
  const project = Project.fromJSON(data);
497800
497930
  const dirPath = resolve76(ctx.workingDirectory, args.directory);
@@ -497805,7 +497935,7 @@ var batchImportTool = defineTool({
497805
497935
  const scanDir = async (dir) => {
497806
497936
  const entries2 = await readdir9(dir, { withFileTypes: true });
497807
497937
  for (const entry of entries2) {
497808
- const entryPath = join43(dir, entry.name);
497938
+ const entryPath = join44(dir, entry.name);
497809
497939
  if (entry.isDirectory() && recursive) {
497810
497940
  await scanDir(entryPath);
497811
497941
  } else if (entry.isFile()) {
@@ -497866,7 +497996,7 @@ var batchConcatTool = defineTool({
497866
497996
  async execute(args, ctx) {
497867
497997
  try {
497868
497998
  const filePath = resolve76(ctx.workingDirectory, args.project);
497869
- const content = await readFile44(filePath, "utf-8");
497999
+ const content = await readFile45(filePath, "utf-8");
497870
498000
  const data = JSON.parse(content);
497871
498001
  const project = Project.fromJSON(data);
497872
498002
  const sourceIds = args.sourceIds ?? [];
@@ -497937,7 +498067,7 @@ var batchApplyEffectTool = defineTool({
497937
498067
  async execute(args, ctx) {
497938
498068
  try {
497939
498069
  const filePath = resolve76(ctx.workingDirectory, args.project);
497940
- const content = await readFile44(filePath, "utf-8");
498070
+ const content = await readFile45(filePath, "utf-8");
497941
498071
  const data = JSON.parse(content);
497942
498072
  const project = Project.fromJSON(data);
497943
498073
  const clipIds = args.clipIds ?? [];
@@ -497992,7 +498122,7 @@ var timelineClearTool = defineTool({
497992
498122
  async execute(args, ctx) {
497993
498123
  try {
497994
498124
  const filePath = await resolveTimelineFile(args.project, ctx.workingDirectory);
497995
- const content = await readFile44(filePath, "utf-8");
498125
+ const content = await readFile45(filePath, "utf-8");
497996
498126
  const data = JSON.parse(content);
497997
498127
  const project = Project.fromJSON(data);
497998
498128
  const what = args.what ?? "clips";
@@ -498069,7 +498199,7 @@ var projectSetTool = defineTool({
498069
498199
  async execute(args, ctx) {
498070
498200
  try {
498071
498201
  const filePath = await resolveTimelineFile(args.projectPath, ctx.workingDirectory);
498072
- const content = await readFile44(filePath, "utf-8");
498202
+ const content = await readFile45(filePath, "utf-8");
498073
498203
  const data = JSON.parse(content);
498074
498204
  const project = Project.fromJSON(data);
498075
498205
  const updates = [];
@@ -498343,8 +498473,8 @@ var mediaCompressTool = defineTool({
498343
498473
  ],
498344
498474
  { maxBuffer: 50 * 1024 * 1024 }
498345
498475
  );
498346
- const inputBuf = await readFile44(absInput);
498347
- const outputBuf = await readFile44(outputPath);
498476
+ const inputBuf = await readFile45(absInput);
498477
+ const outputBuf = await readFile45(outputPath);
498348
498478
  const inputSize = inputBuf.length;
498349
498479
  const outputSize = outputBuf.length;
498350
498480
  const reduction = (inputSize - outputSize) / inputSize * 100;
@@ -499366,7 +499496,7 @@ async function handleToolCall(name, args, extra) {
499366
499496
 
499367
499497
  // src/resources/index.ts
499368
499498
  init_engine();
499369
- import { readFile as readFile45 } from "node:fs/promises";
499499
+ import { readFile as readFile46 } from "node:fs/promises";
499370
499500
  import { resolve as resolve78 } from "node:path";
499371
499501
  var resources = [
499372
499502
  {
@@ -499403,7 +499533,7 @@ var resources = [
499403
499533
  var currentProjectPath = process.env.VIBE_PROJECT_PATH || null;
499404
499534
  async function loadProject2(projectPath) {
499405
499535
  const absPath = resolve78(process.cwd(), projectPath);
499406
- const content = await readFile45(absPath, "utf-8");
499536
+ const content = await readFile46(absPath, "utf-8");
499407
499537
  const data = JSON.parse(content);
499408
499538
  return Project.fromJSON(data);
499409
499539
  }
@@ -499795,14 +499925,14 @@ This creates a music video-style edit where cuts happen in rhythm with the music
499795
499925
  }
499796
499926
 
499797
499927
  // src/instructions.ts
499798
- import { existsSync as existsSync66, mkdirSync as mkdirSync13 } from "node:fs";
499928
+ import { existsSync as existsSync67, mkdirSync as mkdirSync13 } from "node:fs";
499799
499929
  import { delimiter, isAbsolute as isAbsolute9, resolve as resolve79 } from "node:path";
499800
499930
  var DEFAULT_EXTRA_PATH_DIRS = process.platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin", "/opt/local/bin"] : ["/usr/local/bin"];
499801
499931
  function ensureSystemPath(env4 = process.env, extraDirs = DEFAULT_EXTRA_PATH_DIRS) {
499802
499932
  const current = (env4.PATH ?? "").split(delimiter).filter(Boolean);
499803
499933
  const added = [];
499804
499934
  for (const dir of extraDirs) {
499805
- if (!current.includes(dir) && existsSync66(dir)) {
499935
+ if (!current.includes(dir) && existsSync67(dir)) {
499806
499936
  current.push(dir);
499807
499937
  added.push(dir);
499808
499938
  }
@@ -499904,7 +500034,7 @@ function handleCliFlags(argv, version) {
499904
500034
  }
499905
500035
 
499906
500036
  // src/index.ts
499907
- if (handleCliFlags(process.argv.slice(2), "0.113.10")) {
500037
+ if (handleCliFlags(process.argv.slice(2), "0.113.11")) {
499908
500038
  process.exit(0);
499909
500039
  }
499910
500040
  console.log = (...args) => console.error(...args);
@@ -499917,7 +500047,7 @@ var server2 = new Server(
499917
500047
  {
499918
500048
  name: "vibeframe",
499919
500049
  // Stamped with the package version by build.js at bundle time.
499920
- version: "0.113.10"
500050
+ version: "0.113.11"
499921
500051
  },
499922
500052
  {
499923
500053
  capabilities: {