@vibeframe/cli 0.106.3 → 0.106.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -7844,7 +7844,7 @@ function errorMessage(error) {
7844
7844
  return error instanceof Error ? error.message : "Unknown error";
7845
7845
  }
7846
7846
  function sleep(ms) {
7847
- return new Promise((resolve81) => setTimeout(resolve81, ms));
7847
+ return new Promise((resolve83) => setTimeout(resolve83, ms));
7848
7848
  }
7849
7849
  var ProviderHttpError;
7850
7850
  var init_http = __esm({
@@ -12238,7 +12238,7 @@ var init_RunwayProvider = __esm({
12238
12238
  * Sleep helper
12239
12239
  */
12240
12240
  sleep(ms) {
12241
- return new Promise((resolve81) => setTimeout(resolve81, ms));
12241
+ return new Promise((resolve83) => setTimeout(resolve83, ms));
12242
12242
  }
12243
12243
  };
12244
12244
  RunwayProvider.API_VERSION = "2024-11-06";
@@ -12679,7 +12679,7 @@ var init_KlingProvider = __esm({
12679
12679
  * Sleep helper
12680
12680
  */
12681
12681
  sleep(ms) {
12682
- return new Promise((resolve81) => setTimeout(resolve81, ms));
12682
+ return new Promise((resolve83) => setTimeout(resolve83, ms));
12683
12683
  }
12684
12684
  };
12685
12685
  klingProvider = new KlingProvider();
@@ -12997,7 +12997,7 @@ var init_GrokProvider = __esm({
12997
12997
  }
12998
12998
  }
12999
12999
  sleep(ms) {
13000
- return new Promise((resolve81) => setTimeout(resolve81, ms));
13000
+ return new Promise((resolve83) => setTimeout(resolve83, ms));
13001
13001
  }
13002
13002
  };
13003
13003
  grokProvider = new GrokProvider();
@@ -13032,11 +13032,11 @@ var require_middleware = __commonJS({
13032
13032
  "use strict";
13033
13033
  var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
13034
13034
  function adopt(value) {
13035
- return value instanceof P ? value : new P(function(resolve81) {
13036
- resolve81(value);
13035
+ return value instanceof P ? value : new P(function(resolve83) {
13036
+ resolve83(value);
13037
13037
  });
13038
13038
  }
13039
- return new (P || (P = Promise))(function(resolve81, reject) {
13039
+ return new (P || (P = Promise))(function(resolve83, reject) {
13040
13040
  function fulfilled(value) {
13041
13041
  try {
13042
13042
  step(generator.next(value));
@@ -13052,7 +13052,7 @@ var require_middleware = __commonJS({
13052
13052
  }
13053
13053
  }
13054
13054
  function step(result) {
13055
- result.done ? resolve81(result.value) : adopt(result.value).then(fulfilled, rejected);
13055
+ result.done ? resolve83(result.value) : adopt(result.value).then(fulfilled, rejected);
13056
13056
  }
13057
13057
  step((generator = generator.apply(thisArg, _arguments || [])).next());
13058
13058
  });
@@ -13137,11 +13137,11 @@ var require_response = __commonJS({
13137
13137
  "use strict";
13138
13138
  var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
13139
13139
  function adopt(value) {
13140
- return value instanceof P ? value : new P(function(resolve81) {
13141
- resolve81(value);
13140
+ return value instanceof P ? value : new P(function(resolve83) {
13141
+ resolve83(value);
13142
13142
  });
13143
13143
  }
13144
- return new (P || (P = Promise))(function(resolve81, reject) {
13144
+ return new (P || (P = Promise))(function(resolve83, reject) {
13145
13145
  function fulfilled(value) {
13146
13146
  try {
13147
13147
  step(generator.next(value));
@@ -13157,7 +13157,7 @@ var require_response = __commonJS({
13157
13157
  }
13158
13158
  }
13159
13159
  function step(result) {
13160
- result.done ? resolve81(result.value) : adopt(result.value).then(fulfilled, rejected);
13160
+ result.done ? resolve83(result.value) : adopt(result.value).then(fulfilled, rejected);
13161
13161
  }
13162
13162
  step((generator = generator.apply(thisArg, _arguments || [])).next());
13163
13163
  });
@@ -13264,11 +13264,11 @@ var require_utils = __commonJS({
13264
13264
  "use strict";
13265
13265
  var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
13266
13266
  function adopt(value) {
13267
- return value instanceof P ? value : new P(function(resolve81) {
13268
- resolve81(value);
13267
+ return value instanceof P ? value : new P(function(resolve83) {
13268
+ resolve83(value);
13269
13269
  });
13270
13270
  }
13271
- return new (P || (P = Promise))(function(resolve81, reject) {
13271
+ return new (P || (P = Promise))(function(resolve83, reject) {
13272
13272
  function fulfilled(value) {
13273
13273
  try {
13274
13274
  step(generator.next(value));
@@ -13284,7 +13284,7 @@ var require_utils = __commonJS({
13284
13284
  }
13285
13285
  }
13286
13286
  function step(result) {
13287
- result.done ? resolve81(result.value) : adopt(result.value).then(fulfilled, rejected);
13287
+ result.done ? resolve83(result.value) : adopt(result.value).then(fulfilled, rejected);
13288
13288
  }
13289
13289
  step((generator = generator.apply(thisArg, _arguments || [])).next());
13290
13290
  });
@@ -13377,7 +13377,7 @@ var require_utils = __commonJS({
13377
13377
  }
13378
13378
  function sleep4(ms) {
13379
13379
  return __awaiter(this, void 0, void 0, function* () {
13380
- return new Promise((resolve81) => setTimeout(resolve81, ms));
13380
+ return new Promise((resolve83) => setTimeout(resolve83, ms));
13381
13381
  });
13382
13382
  }
13383
13383
  }
@@ -13389,11 +13389,11 @@ var require_retry = __commonJS({
13389
13389
  "use strict";
13390
13390
  var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
13391
13391
  function adopt(value) {
13392
- return value instanceof P ? value : new P(function(resolve81) {
13393
- resolve81(value);
13392
+ return value instanceof P ? value : new P(function(resolve83) {
13393
+ resolve83(value);
13394
13394
  });
13395
13395
  }
13396
- return new (P || (P = Promise))(function(resolve81, reject) {
13396
+ return new (P || (P = Promise))(function(resolve83, reject) {
13397
13397
  function fulfilled(value) {
13398
13398
  try {
13399
13399
  step(generator.next(value));
@@ -13409,7 +13409,7 @@ var require_retry = __commonJS({
13409
13409
  }
13410
13410
  }
13411
13411
  function step(result) {
13412
- result.done ? resolve81(result.value) : adopt(result.value).then(fulfilled, rejected);
13412
+ result.done ? resolve83(result.value) : adopt(result.value).then(fulfilled, rejected);
13413
13413
  }
13414
13414
  step((generator = generator.apply(thisArg, _arguments || [])).next());
13415
13415
  });
@@ -13616,11 +13616,11 @@ var require_request = __commonJS({
13616
13616
  "use strict";
13617
13617
  var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
13618
13618
  function adopt(value) {
13619
- return value instanceof P ? value : new P(function(resolve81) {
13620
- resolve81(value);
13619
+ return value instanceof P ? value : new P(function(resolve83) {
13620
+ resolve83(value);
13621
13621
  });
13622
13622
  }
13623
- return new (P || (P = Promise))(function(resolve81, reject) {
13623
+ return new (P || (P = Promise))(function(resolve83, reject) {
13624
13624
  function fulfilled(value) {
13625
13625
  try {
13626
13626
  step(generator.next(value));
@@ -13636,7 +13636,7 @@ var require_request = __commonJS({
13636
13636
  }
13637
13637
  }
13638
13638
  function step(result) {
13639
- result.done ? resolve81(result.value) : adopt(result.value).then(fulfilled, rejected);
13639
+ result.done ? resolve83(result.value) : adopt(result.value).then(fulfilled, rejected);
13640
13640
  }
13641
13641
  step((generator = generator.apply(thisArg, _arguments || [])).next());
13642
13642
  });
@@ -13723,11 +13723,11 @@ var require_storage = __commonJS({
13723
13723
  "use strict";
13724
13724
  var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
13725
13725
  function adopt(value) {
13726
- return value instanceof P ? value : new P(function(resolve81) {
13727
- resolve81(value);
13726
+ return value instanceof P ? value : new P(function(resolve83) {
13727
+ resolve83(value);
13728
13728
  });
13729
13729
  }
13730
- return new (P || (P = Promise))(function(resolve81, reject) {
13730
+ return new (P || (P = Promise))(function(resolve83, reject) {
13731
13731
  function fulfilled(value) {
13732
13732
  try {
13733
13733
  step(generator.next(value));
@@ -13743,7 +13743,7 @@ var require_storage = __commonJS({
13743
13743
  }
13744
13744
  }
13745
13745
  function step(result) {
13746
- result.done ? resolve81(result.value) : adopt(result.value).then(fulfilled, rejected);
13746
+ result.done ? resolve83(result.value) : adopt(result.value).then(fulfilled, rejected);
13747
13747
  }
13748
13748
  step((generator = generator.apply(thisArg, _arguments || [])).next());
13749
13749
  });
@@ -14071,11 +14071,11 @@ var require_auth = __commonJS({
14071
14071
  "use strict";
14072
14072
  var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
14073
14073
  function adopt(value) {
14074
- return value instanceof P ? value : new P(function(resolve81) {
14075
- resolve81(value);
14074
+ return value instanceof P ? value : new P(function(resolve83) {
14075
+ resolve83(value);
14076
14076
  });
14077
14077
  }
14078
- return new (P || (P = Promise))(function(resolve81, reject) {
14078
+ return new (P || (P = Promise))(function(resolve83, reject) {
14079
14079
  function fulfilled(value) {
14080
14080
  try {
14081
14081
  step(generator.next(value));
@@ -14091,7 +14091,7 @@ var require_auth = __commonJS({
14091
14091
  }
14092
14092
  }
14093
14093
  function step(result) {
14094
- result.done ? resolve81(result.value) : adopt(result.value).then(fulfilled, rejected);
14094
+ result.done ? resolve83(result.value) : adopt(result.value).then(fulfilled, rejected);
14095
14095
  }
14096
14096
  step((generator = generator.apply(thisArg, _arguments || [])).next());
14097
14097
  });
@@ -14130,11 +14130,11 @@ var require_streaming = __commonJS({
14130
14130
  "use strict";
14131
14131
  var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
14132
14132
  function adopt(value) {
14133
- return value instanceof P ? value : new P(function(resolve81) {
14134
- resolve81(value);
14133
+ return value instanceof P ? value : new P(function(resolve83) {
14134
+ resolve83(value);
14135
14135
  });
14136
14136
  }
14137
- return new (P || (P = Promise))(function(resolve81, reject) {
14137
+ return new (P || (P = Promise))(function(resolve83, reject) {
14138
14138
  function fulfilled(value) {
14139
14139
  try {
14140
14140
  step(generator.next(value));
@@ -14150,7 +14150,7 @@ var require_streaming = __commonJS({
14150
14150
  }
14151
14151
  }
14152
14152
  function step(result) {
14153
- result.done ? resolve81(result.value) : adopt(result.value).then(fulfilled, rejected);
14153
+ result.done ? resolve83(result.value) : adopt(result.value).then(fulfilled, rejected);
14154
14154
  }
14155
14155
  step((generator = generator.apply(thisArg, _arguments || [])).next());
14156
14156
  });
@@ -14383,7 +14383,7 @@ var require_streaming = __commonJS({
14383
14383
  query: options.queryParams
14384
14384
  });
14385
14385
  this.options = options;
14386
- this.donePromise = new Promise((resolve81, reject) => {
14386
+ this.donePromise = new Promise((resolve83, reject) => {
14387
14387
  if (this.streamClosed) {
14388
14388
  reject(new response_1.ApiError({
14389
14389
  message: "Streaming connection is already closed.",
@@ -14394,11 +14394,11 @@ var require_streaming = __commonJS({
14394
14394
  }
14395
14395
  this.signal.addEventListener("abort", () => {
14396
14396
  var _a2;
14397
- resolve81((_a2 = this.currentData) !== null && _a2 !== void 0 ? _a2 : {});
14397
+ resolve83((_a2 = this.currentData) !== null && _a2 !== void 0 ? _a2 : {});
14398
14398
  });
14399
14399
  this.on("done", (data) => {
14400
14400
  this.streamClosed = true;
14401
- resolve81(data);
14401
+ resolve83(data);
14402
14402
  });
14403
14403
  this.on("error", (error) => {
14404
14404
  this.streamClosed = true;
@@ -14423,7 +14423,7 @@ var require_streaming = __commonJS({
14423
14423
  if (data) {
14424
14424
  yield yield __await(data);
14425
14425
  }
14426
- yield __await(new Promise((resolve81) => setTimeout(resolve81, 16)));
14426
+ yield __await(new Promise((resolve83) => setTimeout(resolve83, 16)));
14427
14427
  }
14428
14428
  });
14429
14429
  }
@@ -14468,11 +14468,11 @@ var require_queue = __commonJS({
14468
14468
  "use strict";
14469
14469
  var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
14470
14470
  function adopt(value) {
14471
- return value instanceof P ? value : new P(function(resolve81) {
14472
- resolve81(value);
14471
+ return value instanceof P ? value : new P(function(resolve83) {
14472
+ resolve83(value);
14473
14473
  });
14474
14474
  }
14475
- return new (P || (P = Promise))(function(resolve81, reject) {
14475
+ return new (P || (P = Promise))(function(resolve83, reject) {
14476
14476
  function fulfilled(value) {
14477
14477
  try {
14478
14478
  step(generator.next(value));
@@ -14488,7 +14488,7 @@ var require_queue = __commonJS({
14488
14488
  }
14489
14489
  }
14490
14490
  function step(result) {
14491
- result.done ? resolve81(result.value) : adopt(result.value).then(fulfilled, rejected);
14491
+ result.done ? resolve83(result.value) : adopt(result.value).then(fulfilled, rejected);
14492
14492
  }
14493
14493
  step((generator = generator.apply(thisArg, _arguments || [])).next());
14494
14494
  });
@@ -14623,7 +14623,7 @@ var require_queue = __commonJS({
14623
14623
  }
14624
14624
  return doneStatus;
14625
14625
  }
14626
- return new Promise((resolve81, reject) => {
14626
+ return new Promise((resolve83, reject) => {
14627
14627
  var _a;
14628
14628
  let pollingTimeoutId;
14629
14629
  const pollInterval = "pollInterval" in options && typeof options.pollInterval === "number" ? (_a = options.pollInterval) !== null && _a !== void 0 ? _a : DEFAULT_POLL_INTERVAL : DEFAULT_POLL_INTERVAL;
@@ -14655,7 +14655,7 @@ var require_queue = __commonJS({
14655
14655
  }
14656
14656
  if (requestStatus.status === "COMPLETED") {
14657
14657
  clearScheduledTasks();
14658
- resolve81(requestStatus);
14658
+ resolve83(requestStatus);
14659
14659
  return;
14660
14660
  }
14661
14661
  pollingTimeoutId = setTimeout(poll, pollInterval);
@@ -16616,11 +16616,11 @@ var require_realtime = __commonJS({
16616
16616
  "use strict";
16617
16617
  var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
16618
16618
  function adopt(value) {
16619
- return value instanceof P ? value : new P(function(resolve81) {
16620
- resolve81(value);
16619
+ return value instanceof P ? value : new P(function(resolve83) {
16620
+ resolve83(value);
16621
16621
  });
16622
16622
  }
16623
- return new (P || (P = Promise))(function(resolve81, reject) {
16623
+ return new (P || (P = Promise))(function(resolve83, reject) {
16624
16624
  function fulfilled(value) {
16625
16625
  try {
16626
16626
  step(generator.next(value));
@@ -16636,7 +16636,7 @@ var require_realtime = __commonJS({
16636
16636
  }
16637
16637
  }
16638
16638
  function step(result) {
16639
- result.done ? resolve81(result.value) : adopt(result.value).then(fulfilled, rejected);
16639
+ result.done ? resolve83(result.value) : adopt(result.value).then(fulfilled, rejected);
16640
16640
  }
16641
16641
  step((generator = generator.apply(thisArg, _arguments || [])).next());
16642
16642
  });
@@ -16961,11 +16961,11 @@ var require_client = __commonJS({
16961
16961
  "use strict";
16962
16962
  var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
16963
16963
  function adopt(value) {
16964
- return value instanceof P ? value : new P(function(resolve81) {
16965
- resolve81(value);
16964
+ return value instanceof P ? value : new P(function(resolve83) {
16965
+ resolve83(value);
16966
16966
  });
16967
16967
  }
16968
- return new (P || (P = Promise))(function(resolve81, reject) {
16968
+ return new (P || (P = Promise))(function(resolve83, reject) {
16969
16969
  function fulfilled(value) {
16970
16970
  try {
16971
16971
  step(generator.next(value));
@@ -16981,7 +16981,7 @@ var require_client = __commonJS({
16981
16981
  }
16982
16982
  }
16983
16983
  function step(result) {
16984
- result.done ? resolve81(result.value) : adopt(result.value).then(fulfilled, rejected);
16984
+ result.done ? resolve83(result.value) : adopt(result.value).then(fulfilled, rejected);
16985
16985
  }
16986
16986
  step((generator = generator.apply(thisArg, _arguments || [])).next());
16987
16987
  });
@@ -17666,7 +17666,7 @@ var init_ReplicateProvider = __esm({
17666
17666
  * Sleep helper
17667
17667
  */
17668
17668
  sleep(ms) {
17669
- return new Promise((resolve81) => setTimeout(resolve81, ms));
17669
+ return new Promise((resolve83) => setTimeout(resolve83, ms));
17670
17670
  }
17671
17671
  /**
17672
17672
  * Generate music from text prompt using MusicGen
@@ -21601,7 +21601,7 @@ var require_timestamp2 = __commonJS({
21601
21601
  resolve: (str) => parseSexagesimal(str, false),
21602
21602
  stringify: stringifySexagesimal
21603
21603
  };
21604
- var timestamp = {
21604
+ var timestamp2 = {
21605
21605
  identify: (value) => value instanceof Date,
21606
21606
  default: true,
21607
21607
  tag: "tag:yaml.org,2002:timestamp",
@@ -21610,7 +21610,7 @@ var require_timestamp2 = __commonJS({
21610
21610
  // assumed to be 00:00:00Z (start of day, UTC).
21611
21611
  test: RegExp("^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})(?:(?:t|T|[ \\t]+)([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2}(\\.[0-9]+)?)(?:[ \\t]*(Z|[-+][012]?[0-9](?::[0-9]{2})?))?)?$"),
21612
21612
  resolve(str) {
21613
- const match = str.match(timestamp.test);
21613
+ const match = str.match(timestamp2.test);
21614
21614
  if (!match)
21615
21615
  throw new Error("!!timestamp expects a date, starting with yyyy-mm-dd");
21616
21616
  const [, year, month, day, hour, minute, second] = match.map(Number);
@@ -21629,7 +21629,7 @@ var require_timestamp2 = __commonJS({
21629
21629
  };
21630
21630
  exports.floatTime = floatTime;
21631
21631
  exports.intTime = intTime;
21632
- exports.timestamp = timestamp;
21632
+ exports.timestamp = timestamp2;
21633
21633
  }
21634
21634
  });
21635
21635
 
@@ -21649,7 +21649,7 @@ var require_schema3 = __commonJS({
21649
21649
  var omap = require_omap();
21650
21650
  var pairs = require_pairs();
21651
21651
  var set = require_set();
21652
- var timestamp = require_timestamp2();
21652
+ var timestamp2 = require_timestamp2();
21653
21653
  var schema = [
21654
21654
  map.map,
21655
21655
  seq.seq,
@@ -21669,9 +21669,9 @@ var require_schema3 = __commonJS({
21669
21669
  omap.omap,
21670
21670
  pairs.pairs,
21671
21671
  set.set,
21672
- timestamp.intTime,
21673
- timestamp.floatTime,
21674
- timestamp.timestamp
21672
+ timestamp2.intTime,
21673
+ timestamp2.floatTime,
21674
+ timestamp2.timestamp
21675
21675
  ];
21676
21676
  exports.schema = schema;
21677
21677
  }
@@ -21696,7 +21696,7 @@ var require_tags = __commonJS({
21696
21696
  var pairs = require_pairs();
21697
21697
  var schema$2 = require_schema3();
21698
21698
  var set = require_set();
21699
- var timestamp = require_timestamp2();
21699
+ var timestamp2 = require_timestamp2();
21700
21700
  var schemas = /* @__PURE__ */ new Map([
21701
21701
  ["core", schema.schema],
21702
21702
  ["failsafe", [map.map, seq.seq, string.string]],
@@ -21710,11 +21710,11 @@ var require_tags = __commonJS({
21710
21710
  float: float.float,
21711
21711
  floatExp: float.floatExp,
21712
21712
  floatNaN: float.floatNaN,
21713
- floatTime: timestamp.floatTime,
21713
+ floatTime: timestamp2.floatTime,
21714
21714
  int: int.int,
21715
21715
  intHex: int.intHex,
21716
21716
  intOct: int.intOct,
21717
- intTime: timestamp.intTime,
21717
+ intTime: timestamp2.intTime,
21718
21718
  map: map.map,
21719
21719
  merge: merge.merge,
21720
21720
  null: _null.nullTag,
@@ -21722,7 +21722,7 @@ var require_tags = __commonJS({
21722
21722
  pairs: pairs.pairs,
21723
21723
  seq: seq.seq,
21724
21724
  set: set.set,
21725
- timestamp: timestamp.timestamp
21725
+ timestamp: timestamp2.timestamp
21726
21726
  };
21727
21727
  var coreKnownTags = {
21728
21728
  "tag:yaml.org,2002:binary": binary.binary,
@@ -21730,7 +21730,7 @@ var require_tags = __commonJS({
21730
21730
  "tag:yaml.org,2002:omap": omap.omap,
21731
21731
  "tag:yaml.org,2002:pairs": pairs.pairs,
21732
21732
  "tag:yaml.org,2002:set": set.set,
21733
- "tag:yaml.org,2002:timestamp": timestamp.timestamp
21733
+ "tag:yaml.org,2002:timestamp": timestamp2.timestamp
21734
21734
  };
21735
21735
  function getTags(customTags, schemaName, addMergeTag) {
21736
21736
  const schemaTags = schemas.get(schemaName);
@@ -26132,7 +26132,7 @@ async function prompt(question, hidden = false) {
26132
26132
  input: process.stdin,
26133
26133
  output: process.stdout
26134
26134
  });
26135
- return new Promise((resolve81) => {
26135
+ return new Promise((resolve83) => {
26136
26136
  if (hidden && process.stdin.isTTY) {
26137
26137
  process.stdout.write(question);
26138
26138
  let input = "";
@@ -26146,7 +26146,7 @@ async function prompt(question, hidden = false) {
26146
26146
  process.stdin.removeListener("data", onData);
26147
26147
  process.stdout.write("\n");
26148
26148
  rl.close();
26149
- resolve81(input);
26149
+ resolve83(input);
26150
26150
  } else if (char === "") {
26151
26151
  process.exit(1);
26152
26152
  } else if (char === "\x7F" || char === "\b") {
@@ -26161,7 +26161,7 @@ async function prompt(question, hidden = false) {
26161
26161
  } else {
26162
26162
  rl.question(question, (answer) => {
26163
26163
  rl.close();
26164
- resolve81(answer);
26164
+ resolve83(answer);
26165
26165
  });
26166
26166
  }
26167
26167
  });
@@ -26758,6 +26758,18 @@ a host agent's built-in image/audio generation tool for VibeFrame project
26758
26758
  assets unless the user explicitly requests an external, non-VibeFrame
26759
26759
  asset.
26760
26760
 
26761
+ ## App host setup
26762
+
26763
+ VibeFrame is CLI-first, not terminal-only. Codex, Claude Code, and Cursor can
26764
+ drive this project through shell commands, and app hosts can use the MCP server
26765
+ as a typed tool surface.
26766
+
26767
+ \`\`\`bash
26768
+ vibe host setup all # print Codex/Claude/Cursor snippets
26769
+ vibe host setup all --write # write project/app config
26770
+ vibe host doctor all --json # verify readiness
26771
+ \`\`\`
26772
+
26761
26773
  ## Skills \u2014 USE THESE FIRST
26762
26774
 
26763
26775
  @SKILL.md
@@ -33269,16 +33281,16 @@ async function prompt2(question) {
33269
33281
  input,
33270
33282
  output: process.stdout
33271
33283
  });
33272
- return new Promise((resolve81) => {
33284
+ return new Promise((resolve83) => {
33273
33285
  rl.question(question, (answer) => {
33274
33286
  rl.close();
33275
- resolve81(answer);
33287
+ resolve83(answer);
33276
33288
  });
33277
33289
  });
33278
33290
  }
33279
33291
  async function promptHidden(question, opts = {}) {
33280
33292
  const input = getTTYInputStream();
33281
- return new Promise((resolve81) => {
33293
+ return new Promise((resolve83) => {
33282
33294
  let value = "";
33283
33295
  if (typeof input.setRawMode === "function") {
33284
33296
  input.setRawMode(true);
@@ -33292,7 +33304,7 @@ async function promptHidden(question, opts = {}) {
33292
33304
  input.setRawMode(false);
33293
33305
  input.removeListener("data", onData);
33294
33306
  process.stdout.write("\n");
33295
- resolve81(value);
33307
+ resolve83(value);
33296
33308
  } else if (char === "") {
33297
33309
  input.setRawMode(false);
33298
33310
  process.stdout.write("\n");
@@ -33318,7 +33330,7 @@ async function promptHidden(question, opts = {}) {
33318
33330
  const rl = createInterface2({ input, output: process.stdout });
33319
33331
  rl.question(question, (answer) => {
33320
33332
  rl.close();
33321
- resolve81(answer);
33333
+ resolve83(answer);
33322
33334
  });
33323
33335
  }
33324
33336
  });
@@ -33326,7 +33338,7 @@ async function promptHidden(question, opts = {}) {
33326
33338
  async function promptSelect(_question, options, defaultIndex = 0, opts = {}) {
33327
33339
  const input = getTTYInputStream();
33328
33340
  if (typeof input.setRawMode === "function") {
33329
- return new Promise((resolve81) => {
33341
+ return new Promise((resolve83) => {
33330
33342
  let selected = defaultIndex;
33331
33343
  const render = () => {
33332
33344
  if (renderCount > 0) {
@@ -33354,7 +33366,7 @@ async function promptSelect(_question, options, defaultIndex = 0, opts = {}) {
33354
33366
  input.setRawMode(false);
33355
33367
  input.removeListener("data", onData);
33356
33368
  process.stdout.write("\n");
33357
- resolve81(selected);
33369
+ resolve83(selected);
33358
33370
  } else if (char === "") {
33359
33371
  input.setRawMode(false);
33360
33372
  process.stdout.write("\n");
@@ -33364,7 +33376,7 @@ async function promptSelect(_question, options, defaultIndex = 0, opts = {}) {
33364
33376
  input.setRawMode(false);
33365
33377
  input.removeListener("data", onData);
33366
33378
  process.stdout.write("\n");
33367
- resolve81(opts.backIndex);
33379
+ resolve83(opts.backIndex);
33368
33380
  } else if (char === "\x1B[A" || char === "k") {
33369
33381
  selected = (selected - 1 + options.length) % options.length;
33370
33382
  render();
@@ -33378,7 +33390,7 @@ async function promptSelect(_question, options, defaultIndex = 0, opts = {}) {
33378
33390
  input.removeListener("data", onData);
33379
33391
  render();
33380
33392
  process.stdout.write("\n");
33381
- resolve81(selected);
33393
+ resolve83(selected);
33382
33394
  }
33383
33395
  };
33384
33396
  const onData = (chunk) => {
@@ -33402,7 +33414,7 @@ async function promptSelect(_question, options, defaultIndex = 0, opts = {}) {
33402
33414
  async function promptConfirm(question, defaultYes = true) {
33403
33415
  const input = getTTYInputStream();
33404
33416
  if (typeof input.setRawMode === "function") {
33405
- return new Promise((resolve81) => {
33417
+ return new Promise((resolve83) => {
33406
33418
  const options = ["Yes", "No"];
33407
33419
  let selected = defaultYes ? 0 : 1;
33408
33420
  let renderCount = 0;
@@ -33432,7 +33444,7 @@ async function promptConfirm(question, defaultYes = true) {
33432
33444
  finished = true;
33433
33445
  input.setRawMode(false);
33434
33446
  input.removeListener("data", onData);
33435
- resolve81(selected === 0);
33447
+ resolve83(selected === 0);
33436
33448
  } else if (char === "") {
33437
33449
  input.setRawMode(false);
33438
33450
  process.stdout.write("\n");
@@ -33446,14 +33458,14 @@ async function promptConfirm(question, defaultYes = true) {
33446
33458
  input.setRawMode(false);
33447
33459
  input.removeListener("data", onData);
33448
33460
  render();
33449
- resolve81(true);
33461
+ resolve83(true);
33450
33462
  } else if (char === "n" || char === "N") {
33451
33463
  selected = 1;
33452
33464
  finished = true;
33453
33465
  input.setRawMode(false);
33454
33466
  input.removeListener("data", onData);
33455
33467
  render();
33456
- resolve81(false);
33468
+ resolve83(false);
33457
33469
  }
33458
33470
  };
33459
33471
  const onData = (chunk) => {
@@ -33472,7 +33484,7 @@ async function promptMultiSelect(_question, options, defaultSelected = [], opts
33472
33484
  const input = getTTYInputStream();
33473
33485
  const selected = options.map((_, i) => Boolean(defaultSelected[i]));
33474
33486
  if (typeof input.setRawMode === "function") {
33475
- return new Promise((resolve81) => {
33487
+ return new Promise((resolve83) => {
33476
33488
  let cursor = 0;
33477
33489
  let renderCount = 0;
33478
33490
  let userToggled = false;
@@ -33502,7 +33514,7 @@ async function promptMultiSelect(_question, options, defaultSelected = [], opts
33502
33514
  for (let i = 0; i < selected.length; i++) {
33503
33515
  if (selected[i]) result.push(i);
33504
33516
  }
33505
- resolve81(result);
33517
+ resolve83(result);
33506
33518
  };
33507
33519
  let finished = false;
33508
33520
  const handleChar = (char) => {
@@ -33816,7 +33828,7 @@ var init_speech = __esm({
33816
33828
  import { writeFile as writeFile19, unlink, rename } from "node:fs/promises";
33817
33829
  import { resolve as resolve22, basename as basename4 } from "node:path";
33818
33830
  function sleep2(ms) {
33819
- return new Promise((resolve81) => setTimeout(resolve81, ms));
33831
+ return new Promise((resolve83) => setTimeout(resolve83, ms));
33820
33832
  }
33821
33833
  async function uploadToImgbb(imageBuffer, apiKey) {
33822
33834
  try {
@@ -35506,7 +35518,7 @@ function unique(items) {
35506
35518
  ];
35507
35519
  }
35508
35520
  function sleep3(ms) {
35509
- return new Promise((resolve81) => setTimeout(resolve81, ms));
35521
+ return new Promise((resolve83) => setTimeout(resolve83, ms));
35510
35522
  }
35511
35523
  var init_status_jobs = __esm({
35512
35524
  "src/commands/_shared/status-jobs.ts"() {
@@ -36015,20 +36027,20 @@ async function executeThumbnailBestFrame(options) {
36015
36027
  if (!jsonMatch) {
36016
36028
  return { success: false, error: `Could not parse timestamp from Gemini response: ${result.response.slice(0, 200)}` };
36017
36029
  }
36018
- const timestamp = parseFloat(jsonMatch[1]);
36030
+ const timestamp2 = parseFloat(jsonMatch[1]);
36019
36031
  let reason;
36020
36032
  const reasonMatch = result.response.match(/"reason"\s*:\s*"([^"]+)"/);
36021
36033
  if (reasonMatch) {
36022
36034
  reason = reasonMatch[1];
36023
36035
  }
36024
- await execSafe("ffmpeg", ["-ss", String(timestamp), "-i", videoPath, "-frames:v", "1", "-q:v", "2", outputPath, "-y"], { timeout: 6e4, maxBuffer: 50 * 1024 * 1024 });
36036
+ await execSafe("ffmpeg", ["-ss", String(timestamp2), "-i", videoPath, "-frames:v", "1", "-q:v", "2", outputPath, "-y"], { timeout: 6e4, maxBuffer: 50 * 1024 * 1024 });
36025
36037
  if (!existsSync16(outputPath)) {
36026
36038
  return { success: false, error: "FFmpeg failed to extract frame" };
36027
36039
  }
36028
36040
  return {
36029
36041
  success: true,
36030
36042
  outputPath,
36031
- timestamp,
36043
+ timestamp: timestamp2,
36032
36044
  reason
36033
36045
  };
36034
36046
  } catch (error) {
@@ -39557,8 +39569,8 @@ function parseSRT(content) {
39557
39569
  }
39558
39570
  return segments;
39559
39571
  }
39560
- function parseSRTTimestamp(timestamp) {
39561
- const normalized = timestamp.replace(",", ".");
39572
+ function parseSRTTimestamp(timestamp2) {
39573
+ const normalized = timestamp2.replace(",", ".");
39562
39574
  const parts = normalized.split(":");
39563
39575
  const hours = parseInt(parts[0], 10);
39564
39576
  const mins = parseInt(parts[1], 10);
@@ -47096,6 +47108,7 @@ var init_product_surface = __esm({
47096
47108
  build: { surface: "public", note: "Primary storyboard-to-video build engine." },
47097
47109
  render: { surface: "public", note: "Project render entrypoint." },
47098
47110
  doctor: { surface: "public", note: "System and provider health check." },
47111
+ host: { surface: "public", note: "Codex, Claude, and Cursor app integration setup." },
47099
47112
  guide: { surface: "public", note: "Workflow chooser and first-run guidance." },
47100
47113
  demo: { surface: "advanced", note: "Smoke-test/demo helper, not a core workflow." },
47101
47114
  run: { surface: "agent", note: "Automation surface for YAML pipelines." },
@@ -50855,11 +50868,11 @@ var init_FrameParser = __esm({
50855
50868
  const nullStr = _FrameParser.readNullTerminatedString(uint8Array, syltHeader.encoding);
50856
50869
  uint8Array = uint8Array.subarray(nullStr.len);
50857
50870
  if (readSyllables) {
50858
- const timestamp = UINT32_BE.get(uint8Array, 0);
50871
+ const timestamp2 = UINT32_BE.get(uint8Array, 0);
50859
50872
  uint8Array = uint8Array.subarray(UINT32_BE.len);
50860
50873
  result.syncText.push({
50861
50874
  text: nullStr.text,
50862
- timestamp
50875
+ timestamp: timestamp2
50863
50876
  });
50864
50877
  } else {
50865
50878
  result.descriptor = nullStr.text;
@@ -56854,8 +56867,8 @@ var init_detect = __esm({
56854
56867
  let match;
56855
56868
  scenes.push({ timestamp: 0, score: 1 });
56856
56869
  while ((match = regex2.exec(output)) !== null) {
56857
- const timestamp = parseFloat(match[1]);
56858
- scenes.push({ timestamp, score: threshold });
56870
+ const timestamp2 = parseFloat(match[1]);
56871
+ scenes.push({ timestamp: timestamp2, score: threshold });
56859
56872
  }
56860
56873
  const totalDuration = await ffprobeDuration(absPath);
56861
56874
  spinner2.succeed(source_default.green(`Detected ${scenes.length} scenes`));
@@ -58464,14 +58477,14 @@ var init_adapters = __esm({
58464
58477
  });
58465
58478
 
58466
58479
  // src/commands/_shared/storyboard-revise.ts
58467
- import { existsSync as existsSync41 } from "node:fs";
58468
- import { readFile as readFile38, writeFile as writeFile45 } from "node:fs/promises";
58469
- import { join as join19, resolve as resolve54 } from "node:path";
58480
+ import { existsSync as existsSync42 } from "node:fs";
58481
+ import { readFile as readFile39, writeFile as writeFile46 } from "node:fs/promises";
58482
+ import { join as join20, resolve as resolve55 } from "node:path";
58470
58483
  async function executeStoryboardRevision(opts) {
58471
- const projectDir = resolve54(opts.projectDir);
58472
- const storyboardPath2 = join19(projectDir, "STORYBOARD.md");
58484
+ const projectDir = resolve55(opts.projectDir);
58485
+ const storyboardPath2 = join20(projectDir, "STORYBOARD.md");
58473
58486
  const retryWith = [`vibe storyboard revise ${projectDir} --from "<request>" --dry-run --json`];
58474
- if (!existsSync41(storyboardPath2)) {
58487
+ if (!existsSync42(storyboardPath2)) {
58475
58488
  return failureResult({
58476
58489
  projectDir,
58477
58490
  storyboardPath: storyboardPath2,
@@ -58481,7 +58494,7 @@ async function executeStoryboardRevision(opts) {
58481
58494
  retryWith: [`vibe init ${projectDir} --from "<brief>" --json`]
58482
58495
  });
58483
58496
  }
58484
- const currentStoryboard = await readFile38(storyboardPath2, "utf-8");
58497
+ const currentStoryboard = await readFile39(storyboardPath2, "utf-8");
58485
58498
  const projectConfig = await readProjectConfig(projectDir);
58486
58499
  const explicitComposer = opts.composer ?? projectConfig.config.providers.composer ?? void 0;
58487
58500
  let provider = explicitComposer ?? "claude";
@@ -58580,7 +58593,7 @@ async function executeStoryboardRevision(opts) {
58580
58593
  }
58581
58594
  const storyboardMd = normalizeMarkdown(payload.storyboardMd);
58582
58595
  if (!opts.dryRun) {
58583
- await writeFile45(storyboardPath2, storyboardMd, "utf-8");
58596
+ await writeFile46(storyboardPath2, storyboardMd, "utf-8");
58584
58597
  }
58585
58598
  const changedBeats = unique2([...diffChangedBeats(currentStoryboard, storyboardMd), ...payload.changedBeats]);
58586
58599
  return stripUndefined3({
@@ -58703,18 +58716,18 @@ function diffChangedBeats(before, after) {
58703
58716
  return ids.filter((id) => JSON.stringify(beforeBeats.get(id) ?? null) !== JSON.stringify(afterBeats.get(id) ?? null));
58704
58717
  }
58705
58718
  async function readRevisionContext(projectDir) {
58706
- const designMd = await readOptionalText(join19(projectDir, "DESIGN.md"));
58707
- const buildReportJson = await readOptionalJsonText(join19(projectDir, "build-report.json"));
58719
+ const designMd = await readOptionalText(join20(projectDir, "DESIGN.md"));
58720
+ const buildReportJson = await readOptionalJsonText(join20(projectDir, "build-report.json"));
58708
58721
  return { designMd, buildReportJson };
58709
58722
  }
58710
58723
  async function readOptionalText(path2) {
58711
- if (!existsSync41(path2)) return null;
58712
- return readFile38(path2, "utf-8");
58724
+ if (!existsSync42(path2)) return null;
58725
+ return readFile39(path2, "utf-8");
58713
58726
  }
58714
58727
  async function readOptionalJsonText(path2) {
58715
- if (!existsSync41(path2)) return null;
58728
+ if (!existsSync42(path2)) return null;
58716
58729
  try {
58717
- const parsed = JSON.parse(await readFile38(path2, "utf-8"));
58730
+ const parsed = JSON.parse(await readFile39(path2, "utf-8"));
58718
58731
  return JSON.stringify(parsed, null, 2);
58719
58732
  } catch {
58720
58733
  return null;
@@ -58762,8 +58775,8 @@ var init_storyboard_revise = __esm({
58762
58775
  });
58763
58776
 
58764
58777
  // src/commands/_shared/build-asset-reference.ts
58765
- import { existsSync as existsSync43 } from "node:fs";
58766
- import { extname as extname13, isAbsolute as isAbsolute5, relative as relative10, resolve as resolve56, sep } from "node:path";
58778
+ import { existsSync as existsSync44 } from "node:fs";
58779
+ import { extname as extname13, isAbsolute as isAbsolute5, relative as relative10, resolve as resolve57, sep } from "node:path";
58767
58780
  function resolveTypedAssetReference(projectDir, kind, value) {
58768
58781
  const raw = stringOrUndefined2(value);
58769
58782
  if (!raw || !looksLikeAssetPath(raw)) return null;
@@ -58790,10 +58803,10 @@ function isReadyAssetReference(reference) {
58790
58803
  function resolveReference(projectDir, kind, raw, source, forcedError) {
58791
58804
  const ext = extname13(raw).toLowerCase();
58792
58805
  const inferred = inferAssetKind(raw);
58793
- const absPath = isAbsolute5(raw) ? resolve56(raw) : resolve56(projectDir, raw);
58794
- const rel = relative10(resolve56(projectDir), absPath);
58806
+ const absPath = isAbsolute5(raw) ? resolve57(raw) : resolve57(projectDir, raw);
58807
+ const rel = relative10(resolve57(projectDir), absPath);
58795
58808
  const withinProject = rel.length > 0 && !rel.startsWith("..") && !isAbsolute5(rel);
58796
- const exists = withinProject && existsSync43(absPath);
58809
+ const exists = withinProject && existsSync44(absPath);
58797
58810
  let error = forcedError;
58798
58811
  if (!error && inferred && inferred !== kind && !isNarrationAudioReference(kind, ext)) {
58799
58812
  error = `Asset reference "${raw}" is a ${inferred} asset, not ${kind}.`;
@@ -58952,19 +58965,19 @@ var init_build_backdrop_prompt = __esm({
58952
58965
  });
58953
58966
 
58954
58967
  // src/commands/_shared/build-plan.ts
58955
- import { existsSync as existsSync44 } from "node:fs";
58956
- import { readFile as readFile40 } from "node:fs/promises";
58957
- import { dirname as dirname19, join as join20, resolve as resolve57 } from "node:path";
58968
+ import { existsSync as existsSync45 } from "node:fs";
58969
+ import { readFile as readFile41 } from "node:fs/promises";
58970
+ import { dirname as dirname20, join as join21, resolve as resolve58 } from "node:path";
58958
58971
  async function createBuildPlan(opts) {
58959
- const projectDir = resolve57(opts.projectDir);
58972
+ const projectDir = resolve58(opts.projectDir);
58960
58973
  loadPlanEnv(projectDir);
58961
58974
  const stage = opts.stage ?? "all";
58962
58975
  const config2 = await readProjectConfig(projectDir);
58963
- const storyboardPath2 = join20(projectDir, "STORYBOARD.md");
58976
+ const storyboardPath2 = join21(projectDir, "STORYBOARD.md");
58964
58977
  const warnings = [];
58965
58978
  const retryWith = [];
58966
58979
  const providerResolution = [];
58967
- if (!existsSync44(storyboardPath2)) {
58980
+ if (!existsSync45(storyboardPath2)) {
58968
58981
  const validation2 = {
58969
58982
  ok: false,
58970
58983
  issues: [
@@ -58993,7 +59006,7 @@ async function createBuildPlan(opts) {
58993
59006
  validation: validation2
58994
59007
  });
58995
59008
  }
58996
- const storyboardMd = await readFile40(storyboardPath2, "utf-8");
59009
+ const storyboardMd = await readFile41(storyboardPath2, "utf-8");
58997
59010
  const validation = validateStoryboardMarkdown(storyboardMd);
58998
59011
  const validationIssues = [...validation.issues];
58999
59012
  const parsed = parseStoryboard(storyboardMd);
@@ -59019,7 +59032,7 @@ async function createBuildPlan(opts) {
59019
59032
  const imageQuality = opts.imageQuality ?? config2.config.build.imageQuality ?? "hd";
59020
59033
  const imageSize2 = opts.imageSize ?? config2.config.build.imageSize ?? "1536x1024";
59021
59034
  const imageRatio = imageRatioForSize(imageSize2);
59022
- const needsComposer = includeCompose && mode !== "agent" && sourceBeats.some((beat) => !existsSync44(join20(projectDir, `compositions/scene-${beat.id}.html`)));
59035
+ const needsComposer = includeCompose && mode !== "agent" && sourceBeats.some((beat) => !existsSync45(join21(projectDir, `compositions/scene-${beat.id}.html`)));
59023
59036
  const resolved = await resolvePlanProviders({
59024
59037
  projectDir,
59025
59038
  config: config2,
@@ -59140,7 +59153,7 @@ async function createBuildPlan(opts) {
59140
59153
  active: includeAssets
59141
59154
  }) : null;
59142
59155
  const compositionPath = `compositions/scene-${beat.id}.html`;
59143
- const compositionExists = existsSync44(join20(projectDir, compositionPath));
59156
+ const compositionExists = existsSync45(join21(projectDir, compositionPath));
59144
59157
  for (const asset of [narration, backdrop, video, music]) {
59145
59158
  if (!asset) continue;
59146
59159
  if (asset.referenceError) {
@@ -59207,7 +59220,7 @@ async function createBuildPlan(opts) {
59207
59220
  }
59208
59221
  }
59209
59222
  const validationOk = !validationIssues.some((issue) => issue.severity === "error");
59210
- if (!existsSync44(join20(projectDir, config2.config.composition.entry))) {
59223
+ if (!existsSync45(join21(projectDir, config2.config.composition.entry))) {
59211
59224
  missing.add("root-composition");
59212
59225
  if (validationOk) retryWith.push(`vibe build ${projectDir} --stage sync --json`);
59213
59226
  }
@@ -59339,8 +59352,8 @@ function assetPlan(opts) {
59339
59352
  reason: ready ? "referenced-asset" : "invalid-reference"
59340
59353
  };
59341
59354
  }
59342
- const canonicalExists = existsSync44(join20(opts.projectDir, opts.path));
59343
- const cacheHit = opts.cache ? existsSync44(join20(opts.projectDir, opts.cache.path)) : false;
59355
+ const canonicalExists = existsSync45(join21(opts.projectDir, opts.path));
59356
+ const cacheHit = opts.cache ? existsSync45(join21(opts.projectDir, opts.cache.path)) : false;
59344
59357
  const freshness = assetFreshnessFromMetadata({
59345
59358
  projectDir: opts.projectDir,
59346
59359
  kind: opts.kind,
@@ -59534,7 +59547,7 @@ async function firstConfiguredComposer(projectDir) {
59534
59547
  }
59535
59548
  function firstExisting2(projectDir, paths) {
59536
59549
  for (const path2 of paths) {
59537
- if (existsSync44(join20(projectDir, path2))) return path2;
59550
+ if (existsSync45(join21(projectDir, path2))) return path2;
59538
59551
  }
59539
59552
  return null;
59540
59553
  }
@@ -59575,15 +59588,15 @@ function unique3(items) {
59575
59588
  return [...new Set(items.filter((item) => item.length > 0))];
59576
59589
  }
59577
59590
  function loadPlanEnv(projectDir) {
59578
- (0, import_dotenv3.config)({ path: join20(projectDir, ".env"), quiet: true });
59579
- (0, import_dotenv3.config)({ path: resolve57(process.cwd(), ".env"), quiet: true });
59591
+ (0, import_dotenv3.config)({ path: join21(projectDir, ".env"), quiet: true });
59592
+ (0, import_dotenv3.config)({ path: resolve58(process.cwd(), ".env"), quiet: true });
59580
59593
  let dir = process.cwd();
59581
- while (dir !== dirname19(dir)) {
59582
- if (existsSync44(join20(dir, "pnpm-workspace.yaml"))) {
59583
- (0, import_dotenv3.config)({ path: join20(dir, ".env"), quiet: true });
59594
+ while (dir !== dirname20(dir)) {
59595
+ if (existsSync45(join21(dir, "pnpm-workspace.yaml"))) {
59596
+ (0, import_dotenv3.config)({ path: join21(dir, ".env"), quiet: true });
59584
59597
  return;
59585
59598
  }
59586
- dir = dirname19(dir);
59599
+ dir = dirname20(dir);
59587
59600
  }
59588
59601
  }
59589
59602
  var import_dotenv3, BACKDROP_COST_USD, VIDEO_COST_USD, MUSIC_COST_USD, ELEVENLABS_NARRATION_COST_USD, COMPOSE_COST_USD, SUPPORTED_BUILD_IMAGE_PROVIDERS;
@@ -59611,8 +59624,8 @@ var init_build_plan = __esm({
59611
59624
  });
59612
59625
 
59613
59626
  // src/commands/_shared/scene-audio-scan.ts
59614
- import { readFile as readFile41 } from "node:fs/promises";
59615
- import { resolve as resolve59 } from "node:path";
59627
+ import { readFile as readFile42 } from "node:fs/promises";
59628
+ import { resolve as resolve60 } from "node:path";
59616
59629
  function parseRootClips(rootHtml) {
59617
59630
  const clips = [];
59618
59631
  const clipRegex = /<div\b[^>]*class="clip"[^>]*>/gi;
@@ -59650,9 +59663,9 @@ function parseSceneAudios(compositionHtml) {
59650
59663
  }
59651
59664
  function makeFsCompositionReader(projectDir) {
59652
59665
  return async (compositionSrcRel) => {
59653
- const abs = resolve59(projectDir, compositionSrcRel);
59666
+ const abs = resolve60(projectDir, compositionSrcRel);
59654
59667
  try {
59655
- return await readFile41(abs, "utf-8");
59668
+ return await readFile42(abs, "utf-8");
59656
59669
  } catch {
59657
59670
  return null;
59658
59671
  }
@@ -59669,7 +59682,7 @@ async function scanSceneAudio(opts) {
59669
59682
  for (const audio of audios) {
59670
59683
  out.push({
59671
59684
  srcRel: audio.srcRel,
59672
- srcAbs: resolve59(opts.projectDir, audio.srcRel),
59685
+ srcAbs: resolve60(opts.projectDir, audio.srcRel),
59673
59686
  absoluteStart: clip.start + audio.localStart,
59674
59687
  durationHint: audio.durationHint,
59675
59688
  clipDurationCap: clip.duration - audio.localStart,
@@ -59684,7 +59697,7 @@ async function scanSceneAudio(opts) {
59684
59697
  for (const audio of rootAudios) {
59685
59698
  out.push({
59686
59699
  srcRel: audio.srcRel,
59687
- srcAbs: resolve59(opts.projectDir, audio.srcRel),
59700
+ srcAbs: resolve60(opts.projectDir, audio.srcRel),
59688
59701
  absoluteStart: audio.localStart,
59689
59702
  durationHint: audio.durationHint,
59690
59703
  clipDurationCap: Math.max(0, maxClipEnd - audio.localStart),
@@ -59719,7 +59732,7 @@ var init_scene_audio_scan = __esm({
59719
59732
 
59720
59733
  // src/commands/_shared/scene-audio-mux.ts
59721
59734
  import { rename as rename4, unlink as unlink3 } from "node:fs/promises";
59722
- import { resolve as resolve60, dirname as dirname20, extname as extname14, basename as basename20 } from "node:path";
59735
+ import { resolve as resolve61, dirname as dirname21, extname as extname14, basename as basename20 } from "node:path";
59723
59736
  function buildAudioMuxFilter(audios) {
59724
59737
  if (audios.length === 0) return null;
59725
59738
  const labels = [];
@@ -59779,8 +59792,8 @@ async function muxAudioIntoVideo(opts) {
59779
59792
  return { success: true, outputPath: opts.videoPath, audioCount: 0 };
59780
59793
  }
59781
59794
  const ext = extname14(opts.videoPath) || `.${opts.format}`;
59782
- const tmpPath = resolve60(
59783
- dirname20(opts.videoPath),
59795
+ const tmpPath = resolve61(
59796
+ dirname21(opts.videoPath),
59784
59797
  `.${basename20(opts.videoPath, ext)}.muxing${ext}`
59785
59798
  );
59786
59799
  const args = ["-y", "-loglevel", "error", "-i", opts.videoPath];
@@ -59850,9 +59863,9 @@ __export(scene_render_exports, {
59850
59863
  prepareBeatRenderRoot: () => prepareBeatRenderRoot,
59851
59864
  qualityToCrf: () => qualityToCrf2
59852
59865
  });
59853
- import { existsSync as existsSync45 } from "node:fs";
59854
- import { mkdir as mkdir23, readFile as readFile42, stat as stat8, writeFile as writeFile47 } from "node:fs/promises";
59855
- import { resolve as resolve61, relative as relative11, dirname as dirname21, basename as basename21, join as join21, isAbsolute as isAbsolute6 } from "node:path";
59866
+ import { existsSync as existsSync46 } from "node:fs";
59867
+ import { mkdir as mkdir24, readFile as readFile43, stat as stat8, writeFile as writeFile48 } from "node:fs/promises";
59868
+ import { resolve as resolve62, relative as relative11, dirname as dirname22, basename as basename21, join as join22, isAbsolute as isAbsolute6 } from "node:path";
59856
59869
  import {
59857
59870
  createRenderJob,
59858
59871
  executeRenderJob
@@ -59864,9 +59877,9 @@ function defaultOutputPath(opts) {
59864
59877
  const fmt = opts.format ?? "mp4";
59865
59878
  const now = opts.now ?? /* @__PURE__ */ new Date();
59866
59879
  const stamp = now.toISOString().replace(/[:T]/g, "-").replace(/\..+$/, "");
59867
- const name = (opts.projectName ?? basename21(resolve61(opts.projectDir))) || "scene";
59880
+ const name = (opts.projectName ?? basename21(resolve62(opts.projectDir))) || "scene";
59868
59881
  const beat = opts.beatId ? `-${sanitizeFileSegment2(opts.beatId)}` : "";
59869
- return resolve61(opts.projectDir, "renders", `${name}${beat}-${stamp}.${fmt}`);
59882
+ return resolve62(opts.projectDir, "renders", `${name}${beat}-${stamp}.${fmt}`);
59870
59883
  }
59871
59884
  function buildRenderConfig(opts) {
59872
59885
  const quality = opts.quality ?? "standard";
@@ -59880,7 +59893,7 @@ function buildRenderConfig(opts) {
59880
59893
  };
59881
59894
  }
59882
59895
  async function executeSceneRender(opts = {}) {
59883
- const projectDir = resolve61(opts.projectDir ?? ".");
59896
+ const projectDir = resolve62(opts.projectDir ?? ".");
59884
59897
  const projectConfig = await readProjectConfig(projectDir);
59885
59898
  const engine = projectConfig.config.composition.engine;
59886
59899
  if (engine !== "hyperframes") {
@@ -59926,7 +59939,7 @@ async function executeSceneRender(opts = {}) {
59926
59939
  kind: "render",
59927
59940
  beat: opts.beatId ?? null,
59928
59941
  root,
59929
- error: `Root composition not found: ${resolve61(projectDir, root)}. Run \`vibe scene init\` first.`
59942
+ error: `Root composition not found: ${resolve62(projectDir, root)}. Run \`vibe scene init\` first.`
59930
59943
  };
59931
59944
  }
59932
59945
  const chrome = await preflightChrome();
@@ -59940,8 +59953,8 @@ async function executeSceneRender(opts = {}) {
59940
59953
  };
59941
59954
  }
59942
59955
  const projectName = projectConfig.config.name;
59943
- const outputPath = opts.output ? resolve61(projectDir, opts.output) : defaultOutputPath({ projectDir, projectName, format: opts.format, beatId: opts.beatId });
59944
- await mkdir23(dirname21(outputPath), { recursive: true });
59956
+ const outputPath = opts.output ? resolve62(projectDir, opts.output) : defaultOutputPath({ projectDir, projectName, format: opts.format, beatId: opts.beatId });
59957
+ await mkdir24(dirname22(outputPath), { recursive: true });
59945
59958
  const config2 = buildRenderConfig({
59946
59959
  fps: opts.fps,
59947
59960
  quality: opts.quality,
@@ -59973,7 +59986,7 @@ async function executeSceneRender(opts = {}) {
59973
59986
  let audioMuxWarning;
59974
59987
  try {
59975
59988
  opts.onProgress?.(0.95, "Mixing audio");
59976
- const rootHtml = await readFile42(resolve61(projectDir, root), "utf-8");
59989
+ const rootHtml = await readFile43(resolve62(projectDir, root), "utf-8");
59977
59990
  const audios = await scanSceneAudio({ projectDir, rootHtml });
59978
59991
  audioCount = audios.length;
59979
59992
  if (audios.length > 0) {
@@ -60027,11 +60040,11 @@ async function safeStat(p) {
60027
60040
  }
60028
60041
  async function prepareBeatRenderRoot(opts) {
60029
60042
  const root = `.vibeframe/tmp/render-beat-${sanitizeFileSegment2(opts.beatId)}.html`;
60030
- const reportPath = join21(opts.projectDir, "build-report.json");
60043
+ const reportPath = join22(opts.projectDir, "build-report.json");
60031
60044
  const retryWith = [
60032
60045
  `vibe build ${opts.projectDir} --beat ${opts.beatId} --stage sync --json`
60033
60046
  ];
60034
- if (!existsSync45(reportPath)) {
60047
+ if (!existsSync46(reportPath)) {
60035
60048
  return {
60036
60049
  success: false,
60037
60050
  root,
@@ -60042,7 +60055,7 @@ async function prepareBeatRenderRoot(opts) {
60042
60055
  }
60043
60056
  let report;
60044
60057
  try {
60045
- report = JSON.parse(await readFile42(reportPath, "utf-8"));
60058
+ report = JSON.parse(await readFile43(reportPath, "utf-8"));
60046
60059
  } catch (error) {
60047
60060
  return {
60048
60061
  success: false,
@@ -60111,8 +60124,8 @@ async function prepareBeatRenderRoot(opts) {
60111
60124
  durationSec,
60112
60125
  narrationPath
60113
60126
  });
60114
- await mkdir23(dirname21(join21(opts.projectDir, root)), { recursive: true });
60115
- await writeFile47(join21(opts.projectDir, root), html, "utf-8");
60127
+ await mkdir24(dirname22(join22(opts.projectDir, root)), { recursive: true });
60128
+ await writeFile48(join22(opts.projectDir, root), html, "utf-8");
60116
60129
  return {
60117
60130
  success: true,
60118
60131
  root,
@@ -60176,9 +60189,9 @@ function reportedBeatAssetPaths(beat) {
60176
60189
  ]);
60177
60190
  }
60178
60191
  async function writeRenderReport(projectDir, result) {
60179
- const reportPath = join21(projectDir, "render-report.json");
60192
+ const reportPath = join22(projectDir, "render-report.json");
60180
60193
  try {
60181
- await writeFile47(
60194
+ await writeFile48(
60182
60195
  reportPath,
60183
60196
  JSON.stringify(
60184
60197
  {
@@ -60210,8 +60223,8 @@ async function writeRenderReport(projectDir, result) {
60210
60223
  }
60211
60224
  }
60212
60225
  function pathExists3(projectDir, value) {
60213
- const abs = isAbsolute6(value) ? value : resolve61(projectDir, value);
60214
- return existsSync45(abs);
60226
+ const abs = isAbsolute6(value) ? value : resolve62(projectDir, value);
60227
+ return existsSync46(abs);
60215
60228
  }
60216
60229
  function stringValue(value) {
60217
60230
  return typeof value === "string" && value.length > 0 ? value : void 0;
@@ -60264,12 +60277,12 @@ __export(scene_build_exports, {
60264
60277
  executeSceneBuild: () => executeSceneBuild,
60265
60278
  resolveSceneBuildMode: () => resolveSceneBuildMode
60266
60279
  });
60267
- import { existsSync as existsSync46 } from "node:fs";
60268
- import { copyFile as copyFile5, mkdir as mkdir24, readFile as readFile43, writeFile as writeFile48 } from "node:fs/promises";
60269
- import { dirname as dirname22, join as join22, resolve as resolve62 } from "node:path";
60280
+ import { existsSync as existsSync47 } from "node:fs";
60281
+ import { copyFile as copyFile5, mkdir as mkdir25, readFile as readFile44, writeFile as writeFile49 } from "node:fs/promises";
60282
+ import { dirname as dirname23, join as join23, resolve as resolve63 } from "node:path";
60270
60283
  async function executeSceneBuild(opts) {
60271
60284
  const startedAt = Date.now();
60272
- const projectDir = resolve62(opts.projectDir);
60285
+ const projectDir = resolve63(opts.projectDir);
60273
60286
  const onProgress = opts.onProgress ?? (() => {
60274
60287
  });
60275
60288
  const mode = resolveSceneBuildMode(opts);
@@ -60278,7 +60291,7 @@ async function executeSceneBuild(opts) {
60278
60291
  const warnings = [];
60279
60292
  const retryWith = [];
60280
60293
  let sceneRepair = skippedSceneRepairSummary();
60281
- const storyboardPath2 = join22(projectDir, "STORYBOARD.md");
60294
+ const storyboardPath2 = join23(projectDir, "STORYBOARD.md");
60282
60295
  const buildPlan = await createBuildPlan({
60283
60296
  projectDir,
60284
60297
  stage: selectedStage,
@@ -60306,8 +60319,8 @@ async function executeSceneBuild(opts) {
60306
60319
  });
60307
60320
  if (!buildPlan.validation.ok) {
60308
60321
  let invalidBeats = [];
60309
- if (existsSync46(storyboardPath2)) {
60310
- invalidBeats = parseStoryboard(await readFile43(storyboardPath2, "utf-8")).beats;
60322
+ if (existsSync47(storyboardPath2)) {
60323
+ invalidBeats = parseStoryboard(await readFile44(storyboardPath2, "utf-8")).beats;
60311
60324
  }
60312
60325
  return finishBuildResult({
60313
60326
  success: false,
@@ -60331,7 +60344,7 @@ async function executeSceneBuild(opts) {
60331
60344
  totalLatencyMs: Date.now() - startedAt
60332
60345
  });
60333
60346
  }
60334
- if (!existsSync46(storyboardPath2)) {
60347
+ if (!existsSync47(storyboardPath2)) {
60335
60348
  return finishBuildResult({
60336
60349
  success: false,
60337
60350
  phase: "failed",
@@ -60345,7 +60358,7 @@ async function executeSceneBuild(opts) {
60345
60358
  totalLatencyMs: Date.now() - startedAt
60346
60359
  });
60347
60360
  }
60348
- const storyboardMd = await readFile43(storyboardPath2, "utf-8");
60361
+ const storyboardMd = await readFile44(storyboardPath2, "utf-8");
60349
60362
  const parsed = parseStoryboard(storyboardMd);
60350
60363
  if (parsed.beats.length === 0) {
60351
60364
  return finishBuildResult({
@@ -60513,9 +60526,9 @@ async function executeSceneBuild(opts) {
60513
60526
  let composeData;
60514
60527
  if (shouldRunStage(selectedStage, "compose")) {
60515
60528
  if (mode === "agent") {
60516
- const compositionsDir = join22(projectDir, "compositions");
60529
+ const compositionsDir = join23(projectDir, "compositions");
60517
60530
  const missingBeats = activeBeats.filter(
60518
- (b) => !existsSync46(join22(compositionsDir, `scene-${b.id}.html`))
60531
+ (b) => !existsSync47(join23(compositionsDir, `scene-${b.id}.html`))
60519
60532
  );
60520
60533
  if (missingBeats.length > 0) {
60521
60534
  const plan = await getComposePrompts({ projectDir, beatId: opts.beatId });
@@ -60651,7 +60664,7 @@ async function executeSceneBuild(opts) {
60651
60664
  });
60652
60665
  }
60653
60666
  if (shouldRunStage(selectedStage, "sync")) {
60654
- if (!existsSync46(join22(projectDir, "index.html"))) {
60667
+ if (!existsSync47(join23(projectDir, "index.html"))) {
60655
60668
  await scaffoldSceneProject({
60656
60669
  dir: projectDir,
60657
60670
  name: projectDir.split(/[\\/]/).filter(Boolean).pop(),
@@ -60910,7 +60923,7 @@ async function dispatchNarration(beat, ctx) {
60910
60923
  return {
60911
60924
  status: "cached",
60912
60925
  path: existingRel,
60913
- durationSec: await safeAudioDuration(join22(ctx.projectDir, existingRel)),
60926
+ durationSec: await safeAudioDuration(join23(ctx.projectDir, existingRel)),
60914
60927
  provider: metadata?.provider,
60915
60928
  cachePath: metadata?.cachePath,
60916
60929
  cacheKey: metadata?.cacheKey,
@@ -60934,9 +60947,9 @@ async function dispatchNarration(beat, ctx) {
60934
60947
  voice,
60935
60948
  ext: resolution.audioExtension
60936
60949
  });
60937
- const cacheAbs = join22(ctx.projectDir, cache.path);
60950
+ const cacheAbs = join23(ctx.projectDir, cache.path);
60938
60951
  const rel = `assets/narration-${beat.id}.${resolution.audioExtension}`;
60939
- const abs = join22(ctx.projectDir, rel);
60952
+ const abs = join23(ctx.projectDir, rel);
60940
60953
  if (existingRel && !ctx.force && isFreshCanonicalAsset({
60941
60954
  projectDir: ctx.projectDir,
60942
60955
  kind: "narration",
@@ -60950,7 +60963,7 @@ async function dispatchNarration(beat, ctx) {
60950
60963
  return {
60951
60964
  status: "cached",
60952
60965
  path: existingRel,
60953
- durationSec: await safeAudioDuration(join22(ctx.projectDir, existingRel)),
60966
+ durationSec: await safeAudioDuration(join23(ctx.projectDir, existingRel)),
60954
60967
  provider: resolution.provider,
60955
60968
  cachePath: cache.path,
60956
60969
  cacheKey: cache.key,
@@ -60958,8 +60971,8 @@ async function dispatchNarration(beat, ctx) {
60958
60971
  freshness: "fresh"
60959
60972
  };
60960
60973
  }
60961
- if (existsSync46(cacheAbs) && !ctx.force) {
60962
- await mkdir24(dirname22(abs), { recursive: true });
60974
+ if (existsSync47(cacheAbs) && !ctx.force) {
60975
+ await mkdir25(dirname23(abs), { recursive: true });
60963
60976
  await copyFile5(cacheAbs, abs);
60964
60977
  await writeAssetMetadata({
60965
60978
  projectDir: ctx.projectDir,
@@ -60990,10 +61003,10 @@ async function dispatchNarration(beat, ctx) {
60990
61003
  ctx.onProgress({ type: "narration-failed", beatId: beat.id, error });
60991
61004
  return { status: "failed", error };
60992
61005
  }
60993
- await mkdir24(dirname22(abs), { recursive: true });
60994
- await writeFile48(abs, result.audioBuffer);
60995
- await mkdir24(dirname22(cacheAbs), { recursive: true });
60996
- await writeFile48(cacheAbs, result.audioBuffer);
61006
+ await mkdir25(dirname23(abs), { recursive: true });
61007
+ await writeFile49(abs, result.audioBuffer);
61008
+ await mkdir25(dirname23(cacheAbs), { recursive: true });
61009
+ await writeFile49(cacheAbs, result.audioBuffer);
60997
61010
  await writeAssetMetadata({
60998
61011
  projectDir: ctx.projectDir,
60999
61012
  kind: "narration",
@@ -61029,7 +61042,7 @@ async function dispatchBackdrop(beat, ctx) {
61029
61042
  if (!cue) return { status: "no-cue" };
61030
61043
  const prompt3 = augmentBackdropPrompt(cue);
61031
61044
  const rel = `assets/backdrop-${beat.id}.png`;
61032
- const abs = join22(ctx.projectDir, rel);
61045
+ const abs = join23(ctx.projectDir, rel);
61033
61046
  const size = ctx.imageSize ?? "1536x1024";
61034
61047
  const ratio = imageRatioForSize(size);
61035
61048
  const metadataOptions = { quality: ctx.imageQuality, size, ratio };
@@ -61042,7 +61055,7 @@ async function dispatchBackdrop(beat, ctx) {
61042
61055
  ratio
61043
61056
  });
61044
61057
  const metadataPath = assetMetadataPath("backdrop", beat.id);
61045
- if (existsSync46(abs) && !ctx.force) {
61058
+ if (existsSync47(abs) && !ctx.force) {
61046
61059
  const metadata = readAssetMetadata(ctx.projectDir, "backdrop", beat.id);
61047
61060
  if (!metadata || isFreshCanonicalAsset({
61048
61061
  projectDir: ctx.projectDir,
@@ -61065,9 +61078,9 @@ async function dispatchBackdrop(beat, ctx) {
61065
61078
  };
61066
61079
  }
61067
61080
  }
61068
- const cacheAbs = join22(ctx.projectDir, cache.path);
61069
- if (existsSync46(cacheAbs) && !ctx.force) {
61070
- await mkdir24(dirname22(abs), { recursive: true });
61081
+ const cacheAbs = join23(ctx.projectDir, cache.path);
61082
+ if (existsSync47(cacheAbs) && !ctx.force) {
61083
+ await mkdir25(dirname23(abs), { recursive: true });
61071
61084
  await copyFile5(cacheAbs, abs);
61072
61085
  await writeAssetMetadata({
61073
61086
  projectDir: ctx.projectDir,
@@ -61097,11 +61110,11 @@ async function dispatchBackdrop(beat, ctx) {
61097
61110
  ctx.onProgress({ type: "backdrop-failed", beatId: beat.id, error });
61098
61111
  return { status: "failed", error };
61099
61112
  }
61100
- await mkdir24(dirname22(abs), { recursive: true });
61113
+ await mkdir25(dirname23(abs), { recursive: true });
61101
61114
  const buffer = generated.buffer;
61102
- await writeFile48(abs, buffer);
61103
- await mkdir24(dirname22(cacheAbs), { recursive: true });
61104
- await writeFile48(cacheAbs, buffer);
61115
+ await writeFile49(abs, buffer);
61116
+ await mkdir25(dirname23(cacheAbs), { recursive: true });
61117
+ await writeFile49(cacheAbs, buffer);
61105
61118
  await writeAssetMetadata({
61106
61119
  projectDir: ctx.projectDir,
61107
61120
  kind: "backdrop",
@@ -61192,7 +61205,7 @@ async function dispatchVideo(beat, ctx) {
61192
61205
  const prompt3 = stringOrUndefined4(beat.cues?.video);
61193
61206
  if (!prompt3) return { status: "no-cue" };
61194
61207
  const rel = `assets/video-${beat.id}.mp4`;
61195
- const abs = join22(ctx.projectDir, rel);
61208
+ const abs = join23(ctx.projectDir, rel);
61196
61209
  const cache = videoCacheDescriptor({
61197
61210
  beatId: beat.id,
61198
61211
  cue: prompt3,
@@ -61200,7 +61213,7 @@ async function dispatchVideo(beat, ctx) {
61200
61213
  duration: normalizeVideoDuration(beat.duration)
61201
61214
  });
61202
61215
  const metadataPath = assetMetadataPath("video", beat.id);
61203
- if (existsSync46(abs) && !ctx.force) {
61216
+ if (existsSync47(abs) && !ctx.force) {
61204
61217
  const metadata = readAssetMetadata(ctx.projectDir, "video", beat.id);
61205
61218
  if (!metadata || isFreshCanonicalAsset({
61206
61219
  projectDir: ctx.projectDir,
@@ -61223,9 +61236,9 @@ async function dispatchVideo(beat, ctx) {
61223
61236
  };
61224
61237
  }
61225
61238
  }
61226
- const cacheAbs = join22(ctx.projectDir, cache.path);
61227
- if (existsSync46(cacheAbs) && !ctx.force) {
61228
- await mkdir24(dirname22(abs), { recursive: true });
61239
+ const cacheAbs = join23(ctx.projectDir, cache.path);
61240
+ if (existsSync47(cacheAbs) && !ctx.force) {
61241
+ await mkdir25(dirname23(abs), { recursive: true });
61229
61242
  await copyFile5(cacheAbs, abs);
61230
61243
  await writeAssetMetadata({
61231
61244
  projectDir: ctx.projectDir,
@@ -61264,8 +61277,8 @@ async function dispatchVideo(beat, ctx) {
61264
61277
  ctx.onProgress({ type: "video-failed", beatId: beat.id, error });
61265
61278
  return { status: "failed", error };
61266
61279
  }
61267
- if (result.status === "completed" && existsSync46(abs)) {
61268
- await mkdir24(dirname22(cacheAbs), { recursive: true });
61280
+ if (result.status === "completed" && existsSync47(abs)) {
61281
+ await mkdir25(dirname23(cacheAbs), { recursive: true });
61269
61282
  await copyFile5(abs, cacheAbs);
61270
61283
  await writeAssetMetadata({
61271
61284
  projectDir: ctx.projectDir,
@@ -61332,7 +61345,7 @@ async function dispatchMusic(beat, ctx) {
61332
61345
  const prompt3 = stringOrUndefined4(beat.cues?.music);
61333
61346
  if (!prompt3) return { status: "no-cue" };
61334
61347
  const rel = `assets/music-${beat.id}.mp3`;
61335
- const abs = join22(ctx.projectDir, rel);
61348
+ const abs = join23(ctx.projectDir, rel);
61336
61349
  const duration = normalizeMusicDuration(beat.duration);
61337
61350
  const cache = musicCacheDescriptor({
61338
61351
  beatId: beat.id,
@@ -61341,7 +61354,7 @@ async function dispatchMusic(beat, ctx) {
61341
61354
  duration
61342
61355
  });
61343
61356
  const metadataPath = assetMetadataPath("music", beat.id);
61344
- if (existsSync46(abs) && !ctx.force) {
61357
+ if (existsSync47(abs) && !ctx.force) {
61345
61358
  const metadata = readAssetMetadata(ctx.projectDir, "music", beat.id);
61346
61359
  if (!metadata || isFreshCanonicalAsset({
61347
61360
  projectDir: ctx.projectDir,
@@ -61365,9 +61378,9 @@ async function dispatchMusic(beat, ctx) {
61365
61378
  };
61366
61379
  }
61367
61380
  }
61368
- const cacheAbs = join22(ctx.projectDir, cache.path);
61369
- if (existsSync46(cacheAbs) && !ctx.force) {
61370
- await mkdir24(dirname22(abs), { recursive: true });
61381
+ const cacheAbs = join23(ctx.projectDir, cache.path);
61382
+ if (existsSync47(cacheAbs) && !ctx.force) {
61383
+ await mkdir25(dirname23(abs), { recursive: true });
61371
61384
  await copyFile5(cacheAbs, abs);
61372
61385
  await writeAssetMetadata({
61373
61386
  projectDir: ctx.projectDir,
@@ -61440,12 +61453,12 @@ async function dispatchMusic(beat, ctx) {
61440
61453
  metadataPath
61441
61454
  };
61442
61455
  }
61443
- if (!existsSync46(abs)) {
61456
+ if (!existsSync47(abs)) {
61444
61457
  const error = result.outputPath ? `music output was not written at ${abs}` : "music generation did not return an output file";
61445
61458
  ctx.onProgress({ type: "music-failed", beatId: beat.id, error });
61446
61459
  return { status: "failed", error };
61447
61460
  }
61448
- await mkdir24(dirname22(cacheAbs), { recursive: true });
61461
+ await mkdir25(dirname23(cacheAbs), { recursive: true });
61449
61462
  await copyFile5(abs, cacheAbs);
61450
61463
  await writeAssetMetadata({
61451
61464
  projectDir: ctx.projectDir,
@@ -61476,15 +61489,15 @@ async function dispatchMusic(beat, ctx) {
61476
61489
  };
61477
61490
  }
61478
61491
  function loadSceneBuildEnv(projectDir) {
61479
- (0, import_dotenv4.config)({ path: join22(projectDir, ".env"), quiet: true });
61480
- (0, import_dotenv4.config)({ path: resolve62(process.cwd(), ".env"), quiet: true });
61492
+ (0, import_dotenv4.config)({ path: join23(projectDir, ".env"), quiet: true });
61493
+ (0, import_dotenv4.config)({ path: resolve63(process.cwd(), ".env"), quiet: true });
61481
61494
  let dir = process.cwd();
61482
- while (dir !== dirname22(dir)) {
61483
- if (existsSync46(join22(dir, "pnpm-workspace.yaml"))) {
61484
- (0, import_dotenv4.config)({ path: join22(dir, ".env"), quiet: true });
61495
+ while (dir !== dirname23(dir)) {
61496
+ if (existsSync47(join23(dir, "pnpm-workspace.yaml"))) {
61497
+ (0, import_dotenv4.config)({ path: join23(dir, ".env"), quiet: true });
61485
61498
  return;
61486
61499
  }
61487
- dir = dirname22(dir);
61500
+ dir = dirname23(dir);
61488
61501
  }
61489
61502
  }
61490
61503
  async function skipped(kind, beatId, reason, ctx) {
@@ -61690,7 +61703,7 @@ function mergeBeatOutcomes(base, updates) {
61690
61703
  }
61691
61704
  function firstExisting3(projectDir, relPaths) {
61692
61705
  for (const rel of relPaths) {
61693
- if (existsSync46(join22(projectDir, rel))) return rel;
61706
+ if (existsSync47(join23(projectDir, rel))) return rel;
61694
61707
  }
61695
61708
  return null;
61696
61709
  }
@@ -61721,7 +61734,7 @@ async function apiKeyForVideoProvider(provider, projectDir) {
61721
61734
  return getApiKeyFromConfig(providerKey, { cwd: projectDir });
61722
61735
  }
61723
61736
  async function finalizeBuildResult(projectDir, startedAt, result) {
61724
- const reportPath = join22(projectDir, "build-report.json");
61737
+ const reportPath = join23(projectDir, "build-report.json");
61725
61738
  if (result.stageReports) {
61726
61739
  for (const report of Object.values(result.stageReports)) {
61727
61740
  if (report.status === "pending") report.status = "skipped";
@@ -61737,7 +61750,7 @@ async function finalizeBuildResult(projectDir, startedAt, result) {
61737
61750
  totalLatencyMs: Date.now() - startedAt
61738
61751
  };
61739
61752
  try {
61740
- await writeFile48(
61753
+ await writeFile49(
61741
61754
  reportPath,
61742
61755
  JSON.stringify(toBuildReport(projectDir, withMeta), null, 2) + "\n",
61743
61756
  "utf-8"
@@ -61880,7 +61893,7 @@ function normalizeReportDuration(value) {
61880
61893
  }
61881
61894
  function buildReportComposition(projectDir, result, beatId) {
61882
61895
  const path2 = `compositions/scene-${beatId}.html`;
61883
- const exists = existsSync46(join22(projectDir, path2));
61896
+ const exists = existsSync47(join23(projectDir, path2));
61884
61897
  const written = composeWrittenEntry(result, beatId);
61885
61898
  if (written) {
61886
61899
  return {
@@ -61937,8 +61950,8 @@ function summarizeBuildBeats(projectDir, beats) {
61937
61950
  let compositionsReady = 0;
61938
61951
  for (const beat of beats) {
61939
61952
  if (beatAssetsReady(beat)) assetsReady += 1;
61940
- const compositionPath = join22(projectDir, "compositions", `scene-${beat.beatId}.html`);
61941
- if (existsSync46(compositionPath)) {
61953
+ const compositionPath = join23(projectDir, "compositions", `scene-${beat.beatId}.html`);
61954
+ if (existsSync47(compositionPath)) {
61942
61955
  compositionsReady += 1;
61943
61956
  } else {
61944
61957
  needsAuthor.push(beat.beatId);
@@ -61972,7 +61985,7 @@ async function resolveBeatDuration(opts) {
61972
61985
  const storyboardMin = opts.beatDuration ?? 3;
61973
61986
  if (!opts.narrationPath) return Number(storyboardMin.toFixed(2));
61974
61987
  try {
61975
- const audioDuration = await getAudioDuration(join22(opts.projectDir, opts.narrationPath));
61988
+ const audioDuration = await getAudioDuration(join23(opts.projectDir, opts.narrationPath));
61976
61989
  return Number(Math.max(storyboardMin, audioDuration + 0.5).toFixed(2));
61977
61990
  } catch {
61978
61991
  return Number(storyboardMin.toFixed(2));
@@ -62076,19 +62089,19 @@ __export(ai_audio_exports, {
62076
62089
  executeTranscribe: () => executeTranscribe,
62077
62090
  executeVoiceClone: () => executeVoiceClone
62078
62091
  });
62079
- import { resolve as resolve69, dirname as dirname24, basename as basename22, extname as extname15 } from "node:path";
62080
- import { readFile as readFile45, writeFile as writeFile49 } from "node:fs/promises";
62081
- import { existsSync as existsSync51 } from "node:fs";
62092
+ import { resolve as resolve71, dirname as dirname25, basename as basename22, extname as extname15 } from "node:path";
62093
+ import { readFile as readFile46, writeFile as writeFile50 } from "node:fs/promises";
62094
+ import { existsSync as existsSync52 } from "node:fs";
62082
62095
  async function executeTranscribe(options) {
62083
62096
  const { audioPath, language, output, format, apiKey } = options;
62084
62097
  try {
62085
62098
  const key = apiKey || process.env.OPENAI_API_KEY;
62086
62099
  if (!key) return { success: false, error: "OPENAI_API_KEY required" };
62087
- const absPath = resolve69(process.cwd(), audioPath);
62088
- if (!existsSync51(absPath)) return { success: false, error: `File not found: ${absPath}` };
62100
+ const absPath = resolve71(process.cwd(), audioPath);
62101
+ if (!existsSync52(absPath)) return { success: false, error: `File not found: ${absPath}` };
62089
62102
  const whisper = new WhisperProvider();
62090
62103
  await whisper.initialize({ apiKey: key });
62091
- const audioBuffer = await readFile45(absPath);
62104
+ const audioBuffer = await readFile46(absPath);
62092
62105
  const audioBlob = new Blob([audioBuffer]);
62093
62106
  const result = await whisper.transcribe(audioBlob, language);
62094
62107
  if (result.status === "failed") {
@@ -62096,10 +62109,10 @@ async function executeTranscribe(options) {
62096
62109
  }
62097
62110
  let outputPath;
62098
62111
  if (output) {
62099
- outputPath = resolve69(process.cwd(), output);
62112
+ outputPath = resolve71(process.cwd(), output);
62100
62113
  const fmt = detectFormat(output, format);
62101
62114
  const content = formatTranscript(result, fmt);
62102
- await writeFile49(outputPath, content, "utf-8");
62115
+ await writeFile50(outputPath, content, "utf-8");
62103
62116
  }
62104
62117
  return {
62105
62118
  success: true,
@@ -62117,17 +62130,17 @@ async function executeIsolate(options) {
62117
62130
  try {
62118
62131
  const key = apiKey || process.env.ELEVENLABS_API_KEY;
62119
62132
  if (!key) return { success: false, error: "ELEVENLABS_API_KEY required" };
62120
- const absPath = resolve69(process.cwd(), audioPath);
62121
- if (!existsSync51(absPath)) return { success: false, error: `File not found: ${absPath}` };
62122
- const audioBuffer = await readFile45(absPath);
62133
+ const absPath = resolve71(process.cwd(), audioPath);
62134
+ if (!existsSync52(absPath)) return { success: false, error: `File not found: ${absPath}` };
62135
+ const audioBuffer = await readFile46(absPath);
62123
62136
  const elevenlabs = new ElevenLabsProvider();
62124
62137
  await elevenlabs.initialize({ apiKey: key });
62125
62138
  const result = await elevenlabs.isolateVocals(audioBuffer);
62126
62139
  if (!result.success || !result.audioBuffer) {
62127
62140
  return { success: false, error: result.error || "Audio isolation failed" };
62128
62141
  }
62129
- const outputPath = resolve69(process.cwd(), output);
62130
- await writeFile49(outputPath, result.audioBuffer);
62142
+ const outputPath = resolve71(process.cwd(), output);
62143
+ await writeFile50(outputPath, result.audioBuffer);
62131
62144
  return { success: true, outputPath };
62132
62145
  } catch (error) {
62133
62146
  return { success: false, error: `Audio isolation failed: ${error instanceof Error ? error.message : String(error)}` };
@@ -62143,9 +62156,9 @@ async function executeVoiceClone(options) {
62143
62156
  }
62144
62157
  const audioBuffers = [];
62145
62158
  for (const samplePath of samplePaths) {
62146
- const absPath = resolve69(process.cwd(), samplePath);
62147
- if (!existsSync51(absPath)) return { success: false, error: `File not found: ${samplePath}` };
62148
- const buffer = await readFile45(absPath);
62159
+ const absPath = resolve71(process.cwd(), samplePath);
62160
+ if (!existsSync52(absPath)) return { success: false, error: `File not found: ${samplePath}` };
62161
+ const buffer = await readFile46(absPath);
62149
62162
  audioBuffers.push(buffer);
62150
62163
  }
62151
62164
  const elevenlabs = new ElevenLabsProvider();
@@ -62165,8 +62178,8 @@ async function executeVoiceClone(options) {
62165
62178
  async function executeDub(options) {
62166
62179
  const { mediaPath, language, source, voice, analyzeOnly, output } = options;
62167
62180
  try {
62168
- const absPath = resolve69(process.cwd(), mediaPath);
62169
- if (!existsSync51(absPath)) return { success: false, error: `File not found: ${absPath}` };
62181
+ const absPath = resolve71(process.cwd(), mediaPath);
62182
+ if (!existsSync52(absPath)) return { success: false, error: `File not found: ${absPath}` };
62170
62183
  const openaiKey = process.env.OPENAI_API_KEY;
62171
62184
  const anthropicKey = process.env.ANTHROPIC_API_KEY;
62172
62185
  const elevenlabsKey = process.env.ELEVENLABS_API_KEY;
@@ -62177,13 +62190,13 @@ async function executeDub(options) {
62177
62190
  const isVideo = [".mp4", ".mov", ".avi", ".mkv", ".webm"].includes(ext);
62178
62191
  let audioPath = absPath;
62179
62192
  if (isVideo) {
62180
- const tempAudioPath = resolve69(dirname24(absPath), `temp-audio-${Date.now()}.mp3`);
62193
+ const tempAudioPath = resolve71(dirname25(absPath), `temp-audio-${Date.now()}.mp3`);
62181
62194
  execSafeSync("ffmpeg", ["-i", absPath, "-vn", "-acodec", "mp3", "-y", tempAudioPath]);
62182
62195
  audioPath = tempAudioPath;
62183
62196
  }
62184
62197
  const whisper = new WhisperProvider();
62185
62198
  await whisper.initialize({ apiKey: openaiKey });
62186
- const audioBuffer = await readFile45(audioPath);
62199
+ const audioBuffer = await readFile46(audioPath);
62187
62200
  const audioBlob = new Blob([audioBuffer]);
62188
62201
  const transcriptResult = await whisper.transcribe(audioBlob, source);
62189
62202
  if (transcriptResult.status === "failed" || !transcriptResult.segments) {
@@ -62226,7 +62239,7 @@ ${segmentTexts}`,
62226
62239
  }
62227
62240
  if (analyzeOnly) {
62228
62241
  if (output) {
62229
- const timingPath = resolve69(process.cwd(), output);
62242
+ const timingPath = resolve71(process.cwd(), output);
62230
62243
  const timingData = {
62231
62244
  sourcePath: absPath,
62232
62245
  sourceLanguage: transcriptResult.detectedLanguage || source || "auto",
@@ -62238,14 +62251,14 @@ ${segmentTexts}`,
62238
62251
  translated: translatedSegments[i]?.text || s.text
62239
62252
  }))
62240
62253
  };
62241
- await writeFile49(timingPath, JSON.stringify(timingData, null, 2));
62254
+ await writeFile50(timingPath, JSON.stringify(timingData, null, 2));
62242
62255
  }
62243
62256
  return {
62244
62257
  success: true,
62245
62258
  sourceLanguage: transcriptResult.detectedLanguage || source || "auto",
62246
62259
  targetLanguage: language,
62247
62260
  segmentCount: segments.length,
62248
- outputPath: output ? resolve69(process.cwd(), output) : void 0
62261
+ outputPath: output ? resolve71(process.cwd(), output) : void 0
62249
62262
  };
62250
62263
  }
62251
62264
  const elevenlabs = new ElevenLabsProvider();
@@ -62259,9 +62272,9 @@ ${segmentTexts}`,
62259
62272
  }
62260
62273
  const combinedBuffer = Buffer.concat(dubbedBuffers);
62261
62274
  const outputExt = isVideo ? ".mp3" : extname15(absPath);
62262
- const defaultOutputPath2 = resolve69(dirname24(absPath), `${basename22(absPath, extname15(absPath))}-${language}${outputExt}`);
62263
- const finalOutputPath = resolve69(process.cwd(), output || defaultOutputPath2);
62264
- await writeFile49(finalOutputPath, combinedBuffer);
62275
+ const defaultOutputPath2 = resolve71(dirname25(absPath), `${basename22(absPath, extname15(absPath))}-${language}${outputExt}`);
62276
+ const finalOutputPath = resolve71(process.cwd(), output || defaultOutputPath2);
62277
+ await writeFile50(finalOutputPath, combinedBuffer);
62265
62278
  if (isVideo && audioPath !== absPath) {
62266
62279
  try {
62267
62280
  const { unlink: unlink5 } = await import("node:fs/promises");
@@ -62292,12 +62305,12 @@ async function executeDuck(options) {
62292
62305
  } = options;
62293
62306
  try {
62294
62307
  if (!commandExists("ffmpeg")) return { success: false, error: "FFmpeg not found" };
62295
- const absMusicPath = resolve69(process.cwd(), musicPath);
62296
- const absVoicePath = resolve69(process.cwd(), voicePath);
62297
- if (!existsSync51(absMusicPath)) return { success: false, error: `Music file not found: ${absMusicPath}` };
62298
- if (!existsSync51(absVoicePath)) return { success: false, error: `Voice file not found: ${absVoicePath}` };
62299
- const defaultOutput = resolve69(dirname24(absMusicPath), `${basename22(absMusicPath, extname15(absMusicPath))}-ducked${extname15(absMusicPath)}`);
62300
- const outputPath = resolve69(process.cwd(), output || defaultOutput);
62308
+ const absMusicPath = resolve71(process.cwd(), musicPath);
62309
+ const absVoicePath = resolve71(process.cwd(), voicePath);
62310
+ if (!existsSync52(absMusicPath)) return { success: false, error: `Music file not found: ${absMusicPath}` };
62311
+ if (!existsSync52(absVoicePath)) return { success: false, error: `Voice file not found: ${absVoicePath}` };
62312
+ const defaultOutput = resolve71(dirname25(absMusicPath), `${basename22(absMusicPath, extname15(absMusicPath))}-ducked${extname15(absMusicPath)}`);
62313
+ const outputPath = resolve71(process.cwd(), output || defaultOutput);
62301
62314
  const filter = `[1:a]asplit=2[sc][mix];[0:a][sc]sidechaincompress=threshold=${threshold}dB:ratio=${ratio}:attack=${attack}:release=${release}[ducked];[ducked][mix]amix=inputs=2:duration=longest`;
62302
62315
  await execSafe("ffmpeg", [
62303
62316
  "-i",
@@ -62309,7 +62322,7 @@ async function executeDuck(options) {
62309
62322
  "-y",
62310
62323
  outputPath
62311
62324
  ], { timeout: 12e4, maxBuffer: 50 * 1024 * 1024 });
62312
- if (!existsSync51(outputPath)) return { success: false, error: "FFmpeg failed to create output" };
62325
+ if (!existsSync52(outputPath)) return { success: false, error: "FFmpeg failed to create output" };
62313
62326
  return { success: true, outputPath };
62314
62327
  } catch (error) {
62315
62328
  return { success: false, error: `Audio ducking failed: ${error instanceof Error ? error.message : String(error)}` };
@@ -62325,9 +62338,9 @@ var init_ai_audio = __esm({
62325
62338
  });
62326
62339
 
62327
62340
  // src/pipeline/executor.ts
62328
- import { resolve as resolve70 } from "node:path";
62329
- import { readFile as readFile46, writeFile as writeFile50, mkdir as mkdir26 } from "node:fs/promises";
62330
- import { existsSync as existsSync52 } from "node:fs";
62341
+ import { resolve as resolve72 } from "node:path";
62342
+ import { readFile as readFile47, writeFile as writeFile51, mkdir as mkdir27 } from "node:fs/promises";
62343
+ import { existsSync as existsSync53 } from "node:fs";
62331
62344
  function maxCostFor(action) {
62332
62345
  const cmd = ACTION_METADATA[action]?.command;
62333
62346
  if (!cmd) return 0;
@@ -62338,9 +62351,9 @@ function registerAction(action, handler) {
62338
62351
  }
62339
62352
  function getOutput(params, outputDir, defaultName) {
62340
62353
  if (params.output && typeof params.output === "string") {
62341
- return resolve70(outputDir, params.output);
62354
+ return resolve72(outputDir, params.output);
62342
62355
  }
62343
- return resolve70(outputDir, defaultName);
62356
+ return resolve72(outputDir, defaultName);
62344
62357
  }
62345
62358
  function stringParam(value) {
62346
62359
  return typeof value === "string" && value.trim() !== "" ? value : void 0;
@@ -62591,7 +62604,7 @@ async function ensureActionsRegistered() {
62591
62604
  const { executeSceneBuild: executeSceneBuild2 } = await Promise.resolve().then(() => (init_scene_build(), scene_build_exports));
62592
62605
  const projectRel = params.project ?? ".";
62593
62606
  const r = await executeSceneBuild2({
62594
- projectDir: resolve70(outputDir, projectRel),
62607
+ projectDir: resolve72(outputDir, projectRel),
62595
62608
  mode: params.mode,
62596
62609
  effort: params.effort,
62597
62610
  composer: params.composer,
@@ -62617,7 +62630,7 @@ async function ensureActionsRegistered() {
62617
62630
  const { executeSceneRender: executeSceneRender2 } = await Promise.resolve().then(() => (init_scene_render(), scene_render_exports));
62618
62631
  const projectRel = params.project ?? ".";
62619
62632
  const r = await executeSceneRender2({
62620
- projectDir: resolve70(outputDir, projectRel),
62633
+ projectDir: resolve72(outputDir, projectRel),
62621
62634
  root: params.root,
62622
62635
  output: params.output,
62623
62636
  fps: params.fps,
@@ -62641,11 +62654,11 @@ async function ensureActionsRegistered() {
62641
62654
  });
62642
62655
  }
62643
62656
  async function loadPipeline(filePath) {
62644
- const absPath = resolve70(process.cwd(), filePath);
62645
- if (!existsSync52(absPath)) {
62657
+ const absPath = resolve72(process.cwd(), filePath);
62658
+ if (!existsSync53(absPath)) {
62646
62659
  throw new Error(`Pipeline file not found: ${absPath}`);
62647
62660
  }
62648
- const content = await readFile46(absPath, "utf-8");
62661
+ const content = await readFile47(absPath, "utf-8");
62649
62662
  const manifest2 = (0, import_yaml8.parse)(content);
62650
62663
  if (!manifest2.name) throw new Error("Pipeline missing 'name' field");
62651
62664
  if (!manifest2.steps || !Array.isArray(manifest2.steps)) throw new Error("Pipeline missing 'steps' array");
@@ -62660,15 +62673,15 @@ async function loadPipeline(filePath) {
62660
62673
  }
62661
62674
  async function executePipeline(manifest2, options = {}) {
62662
62675
  await ensureActionsRegistered();
62663
- const outputDir = resolve70(process.cwd(), options.outputDir || `${manifest2.name}-output`);
62664
- await mkdir26(outputDir, { recursive: true });
62676
+ const outputDir = resolve72(process.cwd(), options.outputDir || `${manifest2.name}-output`);
62677
+ await mkdir27(outputDir, { recursive: true });
62665
62678
  const completedSteps = /* @__PURE__ */ new Map();
62666
62679
  const results = [];
62667
62680
  const startTime = Date.now();
62668
62681
  if (options.resume) {
62669
- const checkpointPath = resolve70(outputDir, CHECKPOINT_FILE);
62670
- if (existsSync52(checkpointPath)) {
62671
- const checkpointContent = await readFile46(checkpointPath, "utf-8");
62682
+ const checkpointPath = resolve72(outputDir, CHECKPOINT_FILE);
62683
+ if (existsSync53(checkpointPath)) {
62684
+ const checkpointContent = await readFile47(checkpointPath, "utf-8");
62672
62685
  const checkpoint = (0, import_yaml8.parse)(checkpointContent);
62673
62686
  for (const cs of checkpoint.completedSteps) {
62674
62687
  completedSteps.set(cs.id, {
@@ -62786,8 +62799,8 @@ async function executePipeline(manifest2, options = {}) {
62786
62799
  data: s.data
62787
62800
  }))
62788
62801
  };
62789
- await writeFile50(
62790
- resolve70(outputDir, CHECKPOINT_FILE),
62802
+ await writeFile51(
62803
+ resolve72(outputDir, CHECKPOINT_FILE),
62791
62804
  (0, import_yaml8.stringify)(checkpoint, { indent: 2 }),
62792
62805
  "utf-8"
62793
62806
  );
@@ -67041,7 +67054,7 @@ var init_define_tool = __esm({
67041
67054
  });
67042
67055
 
67043
67056
  // src/tools/manifest/scene.ts
67044
- import { resolve as resolve71, relative as relative12 } from "node:path";
67057
+ import { resolve as resolve73, relative as relative12 } from "node:path";
67045
67058
  function summariseLint(result) {
67046
67059
  return {
67047
67060
  ok: result.ok,
@@ -67157,7 +67170,7 @@ var init_scene2 = __esm({
67157
67170
  description: "Scaffold a new VibeFrame video scene project. Supports minimal, agent, and full profiles; full includes the current HTML render backend metadata. Idempotent: re-running keeps user-authored files and merges backend config instead of overwriting. No API keys required.",
67158
67171
  schema: sceneInitSchema,
67159
67172
  async execute(args, ctx) {
67160
- const dir = resolve71(ctx.workingDirectory, args.dir);
67173
+ const dir = resolve73(ctx.workingDirectory, args.dir);
67161
67174
  const result = await scaffoldSceneProject({
67162
67175
  dir,
67163
67176
  name: args.name,
@@ -67207,7 +67220,7 @@ var init_scene2 = __esm({
67207
67220
  description: "Add a single scene to an existing scene project. Optionally generates narration audio (ElevenLabs) and/or a backdrop image (Gemini/OpenAI), then emits compositions/scene-<id>.html with a paused GSAP timeline and splices a clip reference into the root index.html. Use skipAudio:true and skipImage:true for text-only scenes that need no API calls.",
67208
67221
  schema: sceneAddSchema,
67209
67222
  async execute(args, ctx) {
67210
- const projectDir = args.projectDir ? resolve71(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
67223
+ const projectDir = args.projectDir ? resolve73(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
67211
67224
  const result = await executeSceneAdd({
67212
67225
  name: args.name,
67213
67226
  preset: args.preset ?? "simple",
@@ -67264,7 +67277,7 @@ var init_scene2 = __esm({
67264
67277
  description: "Validate every scene file in a project against the public Hyperframes lint rules (in-process, no Chrome required). Returns errors, warnings, and info findings per file. Optional fix:true mechanically repairs `timed_element_missing_clip_class` only \u2014 other issues surface with fixHints.",
67265
67278
  schema: sceneLintSchema,
67266
67279
  async execute(args, ctx) {
67267
- const projectDir = args.projectDir ? resolve71(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
67280
+ const projectDir = args.projectDir ? resolve73(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
67268
67281
  const result = await runProjectLint({
67269
67282
  projectDir,
67270
67283
  rootRel: args.root,
@@ -67301,7 +67314,7 @@ var init_scene2 = __esm({
67301
67314
  description: "Apply deterministic mechanical scene repairs. Currently uses the safe lint auto-fix allow-list and never performs semantic creative rewrites.",
67302
67315
  schema: sceneRepairSchema,
67303
67316
  async execute(args, ctx) {
67304
- const projectDir = args.projectDir ? resolve71(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
67317
+ const projectDir = args.projectDir ? resolve73(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
67305
67318
  const result = await executeSceneRepair({
67306
67319
  projectDir,
67307
67320
  rootRel: args.root,
@@ -67335,7 +67348,7 @@ var init_scene2 = __esm({
67335
67348
  description: "Render a scene project to MP4/WebM/MOV via the Hyperframes producer. Requires Chrome installed locally. Output defaults to renders/<projectName>-<isoStamp>.<format>.",
67336
67349
  schema: sceneRenderSchema,
67337
67350
  async execute(args, ctx) {
67338
- const projectDir = args.projectDir ? resolve71(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
67351
+ const projectDir = args.projectDir ? resolve73(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
67339
67352
  const result = await executeSceneRender({
67340
67353
  projectDir,
67341
67354
  root: args.root,
@@ -67409,7 +67422,7 @@ var init_scene2 = __esm({
67409
67422
  description: "v0.60 one-shot orchestrator: read STORYBOARD.md per-beat YAML cues (narration / backdrop / duration), dispatch TTS + image generation per beat, compose scene HTML via the compose-scenes-with-skills pipeline, then render to MP4. Use this instead of chaining init + scene_add + render manually. Caches by SHA256 of (DESIGN.md + cue body) so re-runs are idempotent and cheap.",
67410
67423
  schema: sceneBuildSchema,
67411
67424
  async execute(args, ctx) {
67412
- const projectDir = args.projectDir ? resolve71(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
67425
+ const projectDir = args.projectDir ? resolve73(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
67413
67426
  const result = await executeSceneBuild({
67414
67427
  projectDir,
67415
67428
  stage: args.stage,
@@ -67506,7 +67519,7 @@ var init_scene2 = __esm({
67506
67519
  description: "Install the vendored Hyperframes skill bundle into a scene project so the host agent (Claude Code, Cursor, Codex, Aider) can read framework rules + house style directly. Writes a universal SKILL.md + references/ at the project root, plus per-host layouts (.claude/skills/hyperframes/ for Claude Code, .cursor/rules/hyperframes.mdc for Cursor) when those hosts are detected. Phase H1 of the agentic-native composer plan \u2014 once installed, the host agent itself can author scene HTML using the rules instead of relying on vibe's internal LLM call.",
67507
67520
  schema: sceneInstallSkillSchema,
67508
67521
  async execute(args, ctx) {
67509
- const projectDir = resolve71(ctx.workingDirectory, args.projectDir);
67522
+ const projectDir = resolve73(ctx.workingDirectory, args.projectDir);
67510
67523
  const hostFlag = args.host ?? "auto";
67511
67524
  const hosts = (() => {
67512
67525
  if (hostFlag === "all") return ["all"];
@@ -67552,7 +67565,7 @@ var init_scene2 = __esm({
67552
67565
  description: "Emit the per-beat compose plan for the host agent to author scene HTML itself. Reads STORYBOARD.md + DESIGN.md and returns each beat's outputPath + userPrompt + cues + body, plus references to the project's SKILL.md (Hyperframes rules) and DESIGN.md (visual identity). The host agent writes each compositions/scene-<id>.html file directly \u2014 VibeFrame makes NO LLM call here. Pairs with scene_install_skill (Phase H1). Phase H2 of the agentic-native composer plan; the internal-LLM batch path (build) remains as a fallback for non-agent contexts.",
67553
67566
  schema: sceneComposePromptsSchema,
67554
67567
  async execute(args, ctx) {
67555
- const projectDir = resolve71(ctx.workingDirectory, args.projectDir);
67568
+ const projectDir = resolve73(ctx.workingDirectory, args.projectDir);
67556
67569
  const result = await getComposePrompts({
67557
67570
  projectDir,
67558
67571
  beatId: args.beat
@@ -68180,14 +68193,14 @@ var init_edit = __esm({
68180
68193
  });
68181
68194
 
68182
68195
  // src/commands/ai-suggest-edit.ts
68183
- import { readFile as readFile47, writeFile as writeFile51 } from "node:fs/promises";
68184
- import { resolve as resolve72 } from "node:path";
68196
+ import { readFile as readFile48, writeFile as writeFile52 } from "node:fs/promises";
68197
+ import { resolve as resolve74 } from "node:path";
68185
68198
  async function executeSuggestEdit(options) {
68186
68199
  try {
68187
68200
  const apiKey = options.apiKey ?? process.env.GOOGLE_API_KEY;
68188
68201
  if (!apiKey) return { success: false, error: "GOOGLE_API_KEY required for suggest" };
68189
- const filePath = resolve72(process.cwd(), options.projectPath);
68190
- const content = await readFile47(filePath, "utf-8");
68202
+ const filePath = resolve74(process.cwd(), options.projectPath);
68203
+ const content = await readFile48(filePath, "utf-8");
68191
68204
  const data = JSON.parse(content);
68192
68205
  const project = Project.fromJSON(data);
68193
68206
  const gemini = new GeminiProvider();
@@ -68198,7 +68211,7 @@ async function executeSuggestEdit(options) {
68198
68211
  const first = suggestions[0];
68199
68212
  const applied = applySuggestion(project, first);
68200
68213
  if (applied) {
68201
- await writeFile51(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
68214
+ await writeFile52(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
68202
68215
  return {
68203
68216
  success: true,
68204
68217
  suggestions,
@@ -68227,7 +68240,7 @@ var init_ai_suggest_edit = __esm({
68227
68240
  });
68228
68241
 
68229
68242
  // src/tools/manifest/inspect.ts
68230
- import { resolve as resolve73 } from "node:path";
68243
+ import { resolve as resolve75 } from "node:path";
68231
68244
  var inspectProjectTool, inspectRenderTool, analyzeMediaTool, analyzeVideoTool, analyzeReviewTool, analyzeSuggestTool, inspectTools;
68232
68245
  var init_inspect = __esm({
68233
68246
  "src/tools/manifest/inspect.ts"() {
@@ -68251,11 +68264,11 @@ var init_inspect = __esm({
68251
68264
  report: external_exports.boolean().optional().describe("Write review-report.json. Default true.")
68252
68265
  }),
68253
68266
  async execute(args, ctx) {
68254
- const projectDir = args.projectDir ? resolve73(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
68267
+ const projectDir = args.projectDir ? resolve75(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
68255
68268
  const result = await inspectProject({
68256
68269
  projectDir,
68257
68270
  beatId: args.beat,
68258
- outputPath: args.outputPath ? resolve73(ctx.workingDirectory, args.outputPath) : void 0,
68271
+ outputPath: args.outputPath ? resolve75(ctx.workingDirectory, args.outputPath) : void 0,
68259
68272
  writeReport: args.report !== false
68260
68273
  });
68261
68274
  return {
@@ -68285,13 +68298,13 @@ var init_inspect = __esm({
68285
68298
  dryRun: external_exports.boolean().optional().describe("Preview resolved inputs without probing video or calling Gemini.")
68286
68299
  }),
68287
68300
  async execute(args, ctx) {
68288
- const projectDir = args.projectDir ? resolve73(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
68301
+ const projectDir = args.projectDir ? resolve75(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
68289
68302
  if (args.dryRun) {
68290
68303
  const result2 = await previewInspectRender({
68291
68304
  projectDir,
68292
68305
  beatId: args.beat,
68293
- videoPath: args.videoPath ? resolve73(ctx.workingDirectory, args.videoPath) : void 0,
68294
- outputPath: args.outputPath ? resolve73(ctx.workingDirectory, args.outputPath) : void 0,
68306
+ videoPath: args.videoPath ? resolve75(ctx.workingDirectory, args.videoPath) : void 0,
68307
+ outputPath: args.outputPath ? resolve75(ctx.workingDirectory, args.outputPath) : void 0,
68295
68308
  writeReport: args.report !== false,
68296
68309
  ai: args.ai === true,
68297
68310
  model: args.model
@@ -68308,8 +68321,8 @@ var init_inspect = __esm({
68308
68321
  const result = await inspectRender({
68309
68322
  projectDir,
68310
68323
  beatId: args.beat,
68311
- videoPath: args.videoPath ? resolve73(ctx.workingDirectory, args.videoPath) : void 0,
68312
- outputPath: args.outputPath ? resolve73(ctx.workingDirectory, args.outputPath) : void 0,
68324
+ videoPath: args.videoPath ? resolve75(ctx.workingDirectory, args.videoPath) : void 0,
68325
+ outputPath: args.outputPath ? resolve75(ctx.workingDirectory, args.outputPath) : void 0,
68313
68326
  writeReport: args.report !== false,
68314
68327
  ai: args.ai === true,
68315
68328
  model: args.model
@@ -68899,13 +68912,13 @@ var init_generate2 = __esm({
68899
68912
  });
68900
68913
 
68901
68914
  // src/tools/manifest/storyboard.ts
68902
- import { existsSync as existsSync53 } from "node:fs";
68903
- import { readFile as readFile48, writeFile as writeFile52 } from "node:fs/promises";
68904
- import { resolve as resolve74 } from "node:path";
68915
+ import { existsSync as existsSync54 } from "node:fs";
68916
+ import { readFile as readFile49, writeFile as writeFile53 } from "node:fs/promises";
68917
+ import { resolve as resolve76 } from "node:path";
68905
68918
  async function readStoryboard2(projectDir) {
68906
- const path2 = resolve74(projectDir, "STORYBOARD.md");
68907
- if (!existsSync53(path2)) return null;
68908
- return { path: path2, markdown: await readFile48(path2, "utf-8") };
68919
+ const path2 = resolve76(projectDir, "STORYBOARD.md");
68920
+ if (!existsSync54(path2)) return null;
68921
+ return { path: path2, markdown: await readFile49(path2, "utf-8") };
68909
68922
  }
68910
68923
  var projectDirSchema, storyboardListTool, storyboardValidateTool, storyboardGetTool, storyboardSetTool, storyboardMoveTool, storyboardReviseTool, planTool, storyboardTools;
68911
68924
  var init_storyboard2 = __esm({
@@ -68927,7 +68940,7 @@ var init_storyboard2 = __esm({
68927
68940
  description: "List beats, ids, durations, and cue blocks from a project's STORYBOARD.md.",
68928
68941
  schema: projectDirSchema,
68929
68942
  async execute(args, ctx) {
68930
- const projectDir = args.projectDir ? resolve74(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
68943
+ const projectDir = args.projectDir ? resolve76(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
68931
68944
  const file = await readStoryboard2(projectDir);
68932
68945
  if (!file) return { success: false, error: `STORYBOARD.md not found in ${projectDir}` };
68933
68946
  const parsed = parseStoryboard(file.markdown);
@@ -68953,7 +68966,7 @@ var init_storyboard2 = __esm({
68953
68966
  description: "Validate STORYBOARD.md beat ids and cue blocks.",
68954
68967
  schema: projectDirSchema,
68955
68968
  async execute(args, ctx) {
68956
- const projectDir = args.projectDir ? resolve74(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
68969
+ const projectDir = args.projectDir ? resolve76(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
68957
68970
  const file = await readStoryboard2(projectDir);
68958
68971
  if (!file) return { success: false, error: `STORYBOARD.md not found in ${projectDir}` };
68959
68972
  const result = validateStoryboardMarkdown(file.markdown);
@@ -68986,7 +68999,7 @@ var init_storyboard2 = __esm({
68986
68999
  beat: external_exports.string().describe("Beat id to return.")
68987
69000
  }),
68988
69001
  async execute(args, ctx) {
68989
- const projectDir = args.projectDir ? resolve74(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
69002
+ const projectDir = args.projectDir ? resolve76(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
68990
69003
  const file = await readStoryboard2(projectDir);
68991
69004
  if (!file) return { success: false, error: `STORYBOARD.md not found in ${projectDir}` };
68992
69005
  const beat = getStoryboardBeat(file.markdown, args.beat);
@@ -69012,7 +69025,7 @@ var init_storyboard2 = __esm({
69012
69025
  unset: external_exports.boolean().optional().describe("Remove the cue key.")
69013
69026
  }),
69014
69027
  async execute(args, ctx) {
69015
- const projectDir = args.projectDir ? resolve74(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
69028
+ const projectDir = args.projectDir ? resolve76(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
69016
69029
  const file = await readStoryboard2(projectDir);
69017
69030
  if (!file) return { success: false, error: `STORYBOARD.md not found in ${projectDir}` };
69018
69031
  try {
@@ -69023,7 +69036,7 @@ var init_storyboard2 = __esm({
69023
69036
  value,
69024
69037
  unset: args.unset
69025
69038
  });
69026
- await writeFile52(file.path, next, "utf-8");
69039
+ await writeFile53(file.path, next, "utf-8");
69027
69040
  return {
69028
69041
  success: true,
69029
69042
  data: { beat: args.beat, key: args.key },
@@ -69045,7 +69058,7 @@ var init_storyboard2 = __esm({
69045
69058
  after: external_exports.string().describe("Beat id that should precede the moved beat.")
69046
69059
  }),
69047
69060
  async execute(args, ctx) {
69048
- const projectDir = args.projectDir ? resolve74(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
69061
+ const projectDir = args.projectDir ? resolve76(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
69049
69062
  const file = await readStoryboard2(projectDir);
69050
69063
  if (!file) return { success: false, error: `STORYBOARD.md not found in ${projectDir}` };
69051
69064
  try {
@@ -69053,7 +69066,7 @@ var init_storyboard2 = __esm({
69053
69066
  beatId: args.beat,
69054
69067
  afterBeatId: args.after
69055
69068
  });
69056
- await writeFile52(file.path, next, "utf-8");
69069
+ await writeFile53(file.path, next, "utf-8");
69057
69070
  return {
69058
69071
  success: true,
69059
69072
  data: { beat: args.beat, after: args.after },
@@ -69077,7 +69090,7 @@ var init_storyboard2 = __esm({
69077
69090
  dryRun: external_exports.boolean().optional().describe("Preview the revised storyboard without writing.")
69078
69091
  }),
69079
69092
  async execute(args, ctx) {
69080
- const projectDir = args.projectDir ? resolve74(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
69093
+ const projectDir = args.projectDir ? resolve76(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
69081
69094
  const result = await executeStoryboardRevision({
69082
69095
  projectDir,
69083
69096
  request: args.request,
@@ -69120,7 +69133,7 @@ var init_storyboard2 = __esm({
69120
69133
  force: external_exports.boolean().optional().describe("Plan regeneration even when outputs exist.")
69121
69134
  }),
69122
69135
  async execute(args, ctx) {
69123
- const projectDir = args.projectDir ? resolve74(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
69136
+ const projectDir = args.projectDir ? resolve76(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
69124
69137
  const plan = await createBuildPlan({
69125
69138
  projectDir,
69126
69139
  stage: args.stage,
@@ -69163,9 +69176,9 @@ var init_storyboard2 = __esm({
69163
69176
  });
69164
69177
 
69165
69178
  // src/tools/manifest/remix.ts
69166
- import { writeFile as writeFile53 } from "node:fs/promises";
69179
+ import { writeFile as writeFile54 } from "node:fs/promises";
69167
69180
  import { tmpdir as tmpdir4 } from "node:os";
69168
- import { join as join24 } from "node:path";
69181
+ import { join as join25 } from "node:path";
69169
69182
  var pipelineHighlightsTool, pipelineAutoShortsTool, pipelineRunTool, pipelineRegenerateSceneTool, remixTools;
69170
69183
  var init_remix = __esm({
69171
69184
  "src/tools/manifest/remix.ts"() {
@@ -69273,8 +69286,8 @@ var init_remix = __esm({
69273
69286
  let resolvedPath = args.pipelinePath;
69274
69287
  let tempPath;
69275
69288
  if (args.pipelineYaml) {
69276
- tempPath = join24(tmpdir4(), `vibe-mcp-pipeline-${Date.now()}.yaml`);
69277
- await writeFile53(tempPath, args.pipelineYaml, "utf-8");
69289
+ tempPath = join25(tmpdir4(), `vibe-mcp-pipeline-${Date.now()}.yaml`);
69290
+ await writeFile54(tempPath, args.pipelineYaml, "utf-8");
69278
69291
  resolvedPath = tempPath;
69279
69292
  }
69280
69293
  try {
@@ -69441,15 +69454,15 @@ var init_detect2 = __esm({
69441
69454
  });
69442
69455
 
69443
69456
  // src/tools/manifest/_project-io.ts
69444
- import { readFile as readFile49, writeFile as writeFile54 } from "node:fs/promises";
69457
+ import { readFile as readFile50, writeFile as writeFile55 } from "node:fs/promises";
69445
69458
  async function loadProject2(projectPath, cwd) {
69446
69459
  const absPath = await resolveTimelineFile(projectPath, cwd);
69447
- const content = await readFile49(absPath, "utf-8");
69460
+ const content = await readFile50(absPath, "utf-8");
69448
69461
  const data = JSON.parse(content);
69449
69462
  return { project: Project.fromJSON(data), absPath };
69450
69463
  }
69451
69464
  async function saveProject(absPath, project) {
69452
- await writeFile54(absPath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
69465
+ await writeFile55(absPath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
69453
69466
  }
69454
69467
  var init_project_io = __esm({
69455
69468
  "src/tools/manifest/_project-io.ts"() {
@@ -69460,8 +69473,8 @@ var init_project_io = __esm({
69460
69473
  });
69461
69474
 
69462
69475
  // src/tools/manifest/timeline.ts
69463
- import { mkdir as mkdir27, writeFile as writeFile55 } from "node:fs/promises";
69464
- import { basename as basename23, resolve as resolve75 } from "node:path";
69476
+ import { mkdir as mkdir28, writeFile as writeFile56 } from "node:fs/promises";
69477
+ import { basename as basename23, resolve as resolve77 } from "node:path";
69465
69478
  var MEDIA_TYPES, timelineCreateTool, timelineInfoTool, timelineAddSourceTool, timelineAddClipTool, timelineSplitClipTool, timelineTrimClipTool, timelineMoveClipTool, timelineDeleteClipTool, timelineDuplicateClipTool, timelineAddEffectTool, timelineAddTrackTool, timelineListTool, timelineTools;
69466
69479
  var init_timeline = __esm({
69467
69480
  "src/tools/manifest/timeline.ts"() {
@@ -69497,18 +69510,18 @@ var init_timeline = __esm({
69497
69510
  fps: external_exports.number().optional().describe("Frames per second (default: 30)")
69498
69511
  }),
69499
69512
  async execute(args, ctx) {
69500
- const projectName = args.name === "." ? basename23(ctx.workingDirectory) : basename23(resolve75(ctx.workingDirectory, args.name));
69513
+ const projectName = args.name === "." ? basename23(ctx.workingDirectory) : basename23(resolve77(ctx.workingDirectory, args.name));
69501
69514
  const project = new Project(projectName);
69502
69515
  if (args.fps) project.setFrameRate(args.fps);
69503
69516
  let outputPath;
69504
69517
  if (args.outputPath) {
69505
- outputPath = resolve75(ctx.workingDirectory, args.outputPath);
69518
+ outputPath = resolve77(ctx.workingDirectory, args.outputPath);
69506
69519
  } else {
69507
- const dirPath = resolve75(ctx.workingDirectory, args.name);
69508
- await mkdir27(dirPath, { recursive: true });
69509
- outputPath = resolve75(dirPath, TIMELINE_FILENAME);
69520
+ const dirPath = resolve77(ctx.workingDirectory, args.name);
69521
+ await mkdir28(dirPath, { recursive: true });
69522
+ outputPath = resolve77(dirPath, TIMELINE_FILENAME);
69510
69523
  }
69511
- await writeFile55(outputPath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
69524
+ await writeFile56(outputPath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
69512
69525
  return {
69513
69526
  success: true,
69514
69527
  data: { name: projectName, outputPath },
@@ -69556,7 +69569,7 @@ var init_timeline = __esm({
69556
69569
  }),
69557
69570
  async execute(args, ctx) {
69558
69571
  const { project, absPath } = await loadProject2(args.projectPath, ctx.workingDirectory);
69559
- const mediaPath = resolve75(ctx.workingDirectory, args.mediaPath);
69572
+ const mediaPath = resolve77(ctx.workingDirectory, args.mediaPath);
69560
69573
  const ext = mediaPath.split(".").pop()?.toLowerCase() ?? "";
69561
69574
  const source = project.addSource({
69562
69575
  name: args.name ?? mediaPath.split("/").pop() ?? "media",
@@ -69784,8 +69797,8 @@ var init_timeline = __esm({
69784
69797
  });
69785
69798
 
69786
69799
  // src/tools/manifest/project.ts
69787
- import { resolve as resolve76 } from "node:path";
69788
- import { writeFile as writeFile56 } from "node:fs/promises";
69800
+ import { resolve as resolve78 } from "node:path";
69801
+ import { writeFile as writeFile57 } from "node:fs/promises";
69789
69802
  var projectCreateTool, projectInfoTool, projectTools;
69790
69803
  var init_project2 = __esm({
69791
69804
  "src/tools/manifest/project.ts"() {
@@ -69807,10 +69820,10 @@ var init_project2 = __esm({
69807
69820
  fps: external_exports.number().optional().describe("Frames per second (default: 30)")
69808
69821
  }),
69809
69822
  async execute(args, ctx) {
69810
- const outputPath = resolve76(ctx.workingDirectory, args.outputPath ?? `${args.name}.vibe.json`);
69823
+ const outputPath = resolve78(ctx.workingDirectory, args.outputPath ?? `${args.name}.vibe.json`);
69811
69824
  const project = new Project(args.name);
69812
69825
  if (args.fps) project.setFrameRate(args.fps);
69813
- await writeFile56(outputPath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
69826
+ await writeFile57(outputPath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
69814
69827
  return {
69815
69828
  success: true,
69816
69829
  data: { name: args.name, outputPath },
@@ -69853,8 +69866,8 @@ var init_project2 = __esm({
69853
69866
  });
69854
69867
 
69855
69868
  // src/commands/export.ts
69856
- import { readFile as readFile50, access as access7 } from "node:fs/promises";
69857
- import { resolve as resolve77, basename as basename24 } from "node:path";
69869
+ import { readFile as readFile51, access as access7 } from "node:fs/promises";
69870
+ import { resolve as resolve79, basename as basename24 } from "node:path";
69858
69871
  import { spawn as spawn3 } from "node:child_process";
69859
69872
  function timelineBaseName(path2) {
69860
69873
  const name = basename24(path2);
@@ -69922,7 +69935,7 @@ async function runExport(projectPath, outputPath, options = {}) {
69922
69935
  };
69923
69936
  }
69924
69937
  const filePath = await resolveTimelineFile(projectPath);
69925
- const content = await readFile50(filePath, "utf-8");
69938
+ const content = await readFile51(filePath, "utf-8");
69926
69939
  const data = JSON.parse(content);
69927
69940
  const project = Project.fromJSON(data);
69928
69941
  const summary = project.getSummary();
@@ -69932,7 +69945,7 @@ async function runExport(projectPath, outputPath, options = {}) {
69932
69945
  message: "Project has no clips to export"
69933
69946
  };
69934
69947
  }
69935
- const finalOutputPath = resolve77(process.cwd(), outputPath);
69948
+ const finalOutputPath = resolve79(process.cwd(), outputPath);
69936
69949
  const basePresetSettings = getPresetSettings(preset, summary.aspectRatio);
69937
69950
  const presetSettings = applyCustomOverrides(basePresetSettings, { bitrate, fps, resolution, codec });
69938
69951
  const clips = project.getClips().sort((a, b) => a.startTime - b.startTime);
@@ -70328,7 +70341,7 @@ function buildFFmpegArgs(clips, sources, presetSettings, outputPath, options, so
70328
70341
  return args;
70329
70342
  }
70330
70343
  function runFFmpegProcess(ffmpegPath, args, onProgress) {
70331
- return new Promise((resolve81, reject) => {
70344
+ return new Promise((resolve83, reject) => {
70332
70345
  const ffmpeg = spawn3(ffmpegPath, args, {
70333
70346
  stdio: ["pipe", "pipe", "pipe"]
70334
70347
  });
@@ -70352,7 +70365,7 @@ function runFFmpegProcess(ffmpegPath, args, onProgress) {
70352
70365
  });
70353
70366
  ffmpeg.on("close", (code) => {
70354
70367
  if (code === 0) {
70355
- resolve81();
70368
+ resolve83();
70356
70369
  } else {
70357
70370
  const errorMatch = stderr.match(/Error.*$/m);
70358
70371
  const errorMsg = errorMatch ? errorMatch[0] : `FFmpeg exited with code ${code}`;
@@ -70488,17 +70501,17 @@ function getPresetSettings(preset, aspectRatio2) {
70488
70501
  }
70489
70502
  async function runHyperframesExport(projectPath, options, spinner2, startedAt) {
70490
70503
  spinner2.text = "Loading project...";
70491
- const { readFile: readFile52 } = await import("node:fs/promises");
70492
- const { resolve: resolve81 } = await import("node:path");
70504
+ const { readFile: readFile53 } = await import("node:fs/promises");
70505
+ const { resolve: resolve83 } = await import("node:path");
70493
70506
  const { Project: Project2 } = await Promise.resolve().then(() => (init_engine(), engine_exports));
70494
70507
  const { createHyperframesBackend: createHyperframesBackend2 } = await Promise.resolve().then(() => (init_hyperframes(), hyperframes_exports));
70495
70508
  const { exitWithError: exitWithError2, generalError: generalError2, outputSuccess: outputSuccess2 } = await Promise.resolve().then(() => (init_output(), output_exports));
70496
70509
  const chalk2 = (await Promise.resolve().then(() => (init_source(), source_exports))).default;
70497
70510
  const filePath = await resolveTimelineFile(projectPath);
70498
- const content = await readFile52(filePath, "utf-8");
70511
+ const content = await readFile53(filePath, "utf-8");
70499
70512
  const project = Project2.fromJSON(JSON.parse(content));
70500
70513
  const state = project.getState();
70501
- const outputPath = options.output ? resolve81(process.cwd(), options.output) : resolve81(process.cwd(), `${timelineBaseName(projectPath)}.${options.format ?? "mp4"}`);
70514
+ const outputPath = options.output ? resolve83(process.cwd(), options.output) : resolve83(process.cwd(), `${timelineBaseName(projectPath)}.${options.format ?? "mp4"}`);
70502
70515
  const quality = ["draft", "standard", "high"].includes(options.preset ?? "") ? options.preset : "standard";
70503
70516
  const backend = createHyperframesBackend2();
70504
70517
  spinner2.text = "Rendering with Hyperframes...";
@@ -70617,7 +70630,7 @@ Run 'vibe schema export' for structured parameter info.`).action(async (projectP
70617
70630
  }
70618
70631
  spinner2.text = "Loading project...";
70619
70632
  const filePath = await resolveTimelineFile(projectPath);
70620
- const content = await readFile50(filePath, "utf-8");
70633
+ const content = await readFile51(filePath, "utf-8");
70621
70634
  const data = JSON.parse(content);
70622
70635
  const project = Project.fromJSON(data);
70623
70636
  const summary = project.getSummary();
@@ -70625,7 +70638,7 @@ Run 'vibe schema export' for structured parameter info.`).action(async (projectP
70625
70638
  spinner2.fail("Project has no clips to export");
70626
70639
  exitWithError(usageError("Project has no clips to export"));
70627
70640
  }
70628
- const outputPath = options.output ? resolve77(process.cwd(), options.output) : resolve77(
70641
+ const outputPath = options.output ? resolve79(process.cwd(), options.output) : resolve79(
70629
70642
  process.cwd(),
70630
70643
  `${timelineBaseName(projectPath)}.${options.format}`
70631
70644
  );
@@ -70709,7 +70722,7 @@ Run 'vibe schema export' for structured parameter info.`).action(async (projectP
70709
70722
  });
70710
70723
 
70711
70724
  // src/tools/manifest/export.ts
70712
- import { resolve as resolve78 } from "node:path";
70725
+ import { resolve as resolve80 } from "node:path";
70713
70726
  var exportVideoTool, exportTools;
70714
70727
  var init_export2 = __esm({
70715
70728
  "src/tools/manifest/export.ts"() {
@@ -70730,8 +70743,8 @@ var init_export2 = __esm({
70730
70743
  overwrite: external_exports.boolean().optional().describe("Overwrite existing output file (default: false)")
70731
70744
  }),
70732
70745
  async execute(args, ctx) {
70733
- const projectPath = resolve78(ctx.workingDirectory, args.projectPath);
70734
- const outputPath = resolve78(ctx.workingDirectory, args.outputPath);
70746
+ const projectPath = resolve80(ctx.workingDirectory, args.projectPath);
70747
+ const outputPath = resolve80(ctx.workingDirectory, args.outputPath);
70735
70748
  const result = await runExport(projectPath, outputPath, {
70736
70749
  preset: args.preset,
70737
70750
  format: args.format,
@@ -70750,8 +70763,8 @@ var init_export2 = __esm({
70750
70763
  });
70751
70764
 
70752
70765
  // src/tools/manifest/agent-only.ts
70753
- import { readFile as readFile51, writeFile as writeFile57, readdir as readdir7, stat as stat9, access as access8, unlink as unlink4 } from "node:fs/promises";
70754
- import { resolve as resolve79, join as join25, basename as basename25, extname as extname16 } from "node:path";
70766
+ import { readFile as readFile52, writeFile as writeFile58, readdir as readdir7, stat as stat9, access as access8, unlink as unlink4 } from "node:fs/promises";
70767
+ import { resolve as resolve81, join as join26, basename as basename25, extname as extname16 } from "node:path";
70755
70768
  function matchPattern(filename, pattern) {
70756
70769
  const regex2 = new RegExp(
70757
70770
  "^" + pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".") + "$",
@@ -70829,12 +70842,12 @@ var init_agent_only = __esm({
70829
70842
  async execute(args, ctx) {
70830
70843
  const dirPath = args.path ?? ".";
70831
70844
  try {
70832
- const absPath = resolve79(ctx.workingDirectory, dirPath);
70845
+ const absPath = resolve81(ctx.workingDirectory, dirPath);
70833
70846
  const entries = await readdir7(absPath, { withFileTypes: true });
70834
70847
  const results = [];
70835
70848
  for (const entry of entries) {
70836
70849
  if (args.pattern && !matchPattern(entry.name, args.pattern)) continue;
70837
- const fullPath = join25(absPath, entry.name);
70850
+ const fullPath = join26(absPath, entry.name);
70838
70851
  const stats = await stat9(fullPath);
70839
70852
  if (entry.isDirectory()) {
70840
70853
  results.push(`[DIR] ${entry.name}/`);
@@ -70860,8 +70873,8 @@ var init_agent_only = __esm({
70860
70873
  }),
70861
70874
  async execute(args, ctx) {
70862
70875
  try {
70863
- const absPath = resolve79(ctx.workingDirectory, args.path);
70864
- const content = await readFile51(absPath, "utf-8");
70876
+ const absPath = resolve81(ctx.workingDirectory, args.path);
70877
+ const content = await readFile52(absPath, "utf-8");
70865
70878
  const maxLength = 4e3;
70866
70879
  const truncated = content.length > maxLength;
70867
70880
  const output = truncated ? content.substring(0, maxLength) + "\n... (truncated)" : content;
@@ -70883,8 +70896,8 @@ var init_agent_only = __esm({
70883
70896
  }),
70884
70897
  async execute(args, ctx) {
70885
70898
  try {
70886
- const absPath = resolve79(ctx.workingDirectory, args.path);
70887
- await writeFile57(absPath, args.content, "utf-8");
70899
+ const absPath = resolve81(ctx.workingDirectory, args.path);
70900
+ await writeFile58(absPath, args.content, "utf-8");
70888
70901
  return { success: true, data: { bytes: args.content.length }, humanLines: [`File written: ${args.path} (${formatSize(args.content.length)})`] };
70889
70902
  } catch (error) {
70890
70903
  return { success: false, error: `Failed to write file: ${error instanceof Error ? error.message : String(error)}` };
@@ -70901,7 +70914,7 @@ var init_agent_only = __esm({
70901
70914
  path: external_exports.string().describe("Path to check")
70902
70915
  }),
70903
70916
  async execute(args, ctx) {
70904
- const absPath = resolve79(ctx.workingDirectory, args.path);
70917
+ const absPath = resolve81(ctx.workingDirectory, args.path);
70905
70918
  try {
70906
70919
  await access8(absPath);
70907
70920
  const stats = await stat9(absPath);
@@ -70927,11 +70940,11 @@ var init_agent_only = __esm({
70927
70940
  }),
70928
70941
  async execute(args, ctx) {
70929
70942
  try {
70930
- const filePath = resolve79(ctx.workingDirectory, args.project);
70931
- const content = await readFile51(filePath, "utf-8");
70943
+ const filePath = resolve81(ctx.workingDirectory, args.project);
70944
+ const content = await readFile52(filePath, "utf-8");
70932
70945
  const data = JSON.parse(content);
70933
70946
  const project = Project.fromJSON(data);
70934
- const dirPath = resolve79(ctx.workingDirectory, args.directory);
70947
+ const dirPath = resolve81(ctx.workingDirectory, args.directory);
70935
70948
  const filterExts = args.filter ? args.filter.split(",").map((e) => e.trim().toLowerCase()) : null;
70936
70949
  const imageDuration = args.imageDuration ?? 5;
70937
70950
  const recursive = args.recursive ?? false;
@@ -70939,7 +70952,7 @@ var init_agent_only = __esm({
70939
70952
  const scanDir = async (dir) => {
70940
70953
  const entries = await readdir7(dir, { withFileTypes: true });
70941
70954
  for (const entry of entries) {
70942
- const entryPath = join25(dir, entry.name);
70955
+ const entryPath = join26(dir, entry.name);
70943
70956
  if (entry.isDirectory() && recursive) {
70944
70957
  await scanDir(entryPath);
70945
70958
  } else if (entry.isFile()) {
@@ -70966,7 +70979,7 @@ var init_agent_only = __esm({
70966
70979
  const source = project.addSource({ name: mediaName, type: mediaType, url: mediaFile, duration });
70967
70980
  addedSources.push({ id: source.id, name: mediaName, type: mediaType });
70968
70981
  }
70969
- await writeFile57(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
70982
+ await writeFile58(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
70970
70983
  return {
70971
70984
  success: true,
70972
70985
  data: { count: addedSources.length, sources: addedSources },
@@ -70997,8 +71010,8 @@ var init_agent_only = __esm({
70997
71010
  }),
70998
71011
  async execute(args, ctx) {
70999
71012
  try {
71000
- const filePath = resolve79(ctx.workingDirectory, args.project);
71001
- const content = await readFile51(filePath, "utf-8");
71013
+ const filePath = resolve81(ctx.workingDirectory, args.project);
71014
+ const content = await readFile52(filePath, "utf-8");
71002
71015
  const data = JSON.parse(content);
71003
71016
  const project = Project.fromJSON(data);
71004
71017
  const sourceIds = args.sourceIds ?? [];
@@ -71034,7 +71047,7 @@ var init_agent_only = __esm({
71034
71047
  createdClips.push({ id: clip.id, sourceName: source.name, startTime: currentTime, duration: source.duration });
71035
71048
  currentTime += source.duration + gap;
71036
71049
  }
71037
- await writeFile57(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
71050
+ await writeFile58(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
71038
71051
  const totalDuration = currentTime - gap - startTime;
71039
71052
  return {
71040
71053
  success: true,
@@ -71066,8 +71079,8 @@ var init_agent_only = __esm({
71066
71079
  }),
71067
71080
  async execute(args, ctx) {
71068
71081
  try {
71069
- const filePath = resolve79(ctx.workingDirectory, args.project);
71070
- const content = await readFile51(filePath, "utf-8");
71082
+ const filePath = resolve81(ctx.workingDirectory, args.project);
71083
+ const content = await readFile52(filePath, "utf-8");
71071
71084
  const data = JSON.parse(content);
71072
71085
  const project = Project.fromJSON(data);
71073
71086
  const clipIds = args.clipIds ?? [];
@@ -71095,7 +71108,7 @@ var init_agent_only = __esm({
71095
71108
  });
71096
71109
  if (effect) appliedEffects.push({ clipId: clip.id, effectId: effect.id });
71097
71110
  }
71098
- await writeFile57(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
71111
+ await writeFile58(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
71099
71112
  return {
71100
71113
  success: true,
71101
71114
  data: { applied: appliedEffects.length, effectType: args.effectType },
@@ -71120,7 +71133,7 @@ var init_agent_only = __esm({
71120
71133
  async execute(args, ctx) {
71121
71134
  try {
71122
71135
  const filePath = await resolveTimelineFile(args.project, ctx.workingDirectory);
71123
- const content = await readFile51(filePath, "utf-8");
71136
+ const content = await readFile52(filePath, "utf-8");
71124
71137
  const data = JSON.parse(content);
71125
71138
  const project = Project.fromJSON(data);
71126
71139
  const what = args.what ?? "clips";
@@ -71162,7 +71175,7 @@ var init_agent_only = __esm({
71162
71175
  removed.sources++;
71163
71176
  }
71164
71177
  }
71165
- await writeFile57(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
71178
+ await writeFile58(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
71166
71179
  const parts = [];
71167
71180
  if (removed.clips > 0) parts.push(`${removed.clips} clips`);
71168
71181
  if (removed.tracks > 0) parts.push(`${removed.tracks} tracks`);
@@ -71195,7 +71208,7 @@ var init_agent_only = __esm({
71195
71208
  async execute(args, ctx) {
71196
71209
  try {
71197
71210
  const filePath = await resolveTimelineFile(args.projectPath, ctx.workingDirectory);
71198
- const content = await readFile51(filePath, "utf-8");
71211
+ const content = await readFile52(filePath, "utf-8");
71199
71212
  const data = JSON.parse(content);
71200
71213
  const project = Project.fromJSON(data);
71201
71214
  const updates = [];
@@ -71211,7 +71224,7 @@ var init_agent_only = __esm({
71211
71224
  project.setFrameRate(args.fps);
71212
71225
  updates.push(`Frame Rate: ${args.fps} fps`);
71213
71226
  }
71214
- await writeFile57(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
71227
+ await writeFile58(filePath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
71215
71228
  return {
71216
71229
  success: true,
71217
71230
  data: { updates },
@@ -71344,7 +71357,7 @@ var init_agent_only = __esm({
71344
71357
  }),
71345
71358
  async execute(args, ctx) {
71346
71359
  try {
71347
- const absPath = resolve79(ctx.workingDirectory, args.path);
71360
+ const absPath = resolve81(ctx.workingDirectory, args.path);
71348
71361
  const { stdout } = await execSafe(
71349
71362
  "ffprobe",
71350
71363
  ["-v", "quiet", "-print_format", "json", "-show_format", "-show_streams", absPath],
@@ -71431,10 +71444,10 @@ Audio:`);
71431
71444
  }),
71432
71445
  async execute(args, ctx) {
71433
71446
  try {
71434
- const absInput = resolve79(ctx.workingDirectory, args.input);
71447
+ const absInput = resolve81(ctx.workingDirectory, args.input);
71435
71448
  const ext = args.input.split(".").pop() || "mp4";
71436
71449
  const baseName = args.input.replace(/\.[^/.]+$/, "");
71437
- const outputPath = args.output ? resolve79(ctx.workingDirectory, args.output) : resolve79(ctx.workingDirectory, `${baseName}-compressed.${ext}`);
71450
+ const outputPath = args.output ? resolve81(ctx.workingDirectory, args.output) : resolve81(ctx.workingDirectory, `${baseName}-compressed.${ext}`);
71438
71451
  const crfValues = { low: 28, medium: 23, high: 18 };
71439
71452
  const crf = crfValues[args.quality ?? "medium"];
71440
71453
  await execSafe(
@@ -71457,8 +71470,8 @@ Audio:`);
71457
71470
  ],
71458
71471
  { maxBuffer: 50 * 1024 * 1024 }
71459
71472
  );
71460
- const inputBuf = await readFile51(absInput);
71461
- const outputBuf = await readFile51(outputPath);
71473
+ const inputBuf = await readFile52(absInput);
71474
+ const outputBuf = await readFile52(outputPath);
71462
71475
  const inputSize = inputBuf.length;
71463
71476
  const outputSize = outputBuf.length;
71464
71477
  const reduction = (inputSize - outputSize) / inputSize * 100;
@@ -71492,8 +71505,8 @@ Audio:`);
71492
71505
  }),
71493
71506
  async execute(args, ctx) {
71494
71507
  try {
71495
- const absInput = resolve79(ctx.workingDirectory, args.input);
71496
- const absOutput = resolve79(ctx.workingDirectory, args.output);
71508
+ const absInput = resolve81(ctx.workingDirectory, args.input);
71509
+ const absOutput = resolve81(ctx.workingDirectory, args.output);
71497
71510
  const codecMap = {
71498
71511
  h264: "libx264",
71499
71512
  h265: "libx265",
@@ -71544,11 +71557,11 @@ Audio:`);
71544
71557
  };
71545
71558
  }
71546
71559
  try {
71547
- const absOutput = resolve79(ctx.workingDirectory, args.output);
71560
+ const absOutput = resolve81(ctx.workingDirectory, args.output);
71548
71561
  if (args.reencode) {
71549
71562
  const ffmpegArgs = [];
71550
71563
  for (const i of args.inputs) {
71551
- ffmpegArgs.push("-i", resolve79(ctx.workingDirectory, i));
71564
+ ffmpegArgs.push("-i", resolve81(ctx.workingDirectory, i));
71552
71565
  }
71553
71566
  const filterComplex = args.inputs.map((_, i) => `[${i}:v][${i}:a]`).join("");
71554
71567
  ffmpegArgs.push(
@@ -71563,9 +71576,9 @@ Audio:`);
71563
71576
  );
71564
71577
  await execSafe("ffmpeg", ffmpegArgs, { maxBuffer: 100 * 1024 * 1024 });
71565
71578
  } else {
71566
- const tempList = resolve79(ctx.workingDirectory, `concat-list-${Date.now()}.txt`);
71567
- const listContent = args.inputs.map((i) => `file '${resolve79(ctx.workingDirectory, i)}'`).join("\n");
71568
- await writeFile57(tempList, listContent, "utf-8");
71579
+ const tempList = resolve81(ctx.workingDirectory, `concat-list-${Date.now()}.txt`);
71580
+ const listContent = args.inputs.map((i) => `file '${resolve81(ctx.workingDirectory, i)}'`).join("\n");
71581
+ await writeFile58(tempList, listContent, "utf-8");
71569
71582
  try {
71570
71583
  await execSafe(
71571
71584
  "ffmpeg",
@@ -71659,7 +71672,7 @@ var init_walkthrough = __esm({
71659
71672
  });
71660
71673
 
71661
71674
  // src/tools/manifest/status.ts
71662
- import { resolve as resolve80 } from "node:path";
71675
+ import { resolve as resolve82 } from "node:path";
71663
71676
  var statusJobTool, statusProjectTool, statusTools;
71664
71677
  var init_status = __esm({
71665
71678
  "src/tools/manifest/status.ts"() {
@@ -71680,7 +71693,7 @@ var init_status = __esm({
71680
71693
  output: external_exports.string().optional().describe("Download result media to this path when complete.")
71681
71694
  }),
71682
71695
  async execute(args, ctx) {
71683
- const projectDir = args.projectDir ? resolve80(ctx.workingDirectory, args.projectDir) : findProjectRoot(ctx.workingDirectory);
71696
+ const projectDir = args.projectDir ? resolve82(ctx.workingDirectory, args.projectDir) : findProjectRoot(ctx.workingDirectory);
71684
71697
  const record = await readJobRecord(args.jobId, projectDir);
71685
71698
  if (!record) return { success: false, error: `Job not found: ${args.jobId}` };
71686
71699
  const result = args.refresh === false ? makeJobStatusResult(record, {
@@ -71689,7 +71702,7 @@ var init_status = __esm({
71689
71702
  warnings: []
71690
71703
  }) : await refreshJobRecord(record, {
71691
71704
  wait: args.wait,
71692
- output: args.output ? resolve80(ctx.workingDirectory, args.output) : void 0,
71705
+ output: args.output ? resolve82(ctx.workingDirectory, args.output) : void 0,
71693
71706
  workingDirectory: ctx.workingDirectory
71694
71707
  });
71695
71708
  return {
@@ -71712,7 +71725,7 @@ var init_status = __esm({
71712
71725
  refresh: external_exports.boolean().optional().describe("Refresh active supported jobs before summarizing. Default false.")
71713
71726
  }),
71714
71727
  async execute(args, ctx) {
71715
- const projectDir = args.projectDir ? resolve80(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
71728
+ const projectDir = args.projectDir ? resolve82(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
71716
71729
  const result = await inspectProjectStatus(projectDir, { refresh: args.refresh === true });
71717
71730
  return {
71718
71731
  success: true,
@@ -71994,8 +72007,8 @@ init_source();
71994
72007
  // package.json
71995
72008
  var package_default = {
71996
72009
  name: "@vibeframe/cli",
71997
- version: "0.106.3",
71998
- description: "VibeFrame CLI - natural language video editing from the terminal",
72010
+ version: "0.106.5",
72011
+ description: "VibeFrame CLI - agentic video workflow runtime",
71999
72012
  private: false,
72000
72013
  license: "MIT",
72001
72014
  repository: {
@@ -78013,9 +78026,9 @@ function parseLrc(lrcString) {
78013
78026
  const minutes = Number.parseInt(match[1], 10);
78014
78027
  const seconds = Number.parseInt(match[2], 10);
78015
78028
  const ms = match[3].length === 3 ? Number.parseInt(match[3], 10) : Number.parseInt(match[3], 10) * 10;
78016
- const timestamp = (minutes * 60 + seconds) * 1e3 + ms;
78029
+ const timestamp2 = (minutes * 60 + seconds) * 1e3 + ms;
78017
78030
  const text = line.replace(TIMESTAMP_REGEX, "").trim();
78018
- syncText.push({ timestamp, text });
78031
+ syncText.push({ timestamp: timestamp2, text });
78019
78032
  }
78020
78033
  }
78021
78034
  return {
@@ -79170,12 +79183,12 @@ function resolveCopier() {
79170
79183
  async function copyToClipboard(text) {
79171
79184
  const opener = resolveCopier();
79172
79185
  if (!opener) return false;
79173
- return new Promise((resolve81) => {
79186
+ return new Promise((resolve83) => {
79174
79187
  let settled = false;
79175
79188
  const finish = (ok) => {
79176
79189
  if (settled) return;
79177
79190
  settled = true;
79178
- resolve81(ok);
79191
+ resolve83(ok);
79179
79192
  };
79180
79193
  try {
79181
79194
  const child = spawn2(opener.command, opener.args, {
@@ -80428,9 +80441,9 @@ init_source();
80428
80441
  init_agent_host_detect();
80429
80442
  init_scene_project();
80430
80443
  init_visual_styles();
80431
- import { existsSync as existsSync40 } from "node:fs";
80432
- import { mkdir as mkdir22, readFile as readFile37, writeFile as writeFile44 } from "node:fs/promises";
80433
- import { basename as basename19, dirname as dirname18, resolve as resolve53 } from "node:path";
80444
+ import { existsSync as existsSync41 } from "node:fs";
80445
+ import { mkdir as mkdir23, readFile as readFile38, writeFile as writeFile45 } from "node:fs/promises";
80446
+ import { basename as basename19, dirname as dirname19, resolve as resolve54 } from "node:path";
80434
80447
 
80435
80448
  // src/commands/_shared/storyboard-draft.ts
80436
80449
  init_scene_project();
@@ -80588,6 +80601,261 @@ function escapeRegExp2(value) {
80588
80601
  init_project_config();
80589
80602
  init_install_skill();
80590
80603
 
80604
+ // src/commands/_shared/host-integration.ts
80605
+ import { existsSync as existsSync40 } from "node:fs";
80606
+ import { mkdir as mkdir22, readFile as readFile37, writeFile as writeFile44 } from "node:fs/promises";
80607
+ import { homedir as homedir6 } from "node:os";
80608
+ import { dirname as dirname18, join as join19, resolve as resolve53 } from "node:path";
80609
+ var HOST_SELECTIONS = [
80610
+ "codex",
80611
+ "claude",
80612
+ "claude-code",
80613
+ "claude-desktop",
80614
+ "cursor",
80615
+ "all"
80616
+ ];
80617
+ var VIBEFRAME_MCP_JSON = {
80618
+ command: "npx",
80619
+ args: ["-y", "@vibeframe/mcp-server"]
80620
+ };
80621
+ var CODEX_MCP_BLOCK = `[mcp_servers.vibeframe]
80622
+ command = "npx"
80623
+ args = ["-y", "@vibeframe/mcp-server"]
80624
+ enabled = true
80625
+ `;
80626
+ var CODEX_MANAGED_START = "# >>> VibeFrame MCP server >>>";
80627
+ var CODEX_MANAGED_END = "# <<< VibeFrame MCP server <<<";
80628
+ function hostDefinitions(_projectDir = process.cwd()) {
80629
+ return [
80630
+ {
80631
+ id: "codex",
80632
+ label: "OpenAI Codex",
80633
+ surfaces: ["shell", "project-guidance", "mcp"],
80634
+ guidanceFiles: ["AGENTS.md"],
80635
+ configPath: (dir) => join19(resolve53(dir), ".codex", "config.toml"),
80636
+ configKind: "codex-toml",
80637
+ notes: [
80638
+ "Codex reads AGENTS.md and can also load project-scoped .codex/config.toml after the project is trusted.",
80639
+ "Keep provider/auth keys in VibeFrame config or environment, not in project-local Codex config."
80640
+ ]
80641
+ },
80642
+ {
80643
+ id: "claude-code",
80644
+ label: "Claude Code",
80645
+ surfaces: ["shell", "project-guidance", "mcp"],
80646
+ guidanceFiles: ["AGENTS.md", "CLAUDE.md", ".claude/skills/hyperframes/"],
80647
+ configPath: (dir) => join19(resolve53(dir), ".mcp.json"),
80648
+ configKind: "mcp-json",
80649
+ notes: [
80650
+ "Claude Code can drive vibe directly through shell plus AGENTS.md/CLAUDE.md.",
80651
+ "The MCP entry is optional and gives Claude Code a typed tool surface."
80652
+ ]
80653
+ },
80654
+ {
80655
+ id: "claude-desktop",
80656
+ label: "Claude Desktop",
80657
+ surfaces: ["mcp"],
80658
+ guidanceFiles: [],
80659
+ configPath: (_dir) => claudeDesktopConfigPath(),
80660
+ configKind: "mcp-json",
80661
+ notes: [
80662
+ "Claude Desktop uses MCP config rather than project shell commands.",
80663
+ "With --write, VibeFrame backs up the existing config before merging."
80664
+ ]
80665
+ },
80666
+ {
80667
+ id: "cursor",
80668
+ label: "Cursor",
80669
+ surfaces: ["shell", "project-guidance", "mcp"],
80670
+ guidanceFiles: ["AGENTS.md", ".cursor/rules/hyperframes.mdc"],
80671
+ configPath: (dir) => join19(resolve53(dir), ".cursor", "mcp.json"),
80672
+ configKind: "mcp-json",
80673
+ notes: [
80674
+ "Cursor can use AGENTS.md/rules for shell-driven work and .cursor/mcp.json for typed MCP tools."
80675
+ ]
80676
+ }
80677
+ ];
80678
+ }
80679
+ function resolveHostSelection(selection) {
80680
+ if (selection === "all") return ["codex", "claude-code", "claude-desktop", "cursor"];
80681
+ if (selection === "claude") return ["claude-code", "claude-desktop"];
80682
+ return [selection];
80683
+ }
80684
+ function renderHostSnippet(host, _projectDir) {
80685
+ if (host.configKind === "codex-toml") return CODEX_MCP_BLOCK.trimEnd();
80686
+ return JSON.stringify({ mcpServers: { vibeframe: VIBEFRAME_MCP_JSON } }, null, 2);
80687
+ }
80688
+ function claudeCodeAddCommand() {
80689
+ return "claude mcp add vibeframe --scope project -- npx -y @vibeframe/mcp-server";
80690
+ }
80691
+ async function planHostSetup(host, projectDir, opts) {
80692
+ const configPath = host.configPath(projectDir);
80693
+ const snippet = renderHostSnippet(host, projectDir);
80694
+ const files = [];
80695
+ const warnings = [];
80696
+ const nextSteps = hostNextSteps(host);
80697
+ for (const relPath of host.guidanceFiles.filter((p) => !p.endsWith("/"))) {
80698
+ const absPath = join19(resolve53(projectDir), relPath);
80699
+ files.push({
80700
+ path: absPath,
80701
+ status: existsSync40(absPath) ? "skipped-exists" : "missing",
80702
+ reason: existsSync40(absPath) ? "already present" : "run vibe init --agent all first"
80703
+ });
80704
+ }
80705
+ if (!opts.write || opts.dryRun) {
80706
+ files.push({
80707
+ path: configPath,
80708
+ status: opts.write ? "would-merge" : "would-write",
80709
+ reason: opts.write ? "dry run" : "snippet only; pass --write to modify"
80710
+ });
80711
+ return { host, snippet, command: host.id === "claude-code" ? claudeCodeAddCommand() : void 0, configPath, files, warnings, nextSteps };
80712
+ }
80713
+ try {
80714
+ const action = host.configKind === "codex-toml" ? await mergeCodexToml(configPath, { force: opts.force === true }) : await mergeMcpJson(configPath, {
80715
+ force: opts.force === true,
80716
+ backup: host.id === "claude-desktop"
80717
+ });
80718
+ files.push(action);
80719
+ } catch (error) {
80720
+ warnings.push(error instanceof Error ? error.message : String(error));
80721
+ }
80722
+ return { host, snippet, command: host.id === "claude-code" ? claudeCodeAddCommand() : void 0, configPath, files, warnings, nextSteps };
80723
+ }
80724
+ async function inspectHost(host, projectDir) {
80725
+ const configPath = host.configPath(projectDir);
80726
+ const warnings = [];
80727
+ const nextSteps = hostNextSteps(host);
80728
+ const guidanceFiles = host.guidanceFiles.map((relPath) => {
80729
+ const absPath = relPath.endsWith("/") ? join19(resolve53(projectDir), relPath) : join19(resolve53(projectDir), relPath);
80730
+ return {
80731
+ path: absPath,
80732
+ status: existsSync40(absPath) ? "skipped-exists" : "missing",
80733
+ reason: existsSync40(absPath) ? "present" : "missing"
80734
+ };
80735
+ });
80736
+ let configured = false;
80737
+ if (existsSync40(configPath)) {
80738
+ try {
80739
+ const content = await readFile37(configPath, "utf-8");
80740
+ configured = host.configKind === "codex-toml" ? /\[mcp_servers\.vibeframe\]/.test(content) : hasVibeframeMcpServer(JSON.parse(content));
80741
+ } catch (error) {
80742
+ warnings.push(error instanceof Error ? error.message : String(error));
80743
+ }
80744
+ }
80745
+ return { host, configPath, configured, guidanceFiles, warnings, nextSteps };
80746
+ }
80747
+ async function mergeMcpJson(configPath, opts) {
80748
+ let root = {};
80749
+ const exists = existsSync40(configPath);
80750
+ if (exists) {
80751
+ const raw = await readFile37(configPath, "utf-8");
80752
+ try {
80753
+ root = raw.trim() ? JSON.parse(raw) : {};
80754
+ } catch (error) {
80755
+ throw new Error(`Invalid JSON in ${configPath}: ${error instanceof Error ? error.message : String(error)}`);
80756
+ }
80757
+ }
80758
+ const mcpServers = typeof root.mcpServers === "object" && root.mcpServers !== null && !Array.isArray(root.mcpServers) ? root.mcpServers : {};
80759
+ if (mcpServers.vibeframe && !opts.force) {
80760
+ return {
80761
+ path: configPath,
80762
+ status: "skipped-exists",
80763
+ reason: "vibeframe MCP server already exists; pass --force to replace"
80764
+ };
80765
+ }
80766
+ root.mcpServers = { ...mcpServers, vibeframe: VIBEFRAME_MCP_JSON };
80767
+ await mkdir22(dirname18(configPath), { recursive: true });
80768
+ if (exists && opts.backup) {
80769
+ await writeFile44(`${configPath}.bak-${timestamp()}`, await readFile37(configPath, "utf-8"), "utf-8");
80770
+ }
80771
+ await writeFile44(configPath, JSON.stringify(root, null, 2) + "\n", "utf-8");
80772
+ return { path: configPath, status: exists ? "merged" : "wrote" };
80773
+ }
80774
+ async function mergeCodexToml(configPath, opts) {
80775
+ const exists = existsSync40(configPath);
80776
+ const block = `${CODEX_MANAGED_START}
80777
+ ${CODEX_MCP_BLOCK}${CODEX_MANAGED_END}`;
80778
+ if (!exists) {
80779
+ await mkdir22(dirname18(configPath), { recursive: true });
80780
+ await writeFile44(configPath, `#:schema https://developers.openai.com/codex/config-schema.json
80781
+
80782
+ ${block}
80783
+ `, "utf-8");
80784
+ return { path: configPath, status: "wrote" };
80785
+ }
80786
+ const raw = await readFile37(configPath, "utf-8");
80787
+ if (raw.includes(CODEX_MANAGED_START)) {
80788
+ const updated = raw.replace(
80789
+ new RegExp(`${escapeRegExp3(CODEX_MANAGED_START)}[\\s\\S]*?${escapeRegExp3(CODEX_MANAGED_END)}`),
80790
+ block
80791
+ );
80792
+ await writeFile44(configPath, ensureTrailingNewline(updated), "utf-8");
80793
+ return { path: configPath, status: "merged", reason: "updated managed VibeFrame block" };
80794
+ }
80795
+ if (/\[mcp_servers\.vibeframe\]/.test(raw)) {
80796
+ if (!opts.force) {
80797
+ return {
80798
+ path: configPath,
80799
+ status: "skipped-exists",
80800
+ reason: "vibeframe MCP table already exists; pass --force to replace"
80801
+ };
80802
+ }
80803
+ const updated = raw.replace(/\n?\[mcp_servers\.vibeframe\][\s\S]*?(?=\n\[|$)/, `
80804
+ ${block}
80805
+ `);
80806
+ await writeFile44(configPath, ensureTrailingNewline(updated), "utf-8");
80807
+ return { path: configPath, status: "merged", reason: "replaced existing VibeFrame MCP table" };
80808
+ }
80809
+ await writeFile44(configPath, `${ensureTrailingNewline(raw)}
80810
+ ${block}
80811
+ `, "utf-8");
80812
+ return { path: configPath, status: "merged" };
80813
+ }
80814
+ function hasVibeframeMcpServer(value) {
80815
+ if (!value || typeof value !== "object") return false;
80816
+ const root = value;
80817
+ if (!root.mcpServers || typeof root.mcpServers !== "object") return false;
80818
+ return Object.prototype.hasOwnProperty.call(root.mcpServers, "vibeframe");
80819
+ }
80820
+ function hostNextSteps(host) {
80821
+ if (host.id === "codex") {
80822
+ return [
80823
+ "Trust the project in Codex so .codex/config.toml is loaded.",
80824
+ "Run /mcp in Codex to confirm the vibeframe server is connected."
80825
+ ];
80826
+ }
80827
+ if (host.id === "claude-code") {
80828
+ return [
80829
+ "Restart Claude Code or run /mcp to approve the project-scoped server.",
80830
+ "Use AGENTS.md/CLAUDE.md for shell-driven vibe workflows."
80831
+ ];
80832
+ }
80833
+ if (host.id === "claude-desktop") {
80834
+ return ["Restart Claude Desktop after updating its MCP config."];
80835
+ }
80836
+ return ["Restart Cursor or reload MCP servers, then ask Cursor to use the vibeframe MCP tools."];
80837
+ }
80838
+ function claudeDesktopConfigPath() {
80839
+ const home = homedir6();
80840
+ if (process.platform === "darwin") {
80841
+ return join19(home, "Library", "Application Support", "Claude", "claude_desktop_config.json");
80842
+ }
80843
+ if (process.platform === "win32") {
80844
+ return join19(process.env.APPDATA ?? join19(home, "AppData", "Roaming"), "Claude", "claude_desktop_config.json");
80845
+ }
80846
+ return join19(home, ".config", "Claude", "claude_desktop_config.json");
80847
+ }
80848
+ function timestamp() {
80849
+ return (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
80850
+ }
80851
+ function ensureTrailingNewline(value) {
80852
+ return value.endsWith("\n") ? value : `${value}
80853
+ `;
80854
+ }
80855
+ function escapeRegExp3(value) {
80856
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
80857
+ }
80858
+
80591
80859
  // src/commands/_shared/init-templates.ts
80592
80860
  var AGENTS_MD = `# AGENTS.md
80593
80861
 
@@ -80628,6 +80896,8 @@ vibe schema --list # full machine-readable catalog (80+)
80628
80896
  vibe schema --list --surface public # small first-run/product command surface
80629
80897
  vibe schema generate.video # JSON Schema for any single command
80630
80898
  vibe doctor # available providers + system health
80899
+ vibe host setup all # print Codex/Claude/Cursor app integration snippets
80900
+ vibe host doctor all --json # verify project guidance + MCP config
80631
80901
  vibe guide motion # choose text-overlay vs motion-overlay vs generate motion
80632
80902
  vibe guide scene # step-by-step authoring guide (scene)
80633
80903
  vibe guide pipeline # step-by-step authoring guide (pipeline)
@@ -80752,6 +81022,22 @@ unless the user explicitly asks for a non-VibeFrame asset.
80752
81022
  \`.env\` is still supported as a gitignored fallback. Copy \`.env.example\`
80753
81023
  to start if you prefer environment variables.
80754
81024
 
81025
+ ## App host setup
81026
+
81027
+ VibeFrame is CLI-first, not terminal-only. Codex, Claude Code, and Cursor can
81028
+ drive the same project through shell commands, and app hosts can also use
81029
+ VibeFrame's MCP server as a typed tool surface.
81030
+
81031
+ \`\`\`bash
81032
+ vibe host setup all # print snippets only
81033
+ vibe host setup all --write # write project/app config
81034
+ vibe host doctor all --json # verify readiness
81035
+ \`\`\`
81036
+
81037
+ Default setup is snippet-only; use \`--write\` when you want VibeFrame to merge
81038
+ the generated config. Keep provider keys in \`.vibeframe/config.yaml\`, user
81039
+ config, or env files \u2014 not in app host config.
81040
+
80755
81041
  ### Composition rules (scene HTML)
80756
81042
 
80757
81043
  \`vibe init\` installs local composition rules into your project. The
@@ -80942,7 +81228,7 @@ var initCommand = new Command("init").description("Scaffold a VibeFrame project
80942
81228
  ).option(
80943
81229
  "--from <brief>",
80944
81230
  "Draft STORYBOARD.md and DESIGN.md from a brief string or text/markdown file"
80945
- ).option("-r, --ratio <ratio>", "Scene aspect ratio: 16:9, 9:16, 1:1, 4:5", "16:9").option("-d, --duration <sec>", "Default scene/root duration in seconds", "10").option("--visual-style <name>", "Seed scene DESIGN.md from a named style").option("--agent <id>", `Agent target: ${VALID_AGENTS.join(" | ")}`, "auto").option("--force", "Overwrite existing files instead of skipping").option("--dry-run", "Print the file list without writing anything").action(async (projectDirArg, options) => {
81231
+ ).option("-r, --ratio <ratio>", "Scene aspect ratio: 16:9, 9:16, 1:1, 4:5", "16:9").option("-d, --duration <sec>", "Default scene/root duration in seconds", "10").option("--visual-style <name>", "Seed scene DESIGN.md from a named style").option("--agent <id>", `Agent target: ${VALID_AGENTS.join(" | ")}`, "auto").option("--mcp", "Also write project-scoped MCP config for Codex/Claude Code/Cursor").option("--force", "Overwrite existing files instead of skipping").option("--dry-run", "Print the file list without writing anything").action(async (projectDirArg, options) => {
80946
81232
  const startedAt = Date.now();
80947
81233
  const initType = String(options.type ?? "scene");
80948
81234
  if (initType !== "scene" && initType !== "agent") {
@@ -80958,14 +81244,14 @@ var initCommand = new Command("init").description("Scaffold a VibeFrame project
80958
81244
  usageError(`Invalid --agent: ${agent}`, `Must be one of: ${VALID_AGENTS.join(", ")}`)
80959
81245
  );
80960
81246
  }
80961
- const projectDir = resolve53(projectDirArg);
81247
+ const projectDir = resolve54(projectDirArg);
80962
81248
  const projectName = basename19(projectDir);
80963
81249
  const targetHosts = resolveTargets(agent);
80964
81250
  const wantsClaude = targetHosts.includes("claude-code");
80965
81251
  const wantsGemini = targetHosts.includes("gemini-cli");
80966
81252
  const wantsCrossTool = targetHosts.some((h) => h !== "claude-code");
80967
81253
  const actions = [];
80968
- if (!existsSync40(projectDir)) {
81254
+ if (!existsSync41(projectDir)) {
80969
81255
  if (options.dryRun) {
80970
81256
  actions.push({
80971
81257
  path: projectDir,
@@ -80973,13 +81259,13 @@ var initCommand = new Command("init").description("Scaffold a VibeFrame project
80973
81259
  reason: "(would create directory)"
80974
81260
  });
80975
81261
  } else {
80976
- await mkdir22(projectDir, { recursive: true });
81262
+ await mkdir23(projectDir, { recursive: true });
80977
81263
  }
80978
81264
  }
80979
81265
  if (wantsCrossTool || !wantsClaude) {
80980
81266
  actions.push(
80981
81267
  await writeIfMissing(
80982
- resolve53(projectDir, "AGENTS.md"),
81268
+ resolve54(projectDir, "AGENTS.md"),
80983
81269
  AGENTS_MD,
80984
81270
  options.force,
80985
81271
  options.dryRun
@@ -80989,7 +81275,7 @@ var initCommand = new Command("init").description("Scaffold a VibeFrame project
80989
81275
  if (wantsClaude) {
80990
81276
  actions.push(
80991
81277
  await writeIfMissing(
80992
- resolve53(projectDir, "CLAUDE.md"),
81278
+ resolve54(projectDir, "CLAUDE.md"),
80993
81279
  CLAUDE_MD,
80994
81280
  options.force,
80995
81281
  options.dryRun
@@ -80999,7 +81285,7 @@ var initCommand = new Command("init").description("Scaffold a VibeFrame project
80999
81285
  if (wantsGemini) {
81000
81286
  actions.push(
81001
81287
  await writeIfMissing(
81002
- resolve53(projectDir, "GEMINI.md"),
81288
+ resolve54(projectDir, "GEMINI.md"),
81003
81289
  GEMINI_MD,
81004
81290
  options.force,
81005
81291
  options.dryRun
@@ -81008,18 +81294,18 @@ var initCommand = new Command("init").description("Scaffold a VibeFrame project
81008
81294
  }
81009
81295
  actions.push(
81010
81296
  await writeIfMissing(
81011
- resolve53(projectDir, ".env.example"),
81297
+ resolve54(projectDir, ".env.example"),
81012
81298
  renderEnvExample(),
81013
81299
  options.force,
81014
81300
  options.dryRun
81015
81301
  )
81016
81302
  );
81017
81303
  actions.push(
81018
- await mergeGitignore(resolve53(projectDir, ".gitignore"), GITIGNORE_ADDITIONS, options.dryRun)
81304
+ await mergeGitignore(resolve54(projectDir, ".gitignore"), GITIGNORE_ADDITIONS, options.dryRun)
81019
81305
  );
81020
81306
  actions.push(
81021
81307
  await writeIfMissing(
81022
- resolve53(projectDir, VIBE_CONFIG_FILENAME),
81308
+ resolve54(projectDir, VIBE_CONFIG_FILENAME),
81023
81309
  projectConfigJson({ name: projectName }),
81024
81310
  options.force,
81025
81311
  options.dryRun
@@ -81027,12 +81313,20 @@ var initCommand = new Command("init").description("Scaffold a VibeFrame project
81027
81313
  );
81028
81314
  actions.push(
81029
81315
  await writeIfMissing(
81030
- resolve53(projectDir, "vibe.project.yaml"),
81316
+ resolve54(projectDir, "vibe.project.yaml"),
81031
81317
  renderProjectYaml({ name: projectName }),
81032
81318
  options.force,
81033
81319
  options.dryRun
81034
81320
  )
81035
81321
  );
81322
+ if (options.mcp === true) {
81323
+ actions.push(
81324
+ ...await setupProjectMcpTargets(projectDir, targetHosts, {
81325
+ force: options.force === true,
81326
+ dryRun: options.dryRun === true
81327
+ })
81328
+ );
81329
+ }
81036
81330
  if (isJsonMode()) {
81037
81331
  outputSuccess({
81038
81332
  command: "init",
@@ -81117,7 +81411,7 @@ async function runSceneInit(projectDirArg, options, startedAt) {
81117
81411
  )
81118
81412
  );
81119
81413
  }
81120
- const projectDir = resolve53(projectDirArg);
81414
+ const projectDir = resolve54(projectDirArg);
81121
81415
  const projectName = basename19(projectDir);
81122
81416
  const groups = describeSceneScaffold({ dir: projectDir, profile });
81123
81417
  const fromBrief = typeof options.from === "string" && options.from.trim() ? await readBriefOrLiteral(String(options.from), process.cwd()) : null;
@@ -81170,14 +81464,14 @@ async function runSceneInit(projectDirArg, options, startedAt) {
81170
81464
  aspect,
81171
81465
  visualStyle
81172
81466
  });
81173
- const storyboardPath2 = resolve53(projectDir, "STORYBOARD.md");
81174
- const designPath = resolve53(projectDir, "DESIGN.md");
81175
- if (options.force || result.created.includes(storyboardPath2) || !existsSync40(storyboardPath2)) {
81176
- await writeFile44(storyboardPath2, draft.storyboardMd, "utf-8");
81467
+ const storyboardPath2 = resolve54(projectDir, "STORYBOARD.md");
81468
+ const designPath = resolve54(projectDir, "DESIGN.md");
81469
+ if (options.force || result.created.includes(storyboardPath2) || !existsSync41(storyboardPath2)) {
81470
+ await writeFile45(storyboardPath2, draft.storyboardMd, "utf-8");
81177
81471
  if (!result.created.includes(storyboardPath2)) result.created.push(storyboardPath2);
81178
81472
  }
81179
- if (options.force || result.created.includes(designPath) || !existsSync40(designPath)) {
81180
- await writeFile44(designPath, draft.designMd, "utf-8");
81473
+ if (options.force || result.created.includes(designPath) || !existsSync41(designPath)) {
81474
+ await writeFile45(designPath, draft.designMd, "utf-8");
81181
81475
  if (!result.created.includes(designPath)) result.created.push(designPath);
81182
81476
  }
81183
81477
  draftWarnings.push(...draft.warnings);
@@ -81187,6 +81481,10 @@ async function runSceneInit(projectDirArg, options, startedAt) {
81187
81481
  projectDir,
81188
81482
  hosts: deriveInstallHosts(detectedIds)
81189
81483
  }) : { success: true, files: [], bundleVersion: "not-installed" };
81484
+ const mcpActions = options.mcp === true ? await setupProjectMcpTargets(projectDir, detectedIds, {
81485
+ force: options.force === true,
81486
+ dryRun: false
81487
+ }) : [];
81190
81488
  if (isJsonMode()) {
81191
81489
  outputSuccess({
81192
81490
  command: "init",
@@ -81206,6 +81504,7 @@ async function runSceneInit(projectDirArg, options, startedAt) {
81206
81504
  groups: result.groups,
81207
81505
  skillFiles: skillResult.files,
81208
81506
  skillBundleVersion: skillResult.bundleVersion,
81507
+ mcpFiles: mcpActions,
81209
81508
  warnings: draftWarnings
81210
81509
  }
81211
81510
  });
@@ -81243,6 +81542,10 @@ async function runSceneInit(projectDirArg, options, startedAt) {
81243
81542
  for (const f of skillResult.files.filter((f2) => f2.status === "wrote")) {
81244
81543
  console.log(source_default.green(` + ${f.path.replace(projectDir + "/", "")}`));
81245
81544
  }
81545
+ for (const f of mcpActions) {
81546
+ const icon = f.status === "wrote" || f.status === "merged" ? source_default.green("+") : source_default.dim("\xB7");
81547
+ console.log(`${icon} ${f.path.replace(projectDir + "/", "")} ${source_default.dim(`(${f.status})`)}`);
81548
+ }
81246
81549
  console.log();
81247
81550
  console.log(source_default.dim(`Tip: cd ${projectDirArg} before running the next commands.`));
81248
81551
  console.log();
@@ -81290,9 +81593,9 @@ function printGroup(label, files, projectDir) {
81290
81593
  }
81291
81594
  }
81292
81595
  async function readBriefOrLiteral(value, cwd) {
81293
- const candidate = resolve53(cwd, value);
81294
- if (existsSync40(candidate)) {
81295
- return readFile37(candidate, "utf-8");
81596
+ const candidate = resolve54(cwd, value);
81597
+ if (existsSync41(candidate)) {
81598
+ return readFile38(candidate, "utf-8");
81296
81599
  }
81297
81600
  return value;
81298
81601
  }
@@ -81311,32 +81614,65 @@ function resolveTargets(agent) {
81311
81614
  }
81312
81615
  return [agent];
81313
81616
  }
81617
+ async function setupProjectMcpTargets(projectDir, targetHosts, opts) {
81618
+ const ids = /* @__PURE__ */ new Set();
81619
+ if (targetHosts.includes("codex")) ids.add("codex");
81620
+ if (targetHosts.includes("claude-code")) ids.add("claude-code");
81621
+ if (targetHosts.includes("cursor")) ids.add("cursor");
81622
+ if (targetHosts.length === 0) {
81623
+ ids.add("codex");
81624
+ ids.add("claude-code");
81625
+ ids.add("cursor");
81626
+ }
81627
+ const actions = [];
81628
+ for (const host of hostDefinitions(projectDir).filter((h) => ids.has(h.id))) {
81629
+ const plan = await planHostSetup(host, projectDir, {
81630
+ write: true,
81631
+ dryRun: opts.dryRun,
81632
+ force: opts.force
81633
+ });
81634
+ const configAction = plan.files.find((file) => file.path === plan.configPath);
81635
+ if (!configAction) continue;
81636
+ actions.push({
81637
+ path: configAction.path,
81638
+ status: normalizeHostAction(configAction.status),
81639
+ reason: configAction.reason
81640
+ });
81641
+ }
81642
+ return actions;
81643
+ }
81644
+ function normalizeHostAction(status) {
81645
+ if (status === "merged") return "merged";
81646
+ if (status === "wrote") return "wrote";
81647
+ if (status === "skipped-exists") return "skipped-exists";
81648
+ return "would-write";
81649
+ }
81314
81650
  async function writeIfMissing(absPath, content, force, dryRun) {
81315
- const exists = existsSync40(absPath);
81651
+ const exists = existsSync41(absPath);
81316
81652
  if (exists && !force) {
81317
81653
  return { path: absPath, status: "skipped-exists", reason: "(use --force to overwrite)" };
81318
81654
  }
81319
81655
  if (dryRun) {
81320
81656
  return { path: absPath, status: "would-write" };
81321
81657
  }
81322
- await mkdir22(dirname18(absPath), { recursive: true });
81323
- await writeFile44(absPath, content, "utf-8");
81658
+ await mkdir23(dirname19(absPath), { recursive: true });
81659
+ await writeFile45(absPath, content, "utf-8");
81324
81660
  return { path: absPath, status: "wrote" };
81325
81661
  }
81326
81662
  async function mergeGitignore(absPath, additions, dryRun) {
81327
81663
  const marker = "# VibeFrame";
81328
- if (!existsSync40(absPath)) {
81664
+ if (!existsSync41(absPath)) {
81329
81665
  if (dryRun) return { path: absPath, status: "would-write" };
81330
- await writeFile44(absPath, additions.trimStart(), "utf-8");
81666
+ await writeFile45(absPath, additions.trimStart(), "utf-8");
81331
81667
  return { path: absPath, status: "wrote" };
81332
81668
  }
81333
- const existing = await readFile37(absPath, "utf-8");
81669
+ const existing = await readFile38(absPath, "utf-8");
81334
81670
  if (existing.includes(marker)) {
81335
81671
  return { path: absPath, status: "skipped-exists", reason: "(already has VibeFrame block)" };
81336
81672
  }
81337
81673
  if (dryRun) return { path: absPath, status: "merged" };
81338
81674
  const trailing = existing.endsWith("\n") ? "" : "\n";
81339
- await writeFile44(absPath, existing + trailing + additions, "utf-8");
81675
+ await writeFile45(absPath, existing + trailing + additions, "utf-8");
81340
81676
  return { path: absPath, status: "merged" };
81341
81677
  }
81342
81678
  function formatStatusIcon(status) {
@@ -81363,9 +81699,9 @@ init_storyboard_revise();
81363
81699
  init_composer_resolve();
81364
81700
  init_cost_tier();
81365
81701
  init_output();
81366
- import { readFile as readFile39, writeFile as writeFile46 } from "node:fs/promises";
81367
- import { existsSync as existsSync42 } from "node:fs";
81368
- import { resolve as resolve55 } from "node:path";
81702
+ import { readFile as readFile40, writeFile as writeFile47 } from "node:fs/promises";
81703
+ import { existsSync as existsSync43 } from "node:fs";
81704
+ import { resolve as resolve56 } from "node:path";
81369
81705
  var storyboardCommand = new Command("storyboard").description("Read, validate, and safely mutate STORYBOARD.md cue blocks").addHelpText("after", `
81370
81706
  Examples:
81371
81707
  $ vibe storyboard validate my-video --json
@@ -81377,7 +81713,7 @@ Examples:
81377
81713
  `);
81378
81714
  storyboardCommand.command("list").description("List beats, ids, cues, and durations from STORYBOARD.md").argument("[project-dir]", "Project directory", ".").action(async (projectDirArg) => {
81379
81715
  const startedAt = Date.now();
81380
- const projectDir = resolve55(projectDirArg);
81716
+ const projectDir = resolve56(projectDirArg);
81381
81717
  const md = await readStoryboard(projectDir);
81382
81718
  const parsed = parseStoryboard(md);
81383
81719
  const data = {
@@ -81399,7 +81735,7 @@ storyboardCommand.command("list").description("List beats, ids, cues, and durati
81399
81735
  });
81400
81736
  storyboardCommand.command("get").description("Print one beat as structured JSON").argument("<project-dir>", "Project directory").argument("<beat>", "Beat id").action(async (projectDirArg, beatId) => {
81401
81737
  const startedAt = Date.now();
81402
- const projectDir = resolve55(projectDirArg);
81738
+ const projectDir = resolve56(projectDirArg);
81403
81739
  const md = await readStoryboard(projectDir);
81404
81740
  const beat = getStoryboardBeat(md, beatId);
81405
81741
  if (!beat) {
@@ -81422,7 +81758,7 @@ storyboardCommand.command("get").description("Print one beat as structured JSON"
81422
81758
  });
81423
81759
  storyboardCommand.command("set").description("Update one cue in one beat without raw Markdown editing").argument("<project-dir>", "Project directory").argument("<beat>", "Beat id").argument("<key>", `Cue key: ${STORYBOARD_CUE_KEYS.join(" | ")}`).argument("[value...]", "Cue value. Use --json-value to pass a JSON scalar/object.").option("--json-value", "Parse value as JSON instead of a string").option("--unset", "Remove the cue key from the beat").action(async (projectDirArg, beatId, key, valueParts, options) => {
81424
81760
  const startedAt = Date.now();
81425
- const projectDir = resolve55(projectDirArg);
81761
+ const projectDir = resolve56(projectDirArg);
81426
81762
  if (!options.unset && (!valueParts || valueParts.length === 0)) {
81427
81763
  exitWithError(usageError("Cue value is required unless --unset is passed."));
81428
81764
  }
@@ -81441,7 +81777,7 @@ storyboardCommand.command("set").description("Update one cue in one beat without
81441
81777
  } catch (error) {
81442
81778
  exitWithError(usageError(error instanceof Error ? error.message : String(error)));
81443
81779
  }
81444
- await writeFile46(storyboardPath(projectDir), next, "utf-8");
81780
+ await writeFile47(storyboardPath(projectDir), next, "utf-8");
81445
81781
  const beat = getStoryboardBeat(next, beatId);
81446
81782
  outputSuccess({
81447
81783
  command: "storyboard set",
@@ -81457,7 +81793,7 @@ storyboardCommand.command("set").description("Update one cue in one beat without
81457
81793
  });
81458
81794
  storyboardCommand.command("move").description("Reorder beats safely").argument("<project-dir>", "Project directory").argument("<beat>", "Beat id to move").requiredOption("--after <beat>", "Place the beat after this beat id").action(async (projectDirArg, beatId, options) => {
81459
81795
  const startedAt = Date.now();
81460
- const projectDir = resolve55(projectDirArg);
81796
+ const projectDir = resolve56(projectDirArg);
81461
81797
  const md = await readStoryboard(projectDir);
81462
81798
  let next;
81463
81799
  try {
@@ -81465,7 +81801,7 @@ storyboardCommand.command("move").description("Reorder beats safely").argument("
81465
81801
  } catch (error) {
81466
81802
  exitWithError(usageError(error instanceof Error ? error.message : String(error)));
81467
81803
  }
81468
- await writeFile46(storyboardPath(projectDir), next, "utf-8");
81804
+ await writeFile47(storyboardPath(projectDir), next, "utf-8");
81469
81805
  const parsed = parseStoryboard(next);
81470
81806
  outputSuccess({
81471
81807
  command: "storyboard move",
@@ -81480,7 +81816,7 @@ storyboardCommand.command("move").description("Reorder beats safely").argument("
81480
81816
  });
81481
81817
  storyboardCommand.command("revise").description("Revise STORYBOARD.md from a request or source file").argument("<project-dir>", "Project directory").requiredOption("--from <brief>", "Revision request or path to a text/markdown file").option("-d, --duration <sec>", "Target total duration in seconds").option("--composer <provider>", "Revision LLM provider: claude|openai|gemini").option("--dry-run", "Preview the revised storyboard without writing").action(async (projectDirArg, options) => {
81482
81818
  const startedAt = Date.now();
81483
- const projectDir = resolve55(projectDirArg);
81819
+ const projectDir = resolve56(projectDirArg);
81484
81820
  const brief = await readBrief(options.from, process.cwd());
81485
81821
  const duration = options.duration ? Number.parseFloat(options.duration) : void 0;
81486
81822
  if (duration !== void 0 && (!Number.isFinite(duration) || duration <= 0)) {
@@ -81512,7 +81848,7 @@ storyboardCommand.command("revise").description("Revise STORYBOARD.md from a req
81512
81848
  });
81513
81849
  storyboardCommand.command("validate").description("Validate cue blocks and beat ids").argument("[project-dir]", "Project directory", ".").action(async (projectDirArg) => {
81514
81850
  const startedAt = Date.now();
81515
- const projectDir = resolve55(projectDirArg);
81851
+ const projectDir = resolve56(projectDirArg);
81516
81852
  const md = await readStoryboard(projectDir);
81517
81853
  const result = validateStoryboardMarkdown(md);
81518
81854
  if (isJsonMode()) {
@@ -81547,13 +81883,13 @@ storyboardCommand.command("validate").description("Validate cue blocks and beat
81547
81883
  });
81548
81884
  async function readStoryboard(projectDir) {
81549
81885
  const path2 = storyboardPath(projectDir);
81550
- if (!existsSync42(path2)) {
81886
+ if (!existsSync43(path2)) {
81551
81887
  exitWithError(generalError(`STORYBOARD.md not found at ${path2}`, `Run 'vibe init ${projectDir} --from "<brief>"' first.`));
81552
81888
  }
81553
- return readFile39(path2, "utf-8");
81889
+ return readFile40(path2, "utf-8");
81554
81890
  }
81555
81891
  function storyboardPath(projectDir) {
81556
- return resolve55(projectDir, "STORYBOARD.md");
81892
+ return resolve56(projectDir, "STORYBOARD.md");
81557
81893
  }
81558
81894
  function parseComposer(value) {
81559
81895
  if (value === void 0) return void 0;
@@ -81561,9 +81897,9 @@ function parseComposer(value) {
81561
81897
  exitWithError(usageError(`Invalid --composer: ${value}`, "Must be one of: claude, openai, gemini"));
81562
81898
  }
81563
81899
  async function readBrief(value, cwd) {
81564
- const candidate = resolve55(cwd, value);
81565
- if (existsSync42(candidate)) {
81566
- return readFile39(candidate, "utf-8");
81900
+ const candidate = resolve56(cwd, value);
81901
+ if (existsSync43(candidate)) {
81902
+ return readFile40(candidate, "utf-8");
81567
81903
  }
81568
81904
  return value;
81569
81905
  }
@@ -81596,7 +81932,7 @@ init_esm();
81596
81932
  init_source();
81597
81933
  init_build_plan();
81598
81934
  init_output();
81599
- import { resolve as resolve58 } from "node:path";
81935
+ import { resolve as resolve59 } from "node:path";
81600
81936
  var VALID_STAGES = ["assets", "compose", "sync", "render", "all"];
81601
81937
  var VALID_MODES = ["agent", "batch", "auto"];
81602
81938
  var VALID_TTS_PROVIDERS = ["auto", "elevenlabs", "kokoro"];
@@ -81644,7 +81980,7 @@ var planCommand = new Command("plan").description("Read STORYBOARD.md and show b
81644
81980
  )
81645
81981
  );
81646
81982
  }
81647
- const projectDir = resolve58(projectDirArg);
81983
+ const projectDir = resolve59(projectDirArg);
81648
81984
  const plan = await createBuildPlan({
81649
81985
  projectDir,
81650
81986
  stage,
@@ -81789,8 +82125,8 @@ init_scene_build();
81789
82125
  init_build_plan();
81790
82126
  init_storyboard_parse();
81791
82127
  init_output();
81792
- import { resolve as resolve63, join as join23 } from "node:path";
81793
- import { readFileSync as readFileSync3, existsSync as existsSync47 } from "node:fs";
82128
+ import { resolve as resolve64, join as join24 } from "node:path";
82129
+ import { readFileSync as readFileSync3, existsSync as existsSync48 } from "node:fs";
81794
82130
  var VALID_MODES2 = ["agent", "batch", "auto"];
81795
82131
  var VALID_STAGES2 = ["assets", "compose", "sync", "render", "all"];
81796
82132
  var VALID_IMAGE_PROVIDERS2 = ["openai", "gemini", "grok"];
@@ -81807,7 +82143,7 @@ Examples:
81807
82143
  Advanced equivalent: \`vibe scene build\`.`
81808
82144
  ).action(async (projectDirArg, options) => {
81809
82145
  const startedAt = Date.now();
81810
- const projectDir = resolve63(projectDirArg);
82146
+ const projectDir = resolve64(projectDirArg);
81811
82147
  const mode = String(options.mode ?? "auto");
81812
82148
  if (!VALID_MODES2.includes(mode)) {
81813
82149
  exitWithError(
@@ -82153,8 +82489,8 @@ function buildPlanValidationFailureData(plan) {
82153
82489
  };
82154
82490
  }
82155
82491
  function estimateBuildCost(params) {
82156
- const storyboardPath2 = join23(params.projectDir, "STORYBOARD.md");
82157
- if (!existsSync47(storyboardPath2)) return null;
82492
+ const storyboardPath2 = join24(params.projectDir, "STORYBOARD.md");
82493
+ if (!existsSync48(storyboardPath2)) return null;
82158
82494
  let beats = 0;
82159
82495
  try {
82160
82496
  const md = readFileSync3(storyboardPath2, "utf-8");
@@ -82298,7 +82634,7 @@ init_source();
82298
82634
  init_ora();
82299
82635
  init_scene_render();
82300
82636
  init_output();
82301
- import { resolve as resolve64 } from "node:path";
82637
+ import { resolve as resolve65 } from "node:path";
82302
82638
  var VALID_FPS = [24, 30, 60];
82303
82639
  var VALID_QUALITIES = ["draft", "standard", "high"];
82304
82640
  var VALID_FORMATS = ["mp4", "webm", "mov"];
@@ -82309,7 +82645,7 @@ Examples:
82309
82645
 
82310
82646
  Alias note: this is the project-level entrypoint for \`vibe scene render\`.`).action(async (projectDirArg, options) => {
82311
82647
  const startedAt = Date.now();
82312
- const projectDir = resolve64(projectDirArg);
82648
+ const projectDir = resolve65(projectDirArg);
82313
82649
  const fps = parseFps(String(options.fps));
82314
82650
  const quality = parseQuality(String(options.quality));
82315
82651
  const format = parseFormat(String(options.format));
@@ -82432,7 +82768,7 @@ init_source();
82432
82768
  init_cost_tier();
82433
82769
  init_status_jobs();
82434
82770
  init_output();
82435
- import { resolve as resolve65 } from "node:path";
82771
+ import { resolve as resolve66 } from "node:path";
82436
82772
  var statusCommand = new Command("status").description("Inspect local async jobs and project workflow status").addHelpText("after", `
82437
82773
  Examples:
82438
82774
  $ vibe status job job_abc123 --json
@@ -82443,7 +82779,7 @@ Examples:
82443
82779
  statusCommand.command("job").description("Show one async job status").argument("<job-id>", "Local job id from a no-wait command").option("--project <dir>", "Project directory containing .vibeframe/jobs").option("--no-refresh", "Read local job record only; do not call provider APIs").option("--wait", "Wait for completion when the provider status helper supports it").option("-o, --output <path>", "Download result media when complete").action(async (jobId, options) => {
82444
82780
  const startedAt = Date.now();
82445
82781
  try {
82446
- const projectDir = options.project ? resolve65(options.project) : findProjectRoot();
82782
+ const projectDir = options.project ? resolve66(options.project) : findProjectRoot();
82447
82783
  const record = await readJobRecord(jobId, projectDir);
82448
82784
  if (!record) {
82449
82785
  exitWithError(generalError(`Job not found: ${jobId}`, `Run 'vibe status project ${projectDir} --json' to list known jobs.`));
@@ -82471,7 +82807,7 @@ applyTier(statusCommand.commands[statusCommand.commands.length - 1], "free");
82471
82807
  statusCommand.command("project").description("Summarize build, review, and async job status for a project").argument("[project-dir]", "VibeFrame project directory", ".").option("--refresh", "Refresh active supported jobs before summarizing").action(async (projectDirArg, options) => {
82472
82808
  const startedAt = Date.now();
82473
82809
  try {
82474
- const result = await inspectProjectStatus(resolve65(projectDirArg), {
82810
+ const result = await inspectProjectStatus(resolve66(projectDirArg), {
82475
82811
  refresh: options.refresh === true
82476
82812
  });
82477
82813
  if (isJsonMode()) {
@@ -82567,8 +82903,8 @@ init_composer_resolve();
82567
82903
  init_cost_tier();
82568
82904
  init_scene_build_mode();
82569
82905
  init_output();
82570
- import { existsSync as existsSync48 } from "node:fs";
82571
- import { resolve as resolve66 } from "node:path";
82906
+ import { existsSync as existsSync49 } from "node:fs";
82907
+ import { resolve as resolve67 } from "node:path";
82572
82908
  var COMMAND_KEY_MAP = getCommandKeyMap();
82573
82909
  var FREE_COMMANDS = [
82574
82910
  "edit silence-cut",
@@ -82695,14 +83031,14 @@ async function runDiagnostics() {
82695
83031
  installed = false;
82696
83032
  }
82697
83033
  } else if (toolName === "chrome") {
82698
- const { existsSync: existsSync54 } = await import("node:fs");
82699
- const { homedir: homedir6 } = await import("node:os");
82700
- const { join: join26 } = await import("node:path");
83034
+ const { existsSync: existsSync55 } = await import("node:fs");
83035
+ const { homedir: homedir7 } = await import("node:os");
83036
+ const { join: join27 } = await import("node:path");
82701
83037
  const chromePaths = [
82702
83038
  process.env.HYPERFRAMES_CHROME_PATH,
82703
83039
  process.env.CHROME_PATH,
82704
- join26(
82705
- homedir6(),
83040
+ join27(
83041
+ homedir7(),
82706
83042
  ".cache",
82707
83043
  "puppeteer",
82708
83044
  "chrome-headless-shell",
@@ -82716,7 +83052,7 @@ async function runDiagnostics() {
82716
83052
  "/usr/bin/chromium",
82717
83053
  "/usr/bin/chromium-browser"
82718
83054
  ];
82719
- installed = chromePaths.some((p) => p && existsSync54(p));
83055
+ installed = chromePaths.some((p) => p && existsSync55(p));
82720
83056
  } else {
82721
83057
  installed = commandExists(toolName);
82722
83058
  }
@@ -82756,7 +83092,7 @@ async function runDiagnostics() {
82756
83092
  }
82757
83093
  const projectFiles = ["AGENTS.md", "CLAUDE.md", "vibe.project.yaml"].map((rel) => ({
82758
83094
  path: rel,
82759
- exists: existsSync48(resolve66(cwd, rel))
83095
+ exists: existsSync49(resolve67(cwd, rel))
82760
83096
  }));
82761
83097
  const projectInitialized = projectFiles.some((f) => f.exists);
82762
83098
  const nearestProjectConfigPath = await findProjectConfigPath(cwd);
@@ -82775,8 +83111,8 @@ async function runDiagnostics() {
82775
83111
  } catch (err) {
82776
83112
  if (!(err instanceof ComposerResolveError)) throw err;
82777
83113
  }
82778
- const sceneProjectInCwd = existsSync48(resolve66(cwd, "STORYBOARD.md"));
82779
- const skillInstalled = existsSync48(resolve66(cwd, "SKILL.md"));
83114
+ const sceneProjectInCwd = existsSync49(resolve67(cwd, "STORYBOARD.md"));
83115
+ const skillInstalled = existsSync49(resolve67(cwd, "SKILL.md"));
82780
83116
  return {
82781
83117
  system: {
82782
83118
  node: { version: nodeVersion, ok: true },
@@ -83123,6 +83459,198 @@ function pickNextStep(results, hasMissingProviders) {
83123
83459
  return null;
83124
83460
  }
83125
83461
 
83462
+ // src/commands/host.ts
83463
+ init_esm();
83464
+ init_source();
83465
+ init_exec_safe();
83466
+ init_cost_tier();
83467
+ import { resolve as resolve68 } from "node:path";
83468
+ init_output();
83469
+ var hostCommand = new Command("host").description("Set up Codex, Claude, and Cursor app integrations").addHelpText(
83470
+ "after",
83471
+ `
83472
+ Examples:
83473
+ $ vibe host list --json
83474
+ $ vibe host setup all Print MCP/project config snippets
83475
+ $ vibe host setup cursor --write Write .cursor/mcp.json
83476
+ $ vibe host doctor all --json Check host-app readiness
83477
+ `
83478
+ );
83479
+ hostCommand.command("list").description("List supported app hosts and integration surfaces").action(() => {
83480
+ const startedAt = Date.now();
83481
+ const hosts = hostDefinitions(resolve68(".")).map((host) => ({
83482
+ id: host.id,
83483
+ label: host.label,
83484
+ surfaces: host.surfaces,
83485
+ guidanceFiles: host.guidanceFiles,
83486
+ notes: host.notes
83487
+ }));
83488
+ if (isJsonMode()) {
83489
+ outputSuccess({ command: "host list", startedAt, data: { hosts } });
83490
+ return;
83491
+ }
83492
+ console.log();
83493
+ console.log(source_default.bold.cyan("Supported Host Apps"));
83494
+ console.log(source_default.dim("\u2500".repeat(60)));
83495
+ for (const host of hosts) {
83496
+ console.log(` ${source_default.bold(host.label)} ${source_default.dim(`(${host.id})`)}`);
83497
+ console.log(source_default.dim(` surfaces: ${host.surfaces.join(", ")}`));
83498
+ if (host.guidanceFiles.length > 0) {
83499
+ console.log(source_default.dim(` files: ${host.guidanceFiles.join(", ")}`));
83500
+ }
83501
+ }
83502
+ console.log();
83503
+ });
83504
+ applyTier(hostCommand.commands[hostCommand.commands.length - 1], "free");
83505
+ hostCommand.command("setup").description("Print or write Codex/Claude/Cursor MCP and project integration config").argument("[host]", `Host target: ${HOST_SELECTIONS.join(" | ")}`, "all").argument("[project-dir]", "Project directory for project-scoped config", ".").option("--write", "Write config files instead of printing snippets only").option("--dry-run", "Show file actions without writing").option("--force", "Replace an existing vibeframe MCP entry").action(async (hostArg, projectDirArg, options) => {
83506
+ const startedAt = Date.now();
83507
+ const selection = validateHostSelection(hostArg);
83508
+ const projectDir = resolve68(projectDirArg);
83509
+ const ids = resolveHostSelection(selection);
83510
+ const defs = hostDefinitions(projectDir).filter((host) => ids.includes(host.id));
83511
+ const plans = [];
83512
+ for (const host of defs) {
83513
+ plans.push(
83514
+ await planHostSetup(host, projectDir, {
83515
+ write: Boolean(options.write),
83516
+ dryRun: Boolean(options.dryRun),
83517
+ force: Boolean(options.force)
83518
+ })
83519
+ );
83520
+ }
83521
+ if (isJsonMode()) {
83522
+ outputSuccess({
83523
+ command: "host setup",
83524
+ startedAt,
83525
+ ...options.dryRun ? { dryRun: true } : {},
83526
+ data: {
83527
+ projectDir,
83528
+ selection,
83529
+ write: Boolean(options.write),
83530
+ hosts: plans.map(serializeSetupPlan)
83531
+ },
83532
+ warnings: plans.flatMap((plan) => plan.warnings)
83533
+ });
83534
+ return;
83535
+ }
83536
+ printSetupPlans(plans, { write: Boolean(options.write), dryRun: Boolean(options.dryRun) });
83537
+ });
83538
+ applyTier(hostCommand.commands[hostCommand.commands.length - 1], "free");
83539
+ hostCommand.command("doctor").description("Check Codex/Claude/Cursor app integration readiness").argument("[host]", `Host target: ${HOST_SELECTIONS.join(" | ")}`, "all").argument("[project-dir]", "Project directory to inspect", ".").action(async (hostArg, projectDirArg) => {
83540
+ const startedAt = Date.now();
83541
+ const selection = validateHostSelection(hostArg);
83542
+ const projectDir = resolve68(projectDirArg);
83543
+ const ids = resolveHostSelection(selection);
83544
+ const defs = hostDefinitions(projectDir).filter((host) => ids.includes(host.id));
83545
+ const hosts = await Promise.all(defs.map((host) => inspectHost(host, projectDir)));
83546
+ const system = {
83547
+ vibe: commandExists("vibe"),
83548
+ npx: commandExists("npx")
83549
+ };
83550
+ const warnings = [
83551
+ ...system.vibe ? [] : ["vibe binary not found on PATH"],
83552
+ ...system.npx ? [] : ["npx not found on PATH; MCP stdio config needs npx"],
83553
+ ...hosts.flatMap((host) => host.warnings)
83554
+ ];
83555
+ if (isJsonMode()) {
83556
+ outputSuccess({
83557
+ command: "host doctor",
83558
+ startedAt,
83559
+ data: {
83560
+ projectDir,
83561
+ selection,
83562
+ system,
83563
+ hosts: hosts.map(serializeDoctorResult)
83564
+ },
83565
+ warnings
83566
+ });
83567
+ return;
83568
+ }
83569
+ printDoctor(hosts, system, warnings);
83570
+ });
83571
+ applyTier(hostCommand.commands[hostCommand.commands.length - 1], "free");
83572
+ function validateHostSelection(value) {
83573
+ if (HOST_SELECTIONS.includes(value)) return value;
83574
+ exitWithError(
83575
+ usageError(`Invalid host target: ${value}`, `Must be one of: ${HOST_SELECTIONS.join(", ")}`)
83576
+ );
83577
+ }
83578
+ function serializeSetupPlan(plan) {
83579
+ return {
83580
+ id: plan.host.id,
83581
+ label: plan.host.label,
83582
+ surfaces: plan.host.surfaces,
83583
+ configPath: plan.configPath,
83584
+ snippet: plan.snippet,
83585
+ ...plan.command ? { command: plan.command } : {},
83586
+ files: plan.files,
83587
+ warnings: plan.warnings,
83588
+ nextSteps: plan.nextSteps
83589
+ };
83590
+ }
83591
+ function serializeDoctorResult(result) {
83592
+ return {
83593
+ id: result.host.id,
83594
+ label: result.host.label,
83595
+ surfaces: result.host.surfaces,
83596
+ configPath: result.configPath,
83597
+ configured: result.configured,
83598
+ guidanceFiles: result.guidanceFiles,
83599
+ warnings: result.warnings,
83600
+ nextSteps: result.nextSteps
83601
+ };
83602
+ }
83603
+ function printSetupPlans(plans, opts) {
83604
+ console.log();
83605
+ console.log(source_default.bold.cyan("VibeFrame Host Setup"));
83606
+ console.log(source_default.dim("\u2500".repeat(60)));
83607
+ if (!opts.write) {
83608
+ console.log(source_default.dim("Snippet mode \u2014 no files were changed. Pass --write to apply."));
83609
+ } else if (opts.dryRun) {
83610
+ console.log(source_default.dim("Dry run \u2014 no files were changed."));
83611
+ }
83612
+ for (const plan of plans) {
83613
+ console.log();
83614
+ console.log(source_default.bold(plan.host.label) + source_default.dim(` (${plan.host.id})`));
83615
+ console.log(source_default.dim(`Config: ${plan.configPath}`));
83616
+ if (plan.command) console.log(source_default.dim(`Command: ${plan.command}`));
83617
+ console.log();
83618
+ console.log(plan.snippet);
83619
+ if (plan.files.length > 0) {
83620
+ console.log();
83621
+ for (const file of plan.files) {
83622
+ console.log(` ${formatAction(file.status)} ${file.path}${file.reason ? source_default.dim(` ${file.reason}`) : ""}`);
83623
+ }
83624
+ }
83625
+ for (const warning of plan.warnings) console.log(source_default.yellow(` Warning: ${warning}`));
83626
+ }
83627
+ console.log();
83628
+ }
83629
+ function printDoctor(hosts, system, warnings) {
83630
+ console.log();
83631
+ console.log(source_default.bold.cyan("VibeFrame Host Doctor"));
83632
+ console.log(source_default.dim("\u2500".repeat(60)));
83633
+ console.log(` vibe: ${system.vibe ? source_default.green("OK") : source_default.red("MISSING")}`);
83634
+ console.log(` npx: ${system.npx ? source_default.green("OK") : source_default.red("MISSING")}`);
83635
+ console.log();
83636
+ for (const host of hosts) {
83637
+ console.log(source_default.bold(host.host.label) + source_default.dim(` (${host.host.id})`));
83638
+ console.log(` MCP config: ${host.configured ? source_default.green("OK") : source_default.yellow("missing")} ${source_default.dim(host.configPath)}`);
83639
+ for (const file of host.guidanceFiles) {
83640
+ const ok = file.status !== "missing";
83641
+ console.log(` ${ok ? source_default.green("OK") : source_default.yellow("MISSING")} ${source_default.dim(file.path)}`);
83642
+ }
83643
+ console.log();
83644
+ }
83645
+ for (const warning of warnings) console.log(source_default.yellow(`Warning: ${warning}`));
83646
+ }
83647
+ function formatAction(status) {
83648
+ if (status === "wrote" || status === "merged") return source_default.green("\u2713");
83649
+ if (status.startsWith("would")) return source_default.cyan("\u2192");
83650
+ if (status === "missing") return source_default.yellow("!");
83651
+ return source_default.dim("\u25CB");
83652
+ }
83653
+
83126
83654
  // src/commands/demo.ts
83127
83655
  init_esm();
83128
83656
  init_source();
@@ -83131,10 +83659,10 @@ init_exec_safe();
83131
83659
  init_detect();
83132
83660
  init_ai_edit();
83133
83661
  init_output();
83134
- import { resolve as resolve67 } from "node:path";
83135
- import { existsSync as existsSync49 } from "node:fs";
83136
- import { mkdir as mkdir25, rm as rm4 } from "node:fs/promises";
83137
- var DEMO_DIR = resolve67(process.cwd(), ".vibeframe-demo");
83662
+ import { resolve as resolve69 } from "node:path";
83663
+ import { existsSync as existsSync50 } from "node:fs";
83664
+ import { mkdir as mkdir26, rm as rm4 } from "node:fs/promises";
83665
+ var DEMO_DIR = resolve69(process.cwd(), ".vibeframe-demo");
83138
83666
  async function generateTestVideo(outputPath) {
83139
83667
  const filter = [
83140
83668
  // Video: color bars with text
@@ -83163,7 +83691,7 @@ async function generateTestVideo(outputPath) {
83163
83691
  "-y",
83164
83692
  outputPath
83165
83693
  ], { timeout: 3e4, maxBuffer: 50 * 1024 * 1024 });
83166
- return existsSync49(outputPath);
83694
+ return existsSync50(outputPath);
83167
83695
  } catch {
83168
83696
  try {
83169
83697
  await execSafe("ffmpeg", [
@@ -83189,7 +83717,7 @@ async function generateTestVideo(outputPath) {
83189
83717
  "-y",
83190
83718
  outputPath
83191
83719
  ], { timeout: 3e4, maxBuffer: 50 * 1024 * 1024 });
83192
- return existsSync49(outputPath);
83720
+ return existsSync50(outputPath);
83193
83721
  } catch {
83194
83722
  return false;
83195
83723
  }
@@ -83213,8 +83741,8 @@ var demoCommand = new Command("demo").description("Run sample edits on a test vi
83213
83741
  console.log(source_default.dim(" " + "\u2500".repeat(50)));
83214
83742
  console.log();
83215
83743
  }
83216
- await mkdir25(DEMO_DIR, { recursive: true });
83217
- const testVideo = resolve67(DEMO_DIR, "test-input.mp4");
83744
+ await mkdir26(DEMO_DIR, { recursive: true });
83745
+ const testVideo = resolve69(DEMO_DIR, "test-input.mp4");
83218
83746
  const genSpinner = !isJson ? ora("Generating test video...").start() : null;
83219
83747
  const generated = await generateTestVideo(testVideo);
83220
83748
  if (!generated) {
@@ -83243,7 +83771,7 @@ var demoCommand = new Command("demo").description("Run sample edits on a test vi
83243
83771
  name: "Silence Cut",
83244
83772
  description: "Removing silent segments",
83245
83773
  run: async () => {
83246
- const output = resolve67(DEMO_DIR, "silence-cut.mp4");
83774
+ const output = resolve69(DEMO_DIR, "silence-cut.mp4");
83247
83775
  const r = await executeSilenceCut({ videoPath: testVideo, outputPath: output, padding: 0.1 });
83248
83776
  if (r.success && r.totalDuration && r.silentDuration) {
83249
83777
  return { success: true, detail: `Removed ${r.silentDuration.toFixed(1)}s silence (${r.totalDuration.toFixed(1)}s \u2192 ${(r.totalDuration - r.silentDuration).toFixed(1)}s)` };
@@ -83255,7 +83783,7 @@ var demoCommand = new Command("demo").description("Run sample edits on a test vi
83255
83783
  name: "Noise Reduce",
83256
83784
  description: "Reducing background noise",
83257
83785
  run: async () => {
83258
- const output = resolve67(DEMO_DIR, "noise-reduced.mp4");
83786
+ const output = resolve69(DEMO_DIR, "noise-reduced.mp4");
83259
83787
  const r = await executeNoiseReduce({ inputPath: testVideo, outputPath: output, strength: "medium" });
83260
83788
  return { success: r.success, detail: r.success ? `Cleaned audio \u2192 ${output}` : r.error };
83261
83789
  }
@@ -83264,7 +83792,7 @@ var demoCommand = new Command("demo").description("Run sample edits on a test vi
83264
83792
  name: "Fade Effects",
83265
83793
  description: "Adding fade in/out",
83266
83794
  run: async () => {
83267
- const output = resolve67(DEMO_DIR, "faded.mp4");
83795
+ const output = resolve69(DEMO_DIR, "faded.mp4");
83268
83796
  const r = await executeFade({ videoPath: testVideo, outputPath: output, fadeIn: 1, fadeOut: 1 });
83269
83797
  return { success: r.success, detail: r.success ? `1s fade in + 1s fade out \u2192 ${output}` : r.error };
83270
83798
  }
@@ -83331,20 +83859,20 @@ var demoCommand = new Command("demo").description("Run sample edits on a test vi
83331
83859
 
83332
83860
  // src/commands/context.ts
83333
83861
  init_esm();
83334
- import { existsSync as existsSync50 } from "node:fs";
83335
- import { readFile as readFile44 } from "node:fs/promises";
83336
- import { resolve as resolve68, dirname as dirname23 } from "node:path";
83862
+ import { existsSync as existsSync51 } from "node:fs";
83863
+ import { readFile as readFile45 } from "node:fs/promises";
83864
+ import { resolve as resolve70, dirname as dirname24 } from "node:path";
83337
83865
  import { fileURLToPath as fileURLToPath2 } from "node:url";
83338
83866
  var __filename = fileURLToPath2(import.meta.url);
83339
- var __dirname = dirname23(__filename);
83867
+ var __dirname = dirname24(__filename);
83340
83868
  function resolveContextPath(baseDir = __dirname) {
83341
83869
  const candidates = [
83342
83870
  // Bundled package layout: packages/cli/dist/index.js -> packages/cli/CONTEXT.md
83343
- resolve68(baseDir, "../CONTEXT.md"),
83871
+ resolve70(baseDir, "../CONTEXT.md"),
83344
83872
  // Source/dev layout: packages/cli/src/commands/context.ts -> packages/cli/CONTEXT.md
83345
- resolve68(baseDir, "../../CONTEXT.md")
83873
+ resolve70(baseDir, "../../CONTEXT.md")
83346
83874
  ];
83347
- return candidates.find((candidate) => existsSync50(candidate)) ?? null;
83875
+ return candidates.find((candidate) => existsSync51(candidate)) ?? null;
83348
83876
  }
83349
83877
  var contextCommand = new Command("context").description("Print CLI context/guidelines for AI agent integration").option("--format <format>", "Output format: markdown | json", "markdown").action(async (_options, cmd) => {
83350
83878
  const options = {
@@ -83434,7 +83962,7 @@ var contextCommand = new Command("context").description("Print CLI context/guide
83434
83962
  try {
83435
83963
  const contextPath = resolveContextPath();
83436
83964
  if (!contextPath) throw new Error("CONTEXT.md not found");
83437
- const content = await readFile44(contextPath, "utf-8");
83965
+ const content = await readFile45(contextPath, "utf-8");
83438
83966
  console.log(
83439
83967
  content.replace(
83440
83968
  "## Mental model",
@@ -84376,7 +84904,7 @@ async function startAgent(options = {}) {
84376
84904
  console.log();
84377
84905
  console.log(source_default.dim(" Commands: exit \xB7 reset \xB7 tools \xB7 context"));
84378
84906
  console.log();
84379
- return new Promise((resolve81) => {
84907
+ return new Promise((resolve83) => {
84380
84908
  if (typeof process.stdin.ref === "function") {
84381
84909
  process.stdin.ref();
84382
84910
  }
@@ -84483,7 +85011,7 @@ async function startAgent(options = {}) {
84483
85011
  clearInterval(keepalive);
84484
85012
  console.log();
84485
85013
  console.log(source_default.dim("Goodbye!"));
84486
- resolve81();
85014
+ resolve83();
84487
85015
  });
84488
85016
  rl.prompt();
84489
85017
  });
@@ -84756,8 +85284,8 @@ init_source();
84756
85284
  init_config();
84757
85285
  init_schema();
84758
85286
  init_api_key();
84759
- import { access as access9, writeFile as writeFile58, mkdir as mkdir28 } from "node:fs/promises";
84760
- import { dirname as dirname25 } from "node:path";
85287
+ import { access as access9, writeFile as writeFile59, mkdir as mkdir29 } from "node:fs/promises";
85288
+ import { dirname as dirname26 } from "node:path";
84761
85289
  var BANNER_SHOWN_PATH = `${USER_CONFIG_DIR}/.banner-shown`;
84762
85290
  async function isFirstRun() {
84763
85291
  try {
@@ -84776,8 +85304,8 @@ async function isFirstRun() {
84776
85304
  }
84777
85305
  async function markBannerShown() {
84778
85306
  try {
84779
- await mkdir28(dirname25(BANNER_SHOWN_PATH), { recursive: true });
84780
- await writeFile58(BANNER_SHOWN_PATH, (/* @__PURE__ */ new Date()).toISOString());
85307
+ await mkdir29(dirname26(BANNER_SHOWN_PATH), { recursive: true });
85308
+ await writeFile59(BANNER_SHOWN_PATH, (/* @__PURE__ */ new Date()).toISOString());
84781
85309
  } catch {
84782
85310
  }
84783
85311
  }
@@ -84912,6 +85440,7 @@ this section shows the typical entry points by use case):
84912
85440
  vibe schema --list --surface public Compact first-run command catalog
84913
85441
  vibe schema generate.video JSON schema for any command
84914
85442
  vibe context Agent integration quickstart
85443
+ vibe host setup all Configure Codex/Claude/Cursor app integrations
84915
85444
  vibe agent Optional built-in agent when you do not use Claude Code/Codex/etc.
84916
85445
 
84917
85446
  Common-flag note: most commands accept --dry-run to preview cost/output
@@ -85013,6 +85542,7 @@ program2.addCommand(buildCommand);
85013
85542
  program2.addCommand(renderCommand);
85014
85543
  program2.addCommand(statusCommand);
85015
85544
  program2.addCommand(doctorCommand);
85545
+ program2.addCommand(hostCommand);
85016
85546
  program2.addCommand(demoCommand, { hidden: true });
85017
85547
  program2.addCommand(runCommand);
85018
85548
  program2.addCommand(agentCommand);