@vibeframe/mcp-server 0.113.9 → 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 +691 -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;
@@ -470555,6 +470643,13 @@ ${finalDurationBullet}
470555
470643
  - If the beat cues include \`narration\`, do not embed an \`<audio>\` tag in the
470556
470644
  scene fragment. The root timeline wires \`assets/narration-${ctx.beat.id}.wav\`
470557
470645
  or \`assets/narration-${ctx.beat.id}.mp3\` separately.
470646
+ - Do NOT invent sound effects. This scene fragment is visual-only: never add
470647
+ an \`<audio>\` tag, and never imply ambient/foley SFX (keyboard clicks, whoosh,
470648
+ applause, room tone) that the beat did not explicitly request. Audio comes
470649
+ only from the beat's explicit \`narration\` and \`music\` cues, wired by the
470650
+ root timeline. If the beat declares an explicit \`sfx\` cue, treat it as intent
470651
+ for the storyboard author \u2014 still do not embed it here \u2014 and only when it is
470652
+ clearly tied to the beat's narration/motion; ignore orphaned or generic SFX.
470558
470653
  - **\`.clip\` elements get visibility control from the framework but NO
470559
470654
  sizing.** Always give \`.clip\` explicit fill via CSS:
470560
470655
  \`{ position: absolute; inset: 0; }\` (or equivalent
@@ -470620,7 +470715,7 @@ ${ctx.storyboardGlobal || "(no global direction)"}
470620
470715
 
470621
470716
  ## ${ctx.beat.heading}
470622
470717
  ${formatBeatCues(ctx.beat.cues)}${cueDurationNote}
470623
- ${ctx.beat.body}
470718
+ ${ctx.beat.body}${formatTranscriptSection(ctx.transcript)}
470624
470719
 
470625
470720
  === Output format ===
470626
470721
 
@@ -470640,7 +470735,7 @@ function computeCacheKey(parts) {
470640
470735
  return createHash5("sha256").update(parts.provider).update("\u241E").update(parts.model).update("\u241E").update(parts.systemPrompt).update("\u241E").update(parts.userPrompt).digest("hex");
470641
470736
  }
470642
470737
  function defaultCacheDir() {
470643
- return join24(USER_CACHE_DIR, "compose-scenes");
470738
+ return join25(USER_CACHE_DIR, "compose-scenes");
470644
470739
  }
470645
470740
  function extractHtml(responseText) {
470646
470741
  const fenced = responseText.match(/```html\s*\n([\s\S]*?)\n```/);
@@ -470664,9 +470759,9 @@ async function composeBeatHtml(ctx, overrides) {
470664
470759
  model: settings.model
470665
470760
  });
470666
470761
  const cacheDir = ctx.cacheDir ?? defaultCacheDir();
470667
- const cachePath = join24(cacheDir, `${cacheKey2}.html`);
470668
- if (existsSync24(cachePath)) {
470669
- 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");
470670
470765
  return { html: html2, cached: true, cacheKey: cacheKey2, model: settings.model, provider: ctx.provider };
470671
470766
  }
470672
470767
  if (!ctx.apiKey) {
@@ -470802,14 +470897,14 @@ async function executeComposeScenesWithSkills(params, outputDir, overrides) {
470802
470897
  const projectRoot = params.project ? resolve18(outputDir, params.project) : resolve18(outputDir);
470803
470898
  const designPath = resolve18(projectRoot, params.design ?? "DESIGN.md");
470804
470899
  const storyboardPath = resolve18(projectRoot, params.storyboard ?? "STORYBOARD.md");
470805
- if (!existsSync24(designPath)) {
470900
+ if (!existsSync25(designPath)) {
470806
470901
  return { success: false, error: `DESIGN.md not found at ${designPath}` };
470807
470902
  }
470808
- if (!existsSync24(storyboardPath)) {
470903
+ if (!existsSync25(storyboardPath)) {
470809
470904
  return { success: false, error: `STORYBOARD.md not found at ${storyboardPath}` };
470810
470905
  }
470811
- const designMd = await readFile9(designPath, "utf-8");
470812
- const storyboardMd = await readFile9(storyboardPath, "utf-8");
470906
+ const designMd = await readFile10(designPath, "utf-8");
470907
+ const storyboardMd = await readFile10(storyboardPath, "utf-8");
470813
470908
  const { global: storyboardGlobal, beats } = parseStoryboard(storyboardMd);
470814
470909
  if (beats.length === 0) {
470815
470910
  return {
@@ -470829,7 +470924,7 @@ async function executeComposeScenesWithSkills(params, outputDir, overrides) {
470829
470924
  provider = params.composer ?? "claude";
470830
470925
  apiKey = "";
470831
470926
  }
470832
- const compositionsDir = join24(projectRoot, "compositions");
470927
+ const compositionsDir = join25(projectRoot, "compositions");
470833
470928
  await mkdir9(compositionsDir, { recursive: true });
470834
470929
  let finalDurations = /* @__PURE__ */ new Map();
470835
470930
  try {
@@ -470843,6 +470938,7 @@ async function executeComposeScenesWithSkills(params, outputDir, overrides) {
470843
470938
  async (beat, beatIndex) => {
470844
470939
  onProgress({ type: "beat-start", beatId: beat.id, beatIndex, totalBeats });
470845
470940
  try {
470941
+ const transcript = await readBeatTranscript(projectRoot, beat.id);
470846
470942
  const result = await composeBeatWithRetry(
470847
470943
  {
470848
470944
  beat,
@@ -470853,11 +470949,12 @@ async function executeComposeScenesWithSkills(params, outputDir, overrides) {
470853
470949
  apiKey,
470854
470950
  effort: params.effort,
470855
470951
  cacheDir: params.cacheDir,
470856
- finalDurationSec: finalDurations.get(beat.id)
470952
+ finalDurationSec: finalDurations.get(beat.id),
470953
+ transcript
470857
470954
  },
470858
470955
  overrides
470859
470956
  );
470860
- const compositionPath = join24(compositionsDir, `scene-${beat.id}.html`);
470957
+ const compositionPath = join25(compositionsDir, `scene-${beat.id}.html`);
470861
470958
  await mkdir9(dirname13(compositionPath), { recursive: true });
470862
470959
  await writeFile14(compositionPath, result.html, "utf-8");
470863
470960
  if (result.cached) {
@@ -470936,7 +471033,7 @@ ${failures.map((f2) => ` - ${f2.beatId}: ${f2.error}`).join("\n")}`,
470936
471033
  data: aggregateData
470937
471034
  };
470938
471035
  }
470939
- 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;
470940
471037
  var init_compose_scenes_skills = __esm({
470941
471038
  "../cli/src/commands/_shared/compose-scenes-skills.ts"() {
470942
471039
  "use strict";
@@ -470952,6 +471049,7 @@ var init_compose_scenes_skills = __esm({
470952
471049
  init_root_sync();
470953
471050
  init_composer_resolve();
470954
471051
  init_config();
471052
+ init_transcribe_narration();
470955
471053
  MODEL_SETTINGS_BY_PROVIDER = {
470956
471054
  // Anthropic Claude Sonnet 4.6 — v0.69 baseline. ~9 s/beat, $3/$15 per MTok.
470957
471055
  claude: {
@@ -470975,6 +471073,7 @@ var init_compose_scenes_skills = __esm({
470975
471073
  high: { model: GEMINI_DEFAULT_TEXT_MODEL, maxTokens: 8e3, costPerMTokIn: 1.5, costPerMTokOut: 9 }
470976
471074
  }
470977
471075
  };
471076
+ TRANSCRIPT_PROMPT_MAX_WORDS = 120;
470978
471077
  ComposeBeatError = class extends Error {
470979
471078
  constructor(code, message, cause) {
470980
471079
  super(message);
@@ -471060,22 +471159,22 @@ var init_compose_scenes_skills = __esm({
471060
471159
  });
471061
471160
 
471062
471161
  // ../cli/src/commands/_shared/compose-prompts.ts
471063
- import { existsSync as existsSync25 } from "node:fs";
471064
- import { readFile as readFile10 } from "node:fs/promises";
471065
- 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";
471066
471165
  async function getComposePrompts(opts) {
471067
471166
  const projectDir = resolve19(opts.projectDir);
471068
- const designPath = join25(projectDir, "DESIGN.md");
471069
- const storyboardPath = join25(projectDir, "STORYBOARD.md");
471070
- const skillPath = join25(projectDir, "SKILL.md");
471071
- 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");
471072
471171
  const warnings = [];
471073
471172
  const baseError = (msg) => ({
471074
471173
  success: false,
471075
471174
  projectDir,
471076
471175
  designReference: "DESIGN.md",
471077
471176
  storyboardReference: "STORYBOARD.md",
471078
- skillReference: existsSync25(skillPath) ? "SKILL.md" : null,
471177
+ skillReference: existsSync26(skillPath) ? "SKILL.md" : null,
471079
471178
  compositionsDir: "compositions",
471080
471179
  beats: [],
471081
471180
  instructions: [],
@@ -471083,18 +471182,18 @@ async function getComposePrompts(opts) {
471083
471182
  warnings,
471084
471183
  error: msg
471085
471184
  });
471086
- if (!existsSync25(designPath)) {
471185
+ if (!existsSync26(designPath)) {
471087
471186
  return baseError(`DESIGN.md not found at ${designPath}. Run \`vibe scene init <dir>\` first.`);
471088
471187
  }
471089
- if (!existsSync25(storyboardPath)) {
471188
+ if (!existsSync26(storyboardPath)) {
471090
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.`);
471091
471190
  }
471092
- if (!existsSync25(skillPath)) {
471191
+ if (!existsSync26(skillPath)) {
471093
471192
  warnings.push(
471094
471193
  "SKILL.md not installed \u2014 host agent won't have Hyperframes rules in context. Run `vibe scene install-skill` to install it."
471095
471194
  );
471096
471195
  }
471097
- const storyboardMd = await readFile10(storyboardPath, "utf-8");
471196
+ const storyboardMd = await readFile11(storyboardPath, "utf-8");
471098
471197
  const parsed = parseStoryboard(storyboardMd);
471099
471198
  if (parsed.beats.length === 0) {
471100
471199
  return baseError(`STORYBOARD.md has no \`## Beat \u2026\` headings.`);
@@ -471116,28 +471215,33 @@ async function getComposePrompts(opts) {
471116
471215
  finalDurations = await resolveProjectBeatDurations(projectDir);
471117
471216
  } catch {
471118
471217
  }
471119
- const result = beats.map((beat) => {
471120
- const outputPathAbs = join25(compositionsDir, `scene-${beat.id}.html`);
471121
- const outputPathRel = relative6(projectDir, outputPathAbs);
471122
- const finalDurationSec = finalDurations.get(beat.id);
471123
- const userPrompt = buildUserPrompt({
471124
- beat,
471125
- storyboardGlobal: parsed.global,
471126
- finalDurationSec
471127
- });
471128
- return {
471129
- id: beat.id,
471130
- heading: beat.heading,
471131
- outputPath: outputPathRel,
471132
- duration: beat.duration,
471133
- finalDurationSec,
471134
- cues: beat.cues,
471135
- body: beat.body,
471136
- userPrompt,
471137
- exists: existsSync25(outputPathAbs)
471138
- };
471139
- });
471140
- 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;
471141
471245
  const instructions = buildInstructions({
471142
471246
  skillRef,
471143
471247
  beatCount: result.length,
@@ -471185,13 +471289,14 @@ var init_compose_prompts = __esm({
471185
471289
  init_compose_scenes_skills();
471186
471290
  init_root_sync();
471187
471291
  init_bundle();
471292
+ init_transcribe_narration();
471188
471293
  }
471189
471294
  });
471190
471295
 
471191
471296
  // ../cli/src/commands/_shared/sub-comp-duration-sync.ts
471192
- import { existsSync as existsSync27 } from "node:fs";
471193
- import { readFile as readFile12 } from "node:fs/promises";
471194
- 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";
471195
471300
  function syncSubCompositionDurationHtml(html, beatId, newDurationSec, fileRel) {
471196
471301
  const compositionId = `scene-${beatId}`;
471197
471302
  const file = fileRel ?? `compositions/${compositionId}.html`;
@@ -471283,15 +471388,15 @@ async function createSubCompDurationSyncPlans(opts) {
471283
471388
  const results = [];
471284
471389
  for (const beat of opts.beats) {
471285
471390
  const fileRel = `compositions/scene-${beat.id}.html`;
471286
- const filePath = join27(projectDir, fileRel);
471287
- if (!existsSync27(filePath)) continue;
471391
+ const filePath = join28(projectDir, fileRel);
471392
+ if (!existsSync28(filePath)) continue;
471288
471393
  const newDurationSec = await resolveSyncedBeatDuration({
471289
471394
  projectDir,
471290
471395
  beatDuration: beat.duration,
471291
471396
  narrationPath: beat.narrationPath,
471292
471397
  sceneDurationSec: beat.sceneDurationSec
471293
471398
  });
471294
- const html = await readFile12(filePath, "utf-8");
471399
+ const html = await readFile13(filePath, "utf-8");
471295
471400
  const outcome = syncSubCompositionDurationHtml(html, beat.id, newDurationSec, fileRel);
471296
471401
  results.push({ ...outcome, file: fileRel, beatId: beat.id });
471297
471402
  }
@@ -471315,7 +471420,7 @@ var init_sub_comp_duration_sync = __esm({
471315
471420
  });
471316
471421
 
471317
471422
  // ../cli/src/commands/_shared/scene-repair.ts
471318
- import { readFile as readFile13, writeFile as writeFile16 } from "node:fs/promises";
471423
+ import { readFile as readFile14, writeFile as writeFile16 } from "node:fs/promises";
471319
471424
  import { relative as relative7, resolve as resolve23 } from "node:path";
471320
471425
  async function executeSceneRepair(opts) {
471321
471426
  const projectDir = resolve23(opts.projectDir);
@@ -471360,7 +471465,7 @@ async function executeSceneRepair(opts) {
471360
471465
  }
471361
471466
  for (const target of targets) {
471362
471467
  const rel = relative7(projectDir, target.abs) || target.abs;
471363
- const html = await readFile13(target.abs, "utf-8");
471468
+ const html = await readFile14(target.abs, "utf-8");
471364
471469
  const findings = lintHtml(html, rel, target.isSub);
471365
471470
  const { html: nextHtml, fixedCodes } = applyMechanicalFixes(html, findings);
471366
471471
  if (fixedCodes.length > 0) {
@@ -471733,15 +471838,15 @@ var init_storyboard_edit = __esm({
471733
471838
  });
471734
471839
 
471735
471840
  // ../cli/src/pipeline/renderers/chrome.ts
471736
- import { existsSync as existsSync29 } from "node:fs";
471841
+ import { existsSync as existsSync30 } from "node:fs";
471737
471842
  import { homedir as homedir7 } from "node:os";
471738
- import { join as join28 } from "node:path";
471843
+ import { join as join29 } from "node:path";
471739
471844
  function findChrome() {
471740
471845
  const candidates = [
471741
471846
  process.env.HYPERFRAMES_CHROME_PATH,
471742
471847
  process.env.CHROME_PATH,
471743
471848
  // puppeteer auto-downloaded headless shell
471744
- join28(
471849
+ join29(
471745
471850
  homedir7(),
471746
471851
  ".cache",
471747
471852
  "puppeteer",
@@ -471759,7 +471864,7 @@ function findChrome() {
471759
471864
  "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe"
471760
471865
  ];
471761
471866
  for (const c2 of candidates) {
471762
- if (c2 && existsSync29(c2)) return c2;
471867
+ if (c2 && existsSync30(c2)) return c2;
471763
471868
  }
471764
471869
  return void 0;
471765
471870
  }
@@ -471791,7 +471896,7 @@ var init_ffmpeg_gate = __esm({
471791
471896
  });
471792
471897
 
471793
471898
  // ../cli/src/commands/_shared/scene-audio-scan.ts
471794
- import { readFile as readFile15 } from "node:fs/promises";
471899
+ import { readFile as readFile16 } from "node:fs/promises";
471795
471900
  import { resolve as resolve25 } from "node:path";
471796
471901
  function parseRootClips(rootHtml) {
471797
471902
  const clips = [];
@@ -471832,7 +471937,7 @@ function makeFsCompositionReader(projectDir) {
471832
471937
  return async (compositionSrcRel) => {
471833
471938
  const abs = resolve25(projectDir, compositionSrcRel);
471834
471939
  try {
471835
- return await readFile15(abs, "utf-8");
471940
+ return await readFile16(abs, "utf-8");
471836
471941
  } catch {
471837
471942
  return null;
471838
471943
  }
@@ -472032,9 +472137,9 @@ __export(scene_render_exports, {
472032
472137
  qualityToCrf: () => qualityToCrf
472033
472138
  });
472034
472139
  import { execFile as execFile2 } from "node:child_process";
472035
- import { existsSync as existsSync30 } from "node:fs";
472036
- import { mkdir as mkdir12, readFile as readFile16, stat as stat3, writeFile as writeFile18 } from "node:fs/promises";
472037
- 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";
472038
472143
  import { promisify as promisify2 } from "node:util";
472039
472144
  function qualityToCrf(quality = "standard") {
472040
472145
  return quality === "draft" ? 28 : quality === "high" ? 18 : 23;
@@ -472122,7 +472227,7 @@ async function executeSceneRender(opts = {}) {
472122
472227
  }
472123
472228
  let autoSyncApplied = false;
472124
472229
  let autoSyncWarning;
472125
- if (!opts.beatId && existsSync30(join29(projectDir, "STORYBOARD.md"))) {
472230
+ if (!opts.beatId && existsSync31(join30(projectDir, "STORYBOARD.md"))) {
472126
472231
  try {
472127
472232
  const rootPlan = await createProjectRootSyncPlan({ projectDir });
472128
472233
  const subPlans = await createSubCompDurationSyncPlans({
@@ -472214,7 +472319,7 @@ async function executeSceneRender(opts = {}) {
472214
472319
  let audioMuxWarning;
472215
472320
  try {
472216
472321
  opts.onProgress?.(0.95, "Mixing audio");
472217
- const rootHtml = await readFile16(resolve27(projectDir, root2), "utf-8");
472322
+ const rootHtml = await readFile17(resolve27(projectDir, root2), "utf-8");
472218
472323
  const audios = await scanSceneAudio({ projectDir, rootHtml });
472219
472324
  audioCount = audios.length;
472220
472325
  if (audios.length > 0) {
@@ -472299,11 +472404,11 @@ async function safeStat(p2) {
472299
472404
  }
472300
472405
  async function prepareBeatRenderRoot(opts) {
472301
472406
  const root2 = `.vibeframe/tmp/render-beat-${sanitizeFileSegment(opts.beatId)}.html`;
472302
- const reportPath = join29(opts.projectDir, "build-report.json");
472407
+ const reportPath = join30(opts.projectDir, "build-report.json");
472303
472408
  const retryWith = [
472304
472409
  `vibe build ${opts.projectDir} --beat ${opts.beatId} --stage sync --json`
472305
472410
  ];
472306
- if (!existsSync30(reportPath)) {
472411
+ if (!existsSync31(reportPath)) {
472307
472412
  return {
472308
472413
  success: false,
472309
472414
  root: root2,
@@ -472314,7 +472419,7 @@ async function prepareBeatRenderRoot(opts) {
472314
472419
  }
472315
472420
  let report;
472316
472421
  try {
472317
- report = JSON.parse(await readFile16(reportPath, "utf-8"));
472422
+ report = JSON.parse(await readFile17(reportPath, "utf-8"));
472318
472423
  } catch (error) {
472319
472424
  return {
472320
472425
  success: false,
@@ -472383,8 +472488,8 @@ async function prepareBeatRenderRoot(opts) {
472383
472488
  durationSec,
472384
472489
  narrationPath
472385
472490
  });
472386
- await mkdir12(dirname16(join29(opts.projectDir, root2)), { recursive: true });
472387
- 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");
472388
472493
  return {
472389
472494
  success: true,
472390
472495
  root: root2,
@@ -472448,7 +472553,7 @@ function reportedBeatAssetPaths(beat) {
472448
472553
  ]);
472449
472554
  }
472450
472555
  async function writeRenderReport(projectDir, result) {
472451
- const reportPath = join29(projectDir, "render-report.json");
472556
+ const reportPath = join30(projectDir, "render-report.json");
472452
472557
  try {
472453
472558
  await writeFile18(
472454
472559
  reportPath,
@@ -472490,7 +472595,7 @@ async function writeRenderReport(projectDir, result) {
472490
472595
  }
472491
472596
  function pathExists3(projectDir, value) {
472492
472597
  const abs = isAbsolute3(value) ? value : resolve27(projectDir, value);
472493
- return existsSync30(abs);
472598
+ return existsSync31(abs);
472494
472599
  }
472495
472600
  function stringValue2(value) {
472496
472601
  return typeof value === "string" && value.length > 0 ? value : void 0;
@@ -472564,7 +472669,7 @@ var init_concurrency = __esm({
472564
472669
  });
472565
472670
 
472566
472671
  // ../cli/src/commands/_shared/build-asset-reference.ts
472567
- import { existsSync as existsSync31 } from "node:fs";
472672
+ import { existsSync as existsSync33 } from "node:fs";
472568
472673
  import { extname as extname5, isAbsolute as isAbsolute4, relative as relative10, resolve as resolve28, sep } from "node:path";
472569
472674
  function resolveTypedAssetReference(projectDir, kind3, value) {
472570
472675
  const raw2 = stringOrUndefined2(value);
@@ -472595,7 +472700,7 @@ function resolveReference(projectDir, kind3, raw2, source3, forcedError) {
472595
472700
  const absPath = isAbsolute4(raw2) ? resolve28(raw2) : resolve28(projectDir, raw2);
472596
472701
  const rel = relative10(resolve28(projectDir), absPath);
472597
472702
  const withinProject = rel.length > 0 && !rel.startsWith("..") && !isAbsolute4(rel);
472598
- const exists = withinProject && existsSync31(absPath);
472703
+ const exists = withinProject && existsSync33(absPath);
472599
472704
  let error = forcedError;
472600
472705
  if (!error && inferred && inferred !== kind3 && !isNarrationAudioReference(kind3, ext)) {
472601
472706
  error = `Asset reference "${raw2}" is a ${inferred} asset, not ${kind3}.`;
@@ -472782,9 +472887,9 @@ var init_build_backdrop_prompt = __esm({
472782
472887
  });
472783
472888
 
472784
472889
  // ../cli/src/commands/_shared/build-plan.ts
472785
- import { existsSync as existsSync33 } from "node:fs";
472786
- import { readFile as readFile17 } from "node:fs/promises";
472787
- 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";
472788
472893
  function backdropCostUsd(quality) {
472789
472894
  return quality === "hd" ? 0.2 : 0.05;
472790
472895
  }
@@ -472793,11 +472898,11 @@ async function createBuildPlan(opts) {
472793
472898
  loadPlanEnv(projectDir);
472794
472899
  const stage = opts.stage ?? "all";
472795
472900
  const config4 = await readProjectConfig(projectDir);
472796
- const storyboardPath = join30(projectDir, "STORYBOARD.md");
472901
+ const storyboardPath = join31(projectDir, "STORYBOARD.md");
472797
472902
  const warnings = [];
472798
472903
  const retryWith = [];
472799
472904
  const providerResolution = [];
472800
- if (!existsSync33(storyboardPath)) {
472905
+ if (!existsSync34(storyboardPath)) {
472801
472906
  const validation4 = {
472802
472907
  ok: false,
472803
472908
  issues: [
@@ -472826,7 +472931,7 @@ async function createBuildPlan(opts) {
472826
472931
  validation: validation4
472827
472932
  });
472828
472933
  }
472829
- const storyboardMd = await readFile17(storyboardPath, "utf-8");
472934
+ const storyboardMd = await readFile18(storyboardPath, "utf-8");
472830
472935
  const validation3 = validateStoryboardMarkdown(storyboardMd);
472831
472936
  const validationIssues = [...validation3.issues];
472832
472937
  const parsed = parseStoryboard(storyboardMd);
@@ -472852,7 +472957,7 @@ async function createBuildPlan(opts) {
472852
472957
  const imageQuality = opts.imageQuality ?? config4.config.build.imageQuality ?? "hd";
472853
472958
  const imageSize2 = opts.imageSize ?? config4.config.build.imageSize ?? "1536x1024";
472854
472959
  const imageRatio = imageRatioForSize(imageSize2);
472855
- 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`)));
472856
472961
  const resolved = await resolvePlanProviders({
472857
472962
  projectDir,
472858
472963
  config: config4,
@@ -473000,7 +473105,7 @@ async function createBuildPlan(opts) {
473000
473105
  active: includeAssets
473001
473106
  }) : null;
473002
473107
  const compositionPath = `compositions/scene-${beat.id}.html`;
473003
- const compositionExists = existsSync33(join30(projectDir, compositionPath));
473108
+ const compositionExists = existsSync34(join31(projectDir, compositionPath));
473004
473109
  for (const asset of [narration, backdrop, keyframe, video, music]) {
473005
473110
  if (!asset) continue;
473006
473111
  if (asset.referenceError) {
@@ -473069,7 +473174,7 @@ async function createBuildPlan(opts) {
473069
473174
  }
473070
473175
  }
473071
473176
  const validationOk = !validationIssues.some((issue) => issue.severity === "error");
473072
- if (!existsSync33(join30(projectDir, config4.config.composition.entry))) {
473177
+ if (!existsSync34(join31(projectDir, config4.config.composition.entry))) {
473073
473178
  missing.add("root-composition");
473074
473179
  if (validationOk) retryWith.push(`vibe build ${projectDir} --stage sync --json`);
473075
473180
  }
@@ -473103,7 +473208,7 @@ async function createBuildPlan(opts) {
473103
473208
  }
473104
473209
  if (referenced.size > 0) {
473105
473210
  const toGenerate = resolveCharacters(parsed.frontmatter).filter(
473106
- (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`)))
473107
473212
  );
473108
473213
  if (toGenerate.length > 0) {
473109
473214
  estimatedCostUsd += toGenerate.length * backdropCostUsd(opts.imageQuality ?? "hd");
@@ -473216,8 +473321,8 @@ function assetPlan(opts) {
473216
473321
  reason: ready ? "referenced-asset" : "invalid-reference"
473217
473322
  };
473218
473323
  }
473219
- const canonicalExists = existsSync33(join30(opts.projectDir, opts.path));
473220
- 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;
473221
473326
  const freshness = assetFreshnessFromMetadata({
473222
473327
  projectDir: opts.projectDir,
473223
473328
  kind: opts.kind,
@@ -473415,7 +473520,7 @@ async function firstConfiguredComposer(projectDir) {
473415
473520
  }
473416
473521
  function firstExisting2(projectDir, paths) {
473417
473522
  for (const path14 of paths) {
473418
- if (existsSync33(join30(projectDir, path14))) return path14;
473523
+ if (existsSync34(join31(projectDir, path14))) return path14;
473419
473524
  }
473420
473525
  return null;
473421
473526
  }
@@ -473456,12 +473561,12 @@ function unique3(items) {
473456
473561
  return [...new Set(items.filter((item) => item.length > 0))];
473457
473562
  }
473458
473563
  function loadPlanEnv(projectDir) {
473459
- (0, import_dotenv2.config)({ path: join30(projectDir, ".env"), quiet: true });
473564
+ (0, import_dotenv2.config)({ path: join31(projectDir, ".env"), quiet: true });
473460
473565
  (0, import_dotenv2.config)({ path: resolve29(process.cwd(), ".env"), quiet: true });
473461
473566
  let dir = process.cwd();
473462
473567
  while (dir !== dirname17(dir)) {
473463
- if (existsSync33(join30(dir, "pnpm-workspace.yaml"))) {
473464
- (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 });
473465
473570
  return;
473466
473571
  }
473467
473572
  dir = dirname17(dir);
@@ -473523,7 +473628,7 @@ var init_validate = __esm({
473523
473628
  // ../cli/src/commands/generate/music.ts
473524
473629
  import { resolve as resolve31 } from "node:path";
473525
473630
  import { writeFile as writeFile19 } from "node:fs/promises";
473526
- import { existsSync as existsSync34 } from "node:fs";
473631
+ import { existsSync as existsSync35 } from "node:fs";
473527
473632
  async function executeMusic(options) {
473528
473633
  try {
473529
473634
  const provider = options.provider || "elevenlabs";
@@ -473676,7 +473781,7 @@ function registerMusicCommand(parent) {
473676
473781
  if (options.melody) {
473677
473782
  spinner2.text = "Uploading melody reference...";
473678
473783
  const absPath = resolve31(process.cwd(), options.melody);
473679
- if (!existsSync34(absPath)) {
473784
+ if (!existsSync35(absPath)) {
473680
473785
  spinner2.fail(`Melody file not found: ${options.melody}`);
473681
473786
  exitWithError(notFoundError(options.melody));
473682
473787
  }
@@ -473809,9 +473914,9 @@ __export(scene_build_exports, {
473809
473914
  executeSceneBuild: () => executeSceneBuild,
473810
473915
  resolveSceneBuildMode: () => resolveSceneBuildMode
473811
473916
  });
473812
- import { existsSync as existsSync35, readFileSync as readFileSync12 } from "node:fs";
473813
- import { copyFile as copyFile4, mkdir as mkdir13, readFile as readFile18, rm as rm3, writeFile as writeFile20 } from "node:fs/promises";
473814
- 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";
473815
473920
  async function executeSceneBuild(opts) {
473816
473921
  const startedAt = Date.now();
473817
473922
  const projectDir = resolve33(opts.projectDir);
@@ -473830,7 +473935,7 @@ async function executeSceneBuild(opts) {
473830
473935
  );
473831
473936
  }
473832
473937
  let sceneRepair = skippedSceneRepairSummary();
473833
- const storyboardPath = join31(projectDir, "STORYBOARD.md");
473938
+ const storyboardPath = join33(projectDir, "STORYBOARD.md");
473834
473939
  const buildPlan = await createBuildPlan({
473835
473940
  projectDir,
473836
473941
  stage: selectedStage,
@@ -473881,8 +473986,8 @@ async function executeSceneBuild(opts) {
473881
473986
  }
473882
473987
  if (!buildPlan.validation.ok) {
473883
473988
  let invalidBeats = [];
473884
- if (existsSync35(storyboardPath)) {
473885
- invalidBeats = parseStoryboard(await readFile18(storyboardPath, "utf-8")).beats;
473989
+ if (existsSync36(storyboardPath)) {
473990
+ invalidBeats = parseStoryboard(await readFile19(storyboardPath, "utf-8")).beats;
473886
473991
  }
473887
473992
  return finishBuildResult({
473888
473993
  success: false,
@@ -473906,7 +474011,7 @@ async function executeSceneBuild(opts) {
473906
474011
  totalLatencyMs: Date.now() - startedAt
473907
474012
  });
473908
474013
  }
473909
- if (!existsSync35(storyboardPath)) {
474014
+ if (!existsSync36(storyboardPath)) {
473910
474015
  return finishBuildResult({
473911
474016
  success: false,
473912
474017
  phase: "failed",
@@ -473920,7 +474025,7 @@ async function executeSceneBuild(opts) {
473920
474025
  totalLatencyMs: Date.now() - startedAt
473921
474026
  });
473922
474027
  }
473923
- const storyboardMd = await readFile18(storyboardPath, "utf-8");
474028
+ const storyboardMd = await readFile19(storyboardPath, "utf-8");
473924
474029
  const parsed = parseStoryboard(storyboardMd);
473925
474030
  if (parsed.beats.length === 0) {
473926
474031
  return finishBuildResult({
@@ -474027,6 +474132,7 @@ async function executeSceneBuild(opts) {
474027
474132
  skipVideo: opts.skipVideo ?? false,
474028
474133
  skipKeyframe: opts.skipKeyframe ?? false,
474029
474134
  skipMusic: opts.skipMusic ?? false,
474135
+ skipTranscript: opts.skipTranscript ?? false,
474030
474136
  force: opts.force ?? false,
474031
474137
  onProgress,
474032
474138
  characterPaths
@@ -474114,9 +474220,9 @@ async function executeSceneBuild(opts) {
474114
474220
  let composeData;
474115
474221
  if (shouldRunStage(selectedStage, "compose")) {
474116
474222
  if (mode === "agent") {
474117
- const compositionsDir = join31(projectDir, "compositions");
474223
+ const compositionsDir = join33(projectDir, "compositions");
474118
474224
  const missingBeats = activeBeats.filter(
474119
- (b2) => !existsSync35(join31(compositionsDir, `scene-${b2.id}.html`))
474225
+ (b2) => !existsSync36(join33(compositionsDir, `scene-${b2.id}.html`))
474120
474226
  );
474121
474227
  if (missingBeats.length > 0) {
474122
474228
  const plan = await getComposePrompts({ projectDir, beatId: opts.beatId });
@@ -474205,8 +474311,8 @@ async function executeSceneBuild(opts) {
474205
474311
  if (stageReports.compose.status === "done") {
474206
474312
  for (const beat of activeBeats) {
474207
474313
  const videoRel = `assets/video-${beat.id}.mp4`;
474208
- const compositionAbs = join31(projectDir, "compositions", `scene-${beat.id}.html`);
474209
- 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;
474210
474316
  const html = readFileSync12(compositionAbs, "utf-8");
474211
474317
  if (!html.includes(videoRel)) {
474212
474318
  warnings.push(
@@ -474264,7 +474370,7 @@ async function executeSceneBuild(opts) {
474264
474370
  });
474265
474371
  }
474266
474372
  if (shouldRunStage(selectedStage, "sync")) {
474267
- if (!existsSync35(join31(projectDir, "index.html"))) {
474373
+ if (!existsSync36(join33(projectDir, "index.html"))) {
474268
474374
  await scaffoldSceneProject({
474269
474375
  dir: projectDir,
474270
474376
  name: projectDir.split(/[\\/]/).filter(Boolean).pop(),
@@ -474409,6 +474515,9 @@ async function buildBeatPrimitives(beat, ctx) {
474409
474515
  ctx.skipVideo ? skipped("video", beat.id, "--skip-video", ctx) : dispatchVideo(beat, ctx, keyframe),
474410
474516
  ctx.skipMusic ? skipped("music", beat.id, "--skip-music", ctx) : dispatchMusic(beat, ctx)
474411
474517
  ]);
474518
+ if (!ctx.skipTranscript) {
474519
+ await dispatchTranscript(beat, narration, ctx);
474520
+ }
474412
474521
  return {
474413
474522
  outcome: {
474414
474523
  beatId: beat.id,
@@ -474526,7 +474635,7 @@ async function dispatchNarration(beat, ctx) {
474526
474635
  return {
474527
474636
  status: "cached",
474528
474637
  path: existingRel,
474529
- durationSec: await safeAudioDuration(join31(ctx.projectDir, existingRel)),
474638
+ durationSec: await safeAudioDuration(join33(ctx.projectDir, existingRel)),
474530
474639
  provider: metadata?.provider,
474531
474640
  cachePath: metadata?.cachePath,
474532
474641
  cacheKey: metadata?.cacheKey,
@@ -474550,9 +474659,9 @@ async function dispatchNarration(beat, ctx) {
474550
474659
  voice,
474551
474660
  ext: resolution.audioExtension
474552
474661
  });
474553
- const cacheAbs = join31(ctx.projectDir, cache.path);
474662
+ const cacheAbs = join33(ctx.projectDir, cache.path);
474554
474663
  const rel = `assets/narration-${beat.id}.${resolution.audioExtension}`;
474555
- const abs = join31(ctx.projectDir, rel);
474664
+ const abs = join33(ctx.projectDir, rel);
474556
474665
  if (existingRel && !ctx.force && isFreshCanonicalAsset({
474557
474666
  projectDir: ctx.projectDir,
474558
474667
  kind: "narration",
@@ -474566,7 +474675,7 @@ async function dispatchNarration(beat, ctx) {
474566
474675
  return {
474567
474676
  status: "cached",
474568
474677
  path: existingRel,
474569
- durationSec: await safeAudioDuration(join31(ctx.projectDir, existingRel)),
474678
+ durationSec: await safeAudioDuration(join33(ctx.projectDir, existingRel)),
474570
474679
  provider: resolution.provider,
474571
474680
  cachePath: cache.path,
474572
474681
  cacheKey: cache.key,
@@ -474574,7 +474683,7 @@ async function dispatchNarration(beat, ctx) {
474574
474683
  freshness: "fresh"
474575
474684
  };
474576
474685
  }
474577
- if (existsSync35(cacheAbs) && !ctx.force) {
474686
+ if (existsSync36(cacheAbs) && !ctx.force) {
474578
474687
  await mkdir13(dirname18(abs), { recursive: true });
474579
474688
  await copyFile4(cacheAbs, abs);
474580
474689
  await writeAssetMetadata({
@@ -474609,8 +474718,8 @@ async function dispatchNarration(beat, ctx) {
474609
474718
  await mkdir13(dirname18(abs), { recursive: true });
474610
474719
  await writeFile20(abs, result.audioBuffer);
474611
474720
  for (const otherExt of ["mp3", "wav"]) {
474612
- const sibling = join31(ctx.projectDir, `assets/narration-${beat.id}.${otherExt}`);
474613
- 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 });
474614
474723
  }
474615
474724
  await mkdir13(dirname18(cacheAbs), { recursive: true });
474616
474725
  await writeFile20(cacheAbs, result.audioBuffer);
@@ -474642,6 +474751,42 @@ async function dispatchNarration(beat, ctx) {
474642
474751
  freshness: "fresh"
474643
474752
  };
474644
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
+ }
474645
474790
  function characterSheetPrompt(name, description) {
474646
474791
  return [
474647
474792
  `Character reference sheet of an original fictional character named ${name}: ${description}.`,
@@ -474659,7 +474804,7 @@ async function buildCharacters(characters, ctx) {
474659
474804
  const size = ctx.imageSize ?? "1536x1024";
474660
474805
  for (const character of characters) {
474661
474806
  if (character.imagePath) {
474662
- if (existsSync35(join31(ctx.projectDir, character.imagePath))) {
474807
+ if (existsSync36(join33(ctx.projectDir, character.imagePath))) {
474663
474808
  paths.set(character.name, character.imagePath);
474664
474809
  ctx.onProgress({ type: "character-cached", name: character.name, path: character.imagePath });
474665
474810
  } else {
@@ -474672,7 +474817,7 @@ async function buildCharacters(characters, ctx) {
474672
474817
  if (!character.prompt) continue;
474673
474818
  const prompt3 = characterSheetPrompt(character.name, character.prompt);
474674
474819
  const rel = `assets/character-${character.name}.png`;
474675
- const abs = join31(ctx.projectDir, rel);
474820
+ const abs = join33(ctx.projectDir, rel);
474676
474821
  const metadataOptions = { quality: ctx.imageQuality, size };
474677
474822
  const cache = characterCacheDescriptor({
474678
474823
  name: character.name,
@@ -474681,7 +474826,7 @@ async function buildCharacters(characters, ctx) {
474681
474826
  quality: ctx.imageQuality,
474682
474827
  size
474683
474828
  });
474684
- if (existsSync35(abs) && !ctx.force) {
474829
+ if (existsSync36(abs) && !ctx.force) {
474685
474830
  const metadata = readAssetMetadata(ctx.projectDir, "character", character.name);
474686
474831
  if (!metadata || isFreshCanonicalAsset({
474687
474832
  projectDir: ctx.projectDir,
@@ -474697,8 +474842,8 @@ async function buildCharacters(characters, ctx) {
474697
474842
  continue;
474698
474843
  }
474699
474844
  }
474700
- const cacheAbs = join31(ctx.projectDir, cache.path);
474701
- if (existsSync35(cacheAbs) && !ctx.force) {
474845
+ const cacheAbs = join33(ctx.projectDir, cache.path);
474846
+ if (existsSync36(cacheAbs) && !ctx.force) {
474702
474847
  await mkdir13(dirname18(abs), { recursive: true });
474703
474848
  await copyFile4(cacheAbs, abs);
474704
474849
  await writeAssetMetadata({
@@ -474764,7 +474909,7 @@ async function dispatchBackdrop(beat, ctx) {
474764
474909
  if (!cue) return { status: "no-cue" };
474765
474910
  const prompt3 = augmentBackdropPrompt(cue);
474766
474911
  const rel = `assets/backdrop-${beat.id}.png`;
474767
- const abs = join31(ctx.projectDir, rel);
474912
+ const abs = join33(ctx.projectDir, rel);
474768
474913
  const size = ctx.imageSize ?? "1536x1024";
474769
474914
  const ratio = imageRatioForSize(size);
474770
474915
  const metadataOptions = { quality: ctx.imageQuality, size, ratio };
@@ -474777,7 +474922,7 @@ async function dispatchBackdrop(beat, ctx) {
474777
474922
  ratio
474778
474923
  });
474779
474924
  const metadataPath = assetMetadataPath("backdrop", beat.id);
474780
- if (existsSync35(abs) && !ctx.force) {
474925
+ if (existsSync36(abs) && !ctx.force) {
474781
474926
  const metadata = readAssetMetadata(ctx.projectDir, "backdrop", beat.id);
474782
474927
  if (!metadata || isFreshCanonicalAsset({
474783
474928
  projectDir: ctx.projectDir,
@@ -474800,8 +474945,8 @@ async function dispatchBackdrop(beat, ctx) {
474800
474945
  };
474801
474946
  }
474802
474947
  }
474803
- const cacheAbs = join31(ctx.projectDir, cache.path);
474804
- if (existsSync35(cacheAbs) && !ctx.force) {
474948
+ const cacheAbs = join33(ctx.projectDir, cache.path);
474949
+ if (existsSync36(cacheAbs) && !ctx.force) {
474805
474950
  await mkdir13(dirname18(abs), { recursive: true });
474806
474951
  await copyFile4(cacheAbs, abs);
474807
474952
  await writeAssetMetadata({
@@ -474933,7 +475078,7 @@ async function editKeyframeImage(prompt3, sheetBuffers, ctx, ratio) {
474933
475078
  }
474934
475079
  async function ensureKeyframe(beat, ctx, keyframeCue, characterRefsRel) {
474935
475080
  const rel = `assets/keyframe-${beat.id}.png`;
474936
- const abs = join31(ctx.projectDir, rel);
475081
+ const abs = join33(ctx.projectDir, rel);
474937
475082
  const size = ctx.imageSize ?? "1536x1024";
474938
475083
  const ratio = imageRatioForSize(size);
474939
475084
  const metadataOptions = { quality: ctx.imageQuality, size, ratio };
@@ -474946,7 +475091,7 @@ async function ensureKeyframe(beat, ctx, keyframeCue, characterRefsRel) {
474946
475091
  ratio,
474947
475092
  characters: characterRefsRel
474948
475093
  });
474949
- if (existsSync35(abs) && !ctx.force) {
475094
+ if (existsSync36(abs) && !ctx.force) {
474950
475095
  const metadata = readAssetMetadata(ctx.projectDir, "keyframe", beat.id);
474951
475096
  if (!metadata || isFreshCanonicalAsset({
474952
475097
  projectDir: ctx.projectDir,
@@ -474960,8 +475105,8 @@ async function ensureKeyframe(beat, ctx, keyframeCue, characterRefsRel) {
474960
475105
  return { status: "cached", rel };
474961
475106
  }
474962
475107
  }
474963
- const cacheAbs = join31(ctx.projectDir, cache.path);
474964
- if (existsSync35(cacheAbs) && !ctx.force) {
475108
+ const cacheAbs = join33(ctx.projectDir, cache.path);
475109
+ if (existsSync36(cacheAbs) && !ctx.force) {
474965
475110
  await mkdir13(dirname18(abs), { recursive: true });
474966
475111
  await copyFile4(cacheAbs, abs);
474967
475112
  await writeAssetMetadata({
@@ -474979,8 +475124,8 @@ async function ensureKeyframe(beat, ctx, keyframeCue, characterRefsRel) {
474979
475124
  }
474980
475125
  const sheetBuffers = [];
474981
475126
  for (const relPath of characterRefsRel) {
474982
- const sheetAbs = join31(ctx.projectDir, relPath);
474983
- if (existsSync35(sheetAbs)) sheetBuffers.push(await readFile18(sheetAbs));
475127
+ const sheetAbs = join33(ctx.projectDir, relPath);
475128
+ if (existsSync36(sheetAbs)) sheetBuffers.push(await readFile19(sheetAbs));
474984
475129
  }
474985
475130
  const imgCtx = {
474986
475131
  projectDir: ctx.projectDir,
@@ -475049,9 +475194,9 @@ async function dispatchVideo(beat, ctx, keyframe) {
475049
475194
  const prompt3 = stringOrUndefined4(beat.cues?.video) ?? keyframeCue;
475050
475195
  if (!prompt3) return { status: "no-cue" };
475051
475196
  const characterRefsRel = beatCharacterNames(beat.cues).map((name) => ctx.characterPaths?.get(name)).filter((p2) => typeof p2 === "string");
475052
- const characterRefsAbs = characterRefsRel.map((p2) => join31(ctx.projectDir, p2));
475197
+ const characterRefsAbs = characterRefsRel.map((p2) => join33(ctx.projectDir, p2));
475053
475198
  const rel = `assets/video-${beat.id}.mp4`;
475054
- const abs = join31(ctx.projectDir, rel);
475199
+ const abs = join33(ctx.projectDir, rel);
475055
475200
  const cache = videoCacheDescriptor({
475056
475201
  beatId: beat.id,
475057
475202
  cue: prompt3,
@@ -475063,7 +475208,7 @@ async function dispatchVideo(beat, ctx, keyframe) {
475063
475208
  keyframe: keyframeCue
475064
475209
  });
475065
475210
  const metadataPath = assetMetadataPath("video", beat.id);
475066
- if (existsSync35(abs) && !ctx.force) {
475211
+ if (existsSync36(abs) && !ctx.force) {
475067
475212
  const metadata = readAssetMetadata(ctx.projectDir, "video", beat.id);
475068
475213
  if (!metadata || isFreshCanonicalAsset({
475069
475214
  projectDir: ctx.projectDir,
@@ -475086,8 +475231,8 @@ async function dispatchVideo(beat, ctx, keyframe) {
475086
475231
  };
475087
475232
  }
475088
475233
  }
475089
- const cacheAbs = join31(ctx.projectDir, cache.path);
475090
- if (existsSync35(cacheAbs) && !ctx.force) {
475234
+ const cacheAbs = join33(ctx.projectDir, cache.path);
475235
+ if (existsSync36(cacheAbs) && !ctx.force) {
475091
475236
  await mkdir13(dirname18(abs), { recursive: true });
475092
475237
  await copyFile4(cacheAbs, abs);
475093
475238
  await writeAssetMetadata({
@@ -475118,7 +475263,7 @@ async function dispatchVideo(beat, ctx, keyframe) {
475118
475263
  ctx.onProgress({ type: "video-skipped", beatId: beat.id, reason });
475119
475264
  return { status: "skipped" };
475120
475265
  }
475121
- const keyframeImageAbs = keyframeImageRel ? join31(ctx.projectDir, keyframeImageRel) : void 0;
475266
+ const keyframeImageAbs = keyframeImageRel ? join33(ctx.projectDir, keyframeImageRel) : void 0;
475122
475267
  loadSceneBuildEnv(ctx.projectDir);
475123
475268
  const result = await executeVideoGenerate({
475124
475269
  prompt: prompt3,
@@ -475142,7 +475287,7 @@ async function dispatchVideo(beat, ctx, keyframe) {
475142
475287
  ctx.onProgress({ type: "video-failed", beatId: beat.id, error });
475143
475288
  return { status: "failed", error };
475144
475289
  }
475145
- if (result.status === "completed" && existsSync35(abs)) {
475290
+ if (result.status === "completed" && existsSync36(abs)) {
475146
475291
  await mkdir13(dirname18(cacheAbs), { recursive: true });
475147
475292
  await copyFile4(abs, cacheAbs);
475148
475293
  await writeAssetMetadata({
@@ -475210,7 +475355,7 @@ async function dispatchMusic(beat, ctx) {
475210
475355
  const prompt3 = stringOrUndefined4(beat.cues?.music);
475211
475356
  if (!prompt3) return { status: "no-cue" };
475212
475357
  const rel = `assets/music-${beat.id}.mp3`;
475213
- const abs = join31(ctx.projectDir, rel);
475358
+ const abs = join33(ctx.projectDir, rel);
475214
475359
  const duration = normalizeMusicDuration(beat.duration);
475215
475360
  const cache = musicCacheDescriptor({
475216
475361
  beatId: beat.id,
@@ -475219,7 +475364,7 @@ async function dispatchMusic(beat, ctx) {
475219
475364
  duration
475220
475365
  });
475221
475366
  const metadataPath = assetMetadataPath("music", beat.id);
475222
- if (existsSync35(abs) && !ctx.force) {
475367
+ if (existsSync36(abs) && !ctx.force) {
475223
475368
  const metadata = readAssetMetadata(ctx.projectDir, "music", beat.id);
475224
475369
  if (!metadata || isFreshCanonicalAsset({
475225
475370
  projectDir: ctx.projectDir,
@@ -475243,8 +475388,8 @@ async function dispatchMusic(beat, ctx) {
475243
475388
  };
475244
475389
  }
475245
475390
  }
475246
- const cacheAbs = join31(ctx.projectDir, cache.path);
475247
- if (existsSync35(cacheAbs) && !ctx.force) {
475391
+ const cacheAbs = join33(ctx.projectDir, cache.path);
475392
+ if (existsSync36(cacheAbs) && !ctx.force) {
475248
475393
  await mkdir13(dirname18(abs), { recursive: true });
475249
475394
  await copyFile4(cacheAbs, abs);
475250
475395
  await writeAssetMetadata({
@@ -475318,7 +475463,7 @@ async function dispatchMusic(beat, ctx) {
475318
475463
  metadataPath
475319
475464
  };
475320
475465
  }
475321
- if (!existsSync35(abs)) {
475466
+ if (!existsSync36(abs)) {
475322
475467
  const error = result.outputPath ? `music output was not written at ${abs}` : "music generation did not return an output file";
475323
475468
  ctx.onProgress({ type: "music-failed", beatId: beat.id, error });
475324
475469
  return { status: "failed", error };
@@ -475354,12 +475499,12 @@ async function dispatchMusic(beat, ctx) {
475354
475499
  };
475355
475500
  }
475356
475501
  function loadSceneBuildEnv(projectDir) {
475357
- (0, import_dotenv3.config)({ path: join31(projectDir, ".env"), quiet: true });
475502
+ (0, import_dotenv3.config)({ path: join33(projectDir, ".env"), quiet: true });
475358
475503
  (0, import_dotenv3.config)({ path: resolve33(process.cwd(), ".env"), quiet: true });
475359
475504
  let dir = process.cwd();
475360
475505
  while (dir !== dirname18(dir)) {
475361
- if (existsSync35(join31(dir, "pnpm-workspace.yaml"))) {
475362
- (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 });
475363
475508
  return;
475364
475509
  }
475365
475510
  dir = dirname18(dir);
@@ -475575,7 +475720,7 @@ function mergeBeatOutcomes(base, updates) {
475575
475720
  }
475576
475721
  function firstExisting3(projectDir, relPaths) {
475577
475722
  for (const rel of relPaths) {
475578
- if (existsSync35(join31(projectDir, rel))) return rel;
475723
+ if (existsSync36(join33(projectDir, rel))) return rel;
475579
475724
  }
475580
475725
  return null;
475581
475726
  }
@@ -475606,7 +475751,7 @@ async function apiKeyForVideoProvider(provider, projectDir) {
475606
475751
  return getApiKeyFromConfig(providerKey, { cwd: projectDir });
475607
475752
  }
475608
475753
  async function finalizeBuildResult(projectDir, startedAt, result) {
475609
- const reportPath = join31(projectDir, "build-report.json");
475754
+ const reportPath = join33(projectDir, "build-report.json");
475610
475755
  if (result.stageReports) {
475611
475756
  for (const report of Object.values(result.stageReports)) {
475612
475757
  if (report.status === "pending") report.status = "skipped";
@@ -475765,7 +475910,7 @@ function normalizeReportDuration(value) {
475765
475910
  }
475766
475911
  function buildReportComposition(projectDir, result, beatId) {
475767
475912
  const path14 = `compositions/scene-${beatId}.html`;
475768
- const exists = existsSync35(join31(projectDir, path14));
475913
+ const exists = existsSync36(join33(projectDir, path14));
475769
475914
  const written = composeWrittenEntry(result, beatId);
475770
475915
  if (written) {
475771
475916
  return {
@@ -475822,8 +475967,8 @@ function summarizeBuildBeats(projectDir, beats) {
475822
475967
  let compositionsReady = 0;
475823
475968
  for (const beat of beats) {
475824
475969
  if (beatAssetsReady(beat)) assetsReady += 1;
475825
- const compositionPath = join31(projectDir, "compositions", `scene-${beat.beatId}.html`);
475826
- if (existsSync35(compositionPath)) {
475970
+ const compositionPath = join33(projectDir, "compositions", `scene-${beat.beatId}.html`);
475971
+ if (existsSync36(compositionPath)) {
475827
475972
  compositionsReady += 1;
475828
475973
  } else {
475829
475974
  needsAuthor.push(beat.beatId);
@@ -475865,6 +476010,8 @@ var init_scene_build = __esm({
475865
476010
  init_compose_scenes_skills();
475866
476011
  init_compose_prompts();
475867
476012
  init_config();
476013
+ init_api_key();
476014
+ init_transcribe_narration();
475868
476015
  init_scene_render();
475869
476016
  init_storyboard_parse();
475870
476017
  init_scene_project();
@@ -475993,18 +476140,18 @@ __export(ai_audio_exports, {
475993
476140
  executeVoiceClone: () => executeVoiceClone
475994
476141
  });
475995
476142
  import { resolve as resolve35, dirname as dirname19, basename as basename8, extname as extname6 } from "node:path";
475996
- import { readFile as readFile19, writeFile as writeFile21 } from "node:fs/promises";
475997
- 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";
475998
476145
  async function executeTranscribe(options) {
475999
476146
  const { audioPath, language, output: output3, format: format4, apiKey } = options;
476000
476147
  try {
476001
476148
  const key2 = apiKey || process.env.OPENAI_API_KEY;
476002
476149
  if (!key2) return { success: false, error: "OPENAI_API_KEY required" };
476003
476150
  const absPath = resolve35(process.cwd(), audioPath);
476004
- if (!existsSync36(absPath)) return { success: false, error: `File not found: ${absPath}` };
476151
+ if (!existsSync37(absPath)) return { success: false, error: `File not found: ${absPath}` };
476005
476152
  const whisper = new WhisperProvider();
476006
476153
  await whisper.initialize({ apiKey: key2 });
476007
- const audioBuffer = await readFile19(absPath);
476154
+ const audioBuffer = await readFile20(absPath);
476008
476155
  const audioBlob = new Blob([audioBuffer]);
476009
476156
  const result = await whisper.transcribe(audioBlob, language);
476010
476157
  if (result.status === "failed") {
@@ -476034,8 +476181,8 @@ async function executeIsolate(options) {
476034
476181
  const key2 = apiKey || process.env.ELEVENLABS_API_KEY;
476035
476182
  if (!key2) return { success: false, error: "ELEVENLABS_API_KEY required" };
476036
476183
  const absPath = resolve35(process.cwd(), audioPath);
476037
- if (!existsSync36(absPath)) return { success: false, error: `File not found: ${absPath}` };
476038
- const audioBuffer = await readFile19(absPath);
476184
+ if (!existsSync37(absPath)) return { success: false, error: `File not found: ${absPath}` };
476185
+ const audioBuffer = await readFile20(absPath);
476039
476186
  const elevenlabs = new ElevenLabsProvider();
476040
476187
  await elevenlabs.initialize({ apiKey: key2 });
476041
476188
  const result = await elevenlabs.isolateVocals(audioBuffer);
@@ -476060,8 +476207,8 @@ async function executeVoiceClone(options) {
476060
476207
  const audioBuffers = [];
476061
476208
  for (const samplePath of samplePaths) {
476062
476209
  const absPath = resolve35(process.cwd(), samplePath);
476063
- if (!existsSync36(absPath)) return { success: false, error: `File not found: ${samplePath}` };
476064
- const buffer = await readFile19(absPath);
476210
+ if (!existsSync37(absPath)) return { success: false, error: `File not found: ${samplePath}` };
476211
+ const buffer = await readFile20(absPath);
476065
476212
  audioBuffers.push(buffer);
476066
476213
  }
476067
476214
  const elevenlabs = new ElevenLabsProvider();
@@ -476082,7 +476229,7 @@ async function executeDub(options) {
476082
476229
  const { mediaPath, language, source: source3, voice, analyzeOnly, output: output3 } = options;
476083
476230
  try {
476084
476231
  const absPath = resolve35(process.cwd(), mediaPath);
476085
- if (!existsSync36(absPath)) return { success: false, error: `File not found: ${absPath}` };
476232
+ if (!existsSync37(absPath)) return { success: false, error: `File not found: ${absPath}` };
476086
476233
  const openaiKey = process.env.OPENAI_API_KEY;
476087
476234
  const anthropicKey = process.env.ANTHROPIC_API_KEY;
476088
476235
  const elevenlabsKey = process.env.ELEVENLABS_API_KEY;
@@ -476099,7 +476246,7 @@ async function executeDub(options) {
476099
476246
  }
476100
476247
  const whisper = new WhisperProvider();
476101
476248
  await whisper.initialize({ apiKey: openaiKey });
476102
- const audioBuffer = await readFile19(audioPath);
476249
+ const audioBuffer = await readFile20(audioPath);
476103
476250
  const audioBlob = new Blob([audioBuffer]);
476104
476251
  const transcriptResult = await whisper.transcribe(audioBlob, source3);
476105
476252
  if (transcriptResult.status === "failed" || !transcriptResult.segments) {
@@ -476210,8 +476357,8 @@ async function executeDuck(options) {
476210
476357
  if (!commandExists("ffmpeg")) return { success: false, error: "FFmpeg not found" };
476211
476358
  const absMusicPath = resolve35(process.cwd(), musicPath);
476212
476359
  const absVoicePath = resolve35(process.cwd(), voicePath);
476213
- if (!existsSync36(absMusicPath)) return { success: false, error: `Music file not found: ${absMusicPath}` };
476214
- 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}` };
476215
476362
  const defaultOutput = resolve35(dirname19(absMusicPath), `${basename8(absMusicPath, extname6(absMusicPath))}-ducked${extname6(absMusicPath)}`);
476216
476363
  const outputPath = resolve35(process.cwd(), output3 || defaultOutput);
476217
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`;
@@ -476225,7 +476372,7 @@ async function executeDuck(options) {
476225
476372
  "-y",
476226
476373
  outputPath
476227
476374
  ], { timeout: 12e4, maxBuffer: 50 * 1024 * 1024 });
476228
- 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" };
476229
476376
  return { success: true, outputPath };
476230
476377
  } catch (error) {
476231
476378
  return { success: false, error: `Audio ducking failed: ${error instanceof Error ? error.message : String(error)}` };
@@ -476241,8 +476388,8 @@ var init_ai_audio = __esm({
476241
476388
  });
476242
476389
 
476243
476390
  // ../cli/src/commands/_shared/edit/silence-cut.ts
476244
- import { existsSync as existsSync37 } from "node:fs";
476245
- 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";
476246
476393
  async function detectSilencePeriods(videoPath, noiseThreshold, minDuration) {
476247
476394
  const totalDuration = await getVideoDuration(videoPath);
476248
476395
  const { stdout, stderr } = await execSafe(
@@ -476292,7 +476439,7 @@ async function detectSilencePeriodsWithGemini(videoPath, minDuration, options) {
476292
476439
  }
476293
476440
  const gemini = new GeminiProvider();
476294
476441
  await gemini.initialize({ apiKey: geminiApiKey });
476295
- const videoBuffer = await readFile20(videoPath);
476442
+ const videoBuffer = await readFile21(videoPath);
476296
476443
  const modelId = options.model ? resolveGeminiTextModel(options.model) : void 0;
476297
476444
  const prompt3 = `Analyze this video and identify all silent or dead segments where there is NO meaningful content.
476298
476445
 
@@ -476368,7 +476515,7 @@ async function executeSilenceCut(options) {
476368
476515
  analyzeOnly = false,
476369
476516
  useGemini = false
476370
476517
  } = options;
476371
- if (!existsSync37(videoPath)) {
476518
+ if (!existsSync38(videoPath)) {
476372
476519
  return { success: false, error: `Video not found: ${videoPath}` };
476373
476520
  }
476374
476521
  if (!commandExists("ffmpeg")) {
@@ -476476,11 +476623,11 @@ var init_silence_cut = __esm({
476476
476623
  });
476477
476624
 
476478
476625
  // ../cli/src/commands/_shared/edit/jump-cut.ts
476479
- import { existsSync as existsSync38 } from "node:fs";
476480
- import { readFile as readFile21, writeFile as writeFile22, mkdir as mkdir14 } from "node:fs/promises";
476481
- 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";
476482
476629
  async function transcribeWithWords(audioPath, apiKey, language) {
476483
- const audioBuffer = await readFile21(audioPath);
476630
+ const audioBuffer = await readFile22(audioPath);
476484
476631
  const audioBlob = new Blob([audioBuffer]);
476485
476632
  const formData = new FormData();
476486
476633
  formData.append("file", audioBlob, "audio.wav");
@@ -476539,7 +476686,7 @@ async function executeJumpCut(options) {
476539
476686
  analyzeOnly = false,
476540
476687
  apiKey
476541
476688
  } = options;
476542
- if (!existsSync38(videoPath)) {
476689
+ if (!existsSync39(videoPath)) {
476543
476690
  return { success: false, error: `Video not found: ${videoPath}` };
476544
476691
  }
476545
476692
  if (!commandExists("ffmpeg")) {
@@ -476558,7 +476705,7 @@ async function executeJumpCut(options) {
476558
476705
  try {
476559
476706
  const tmpDir = `/tmp/vibe_jumpcut_${Date.now()}`;
476560
476707
  await mkdir14(tmpDir, { recursive: true });
476561
- const audioPath = join33(tmpDir, "audio.wav");
476708
+ const audioPath = join34(tmpDir, "audio.wav");
476562
476709
  try {
476563
476710
  await execSafe(
476564
476711
  "ffmpeg",
@@ -476612,7 +476759,7 @@ async function executeJumpCut(options) {
476612
476759
  const segmentPaths = [];
476613
476760
  for (let i2 = 0; i2 < segments.length; i2++) {
476614
476761
  const seg = segments[i2];
476615
- const segPath = join33(tmpDir, `seg-${i2.toString().padStart(4, "0")}.ts`);
476762
+ const segPath = join34(tmpDir, `seg-${i2.toString().padStart(4, "0")}.ts`);
476616
476763
  const duration = seg.end - seg.start;
476617
476764
  await execSafe(
476618
476765
  "ffmpeg",
@@ -476635,7 +476782,7 @@ async function executeJumpCut(options) {
476635
476782
  segmentPaths.push(segPath);
476636
476783
  }
476637
476784
  const concatList = segmentPaths.map((p2) => `file '${p2}'`).join("\n");
476638
- const listPath = join33(tmpDir, "concat.txt");
476785
+ const listPath = join34(tmpDir, "concat.txt");
476639
476786
  await writeFile22(listPath, concatList);
476640
476787
  await execSafe(
476641
476788
  "ffmpeg",
@@ -476742,8 +476889,8 @@ __export(remotion_exports, {
476742
476889
  wrapComponentWithVideo: () => wrapComponentWithVideo
476743
476890
  });
476744
476891
  import { writeFile as writeFile23, mkdir as mkdir15, rm as rm4, copyFile as copyFile5 } from "node:fs/promises";
476745
- import { existsSync as existsSync39 } from "node:fs";
476746
- import { join as join34 } from "node:path";
476892
+ import { existsSync as existsSync40 } from "node:fs";
476893
+ import { join as join35 } from "node:path";
476747
476894
  import { tmpdir as tmpdir3 } from "node:os";
476748
476895
  import { createHash as createHash7 } from "node:crypto";
476749
476896
  async function ensureRemotionInstalled() {
@@ -476762,7 +476909,7 @@ async function ensureRemotionInstalled() {
476762
476909
  }
476763
476910
  }
476764
476911
  async function scaffoldRemotionProject(componentCode, componentName, opts) {
476765
- const dir = join34(tmpdir3(), `vibe_motion_${Date.now()}`);
476912
+ const dir = join35(tmpdir3(), `vibe_motion_${Date.now()}`);
476766
476913
  await mkdir15(dir, { recursive: true });
476767
476914
  const deps = {
476768
476915
  remotion: REMOTION_VERSION,
@@ -476781,7 +476928,7 @@ async function scaffoldRemotionProject(componentCode, componentName, opts) {
476781
476928
  dependencies: deps
476782
476929
  };
476783
476930
  const packageJsonStr = JSON.stringify(packageJson, null, 2);
476784
- await writeFile23(join34(dir, "package.json"), packageJsonStr);
476931
+ await writeFile23(join35(dir, "package.json"), packageJsonStr);
476785
476932
  const tsconfig = {
476786
476933
  compilerOptions: {
476787
476934
  target: "ES2020",
@@ -476793,8 +476940,8 @@ async function scaffoldRemotionProject(componentCode, componentName, opts) {
476793
476940
  skipLibCheck: true
476794
476941
  }
476795
476942
  };
476796
- await writeFile23(join34(dir, "tsconfig.json"), JSON.stringify(tsconfig, null, 2));
476797
- 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);
476798
476945
  const rootCode = `import { registerRoot, Composition } from "remotion";
476799
476946
  import { ${componentName} } from "./Component";
476800
476947
 
@@ -476813,14 +476960,14 @@ const Root = () => {
476813
476960
 
476814
476961
  registerRoot(Root);
476815
476962
  `;
476816
- await writeFile23(join34(dir, "Root.tsx"), rootCode);
476963
+ await writeFile23(join35(dir, "Root.tsx"), rootCode);
476817
476964
  const depsHash = createHash7("md5").update(packageJsonStr).digest("hex").slice(0, 12);
476818
- const cacheMarker = join34(REMOTION_CACHE_DIR, `.deps-${depsHash}`);
476819
- const cachedModules = join34(REMOTION_CACHE_DIR, "node_modules");
476820
- 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)) {
476821
476968
  const { symlink } = await import("node:fs/promises");
476822
476969
  try {
476823
- await symlink(cachedModules, join34(dir, "node_modules"), "dir");
476970
+ await symlink(cachedModules, join35(dir, "node_modules"), "dir");
476824
476971
  } catch {
476825
476972
  await this_npmInstall(dir);
476826
476973
  }
@@ -476828,12 +476975,12 @@ registerRoot(Root);
476828
476975
  await this_npmInstall(dir);
476829
476976
  try {
476830
476977
  await mkdir15(REMOTION_CACHE_DIR, { recursive: true });
476831
- await writeFile23(join34(REMOTION_CACHE_DIR, "package.json"), packageJsonStr);
476832
- if (existsSync39(join34(dir, "node_modules"))) {
476978
+ await writeFile23(join35(REMOTION_CACHE_DIR, "package.json"), packageJsonStr);
476979
+ if (existsSync40(join35(dir, "node_modules"))) {
476833
476980
  const { rename: rename7, symlink } = await import("node:fs/promises");
476834
- await rename7(join34(dir, "node_modules"), cachedModules).catch(() => {
476981
+ await rename7(join35(dir, "node_modules"), cachedModules).catch(() => {
476835
476982
  });
476836
- await symlink(cachedModules, join34(dir, "node_modules"), "dir").catch(() => {
476983
+ await symlink(cachedModules, join35(dir, "node_modules"), "dir").catch(() => {
476837
476984
  });
476838
476985
  await writeFile23(cacheMarker, depsHash);
476839
476986
  }
@@ -476870,7 +477017,7 @@ async function renderMotion(options) {
476870
477017
  }
476871
477018
  );
476872
477019
  try {
476873
- const entryPoint = join34(dir, "Root.tsx");
477020
+ const entryPoint = join35(dir, "Root.tsx");
476874
477021
  const { execFile: execFile3 } = await import("node:child_process");
476875
477022
  const { promisify: promisify3 } = await import("node:util");
476876
477023
  const execFileAsync3 = promisify3(execFile3);
@@ -477003,10 +477150,10 @@ async function renderWithEmbeddedImage(options) {
477003
477150
  }
477004
477151
  );
477005
477152
  try {
477006
- const publicDir = join34(dir, "public");
477153
+ const publicDir = join35(dir, "public");
477007
477154
  await mkdir15(publicDir, { recursive: true });
477008
- await copyFile5(options.imagePath, join34(publicDir, options.imageFileName));
477009
- const entryPoint = join34(dir, "Root.tsx");
477155
+ await copyFile5(options.imagePath, join35(publicDir, options.imageFileName));
477156
+ const entryPoint = join35(dir, "Root.tsx");
477010
477157
  const mp4Out = options.outputPath.replace(/\.\w+$/, ".mp4");
477011
477158
  const { execFile: execFileImg } = await import("node:child_process");
477012
477159
  const { promisify: promisifyImg } = await import("node:util");
@@ -477067,10 +477214,10 @@ async function renderWithEmbeddedVideo(options) {
477067
477214
  }
477068
477215
  );
477069
477216
  try {
477070
- const publicDir = join34(dir, "public");
477217
+ const publicDir = join35(dir, "public");
477071
477218
  await mkdir15(publicDir, { recursive: true });
477072
- await copyFile5(options.videoPath, join34(publicDir, options.videoFileName));
477073
- const entryPoint = join34(dir, "Root.tsx");
477219
+ await copyFile5(options.videoPath, join35(publicDir, options.videoFileName));
477220
+ const entryPoint = join35(dir, "Root.tsx");
477074
477221
  const mp4VideoOnly = options.outputPath.replace(/\.\w+$/, "_video_only.mp4");
477075
477222
  const { execFile: execFileVid } = await import("node:child_process");
477076
477223
  const { promisify: promisifyVid } = await import("node:util");
@@ -477486,14 +477633,14 @@ var init_remotion = __esm({
477486
477633
  "use strict";
477487
477634
  init_exec_safe();
477488
477635
  REMOTION_VERSION = "4.0.447";
477489
- REMOTION_CACHE_DIR = join34(tmpdir3(), "vibe_remotion_cache");
477636
+ REMOTION_CACHE_DIR = join35(tmpdir3(), "vibe_remotion_cache");
477490
477637
  }
477491
477638
  });
477492
477639
 
477493
477640
  // ../cli/src/commands/_shared/edit/caption.ts
477494
- import { existsSync as existsSync40 } from "node:fs";
477495
- import { readFile as readFile22, writeFile as writeFile24, mkdir as mkdir16 } from "node:fs/promises";
477496
- 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";
477497
477644
  function getCaptionForceStyle(style, fontSize, fontColor, position) {
477498
477645
  const alignment = position === "top" ? 8 : position === "center" ? 5 : 2;
477499
477646
  const marginV = position === "center" ? 0 : 30;
@@ -477521,7 +477668,7 @@ async function executeCaption(options) {
477521
477668
  position = "bottom",
477522
477669
  apiKey
477523
477670
  } = options;
477524
- if (!existsSync40(videoPath)) {
477671
+ if (!existsSync41(videoPath)) {
477525
477672
  return { success: false, error: `Video not found: ${videoPath}` };
477526
477673
  }
477527
477674
  if (!commandExists("ffmpeg")) {
@@ -477540,8 +477687,8 @@ async function executeCaption(options) {
477540
477687
  try {
477541
477688
  const tmpDir = `/tmp/vibe_caption_${Date.now()}`;
477542
477689
  await mkdir16(tmpDir, { recursive: true });
477543
- const audioPath = join35(tmpDir, "audio.wav");
477544
- const srtPath = join35(tmpDir, "captions.srt");
477690
+ const audioPath = join36(tmpDir, "audio.wav");
477691
+ const srtPath = join36(tmpDir, "captions.srt");
477545
477692
  try {
477546
477693
  await execSafe(
477547
477694
  "ffmpeg",
@@ -477562,7 +477709,7 @@ async function executeCaption(options) {
477562
477709
  );
477563
477710
  const whisper = new WhisperProvider();
477564
477711
  await whisper.initialize({ apiKey: openaiKey });
477565
- const audioBuffer = await readFile22(audioPath);
477712
+ const audioBuffer = await readFile23(audioPath);
477566
477713
  const audioBlob = new Blob([audioBuffer]);
477567
477714
  const transcriptResult = await whisper.transcribe(audioBlob, language);
477568
477715
  if (transcriptResult.status === "failed" || !transcriptResult.segments || transcriptResult.segments.length === 0) {
@@ -477610,7 +477757,7 @@ async function executeCaption(options) {
477610
477757
  const remotionErr = await ensureRemotionInstalled2();
477611
477758
  if (remotionErr) {
477612
477759
  const outputDir2 = dirname20(outputPath);
477613
- const outputSrtPath2 = join35(
477760
+ const outputSrtPath2 = join36(
477614
477761
  outputDir2,
477615
477762
  basename9(outputPath, extname7(outputPath)) + ".srt"
477616
477763
  );
@@ -477649,7 +477796,7 @@ SRT saved to: ${outputSrtPath2}` };
477649
477796
  });
477650
477797
  if (!renderResult.success) {
477651
477798
  const outputDir2 = dirname20(outputPath);
477652
- const outputSrtPath2 = join35(
477799
+ const outputSrtPath2 = join36(
477653
477800
  outputDir2,
477654
477801
  basename9(outputPath, extname7(outputPath)) + ".srt"
477655
477802
  );
@@ -477662,7 +477809,7 @@ SRT saved to: ${outputSrtPath2}`
477662
477809
  }
477663
477810
  }
477664
477811
  const outputDir = dirname20(outputPath);
477665
- const outputSrtPath = join35(
477812
+ const outputSrtPath = join36(
477666
477813
  outputDir,
477667
477814
  basename9(outputPath, extname7(outputPath)) + ".srt"
477668
477815
  );
@@ -477699,10 +477846,10 @@ var init_caption = __esm({
477699
477846
  });
477700
477847
 
477701
477848
  // ../cli/src/commands/_shared/edit/noise-reduce.ts
477702
- import { existsSync as existsSync41 } from "node:fs";
477849
+ import { existsSync as existsSync43 } from "node:fs";
477703
477850
  async function executeNoiseReduce(options) {
477704
477851
  const { inputPath, outputPath, strength = "medium", noiseFloor } = options;
477705
- if (!existsSync41(inputPath)) {
477852
+ if (!existsSync43(inputPath)) {
477706
477853
  return { success: false, error: `File not found: ${inputPath}` };
477707
477854
  }
477708
477855
  if (!commandExists("ffmpeg")) {
@@ -477759,7 +477906,7 @@ var init_noise_reduce = __esm({
477759
477906
  });
477760
477907
 
477761
477908
  // ../cli/src/commands/_shared/edit/fade.ts
477762
- import { existsSync as existsSync43 } from "node:fs";
477909
+ import { existsSync as existsSync44 } from "node:fs";
477763
477910
  async function executeFade(options) {
477764
477911
  const {
477765
477912
  videoPath,
@@ -477769,7 +477916,7 @@ async function executeFade(options) {
477769
477916
  audioOnly = false,
477770
477917
  videoOnly = false
477771
477918
  } = options;
477772
- if (!existsSync43(videoPath)) {
477919
+ if (!existsSync44(videoPath)) {
477773
477920
  return { success: false, error: `Video not found: ${videoPath}` };
477774
477921
  }
477775
477922
  if (!commandExists("ffmpeg")) {
@@ -477836,8 +477983,8 @@ var init_fade = __esm({
477836
477983
  });
477837
477984
 
477838
477985
  // ../cli/src/commands/_shared/edit/translate-srt.ts
477839
- import { existsSync as existsSync44 } from "node:fs";
477840
- 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";
477841
477988
  async function executeTranslateSrt(options) {
477842
477989
  const {
477843
477990
  srtPath,
@@ -477847,11 +477994,11 @@ async function executeTranslateSrt(options) {
477847
477994
  sourceLanguage,
477848
477995
  apiKey
477849
477996
  } = options;
477850
- if (!existsSync44(srtPath)) {
477997
+ if (!existsSync45(srtPath)) {
477851
477998
  return { success: false, error: `SRT file not found: ${srtPath}` };
477852
477999
  }
477853
478000
  try {
477854
- const srtContent = await readFile23(srtPath, "utf-8");
478001
+ const srtContent = await readFile24(srtPath, "utf-8");
477855
478002
  const segments = parseSRT(srtContent);
477856
478003
  if (segments.length === 0) {
477857
478004
  return { success: false, error: "No subtitle segments found in SRT file" };
@@ -477964,7 +478111,7 @@ var init_translate_srt = __esm({
477964
478111
  });
477965
478112
 
477966
478113
  // ../cli/src/commands/_shared/edit/text-overlay.ts
477967
- import { existsSync as existsSync45 } from "node:fs";
478114
+ import { existsSync as existsSync46 } from "node:fs";
477968
478115
  import { resolve as resolve36 } from "node:path";
477969
478116
  function detectSystemFont() {
477970
478117
  const platform = process.platform;
@@ -477975,7 +478122,7 @@ function detectSystemFont() {
477975
478122
  "/Library/Fonts/Arial.ttf"
477976
478123
  ];
477977
478124
  for (const f2 of candidates) {
477978
- if (existsSync45(f2)) return f2;
478125
+ if (existsSync46(f2)) return f2;
477979
478126
  }
477980
478127
  } else if (platform === "linux") {
477981
478128
  const candidates = [
@@ -477984,7 +478131,7 @@ function detectSystemFont() {
477984
478131
  "/usr/share/fonts/TTF/DejaVuSans-Bold.ttf"
477985
478132
  ];
477986
478133
  for (const f2 of candidates) {
477987
- if (existsSync45(f2)) return f2;
478134
+ if (existsSync46(f2)) return f2;
477988
478135
  }
477989
478136
  } else if (platform === "win32") {
477990
478137
  const candidates = [
@@ -477992,7 +478139,7 @@ function detectSystemFont() {
477992
478139
  "C:\\Windows\\Fonts\\segoeui.ttf"
477993
478140
  ];
477994
478141
  for (const f2 of candidates) {
477995
- if (existsSync45(f2)) return f2;
478142
+ if (existsSync46(f2)) return f2;
477996
478143
  }
477997
478144
  }
477998
478145
  return null;
@@ -478013,7 +478160,7 @@ async function applyTextOverlays(options) {
478013
478160
  }
478014
478161
  const absVideoPath = resolve36(process.cwd(), videoPath);
478015
478162
  const absOutputPath = resolve36(process.cwd(), outputPath);
478016
- if (!existsSync45(absVideoPath)) {
478163
+ if (!existsSync46(absVideoPath)) {
478017
478164
  return { success: false, error: `Video not found: ${absVideoPath}` };
478018
478165
  }
478019
478166
  if (!commandExists("ffmpeg")) {
@@ -478194,7 +478341,7 @@ var init_ai_edit = __esm({
478194
478341
 
478195
478342
  // ../cli/src/commands/ai-edit-cli.ts
478196
478343
  import { resolve as resolve37, extname as extname8, basename as basename10 } from "node:path";
478197
- import { existsSync as existsSync46 } from "node:fs";
478344
+ import { existsSync as existsSync47 } from "node:fs";
478198
478345
  function registerEditCommands(aiCommand) {
478199
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", `
478200
478347
  Examples:
@@ -478211,7 +478358,7 @@ No API key needed (FFmpeg only). Use --use-gemini for smart detection (requires
478211
478358
  validateOutputPath(options.output);
478212
478359
  }
478213
478360
  const absVideoPath = resolve37(process.cwd(), videoPath);
478214
- if (!existsSync46(absVideoPath)) {
478361
+ if (!existsSync47(absVideoPath)) {
478215
478362
  exitWithError(notFoundError(absVideoPath));
478216
478363
  }
478217
478364
  if (!commandExists("ffmpeg")) {
@@ -478319,7 +478466,7 @@ Requires: OPENAI_API_KEY (Whisper transcription) + FFmpeg`).action(async (videoP
478319
478466
  validateOutputPath(options.output);
478320
478467
  }
478321
478468
  const absVideoPath = resolve37(process.cwd(), videoPath);
478322
- if (!existsSync46(absVideoPath)) {
478469
+ if (!existsSync47(absVideoPath)) {
478323
478470
  exitWithError(notFoundError(absVideoPath));
478324
478471
  }
478325
478472
  if (!commandExists("ffmpeg")) {
@@ -478400,7 +478547,7 @@ Requires: OPENAI_API_KEY (Whisper transcription) + FFmpeg`).action(async (videoP
478400
478547
  validateOutputPath(options.output);
478401
478548
  }
478402
478549
  const absInputPath = resolve37(process.cwd(), inputPath);
478403
- if (!existsSync46(absInputPath)) {
478550
+ if (!existsSync47(absInputPath)) {
478404
478551
  exitWithError(notFoundError(absInputPath));
478405
478552
  }
478406
478553
  if (!commandExists("ffmpeg")) {
@@ -478466,7 +478613,7 @@ Requires: OPENAI_API_KEY (Whisper transcription) + FFmpeg`).action(async (videoP
478466
478613
  validateOutputPath(options.output);
478467
478614
  }
478468
478615
  const absVideoPath = resolve37(process.cwd(), videoPath);
478469
- if (!existsSync46(absVideoPath)) {
478616
+ if (!existsSync47(absVideoPath)) {
478470
478617
  exitWithError(notFoundError(absVideoPath));
478471
478618
  }
478472
478619
  if (!commandExists("ffmpeg")) {
@@ -478541,7 +478688,7 @@ Requires: OPENAI_API_KEY (Whisper transcription) + FFmpeg`).action(async (videoP
478541
478688
  exitWithError(usageError("Target language required. Use -t or --target"));
478542
478689
  }
478543
478690
  const absSrtPath = resolve37(process.cwd(), srtPath);
478544
- if (!existsSync46(absSrtPath)) {
478691
+ if (!existsSync47(absSrtPath)) {
478545
478692
  exitWithError(notFoundError(absSrtPath));
478546
478693
  }
478547
478694
  if (options.dryRun) {
@@ -478617,7 +478764,7 @@ Requires: OPENAI_API_KEY (Whisper transcription) + FFmpeg`).action(async (videoP
478617
478764
  }
478618
478765
  if (options.fillers) rejectControlChars(options.fillers);
478619
478766
  const absVideoPath = resolve37(process.cwd(), videoPath);
478620
- if (!existsSync46(absVideoPath)) {
478767
+ if (!existsSync47(absVideoPath)) {
478621
478768
  exitWithError(notFoundError(absVideoPath));
478622
478769
  }
478623
478770
  if (!commandExists("ffmpeg")) {
@@ -479109,8 +479256,8 @@ var init_project_resolver = __esm({
479109
479256
  });
479110
479257
 
479111
479258
  // ../cli/src/commands/_shared/execute-fill-gaps.ts
479112
- import { existsSync as existsSync47 } from "node:fs";
479113
- 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";
479114
479261
  import { resolve as resolve39, dirname as dirname21 } from "node:path";
479115
479262
  function detectVideoGaps(videoClips, totalDuration) {
479116
479263
  const gaps = [];
@@ -479167,7 +479314,7 @@ function analyzeGapFillability(gaps, videoClips, sources) {
479167
479314
  }
479168
479315
  async function uploadFrameToImgbb(framePath, imgbbApiKey) {
479169
479316
  try {
479170
- const frameBuffer = await readFile24(framePath);
479317
+ const frameBuffer = await readFile25(framePath);
479171
479318
  const frameBase64 = frameBuffer.toString("base64");
479172
479319
  const formData = new FormData();
479173
479320
  formData.append("key", imgbbApiKey);
@@ -479192,14 +479339,14 @@ async function executeFillGaps(options) {
479192
479339
  try {
479193
479340
  onProgress("Loading timeline...");
479194
479341
  const filePath = await resolveTimelineFile(options.projectPath);
479195
- if (!existsSync47(filePath)) {
479342
+ if (!existsSync48(filePath)) {
479196
479343
  return {
479197
479344
  success: false,
479198
479345
  error: `Timeline file not found: ${filePath}`,
479199
479346
  humanLines
479200
479347
  };
479201
479348
  }
479202
- const content = await readFile24(filePath, "utf-8");
479349
+ const content = await readFile25(filePath, "utf-8");
479203
479350
  const data = JSON.parse(content);
479204
479351
  const project = Project.fromJSON(data);
479205
479352
  const clips = project.getClips().sort((a2, b2) => a2.startTime - b2.startTime);
@@ -479327,7 +479474,7 @@ async function executeFillGaps(options) {
479327
479474
  }
479328
479475
  const projectDir = dirname21(filePath);
479329
479476
  const footageDir = options.dir ? resolve39(process.cwd(), options.dir) : resolve39(projectDir, "footage");
479330
- if (!existsSync47(footageDir)) {
479477
+ if (!existsSync48(footageDir)) {
479331
479478
  await mkdir17(footageDir, { recursive: true });
479332
479479
  }
479333
479480
  humanLines.push("Generating AI Videos");
@@ -479647,8 +479794,8 @@ __export(ai_motion_exports, {
479647
479794
  registerMotionCommand: () => registerMotionCommand
479648
479795
  });
479649
479796
  import { resolve as resolve40 } from "node:path";
479650
- import { existsSync as existsSync48 } from "node:fs";
479651
- 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";
479652
479799
  async function getOptionalGoogleApiKey() {
479653
479800
  const configKey = await getApiKeyFromConfig("google");
479654
479801
  if (configKey) return configKey;
@@ -479695,7 +479842,7 @@ async function executeMotion(options) {
479695
479842
  };
479696
479843
  }
479697
479844
  const imagePath = resolve40(process.cwd(), options.image);
479698
- const imageBuffer = await readFile25(imagePath);
479845
+ const imageBuffer = await readFile26(imagePath);
479699
479846
  const gemini = new GeminiProvider();
479700
479847
  await gemini.initialize({ apiKey: geminiApiKey });
479701
479848
  const analysisResult = await gemini.analyzeImage(
@@ -479732,7 +479879,7 @@ Use this image analysis to inform the color palette, typography placement, and o
479732
479879
  }
479733
479880
  if (geminiApiKey) {
479734
479881
  const videoPath = resolve40(process.cwd(), options.video);
479735
- const videoBuffer = await readFile25(videoPath);
479882
+ const videoBuffer = await readFile26(videoPath);
479736
479883
  const gemini = new GeminiProvider();
479737
479884
  await gemini.initialize({ apiKey: geminiApiKey });
479738
479885
  const analysisPrompt = options.understandingPrompt || `Analyze this video for motion graphics composition. Return concise production guidance:
@@ -479763,10 +479910,10 @@ Use this video understanding to place motion graphics in safe zones, match the c
479763
479910
  let result;
479764
479911
  if (options.fromTsx) {
479765
479912
  const tsxPath = resolve40(process.cwd(), options.fromTsx);
479766
- if (!existsSync48(tsxPath)) {
479913
+ if (!existsSync49(tsxPath)) {
479767
479914
  return { success: false, error: `TSX file not found: ${tsxPath}` };
479768
479915
  }
479769
- const existingCode = await readFile25(tsxPath, "utf-8");
479916
+ const existingCode = await readFile26(tsxPath, "utf-8");
479770
479917
  if (useGemini) {
479771
479918
  const gemini = new GeminiProvider();
479772
479919
  await gemini.initialize({ apiKey });
@@ -480295,7 +480442,7 @@ __export(project_builder_exports, {
480295
480442
  resolveSourceUrl: () => resolveSourceUrl
480296
480443
  });
480297
480444
  import { mkdtemp as mkdtemp4, mkdir as mkdir18, copyFile as copyFile6, writeFile as writeFile28, rm as rm5, readdir as readdir5 } from "node:fs/promises";
480298
- import { existsSync as existsSync49 } from "node:fs";
480445
+ import { existsSync as existsSync50 } from "node:fs";
480299
480446
  import { tmpdir as tmpdir4 } from "node:os";
480300
480447
  import { createRequire } from "node:module";
480301
480448
  import * as path13 from "node:path";
@@ -480307,7 +480454,7 @@ async function buildTempProject(state, projectFileDir) {
480307
480454
  for (const source3 of state.sources) {
480308
480455
  if (copied.has(source3.id)) continue;
480309
480456
  const resolved = resolveSourceUrl(source3.url, projectFileDir);
480310
- if (!existsSync49(resolved)) {
480457
+ if (!existsSync50(resolved)) {
480311
480458
  throw new Error(`Source file not found: ${resolved} (from source id=${source3.id})`);
480312
480459
  }
480313
480460
  const dest = path13.join(assetsDir, path13.basename(resolved));
@@ -480444,7 +480591,7 @@ __export(motion_overlay_exports, {
480444
480591
  registerMotionOverlayCommand: () => registerMotionOverlayCommand
480445
480592
  });
480446
480593
  import { mkdir as mkdir19 } from "node:fs/promises";
480447
- import { existsSync as existsSync50 } from "node:fs";
480594
+ import { existsSync as existsSync51 } from "node:fs";
480448
480595
  import { basename as basename12, dirname as dirname24, extname as extname9, resolve as resolve43 } from "node:path";
480449
480596
  function normalizeUnderstand2(value) {
480450
480597
  return value === "off" || value === "required" || value === "auto" ? value : "auto";
@@ -480575,11 +480722,11 @@ async function executeMotionOverlay(options) {
480575
480722
  const validationError = assertValidRequest(options);
480576
480723
  if (validationError) return { success: false, error: validationError };
480577
480724
  const absVideo = resolve43(process.cwd(), options.videoPath);
480578
- 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}` };
480579
480726
  const outputPath = options.output ? resolve43(process.cwd(), options.output) : defaultOverlayOutput(options.videoPath);
480580
480727
  if (options.asset) {
480581
480728
  const absAsset = resolve43(process.cwd(), options.asset);
480582
- 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}` };
480583
480730
  const [videoDuration, size] = await Promise.all([
480584
480731
  ffprobeDuration(absVideo),
480585
480732
  ffprobeVideoSize(absVideo)
@@ -480746,7 +480893,7 @@ __export(edit_cmd_exports, {
480746
480893
  executeUpscale: () => executeUpscale
480747
480894
  });
480748
480895
  import { resolve as resolve44, dirname as dirname25 } from "node:path";
480749
- 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";
480750
480897
  async function executeGrade(options) {
480751
480898
  const { videoPath, style, preset, output: output3, analyzeOnly, apiKey } = options;
480752
480899
  try {
@@ -480787,7 +480934,7 @@ async function executeSpeedRamp(options) {
480787
480934
  await execSafe("ffmpeg", ["-i", absPath, "-vn", "-acodec", "libmp3lame", "-q:a", "2", tempAudio, "-y"]);
480788
480935
  const whisper = new WhisperProvider();
480789
480936
  await whisper.initialize({ apiKey: openaiKey });
480790
- const audioBuffer = await readFile26(tempAudio);
480937
+ const audioBuffer = await readFile27(tempAudio);
480791
480938
  const transcript = await whisper.transcribe(new Blob([audioBuffer]), language);
480792
480939
  try {
480793
480940
  const { unlink: unlink8 } = await import("node:fs/promises");
@@ -481181,7 +481328,7 @@ Run 'vibe schema edit.<command>' for structured parameter info.
481181
481328
  spinner2.text = "Transcribing audio...";
481182
481329
  const whisper = new WhisperProvider();
481183
481330
  await whisper.initialize({ apiKey: openaiApiKey });
481184
- const audioBuffer = await readFile26(tempAudio);
481331
+ const audioBuffer = await readFile27(tempAudio);
481185
481332
  const audioBlob = new Blob([audioBuffer]);
481186
481333
  const transcript = await whisper.transcribe(audioBlob, options.language);
481187
481334
  if (!transcript.segments || transcript.segments.length === 0) {
@@ -481314,7 +481461,7 @@ Run 'vibe schema edit.<command>' for structured parameter info.
481314
481461
  for (let i2 = 1; i2 <= numKeyframes && i2 <= 30; i2++) {
481315
481462
  const framePath = `${tempDir}/frame-${i2.toString().padStart(4, "0")}.jpg`;
481316
481463
  try {
481317
- const frameBuffer = await readFile26(framePath);
481464
+ const frameBuffer = await readFile27(framePath);
481318
481465
  const frameBase64 = frameBuffer.toString("base64");
481319
481466
  const result = await claude.analyzeFrameForReframe(frameBase64, options.aspect, {
481320
481467
  focusMode: options.focus,
@@ -481443,7 +481590,7 @@ Run 'vibe schema edit.<command>' for structured parameter info.
481443
481590
  const imageBuffers = [];
481444
481591
  for (const imagePath of imagePaths) {
481445
481592
  const absPath = resolve44(process.cwd(), imagePath);
481446
- const buffer = await readFile26(absPath);
481593
+ const buffer = await readFile27(absPath);
481447
481594
  imageBuffers.push(buffer);
481448
481595
  }
481449
481596
  let result;
@@ -481720,8 +481867,8 @@ __export(ai_image_exports, {
481720
481867
  executeThumbnailBestFrame: () => executeThumbnailBestFrame
481721
481868
  });
481722
481869
  import { resolve as resolve46, dirname as dirname27 } from "node:path";
481723
- import { readFile as readFile27, writeFile as writeFile31, mkdir as mkdir23 } from "node:fs/promises";
481724
- 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";
481725
481872
  async function executeImageGenerate(options) {
481726
481873
  const {
481727
481874
  prompt: prompt3,
@@ -481865,10 +482012,10 @@ async function executeGeminiEdit(options) {
481865
482012
  const imageBuffers = [];
481866
482013
  for (const imagePath of imagePaths) {
481867
482014
  const absPath = resolve46(process.cwd(), imagePath);
481868
- if (!existsSync53(absPath)) {
482015
+ if (!existsSync54(absPath)) {
481869
482016
  return { success: false, error: `Image not found: ${absPath}` };
481870
482017
  }
481871
- const buffer = await readFile27(absPath);
482018
+ const buffer = await readFile28(absPath);
481872
482019
  imageBuffers.push(buffer);
481873
482020
  }
481874
482021
  const gemini = new GeminiProvider();
@@ -481913,7 +482060,7 @@ async function executeThumbnailBestFrame(options) {
481913
482060
  model = "flash",
481914
482061
  apiKey
481915
482062
  } = options;
481916
- if (!existsSync53(videoPath)) {
482063
+ if (!existsSync54(videoPath)) {
481917
482064
  return { success: false, error: `Video not found: ${videoPath}` };
481918
482065
  }
481919
482066
  if (!commandExists("ffmpeg")) {
@@ -481926,7 +482073,7 @@ async function executeThumbnailBestFrame(options) {
481926
482073
  try {
481927
482074
  const gemini = new GeminiProvider();
481928
482075
  await gemini.initialize({ apiKey: googleKey });
481929
- const videoData = await readFile27(videoPath);
482076
+ const videoData = await readFile28(videoPath);
481930
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>"}';
481931
482078
  const modelId = resolveGeminiTextModel(model);
481932
482079
  const result = await gemini.analyzeVideo(videoData, analysisPrompt, {
@@ -481947,7 +482094,7 @@ async function executeThumbnailBestFrame(options) {
481947
482094
  reason = reasonMatch[1];
481948
482095
  }
481949
482096
  await execSafe("ffmpeg", ["-ss", String(timestamp), "-i", videoPath, "-frames:v", "1", "-q:v", "2", outputPath, "-y"], { timeout: 6e4, maxBuffer: 50 * 1024 * 1024 });
481950
- if (!existsSync53(outputPath)) {
482097
+ if (!existsSync54(outputPath)) {
481951
482098
  return { success: false, error: "FFmpeg failed to extract frame" };
481952
482099
  }
481953
482100
  return {
@@ -481978,9 +482125,9 @@ __export(ai_analyze_exports, {
481978
482125
  executeGeminiVideo: () => executeGeminiVideo,
481979
482126
  registerAnalyzeCommands: () => registerAnalyzeCommands
481980
482127
  });
481981
- import { readFile as readFile28 } from "node:fs/promises";
482128
+ import { readFile as readFile29 } from "node:fs/promises";
481982
482129
  import { extname as extname10, resolve as resolve47 } from "node:path";
481983
- import { existsSync as existsSync54 } from "node:fs";
482130
+ import { existsSync as existsSync55 } from "node:fs";
481984
482131
  async function executeGeminiVideo(options) {
481985
482132
  try {
481986
482133
  const apiKey = await getApiKey("GOOGLE_API_KEY", "Google");
@@ -481994,10 +482141,10 @@ async function executeGeminiVideo(options) {
481994
482141
  videoData = options.source;
481995
482142
  } else {
481996
482143
  const absPath = resolve47(process.cwd(), options.source);
481997
- if (!existsSync54(absPath)) {
482144
+ if (!existsSync55(absPath)) {
481998
482145
  return { success: false, error: `File not found: ${absPath}` };
481999
482146
  }
482000
- videoData = await readFile28(absPath);
482147
+ videoData = await readFile29(absPath);
482001
482148
  }
482002
482149
  const gemini = new GeminiProvider();
482003
482150
  await gemini.initialize({ apiKey });
@@ -482062,10 +482209,10 @@ async function executeAnalyze(options) {
482062
482209
  imageBuffer = Buffer.from(await response.arrayBuffer());
482063
482210
  } else {
482064
482211
  const absPath = resolve47(process.cwd(), source3);
482065
- if (!existsSync54(absPath)) {
482212
+ if (!existsSync55(absPath)) {
482066
482213
  return { success: false, error: `File not found: ${absPath}` };
482067
482214
  }
482068
- imageBuffer = await readFile28(absPath);
482215
+ imageBuffer = await readFile29(absPath);
482069
482216
  }
482070
482217
  const result2 = await gemini.analyzeImage(imageBuffer, options.prompt, {
482071
482218
  model: modelId,
@@ -482097,10 +482244,10 @@ async function executeAnalyze(options) {
482097
482244
  videoData = Buffer.from(await response.arrayBuffer());
482098
482245
  } else {
482099
482246
  const absPath = resolve47(process.cwd(), source3);
482100
- if (!existsSync54(absPath)) {
482247
+ if (!existsSync55(absPath)) {
482101
482248
  return { success: false, error: `File not found: ${absPath}` };
482102
482249
  }
482103
- videoData = await readFile28(absPath);
482250
+ videoData = await readFile29(absPath);
482104
482251
  }
482105
482252
  const result = await gemini.analyzeVideo(videoData, options.prompt, {
482106
482253
  model: modelId,
@@ -482234,9 +482381,9 @@ __export(ai_review_exports, {
482234
482381
  executeReview: () => executeReview,
482235
482382
  registerReviewCommand: () => registerReviewCommand
482236
482383
  });
482237
- import { readFile as readFile29, rename as rename5 } from "node:fs/promises";
482384
+ import { readFile as readFile30, rename as rename5 } from "node:fs/promises";
482238
482385
  import { resolve as resolve48 } from "node:path";
482239
- import { existsSync as existsSync55 } from "node:fs";
482386
+ import { existsSync as existsSync56 } from "node:fs";
482240
482387
  function parseReviewFeedback(response) {
482241
482388
  let cleaned = response.trim();
482242
482389
  if (cleaned.startsWith("```json")) {
@@ -482268,7 +482415,7 @@ async function executeReview(options) {
482268
482415
  model = "flash"
482269
482416
  } = options;
482270
482417
  const absVideoPath = resolve48(process.cwd(), videoPath);
482271
- if (!existsSync55(absVideoPath)) {
482418
+ if (!existsSync56(absVideoPath)) {
482272
482419
  return { success: false, error: `Video not found: ${absVideoPath}` };
482273
482420
  }
482274
482421
  const apiKey = process.env.GOOGLE_API_KEY || await getApiKey("GOOGLE_API_KEY", "Google");
@@ -482281,8 +482428,8 @@ async function executeReview(options) {
482281
482428
  let storyboardContext = "";
482282
482429
  if (storyboardPath) {
482283
482430
  const absStoryboardPath = resolve48(process.cwd(), storyboardPath);
482284
- if (existsSync55(absStoryboardPath)) {
482285
- const content = await readFile29(absStoryboardPath, "utf-8");
482431
+ if (existsSync56(absStoryboardPath)) {
482432
+ const content = await readFile30(absStoryboardPath, "utf-8");
482286
482433
  storyboardContext = `
482287
482434
 
482288
482435
  Original storyboard for reference:
@@ -482324,7 +482471,7 @@ ${projectContext}` : "";
482324
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}`;
482325
482472
  const gemini = new GeminiProvider();
482326
482473
  await gemini.initialize({ apiKey });
482327
- const videoData = await readFile29(absVideoPath);
482474
+ const videoData = await readFile30(absVideoPath);
482328
482475
  const analysisResult = await gemini.analyzeVideo(videoData, reviewPrompt, {
482329
482476
  model: modelId
482330
482477
  });
@@ -482379,7 +482526,7 @@ Score each category 1-10. Prefer beatIssues when you can map a problem to a stor
482379
482526
  }
482380
482527
  }
482381
482528
  if (verify && result.outputPath) {
482382
- const verifyVideoData = await readFile29(result.outputPath);
482529
+ const verifyVideoData = await readFile30(result.outputPath);
482383
482530
  const verifyResult = await gemini.analyzeVideo(
482384
482531
  verifyVideoData,
482385
482532
  'Rate this video overall quality on a scale of 1-10. Return ONLY a JSON object: {"score": <number>}',
@@ -482843,7 +482990,7 @@ var init_sanitize = __esm({
482843
482990
 
482844
482991
  // ../cli/src/commands/generate/storyboard.ts
482845
482992
  import { resolve as resolve56 } from "node:path";
482846
- import { readFile as readFile33, writeFile as writeFile35 } from "node:fs/promises";
482993
+ import { readFile as readFile34, writeFile as writeFile35 } from "node:fs/promises";
482847
482994
  async function executeStoryboard(options) {
482848
482995
  const { content, duration, creativity = "low", output: output3, apiKey } = options;
482849
482996
  try {
@@ -482891,7 +483038,7 @@ function registerStoryboardCommand(parent) {
482891
483038
  let textContent2 = content;
482892
483039
  if (options.file) {
482893
483040
  const filePath = resolve56(process.cwd(), content);
482894
- textContent2 = await readFile33(filePath, "utf-8");
483041
+ textContent2 = await readFile34(filePath, "utf-8");
482895
483042
  }
482896
483043
  if (options.dryRun) {
482897
483044
  outputSuccess({
@@ -483284,7 +483431,7 @@ var init_speech2 = __esm({
483284
483431
 
483285
483432
  // ../cli/src/commands/generate/thumbnail.ts
483286
483433
  import { resolve as resolve58, dirname as dirname29, basename as basename16, extname as extname11 } from "node:path";
483287
- import { existsSync as existsSync58 } from "node:fs";
483434
+ import { existsSync as existsSync59 } from "node:fs";
483288
483435
  import { writeFile as writeFile37, mkdir as mkdir25 } from "node:fs/promises";
483289
483436
  function registerThumbnailCommand(parent) {
483290
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) => {
@@ -483296,7 +483443,7 @@ function registerThumbnailCommand(parent) {
483296
483443
  }
483297
483444
  if (options.bestFrame) {
483298
483445
  const absVideoPath = resolve58(process.cwd(), options.bestFrame);
483299
- if (!existsSync58(absVideoPath)) {
483446
+ if (!existsSync59(absVideoPath)) {
483300
483447
  exitWithError(notFoundError(absVideoPath));
483301
483448
  }
483302
483449
  if (!commandExists("ffmpeg")) {
@@ -485480,7 +485627,7 @@ var init_dist4 = __esm({
485480
485627
 
485481
485628
  // ../cli/src/commands/generate/video.ts
485482
485629
  import { resolve as resolve63 } from "node:path";
485483
- import { readFile as readFile34, writeFile as writeFile41 } from "node:fs/promises";
485630
+ import { readFile as readFile35, writeFile as writeFile41 } from "node:fs/promises";
485484
485631
  function registerVideoCommand(parent) {
485485
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(
485486
485633
  "-p, --provider <provider>",
@@ -485591,7 +485738,7 @@ Examples:
485591
485738
  let isImageToVideo = false;
485592
485739
  if (options.image) {
485593
485740
  const imagePath = resolve63(process.cwd(), options.image);
485594
- const imageBuffer = await readFile34(imagePath);
485741
+ const imageBuffer = await readFile35(imagePath);
485595
485742
  const ext = options.image.toLowerCase().split(".").pop();
485596
485743
  const mimeTypes = {
485597
485744
  jpg: "image/jpeg",
@@ -485831,7 +485978,7 @@ Examples:
485831
485978
  let lastFrame;
485832
485979
  if (options.lastFrame) {
485833
485980
  const lastFramePath = resolve63(process.cwd(), options.lastFrame);
485834
- const lastFrameBuffer = await readFile34(lastFramePath);
485981
+ const lastFrameBuffer = await readFile35(lastFramePath);
485835
485982
  const ext = options.lastFrame.toLowerCase().split(".").pop();
485836
485983
  const mimeType = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : `image/${ext || "png"}`;
485837
485984
  lastFrame = `data:${mimeType};base64,${lastFrameBuffer.toString("base64")}`;
@@ -485841,7 +485988,7 @@ Examples:
485841
485988
  refImages = [];
485842
485989
  for (const refPath of options.refImages.slice(0, 3)) {
485843
485990
  const absRefPath = resolve63(process.cwd(), refPath);
485844
- const refBuffer = await readFile34(absRefPath);
485991
+ const refBuffer = await readFile35(absRefPath);
485845
485992
  const ext = refPath.toLowerCase().split(".").pop();
485846
485993
  const mimeType = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : `image/${ext || "png"}`;
485847
485994
  refImages.push({ base64: refBuffer.toString("base64"), mimeType });
@@ -485973,7 +486120,7 @@ Examples:
485973
486120
  if (seedanceEndImagePath && seedanceReferences.length === 0) {
485974
486121
  try {
485975
486122
  const absEndImagePath = resolve63(process.cwd(), seedanceEndImagePath);
485976
- const endImageBuffer = await readFile34(absEndImagePath);
486123
+ const endImageBuffer = await readFile35(absEndImagePath);
485977
486124
  const ext = seedanceEndImagePath.toLowerCase().split(".").pop();
485978
486125
  const mimeType = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : `image/${ext || "png"}`;
485979
486126
  const uploadHost = await resolveUploadHost();
@@ -486090,7 +486237,7 @@ async function fileInputToUrlOrDataUri2(input3, fallbackMimeType) {
486090
486237
  return input3;
486091
486238
  }
486092
486239
  const absPath = resolve63(process.cwd(), input3);
486093
- const buffer = await readFile34(absPath);
486240
+ const buffer = await readFile35(absPath);
486094
486241
  return `data:${mimeTypeForPath2(input3, fallbackMimeType)};base64,${buffer.toString("base64")}`;
486095
486242
  }
486096
486243
  function mimeTypeForPath2(path14, fallback2) {
@@ -487098,7 +487245,7 @@ __export(detect_exports, {
487098
487245
  executeDetectScenes: () => executeDetectScenes,
487099
487246
  executeDetectSilence: () => executeDetectSilence
487100
487247
  });
487101
- import { readFile as readFile39, writeFile as writeFile46 } from "node:fs/promises";
487248
+ import { readFile as readFile40, writeFile as writeFile46 } from "node:fs/promises";
487102
487249
  import { resolve as resolve68, basename as basename18 } from "node:path";
487103
487250
  async function executeDetectScenes(options) {
487104
487251
  try {
@@ -487342,7 +487489,7 @@ var init_detect = __esm({
487342
487489
  }
487343
487490
  if (options.project) {
487344
487491
  const projectPath = resolve68(process.cwd(), options.project);
487345
- const content = await readFile39(projectPath, "utf-8");
487492
+ const content = await readFile40(projectPath, "utf-8");
487346
487493
  const data = JSON.parse(content);
487347
487494
  const project = Project.fromJSON(data);
487348
487495
  let source3 = project.getSources().find((s2) => s2.url === absPath);
@@ -488165,8 +488312,8 @@ init_scene_project();
488165
488312
  init_project_config();
488166
488313
  init_cost_tier();
488167
488314
  import { resolve as resolve24, relative as relative8, dirname as dirname14 } from "node:path";
488168
- import { mkdir as mkdir11, readFile as readFile14, writeFile as writeFile17, access as access4, copyFile as copyFile3 } from "node:fs/promises";
488169
- 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";
488170
488317
 
488171
488318
  // ../cli/src/commands/_shared/scene-html-emit.ts
488172
488319
  var SCENE_PRESETS = [
@@ -488735,15 +488882,16 @@ function deriveInstallHosts(detected) {
488735
488882
 
488736
488883
  // ../cli/src/commands/scene.ts
488737
488884
  init_compose_prompts();
488885
+ init_transcribe_narration();
488738
488886
 
488739
488887
  // ../cli/src/commands/_shared/scene-submit.ts
488740
488888
  init_compose_scenes_skills();
488741
488889
  init_scene_lint();
488742
488890
  init_storyboard_parse();
488743
488891
  init_root_sync();
488744
- import { existsSync as existsSync26 } from "node:fs";
488745
- import { mkdir as mkdir10, readFile as readFile11, writeFile as writeFile15 } from "node:fs/promises";
488746
- 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";
488747
488895
  async function executeSceneSubmit(opts) {
488748
488896
  const projectDir = resolve20(opts.projectDir);
488749
488897
  const beatId = opts.beatId.trim();
@@ -488757,15 +488905,15 @@ async function executeSceneSubmit(opts) {
488757
488905
  warnings: [],
488758
488906
  retryWith: []
488759
488907
  };
488760
- const storyboardPath = join26(projectDir, "STORYBOARD.md");
488761
- if (!existsSync26(storyboardPath)) {
488908
+ const storyboardPath = join27(projectDir, "STORYBOARD.md");
488909
+ if (!existsSync27(storyboardPath)) {
488762
488910
  return {
488763
488911
  ...base,
488764
488912
  success: false,
488765
488913
  error: `STORYBOARD.md not found at ${storyboardPath}. Run \`vibe init <dir>\` first.`
488766
488914
  };
488767
488915
  }
488768
- const parsed = parseStoryboard(await readFile11(storyboardPath, "utf-8"));
488916
+ const parsed = parseStoryboard(await readFile12(storyboardPath, "utf-8"));
488769
488917
  const beat = parsed.beats.find((b2) => b2.id === beatId);
488770
488918
  if (!beat) {
488771
488919
  const available = parsed.beats.map((b2) => b2.id).join(", ") || "(none)";
@@ -488835,8 +488983,8 @@ async function executeSceneSubmit(opts) {
488835
488983
  if (opts.validateOnly) {
488836
488984
  return { ...base, success: true };
488837
488985
  }
488838
- const absPath = join26(projectDir, scenePath);
488839
- await mkdir10(join26(projectDir, "compositions"), { recursive: true });
488986
+ const absPath = join27(projectDir, scenePath);
488987
+ await mkdir10(join27(projectDir, "compositions"), { recursive: true });
488840
488988
  await writeFile15(absPath, html.endsWith("\n") ? html : `${html}
488841
488989
  `, "utf-8");
488842
488990
  return {
@@ -489037,7 +489185,7 @@ sceneCommand.command("submit").description(
489037
489185
  }
489038
489186
  html = Buffer.concat(chunks).toString("utf-8");
489039
489187
  } else if (options.file) {
489040
- html = await readFile14(resolve24(String(options.file)), "utf-8");
489188
+ html = await readFile15(resolve24(String(options.file)), "utf-8");
489041
489189
  } else {
489042
489190
  exitWithError(
489043
489191
  usageError(
@@ -489367,8 +489515,8 @@ function readClipStart(rootHtml, beatId) {
489367
489515
  async function resolveNarrationText(value) {
489368
489516
  if (!value) return void 0;
489369
489517
  const looksLikePath = /\.[a-z]{2,4}$/i.test(value) || value.includes("/") || value.includes("\\");
489370
- if (looksLikePath && existsSync28(value)) {
489371
- return (await readFile14(value, "utf-8")).trim();
489518
+ if (looksLikePath && existsSync29(value)) {
489519
+ return (await readFile15(value, "utf-8")).trim();
489372
489520
  }
489373
489521
  return value.trim();
489374
489522
  }
@@ -489407,7 +489555,7 @@ async function executeSceneAdd(opts) {
489407
489555
  if (!opts.force && await pathExists2(scenePath)) {
489408
489556
  return errResult(`Scene already exists: ${sceneRel}. Re-run with --force to overwrite.`);
489409
489557
  }
489410
- const rootHtmlBefore = await readFile14(rootPath, "utf-8");
489558
+ const rootHtmlBefore = await readFile15(rootPath, "utf-8");
489411
489559
  let dims = readRootDims(rootHtmlBefore);
489412
489560
  if (!dims) {
489413
489561
  const cfg2 = await loadVibeProjectConfig(projectDir);
@@ -489483,31 +489631,20 @@ async function executeSceneAdd(opts) {
489483
489631
  );
489484
489632
  } else {
489485
489633
  opts.onProgress?.("Transcribing narration (Whisper word-level)...");
489486
- try {
489487
- const whisper = new WhisperProvider();
489488
- await whisper.initialize({ apiKey: whisperKey });
489489
- const audioBytes = await readFile14(audioAbsPath);
489490
- const audioBlob = new Blob([new Uint8Array(audioBytes)]);
489491
- const transcript = await whisper.transcribe(audioBlob, void 0, {
489492
- granularity: "word",
489493
- language: opts.transcribeLanguage
489494
- });
489495
- if (transcript.status === "completed" && transcript.words?.length) {
489496
- transcriptRelPath = `assets/transcript-${id}.json`;
489497
- const transcriptAbs = resolve24(projectDir, transcriptRelPath);
489498
- await writeFile17(transcriptAbs, JSON.stringify(transcript.words, null, 2), "utf-8");
489499
- transcriptWordCount = transcript.words.length;
489500
- transcriptWords = transcript.words.map((w2) => ({
489501
- text: w2.text,
489502
- start: w2.start,
489503
- end: w2.end
489504
- }));
489505
- } else if (transcript.status === "failed") {
489506
- opts.onProgress?.(`Transcribe failed: ${transcript.error ?? "unknown error"}`);
489507
- }
489508
- } catch (error) {
489509
- const msg = error instanceof Error ? error.message : String(error);
489510
- 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
+ );
489511
489648
  }
489512
489649
  }
489513
489650
  }
@@ -489616,7 +489753,7 @@ async function executeSceneAdd(opts) {
489616
489753
  const shouldSyncStoryboard = opts.syncStoryboard !== false && await pathExists2(storyboardAbsPath);
489617
489754
  if (shouldSyncStoryboard) {
489618
489755
  opts.onProgress?.("Syncing STORYBOARD.md...");
489619
- const before2 = await readFile14(storyboardAbsPath, "utf-8");
489756
+ const before2 = await readFile15(storyboardAbsPath, "utf-8");
489620
489757
  const synced = upsertStoryboardBeat(before2, {
489621
489758
  beatId: id,
489622
489759
  title: opts.headline,
@@ -489658,7 +489795,7 @@ async function executeSceneAdd(opts) {
489658
489795
  });
489659
489796
  const blockingIssue = syncPlan.issues.find((issue) => issue.severity === "error");
489660
489797
  if (blockingIssue) return errResult(blockingIssue.message);
489661
- const rootHtmlAfterSync = await readFile14(rootPath, "utf-8");
489798
+ const rootHtmlAfterSync = await readFile15(rootPath, "utf-8");
489662
489799
  start = readClipStart(rootHtmlAfterSync, id) ?? 0;
489663
489800
  } else {
489664
489801
  start = nextSceneStart(rootHtmlBefore, SCENE_OVERLAP_SECONDS);
@@ -489832,7 +489969,7 @@ async function resolveSceneRepairTarget(rootArg = "index.html", projectArg = "."
489832
489969
  const root2 = rootArg || "index.html";
489833
489970
  const project = projectArg || ".";
489834
489971
  const defaultProject = project === ".";
489835
- 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"))) {
489836
489973
  return { projectDir: resolve24(root2), rootRel: "index.html" };
489837
489974
  }
489838
489975
  return { projectDir: resolve24(project), rootRel: root2 };
@@ -490703,7 +490840,7 @@ init_exec_safe();
490703
490840
  init_remotion();
490704
490841
  import { resolve as resolve45, dirname as dirname26, basename as basename13 } from "node:path";
490705
490842
  import { writeFile as writeFile30, mkdir as mkdir21, rm as rm6 } from "node:fs/promises";
490706
- import { existsSync as existsSync51 } from "node:fs";
490843
+ import { existsSync as existsSync53 } from "node:fs";
490707
490844
  import { tmpdir as tmpdir5 } from "node:os";
490708
490845
  var ASS_STYLES = ["karaoke-sweep", "typewriter"];
490709
490846
  var SENTENCE_BREAKS = /[.!?]/;
@@ -490884,7 +491021,7 @@ async function executeAnimatedCaption(options) {
490884
491021
  const groups = groupWords(transcript.words, { wordsPerGroup, maxChars });
490885
491022
  const absOutputPath = resolve45(process.cwd(), outputPath);
490886
491023
  const outDir = dirname26(absOutputPath);
490887
- if (!existsSync51(outDir)) {
491024
+ if (!existsSync53(outDir)) {
490888
491025
  await mkdir21(outDir, { recursive: true });
490889
491026
  }
490890
491027
  if (tier === "ass") {
@@ -491432,14 +491569,14 @@ init_ai_review();
491432
491569
  init_dist();
491433
491570
  init_engine();
491434
491571
  init_ai_helpers();
491435
- import { readFile as readFile30, writeFile as writeFile32 } from "node:fs/promises";
491572
+ import { readFile as readFile31, writeFile as writeFile32 } from "node:fs/promises";
491436
491573
  import { resolve as resolve49 } from "node:path";
491437
491574
  async function executeSuggestEdit(options) {
491438
491575
  try {
491439
491576
  const apiKey = options.apiKey ?? process.env.GOOGLE_API_KEY;
491440
491577
  if (!apiKey) return { success: false, error: "GOOGLE_API_KEY required for suggest" };
491441
491578
  const filePath = resolve49(process.cwd(), options.projectPath);
491442
- const content = await readFile30(filePath, "utf-8");
491579
+ const content = await readFile31(filePath, "utf-8");
491443
491580
  const data = JSON.parse(content);
491444
491581
  const project = Project.fromJSON(data);
491445
491582
  const gemini = new GeminiProvider();
@@ -491476,9 +491613,9 @@ init_project_config();
491476
491613
  init_scene_lint();
491477
491614
  init_root_sync();
491478
491615
  init_review_report();
491479
- import { existsSync as existsSync56 } from "node:fs";
491480
- import { readdir as readdir6, readFile as readFile31, stat as stat5 } from "node:fs/promises";
491481
- 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";
491482
491619
  async function inspectProject(opts) {
491483
491620
  const projectDir = resolve50(opts.projectDir);
491484
491621
  const issues = [];
@@ -491492,7 +491629,7 @@ async function inspectProject(opts) {
491492
491629
  assets: { checked: 0, missing: [], stale: [], unknownFreshness: [] },
491493
491630
  rootSync: { ok: null, issueCount: 0, issues: [] }
491494
491631
  };
491495
- if (!existsSync56(projectDir) || !await isDirectory(projectDir)) {
491632
+ if (!existsSync57(projectDir) || !await isDirectory(projectDir)) {
491496
491633
  issues.push({
491497
491634
  severity: "error",
491498
491635
  code: "PROJECT_NOT_FOUND",
@@ -491507,15 +491644,15 @@ async function inspectProject(opts) {
491507
491644
  );
491508
491645
  }
491509
491646
  const coreFiles = {
491510
- storyboard: join37(projectDir, "STORYBOARD.md"),
491511
- design: join37(projectDir, "DESIGN.md"),
491512
- config: join37(projectDir, "vibe.config.json"),
491513
- legacyConfig: join37(projectDir, "vibe.project.yaml"),
491514
- buildReport: join37(projectDir, "build-report.json"),
491515
- 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")
491516
491653
  };
491517
491654
  for (const [name, path14] of Object.entries(coreFiles)) {
491518
- checks.files[name] = existsSync56(path14);
491655
+ checks.files[name] = existsSync57(path14);
491519
491656
  }
491520
491657
  let beatIds = [];
491521
491658
  let inspectedBeatIds = [];
@@ -491529,7 +491666,7 @@ async function inspectProject(opts) {
491529
491666
  });
491530
491667
  retryWith.push(`vibe init ${projectDir} --from "<brief>" --json`);
491531
491668
  } else {
491532
- const storyboard = await readFile31(coreFiles.storyboard, "utf-8");
491669
+ const storyboard = await readFile32(coreFiles.storyboard, "utf-8");
491533
491670
  const validation3 = validateStoryboardMarkdown(storyboard);
491534
491671
  storyboardBeats = validation3.beats;
491535
491672
  beatIds = validation3.beats.map((beat) => beat.id);
@@ -491571,7 +491708,7 @@ async function inspectProject(opts) {
491571
491708
  suggestedFix: "Create DESIGN.md or rerun `vibe init --from` in a new project."
491572
491709
  });
491573
491710
  } else {
491574
- const design = await readFile31(coreFiles.design, "utf-8");
491711
+ const design = await readFile32(coreFiles.design, "utf-8");
491575
491712
  for (const issue of designPlaceholderIssues(design)) {
491576
491713
  issues.push(issue);
491577
491714
  }
@@ -491596,20 +491733,20 @@ async function inspectProject(opts) {
491596
491733
  });
491597
491734
  retryWith.push(`vibe build ${projectDir} --stage sync --json`);
491598
491735
  }
491599
- const compositionsDir = join37(projectDir, "compositions");
491600
- 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();
491601
491738
  checks.compositions.expected = inspectedBeatIds.length;
491602
491739
  for (const beatId of inspectedBeatIds) {
491603
491740
  const file = `scene-${beatId}.html`;
491604
491741
  if (existingComps.has(file)) {
491605
491742
  checks.compositions.found++;
491606
491743
  } else {
491607
- checks.compositions.missing.push(join37("compositions", file));
491744
+ checks.compositions.missing.push(join38("compositions", file));
491608
491745
  issues.push({
491609
491746
  severity: "error",
491610
491747
  code: "MISSING_COMPOSITION",
491611
491748
  message: `Composition for beat "${beatId}" is missing.`,
491612
- file: join37("compositions", file),
491749
+ file: join38("compositions", file),
491613
491750
  scene: beatId,
491614
491751
  beatId,
491615
491752
  suggestedFix: "Run `vibe build --stage compose --json`."
@@ -491671,7 +491808,7 @@ async function inspectProject(opts) {
491671
491808
  try {
491672
491809
  const lint = await runProjectLint({ projectDir });
491673
491810
  const lintFiles = opts.beatId ? lint.files.filter(
491674
- (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`)
491675
491812
  ) : lint.files;
491676
491813
  const lintCounts = countLintFindings(lintFiles);
491677
491814
  checks.lint = {
@@ -491817,7 +491954,7 @@ function projectSourceReports(checks) {
491817
491954
  async function inspectBuildReport(projectDir, reportPath, beatId, checks, issues, retryWith, storyboardBeats) {
491818
491955
  checks.buildReport.exists = true;
491819
491956
  try {
491820
- const report = JSON.parse(await readFile31(reportPath, "utf-8"));
491957
+ const report = JSON.parse(await readFile32(reportPath, "utf-8"));
491821
491958
  if (typeof report.outputPath === "string") checks.buildReport.outputPath = report.outputPath;
491822
491959
  const reportBeats = report.beats ?? [];
491823
491960
  const selectedReportBeats = reportBeats.filter((item) => !beatId || item.id === beatId);
@@ -491954,7 +492091,7 @@ function inspectReportedAsset(opts) {
491954
492091
  opts.checks.assets.checked++;
491955
492092
  if (isExternalRef2(opts.value)) return;
491956
492093
  const abs = isAbsolute7(opts.value) ? opts.value : resolve50(opts.projectDir, opts.value);
491957
- if (existsSync56(abs)) return;
492094
+ if (existsSync57(abs)) return;
491958
492095
  opts.checks.assets.missing.push(opts.value);
491959
492096
  opts.issues.push({
491960
492097
  severity: "warning",
@@ -492048,9 +492185,9 @@ init_exec_safe();
492048
492185
  init_project_config();
492049
492186
  init_storyboard_parse();
492050
492187
  init_review_report();
492051
- import { existsSync as existsSync57 } from "node:fs";
492052
- import { readdir as readdir7, readFile as readFile32, stat as stat6 } from "node:fs/promises";
492053
- 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";
492054
492191
  var VIDEO_EXTENSIONS = /* @__PURE__ */ new Set([".mp4", ".mov", ".webm", ".m4v"]);
492055
492192
  var DEFAULT_AI_MODEL = "flash";
492056
492193
  var BLACK_FRAME_MIN_DURATION_SEC = 1;
@@ -492551,11 +492688,11 @@ async function inspectRender(opts) {
492551
492688
  }
492552
492689
  async function renderExpectsAudio(projectDir, beatId) {
492553
492690
  const root2 = resolve51(projectDir);
492554
- const rootHtml = await readTextIfExists(join38(root2, "index.html"));
492691
+ const rootHtml = await readTextIfExists(join39(root2, "index.html"));
492555
492692
  if (rootHtml && rootHtmlExpectsAudio(rootHtml, beatId)) return true;
492556
- const buildReport = await readJsonIfExists(join38(root2, "build-report.json"));
492693
+ const buildReport = await readJsonIfExists(join39(root2, "build-report.json"));
492557
492694
  if (buildReportExpectsAudio(buildReport, beatId)) return true;
492558
- const storyboard = await readTextIfExists(join38(root2, "STORYBOARD.md"));
492695
+ const storyboard = await readTextIfExists(join39(root2, "STORYBOARD.md"));
492559
492696
  if (!storyboard) return false;
492560
492697
  try {
492561
492698
  const parsed = parseStoryboard(storyboard);
@@ -492566,7 +492703,7 @@ async function renderExpectsAudio(projectDir, beatId) {
492566
492703
  `assets/narration-${beat.id}.wav`,
492567
492704
  `assets/music-${beat.id}.mp3`,
492568
492705
  `assets/music-${beat.id}.wav`
492569
- ].some((asset) => existsSync57(join38(root2, asset)))
492706
+ ].some((asset) => existsSync58(join39(root2, asset)))
492570
492707
  );
492571
492708
  } catch {
492572
492709
  return false;
@@ -492674,8 +492811,8 @@ async function maybeWriteRenderReport(projectDir, opts, result) {
492674
492811
  }
492675
492812
  function renderSourceReports(projectDir, videoPath, checks) {
492676
492813
  const reports = [];
492677
- if (existsSync57(join38(projectDir, "build-report.json"))) reports.push("build-report.json");
492678
- 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");
492679
492816
  if (videoPath) reports.push(displayPath(videoPath));
492680
492817
  if (checks.durationSec !== void 0 || checks.width !== void 0 || checks.height !== void 0) {
492681
492818
  reports.push("ffprobe");
@@ -492688,31 +492825,31 @@ function renderSourceReports(projectDir, videoPath, checks) {
492688
492825
  async function resolveRenderVideoPath(projectDir, explicit, beatId) {
492689
492826
  if (explicit) {
492690
492827
  const candidate = resolve51(process.cwd(), explicit);
492691
- return existsSync57(candidate) ? candidate : null;
492828
+ return existsSync58(candidate) ? candidate : null;
492692
492829
  }
492693
- const renderReportPath = join38(projectDir, "render-report.json");
492694
- if (existsSync57(renderReportPath)) {
492830
+ const renderReportPath = join39(projectDir, "render-report.json");
492831
+ if (existsSync58(renderReportPath)) {
492695
492832
  try {
492696
- const report = JSON.parse(await readFile32(renderReportPath, "utf-8"));
492833
+ const report = JSON.parse(await readFile33(renderReportPath, "utf-8"));
492697
492834
  const reportBeat = typeof report.beat === "string" ? report.beat : null;
492698
492835
  if (!beatId && reportBeat === null || beatId && reportBeat === beatId) {
492699
492836
  const candidate = resolveReportedPath(projectDir, report.outputPath);
492700
- if (candidate && existsSync57(candidate)) return candidate;
492837
+ if (candidate && existsSync58(candidate)) return candidate;
492701
492838
  }
492702
492839
  } catch {
492703
492840
  }
492704
492841
  }
492705
- const reportPath = join38(projectDir, "build-report.json");
492706
- if (!beatId && existsSync57(reportPath)) {
492842
+ const reportPath = join39(projectDir, "build-report.json");
492843
+ if (!beatId && existsSync58(reportPath)) {
492707
492844
  try {
492708
- const report = JSON.parse(await readFile32(reportPath, "utf-8"));
492845
+ const report = JSON.parse(await readFile33(reportPath, "utf-8"));
492709
492846
  const candidate = resolveReportedPath(projectDir, report.outputPath);
492710
- if (candidate && existsSync57(candidate)) return candidate;
492847
+ if (candidate && existsSync58(candidate)) return candidate;
492711
492848
  } catch {
492712
492849
  }
492713
492850
  }
492714
- const rendersDir = join38(projectDir, "renders");
492715
- if (!existsSync57(rendersDir)) return null;
492851
+ const rendersDir = join39(projectDir, "renders");
492852
+ if (!existsSync58(rendersDir)) return null;
492716
492853
  const entries2 = await readdir7(rendersDir, { withFileTypes: true });
492717
492854
  const candidates = [];
492718
492855
  for (const entry of entries2) {
@@ -492720,7 +492857,7 @@ async function resolveRenderVideoPath(projectDir, explicit, beatId) {
492720
492857
  const ext = entry.name.slice(entry.name.lastIndexOf(".")).toLowerCase();
492721
492858
  if (!VIDEO_EXTENSIONS.has(ext)) continue;
492722
492859
  if (beatId && !entry.name.includes(sanitizeFileSegment2(beatId))) continue;
492723
- const full = join38(rendersDir, entry.name);
492860
+ const full = join39(rendersDir, entry.name);
492724
492861
  const info = await stat6(full);
492725
492862
  candidates.push({ path: full, mtimeMs: info.mtimeMs });
492726
492863
  }
@@ -492738,14 +492875,14 @@ async function runAiRenderReview(projectDir, videoPath, model) {
492738
492875
  });
492739
492876
  }
492740
492877
  function resolveStoryboardPath(projectDir) {
492741
- const storyboardPath = join38(projectDir, "STORYBOARD.md");
492742
- return existsSync57(storyboardPath) ? storyboardPath : null;
492878
+ const storyboardPath = join39(projectDir, "STORYBOARD.md");
492879
+ return existsSync58(storyboardPath) ? storyboardPath : null;
492743
492880
  }
492744
492881
  async function expectedDurationFromBuildReport(projectDir, beatId) {
492745
- const reportPath = join38(projectDir, "build-report.json");
492746
- if (!existsSync57(reportPath)) return void 0;
492882
+ const reportPath = join39(projectDir, "build-report.json");
492883
+ if (!existsSync58(reportPath)) return void 0;
492747
492884
  try {
492748
- const report = JSON.parse(await readFile32(reportPath, "utf-8"));
492885
+ const report = JSON.parse(await readFile33(reportPath, "utf-8"));
492749
492886
  const beats = beatId ? (report.beats ?? []).filter((beat) => beat.id === beatId) : report.beats ?? [];
492750
492887
  const durations = beats.map(
492751
492888
  (beat) => parseOptionalNumber2(beat.sceneDurationSec) ?? parseOptionalNumber2(beat.narration?.sceneDurationSec)
@@ -492757,10 +492894,10 @@ async function expectedDurationFromBuildReport(projectDir, beatId) {
492757
492894
  }
492758
492895
  }
492759
492896
  async function beatTimingsFromBuildReport(projectDir, beatId) {
492760
- const reportPath = join38(projectDir, "build-report.json");
492761
- if (!existsSync57(reportPath)) return [];
492897
+ const reportPath = join39(projectDir, "build-report.json");
492898
+ if (!existsSync58(reportPath)) return [];
492762
492899
  try {
492763
- const report = JSON.parse(await readFile32(reportPath, "utf-8"));
492900
+ const report = JSON.parse(await readFile33(reportPath, "utf-8"));
492764
492901
  const source3 = report.beats ?? [];
492765
492902
  const selected = beatId ? source3.filter((beat) => beat.id === beatId) : source3;
492766
492903
  let cursor = 0;
@@ -492786,17 +492923,17 @@ async function beatTimingsFromBuildReport(projectDir, beatId) {
492786
492923
  }
492787
492924
  async function buildRenderReviewProjectContext(projectDir) {
492788
492925
  const parts = [];
492789
- const storyboard = await readTextIfExists(join38(projectDir, "STORYBOARD.md"));
492926
+ const storyboard = await readTextIfExists(join39(projectDir, "STORYBOARD.md"));
492790
492927
  if (storyboard) {
492791
492928
  parts.push(`STORYBOARD.md:
492792
492929
  ${truncateText(storyboard, 4e3)}`);
492793
492930
  parts.push(`Storyboard beat cue summary:
492794
492931
  ${storyboardBeatCueSummary(storyboard)}`);
492795
492932
  }
492796
- const design = await readTextIfExists(join38(projectDir, "DESIGN.md"));
492933
+ const design = await readTextIfExists(join39(projectDir, "DESIGN.md"));
492797
492934
  if (design) parts.push(`DESIGN.md:
492798
492935
  ${truncateText(design, 4e3)}`);
492799
- const buildReport = await readTextIfExists(join38(projectDir, "build-report.json"));
492936
+ const buildReport = await readTextIfExists(join39(projectDir, "build-report.json"));
492800
492937
  if (buildReport) parts.push(`build-report.json:
492801
492938
  ${truncateText(buildReport, 6e3)}`);
492802
492939
  const timings = await beatTimingsFromBuildReport(projectDir);
@@ -492824,9 +492961,9 @@ function storyboardBeatCueSummary(storyboard) {
492824
492961
  }
492825
492962
  }
492826
492963
  async function readTextIfExists(path14) {
492827
- if (!existsSync57(path14)) return null;
492964
+ if (!existsSync58(path14)) return null;
492828
492965
  try {
492829
- return await readFile32(path14, "utf-8");
492966
+ return await readFile33(path14, "utf-8");
492830
492967
  } catch {
492831
492968
  return null;
492832
492969
  }
@@ -493645,17 +493782,17 @@ var generateTools = [
493645
493782
  ];
493646
493783
 
493647
493784
  // ../cli/src/tools/manifest/storyboard.ts
493648
- import { existsSync as existsSync60 } from "node:fs";
493649
- 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";
493650
493787
  import { resolve as resolve65 } from "node:path";
493651
493788
  import { z as z7 } from "zod";
493652
493789
  init_storyboard_parse();
493653
493790
  init_storyboard_edit();
493654
493791
 
493655
493792
  // ../cli/src/commands/_shared/storyboard-revise.ts
493656
- import { existsSync as existsSync59 } from "node:fs";
493657
- import { readFile as readFile35, writeFile as writeFile42 } from "node:fs/promises";
493658
- 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";
493659
493796
 
493660
493797
  // ../cli/src/agent/adapters/index.ts
493661
493798
  init_openai3();
@@ -493707,9 +493844,9 @@ init_storyboard_parse();
493707
493844
  init_storyboard_edit();
493708
493845
  async function executeStoryboardRevision(opts) {
493709
493846
  const projectDir = resolve64(opts.projectDir);
493710
- const storyboardPath = join39(projectDir, "STORYBOARD.md");
493847
+ const storyboardPath = join40(projectDir, "STORYBOARD.md");
493711
493848
  const retryWith = [`vibe storyboard revise ${projectDir} --from "<request>" --dry-run --json`];
493712
- if (!existsSync59(storyboardPath)) {
493849
+ if (!existsSync60(storyboardPath)) {
493713
493850
  return failureResult({
493714
493851
  projectDir,
493715
493852
  storyboardPath,
@@ -493719,7 +493856,7 @@ async function executeStoryboardRevision(opts) {
493719
493856
  retryWith: [`vibe init ${projectDir} --from "<brief>" --json`]
493720
493857
  });
493721
493858
  }
493722
- const currentStoryboard = await readFile35(storyboardPath, "utf-8");
493859
+ const currentStoryboard = await readFile36(storyboardPath, "utf-8");
493723
493860
  const projectConfig = await readProjectConfig(projectDir);
493724
493861
  const explicitComposer = opts.composer ?? projectConfig.config.providers.composer ?? void 0;
493725
493862
  let provider = explicitComposer ?? "claude";
@@ -493942,18 +494079,18 @@ function diffChangedBeats(before2, after2) {
493942
494079
  return ids.filter((id) => JSON.stringify(beforeBeats.get(id) ?? null) !== JSON.stringify(afterBeats.get(id) ?? null));
493943
494080
  }
493944
494081
  async function readRevisionContext(projectDir) {
493945
- const designMd = await readOptionalText(join39(projectDir, "DESIGN.md"));
493946
- 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"));
493947
494084
  return { designMd, buildReportJson };
493948
494085
  }
493949
494086
  async function readOptionalText(path14) {
493950
- if (!existsSync59(path14)) return null;
493951
- return readFile35(path14, "utf-8");
494087
+ if (!existsSync60(path14)) return null;
494088
+ return readFile36(path14, "utf-8");
493952
494089
  }
493953
494090
  async function readOptionalJsonText(path14) {
493954
- if (!existsSync59(path14)) return null;
494091
+ if (!existsSync60(path14)) return null;
493955
494092
  try {
493956
- const parsed = JSON.parse(await readFile35(path14, "utf-8"));
494093
+ const parsed = JSON.parse(await readFile36(path14, "utf-8"));
493957
494094
  return JSON.stringify(parsed, null, 2);
493958
494095
  } catch {
493959
494096
  return null;
@@ -493998,8 +494135,8 @@ var projectDirSchema = z7.object({
493998
494135
  });
493999
494136
  async function readStoryboard(projectDir) {
494000
494137
  const path14 = resolve65(projectDir, "STORYBOARD.md");
494001
- if (!existsSync60(path14)) return null;
494002
- 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") };
494003
494140
  }
494004
494141
  var storyboardListTool = defineTool({
494005
494142
  name: "storyboard_list",
@@ -494258,7 +494395,7 @@ var storyboardTools = [
494258
494395
  // ../cli/src/tools/manifest/remix.ts
494259
494396
  import { writeFile as writeFile48 } from "node:fs/promises";
494260
494397
  import { tmpdir as tmpdir6 } from "node:os";
494261
- import { join as join40 } from "node:path";
494398
+ import { join as join41 } from "node:path";
494262
494399
  import { z as z8 } from "zod";
494263
494400
 
494264
494401
  // ../cli/src/commands/ai-script-pipeline.ts
@@ -494269,9 +494406,9 @@ init_config();
494269
494406
  init_audio();
494270
494407
  init_ai_helpers();
494271
494408
  init_video_utils();
494272
- 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";
494273
494410
  import { resolve as resolve66, extname as extname12 } from "node:path";
494274
- import { existsSync as existsSync61 } from "node:fs";
494411
+ import { existsSync as existsSync63 } from "node:fs";
494275
494412
 
494276
494413
  // ../cli/src/commands/_shared/video-providers.ts
494277
494414
  init_source();
@@ -494430,16 +494567,16 @@ async function executeRegenerateScene(options) {
494430
494567
  };
494431
494568
  try {
494432
494569
  const outputDir = resolve66(process.cwd(), options.projectDir);
494433
- if (!existsSync61(outputDir)) {
494570
+ if (!existsSync63(outputDir)) {
494434
494571
  return { ...result, error: `Project directory not found: ${outputDir}` };
494435
494572
  }
494436
494573
  const yamlPath = resolve66(outputDir, "storyboard.yaml");
494437
494574
  const jsonPath = resolve66(outputDir, "storyboard.json");
494438
- const storyboardPath = existsSync61(yamlPath) ? yamlPath : existsSync61(jsonPath) ? jsonPath : null;
494575
+ const storyboardPath = existsSync63(yamlPath) ? yamlPath : existsSync63(jsonPath) ? jsonPath : null;
494439
494576
  if (!storyboardPath) {
494440
494577
  return { ...result, error: `Storyboard not found in: ${outputDir} (expected storyboard.yaml or storyboard.json)` };
494441
494578
  }
494442
- const storyboardContent = await readFile37(storyboardPath, "utf-8");
494579
+ const storyboardContent = await readFile38(storyboardPath, "utf-8");
494443
494580
  const segments = storyboardPath.endsWith(".yaml") ? (0, import_yaml6.parse)(storyboardContent).scenes : JSON.parse(storyboardContent);
494444
494581
  for (const sceneNum of options.scenes) {
494445
494582
  if (sceneNum < 1 || sceneNum > segments.length) {
@@ -494528,15 +494665,15 @@ IMPORTANT - Character appearance must match exactly: ${characterDesc}`;
494528
494665
  const refSceneNum = options.referenceScene;
494529
494666
  if (refSceneNum && refSceneNum >= 1 && refSceneNum <= segments.length && refSceneNum !== sceneNum) {
494530
494667
  const refImagePath = resolve66(outputDir, `scene-${refSceneNum}.png`);
494531
- if (existsSync61(refImagePath)) {
494532
- referenceImageBuffer = await readFile37(refImagePath);
494668
+ if (existsSync63(refImagePath)) {
494669
+ referenceImageBuffer = await readFile38(refImagePath);
494533
494670
  }
494534
494671
  } else if (!refSceneNum) {
494535
494672
  for (let i2 = 1; i2 <= segments.length; i2++) {
494536
494673
  if (i2 !== sceneNum) {
494537
494674
  const otherImagePath = resolve66(outputDir, `scene-${i2}.png`);
494538
- if (existsSync61(otherImagePath)) {
494539
- referenceImageBuffer = await readFile37(otherImagePath);
494675
+ if (existsSync63(otherImagePath)) {
494676
+ referenceImageBuffer = await readFile38(otherImagePath);
494540
494677
  break;
494541
494678
  }
494542
494679
  }
@@ -494624,11 +494761,11 @@ Generate the single-person scene image now.`;
494624
494761
  }
494625
494762
  if (regenerateVideo && videoApiKey) {
494626
494763
  options.onProgress?.(`Scene ${sceneNum}: regenerating video (${options.generator || "grok"})...`);
494627
- if (!existsSync61(imagePath)) {
494764
+ if (!existsSync63(imagePath)) {
494628
494765
  result.failedScenes.push(sceneNum);
494629
494766
  continue;
494630
494767
  }
494631
- const imageBuffer = await readFile37(imagePath);
494768
+ const imageBuffer = await readFile38(imagePath);
494632
494769
  const videoDuration = segment.duration > 5 ? 10 : 5;
494633
494770
  const maxRetries = options.retries ?? DEFAULT_VIDEO_RETRIES;
494634
494771
  if (options.generator === "grok") {
@@ -494836,9 +494973,9 @@ Generate the single-person scene image now.`;
494836
494973
  }
494837
494974
 
494838
494975
  // ../cli/src/commands/ai-highlights.ts
494839
- 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";
494840
494977
  import { resolve as resolve67, dirname as dirname31, basename as basename17, extname as extname13 } from "node:path";
494841
- import { existsSync as existsSync63 } from "node:fs";
494978
+ import { existsSync as existsSync64 } from "node:fs";
494842
494979
  init_dist();
494843
494980
  init_engine();
494844
494981
  init_api_key();
@@ -494869,7 +495006,7 @@ function filterHighlights(highlights, options) {
494869
495006
  async function executeHighlights(options) {
494870
495007
  try {
494871
495008
  const absPath = resolve67(process.cwd(), options.media);
494872
- if (!existsSync63(absPath)) {
495009
+ if (!existsSync64(absPath)) {
494873
495010
  return { success: false, highlights: [], totalDuration: 0, totalHighlightDuration: 0, error: `File not found: ${absPath}` };
494874
495011
  }
494875
495012
  const ext = extname13(absPath).toLowerCase();
@@ -494888,7 +495025,7 @@ async function executeHighlights(options) {
494888
495025
  sourceDuration = await ffprobeDuration(absPath);
494889
495026
  const gemini = new GeminiProvider();
494890
495027
  await gemini.initialize({ apiKey: geminiApiKey });
494891
- const videoBuffer = await readFile38(absPath);
495028
+ const videoBuffer = await readFile39(absPath);
494892
495029
  const criteriaText = options.criteria === "all" || !options.criteria ? "emotional, informative, and funny moments" : `${options.criteria} moments`;
494893
495030
  const durationText = targetDuration ? `Target a total highlight duration of ${targetDuration} seconds.` : "";
494894
495031
  const countText = maxCount ? `Find up to ${maxCount} highlights.` : "";
@@ -494982,10 +495119,10 @@ Analyze both what is SHOWN (visual cues, actions, expressions) and what is SAID
494982
495119
  }
494983
495120
  const whisper = new WhisperProvider();
494984
495121
  await whisper.initialize({ apiKey: openaiApiKey });
494985
- const audioBuffer = await readFile38(audioPath);
495122
+ const audioBuffer = await readFile39(audioPath);
494986
495123
  const audioBlob = new Blob([audioBuffer]);
494987
495124
  const transcriptResult = await whisper.transcribe(audioBlob, options.language);
494988
- if (tempAudioPath && existsSync63(tempAudioPath)) {
495125
+ if (tempAudioPath && existsSync64(tempAudioPath)) {
494989
495126
  const { unlink: unlinkFile } = await import("node:fs/promises");
494990
495127
  await unlinkFile(tempAudioPath).catch(() => {
494991
495128
  });
@@ -495072,7 +495209,7 @@ async function executeAutoShorts(options) {
495072
495209
  return { success: false, shorts: [], error: "FFmpeg not found" };
495073
495210
  }
495074
495211
  const absPath = resolve67(process.cwd(), options.video);
495075
- if (!existsSync63(absPath)) {
495212
+ if (!existsSync64(absPath)) {
495076
495213
  return { success: false, shorts: [], error: `File not found: ${absPath}` };
495077
495214
  }
495078
495215
  const targetDuration = options.duration ?? 60;
@@ -495085,7 +495222,7 @@ async function executeAutoShorts(options) {
495085
495222
  }
495086
495223
  const gemini = new GeminiProvider();
495087
495224
  await gemini.initialize({ apiKey: geminiApiKey });
495088
- const videoBuffer = await readFile38(absPath);
495225
+ const videoBuffer = await readFile39(absPath);
495089
495226
  const geminiPrompt = `Analyze this video to find the BEST moments for short-form vertical video content (TikTok, YouTube Shorts, Instagram Reels).
495090
495227
 
495091
495228
  Find ${shortCount * 3} potential clips that are ${targetDuration} seconds or shorter each.
@@ -495162,7 +495299,7 @@ Analyze both VISUALS (expressions, actions, scene changes) and AUDIO (speech, re
495162
495299
  await execSafe("ffmpeg", ["-i", absPath, "-vn", "-acodec", "libmp3lame", "-q:a", "2", tempAudio, "-y"]);
495163
495300
  const whisper = new WhisperProvider();
495164
495301
  await whisper.initialize({ apiKey: openaiApiKey });
495165
- const audioBuffer = await readFile38(tempAudio);
495302
+ const audioBuffer = await readFile39(tempAudio);
495166
495303
  const audioBlob = new Blob([audioBuffer]);
495167
495304
  const transcript = await whisper.transcribe(audioBlob, options.language);
495168
495305
  try {
@@ -495200,7 +495337,7 @@ Analyze both VISUALS (expressions, actions, scene changes) and AUDIO (speech, re
495200
495337
  };
495201
495338
  }
495202
495339
  const outputDir = options.outputDir ? resolve67(process.cwd(), options.outputDir) : dirname31(absPath);
495203
- if (options.outputDir && !existsSync63(outputDir)) {
495340
+ if (options.outputDir && !existsSync64(outputDir)) {
495204
495341
  await mkdir27(outputDir, { recursive: true });
495205
495342
  }
495206
495343
  const result = {
@@ -495279,8 +495416,8 @@ Analyze both VISUALS (expressions, actions, scene changes) and AUDIO (speech, re
495279
495416
  // ../cli/src/pipeline/executor.ts
495280
495417
  var import_yaml7 = __toESM(require_dist3(), 1);
495281
495418
  import { resolve as resolve69 } from "node:path";
495282
- import { readFile as readFile40, writeFile as writeFile47, mkdir as mkdir28 } from "node:fs/promises";
495283
- 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";
495284
495421
 
495285
495422
  // ../cli/src/pipeline/resolver.ts
495286
495423
  function resolveStepParams(params, completedSteps) {
@@ -495693,10 +495830,10 @@ async function ensureActionsRegistered() {
495693
495830
  }
495694
495831
  async function loadPipeline(filePath) {
495695
495832
  const absPath = resolve69(process.cwd(), filePath);
495696
- if (!existsSync64(absPath)) {
495833
+ if (!existsSync65(absPath)) {
495697
495834
  throw new Error(`Pipeline file not found: ${absPath}`);
495698
495835
  }
495699
- const content = await readFile40(absPath, "utf-8");
495836
+ const content = await readFile41(absPath, "utf-8");
495700
495837
  const manifest2 = (0, import_yaml7.parse)(content);
495701
495838
  if (!manifest2.name) throw new Error("Pipeline missing 'name' field");
495702
495839
  if (!manifest2.steps || !Array.isArray(manifest2.steps)) throw new Error("Pipeline missing 'steps' array");
@@ -495719,8 +495856,8 @@ async function executePipeline(manifest2, options = {}) {
495719
495856
  const startTime = Date.now();
495720
495857
  if (options.resume) {
495721
495858
  const checkpointPath = resolve69(outputDir, CHECKPOINT_FILE);
495722
- if (existsSync64(checkpointPath)) {
495723
- const checkpointContent = await readFile40(checkpointPath, "utf-8");
495859
+ if (existsSync65(checkpointPath)) {
495860
+ const checkpointContent = await readFile41(checkpointPath, "utf-8");
495724
495861
  const checkpoint = (0, import_yaml7.parse)(checkpointContent);
495725
495862
  for (const cs of checkpoint.completedSteps) {
495726
495863
  completedSteps.set(cs.id, {
@@ -495992,7 +496129,7 @@ var pipelineRunTool = defineTool({
495992
496129
  let resolvedPath = args.pipelinePath;
495993
496130
  let tempPath;
495994
496131
  if (args.pipelineYaml) {
495995
- tempPath = join40(tmpdir6(), `vibe-mcp-pipeline-${Date.now()}.yaml`);
496132
+ tempPath = join41(tmpdir6(), `vibe-mcp-pipeline-${Date.now()}.yaml`);
495996
496133
  await writeFile48(tempPath, args.pipelineYaml, "utf-8");
495997
496134
  resolvedPath = tempPath;
495998
496135
  }
@@ -496168,10 +496305,10 @@ init_project_resolver();
496168
496305
  // ../cli/src/tools/manifest/_project-io.ts
496169
496306
  init_engine();
496170
496307
  init_project_resolver();
496171
- import { readFile as readFile41, writeFile as writeFile49 } from "node:fs/promises";
496308
+ import { readFile as readFile42, writeFile as writeFile49 } from "node:fs/promises";
496172
496309
  async function loadProject(projectPath, cwd) {
496173
496310
  const absPath = await resolveTimelineFile(projectPath, cwd);
496174
- const content = await readFile41(absPath, "utf-8");
496311
+ const content = await readFile42(absPath, "utf-8");
496175
496312
  const data = JSON.parse(content);
496176
496313
  return { project: Project.fromJSON(data), absPath };
496177
496314
  }
@@ -496522,12 +496659,12 @@ init_engine();
496522
496659
 
496523
496660
  // ../cli/src/commands/_shared/project-list.ts
496524
496661
  init_storyboard_parse();
496525
- import { readdir as readdir8, readFile as readFile42, stat as stat7 } from "node:fs/promises";
496526
- import { existsSync as existsSync65 } from "node:fs";
496527
- 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";
496528
496665
  async function executeProjectList(opts = {}) {
496529
496666
  const workspaceDir = resolve71(opts.workspaceDir ?? ".");
496530
- if (!existsSync65(workspaceDir)) {
496667
+ if (!existsSync66(workspaceDir)) {
496531
496668
  return {
496532
496669
  success: false,
496533
496670
  workspaceDir,
@@ -496544,11 +496681,11 @@ async function executeProjectList(opts = {}) {
496544
496681
  if (entry.name === "node_modules") continue;
496545
496682
  if (entry.name.startsWith(".")) continue;
496546
496683
  if (entry.name.startsWith("_")) {
496547
- archivedCount += await countProjects(join41(workspaceDir, entry.name));
496684
+ archivedCount += await countProjects(join43(workspaceDir, entry.name));
496548
496685
  continue;
496549
496686
  }
496550
- const projectDir = join41(workspaceDir, entry.name);
496551
- if (!existsSync65(join41(projectDir, "STORYBOARD.md"))) continue;
496687
+ const projectDir = join43(workspaceDir, entry.name);
496688
+ if (!existsSync66(join43(projectDir, "STORYBOARD.md"))) continue;
496552
496689
  projects.push(await describeProject(entry.name, projectDir));
496553
496690
  }
496554
496691
  projects.sort((a2, b2) => b2.updatedAt.localeCompare(a2.updatedAt));
@@ -496558,7 +496695,7 @@ async function countProjects(dir) {
496558
496695
  try {
496559
496696
  const entries2 = await readdir8(dir, { withFileTypes: true });
496560
496697
  return entries2.filter(
496561
- (e2) => e2.isDirectory() && existsSync65(join41(dir, e2.name, "STORYBOARD.md"))
496698
+ (e2) => e2.isDirectory() && existsSync66(join43(dir, e2.name, "STORYBOARD.md"))
496562
496699
  ).length;
496563
496700
  } catch {
496564
496701
  return 0;
@@ -496569,8 +496706,8 @@ async function describeProject(name, projectDir) {
496569
496706
  let storyboardDurationSec = 0;
496570
496707
  const timestamps = [];
496571
496708
  try {
496572
- const storyboardPath = join41(projectDir, "STORYBOARD.md");
496573
- const parsed = parseStoryboard(await readFile42(storyboardPath, "utf-8"));
496709
+ const storyboardPath = join43(projectDir, "STORYBOARD.md");
496710
+ const parsed = parseStoryboard(await readFile43(storyboardPath, "utf-8"));
496574
496711
  beats = parsed.beats.length;
496575
496712
  storyboardDurationSec = Number(
496576
496713
  parsed.beats.reduce((sum, beat) => sum + (beat.duration ?? 0), 0).toFixed(2)
@@ -496581,8 +496718,8 @@ async function describeProject(name, projectDir) {
496581
496718
  let buildStatus;
496582
496719
  let buildUpdatedAt;
496583
496720
  try {
496584
- const reportPath = join41(projectDir, "build-report.json");
496585
- 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"));
496586
496723
  buildStatus = report.status ?? report.phase;
496587
496724
  buildUpdatedAt = report.updatedAt;
496588
496725
  timestamps.push((await stat7(reportPath)).mtimeMs);
@@ -496590,12 +496727,12 @@ async function describeProject(name, projectDir) {
496590
496727
  }
496591
496728
  let latestRender;
496592
496729
  try {
496593
- const rendersDir = join41(projectDir, "renders");
496730
+ const rendersDir = join43(projectDir, "renders");
496594
496731
  const files = await readdir8(rendersDir);
496595
496732
  let newest;
496596
496733
  for (const file of files) {
496597
496734
  if (!/\.(mp4|webm|mov)$/i.test(file)) continue;
496598
- const { mtimeMs } = await stat7(join41(rendersDir, file));
496735
+ const { mtimeMs } = await stat7(join43(rendersDir, file));
496599
496736
  if (!newest || mtimeMs > newest.mtimeMs) newest = { file, mtimeMs };
496600
496737
  }
496601
496738
  if (newest) {
@@ -496730,7 +496867,7 @@ init_exec_safe();
496730
496867
  init_output();
496731
496868
  init_validate();
496732
496869
  init_project_resolver();
496733
- import { readFile as readFile43, access as access6 } from "node:fs/promises";
496870
+ import { readFile as readFile44, access as access6 } from "node:fs/promises";
496734
496871
  import { resolve as resolve74, basename as basename20 } from "node:path";
496735
496872
  import { spawn as spawn9 } from "node:child_process";
496736
496873
  function timelineBaseName(path14) {
@@ -496807,7 +496944,7 @@ async function runExport(projectPath, outputPath, options = {}) {
496807
496944
  };
496808
496945
  }
496809
496946
  const filePath = await resolveTimelineFile(projectPath);
496810
- const content = await readFile43(filePath, "utf-8");
496947
+ const content = await readFile44(filePath, "utf-8");
496811
496948
  const data = JSON.parse(content);
496812
496949
  const project = Project.fromJSON(data);
496813
496950
  const summary = project.getSummary();
@@ -496931,7 +497068,7 @@ Run 'vibe schema export' for structured parameter info.`).action(async (projectP
496931
497068
  }
496932
497069
  spinner2.text = "Loading project...";
496933
497070
  const filePath = await resolveTimelineFile(projectPath);
496934
- const content = await readFile43(filePath, "utf-8");
497071
+ const content = await readFile44(filePath, "utf-8");
496935
497072
  const data = JSON.parse(content);
496936
497073
  const project = Project.fromJSON(data);
496937
497074
  const summary = project.getSummary();
@@ -497529,14 +497666,14 @@ function getPresetSettings(preset, aspectRatio2) {
497529
497666
  }
497530
497667
  async function runHyperframesExport(projectPath, options, spinner2, startedAt) {
497531
497668
  spinner2.text = "Loading project...";
497532
- const { readFile: readFile46 } = await import("node:fs/promises");
497669
+ const { readFile: readFile47 } = await import("node:fs/promises");
497533
497670
  const { resolve: resolve80 } = await import("node:path");
497534
497671
  const { Project: Project2 } = await Promise.resolve().then(() => (init_engine(), engine_exports));
497535
497672
  const { createHyperframesBackend: createHyperframesBackend2 } = await Promise.resolve().then(() => (init_hyperframes(), hyperframes_exports));
497536
497673
  const { exitWithError: exitWithError2, generalError: generalError2, outputSuccess: outputSuccess2 } = await Promise.resolve().then(() => (init_output(), output_exports));
497537
497674
  const chalk2 = (await Promise.resolve().then(() => (init_source(), source_exports))).default;
497538
497675
  const filePath = await resolveTimelineFile(projectPath);
497539
- const content = await readFile46(filePath, "utf-8");
497676
+ const content = await readFile47(filePath, "utf-8");
497540
497677
  const project = Project2.fromJSON(JSON.parse(content));
497541
497678
  const state = project.getState();
497542
497679
  const outputPath = options.output ? resolve80(process.cwd(), options.output) : resolve80(process.cwd(), `${timelineBaseName(projectPath)}.${options.format ?? "mp4"}`);
@@ -497605,8 +497742,8 @@ var exportVideoTool = defineTool({
497605
497742
  var exportTools = [exportVideoTool];
497606
497743
 
497607
497744
  // ../cli/src/tools/manifest/agent-only.ts
497608
- import { readFile as readFile44, writeFile as writeFile52, readdir as readdir9, stat as stat8, access as access7, unlink as unlink7 } from "node:fs/promises";
497609
- 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";
497610
497747
  import { z as z13 } from "zod";
497611
497748
  init_engine();
497612
497749
  init_exec_safe();
@@ -497685,7 +497822,7 @@ var fsListTool = defineTool({
497685
497822
  const results = [];
497686
497823
  for (const entry of entries2) {
497687
497824
  if (args.pattern && !matchPattern(entry.name, args.pattern)) continue;
497688
- const fullPath = join43(absPath, entry.name);
497825
+ const fullPath = join44(absPath, entry.name);
497689
497826
  const stats = await stat8(fullPath);
497690
497827
  if (entry.isDirectory()) {
497691
497828
  results.push(`[DIR] ${entry.name}/`);
@@ -497714,7 +497851,7 @@ var fsReadTool = defineTool({
497714
497851
  async execute(args, ctx) {
497715
497852
  try {
497716
497853
  const absPath = resolve76(ctx.workingDirectory, args.path);
497717
- const content = await readFile44(absPath, "utf-8");
497854
+ const content = await readFile45(absPath, "utf-8");
497718
497855
  const maxLength = 4e3;
497719
497856
  const truncated = content.length > maxLength;
497720
497857
  const output3 = truncated ? content.substring(0, maxLength) + "\n... (truncated)" : content;
@@ -497787,7 +497924,7 @@ var batchImportTool = defineTool({
497787
497924
  async execute(args, ctx) {
497788
497925
  try {
497789
497926
  const filePath = resolve76(ctx.workingDirectory, args.project);
497790
- const content = await readFile44(filePath, "utf-8");
497927
+ const content = await readFile45(filePath, "utf-8");
497791
497928
  const data = JSON.parse(content);
497792
497929
  const project = Project.fromJSON(data);
497793
497930
  const dirPath = resolve76(ctx.workingDirectory, args.directory);
@@ -497798,7 +497935,7 @@ var batchImportTool = defineTool({
497798
497935
  const scanDir = async (dir) => {
497799
497936
  const entries2 = await readdir9(dir, { withFileTypes: true });
497800
497937
  for (const entry of entries2) {
497801
- const entryPath = join43(dir, entry.name);
497938
+ const entryPath = join44(dir, entry.name);
497802
497939
  if (entry.isDirectory() && recursive) {
497803
497940
  await scanDir(entryPath);
497804
497941
  } else if (entry.isFile()) {
@@ -497859,7 +497996,7 @@ var batchConcatTool = defineTool({
497859
497996
  async execute(args, ctx) {
497860
497997
  try {
497861
497998
  const filePath = resolve76(ctx.workingDirectory, args.project);
497862
- const content = await readFile44(filePath, "utf-8");
497999
+ const content = await readFile45(filePath, "utf-8");
497863
498000
  const data = JSON.parse(content);
497864
498001
  const project = Project.fromJSON(data);
497865
498002
  const sourceIds = args.sourceIds ?? [];
@@ -497930,7 +498067,7 @@ var batchApplyEffectTool = defineTool({
497930
498067
  async execute(args, ctx) {
497931
498068
  try {
497932
498069
  const filePath = resolve76(ctx.workingDirectory, args.project);
497933
- const content = await readFile44(filePath, "utf-8");
498070
+ const content = await readFile45(filePath, "utf-8");
497934
498071
  const data = JSON.parse(content);
497935
498072
  const project = Project.fromJSON(data);
497936
498073
  const clipIds = args.clipIds ?? [];
@@ -497985,7 +498122,7 @@ var timelineClearTool = defineTool({
497985
498122
  async execute(args, ctx) {
497986
498123
  try {
497987
498124
  const filePath = await resolveTimelineFile(args.project, ctx.workingDirectory);
497988
- const content = await readFile44(filePath, "utf-8");
498125
+ const content = await readFile45(filePath, "utf-8");
497989
498126
  const data = JSON.parse(content);
497990
498127
  const project = Project.fromJSON(data);
497991
498128
  const what = args.what ?? "clips";
@@ -498062,7 +498199,7 @@ var projectSetTool = defineTool({
498062
498199
  async execute(args, ctx) {
498063
498200
  try {
498064
498201
  const filePath = await resolveTimelineFile(args.projectPath, ctx.workingDirectory);
498065
- const content = await readFile44(filePath, "utf-8");
498202
+ const content = await readFile45(filePath, "utf-8");
498066
498203
  const data = JSON.parse(content);
498067
498204
  const project = Project.fromJSON(data);
498068
498205
  const updates = [];
@@ -498336,8 +498473,8 @@ var mediaCompressTool = defineTool({
498336
498473
  ],
498337
498474
  { maxBuffer: 50 * 1024 * 1024 }
498338
498475
  );
498339
- const inputBuf = await readFile44(absInput);
498340
- const outputBuf = await readFile44(outputPath);
498476
+ const inputBuf = await readFile45(absInput);
498477
+ const outputBuf = await readFile45(outputPath);
498341
498478
  const inputSize = inputBuf.length;
498342
498479
  const outputSize = outputBuf.length;
498343
498480
  const reduction = (inputSize - outputSize) / inputSize * 100;
@@ -499359,7 +499496,7 @@ async function handleToolCall(name, args, extra) {
499359
499496
 
499360
499497
  // src/resources/index.ts
499361
499498
  init_engine();
499362
- import { readFile as readFile45 } from "node:fs/promises";
499499
+ import { readFile as readFile46 } from "node:fs/promises";
499363
499500
  import { resolve as resolve78 } from "node:path";
499364
499501
  var resources = [
499365
499502
  {
@@ -499396,7 +499533,7 @@ var resources = [
499396
499533
  var currentProjectPath = process.env.VIBE_PROJECT_PATH || null;
499397
499534
  async function loadProject2(projectPath) {
499398
499535
  const absPath = resolve78(process.cwd(), projectPath);
499399
- const content = await readFile45(absPath, "utf-8");
499536
+ const content = await readFile46(absPath, "utf-8");
499400
499537
  const data = JSON.parse(content);
499401
499538
  return Project.fromJSON(data);
499402
499539
  }
@@ -499788,14 +499925,14 @@ This creates a music video-style edit where cuts happen in rhythm with the music
499788
499925
  }
499789
499926
 
499790
499927
  // src/instructions.ts
499791
- import { existsSync as existsSync66, mkdirSync as mkdirSync13 } from "node:fs";
499928
+ import { existsSync as existsSync67, mkdirSync as mkdirSync13 } from "node:fs";
499792
499929
  import { delimiter, isAbsolute as isAbsolute9, resolve as resolve79 } from "node:path";
499793
499930
  var DEFAULT_EXTRA_PATH_DIRS = process.platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin", "/opt/local/bin"] : ["/usr/local/bin"];
499794
499931
  function ensureSystemPath(env4 = process.env, extraDirs = DEFAULT_EXTRA_PATH_DIRS) {
499795
499932
  const current = (env4.PATH ?? "").split(delimiter).filter(Boolean);
499796
499933
  const added = [];
499797
499934
  for (const dir of extraDirs) {
499798
- if (!current.includes(dir) && existsSync66(dir)) {
499935
+ if (!current.includes(dir) && existsSync67(dir)) {
499799
499936
  current.push(dir);
499800
499937
  added.push(dir);
499801
499938
  }
@@ -499897,7 +500034,7 @@ function handleCliFlags(argv, version) {
499897
500034
  }
499898
500035
 
499899
500036
  // src/index.ts
499900
- if (handleCliFlags(process.argv.slice(2), "0.113.9")) {
500037
+ if (handleCliFlags(process.argv.slice(2), "0.113.11")) {
499901
500038
  process.exit(0);
499902
500039
  }
499903
500040
  console.log = (...args) => console.error(...args);
@@ -499910,7 +500047,7 @@ var server2 = new Server(
499910
500047
  {
499911
500048
  name: "vibeframe",
499912
500049
  // Stamped with the package version by build.js at bundle time.
499913
- version: "0.113.9"
500050
+ version: "0.113.11"
499914
500051
  },
499915
500052
  {
499916
500053
  capabilities: {