hyperframes 0.7.21 → 0.7.22

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/cli.js CHANGED
@@ -50,7 +50,7 @@ var VERSION;
50
50
  var init_version = __esm({
51
51
  "src/version.ts"() {
52
52
  "use strict";
53
- VERSION = true ? "0.7.21" : "0.0.0-dev";
53
+ VERSION = true ? "0.7.22" : "0.0.0-dev";
54
54
  }
55
55
  });
56
56
 
@@ -813,11 +813,11 @@ function __metadata(metadataKey, metadataValue) {
813
813
  }
814
814
  function __awaiter(thisArg, _arguments, P2, generator) {
815
815
  function adopt(value) {
816
- return value instanceof P2 ? value : new P2(function(resolve60) {
817
- resolve60(value);
816
+ return value instanceof P2 ? value : new P2(function(resolve61) {
817
+ resolve61(value);
818
818
  });
819
819
  }
820
- return new (P2 || (P2 = Promise))(function(resolve60, reject) {
820
+ return new (P2 || (P2 = Promise))(function(resolve61, reject) {
821
821
  function fulfilled(value) {
822
822
  try {
823
823
  step(generator.next(value));
@@ -833,7 +833,7 @@ function __awaiter(thisArg, _arguments, P2, generator) {
833
833
  }
834
834
  }
835
835
  function step(result) {
836
- result.done ? resolve60(result.value) : adopt(result.value).then(fulfilled, rejected);
836
+ result.done ? resolve61(result.value) : adopt(result.value).then(fulfilled, rejected);
837
837
  }
838
838
  step((generator = generator.apply(thisArg, _arguments || [])).next());
839
839
  });
@@ -1024,14 +1024,14 @@ function __asyncValues(o) {
1024
1024
  }, i2);
1025
1025
  function verb(n2) {
1026
1026
  i2[n2] = o[n2] && function(v2) {
1027
- return new Promise(function(resolve60, reject) {
1028
- v2 = o[n2](v2), settle(resolve60, reject, v2.done, v2.value);
1027
+ return new Promise(function(resolve61, reject) {
1028
+ v2 = o[n2](v2), settle(resolve61, reject, v2.done, v2.value);
1029
1029
  });
1030
1030
  };
1031
1031
  }
1032
- function settle(resolve60, reject, d2, v2) {
1032
+ function settle(resolve61, reject, d2, v2) {
1033
1033
  Promise.resolve(v2).then(function(v3) {
1034
- resolve60({ value: v3, done: d2 });
1034
+ resolve61({ value: v3, done: d2 });
1035
1035
  }, reject);
1036
1036
  }
1037
1037
  }
@@ -41859,8 +41859,8 @@ var init_custom_element_registry = __esm({
41859
41859
  } : (element) => element.localName === localName;
41860
41860
  registry.set(localName, { Class, check });
41861
41861
  if (waiting.has(localName)) {
41862
- for (const resolve60 of waiting.get(localName))
41863
- resolve60(Class);
41862
+ for (const resolve61 of waiting.get(localName))
41863
+ resolve61(Class);
41864
41864
  waiting.delete(localName);
41865
41865
  }
41866
41866
  ownerDocument.querySelectorAll(
@@ -41900,13 +41900,13 @@ var init_custom_element_registry = __esm({
41900
41900
  */
41901
41901
  whenDefined(localName) {
41902
41902
  const { registry, waiting } = this;
41903
- return new Promise((resolve60) => {
41903
+ return new Promise((resolve61) => {
41904
41904
  if (registry.has(localName))
41905
- resolve60(registry.get(localName).Class);
41905
+ resolve61(registry.get(localName).Class);
41906
41906
  else {
41907
41907
  if (!waiting.has(localName))
41908
41908
  waiting.set(localName, []);
41909
- waiting.get(localName).push(resolve60);
41909
+ waiting.get(localName).push(resolve61);
41910
41910
  }
41911
41911
  });
41912
41912
  }
@@ -52142,14 +52142,14 @@ function inlineHelper(call, ctx) {
52142
52142
  };
52143
52143
  return expandBody(fn.body.body, bindings, prov, ctx);
52144
52144
  }
52145
- function assignStep(update2, resolve60) {
52146
- if (update2.operator === "+=") return asNum(resolve60(update2.right));
52145
+ function assignStep(update2, resolve61) {
52146
+ if (update2.operator === "+=") return asNum(resolve61(update2.right));
52147
52147
  if (update2.operator === "-=") {
52148
- const s2 = asNum(resolve60(update2.right));
52148
+ const s2 = asNum(resolve61(update2.right));
52149
52149
  return s2 === void 0 ? void 0 : -s2;
52150
52150
  }
52151
52151
  if (update2.operator === "=" && update2.right?.type === "BinaryExpression") {
52152
- return asNum(resolve60(update2.right.right));
52152
+ return asNum(resolve61(update2.right.right));
52153
52153
  }
52154
52154
  return void 0;
52155
52155
  }
@@ -52158,10 +52158,10 @@ function updatedVarName(update2) {
52158
52158
  if (update2?.type === "AssignmentExpression") return update2.left?.name ?? null;
52159
52159
  return null;
52160
52160
  }
52161
- function loopStep(update2, varName, resolve60) {
52161
+ function loopStep(update2, varName, resolve61) {
52162
52162
  if (updatedVarName(update2) !== varName) return void 0;
52163
52163
  if (update2.type === "UpdateExpression") return update2.operator === "++" ? 1 : -1;
52164
- return assignStep(update2, resolve60);
52164
+ return assignStep(update2, resolve61);
52165
52165
  }
52166
52166
  function asNum(v2) {
52167
52167
  return typeof v2 === "number" && Number.isFinite(v2) ? v2 : void 0;
@@ -52178,13 +52178,13 @@ function forInitVar(init) {
52178
52178
  const d2 = init.declarations[0];
52179
52179
  return d2.id?.type === "Identifier" ? { name: d2.id.name, initExpr: d2.init } : null;
52180
52180
  }
52181
- function parseForHeader(stmt, resolve60) {
52181
+ function parseForHeader(stmt, resolve61) {
52182
52182
  const iv = forInitVar(stmt.init);
52183
52183
  const test = stmt.test;
52184
52184
  if (!iv || test?.type !== "BinaryExpression" || test.left?.name !== iv.name) return null;
52185
- const start = asNum(resolve60(iv.initExpr));
52186
- const end = asNum(resolve60(test.right));
52187
- const step = loopStep(stmt.update, iv.name, resolve60);
52185
+ const start = asNum(resolve61(iv.initExpr));
52186
+ const end = asNum(resolve61(test.right));
52187
+ const step = loopStep(stmt.update, iv.name, resolve61);
52188
52188
  if (start === void 0 || end === void 0 || !step) return null;
52189
52189
  return { v: iv.name, start, end, op: test.operator, step };
52190
52190
  }
@@ -52296,12 +52296,12 @@ function expandStatements(stmts, ctx) {
52296
52296
  }
52297
52297
  return out;
52298
52298
  }
52299
- function inlineComputedTimelines(ast, timelineVar, resolve60) {
52299
+ function inlineComputedTimelines(ast, timelineVar, resolve61) {
52300
52300
  const helpers = collectInlinableHelpers(ast, timelineVar);
52301
52301
  const ctx = {
52302
52302
  helpers,
52303
52303
  timelineVar,
52304
- resolve: resolve60,
52304
+ resolve: resolve61,
52305
52305
  depth: 0,
52306
52306
  site: { n: 0 },
52307
52307
  order: { n: 0 }
@@ -59172,9 +59172,9 @@ var require_picocolors = __commonJS({
59172
59172
  var argv2 = p2.argv || [];
59173
59173
  var env = p2.env || {};
59174
59174
  var isColorSupported2 = !(!!env.NO_COLOR || argv2.includes("--no-color")) && (!!env.FORCE_COLOR || argv2.includes("--color") || p2.platform === "win32" || (p2.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
59175
- var formatter = (open2, close, replace4 = open2) => (input2) => {
59176
- let string = "" + input2, index = string.indexOf(close, open2.length);
59177
- return ~index ? open2 + replaceClose(string, close, replace4, index) + close : open2 + string + close;
59175
+ var formatter = (open3, close, replace4 = open3) => (input2) => {
59176
+ let string = "" + input2, index = string.indexOf(close, open3.length);
59177
+ return ~index ? open3 + replaceClose(string, close, replace4, index) + close : open3 + string + close;
59178
59178
  };
59179
59179
  var replaceClose = (string, close, replace4, index) => {
59180
59180
  let result = "", cursor = 0;
@@ -60515,10 +60515,10 @@ async function waitForCloseWithTimeout(promise) {
60515
60515
  () => void 0,
60516
60516
  () => void 0
60517
60517
  ),
60518
- new Promise((resolve60) => {
60518
+ new Promise((resolve61) => {
60519
60519
  timer = setTimeout(() => {
60520
60520
  timedOut = true;
60521
- resolve60();
60521
+ resolve61();
60522
60522
  }, CAPTURE_SESSION_CLOSE_TIMEOUT_MS);
60523
60523
  })
60524
60524
  ]);
@@ -60630,7 +60630,7 @@ async function pollPageExpression(page, expression, timeoutMs, intervalMs = 100)
60630
60630
  while (Date.now() < deadline) {
60631
60631
  const ready = Boolean(await page.evaluate(expression));
60632
60632
  if (ready) return true;
60633
- await new Promise((resolve60) => setTimeout(resolve60, intervalMs));
60633
+ await new Promise((resolve61) => setTimeout(resolve61, intervalMs));
60634
60634
  }
60635
60635
  return Boolean(await page.evaluate(expression));
60636
60636
  }
@@ -60679,7 +60679,7 @@ async function pollHfReady(page, timeoutMs, intervalMs = 100) {
60679
60679
  }
60680
60680
  }
60681
60681
  }
60682
- await new Promise((resolve60) => setTimeout(resolve60, intervalMs));
60682
+ await new Promise((resolve61) => setTimeout(resolve61, intervalMs));
60683
60683
  }
60684
60684
  const diag = await evaluateHfDiagnostic(page);
60685
60685
  if (diag.hasSeek && diag.duration === 0) {
@@ -60745,7 +60745,7 @@ async function pollVideosReady(page, skipIds, timeoutMs, intervalMs = 100) {
60745
60745
  const deadline = Date.now() + timeoutMs;
60746
60746
  while (Date.now() < deadline) {
60747
60747
  if (await check()) return true;
60748
- await new Promise((resolve60) => setTimeout(resolve60, intervalMs));
60748
+ await new Promise((resolve61) => setTimeout(resolve61, intervalMs));
60749
60749
  }
60750
60750
  return check();
60751
60751
  }
@@ -60768,7 +60768,7 @@ async function pollImagesReady(page, timeoutMs, intervalMs = 100) {
60768
60768
  const deadline = Date.now() + timeoutMs;
60769
60769
  while (Date.now() < deadline) {
60770
60770
  if (await check()) return true;
60771
- await new Promise((resolve60) => setTimeout(resolve60, intervalMs));
60771
+ await new Promise((resolve61) => setTimeout(resolve61, intervalMs));
60772
60772
  }
60773
60773
  return check();
60774
60774
  }
@@ -60815,7 +60815,7 @@ async function waitForOptionalTailwindReady(page, timeoutMs) {
60815
60815
  page.evaluate(
60816
60816
  `Promise.resolve(window.__tailwindReady).then(() => true, () => false)`
60817
60817
  ),
60818
- new Promise((resolve60) => setTimeout(() => resolve60(false), timeoutMs))
60818
+ new Promise((resolve61) => setTimeout(() => resolve61(false), timeoutMs))
60819
60819
  ]);
60820
60820
  if (!ready) {
60821
60821
  throw new Error(
@@ -61497,7 +61497,7 @@ var init_frameCapture = __esm({
61497
61497
  BROWSER_CONSOLE_BUFFER_SIZE = 200;
61498
61498
  CAPTURE_SESSION_CLOSE_TIMEOUT_MS = 5e3;
61499
61499
  LOCKED_WARMUP_TICKS = 60;
61500
- realSleep = (ms) => new Promise((resolve60) => setTimeout(resolve60, ms));
61500
+ realSleep = (ms) => new Promise((resolve61) => setTimeout(resolve61, ms));
61501
61501
  HF_READY_DIAGNOSTIC_EXPR = `(function() {
61502
61502
  var hf = window.__hf;
61503
61503
  var player = window.__player;
@@ -61651,7 +61651,7 @@ async function selectUsableGpuEncoder(candidates, isUsable) {
61651
61651
  return null;
61652
61652
  }
61653
61653
  async function detectGpuEncoder() {
61654
- return new Promise((resolve60) => {
61654
+ return new Promise((resolve61) => {
61655
61655
  const ffmpeg = spawn(getFfmpegBinary(), ["-encoders"], {
61656
61656
  stdio: ["pipe", "pipe", "pipe"]
61657
61657
  });
@@ -61661,9 +61661,9 @@ async function detectGpuEncoder() {
61661
61661
  });
61662
61662
  ffmpeg.on("close", () => {
61663
61663
  const candidates = getCompiledGpuEncoders(stdout2);
61664
- void selectUsableGpuEncoder(candidates, canUseGpuEncoder).then(resolve60).catch(() => resolve60(null));
61664
+ void selectUsableGpuEncoder(candidates, canUseGpuEncoder).then(resolve61).catch(() => resolve61(null));
61665
61665
  });
61666
- ffmpeg.on("error", () => resolve60(null));
61666
+ ffmpeg.on("error", () => resolve61(null));
61667
61667
  });
61668
61668
  }
61669
61669
  async function getCachedGpuEncoder() {
@@ -61713,7 +61713,7 @@ function getProbeArgs(encoder) {
61713
61713
  return args;
61714
61714
  }
61715
61715
  async function canUseGpuEncoder(encoder) {
61716
- return new Promise((resolve60) => {
61716
+ return new Promise((resolve61) => {
61717
61717
  let settled = false;
61718
61718
  let timedOut = false;
61719
61719
  let killTimer;
@@ -61723,7 +61723,7 @@ async function canUseGpuEncoder(encoder) {
61723
61723
  settled = true;
61724
61724
  clearTimeout(timer);
61725
61725
  if (killTimer) clearTimeout(killTimer);
61726
- resolve60(usable);
61726
+ resolve61(usable);
61727
61727
  };
61728
61728
  const ffmpeg = spawn(getFfmpegBinary(), getProbeArgs(encoder), {
61729
61729
  stdio: ["ignore", "ignore", "pipe"]
@@ -61862,6 +61862,22 @@ var init_hdr = __esm({
61862
61862
  }
61863
61863
  });
61864
61864
 
61865
+ // ../engine/src/utils/evenDimensions.ts
61866
+ function requiresEvenDimensions(pixelFormat) {
61867
+ return pixelFormat.startsWith("yuv420") || pixelFormat.startsWith("yuvj420");
61868
+ }
61869
+ function withEvenDimensionPad(vfChain, pixelFormat) {
61870
+ if (!requiresEvenDimensions(pixelFormat)) return vfChain;
61871
+ return vfChain ? `${vfChain},${EVEN_DIMENSION_PAD}` : EVEN_DIMENSION_PAD;
61872
+ }
61873
+ var EVEN_DIMENSION_PAD;
61874
+ var init_evenDimensions = __esm({
61875
+ "../engine/src/utils/evenDimensions.ts"() {
61876
+ "use strict";
61877
+ EVEN_DIMENSION_PAD = "pad=ceil(iw/2)*2:ceil(ih/2)*2";
61878
+ }
61879
+ });
61880
+
61865
61881
  // ../engine/src/utils/runFfmpeg.ts
61866
61882
  import { spawn as spawn2 } from "child_process";
61867
61883
  function formatWindowsFfmpegExit(exitCode) {
@@ -61894,7 +61910,7 @@ async function runFfmpeg(args, opts) {
61894
61910
  const signal = opts?.signal;
61895
61911
  const timeout = opts?.timeout ?? DEFAULT_TIMEOUT;
61896
61912
  const onStderr = opts?.onStderr;
61897
- return new Promise((resolve60) => {
61913
+ return new Promise((resolve61) => {
61898
61914
  const ffmpeg = spawn2(getFfmpegBinary(), args);
61899
61915
  trackChildProcess(ffmpeg);
61900
61916
  let stderr = "";
@@ -61921,7 +61937,7 @@ async function runFfmpeg(args, opts) {
61921
61937
  ffmpeg.on("close", (code) => {
61922
61938
  clearTimeout(timer);
61923
61939
  if (signal) signal.removeEventListener("abort", onAbort);
61924
- resolve60({
61940
+ resolve61({
61925
61941
  success: !signal?.aborted && code === 0,
61926
61942
  exitCode: code,
61927
61943
  stderr,
@@ -61931,7 +61947,7 @@ async function runFfmpeg(args, opts) {
61931
61947
  ffmpeg.on("error", (err) => {
61932
61948
  clearTimeout(timer);
61933
61949
  if (signal) signal.removeEventListener("abort", onAbort);
61934
- resolve60({
61950
+ resolve61({
61935
61951
  success: false,
61936
61952
  exitCode: null,
61937
61953
  stderr: err.message,
@@ -61956,7 +61972,7 @@ import { spawn as spawn3 } from "child_process";
61956
61972
  import { readFileSync as readFileSync3 } from "fs";
61957
61973
  import { extname } from "path";
61958
61974
  function runFfprobe(args) {
61959
- return new Promise((resolve60, reject) => {
61975
+ return new Promise((resolve61, reject) => {
61960
61976
  const command2 = getFfprobeBinary();
61961
61977
  const proc = spawn3(command2, args);
61962
61978
  let stdout2 = "";
@@ -61971,7 +61987,7 @@ function runFfprobe(args) {
61971
61987
  if (code !== 0) {
61972
61988
  reject(new Error(`[FFmpeg] ffprobe exited with code ${code}: ${stderr}`));
61973
61989
  } else {
61974
- resolve60(stdout2);
61990
+ resolve61(stdout2);
61975
61991
  }
61976
61992
  });
61977
61993
  proc.on("error", (err) => {
@@ -62461,8 +62477,11 @@ function buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder = null) {
62461
62477
  if (vfIdx !== -1) {
62462
62478
  args[vfIdx + 1] = `scale=in_range=pc:out_range=tv,${args[vfIdx + 1]}`;
62463
62479
  }
62464
- } else if (!shouldUseGpu) {
62465
- args.push("-vf", "scale=in_range=pc:out_range=tv");
62480
+ } else if (shouldUseGpu) {
62481
+ const vf = withEvenDimensionPad("", pixelFormat);
62482
+ if (vf) args.push("-vf", vf);
62483
+ } else {
62484
+ args.push("-vf", withEvenDimensionPad("scale=in_range=pc:out_range=tv", pixelFormat));
62466
62485
  }
62467
62486
  args.push("-video_track_timescale", "90000");
62468
62487
  }
@@ -62496,7 +62515,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
62496
62515
  const inputPath = join6(framesDir, framePattern);
62497
62516
  const inputArgs = ["-framerate", fpsToFfmpegArg(options.fps), "-i", inputPath];
62498
62517
  const args = buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder);
62499
- return new Promise((resolve60) => {
62518
+ return new Promise((resolve61) => {
62500
62519
  const ffmpeg = spawn4(getFfmpegBinary(), args);
62501
62520
  trackChildProcess(ffmpeg);
62502
62521
  let stderr = "";
@@ -62524,7 +62543,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
62524
62543
  if (signal) signal.removeEventListener("abort", onAbort);
62525
62544
  const durationMs = Date.now() - startTime;
62526
62545
  if (signal?.aborted && !timedOut) {
62527
- resolve60({
62546
+ resolve61({
62528
62547
  success: false,
62529
62548
  outputPath,
62530
62549
  durationMs,
@@ -62535,7 +62554,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
62535
62554
  return;
62536
62555
  }
62537
62556
  if (code !== 0 || timedOut) {
62538
- resolve60({
62557
+ resolve61({
62539
62558
  success: false,
62540
62559
  outputPath,
62541
62560
  durationMs,
@@ -62550,12 +62569,12 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
62550
62569
  return;
62551
62570
  }
62552
62571
  const fileSize = existsSync6(outputPath) ? statSync(outputPath).size : 0;
62553
- resolve60({ success: true, outputPath, durationMs, framesEncoded: frameCount, fileSize });
62572
+ resolve61({ success: true, outputPath, durationMs, framesEncoded: frameCount, fileSize });
62554
62573
  });
62555
62574
  ffmpeg.on("error", (err) => {
62556
62575
  clearTimeout(timer);
62557
62576
  if (signal) signal.removeEventListener("abort", onAbort);
62558
- resolve60({
62577
+ resolve61({
62559
62578
  success: false,
62560
62579
  outputPath,
62561
62580
  durationMs: Date.now() - startTime,
@@ -62613,7 +62632,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
62613
62632
  let gpuEncoder = null;
62614
62633
  if (options.useGpu) gpuEncoder = await getCachedGpuEncoder();
62615
62634
  const args = buildEncoderArgs(options, inputArgs, chunkPath, gpuEncoder);
62616
- const chunkResult = await new Promise((resolve60) => {
62635
+ const chunkResult = await new Promise((resolve61) => {
62617
62636
  const ffmpeg = spawn4(getFfmpegBinary(), args);
62618
62637
  trackChildProcess(ffmpeg);
62619
62638
  let stderr = "";
@@ -62628,9 +62647,9 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
62628
62647
  });
62629
62648
  ffmpeg.on("close", (code) => {
62630
62649
  clearTimeout(timer);
62631
- if (code === 0 && !timedOut) resolve60({ success: true });
62650
+ if (code === 0 && !timedOut) resolve61({ success: true });
62632
62651
  else {
62633
- resolve60({
62652
+ resolve61({
62634
62653
  success: false,
62635
62654
  error: appendEncodeTimeoutMessage(
62636
62655
  `Chunk ${i2} encode failed: ${stderr.slice(-400)}`,
@@ -62642,7 +62661,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
62642
62661
  });
62643
62662
  ffmpeg.on("error", (err) => {
62644
62663
  clearTimeout(timer);
62645
- resolve60({
62664
+ resolve61({
62646
62665
  success: false,
62647
62666
  error: appendEncodeTimeoutMessage(
62648
62667
  `Chunk ${i2} encode error: ${err.message}`,
@@ -62679,7 +62698,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
62679
62698
  "-y",
62680
62699
  outputPath
62681
62700
  ];
62682
- const concatResult = await new Promise((resolve60) => {
62701
+ const concatResult = await new Promise((resolve61) => {
62683
62702
  const ffmpeg = spawn4(getFfmpegBinary(), concatArgs);
62684
62703
  trackChildProcess(ffmpeg);
62685
62704
  let stderr = "";
@@ -62694,9 +62713,9 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
62694
62713
  });
62695
62714
  ffmpeg.on("close", (code) => {
62696
62715
  clearTimeout(timer);
62697
- if (code === 0 && !timedOut) resolve60({ success: true });
62716
+ if (code === 0 && !timedOut) resolve61({ success: true });
62698
62717
  else {
62699
- resolve60({
62718
+ resolve61({
62700
62719
  success: false,
62701
62720
  error: appendEncodeTimeoutMessage(
62702
62721
  `Chunk concat failed: ${stderr.slice(-400)}`,
@@ -62708,7 +62727,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
62708
62727
  });
62709
62728
  ffmpeg.on("error", (err) => {
62710
62729
  clearTimeout(timer);
62711
- resolve60({
62730
+ resolve61({
62712
62731
  success: false,
62713
62732
  error: appendEncodeTimeoutMessage(
62714
62733
  `Chunk concat error: ${err.message}`,
@@ -62816,6 +62835,7 @@ var init_chunkEncoder = __esm({
62816
62835
  init_config2();
62817
62836
  init_gpuEncoder();
62818
62837
  init_hdr();
62838
+ init_evenDimensions();
62819
62839
  init_runFfmpeg();
62820
62840
  init_ffmpegBinaries();
62821
62841
  init_ffprobe();
@@ -62847,37 +62867,37 @@ import { dirname as dirname5 } from "path";
62847
62867
  function createFrameReorderBuffer(startFrame, endFrame) {
62848
62868
  let cursor = startFrame;
62849
62869
  const pending = /* @__PURE__ */ new Map();
62850
- const enqueueAt = (frame, resolve60) => {
62870
+ const enqueueAt = (frame, resolve61) => {
62851
62871
  const list = pending.get(frame);
62852
62872
  if (list === void 0) {
62853
- pending.set(frame, [resolve60]);
62873
+ pending.set(frame, [resolve61]);
62854
62874
  } else {
62855
- list.push(resolve60);
62875
+ list.push(resolve61);
62856
62876
  }
62857
62877
  };
62858
62878
  const flushAt = (frame) => {
62859
62879
  const list = pending.get(frame);
62860
62880
  if (list === void 0) return;
62861
62881
  pending.delete(frame);
62862
- for (const resolve60 of list) resolve60();
62882
+ for (const resolve61 of list) resolve61();
62863
62883
  };
62864
- const waitForFrame = (frame) => new Promise((resolve60) => {
62884
+ const waitForFrame = (frame) => new Promise((resolve61) => {
62865
62885
  if (frame === cursor) {
62866
- resolve60();
62886
+ resolve61();
62867
62887
  return;
62868
62888
  }
62869
- enqueueAt(frame, resolve60);
62889
+ enqueueAt(frame, resolve61);
62870
62890
  });
62871
62891
  const advanceTo = (frame) => {
62872
62892
  cursor = frame;
62873
62893
  flushAt(frame);
62874
62894
  };
62875
- const waitForAllDone = () => new Promise((resolve60) => {
62895
+ const waitForAllDone = () => new Promise((resolve61) => {
62876
62896
  if (cursor >= endFrame) {
62877
- resolve60();
62897
+ resolve61();
62878
62898
  return;
62879
62899
  }
62880
- enqueueAt(endFrame, resolve60);
62900
+ enqueueAt(endFrame, resolve61);
62881
62901
  });
62882
62902
  return { waitForFrame, advanceTo, waitForAllDone };
62883
62903
  }
@@ -63036,8 +63056,11 @@ function buildStreamingArgs(options, outputPath, gpuEncoder = null) {
63036
63056
  if (vfIdx !== -1) {
63037
63057
  args[vfIdx + 1] = `scale=in_range=pc:out_range=tv,${args[vfIdx + 1]}`;
63038
63058
  }
63039
- } else if (!shouldUseGpu) {
63040
- args.push("-vf", "scale=in_range=pc:out_range=tv");
63059
+ } else if (shouldUseGpu) {
63060
+ const vf = withEvenDimensionPad("", pixelFormat);
63061
+ if (vf) args.push("-vf", vf);
63062
+ } else {
63063
+ args.push("-vf", withEvenDimensionPad("scale=in_range=pc:out_range=tv", pixelFormat));
63041
63064
  }
63042
63065
  args.push("-video_track_timescale", "90000");
63043
63066
  }
@@ -63065,7 +63088,7 @@ async function spawnStreamingEncoder(outputPath, options, signal, config) {
63065
63088
  let stderr = "";
63066
63089
  let exitCode = null;
63067
63090
  let exitPromiseResolve = null;
63068
- const exitPromise = new Promise((resolve60) => exitPromiseResolve = resolve60);
63091
+ const exitPromise = new Promise((resolve61) => exitPromiseResolve = resolve61);
63069
63092
  ffmpeg.stderr?.on("data", (data2) => {
63070
63093
  stderr += data2.toString();
63071
63094
  });
@@ -63157,8 +63180,8 @@ Process error: ${err.message}`;
63157
63180
  if (signal) signal.removeEventListener("abort", onAbort);
63158
63181
  const stdin = ffmpeg.stdin;
63159
63182
  if (stdin && !stdin.destroyed) {
63160
- await new Promise((resolve60) => {
63161
- stdin.end(() => resolve60());
63183
+ await new Promise((resolve61) => {
63184
+ stdin.end(() => resolve61());
63162
63185
  });
63163
63186
  }
63164
63187
  await exitPromise;
@@ -63194,6 +63217,7 @@ var init_streamingEncoder = __esm({
63194
63217
  init_runFfmpeg();
63195
63218
  init_ffmpegBinaries();
63196
63219
  init_hdr();
63220
+ init_evenDimensions();
63197
63221
  init_config2();
63198
63222
  init_dist3();
63199
63223
  init_vp9Options();
@@ -64423,14 +64447,14 @@ function inlineHelper2(call, ctx) {
64423
64447
  };
64424
64448
  return expandBody2(fn.body.body, bindings, prov, ctx);
64425
64449
  }
64426
- function assignStep2(update2, resolve60) {
64427
- if (update2.operator === "+=") return asNum2(resolve60(update2.right));
64450
+ function assignStep2(update2, resolve61) {
64451
+ if (update2.operator === "+=") return asNum2(resolve61(update2.right));
64428
64452
  if (update2.operator === "-=") {
64429
- const s2 = asNum2(resolve60(update2.right));
64453
+ const s2 = asNum2(resolve61(update2.right));
64430
64454
  return s2 === void 0 ? void 0 : -s2;
64431
64455
  }
64432
64456
  if (update2.operator === "=" && update2.right?.type === "BinaryExpression") {
64433
- return asNum2(resolve60(update2.right.right));
64457
+ return asNum2(resolve61(update2.right.right));
64434
64458
  }
64435
64459
  return void 0;
64436
64460
  }
@@ -64439,10 +64463,10 @@ function updatedVarName2(update2) {
64439
64463
  if (update2?.type === "AssignmentExpression") return update2.left?.name ?? null;
64440
64464
  return null;
64441
64465
  }
64442
- function loopStep2(update2, varName, resolve60) {
64466
+ function loopStep2(update2, varName, resolve61) {
64443
64467
  if (updatedVarName2(update2) !== varName) return void 0;
64444
64468
  if (update2.type === "UpdateExpression") return update2.operator === "++" ? 1 : -1;
64445
- return assignStep2(update2, resolve60);
64469
+ return assignStep2(update2, resolve61);
64446
64470
  }
64447
64471
  function asNum2(v2) {
64448
64472
  return typeof v2 === "number" && Number.isFinite(v2) ? v2 : void 0;
@@ -64459,13 +64483,13 @@ function forInitVar2(init) {
64459
64483
  const d2 = init.declarations[0];
64460
64484
  return d2.id?.type === "Identifier" ? { name: d2.id.name, initExpr: d2.init } : null;
64461
64485
  }
64462
- function parseForHeader2(stmt, resolve60) {
64486
+ function parseForHeader2(stmt, resolve61) {
64463
64487
  const iv = forInitVar2(stmt.init);
64464
64488
  const test = stmt.test;
64465
64489
  if (!iv || test?.type !== "BinaryExpression" || test.left?.name !== iv.name) return null;
64466
- const start = asNum2(resolve60(iv.initExpr));
64467
- const end = asNum2(resolve60(test.right));
64468
- const step = loopStep2(stmt.update, iv.name, resolve60);
64490
+ const start = asNum2(resolve61(iv.initExpr));
64491
+ const end = asNum2(resolve61(test.right));
64492
+ const step = loopStep2(stmt.update, iv.name, resolve61);
64469
64493
  if (start === void 0 || end === void 0 || !step) return null;
64470
64494
  return { v: iv.name, start, end, op: test.operator, step };
64471
64495
  }
@@ -64577,12 +64601,12 @@ function expandStatements2(stmts, ctx) {
64577
64601
  }
64578
64602
  return out;
64579
64603
  }
64580
- function inlineComputedTimelines2(ast, timelineVar, resolve60) {
64604
+ function inlineComputedTimelines2(ast, timelineVar, resolve61) {
64581
64605
  const helpers = collectInlinableHelpers2(ast, timelineVar);
64582
64606
  const ctx = {
64583
64607
  helpers,
64584
64608
  timelineVar,
64585
- resolve: resolve60,
64609
+ resolve: resolve61,
64586
64610
  depth: 0,
64587
64611
  site: { n: 0 },
64588
64612
  order: { n: 0 }
@@ -66495,6 +66519,11 @@ function extractFontFaceFamilies(styles) {
66495
66519
  }
66496
66520
  return families;
66497
66521
  }
66522
+ function normalizeUsedFontName(part) {
66523
+ const name = part.trim().replace(/^['"]|['"]$/g, "").trim().toLowerCase();
66524
+ if (!name || name.includes("(") || name.includes(")")) return null;
66525
+ return name;
66526
+ }
66498
66527
  function extractUsedFontFamilies(styles) {
66499
66528
  const used = [];
66500
66529
  const seen = /* @__PURE__ */ new Set();
@@ -66503,9 +66532,8 @@ function extractUsedFontFamilies(styles) {
66503
66532
  const withoutFontFace = stripCssComments(style.content).replace(/@font-face\s*\{[^}]*\}/gi, "");
66504
66533
  let match;
66505
66534
  while ((match = propRe.exec(withoutFontFace)) !== null) {
66506
- const stack = match[1];
66507
- for (const part of stack.split(",")) {
66508
- const name = part.trim().replace(/^['"]|['"]$/g, "").trim().toLowerCase();
66535
+ for (const part of match[1].split(",")) {
66536
+ const name = normalizeUsedFontName(part);
66509
66537
  if (name && !GENERIC_FAMILIES.has(name) && !seen.has(name)) {
66510
66538
  seen.add(name);
66511
66539
  used.push(name);
@@ -67078,7 +67106,7 @@ function lintDuplicateAudioTracks(htmlSources) {
67078
67106
  }
67079
67107
  return findings;
67080
67108
  }
67081
- var TAG_PATTERN, STYLE_BLOCK_PATTERN, SCRIPT_BLOCK_PATTERN, COMPOSITION_ID_IN_CSS_PATTERN, TIMELINE_REGISTRY_INIT_PATTERN, TIMELINE_REGISTRY_ASSIGN_PATTERN, WINDOW_TIMELINE_ASSIGN_PATTERN, INVALID_SCRIPT_CLOSE_PATTERN, TIMELINE_REGISTRY_KEY_PATTERN, HEAD_BLOCKS_TO_IGNORE_PATTERN, HTML_TAG_PATTERN, HEAD_CONTENT_PATTERN, AFTER_HEAD_BEFORE_BODY_PATTERN, STRAY_HEAD_CLOSE_PATTERN, MARKDOWN_CODE_FENCE_PATTERN, ORPHAN_CSS_AT_RULE_PATTERN, ORPHAN_CSS_RULE_PATTERN, coreRules, mediaRules, SCENE_BOUNDARY_EPSILON_SECONDS, gsapWindowsCache, CONFLICTING_TRANSLATE_PROPS, CONFLICTING_SCALE_PROPS, gsapRules, captionRules, MAX_COMPOSITION_LINES, MAX_TIMED_ELEMENTS_PER_TRACK, TRACK_DENSITY_EXEMPT_TAGS, compositionRules, adapterRules, TEXTURE_BASE_CLASS, TEXTURE_CLASS_PREFIX, textureRules, GENERIC_FAMILIES, fontRules, slideshowRules, ALL_RULES, AUDIO_EXTENSIONS, STYLE_BLOCK_RE, OPEN_TAG_RE, MASK_IMAGE_URL_RE;
67109
+ var TAG_PATTERN, STYLE_BLOCK_PATTERN, SCRIPT_BLOCK_PATTERN, COMPOSITION_ID_IN_CSS_PATTERN, TIMELINE_REGISTRY_INIT_PATTERN, TIMELINE_REGISTRY_ASSIGN_PATTERN, WINDOW_TIMELINE_ASSIGN_PATTERN, INVALID_SCRIPT_CLOSE_PATTERN, TIMELINE_REGISTRY_KEY_PATTERN, HEAD_BLOCKS_TO_IGNORE_PATTERN, HTML_TAG_PATTERN, HEAD_CONTENT_PATTERN, AFTER_HEAD_BEFORE_BODY_PATTERN, STRAY_HEAD_CLOSE_PATTERN, MARKDOWN_CODE_FENCE_PATTERN, ORPHAN_CSS_AT_RULE_PATTERN, ORPHAN_CSS_RULE_PATTERN, coreRules, mediaRules, SCENE_BOUNDARY_EPSILON_SECONDS, UNRESOLVED_TARGET, gsapWindowsCache, CONFLICTING_TRANSLATE_PROPS, CONFLICTING_SCALE_PROPS, gsapRules, captionRules, MAX_COMPOSITION_LINES, MAX_TIMED_ELEMENTS_PER_TRACK, TRACK_DENSITY_EXEMPT_TAGS, compositionRules, adapterRules, TEXTURE_BASE_CLASS, TEXTURE_CLASS_PREFIX, textureRules, GENERIC_FAMILIES, fontRules, slideshowRules, ALL_RULES, AUDIO_EXTENSIONS, STYLE_BLOCK_RE, OPEN_TAG_RE, MASK_IMAGE_URL_RE;
67082
67110
  var init_dist4 = __esm({
67083
67111
  "../lint/dist/index.js"() {
67084
67112
  "use strict";
@@ -67737,6 +67765,7 @@ var init_dist4 = __esm({
67737
67765
  findImperativeMediaControlFindings
67738
67766
  ];
67739
67767
  SCENE_BOUNDARY_EPSILON_SECONDS = 0.05;
67768
+ UNRESOLVED_TARGET = "__unresolved__";
67740
67769
  gsapWindowsCache = /* @__PURE__ */ new Map();
67741
67770
  CONFLICTING_TRANSLATE_PROPS = ["x", "y", "xPercent", "yPercent"];
67742
67771
  CONFLICTING_SCALE_PROPS = ["scale", "scaleX", "scaleY"];
@@ -67774,6 +67803,7 @@ var init_dist4 = __esm({
67774
67803
  const left = gsapWindows[i2];
67775
67804
  if (!left) continue;
67776
67805
  if (left.end <= left.position) continue;
67806
+ if (left.targetSelector === UNRESOLVED_TARGET) continue;
67777
67807
  for (let j3 = i2 + 1; j3 < gsapWindows.length; j3++) {
67778
67808
  const right = gsapWindows[j3];
67779
67809
  if (!right) continue;
@@ -67800,6 +67830,7 @@ ${right.raw}`)
67800
67830
  }
67801
67831
  if (clipStartBoundaries.length > 0) {
67802
67832
  for (const win of gsapWindows) {
67833
+ if (win.targetSelector === UNRESOLVED_TARGET) continue;
67803
67834
  if (!isSceneBoundaryExit(win)) continue;
67804
67835
  const boundary = findMatchingSceneBoundary(win.end, clipStartBoundaries);
67805
67836
  if (boundary == null) continue;
@@ -68942,7 +68973,7 @@ ${right.raw}`)
68942
68973
  (t2) => /["']three["']/.test(t2) && /importmap/.test(scripts.find((s2) => s2.content === t2)?.attrs || "")
68943
68974
  );
68944
68975
  const hasThreeModuleImport = texts.some(
68945
- (t2) => /\bimport\b.*['"]three['"]/.test(t2) || /\bfrom\s+['"]three['"]/.test(t2)
68976
+ (t2) => /\b(?:import|from)\s*[^;\n]*['"][^'"]*three[^'"]*['"]/i.test(t2)
68946
68977
  );
68947
68978
  if (!usesThree || hasThreeScript || hasThreeImportMap || hasThreeModuleImport) return [];
68948
68979
  return [
@@ -69051,6 +69082,12 @@ ${right.raw}`)
69051
69082
  "math",
69052
69083
  "emoji",
69053
69084
  "fangsong",
69085
+ // Vendor-prefixed system-font keywords. Like `system-ui`, the engine resolves
69086
+ // these to the OS UI font — they are never installable files and must not be
69087
+ // flagged as a missing @font-face, even when a generic fallback follows them
69088
+ // (e.g. `-apple-system, system-ui, sans-serif`).
69089
+ "-apple-system",
69090
+ "blinkmacsystemfont",
69054
69091
  "inherit",
69055
69092
  "initial",
69056
69093
  "unset",
@@ -69717,11 +69754,11 @@ function enforceCompositionPixelSizing(document2) {
69717
69754
  for (const [compId, { w: w3, h: h3 }] of sizeMap) {
69718
69755
  const escaped = compId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
69719
69756
  const blockRe = new RegExp(`(\\[data-composition-id=["']${escaped}["']\\]\\s*\\{)([^}]*)(})`, "g");
69720
- css = css.replace(blockRe, (_, open2, body, close) => {
69757
+ css = css.replace(blockRe, (_, open3, body, close) => {
69721
69758
  const newBody = body.replace(/(\bwidth\s*:\s*)100%/g, `$1${w3}px`).replace(/(\bheight\s*:\s*)100%/g, `$1${h3}px`);
69722
69759
  if (newBody !== body)
69723
69760
  modified = true;
69724
- return open2 + newBody + close;
69761
+ return open3 + newBody + close;
69725
69762
  });
69726
69763
  }
69727
69764
  if (modified)
@@ -70414,7 +70451,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
70414
70451
  args.push("-q:v", format === "jpg" ? String(Math.ceil((100 - quality) / 3)) : "0");
70415
70452
  if (format === "png") args.push("-compression_level", "6");
70416
70453
  args.push("-y", outputPattern);
70417
- return new Promise((resolve60, reject) => {
70454
+ return new Promise((resolve61, reject) => {
70418
70455
  const ffmpeg = spawn6(getFfmpegBinary(), args);
70419
70456
  trackChildProcess(ffmpeg);
70420
70457
  let stderr = "";
@@ -70450,7 +70487,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
70450
70487
  files.forEach((file, index) => {
70451
70488
  framePaths.set(index, join11(videoOutputDir, file));
70452
70489
  });
70453
- resolve60({
70490
+ resolve61({
70454
70491
  videoId,
70455
70492
  srcPath: videoPath,
70456
70493
  outputDir: videoOutputDir,
@@ -72341,11 +72378,11 @@ function createFileServer(options) {
72341
72378
  headers: { "Content-Type": contentType }
72342
72379
  });
72343
72380
  });
72344
- return new Promise((resolve60) => {
72381
+ return new Promise((resolve61) => {
72345
72382
  const server = serve({ fetch: app.fetch, port }, (info) => {
72346
72383
  const actualPort = info.port;
72347
72384
  const url = `http://localhost:${actualPort}`;
72348
- resolve60({
72385
+ resolve61({
72349
72386
  url,
72350
72387
  port: actualPort,
72351
72388
  close: () => server.close()
@@ -74497,6 +74534,7 @@ __export(events_exports, {
74497
74534
  trackRenderError: () => trackRenderError,
74498
74535
  trackRenderFeedback: () => trackRenderFeedback,
74499
74536
  trackRenderObservation: () => trackRenderObservation,
74537
+ trackSkillsInstallSkipped: () => trackSkillsInstallSkipped,
74500
74538
  trackTranscribeUnavailable: () => trackTranscribeUnavailable
74501
74539
  });
74502
74540
  function renderObservabilityEventProperties(props) {
@@ -74677,12 +74715,15 @@ function trackCommandFailure(command2, err) {
74677
74715
  function trackTranscribeUnavailable(props) {
74678
74716
  trackEvent("transcribe_unavailable", { optional: props.optional });
74679
74717
  }
74718
+ function trackSkillsInstallSkipped(props) {
74719
+ trackEvent("cli skill install skipped", { reason: props.reason });
74720
+ }
74680
74721
  function trackRenderFeedback(props) {
74681
74722
  trackEvent("survey sent", {
74682
74723
  $survey_id: "render_satisfaction",
74683
74724
  $survey_response: props.rating,
74684
74725
  ...props.comment ? { $survey_response_2: props.comment } : {},
74685
- render_duration_ms: props.renderDurationMs,
74726
+ ...props.renderDurationMs !== void 0 ? { render_duration_ms: props.renderDurationMs } : {},
74686
74727
  ...props.doctorSummary ? { doctor_summary: props.doctorSummary } : {}
74687
74728
  });
74688
74729
  }
@@ -77304,7 +77345,7 @@ import { get as httpsGet } from "https";
77304
77345
  import { pipeline } from "stream/promises";
77305
77346
  function downloadFile(url, dest) {
77306
77347
  const tmp = `${dest}.tmp`;
77307
- return new Promise((resolve60, reject) => {
77348
+ return new Promise((resolve61, reject) => {
77308
77349
  const follow = (u) => {
77309
77350
  httpsGet(u, (res) => {
77310
77351
  if (res.statusCode === 301 || res.statusCode === 302) {
@@ -77321,7 +77362,7 @@ function downloadFile(url, dest) {
77321
77362
  const file = createWriteStream2(tmp);
77322
77363
  pipeline(res, file).then(() => {
77323
77364
  renameSync2(tmp, dest);
77324
- resolve60();
77365
+ resolve61();
77325
77366
  }).catch((err) => {
77326
77367
  try {
77327
77368
  unlinkSync(tmp);
@@ -78495,9 +78536,17 @@ function hasNpx() {
78495
78536
  return false;
78496
78537
  }
78497
78538
  }
78539
+ function hasGit2() {
78540
+ try {
78541
+ execFileSync3("git", ["--version"], { stdio: "ignore", timeout: 5e3 });
78542
+ return true;
78543
+ } catch {
78544
+ return false;
78545
+ }
78546
+ }
78498
78547
  function spawnNpx(args, opts = {}) {
78499
78548
  const npx = buildNpxCommand(args);
78500
- return new Promise((resolve60, reject) => {
78549
+ return new Promise((resolve61, reject) => {
78501
78550
  const child = spawn7(npx.command, npx.args, {
78502
78551
  stdio: "inherit",
78503
78552
  // We install with --full-depth (a full `git clone` of the repo, the only
@@ -78521,7 +78570,7 @@ function spawnNpx(args, opts = {}) {
78521
78570
  }
78522
78571
  });
78523
78572
  child.on("close", (code, signal) => {
78524
- if (code === 0) resolve60();
78573
+ if (code === 0) resolve61();
78525
78574
  else if (signal === "SIGINT" || code === 130) process.exit(0);
78526
78575
  else reject(new Error(`npx ${args.join(" ")} exited with code ${code}`));
78527
78576
  });
@@ -78554,13 +78603,18 @@ function mirrorToInstalledAgents() {
78554
78603
  } catch {
78555
78604
  }
78556
78605
  }
78557
- async function installAllSkills(opts = {}) {
78558
- if (!hasNpx()) {
78559
- const msg = "npx not found. Install Node.js and retry.";
78560
- if (opts.strict) throw new Error(msg);
78561
- R2.error(c.error(msg));
78562
- return;
78606
+ function skillsToolingReady(strict) {
78607
+ for (const tool of SKILLS_TOOLING) {
78608
+ if (tool.has()) continue;
78609
+ if (strict) throw new Error(tool.error);
78610
+ tool.report();
78611
+ trackSkillsInstallSkipped({ reason: tool.reason });
78612
+ return false;
78563
78613
  }
78614
+ return true;
78615
+ }
78616
+ async function installAllSkills(opts = {}) {
78617
+ if (!skillsToolingReady(opts.strict ?? false)) return;
78564
78618
  for (const source of SOURCES) {
78565
78619
  console.log();
78566
78620
  console.log(c.bold(`Installing ${source.name} skills...`));
@@ -78625,7 +78679,7 @@ function renderCheck(result) {
78625
78679
  }
78626
78680
  console.log();
78627
78681
  }
78628
- var examples, GLOBAL_INSTALL_ARGS, PLAIN_SKILL_NAME, SOURCES, checkCommand, updateCommand, skills_default;
78682
+ var examples, GLOBAL_INSTALL_ARGS, PLAIN_SKILL_NAME, SOURCES, SKILLS_TOOLING, checkCommand, updateCommand, skills_default;
78629
78683
  var init_skills = __esm({
78630
78684
  "src/commands/skills.ts"() {
78631
78685
  "use strict";
@@ -78636,6 +78690,7 @@ var init_skills = __esm({
78636
78690
  init_updateCheck();
78637
78691
  init_skillsManifest();
78638
78692
  init_skillsMirror();
78693
+ init_events();
78639
78694
  examples = [
78640
78695
  ["Install all HyperFrames skills", "hyperframes skills"],
78641
78696
  ["Check whether installed skills are up to date", "hyperframes skills check"],
@@ -78655,6 +78710,22 @@ var init_skills = __esm({
78655
78710
  ];
78656
78711
  PLAIN_SKILL_NAME = /^[a-z0-9][a-z0-9._-]*$/i;
78657
78712
  SOURCES = [{ name: "HyperFrames", url: "https://github.com/heygen-com/hyperframes" }];
78713
+ SKILLS_TOOLING = [
78714
+ {
78715
+ has: hasNpx,
78716
+ error: "npx not found. Install Node.js and retry.",
78717
+ reason: "npx_missing",
78718
+ report: () => R2.error(c.error("npx not found. Install Node.js and retry."))
78719
+ },
78720
+ {
78721
+ has: hasGit2,
78722
+ error: "git not found. Install git and retry to add AI coding skills.",
78723
+ reason: "git_missing",
78724
+ // Skip cleanly rather than letting the upstream clone dump a noisy
78725
+ // multi-line `spawn git ENOENT` / "Installation failed" abort.
78726
+ report: () => console.log(c.dim("Skipping AI coding skills: git not available."))
78727
+ }
78728
+ ];
78658
78729
  checkCommand = defineCommand({
78659
78730
  meta: { name: "check", description: "Check whether installed skills are the latest version" },
78660
78731
  args: {
@@ -78973,6 +79044,30 @@ var init_transcribe = __esm({
78973
79044
  }
78974
79045
  });
78975
79046
 
79047
+ // src/utils/errorMessage.ts
79048
+ function normalizeErrorMessage(error) {
79049
+ if (error instanceof Error) return error.message;
79050
+ if (typeof error === "string") return error;
79051
+ if (typeof error === "object" && error !== null) {
79052
+ const msg = error.message;
79053
+ if (typeof msg === "string") return msg;
79054
+ try {
79055
+ return JSON.stringify(error);
79056
+ } catch {
79057
+ try {
79058
+ return `{${Object.keys(error).join(", ")}}`;
79059
+ } catch {
79060
+ }
79061
+ }
79062
+ }
79063
+ return String(error ?? "unknown error");
79064
+ }
79065
+ var init_errorMessage = __esm({
79066
+ "src/utils/errorMessage.ts"() {
79067
+ "use strict";
79068
+ }
79069
+ });
79070
+
78976
79071
  // src/utils/openBrowser.ts
78977
79072
  import { spawn as spawn8 } from "child_process";
78978
79073
  function parseRemoteDebuggingPort(value) {
@@ -79434,6 +79529,11 @@ function formatDuration(ms) {
79434
79529
  const remaining = seconds - minutes * 60;
79435
79530
  return `${minutes}m ${remaining.toFixed(1)}s`;
79436
79531
  }
79532
+ function formatRenderSummaryDetail(input2) {
79533
+ const middle = input2.isDirectory ? input2.frameCount != null ? `${input2.frameCount} frames` : void 0 : input2.outputDurationSeconds != null && input2.outputDurationSeconds > 0 ? `${formatDuration(input2.outputDurationSeconds * 1e3)} video` : void 0;
79534
+ const renderTime = `rendered in ${formatDuration(input2.elapsedMs)}`;
79535
+ return [middle, renderTime].filter(Boolean).join(" \xB7 ");
79536
+ }
79437
79537
  function label(name, value) {
79438
79538
  const pad = 14 - name.length;
79439
79539
  return ` ${c.dim(name)}${" ".repeat(Math.max(1, pad))}${c.bold(value)}`;
@@ -85962,7 +86062,7 @@ var require_processor = __commonJS({
85962
86062
  if (options === void 0) {
85963
86063
  options = {};
85964
86064
  }
85965
- return new Promise(function(resolve60, reject) {
86065
+ return new Promise(function(resolve61, reject) {
85966
86066
  try {
85967
86067
  var root_1 = _this._root(rule, options);
85968
86068
  Promise.resolve(_this.func(root_1)).then(function(transform) {
@@ -85972,7 +86072,7 @@ var require_processor = __commonJS({
85972
86072
  rule.selector = string;
85973
86073
  }
85974
86074
  return { transform, root: root_1, string };
85975
- }).then(resolve60, reject);
86075
+ }).then(resolve61, reject);
85976
86076
  } catch (e3) {
85977
86077
  reject(e3);
85978
86078
  return;
@@ -93578,7 +93678,7 @@ async function loadPuppeteerBrowsers() {
93578
93678
  try {
93579
93679
  return await import("@puppeteer/browsers");
93580
93680
  } catch (err) {
93581
- const cause = err instanceof Error ? err.message : String(err);
93681
+ const cause = normalizeErrorMessage(err);
93582
93682
  throw new Error(
93583
93683
  `Failed to load @puppeteer/browsers: ${cause}
93584
93684
  Fix: run \`npm install\` or \`bun install\` to restore missing packages, then retry.`
@@ -93727,7 +93827,7 @@ async function findBrowser() {
93727
93827
  try {
93728
93828
  return await downloadBrowser();
93729
93829
  } catch (err) {
93730
- const cause = err instanceof Error ? err.message : String(err);
93830
+ const cause = normalizeErrorMessage(err);
93731
93831
  throw new Error(
93732
93832
  `Cached Chrome binary was missing at ${fromCache.staleHyperframesCachePath}, and re-download failed: ${cause}
93733
93833
  Run \`hyperframes browser ensure --force\` to re-download.`
@@ -93829,6 +93929,7 @@ var CHROME_VERSION, CACHE_DIR2, PUPPETEER_CACHE_DIR, SYSTEM_CHROME_PATHS, _warne
93829
93929
  var init_manager2 = __esm({
93830
93930
  "src/browser/manager.ts"() {
93831
93931
  "use strict";
93932
+ init_errorMessage();
93832
93933
  CHROME_VERSION = "131.0.6778.85";
93833
93934
  CACHE_DIR2 = join27(homedir9(), ".cache", "hyperframes", "chrome");
93834
93935
  PUPPETEER_CACHE_DIR = join27(homedir9(), ".cache", "puppeteer", "chrome-headless-shell");
@@ -94463,9 +94564,9 @@ var require_compress_binding = __commonJS({
94463
94564
  });
94464
94565
  } else {
94465
94566
  if (readAsync) {
94466
- return new Promise(function(resolve60, reject) {
94567
+ return new Promise(function(resolve61, reject) {
94467
94568
  readAsync(wasmBinaryFile, function(response) {
94468
- resolve60(new Uint8Array(response));
94569
+ resolve61(new Uint8Array(response));
94469
94570
  }, reject);
94470
94571
  });
94471
94572
  }
@@ -95499,8 +95600,8 @@ var require_compress = __commonJS({
95499
95600
  "../../node_modules/.bun/wawoff2@2.0.1/node_modules/wawoff2/compress.js"(exports, module) {
95500
95601
  "use strict";
95501
95602
  var em_module = require_compress_binding();
95502
- var runtimeInit = new Promise((resolve60) => {
95503
- em_module.onRuntimeInitialized = resolve60;
95603
+ var runtimeInit = new Promise((resolve61) => {
95604
+ em_module.onRuntimeInitialized = resolve61;
95504
95605
  });
95505
95606
  module.exports = async function compress2(buffer) {
95506
95607
  await runtimeInit;
@@ -96019,9 +96120,9 @@ var require_decompress_binding = __commonJS({
96019
96120
  });
96020
96121
  } else {
96021
96122
  if (readAsync) {
96022
- return new Promise(function(resolve60, reject) {
96123
+ return new Promise(function(resolve61, reject) {
96023
96124
  readAsync(wasmBinaryFile, function(response) {
96024
- resolve60(new Uint8Array(response));
96125
+ resolve61(new Uint8Array(response));
96025
96126
  }, reject);
96026
96127
  });
96027
96128
  }
@@ -97036,8 +97137,8 @@ var require_decompress = __commonJS({
97036
97137
  "../../node_modules/.bun/wawoff2@2.0.1/node_modules/wawoff2/decompress.js"(exports, module) {
97037
97138
  "use strict";
97038
97139
  var em_module = require_decompress_binding();
97039
- var runtimeInit = new Promise((resolve60) => {
97040
- em_module.onRuntimeInitialized = resolve60;
97140
+ var runtimeInit = new Promise((resolve61) => {
97141
+ em_module.onRuntimeInitialized = resolve61;
97041
97142
  });
97042
97143
  module.exports = async function decompress(buffer) {
97043
97144
  await runtimeInit;
@@ -98396,10 +98497,10 @@ function createFileServer2(options) {
98396
98497
  }
98397
98498
  });
98398
98499
  });
98399
- return new Promise((resolve60) => {
98500
+ return new Promise((resolve61) => {
98400
98501
  const connections = /* @__PURE__ */ new Set();
98401
98502
  const server = serve2({ fetch: app.fetch, port, hostname: "127.0.0.1" }, (info) => {
98402
- resolve60({
98503
+ resolve61({
98403
98504
  url: `http://localhost:${info.port}`,
98404
98505
  port: info.port,
98405
98506
  addPreHeadScript: (script) => {
@@ -98802,7 +98903,7 @@ var init_shared = __esm({
98802
98903
  });
98803
98904
 
98804
98905
  // ../producer/src/utils/errorMessage.ts
98805
- function normalizeErrorMessage(error) {
98906
+ function normalizeErrorMessage2(error) {
98806
98907
  if (error instanceof Error) return error.message;
98807
98908
  if (typeof error === "string") return error;
98808
98909
  if (typeof error === "object" && error !== null) {
@@ -98819,7 +98920,7 @@ function normalizeErrorMessage(error) {
98819
98920
  }
98820
98921
  return String(error ?? "unknown error");
98821
98922
  }
98822
- var init_errorMessage = __esm({
98923
+ var init_errorMessage2 = __esm({
98823
98924
  "../producer/src/utils/errorMessage.ts"() {
98824
98925
  "use strict";
98825
98926
  }
@@ -98862,10 +98963,10 @@ async function cleanupRenderResources(input2) {
98862
98963
  }
98863
98964
  }
98864
98965
  function buildRenderErrorDetails(input2) {
98865
- const errorMessage3 = normalizeErrorMessage(input2.error);
98966
+ const errorMessage = normalizeErrorMessage2(input2.error);
98866
98967
  const errorStack = input2.error instanceof Error ? input2.error.stack : void 0;
98867
98968
  return {
98868
- message: errorMessage3,
98969
+ message: errorMessage,
98869
98970
  stack: errorStack,
98870
98971
  elapsedMs: Date.now() - input2.pipelineStartMs,
98871
98972
  freeMemoryMB: Math.round(freemem4() / (1024 * 1024)),
@@ -98880,7 +98981,7 @@ var init_cleanup = __esm({
98880
98981
  "use strict";
98881
98982
  init_src();
98882
98983
  init_logger();
98883
- init_errorMessage();
98984
+ init_errorMessage2();
98884
98985
  }
98885
98986
  });
98886
98987
 
@@ -99131,12 +99232,12 @@ var CaptureStageError;
99131
99232
  var init_captureStageError = __esm({
99132
99233
  "../producer/src/services/render/captureStageError.ts"() {
99133
99234
  "use strict";
99134
- init_errorMessage();
99235
+ init_errorMessage2();
99135
99236
  CaptureStageError = class extends Error {
99136
99237
  browserConsole;
99137
99238
  cause;
99138
99239
  constructor(input2) {
99139
- super(normalizeErrorMessage(input2.cause));
99240
+ super(normalizeErrorMessage2(input2.cause));
99140
99241
  this.name = "CaptureStageError";
99141
99242
  this.cause = input2.cause;
99142
99243
  this.browserConsole = input2.browserConsole.slice();
@@ -99444,7 +99545,7 @@ async function runCaptureCalibration(input2) {
99444
99545
  return { calibration, forceScreenshot, probeSession, lastBrowserConsole };
99445
99546
  }
99446
99547
  function shouldFallbackToScreenshotAfterCalibrationError(error) {
99447
- const message = normalizeErrorMessage(error);
99548
+ const message = normalizeErrorMessage2(error);
99448
99549
  return /HeadlessExperimental\.beginFrame timed out|beginFrame probe timeout|Another frame is pending|Frame still pending|Protocol error.*HeadlessExperimental\.beginFrame|Runtime\.callFunctionOn timed out|Runtime\.evaluate timed out/i.test(
99449
99550
  message
99450
99551
  );
@@ -99456,7 +99557,7 @@ var init_captureCost = __esm({
99456
99557
  init_dist3();
99457
99558
  init_src();
99458
99559
  init_logger();
99459
- init_errorMessage();
99560
+ init_errorMessage2();
99460
99561
  CAPTURE_CALIBRATION_TARGET_MS = 600;
99461
99562
  MAX_MEASURED_CAPTURE_COST_MULTIPLIER = 8;
99462
99563
  CAPTURE_CALIBRATION_PROTOCOL_TIMEOUT_MS = 3e4;
@@ -99573,7 +99674,7 @@ var init_observability = __esm({
99573
99674
  "../producer/src/services/render/observability.ts"() {
99574
99675
  "use strict";
99575
99676
  init_dist3();
99576
- init_errorMessage();
99677
+ init_errorMessage2();
99577
99678
  MAX_EVENTS = 160;
99578
99679
  ALLOWED_STRING_DATA_KEYS = /* @__PURE__ */ new Set([
99579
99680
  "browserGpuMode",
@@ -99637,7 +99738,7 @@ var init_observability = __esm({
99637
99738
  status: "error",
99638
99739
  elapsedMs: Date.now() - this.input.pipelineStartMs,
99639
99740
  durationMs: Date.now() - startedAtMs,
99640
- message: sanitizeObservationMessage(normalizeErrorMessage(error)),
99741
+ message: sanitizeObservationMessage(normalizeErrorMessage2(error)),
99641
99742
  data: sanitizeObservationData(data2)
99642
99743
  });
99643
99744
  }
@@ -103404,8 +103505,8 @@ async function createShaderTransitionWorkerPool(opts) {
103404
103505
  if (terminated) {
103405
103506
  throw new Error("shader-blend pool already terminated");
103406
103507
  }
103407
- return new Promise((resolve60, reject) => {
103408
- const task = traceEnabled ? { req, resolve: resolve60, reject, enqueuedAtMs: Date.now(), traceId: ++nextTaskId } : { req, resolve: resolve60, reject };
103508
+ return new Promise((resolve61, reject) => {
103509
+ const task = traceEnabled ? { req, resolve: resolve61, reject, enqueuedAtMs: Date.now(), traceId: ++nextTaskId } : { req, resolve: resolve61, reject };
103409
103510
  const idle = slots.find((s2) => !s2.busy && !s2.dead);
103410
103511
  if (idle) {
103411
103512
  queue.unshift(task);
@@ -104438,7 +104539,7 @@ function captureAttemptMadeProgress(attemptTargetFrameCount, remainingFrameCount
104438
104539
  return remainingFrameCount < attemptTargetFrameCount;
104439
104540
  }
104440
104541
  function isRecoverableParallelCaptureError(error) {
104441
- const message = normalizeErrorMessage(error);
104542
+ const message = normalizeErrorMessage2(error);
104442
104543
  return message.includes("[Parallel] Capture failed") && /Runtime\.callFunctionOn timed out|HeadlessExperimental\.beginFrame timed out|Waiting failed|timeout exceeded|timed out|Navigation timeout|Protocol error|Target closed/i.test(
104443
104544
  message
104444
104545
  );
@@ -105392,7 +105493,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
105392
105493
  if (restoreLogger) restoreLogger();
105393
105494
  throw error instanceof RenderCancelledError ? error : new RenderCancelledError("render_cancelled");
105394
105495
  }
105395
- const errorMessage3 = normalizeErrorMessage(error);
105496
+ const errorMessage = normalizeErrorMessage2(error);
105396
105497
  const carriedBrowserConsole = getCaptureStageBrowserConsole(error);
105397
105498
  if (carriedBrowserConsole.length > 0) {
105398
105499
  lastBrowserConsole = [...lastBrowserConsole, ...carriedBrowserConsole].slice(-200);
@@ -105401,15 +105502,15 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
105401
105502
  const failureStart = Date.now();
105402
105503
  observability.stageError(job.currentStage || "pipeline", failureStart, error);
105403
105504
  }
105404
- const isTimeoutError = errorMessage3.includes("Waiting failed") || errorMessage3.includes("timeout exceeded") || errorMessage3.includes("Navigation timeout");
105505
+ const isTimeoutError = errorMessage.includes("Waiting failed") || errorMessage.includes("timeout exceeded") || errorMessage.includes("Navigation timeout");
105405
105506
  const wasParallel = job.config.workers !== 1;
105406
105507
  if (isTimeoutError && wasParallel) {
105407
105508
  log2.warn(
105408
105509
  `Parallel capture timed out with ${job.config.workers ?? "auto"} workers. Video-heavy compositions often need sequential capture. Retry with --workers 1`
105409
105510
  );
105410
105511
  }
105411
- job.error = errorMessage3;
105412
- updateJobStatus(job, "failed", `Failed: ${errorMessage3}`, job.progress, onProgress);
105512
+ job.error = errorMessage;
105513
+ updateJobStatus(job, "failed", `Failed: ${errorMessage}`, job.progress, onProgress);
105413
105514
  job.failedStage = job.currentStage;
105414
105515
  const observabilitySummary = observability.summary({
105415
105516
  lastBrowserConsole,
@@ -105427,7 +105528,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
105427
105528
  });
105428
105529
  log2.info("[Render] Failure summary", {
105429
105530
  failedStage: job.currentStage,
105430
- error: errorMessage3,
105531
+ error: errorMessage,
105431
105532
  elapsedMs: Date.now() - pipelineStart,
105432
105533
  stageTimings: perfStages,
105433
105534
  isTimeout: isTimeoutError,
@@ -105467,7 +105568,7 @@ var init_renderOrchestrator = __esm({
105467
105568
  init_logger();
105468
105569
  init_shared();
105469
105570
  init_cleanup();
105470
- init_errorMessage();
105571
+ init_errorMessage2();
105471
105572
  init_paths();
105472
105573
  init_hdrMode();
105473
105574
  init_perfSummary();
@@ -105629,12 +105730,12 @@ async function startHealthWorker(options = {}) {
105629
105730
  stdout: false,
105630
105731
  stderr: false
105631
105732
  });
105632
- await new Promise((resolve60, reject) => {
105733
+ await new Promise((resolve61, reject) => {
105633
105734
  const onMessage = (msg) => {
105634
105735
  if (msg?.type === "listening") {
105635
105736
  worker.off("error", onError);
105636
105737
  worker.off("message", onMessage);
105637
- resolve60();
105738
+ resolve61();
105638
105739
  } else if (msg?.type === "listen-error") {
105639
105740
  worker.off("error", onError);
105640
105741
  worker.off("message", onMessage);
@@ -105717,10 +105818,10 @@ var init_semaphore = __esm({
105717
105818
  this.active++;
105718
105819
  return () => this.release();
105719
105820
  }
105720
- return new Promise((resolve60) => {
105821
+ return new Promise((resolve61) => {
105721
105822
  this.queue.push(() => {
105722
105823
  this.active++;
105723
- resolve60(() => this.release());
105824
+ resolve61(() => this.release());
105724
105825
  });
105725
105826
  });
105726
105827
  }
@@ -107767,24 +107868,24 @@ async function defaultRunFfmpeg(args, options) {
107767
107868
  };
107768
107869
  }
107769
107870
  async function runFfmpegWithStdin(args, stdin) {
107770
- return new Promise((resolve60) => {
107871
+ return new Promise((resolve61) => {
107771
107872
  const proc = spawn11(getFfmpegBinary(), args);
107772
107873
  let stderr = "";
107773
107874
  proc.stderr.on("data", (data2) => {
107774
107875
  stderr += data2.toString();
107775
107876
  });
107776
107877
  proc.on("error", (err) => {
107777
- resolve60({
107878
+ resolve61({
107778
107879
  success: false,
107779
107880
  error: `[audioPadTrim] ${err instanceof Error ? err.message : String(err)}`
107780
107881
  });
107781
107882
  });
107782
107883
  proc.on("close", (code) => {
107783
107884
  if (code === 0) {
107784
- resolve60({ success: true });
107885
+ resolve61({ success: true });
107785
107886
  return;
107786
107887
  }
107787
- resolve60({
107888
+ resolve61({
107788
107889
  success: false,
107789
107890
  error: `[audioPadTrim] ${formatFfmpegError(code, stderr)}`
107790
107891
  });
@@ -107793,7 +107894,7 @@ async function runFfmpegWithStdin(args, stdin) {
107793
107894
  });
107794
107895
  }
107795
107896
  function runFfprobeJson(args) {
107796
- return new Promise((resolve60, reject) => {
107897
+ return new Promise((resolve61, reject) => {
107797
107898
  const proc = spawn11(getFfprobeBinary(), args);
107798
107899
  let stdout2 = "";
107799
107900
  let stderr = "";
@@ -107816,7 +107917,7 @@ function runFfprobeJson(args) {
107816
107917
  return;
107817
107918
  }
107818
107919
  try {
107819
- resolve60(JSON.parse(stdout2));
107920
+ resolve61(JSON.parse(stdout2));
107820
107921
  } catch (err) {
107821
107922
  reject(new Error(`Failed to parse ffprobe output: ${err.message}`));
107822
107923
  }
@@ -108137,7 +108238,7 @@ __export(src_exports2, {
108137
108238
  getCapturePerfSummary: () => getCapturePerfSummary,
108138
108239
  getCompositionDuration: () => getCompositionDuration,
108139
108240
  initializeSession: () => initializeSession,
108140
- normalizeErrorMessage: () => normalizeErrorMessage,
108241
+ normalizeErrorMessage: () => normalizeErrorMessage2,
108141
108242
  plan: () => plan,
108142
108243
  prepareCaptureSessionForReuse: () => prepareCaptureSessionForReuse,
108143
108244
  prepareHyperframeLintBody: () => prepareHyperframeLintBody,
@@ -108158,7 +108259,7 @@ var init_src2 = __esm({
108158
108259
  init_config3();
108159
108260
  init_logger();
108160
108261
  init_server();
108161
- init_errorMessage();
108262
+ init_errorMessage2();
108162
108263
  init_parityContract2();
108163
108264
  init_paths();
108164
108265
  init_hyperframeLint();
@@ -108761,9 +108862,6 @@ function printSelectionFailure(code, message, json) {
108761
108862
  }
108762
108863
  process.exitCode = 1;
108763
108864
  }
108764
- function errorMessage(error) {
108765
- return error instanceof Error ? error.message : String(error);
108766
- }
108767
108865
  function previewServerPayload(server) {
108768
108866
  return {
108769
108867
  port: server.port,
@@ -108833,7 +108931,7 @@ async function printCurrentSelection(projectDir, startPort, json, preferredPort)
108833
108931
  try {
108834
108932
  response = await fetchStudioSelection2(server);
108835
108933
  } catch (err) {
108836
- printSelectionFailure("selection-unavailable", errorMessage(err), json);
108934
+ printSelectionFailure("selection-unavailable", normalizeErrorMessage(err), json);
108837
108935
  return;
108838
108936
  }
108839
108937
  if (!response.selection) {
@@ -108884,11 +108982,7 @@ async function printCurrentContext(projectDir, startPort, options) {
108884
108982
  try {
108885
108983
  fields = parseContextFields(options.fields);
108886
108984
  } catch (err) {
108887
- printSelectionFailure(
108888
- "invalid-context-fields",
108889
- err instanceof Error ? err.message : String(err),
108890
- options.json
108891
- );
108985
+ printSelectionFailure("invalid-context-fields", normalizeErrorMessage(err), options.json);
108892
108986
  return;
108893
108987
  }
108894
108988
  const fullDetail = options.detail === "full";
@@ -108959,7 +109053,7 @@ async function printCurrentContext(projectDir, startPort, options) {
108959
109053
  updatedAt: selectionResult.value.updatedAt
108960
109054
  } : {
108961
109055
  ok: false,
108962
- error: selectionResult.status === "rejected" ? { code: "selection-unavailable", message: errorMessage(selectionResult.reason) } : {
109056
+ error: selectionResult.status === "rejected" ? { code: "selection-unavailable", message: normalizeErrorMessage(selectionResult.reason) } : {
108963
109057
  code: "no-selection",
108964
109058
  message: "Studio is running, but no element is selected."
108965
109059
  }
@@ -108970,7 +109064,7 @@ async function printCurrentContext(projectDir, startPort, options) {
108970
109064
  findings: lintResult.value.findings
108971
109065
  } : {
108972
109066
  ok: false,
108973
- error: lintResult.status === "rejected" ? { code: "lint-unavailable", message: errorMessage(lintResult.reason) } : { code: "lint-not-requested", message: "Lint was not requested." }
109067
+ error: lintResult.status === "rejected" ? { code: "lint-unavailable", message: normalizeErrorMessage(lintResult.reason) } : { code: "lint-not-requested", message: "Lint was not requested." }
108974
109068
  };
108975
109069
  const payload = { ok: true };
108976
109070
  if (contextIncludes(fields, "server")) payload.server = previewServerPayload(server);
@@ -109274,6 +109368,7 @@ var init_preview = __esm({
109274
109368
  init_dist8();
109275
109369
  init_colors();
109276
109370
  init_env();
109371
+ init_errorMessage();
109277
109372
  init_npxCommand();
109278
109373
  init_openBrowser();
109279
109374
  init_lintProject();
@@ -111628,9 +111723,10 @@ function archiveArrayBuffer(archive) {
111628
111723
  new Uint8Array(arrayBuffer).set(archive.buffer);
111629
111724
  return arrayBuffer;
111630
111725
  }
111631
- async function publishProjectArchiveDirect(apiBaseUrl2, title, archive) {
111726
+ async function publishProjectArchiveDirect(apiBaseUrl2, title, archive, isPublic) {
111632
111727
  const body = new FormData();
111633
111728
  body.set("title", title);
111729
+ if (isPublic) body.set("is_public", "true");
111634
111730
  body.set(
111635
111731
  "file",
111636
111732
  new File([archiveArrayBuffer(archive)], `${title}.zip`, { type: PUBLISH_CONTENT_TYPE })
@@ -111651,7 +111747,7 @@ async function publishProjectArchiveDirect(apiBaseUrl2, title, archive) {
111651
111747
  }
111652
111748
  return publishedProject;
111653
111749
  }
111654
- async function publishProjectArchiveStaged(apiBaseUrl2, title, archive) {
111750
+ async function publishProjectArchiveStaged(apiBaseUrl2, title, archive, isPublic) {
111655
111751
  const fileName = `${title}.zip`;
111656
111752
  const uploadResponse = await fetch(`${apiBaseUrl2}/v1/hyperframes/projects/publish/upload`, {
111657
111753
  method: "POST",
@@ -111691,7 +111787,8 @@ async function publishProjectArchiveStaged(apiBaseUrl2, title, archive) {
111691
111787
  body: JSON.stringify({
111692
111788
  upload_key: stagedUpload.uploadKey,
111693
111789
  file_name: fileName,
111694
- title
111790
+ title,
111791
+ ...isPublic ? { is_public: true } : {}
111695
111792
  }),
111696
111793
  headers: {
111697
111794
  "content-type": "application/json",
@@ -111706,13 +111803,14 @@ async function publishProjectArchiveStaged(apiBaseUrl2, title, archive) {
111706
111803
  }
111707
111804
  return publishedProject;
111708
111805
  }
111709
- async function publishProjectArchive(projectDir) {
111806
+ async function publishProjectArchive(projectDir, opts = {}) {
111807
+ const isPublic = opts.public === true;
111710
111808
  const title = basename11(projectDir);
111711
111809
  const archive = createPublishArchive(projectDir);
111712
111810
  const apiBaseUrl2 = getPublishApiBaseUrl();
111713
- const stagedResult = await publishProjectArchiveStaged(apiBaseUrl2, title, archive);
111811
+ const stagedResult = await publishProjectArchiveStaged(apiBaseUrl2, title, archive, isPublic);
111714
111812
  if (stagedResult) return stagedResult;
111715
- return publishProjectArchiveDirect(apiBaseUrl2, title, archive);
111813
+ return publishProjectArchiveDirect(apiBaseUrl2, title, archive, isPublic);
111716
111814
  }
111717
111815
  var IGNORED_DIRS, IGNORED_FILES, PUBLISH_CONTENT_TYPE, PUBLISH_METADATA_TIMEOUT_MS, PUBLISH_UPLOAD_MIN_TIMEOUT_MS, PUBLISH_UPLOAD_BYTES_PER_SECOND, EXT_ASSETS_PREFIX;
111718
111816
  var init_publishProject = __esm({
@@ -111752,6 +111850,7 @@ var init_publish = __esm({
111752
111850
  examples8 = [
111753
111851
  ["Publish the current project with a public URL", "hyperframes publish"],
111754
111852
  ["Publish a specific directory", "hyperframes publish ./my-video"],
111853
+ ["Make the claimed project public to anyone", "hyperframes publish --public"],
111755
111854
  ["Skip the consent prompt (scripts)", "hyperframes publish --yes"]
111756
111855
  ];
111757
111856
  publish_default = defineCommand({
@@ -111766,6 +111865,11 @@ var init_publish = __esm({
111766
111865
  alias: "y",
111767
111866
  description: "Skip the publish confirmation prompt",
111768
111867
  default: false
111868
+ },
111869
+ public: {
111870
+ type: "boolean",
111871
+ description: "Make the claimed project public to anyone, not just the claimer",
111872
+ default: false
111769
111873
  }
111770
111874
  },
111771
111875
  async run({ args }) {
@@ -111801,7 +111905,7 @@ var init_publish = __esm({
111801
111905
  const publishSpinner = ft();
111802
111906
  publishSpinner.start("Uploading project...");
111803
111907
  try {
111804
- const published = await publishProjectArchive(dir);
111908
+ const published = await publishProjectArchive(dir, { public: args.public === true });
111805
111909
  const claimUrl = new URL(published.url);
111806
111910
  claimUrl.searchParams.set("claim_token", published.claimToken);
111807
111911
  publishSpinner.stop(c.success("Project published"));
@@ -112209,18 +112313,18 @@ async function getDoctorSummary() {
112209
112313
  }
112210
112314
  }
112211
112315
  function askQuestion(prompt) {
112212
- return new Promise((resolve60) => {
112316
+ return new Promise((resolve61) => {
112213
112317
  const rl = readline.createInterface({
112214
112318
  input: process.stdin,
112215
112319
  output: process.stdout
112216
112320
  });
112217
112321
  rl.question(prompt, (answer) => {
112218
112322
  rl.close();
112219
- resolve60(answer);
112323
+ resolve61(answer);
112220
112324
  });
112221
112325
  const timeout = setTimeout(() => {
112222
112326
  rl.close();
112223
- resolve60("");
112327
+ resolve61("");
112224
112328
  }, 1e4);
112225
112329
  if (typeof timeout === "object" && timeout !== null && "unref" in timeout) {
112226
112330
  timeout.unref();
@@ -112316,30 +112420,6 @@ var init_dockerRunArgs = __esm({
112316
112420
  }
112317
112421
  });
112318
112422
 
112319
- // src/utils/errorMessage.ts
112320
- function normalizeErrorMessage2(error) {
112321
- if (error instanceof Error) return error.message;
112322
- if (typeof error === "string") return error;
112323
- if (typeof error === "object" && error !== null) {
112324
- const msg = error.message;
112325
- if (typeof msg === "string") return msg;
112326
- try {
112327
- return JSON.stringify(error);
112328
- } catch {
112329
- try {
112330
- return `{${Object.keys(error).join(", ")}}`;
112331
- } catch {
112332
- }
112333
- }
112334
- }
112335
- return String(error ?? "unknown error");
112336
- }
112337
- var init_errorMessage2 = __esm({
112338
- "src/utils/errorMessage.ts"() {
112339
- "use strict";
112340
- }
112341
- });
112342
-
112343
112423
  // src/browser/preflight.ts
112344
112424
  import { execFileSync as execFileSync7 } from "child_process";
112345
112425
  import { existsSync as existsSync63 } from "fs";
@@ -112540,10 +112620,7 @@ function parseJson(raw, source) {
112540
112620
  try {
112541
112621
  return JSON.parse(raw);
112542
112622
  } catch (error) {
112543
- throw new BatchRenderInputError(
112544
- "Invalid JSON in --batch",
112545
- `${source}: ${error instanceof Error ? error.message : String(error)}`
112546
- );
112623
+ throw new BatchRenderInputError("Invalid JSON in --batch", `${source}: ${normalizeErrorMessage(error)}`);
112547
112624
  }
112548
112625
  }
112549
112626
  function parseBatchRows(raw, source) {
@@ -112662,7 +112739,7 @@ function prepareBatchRender(options) {
112662
112739
  } catch (error) {
112663
112740
  throw new BatchRenderInputError(
112664
112741
  "Could not read --batch",
112665
- `${batchPath}: ${error instanceof Error ? error.message : String(error)}`
112742
+ `${batchPath}: ${normalizeErrorMessage(error)}`
112666
112743
  );
112667
112744
  }
112668
112745
  const variableRows = parseBatchRows(raw, batchPath);
@@ -112725,9 +112802,6 @@ function writeManifest(manifest) {
112725
112802
  function emitJsonEvent(event, json) {
112726
112803
  if (json) console.log(JSON.stringify(event));
112727
112804
  }
112728
- function errorMessage2(error) {
112729
- return error instanceof Error ? error.message : String(error);
112730
- }
112731
112805
  async function renderBatchRow(row, manifest, options) {
112732
112806
  const manifestRow = manifest.rows[row.index];
112733
112807
  if (!manifestRow) {
@@ -112764,7 +112838,7 @@ async function renderBatchRow(row, manifest, options) {
112764
112838
  return true;
112765
112839
  } catch (error) {
112766
112840
  manifestRow.status = "failed";
112767
- manifestRow.error = errorMessage2(error);
112841
+ manifestRow.error = normalizeErrorMessage(error);
112768
112842
  manifestRow.completedAt = (/* @__PURE__ */ new Date()).toISOString();
112769
112843
  writeManifest(manifest);
112770
112844
  emitJsonEvent(
@@ -112860,6 +112934,7 @@ var init_batchRender = __esm({
112860
112934
  "use strict";
112861
112935
  init_colors();
112862
112936
  init_format();
112937
+ init_errorMessage();
112863
112938
  init_variables();
112864
112939
  BatchRenderInputError = class extends Error {
112865
112940
  title;
@@ -112972,7 +113047,7 @@ function ensureDockerImage(version2, platform10, quiet) {
112972
113047
  { stdio: quiet ? "pipe" : "inherit", timeout: 6e5 }
112973
113048
  );
112974
113049
  } catch (error) {
112975
- const message = error instanceof Error ? error.message : String(error);
113050
+ const message = normalizeErrorMessage(error);
112976
113051
  throw new Error(`Failed to build Docker image: ${message}`);
112977
113052
  } finally {
112978
113053
  rmSync17(tmpDir, { recursive: true, force: true });
@@ -113010,7 +113085,7 @@ async function renderDocker(projectDir, outputPath, options) {
113010
113085
  try {
113011
113086
  imageTag = ensureDockerImage(dockerVersion, platform10, options.quiet);
113012
113087
  } catch (error) {
113013
- const message = error instanceof Error ? error.message : String(error);
113088
+ const message = normalizeErrorMessage(error);
113014
113089
  const isDockerMissing = /connect|not found|ENOENT/i.test(message);
113015
113090
  errorBox(
113016
113091
  isDockerMissing ? "Docker not available" : "Docker image build failed",
@@ -113158,7 +113233,13 @@ async function renderLocal(projectDir, outputPath, options) {
113158
113233
  }
113159
113234
  const elapsed = Date.now() - startTime;
113160
113235
  trackRenderMetrics(job, elapsed, options, false);
113161
- printRenderComplete(outputPath, elapsed, options.quiet);
113236
+ printRenderComplete(
113237
+ outputPath,
113238
+ elapsed,
113239
+ options.quiet,
113240
+ job.perfSummary?.compositionDurationSeconds,
113241
+ job.perfSummary?.totalFrames
113242
+ );
113162
113243
  if (!options.skipFeedback) {
113163
113244
  await maybePromptRenderFeedback({
113164
113245
  renderDurationMs: elapsed,
@@ -113264,7 +113345,7 @@ function createNoopProducerLogger() {
113264
113345
  };
113265
113346
  }
113266
113347
  function handleRenderError(error, options, startTime, docker, hint2, failedStage, job) {
113267
- const message = normalizeErrorMessage2(error);
113348
+ const message = normalizeErrorMessage(error);
113268
113349
  trackRenderError({
113269
113350
  fps: fpsToNumber(options.fps),
113270
113351
  quality: options.quality,
@@ -113333,11 +113414,13 @@ function trackRenderMetrics(job, elapsedMs, options, docker) {
113333
113414
  ...getMemorySnapshot()
113334
113415
  });
113335
113416
  }
113336
- function printRenderComplete(outputPath, elapsedMs, quiet) {
113417
+ function printRenderComplete(outputPath, elapsedMs, quiet, outputDurationSeconds, frameCount) {
113337
113418
  if (quiet) return;
113338
113419
  let fileSize = "unknown";
113420
+ let isDirectory = false;
113339
113421
  try {
113340
113422
  const stat3 = statSync19(outputPath);
113423
+ isDirectory = stat3.isDirectory();
113341
113424
  if (stat3.isDirectory()) {
113342
113425
  let total = 0;
113343
113426
  for (const entry of readdirSync24(outputPath, { withFileTypes: true })) {
@@ -113353,10 +113436,15 @@ function printRenderComplete(outputPath, elapsedMs, quiet) {
113353
113436
  }
113354
113437
  } catch {
113355
113438
  }
113356
- const duration = formatDuration(elapsedMs);
113439
+ const detail = formatRenderSummaryDetail({
113440
+ elapsedMs,
113441
+ outputDurationSeconds,
113442
+ isDirectory,
113443
+ frameCount
113444
+ });
113357
113445
  console.log("");
113358
113446
  console.log(c.success("\u25C7") + " " + c.accent(outputPath));
113359
- console.log(" " + c.bold(fileSize) + c.dim(" \xB7 " + duration + " \xB7 completed"));
113447
+ console.log(" " + c.bold(fileSize) + c.dim(" \xB7 " + detail));
113360
113448
  }
113361
113449
  var examples9, VALID_QUALITY, RENDER_FORMATS, VALID_FORMAT, RENDER_FORMAT_LABEL, FORMAT_EXT, CPU_CORE_COUNT, render_default, DOCKER_IMAGE_PREFIX;
113362
113450
  var init_render = __esm({
@@ -113380,7 +113468,7 @@ var init_render = __esm({
113380
113468
  init_version();
113381
113469
  init_env();
113382
113470
  init_dockerRunArgs();
113383
- init_errorMessage2();
113471
+ init_errorMessage();
113384
113472
  init_preflight();
113385
113473
  init_src();
113386
113474
  init_dist3();
@@ -113833,6 +113921,19 @@ var init_render = __esm({
113833
113921
  batchModule.exitBatchRenderInputError(error);
113834
113922
  }
113835
113923
  }
113924
+ if (!quiet) {
113925
+ try {
113926
+ const renderTarget = entryFile ? resolve44(project.dir, entryFile) : project.indexPath;
113927
+ const { slideshowIslandRegex: slideshowIslandRegex2 } = await Promise.resolve().then(() => (init_slideshow2(), slideshow_exports));
113928
+ if (slideshowIslandRegex2("i").test(readFileSync40(renderTarget, "utf8"))) {
113929
+ console.log(
113930
+ c.warn("\u26A0") + " This composition carries a slideshow island \u2014 `render` captures only the first scene, so the MP4 will be truncated to slide 1. Use " + c.accent("hyperframes present") + " for the deck; a linear main-line MP4 export is not yet available."
113931
+ );
113932
+ console.log("");
113933
+ }
113934
+ } catch {
113935
+ }
113936
+ }
113836
113937
  if (!quiet && !batchPath) {
113837
113938
  const workerLabel = workers != null ? `${workers} workers` : `auto workers (${CPU_CORE_COUNT} cores detected)`;
113838
113939
  console.log("");
@@ -113883,7 +113984,7 @@ var init_render = __esm({
113883
113984
  browserSpinner?.stop(c.error("Browser not available"));
113884
113985
  errorBox(
113885
113986
  "Chrome not found",
113886
- err instanceof Error ? err.message : String(err),
113987
+ normalizeErrorMessage(err),
113887
113988
  "Run: npx hyperframes browser ensure"
113888
113989
  );
113889
113990
  process.exit(1);
@@ -114421,8 +114522,43 @@ __export(staticProjectServer_exports, {
114421
114522
  serveStaticProjectHtml: () => serveStaticProjectHtml
114422
114523
  });
114423
114524
  import { createServer } from "http";
114424
- import { existsSync as existsSync66, readFileSync as readFileSync44 } from "fs";
114525
+ import { createReadStream as createReadStream3, existsSync as existsSync66, statSync as statSync20 } from "fs";
114425
114526
  import { isAbsolute as isAbsolute13, relative as relative14, resolve as resolve46 } from "path";
114527
+ function serveFileWithRange(filePath, rangeHeader, res) {
114528
+ const size = statSync20(filePath).size;
114529
+ const headers = {
114530
+ "Content-Type": getMimeType(filePath),
114531
+ "Accept-Ranges": "bytes"
114532
+ };
114533
+ const last = size - 1;
114534
+ let start = 0;
114535
+ let end = last;
114536
+ let status = 200;
114537
+ const match = rangeHeader ? /^bytes=(\d*)-(\d*)$/.exec(rangeHeader.trim()) : null;
114538
+ if (match) {
114539
+ const hasStart = match[1] !== "";
114540
+ start = hasStart ? Number(match[1]) : Math.max(0, size - Number(match[2]));
114541
+ end = !hasStart ? last : match[2] !== "" ? Math.min(Number(match[2]), last) : last;
114542
+ if (start > end || start > last) {
114543
+ res.writeHead(416, { ...headers, "Content-Range": `bytes */${size}` });
114544
+ res.end();
114545
+ return;
114546
+ }
114547
+ status = 206;
114548
+ headers["Content-Range"] = `bytes ${start}-${end}/${size}`;
114549
+ }
114550
+ headers["Content-Length"] = String(end - start + 1);
114551
+ const stream = createReadStream3(filePath, { start, end });
114552
+ stream.on("open", () => {
114553
+ res.writeHead(status, headers);
114554
+ stream.pipe(res);
114555
+ });
114556
+ stream.on("error", () => {
114557
+ if (!res.headersSent) res.writeHead(500);
114558
+ res.end();
114559
+ stream.destroy();
114560
+ });
114561
+ }
114426
114562
  async function serveStaticProjectHtml(projectDir, html, bindErrorMessage = "Failed to bind local HTTP server") {
114427
114563
  const server = createServer((req, res) => {
114428
114564
  const url = req.url ?? "/";
@@ -114439,8 +114575,7 @@ async function serveStaticProjectHtml(projectDir, html, bindErrorMessage = "Fail
114439
114575
  return;
114440
114576
  }
114441
114577
  if (existsSync66(filePath)) {
114442
- res.writeHead(200, { "Content-Type": getMimeType(filePath) });
114443
- res.end(readFileSync44(filePath));
114578
+ serveFileWithRange(filePath, req.headers.range, res);
114444
114579
  return;
114445
114580
  }
114446
114581
  res.writeHead(404);
@@ -114832,7 +114967,7 @@ var init_motionAudit = __esm({
114832
114967
  });
114833
114968
 
114834
114969
  // src/utils/motionSpec.ts
114835
- import { existsSync as existsSync67, readFileSync as readFileSync45, readdirSync as readdirSync25 } from "fs";
114970
+ import { existsSync as existsSync67, readFileSync as readFileSync44, readdirSync as readdirSync25 } from "fs";
114836
114971
  import { basename as basename13, join as join70 } from "path";
114837
114972
  function isObject2(value) {
114838
114973
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -114894,7 +115029,7 @@ function findMotionSpec(projectDir) {
114894
115029
  function readMotionSpec(path2) {
114895
115030
  let raw;
114896
115031
  try {
114897
- raw = JSON.parse(readFileSync45(path2, "utf-8"));
115032
+ raw = JSON.parse(readFileSync44(path2, "utf-8"));
114898
115033
  } catch (err) {
114899
115034
  return { ok: false, errors: [`could not read ${basename13(path2)}: ${err.message}`] };
114900
115035
  }
@@ -114945,7 +115080,7 @@ __export(layout_exports, {
114945
115080
  default: () => layout_default,
114946
115081
  examples: () => examples12
114947
115082
  });
114948
- import { existsSync as existsSync68, readFileSync as readFileSync46 } from "fs";
115083
+ import { existsSync as existsSync68, readFileSync as readFileSync45 } from "fs";
114949
115084
  import { dirname as dirname32, join as join71 } from "path";
114950
115085
  import { fileURLToPath as fileURLToPath12 } from "url";
114951
115086
  function buildMotionSampleTimes(duration) {
@@ -114981,7 +115116,7 @@ async function waitForFonts(page, timeoutMs) {
114981
115116
  if (!fonts?.ready) return Promise.resolve();
114982
115117
  return Promise.race([
114983
115118
  fonts.ready.then(() => void 0),
114984
- new Promise((resolve60) => setTimeout(resolve60, ms))
115119
+ new Promise((resolve61) => setTimeout(resolve61, ms))
114985
115120
  ]);
114986
115121
  }, timeoutMs).catch(() => {
114987
115122
  });
@@ -115133,7 +115268,7 @@ async function runLayoutAudit(projectDir, opts) {
115133
115268
  function loadBrowserScript(name) {
115134
115269
  const candidates = [join71(__dirname2, name), join71(__dirname2, "commands", name)];
115135
115270
  for (const candidate of candidates) {
115136
- if (existsSync68(candidate)) return readFileSync46(candidate, "utf-8");
115271
+ if (existsSync68(candidate)) return readFileSync45(candidate, "utf-8");
115137
115272
  }
115138
115273
  throw new Error(`Missing browser script ${name}`);
115139
115274
  }
@@ -115380,7 +115515,7 @@ function createInspectCommand(commandName) {
115380
115515
  console.log(`${ok ? c.success("\u25C7") : c.error("\u25C7")} ${parts.join(", ")}${suffix}`);
115381
115516
  process.exit(ok ? 0 : 1);
115382
115517
  } catch (err) {
115383
- const message = err instanceof Error ? err.message : String(err);
115518
+ const message = normalizeErrorMessage(err);
115384
115519
  if (args.json) {
115385
115520
  console.log(
115386
115521
  JSON.stringify(
@@ -115413,6 +115548,7 @@ var init_layout2 = __esm({
115413
115548
  init_dist();
115414
115549
  init_colors();
115415
115550
  init_project();
115551
+ init_errorMessage();
115416
115552
  init_staticProjectServer();
115417
115553
  init_updateCheck();
115418
115554
  init_layoutAudit();
@@ -115478,7 +115614,7 @@ __export(info_exports, {
115478
115614
  default: () => info_default,
115479
115615
  examples: () => examples14
115480
115616
  });
115481
- import { readFileSync as readFileSync47, readdirSync as readdirSync26, statSync as statSync20 } from "fs";
115617
+ import { readFileSync as readFileSync46, readdirSync as readdirSync26, statSync as statSync21 } from "fs";
115482
115618
  import { join as join73 } from "path";
115483
115619
  function totalSize(dir) {
115484
115620
  let total = 0;
@@ -115487,7 +115623,7 @@ function totalSize(dir) {
115487
115623
  if (entry.isDirectory()) {
115488
115624
  total += totalSize(path2);
115489
115625
  } else {
115490
- total += statSync20(path2).size;
115626
+ total += statSync21(path2).size;
115491
115627
  }
115492
115628
  }
115493
115629
  return total;
@@ -115515,7 +115651,7 @@ var init_info = __esm({
115515
115651
  },
115516
115652
  async run({ args }) {
115517
115653
  const project = resolveProject(args.dir);
115518
- const html = readFileSync47(project.indexPath, "utf-8");
115654
+ const html = readFileSync46(project.indexPath, "utf-8");
115519
115655
  ensureDOMParser();
115520
115656
  const parsed = parseHtml(html);
115521
115657
  const tracks = new Set(parsed.elements.map((el) => el.zIndex));
@@ -115573,7 +115709,7 @@ __export(compositions_exports, {
115573
115709
  examples: () => examples15,
115574
115710
  parseSubComposition: () => parseSubComposition
115575
115711
  });
115576
- import { existsSync as existsSync69, readFileSync as readFileSync48 } from "fs";
115712
+ import { existsSync as existsSync69, readFileSync as readFileSync47 } from "fs";
115577
115713
  import { resolve as resolve47, dirname as dirname33 } from "path";
115578
115714
  function countRenderableDescendants(root) {
115579
115715
  return Array.from(root.querySelectorAll("*")).filter(
@@ -115608,7 +115744,7 @@ function parseCompositions(html, baseDir) {
115608
115744
  if (compositionSrc) {
115609
115745
  const subPath = resolve47(baseDir, compositionSrc);
115610
115746
  if (existsSync69(subPath)) {
115611
- const subHtml = readFileSync48(subPath, "utf-8");
115747
+ const subHtml = readFileSync47(subPath, "utf-8");
115612
115748
  const subInfo = parseSubComposition(subHtml, id, width, height);
115613
115749
  compositions.push({ ...subInfo, source: compositionSrc });
115614
115750
  return;
@@ -115711,7 +115847,7 @@ var init_compositions = __esm({
115711
115847
  },
115712
115848
  async run({ args }) {
115713
115849
  const project = resolveProject(args.dir);
115714
- const html = readFileSync48(project.indexPath, "utf-8");
115850
+ const html = readFileSync47(project.indexPath, "utf-8");
115715
115851
  ensureDOMParser();
115716
115852
  const compositions = parseCompositions(html, dirname33(project.indexPath));
115717
115853
  if (compositions.length === 0) {
@@ -115749,7 +115885,7 @@ __export(benchmark_exports, {
115749
115885
  default: () => benchmark_default,
115750
115886
  examples: () => examples16
115751
115887
  });
115752
- import { existsSync as existsSync70, statSync as statSync21 } from "fs";
115888
+ import { existsSync as existsSync70, statSync as statSync23 } from "fs";
115753
115889
  import { resolve as resolve48, join as join74 } from "path";
115754
115890
  var examples16, FPS_30, FPS_60, DEFAULT_CONFIGS, benchmark_default;
115755
115891
  var init_benchmark = __esm({
@@ -115843,7 +115979,7 @@ var init_benchmark = __esm({
115843
115979
  const elapsedMs = Date.now() - startTime;
115844
115980
  let fileSize = null;
115845
115981
  if (existsSync70(outputPath)) {
115846
- const stat3 = statSync21(outputPath);
115982
+ const stat3 = statSync23(outputPath);
115847
115983
  fileSize = stat3.size;
115848
115984
  }
115849
115985
  runs.push({ elapsedMs, fileSize });
@@ -116578,12 +116714,12 @@ async function runPipeline(options, session, media, format, bgFormat, ffmpegPath
116578
116714
  const drains = [];
116579
116715
  if (!fgWroteFully) {
116580
116716
  drains.push(
116581
- new Promise((resolve60) => fg.proc.stdin.once("drain", () => resolve60()))
116717
+ new Promise((resolve61) => fg.proc.stdin.once("drain", () => resolve61()))
116582
116718
  );
116583
116719
  }
116584
116720
  if (!bgWroteFully && bg) {
116585
116721
  drains.push(
116586
- new Promise((resolve60) => bg.proc.stdin.once("drain", () => resolve60()))
116722
+ new Promise((resolve61) => bg.proc.stdin.once("drain", () => resolve61()))
116587
116723
  );
116588
116724
  }
116589
116725
  await Promise.all(drains);
@@ -116616,11 +116752,11 @@ ${decoder.getStderr().slice(-400)}`
116616
116752
  return processed;
116617
116753
  }
116618
116754
  function waitForExit(proc, label2, getStderr) {
116619
- return new Promise((resolve60, reject) => {
116755
+ return new Promise((resolve61, reject) => {
116620
116756
  proc.on("error", reject);
116621
116757
  proc.on("exit", (code, signal) => {
116622
116758
  if (code === 0 && !signal) {
116623
- resolve60();
116759
+ resolve61();
116624
116760
  return;
116625
116761
  }
116626
116762
  const cause = signal ? `killed by ${signal}` : `exited with code ${code}`;
@@ -117395,7 +117531,7 @@ __export(tts_exports, {
117395
117531
  default: () => tts_default,
117396
117532
  examples: () => examples20
117397
117533
  });
117398
- import { existsSync as existsSync77, readFileSync as readFileSync49 } from "fs";
117534
+ import { existsSync as existsSync77, readFileSync as readFileSync48 } from "fs";
117399
117535
  import { resolve as resolve51, extname as extname13 } from "path";
117400
117536
  function listVoices(json) {
117401
117537
  const rows = BUNDLED_VOICES.map((v2) => ({ ...v2, defaultLang: inferLangFromVoiceId(v2.id) }));
@@ -117506,7 +117642,7 @@ var init_tts = __esm({
117506
117642
  let text;
117507
117643
  const maybeFile = resolve51(args.input);
117508
117644
  if (existsSync77(maybeFile) && extname13(maybeFile).toLowerCase() === ".txt") {
117509
- text = readFileSync49(maybeFile, "utf-8").trim();
117645
+ text = readFileSync48(maybeFile, "utf-8").trim();
117510
117646
  if (!text) {
117511
117647
  console.error(c.error("File is empty."));
117512
117648
  process.exit(1);
@@ -117598,7 +117734,7 @@ __export(docs_exports, {
117598
117734
  default: () => docs_default,
117599
117735
  examples: () => examples21
117600
117736
  });
117601
- import { readFileSync as readFileSync50, existsSync as existsSync78 } from "fs";
117737
+ import { readFileSync as readFileSync49, existsSync as existsSync78 } from "fs";
117602
117738
  import { resolve as resolve52, dirname as dirname36, join as join79 } from "path";
117603
117739
  import { fileURLToPath as fileURLToPath13 } from "url";
117604
117740
  function docsDir() {
@@ -117708,7 +117844,7 @@ var init_docs = __esm({
117708
117844
  console.error(c.error(`Doc file not found: ${filePath}`));
117709
117845
  process.exit(1);
117710
117846
  }
117711
- const content = readFileSync50(filePath, "utf-8");
117847
+ const content = readFileSync49(filePath, "utf-8");
117712
117848
  console.log();
117713
117849
  renderMarkdown(content);
117714
117850
  }
@@ -118124,28 +118260,161 @@ var init_upgrade = __esm({
118124
118260
  }
118125
118261
  });
118126
118262
 
118263
+ // src/utils/feedbackIssue.ts
118264
+ function normalizeRepoUrl(repoUrl) {
118265
+ const trimmed = repoUrl.trim().replace(/\/$/, "").replace(/\.git$/, "");
118266
+ return trimmed || HYPERFRAMES_REPO_URL;
118267
+ }
118268
+ function truncate(value, max) {
118269
+ return value.length > max ? `${value.slice(0, max - 1)}\u2026` : value;
118270
+ }
118271
+ function buildIssueTitle(rating, comment) {
118272
+ const firstLine = comment?.split("\n")[0]?.trim();
118273
+ if (!firstLine) return `Render feedback (rating ${rating}/5)`;
118274
+ return `[feedback] ${truncate(firstLine, TITLE_MAX)}`;
118275
+ }
118276
+ function buildIssueBody(input2) {
118277
+ const comment = input2.comment?.trim();
118278
+ const repro = input2.repoPublicUrl ? `Published minimal repro: ${input2.repoPublicUrl}` : "_Publishing the repro failed, no public link available._";
118279
+ return [
118280
+ `**Rating:** ${input2.rating}/5`,
118281
+ "",
118282
+ "## Comment",
118283
+ comment ? truncate(comment, COMMENT_MAX) : "_No comment provided._",
118284
+ "",
118285
+ "## Minimal repro",
118286
+ repro,
118287
+ "",
118288
+ "## Environment",
118289
+ "```",
118290
+ input2.environment || "(unavailable)",
118291
+ `cli=${input2.cliVersion}`,
118292
+ "```",
118293
+ "",
118294
+ "---",
118295
+ "_Filed via `hyperframes feedback --file-issue`._"
118296
+ ].join("\n");
118297
+ }
118298
+ function buildIssueUrl(input2) {
118299
+ const repo = normalizeRepoUrl(input2.repoUrl);
118300
+ const title = encodeURIComponent(buildIssueTitle(input2.rating, input2.comment));
118301
+ const body = encodeURIComponent(buildIssueBody(input2));
118302
+ return `${repo}/issues/new?title=${title}&body=${body}&labels=bug`;
118303
+ }
118304
+ var HYPERFRAMES_REPO_URL, TITLE_MAX, COMMENT_MAX;
118305
+ var init_feedbackIssue = __esm({
118306
+ "src/utils/feedbackIssue.ts"() {
118307
+ "use strict";
118308
+ HYPERFRAMES_REPO_URL = "https://github.com/heygen-com/hyperframes";
118309
+ TITLE_MAX = 80;
118310
+ COMMENT_MAX = 4e3;
118311
+ }
118312
+ });
118313
+
118127
118314
  // src/commands/feedback.ts
118128
118315
  var feedback_exports = {};
118129
118316
  __export(feedback_exports, {
118130
118317
  default: () => feedback_default,
118131
118318
  examples: () => examples24
118132
118319
  });
118320
+ import { resolve as resolve53 } from "path";
118321
+ import open from "open";
118133
118322
  function parseRating(raw) {
118134
118323
  const n2 = parseInt(raw, 10);
118135
118324
  return n2 >= 1 && n2 <= 5 && Number.isFinite(n2) ? n2 : null;
118136
118325
  }
118326
+ function normalizeComment(raw) {
118327
+ return raw || void 0;
118328
+ }
118329
+ function printIssueConsent(dir) {
118330
+ console.log();
118331
+ console.log(
118332
+ ` ${c.bold("Filing an issue will publish this project publicly and open a GitHub issue draft.")}`
118333
+ );
118334
+ console.log(` ${c.dim(`Project at ${dir} will be uploaded to a public URL.`)}`);
118335
+ console.log(
118336
+ ` ${c.dim("The issue draft will contain that public link plus your feedback; you review and submit it.")}`
118337
+ );
118338
+ console.log();
118339
+ }
118340
+ async function promptConfirm() {
118341
+ const approved = await ue({ message: "Publish this project and draft the issue?" });
118342
+ return !q(approved) && approved === true;
118343
+ }
118344
+ async function confirmFileIssue(dir, yes) {
118345
+ printIssueConsent(dir);
118346
+ if (yes) return true;
118347
+ if (!process.stdout.isTTY) {
118348
+ console.log(` ${c.dim("Re-run with --yes to publish the repro and file the issue.")}
118349
+ `);
118350
+ return false;
118351
+ }
118352
+ if (await promptConfirm()) return true;
118353
+ console.log(`
118354
+ ${c.dim("Aborted. Feedback was still sent.")}
118355
+ `);
118356
+ return false;
118357
+ }
118358
+ async function publishRepro(dir) {
118359
+ const spinner = ft();
118360
+ spinner.start("Publishing minimal repro...");
118361
+ try {
118362
+ const published = await publishProjectArchive(dir);
118363
+ spinner.stop(c.success("Repro published"));
118364
+ return published.url;
118365
+ } catch (err) {
118366
+ spinner.stop(c.error("Publish failed"));
118367
+ console.error(` ${err.message}`);
118368
+ console.log(` ${c.dim("Filing the issue without a repro link.")}`);
118369
+ return void 0;
118370
+ }
118371
+ }
118372
+ async function openAndPrintIssue(url) {
118373
+ if (process.stdout.isTTY) {
118374
+ try {
118375
+ await open(url);
118376
+ } catch {
118377
+ }
118378
+ }
118379
+ console.log();
118380
+ console.log(` ${c.dim("Review and submit the pre-filled issue (it is not auto-submitted):")}`);
118381
+ console.log(` ${c.accent(url)}`);
118382
+ console.log();
118383
+ }
118384
+ async function fileGithubIssue(opts) {
118385
+ const dir = resolve53(opts.rawDir ?? ".");
118386
+ if (!await confirmFileIssue(dir, opts.yes)) return;
118387
+ const repoPublicUrl = await publishRepro(dir);
118388
+ const url = buildIssueUrl({
118389
+ repoUrl: HYPERFRAMES_REPO_URL,
118390
+ rating: opts.rating,
118391
+ comment: opts.comment,
118392
+ repoPublicUrl,
118393
+ environment: opts.doctorSummary,
118394
+ cliVersion: VERSION
118395
+ });
118396
+ await openAndPrintIssue(url);
118397
+ }
118137
118398
  var examples24, feedback_default;
118138
118399
  var init_feedback2 = __esm({
118139
118400
  "src/commands/feedback.ts"() {
118140
118401
  "use strict";
118141
118402
  init_dist();
118403
+ init_dist8();
118142
118404
  init_events();
118143
118405
  init_client();
118144
118406
  init_feedback();
118407
+ init_publishProject();
118408
+ init_feedbackIssue();
118409
+ init_version();
118145
118410
  init_colors();
118146
118411
  examples24 = [
118147
118412
  ["Submit render feedback", 'hyperframes feedback --rating 4 --comment "fast but font missing"'],
118148
- ["Quick rating only", "hyperframes feedback --rating 5"]
118413
+ ["Quick rating only", "hyperframes feedback --rating 5"],
118414
+ [
118415
+ "Also file a GitHub issue with a published repro",
118416
+ 'hyperframes feedback --rating 2 --comment "GSAP timeline froze" --file-issue'
118417
+ ]
118149
118418
  ];
118150
118419
  feedback_default = defineCommand({
118151
118420
  meta: { name: "feedback", description: "Submit anonymous feedback about your experience" },
@@ -118158,6 +118427,21 @@ var init_feedback2 = __esm({
118158
118427
  comment: {
118159
118428
  type: "string",
118160
118429
  description: "Optional details about your experience"
118430
+ },
118431
+ "file-issue": {
118432
+ type: "boolean",
118433
+ description: "Also open a pre-filled GitHub issue with a published minimal repro",
118434
+ default: false
118435
+ },
118436
+ dir: {
118437
+ type: "string",
118438
+ description: "Project directory to publish as the repro (default: current directory)"
118439
+ },
118440
+ yes: {
118441
+ type: "boolean",
118442
+ alias: "y",
118443
+ description: "Skip the publish + file-issue consent prompt",
118444
+ default: false
118161
118445
  }
118162
118446
  },
118163
118447
  async run({ args }) {
@@ -118170,15 +118454,20 @@ var init_feedback2 = __esm({
118170
118454
  console.log(c.dim("Telemetry is disabled. Feedback not sent."));
118171
118455
  return;
118172
118456
  }
118457
+ const comment = normalizeComment(args.comment);
118173
118458
  const doctorSummary = await getDoctorSummary();
118174
- trackRenderFeedback({
118175
- rating,
118176
- renderDurationMs: 0,
118177
- comment: args.comment || void 0,
118178
- doctorSummary
118179
- });
118459
+ trackRenderFeedback({ rating, comment, doctorSummary });
118180
118460
  await flush();
118181
118461
  console.log(c.dim("Thanks for the feedback!"));
118462
+ if (args["file-issue"] === true) {
118463
+ await fileGithubIssue({
118464
+ rating,
118465
+ comment,
118466
+ rawDir: args.dir,
118467
+ yes: args.yes === true,
118468
+ doctorSummary
118469
+ });
118470
+ }
118182
118471
  }
118183
118472
  });
118184
118473
  }
@@ -118375,7 +118664,7 @@ __export(validate_exports, {
118375
118664
  default: () => validate_default,
118376
118665
  shouldIgnoreRequestFailure: () => shouldIgnoreRequestFailure
118377
118666
  });
118378
- import { existsSync as existsSync79, readFileSync as readFileSync51 } from "fs";
118667
+ import { existsSync as existsSync79, readFileSync as readFileSync50 } from "fs";
118379
118668
  import { join as join80, dirname as dirname37 } from "path";
118380
118669
  import { fileURLToPath as fileURLToPath14 } from "url";
118381
118670
  function shouldIgnoreRequestFailure(url, errorText, resourceType) {
@@ -118474,7 +118763,7 @@ function loadContrastAuditScript() {
118474
118763
  join80(__dirname3, "commands", "contrast-audit.browser.js")
118475
118764
  ];
118476
118765
  for (const candidate of candidates) {
118477
- if (existsSync79(candidate)) return readFileSync51(candidate, "utf-8");
118766
+ if (existsSync79(candidate)) return readFileSync50(candidate, "utf-8");
118478
118767
  }
118479
118768
  throw new Error("Missing contrast audit browser script");
118480
118769
  }
@@ -118512,7 +118801,7 @@ async function validateInBrowser(projectDir, opts) {
118512
118801
  }
118513
118802
  });
118514
118803
  page.on("pageerror", (err) => {
118515
- const text = err instanceof Error ? err.message : String(err);
118804
+ const text = normalizeErrorMessage(err);
118516
118805
  if (text.includes("Unexpected token '<'") || text.includes("Unexpected token '&lt;'")) return;
118517
118806
  errors.push({ level: "error", text });
118518
118807
  });
@@ -118623,6 +118912,7 @@ var init_validate = __esm({
118623
118912
  "use strict";
118624
118913
  init_dist();
118625
118914
  init_project();
118915
+ init_errorMessage();
118626
118916
  init_compositionViewport();
118627
118917
  init_colors();
118628
118918
  init_updateCheck();
@@ -118669,7 +118959,7 @@ Examples:
118669
118959
  const exitCode = printValidationResult(result, asJson);
118670
118960
  process.exit(exitCode);
118671
118961
  } catch (err) {
118672
- const message = err instanceof Error ? err.message : String(err);
118962
+ const message = normalizeErrorMessage(err);
118673
118963
  emitFailureReport(message, asJson);
118674
118964
  process.exit(1);
118675
118965
  }
@@ -118688,7 +118978,7 @@ __export(contactSheet_exports, {
118688
118978
  createSvgContactSheet: () => createSvgContactSheet
118689
118979
  });
118690
118980
  import sharp from "sharp";
118691
- import { readdirSync as readdirSync28, readFileSync as readFileSync53, writeFileSync as writeFileSync27, unlinkSync as unlinkSync6, existsSync as existsSync80 } from "fs";
118981
+ import { readdirSync as readdirSync28, readFileSync as readFileSync51, writeFileSync as writeFileSync27, unlinkSync as unlinkSync6, existsSync as existsSync80 } from "fs";
118692
118982
  import { join as join81, extname as extname14, basename as basename15, dirname as dirname38 } from "path";
118693
118983
  async function createContactSheet(imagePaths, outputPath, opts = {}) {
118694
118984
  const {
@@ -118839,7 +119129,7 @@ async function createSvgContactSheet(svgsDir, outputPath, assetsRootDir) {
118839
119129
  const svgPath = svgPaths[i2];
118840
119130
  const tmpPath = join81(tmpDir, `.thumb-${i2}.png`);
118841
119131
  try {
118842
- const svgBuf = readFileSync53(svgPath);
119132
+ const svgBuf = readFileSync51(svgPath);
118843
119133
  const thumb = await sharp(svgBuf).resize(thumbSize, thumbSize, {
118844
119134
  fit: "contain",
118845
119135
  background: { r: 245, g: 245, b: 245, alpha: 1 }
@@ -119146,8 +119436,8 @@ var require_p_retry = __commonJS({
119146
119436
  error.retriesLeft = retriesLeft;
119147
119437
  return error;
119148
119438
  };
119149
- var isNetworkError = (errorMessage3) => networkErrorMsgs.includes(errorMessage3);
119150
- var pRetry2 = (input2, options) => new Promise((resolve60, reject) => {
119439
+ var isNetworkError = (errorMessage) => networkErrorMsgs.includes(errorMessage);
119440
+ var pRetry2 = (input2, options) => new Promise((resolve61, reject) => {
119151
119441
  options = {
119152
119442
  onFailedAttempt: () => {
119153
119443
  },
@@ -119157,7 +119447,7 @@ var require_p_retry = __commonJS({
119157
119447
  const operation = retry.operation(options);
119158
119448
  operation.attempt(async (attemptNumber) => {
119159
119449
  try {
119160
- resolve60(await input2(attemptNumber));
119450
+ resolve61(await input2(attemptNumber));
119161
119451
  } catch (error) {
119162
119452
  if (!(error instanceof Error)) {
119163
119453
  reject(new TypeError(`Non-error was thrown: "${error}". You should only throw errors.`));
@@ -119693,8 +119983,8 @@ var require_retry3 = __commonJS({
119693
119983
  }
119694
119984
  const delay = getNextRetryDelay(config);
119695
119985
  err.config.retryConfig.currentRetryAttempt += 1;
119696
- const backoff = config.retryBackoff ? config.retryBackoff(err, delay) : new Promise((resolve60) => {
119697
- setTimeout(resolve60, delay);
119986
+ const backoff = config.retryBackoff ? config.retryBackoff(err, delay) : new Promise((resolve61) => {
119987
+ setTimeout(resolve61, delay);
119698
119988
  });
119699
119989
  if (config.onRetryAttempt) {
119700
119990
  await config.onRetryAttempt(err);
@@ -119822,8 +120112,8 @@ var require_helpers = __commonJS({
119822
120112
  function req(url, opts = {}) {
119823
120113
  const href = typeof url === "string" ? url : url.href;
119824
120114
  const req2 = (href.startsWith("https:") ? https2 : http4).request(url, opts);
119825
- const promise = new Promise((resolve60, reject) => {
119826
- req2.once("response", resolve60).once("error", reject).end();
120115
+ const promise = new Promise((resolve61, reject) => {
120116
+ req2.once("response", resolve61).once("error", reject).end();
119827
120117
  });
119828
120118
  req2.then = promise.then.bind(promise);
119829
120119
  return req2;
@@ -120000,7 +120290,7 @@ var require_parse_proxy_response = __commonJS({
120000
120290
  var debug_1 = __importDefault2(__require("debug"));
120001
120291
  var debug = (0, debug_1.default)("https-proxy-agent:parse-proxy-response");
120002
120292
  function parseProxyResponse(socket) {
120003
- return new Promise((resolve60, reject) => {
120293
+ return new Promise((resolve61, reject) => {
120004
120294
  let buffersLength = 0;
120005
120295
  const buffers = [];
120006
120296
  function read() {
@@ -120066,7 +120356,7 @@ var require_parse_proxy_response = __commonJS({
120066
120356
  }
120067
120357
  debug("got proxy server response: %o %o", firstLine, headers);
120068
120358
  cleanup();
120069
- resolve60({
120359
+ resolve61({
120070
120360
  connect: {
120071
120361
  statusCode,
120072
120362
  statusText,
@@ -120310,7 +120600,7 @@ var require_ponyfill_es2018 = __commonJS({
120310
120600
  return new originalPromise(executor);
120311
120601
  }
120312
120602
  function promiseResolvedWith(value) {
120313
- return newPromise((resolve60) => resolve60(value));
120603
+ return newPromise((resolve61) => resolve61(value));
120314
120604
  }
120315
120605
  function promiseRejectedWith(reason) {
120316
120606
  return originalPromiseReject(reason);
@@ -120480,8 +120770,8 @@ var require_ponyfill_es2018 = __commonJS({
120480
120770
  return new TypeError("Cannot " + name + " a stream using a released reader");
120481
120771
  }
120482
120772
  function defaultReaderClosedPromiseInitialize(reader) {
120483
- reader._closedPromise = newPromise((resolve60, reject) => {
120484
- reader._closedPromise_resolve = resolve60;
120773
+ reader._closedPromise = newPromise((resolve61, reject) => {
120774
+ reader._closedPromise_resolve = resolve61;
120485
120775
  reader._closedPromise_reject = reject;
120486
120776
  });
120487
120777
  }
@@ -120655,8 +120945,8 @@ var require_ponyfill_es2018 = __commonJS({
120655
120945
  }
120656
120946
  let resolvePromise;
120657
120947
  let rejectPromise;
120658
- const promise = newPromise((resolve60, reject) => {
120659
- resolvePromise = resolve60;
120948
+ const promise = newPromise((resolve61, reject) => {
120949
+ resolvePromise = resolve61;
120660
120950
  rejectPromise = reject;
120661
120951
  });
120662
120952
  const readRequest = {
@@ -120761,8 +121051,8 @@ var require_ponyfill_es2018 = __commonJS({
120761
121051
  const reader = this._reader;
120762
121052
  let resolvePromise;
120763
121053
  let rejectPromise;
120764
- const promise = newPromise((resolve60, reject) => {
120765
- resolvePromise = resolve60;
121054
+ const promise = newPromise((resolve61, reject) => {
121055
+ resolvePromise = resolve61;
120766
121056
  rejectPromise = reject;
120767
121057
  });
120768
121058
  const readRequest = {
@@ -121781,8 +122071,8 @@ var require_ponyfill_es2018 = __commonJS({
121781
122071
  }
121782
122072
  let resolvePromise;
121783
122073
  let rejectPromise;
121784
- const promise = newPromise((resolve60, reject) => {
121785
- resolvePromise = resolve60;
122074
+ const promise = newPromise((resolve61, reject) => {
122075
+ resolvePromise = resolve61;
121786
122076
  rejectPromise = reject;
121787
122077
  });
121788
122078
  const readIntoRequest = {
@@ -122094,10 +122384,10 @@ var require_ponyfill_es2018 = __commonJS({
122094
122384
  wasAlreadyErroring = true;
122095
122385
  reason = void 0;
122096
122386
  }
122097
- const promise = newPromise((resolve60, reject) => {
122387
+ const promise = newPromise((resolve61, reject) => {
122098
122388
  stream._pendingAbortRequest = {
122099
122389
  _promise: void 0,
122100
- _resolve: resolve60,
122390
+ _resolve: resolve61,
122101
122391
  _reject: reject,
122102
122392
  _reason: reason,
122103
122393
  _wasAlreadyErroring: wasAlreadyErroring
@@ -122114,9 +122404,9 @@ var require_ponyfill_es2018 = __commonJS({
122114
122404
  if (state === "closed" || state === "errored") {
122115
122405
  return promiseRejectedWith(new TypeError(`The stream (in ${state} state) is not in the writable state and cannot be closed`));
122116
122406
  }
122117
- const promise = newPromise((resolve60, reject) => {
122407
+ const promise = newPromise((resolve61, reject) => {
122118
122408
  const closeRequest = {
122119
- _resolve: resolve60,
122409
+ _resolve: resolve61,
122120
122410
  _reject: reject
122121
122411
  };
122122
122412
  stream._closeRequest = closeRequest;
@@ -122129,9 +122419,9 @@ var require_ponyfill_es2018 = __commonJS({
122129
122419
  return promise;
122130
122420
  }
122131
122421
  function WritableStreamAddWriteRequest(stream) {
122132
- const promise = newPromise((resolve60, reject) => {
122422
+ const promise = newPromise((resolve61, reject) => {
122133
122423
  const writeRequest = {
122134
- _resolve: resolve60,
122424
+ _resolve: resolve61,
122135
122425
  _reject: reject
122136
122426
  };
122137
122427
  stream._writeRequests.push(writeRequest);
@@ -122747,8 +123037,8 @@ var require_ponyfill_es2018 = __commonJS({
122747
123037
  return new TypeError("Cannot " + name + " a stream using a released writer");
122748
123038
  }
122749
123039
  function defaultWriterClosedPromiseInitialize(writer) {
122750
- writer._closedPromise = newPromise((resolve60, reject) => {
122751
- writer._closedPromise_resolve = resolve60;
123040
+ writer._closedPromise = newPromise((resolve61, reject) => {
123041
+ writer._closedPromise_resolve = resolve61;
122752
123042
  writer._closedPromise_reject = reject;
122753
123043
  writer._closedPromiseState = "pending";
122754
123044
  });
@@ -122784,8 +123074,8 @@ var require_ponyfill_es2018 = __commonJS({
122784
123074
  writer._closedPromiseState = "resolved";
122785
123075
  }
122786
123076
  function defaultWriterReadyPromiseInitialize(writer) {
122787
- writer._readyPromise = newPromise((resolve60, reject) => {
122788
- writer._readyPromise_resolve = resolve60;
123077
+ writer._readyPromise = newPromise((resolve61, reject) => {
123078
+ writer._readyPromise_resolve = resolve61;
122789
123079
  writer._readyPromise_reject = reject;
122790
123080
  });
122791
123081
  writer._readyPromiseState = "pending";
@@ -122872,7 +123162,7 @@ var require_ponyfill_es2018 = __commonJS({
122872
123162
  source._disturbed = true;
122873
123163
  let shuttingDown = false;
122874
123164
  let currentWrite = promiseResolvedWith(void 0);
122875
- return newPromise((resolve60, reject) => {
123165
+ return newPromise((resolve61, reject) => {
122876
123166
  let abortAlgorithm;
122877
123167
  if (signal !== void 0) {
122878
123168
  abortAlgorithm = () => {
@@ -123017,7 +123307,7 @@ var require_ponyfill_es2018 = __commonJS({
123017
123307
  if (isError) {
123018
123308
  reject(error);
123019
123309
  } else {
123020
- resolve60(void 0);
123310
+ resolve61(void 0);
123021
123311
  }
123022
123312
  return null;
123023
123313
  }
@@ -123298,8 +123588,8 @@ var require_ponyfill_es2018 = __commonJS({
123298
123588
  let branch1;
123299
123589
  let branch2;
123300
123590
  let resolveCancelPromise;
123301
- const cancelPromise = newPromise((resolve60) => {
123302
- resolveCancelPromise = resolve60;
123591
+ const cancelPromise = newPromise((resolve61) => {
123592
+ resolveCancelPromise = resolve61;
123303
123593
  });
123304
123594
  function pullAlgorithm() {
123305
123595
  if (reading) {
@@ -123390,8 +123680,8 @@ var require_ponyfill_es2018 = __commonJS({
123390
123680
  let branch1;
123391
123681
  let branch2;
123392
123682
  let resolveCancelPromise;
123393
- const cancelPromise = newPromise((resolve60) => {
123394
- resolveCancelPromise = resolve60;
123683
+ const cancelPromise = newPromise((resolve61) => {
123684
+ resolveCancelPromise = resolve61;
123395
123685
  });
123396
123686
  function forwardReaderError(thisReader) {
123397
123687
  uponRejection(thisReader._closedPromise, (r2) => {
@@ -124171,8 +124461,8 @@ var require_ponyfill_es2018 = __commonJS({
124171
124461
  const writableHighWaterMark = ExtractHighWaterMark(writableStrategy, 1);
124172
124462
  const writableSizeAlgorithm = ExtractSizeAlgorithm(writableStrategy);
124173
124463
  let startPromise_resolve;
124174
- const startPromise = newPromise((resolve60) => {
124175
- startPromise_resolve = resolve60;
124464
+ const startPromise = newPromise((resolve61) => {
124465
+ startPromise_resolve = resolve61;
124176
124466
  });
124177
124467
  InitializeTransformStream(this, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm);
124178
124468
  SetUpTransformStreamDefaultControllerFromTransformer(this, transformer);
@@ -124265,8 +124555,8 @@ var require_ponyfill_es2018 = __commonJS({
124265
124555
  if (stream._backpressureChangePromise !== void 0) {
124266
124556
  stream._backpressureChangePromise_resolve();
124267
124557
  }
124268
- stream._backpressureChangePromise = newPromise((resolve60) => {
124269
- stream._backpressureChangePromise_resolve = resolve60;
124558
+ stream._backpressureChangePromise = newPromise((resolve61) => {
124559
+ stream._backpressureChangePromise_resolve = resolve61;
124270
124560
  });
124271
124561
  stream._backpressure = backpressure;
124272
124562
  }
@@ -124434,8 +124724,8 @@ var require_ponyfill_es2018 = __commonJS({
124434
124724
  return controller._finishPromise;
124435
124725
  }
124436
124726
  const readable = stream._readable;
124437
- controller._finishPromise = newPromise((resolve60, reject) => {
124438
- controller._finishPromise_resolve = resolve60;
124727
+ controller._finishPromise = newPromise((resolve61, reject) => {
124728
+ controller._finishPromise_resolve = resolve61;
124439
124729
  controller._finishPromise_reject = reject;
124440
124730
  });
124441
124731
  const cancelPromise = controller._cancelAlgorithm(reason);
@@ -124461,8 +124751,8 @@ var require_ponyfill_es2018 = __commonJS({
124461
124751
  return controller._finishPromise;
124462
124752
  }
124463
124753
  const readable = stream._readable;
124464
- controller._finishPromise = newPromise((resolve60, reject) => {
124465
- controller._finishPromise_resolve = resolve60;
124754
+ controller._finishPromise = newPromise((resolve61, reject) => {
124755
+ controller._finishPromise_resolve = resolve61;
124466
124756
  controller._finishPromise_reject = reject;
124467
124757
  });
124468
124758
  const flushPromise = controller._flushAlgorithm();
@@ -124492,8 +124782,8 @@ var require_ponyfill_es2018 = __commonJS({
124492
124782
  return controller._finishPromise;
124493
124783
  }
124494
124784
  const writable = stream._writable;
124495
- controller._finishPromise = newPromise((resolve60, reject) => {
124496
- controller._finishPromise_resolve = resolve60;
124785
+ controller._finishPromise = newPromise((resolve61, reject) => {
124786
+ controller._finishPromise_resolve = resolve61;
124497
124787
  controller._finishPromise_reject = reject;
124498
124788
  });
124499
124789
  const cancelPromise = controller._cancelAlgorithm(reason);
@@ -125039,7 +125329,7 @@ var require_node_domexception = __commonJS({
125039
125329
  });
125040
125330
 
125041
125331
  // ../../node_modules/.bun/fetch-blob@3.2.0/node_modules/fetch-blob/from.js
125042
- import { statSync as statSync23, createReadStream as createReadStream3, promises as fs2 } from "fs";
125332
+ import { statSync as statSync24, createReadStream as createReadStream4, promises as fs2 } from "fs";
125043
125333
  import { basename as basename16 } from "path";
125044
125334
  var import_node_domexception, stat, blobFromSync, blobFrom, fileFrom, fileFromSync, fromBlob, fromFile, BlobDataItem;
125045
125335
  var init_from = __esm({
@@ -125049,10 +125339,10 @@ var init_from = __esm({
125049
125339
  init_file();
125050
125340
  init_fetch_blob();
125051
125341
  ({ stat } = fs2);
125052
- blobFromSync = (path2, type) => fromBlob(statSync23(path2), path2, type);
125342
+ blobFromSync = (path2, type) => fromBlob(statSync24(path2), path2, type);
125053
125343
  blobFrom = (path2, type) => stat(path2).then((stat3) => fromBlob(stat3, path2, type));
125054
125344
  fileFrom = (path2, type) => stat(path2).then((stat3) => fromFile(stat3, path2, type));
125055
- fileFromSync = (path2, type) => fromFile(statSync23(path2), path2, type);
125345
+ fileFromSync = (path2, type) => fromFile(statSync24(path2), path2, type);
125056
125346
  fromBlob = (stat3, path2, type = "") => new fetch_blob_default([new BlobDataItem({
125057
125347
  path: path2,
125058
125348
  size: stat3.size,
@@ -125091,7 +125381,7 @@ var init_from = __esm({
125091
125381
  if (mtimeMs > this.lastModified) {
125092
125382
  throw new import_node_domexception.default("The requested file could not be read, typically due to permission problems that have occurred after a reference to a file was acquired.", "NotReadableError");
125093
125383
  }
125094
- yield* createReadStream3(this.#path, {
125384
+ yield* createReadStream4(this.#path, {
125095
125385
  start: this.#start,
125096
125386
  end: this.#start + this.size - 1
125097
125387
  });
@@ -126462,7 +126752,7 @@ import zlib from "zlib";
126462
126752
  import Stream2, { PassThrough as PassThrough2, pipeline as pump } from "stream";
126463
126753
  import { Buffer as Buffer4 } from "buffer";
126464
126754
  async function fetch3(url, options_) {
126465
- return new Promise((resolve60, reject) => {
126755
+ return new Promise((resolve61, reject) => {
126466
126756
  const request = new Request2(url, options_);
126467
126757
  const { parsedURL, options } = getNodeRequestOptions(request);
126468
126758
  if (!supportedSchemas.has(parsedURL.protocol)) {
@@ -126471,7 +126761,7 @@ async function fetch3(url, options_) {
126471
126761
  if (parsedURL.protocol === "data:") {
126472
126762
  const data2 = dist_default3(request.url);
126473
126763
  const response2 = new Response2(data2, { headers: { "Content-Type": data2.typeFull } });
126474
- resolve60(response2);
126764
+ resolve61(response2);
126475
126765
  return;
126476
126766
  }
126477
126767
  const send = (parsedURL.protocol === "https:" ? https : http3).request;
@@ -126593,7 +126883,7 @@ async function fetch3(url, options_) {
126593
126883
  if (responseReferrerPolicy) {
126594
126884
  requestOptions.referrerPolicy = responseReferrerPolicy;
126595
126885
  }
126596
- resolve60(fetch3(new Request2(locationURL, requestOptions)));
126886
+ resolve61(fetch3(new Request2(locationURL, requestOptions)));
126597
126887
  finalize();
126598
126888
  return;
126599
126889
  }
@@ -126626,7 +126916,7 @@ async function fetch3(url, options_) {
126626
126916
  const codings = headers.get("Content-Encoding");
126627
126917
  if (!request.compress || request.method === "HEAD" || codings === null || response_.statusCode === 204 || response_.statusCode === 304) {
126628
126918
  response = new Response2(body, responseOptions);
126629
- resolve60(response);
126919
+ resolve61(response);
126630
126920
  return;
126631
126921
  }
126632
126922
  const zlibOptions = {
@@ -126640,7 +126930,7 @@ async function fetch3(url, options_) {
126640
126930
  }
126641
126931
  });
126642
126932
  response = new Response2(body, responseOptions);
126643
- resolve60(response);
126933
+ resolve61(response);
126644
126934
  return;
126645
126935
  }
126646
126936
  if (codings === "deflate" || codings === "x-deflate") {
@@ -126664,12 +126954,12 @@ async function fetch3(url, options_) {
126664
126954
  });
126665
126955
  }
126666
126956
  response = new Response2(body, responseOptions);
126667
- resolve60(response);
126957
+ resolve61(response);
126668
126958
  });
126669
126959
  raw.once("end", () => {
126670
126960
  if (!response) {
126671
126961
  response = new Response2(body, responseOptions);
126672
- resolve60(response);
126962
+ resolve61(response);
126673
126963
  }
126674
126964
  });
126675
126965
  return;
@@ -126681,11 +126971,11 @@ async function fetch3(url, options_) {
126681
126971
  }
126682
126972
  });
126683
126973
  response = new Response2(body, responseOptions);
126684
- resolve60(response);
126974
+ resolve61(response);
126685
126975
  return;
126686
126976
  }
126687
126977
  response = new Response2(body, responseOptions);
126688
- resolve60(response);
126978
+ resolve61(response);
126689
126979
  });
126690
126980
  writeToStream(request_, request).catch(reject);
126691
126981
  });
@@ -132767,7 +133057,7 @@ var require_jwtaccess = __commonJS({
132767
133057
  }
132768
133058
  }
132769
133059
  fromStreamAsync(inputStream) {
132770
- return new Promise((resolve60, reject) => {
133060
+ return new Promise((resolve61, reject) => {
132771
133061
  if (!inputStream) {
132772
133062
  reject(new Error("Must pass in a stream containing the service account auth settings."));
132773
133063
  }
@@ -132776,7 +133066,7 @@ var require_jwtaccess = __commonJS({
132776
133066
  try {
132777
133067
  const data2 = JSON.parse(s2);
132778
133068
  this.fromJSON(data2);
132779
- resolve60();
133069
+ resolve61();
132780
133070
  } catch (err) {
132781
133071
  reject(err);
132782
133072
  }
@@ -133015,7 +133305,7 @@ var require_jwtclient = __commonJS({
133015
133305
  }
133016
133306
  }
133017
133307
  fromStreamAsync(inputStream) {
133018
- return new Promise((resolve60, reject) => {
133308
+ return new Promise((resolve61, reject) => {
133019
133309
  if (!inputStream) {
133020
133310
  throw new Error("Must pass in a stream containing the service account auth settings.");
133021
133311
  }
@@ -133024,7 +133314,7 @@ var require_jwtclient = __commonJS({
133024
133314
  try {
133025
133315
  const data2 = JSON.parse(s2);
133026
133316
  this.fromJSON(data2);
133027
- resolve60();
133317
+ resolve61();
133028
133318
  } catch (e3) {
133029
133319
  reject(e3);
133030
133320
  }
@@ -133157,7 +133447,7 @@ var require_refreshclient = __commonJS({
133157
133447
  }
133158
133448
  }
133159
133449
  async fromStreamAsync(inputStream) {
133160
- return new Promise((resolve60, reject) => {
133450
+ return new Promise((resolve61, reject) => {
133161
133451
  if (!inputStream) {
133162
133452
  return reject(new Error("Must pass in a stream containing the user refresh token."));
133163
133453
  }
@@ -133166,7 +133456,7 @@ var require_refreshclient = __commonJS({
133166
133456
  try {
133167
133457
  const data2 = JSON.parse(s2);
133168
133458
  this.fromJSON(data2);
133169
- return resolve60();
133459
+ return resolve61();
133170
133460
  } catch (err) {
133171
133461
  return reject(err);
133172
133462
  }
@@ -134999,7 +135289,7 @@ var require_pluggable_auth_handler = __commonJS({
134999
135289
  * @return A promise that resolves with the executable response.
135000
135290
  */
135001
135291
  retrieveResponseFromExecutable(envMap) {
135002
- return new Promise((resolve60, reject) => {
135292
+ return new Promise((resolve61, reject) => {
135003
135293
  const child = childProcess.spawn(this.commandComponents[0], this.commandComponents.slice(1), {
135004
135294
  env: { ...process.env, ...Object.fromEntries(envMap) }
135005
135295
  });
@@ -135021,7 +135311,7 @@ var require_pluggable_auth_handler = __commonJS({
135021
135311
  try {
135022
135312
  const responseJson = JSON.parse(output);
135023
135313
  const response = new executable_response_1.ExecutableResponse(responseJson);
135024
- return resolve60(response);
135314
+ return resolve61(response);
135025
135315
  } catch (error) {
135026
135316
  if (error instanceof executable_response_1.ExecutableResponseError) {
135027
135317
  return reject(error);
@@ -135924,7 +136214,7 @@ var require_googleauth = __commonJS({
135924
136214
  }
135925
136215
  }
135926
136216
  fromStreamAsync(inputStream, options) {
135927
- return new Promise((resolve60, reject) => {
136217
+ return new Promise((resolve61, reject) => {
135928
136218
  if (!inputStream) {
135929
136219
  throw new Error("Must pass in a stream containing the Google auth settings.");
135930
136220
  }
@@ -135934,7 +136224,7 @@ var require_googleauth = __commonJS({
135934
136224
  try {
135935
136225
  const data2 = JSON.parse(chunks.join(""));
135936
136226
  const r2 = this._cacheClientFromJSON(data2, options);
135937
- return resolve60(r2);
136227
+ return resolve61(r2);
135938
136228
  } catch (err) {
135939
136229
  if (!this.keyFilename)
135940
136230
  throw err;
@@ -135944,7 +136234,7 @@ var require_googleauth = __commonJS({
135944
136234
  });
135945
136235
  this.cachedCredential = client;
135946
136236
  this.setGapicJWTValues(client);
135947
- return resolve60(client);
136237
+ return resolve61(client);
135948
136238
  }
135949
136239
  } catch (err) {
135950
136240
  return reject(err);
@@ -135980,17 +136270,17 @@ var require_googleauth = __commonJS({
135980
136270
  * Run the Google Cloud SDK command that prints the default project ID
135981
136271
  */
135982
136272
  async getDefaultServiceProjectId() {
135983
- return new Promise((resolve60) => {
136273
+ return new Promise((resolve61) => {
135984
136274
  (0, child_process_1.exec)("gcloud config config-helper --format json", (err, stdout2) => {
135985
136275
  if (!err && stdout2) {
135986
136276
  try {
135987
136277
  const projectId = JSON.parse(stdout2).configuration.properties.core.project;
135988
- resolve60(projectId);
136278
+ resolve61(projectId);
135989
136279
  return;
135990
136280
  } catch (e3) {
135991
136281
  }
135992
136282
  }
135993
- resolve60(null);
136283
+ resolve61(null);
135994
136284
  });
135995
136285
  });
135996
136286
  }
@@ -139782,7 +140072,7 @@ var require_stream = __commonJS({
139782
140072
  };
139783
140073
  duplex._final = function(callback) {
139784
140074
  if (ws.readyState === ws.CONNECTING) {
139785
- ws.once("open", function open2() {
140075
+ ws.once("open", function open3() {
139786
140076
  duplex._final(callback);
139787
140077
  });
139788
140078
  return;
@@ -139803,7 +140093,7 @@ var require_stream = __commonJS({
139803
140093
  };
139804
140094
  duplex._write = function(chunk, encoding, callback) {
139805
140095
  if (ws.readyState === ws.CONNECTING) {
139806
- ws.once("open", function open2() {
140096
+ ws.once("open", function open3() {
139807
140097
  duplex._write(chunk, encoding, callback);
139808
140098
  });
139809
140099
  return;
@@ -143833,14 +144123,14 @@ function __asyncValues2(o) {
143833
144123
  }, i2);
143834
144124
  function verb(n2) {
143835
144125
  i2[n2] = o[n2] && function(v2) {
143836
- return new Promise(function(resolve60, reject) {
143837
- v2 = o[n2](v2), settle(resolve60, reject, v2.done, v2.value);
144126
+ return new Promise(function(resolve61, reject) {
144127
+ v2 = o[n2](v2), settle(resolve61, reject, v2.done, v2.value);
143838
144128
  });
143839
144129
  };
143840
144130
  }
143841
- function settle(resolve60, reject, d2, v2) {
144131
+ function settle(resolve61, reject, d2, v2) {
143842
144132
  Promise.resolve(v2).then(function(v3) {
143843
- resolve60({ value: v3, done: d2 });
144133
+ resolve61({ value: v3, done: d2 });
143844
144134
  }, reject);
143845
144135
  }
143846
144136
  }
@@ -149038,15 +149328,15 @@ async function throwErrorIfNotOK(response) {
149038
149328
  }
149039
149329
  };
149040
149330
  }
149041
- const errorMessage3 = JSON.stringify(errorBody);
149331
+ const errorMessage = JSON.stringify(errorBody);
149042
149332
  if (status >= 400 && status < 600) {
149043
149333
  const apiError = new ApiError({
149044
- message: errorMessage3,
149334
+ message: errorMessage,
149045
149335
  status
149046
149336
  });
149047
149337
  throw apiError;
149048
149338
  }
149049
- throw new Error(errorMessage3);
149339
+ throw new Error(errorMessage);
149050
149340
  }
149051
149341
  }
149052
149342
  function includeExtraBodyToRequestInit(requestInit, extraBody) {
@@ -153978,10 +154268,10 @@ var init_node4 = __esm({
153978
154268
  const errorJson = JSON.parse(JSON.stringify(chunkJson["error"]));
153979
154269
  const status = errorJson["status"];
153980
154270
  const code = errorJson["code"];
153981
- const errorMessage3 = `got status: ${status}. ${JSON.stringify(chunkJson)}`;
154271
+ const errorMessage = `got status: ${status}. ${JSON.stringify(chunkJson)}`;
153982
154272
  if (code >= 400 && code < 600) {
153983
154273
  const apiError = new ApiError({
153984
- message: errorMessage3,
154274
+ message: errorMessage,
153985
154275
  status: code
153986
154276
  });
153987
154277
  throw apiError;
@@ -154330,8 +154620,8 @@ var init_node4 = __esm({
154330
154620
  const url = `${websocketBaseUrl}/ws/google.ai.generativelanguage.${apiVersion}.GenerativeService.BidiGenerateMusic?key=${apiKey}`;
154331
154621
  let onopenResolve = () => {
154332
154622
  };
154333
- const onopenPromise = new Promise((resolve60) => {
154334
- onopenResolve = resolve60;
154623
+ const onopenPromise = new Promise((resolve61) => {
154624
+ onopenResolve = resolve61;
154335
154625
  });
154336
154626
  const callbacks = params.callbacks;
154337
154627
  const onopenAwaitedCallback = function() {
@@ -154537,8 +154827,8 @@ var init_node4 = __esm({
154537
154827
  }
154538
154828
  let onopenResolve = () => {
154539
154829
  };
154540
- const onopenPromise = new Promise((resolve60) => {
154541
- onopenResolve = resolve60;
154830
+ const onopenPromise = new Promise((resolve61) => {
154831
+ onopenResolve = resolve61;
154542
154832
  });
154543
154833
  const callbacks = params.callbacks;
154544
154834
  const onopenAwaitedCallback = function() {
@@ -156886,7 +157176,7 @@ var init_node4 = __esm({
156886
157176
  return void 0;
156887
157177
  }
156888
157178
  };
156889
- sleep$1 = (ms) => new Promise((resolve60) => setTimeout(resolve60, ms));
157179
+ sleep$1 = (ms) => new Promise((resolve61) => setTimeout(resolve61, ms));
156890
157180
  FallbackEncoder = ({ headers, body }) => {
156891
157181
  return {
156892
157182
  bodyHeaders: {
@@ -157395,8 +157685,8 @@ ${underline2}`);
157395
157685
  };
157396
157686
  APIPromise = class _APIPromise extends Promise {
157397
157687
  constructor(client, responsePromise, parseResponse = defaultParseResponse) {
157398
- super((resolve60) => {
157399
- resolve60(null);
157688
+ super((resolve61) => {
157689
+ resolve61(null);
157400
157690
  });
157401
157691
  this.responsePromise = responsePromise;
157402
157692
  this.parseResponse = parseResponse;
@@ -158617,9 +158907,9 @@ __export(snapshot_exports, {
158617
158907
  examples: () => examples26
158618
158908
  });
158619
158909
  import { spawn as spawn16 } from "child_process";
158620
- import { existsSync as existsSync81, mkdtempSync as mkdtempSync5, readFileSync as readFileSync54, mkdirSync as mkdirSync38, rmSync as rmSync18, writeFileSync as writeFileSync28 } from "fs";
158910
+ import { existsSync as existsSync81, mkdtempSync as mkdtempSync5, readFileSync as readFileSync53, mkdirSync as mkdirSync38, rmSync as rmSync18, writeFileSync as writeFileSync28 } from "fs";
158621
158911
  import { tmpdir as tmpdir6 } from "os";
158622
- import { resolve as resolve53, join as join83, relative as relative15, isAbsolute as isAbsolute14 } from "path";
158912
+ import { resolve as resolve54, join as join83, relative as relative15, isAbsolute as isAbsolute14, basename as basename18 } from "path";
158623
158913
  async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDecoder = false) {
158624
158914
  const tmp = mkdtempSync5(join83(tmpdir6(), "hf-snapshot-frame-"));
158625
158915
  const outPath = join83(tmp, "frame.png");
@@ -158665,7 +158955,7 @@ async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDeco
158665
158955
  }
158666
158956
  );
158667
158957
  if (result.code !== 0 || result.timedOut || !existsSync81(outPath)) return null;
158668
- return readFileSync54(outPath);
158958
+ return readFileSync53(outPath);
158669
158959
  } finally {
158670
158960
  try {
158671
158961
  rmSync18(tmp, { recursive: true, force: true });
@@ -158732,21 +159022,24 @@ async function captureSnapshots(projectDir, opts) {
158732
159022
  await new Promise((r2) => setTimeout(r2, 1500));
158733
159023
  const fontReport = await page.evaluate(() => {
158734
159024
  const loaded = [];
158735
- const failed = [];
159025
+ const errored = [];
159026
+ const unused = [];
158736
159027
  document.fonts.forEach((f3) => {
158737
159028
  const entry = `${f3.family} (${f3.weight} ${f3.style})`;
158738
159029
  if (f3.status === "loaded") loaded.push(entry);
158739
- else failed.push(entry + ` [${f3.status}]`);
159030
+ else if (f3.status === "error") errored.push(entry);
159031
+ else unused.push(entry);
158740
159032
  });
158741
- return { loaded, failed };
158742
- }).catch(() => ({ loaded: [], failed: [] }));
158743
- if (fontReport.loaded.length > 0 || fontReport.failed.length > 0) {
158744
- console.log(
158745
- `
158746
- ${c.dim("Fonts loaded:")} ${fontReport.loaded.length > 0 ? fontReport.loaded.join(", ") : "none"}`
158747
- );
158748
- if (fontReport.failed.length > 0) {
158749
- console.log(` ${c.error("Fonts FAILED:")} ${fontReport.failed.join(", ")}`);
159033
+ return { loaded, errored, unused };
159034
+ }).catch(() => ({ loaded: [], errored: [], unused: [] }));
159035
+ if (fontReport.loaded.length > 0 || fontReport.errored.length > 0 || fontReport.unused.length > 0) {
159036
+ const parts = [`${fontReport.loaded.length} loaded`];
159037
+ if (fontReport.errored.length > 0) parts.push(`${fontReport.errored.length} failed`);
159038
+ if (fontReport.unused.length > 0) parts.push(`${fontReport.unused.length} unused`);
159039
+ console.log(`
159040
+ ${c.dim("Fonts:")} ${parts.join(", ")}`);
159041
+ if (fontReport.errored.length > 0) {
159042
+ console.log(` ${c.error("Fonts FAILED:")} ${fontReport.errored.join(", ")}`);
158750
159043
  }
158751
159044
  }
158752
159045
  const duration = await page.evaluate(() => {
@@ -158763,7 +159056,7 @@ async function captureSnapshots(projectDir, opts) {
158763
159056
  return [];
158764
159057
  }
158765
159058
  const positions = opts.at?.length ? opts.at : numFrames === 1 ? [duration / 2] : Array.from({ length: numFrames }, (_, i2) => i2 / (numFrames - 1) * duration);
158766
- const snapshotDir = join83(projectDir, "snapshots");
159059
+ const snapshotDir = opts.outputDir ?? join83(projectDir, "snapshots");
158767
159060
  mkdirSync38(snapshotDir, { recursive: true });
158768
159061
  try {
158769
159062
  const { readdirSync: readdirSync35 } = await import("fs");
@@ -158848,9 +159141,9 @@ async function captureSnapshots(projectDir, opts) {
158848
159141
  try {
158849
159142
  const url = new URL(v2.src);
158850
159143
  const decodedPath = decodeURIComponent(url.pathname).replace(/^\//, "");
158851
- const candidate = resolve53(projectDir, decodedPath);
158852
- const rel = relative15(projectDir, candidate);
158853
- if (!rel.startsWith("..") && !isAbsolute14(rel) && existsSync81(candidate)) {
159144
+ const candidate = resolve54(projectDir, decodedPath);
159145
+ const rel2 = relative15(projectDir, candidate);
159146
+ if (!rel2.startsWith("..") && !isAbsolute14(rel2) && existsSync81(candidate)) {
158854
159147
  filePath = candidate;
158855
159148
  }
158856
159149
  } catch {
@@ -158882,7 +159175,8 @@ async function captureSnapshots(projectDir, opts) {
158882
159175
  const filename = `frame-${String(i2).padStart(2, "0")}-at-${timeLabel}.png`;
158883
159176
  const framePath = join83(snapshotDir, filename);
158884
159177
  await page.screenshot({ path: framePath, type: "png" });
158885
- savedPaths.push(`snapshots/${filename}`);
159178
+ const rel = relative15(projectDir, framePath);
159179
+ savedPaths.push(rel.startsWith("..") || isAbsolute14(rel) ? framePath : rel);
158886
159180
  }
158887
159181
  } finally {
158888
159182
  await chromeBrowser.close();
@@ -158898,6 +159192,7 @@ var init_snapshot = __esm({
158898
159192
  "use strict";
158899
159193
  init_dist();
158900
159194
  init_project();
159195
+ init_errorMessage();
158901
159196
  init_compositionViewport();
158902
159197
  init_staticProjectServer();
158903
159198
  init_colors();
@@ -158918,6 +159213,11 @@ var init_snapshot = __esm({
158918
159213
  description: "Project directory",
158919
159214
  required: false
158920
159215
  },
159216
+ output: {
159217
+ type: "string",
159218
+ alias: "o",
159219
+ description: "Directory to write snapshots into (default: <project>/snapshots)"
159220
+ },
158921
159221
  frames: {
158922
159222
  type: "string",
158923
159223
  description: "Number of evenly-spaced frames to capture (default: 5)",
@@ -158946,7 +159246,13 @@ var init_snapshot = __esm({
158946
159246
  const label2 = atTimestamps ? `${atTimestamps.length} frames at [${atTimestamps.map((t2) => t2.toFixed(1) + "s").join(", ")}]` : `${frames} frames`;
158947
159247
  console.log(`${c.accent("\u25C6")} Capturing ${label2} from ${c.accent(project.name)}`);
158948
159248
  try {
158949
- const paths = await captureSnapshots(project.dir, { frames, timeout, at: atTimestamps });
159249
+ const snapshotDir = args.output ? resolve54(String(args.output)) : join83(project.dir, "snapshots");
159250
+ const paths = await captureSnapshots(project.dir, {
159251
+ frames,
159252
+ timeout,
159253
+ at: atTimestamps,
159254
+ outputDir: snapshotDir
159255
+ });
158950
159256
  if (paths.length === 0) {
158951
159257
  console.log(
158952
159258
  `
@@ -158954,14 +159260,15 @@ ${c.error("\u2717")} Could not determine composition duration \u2014 no frames c
158954
159260
  );
158955
159261
  process.exit(1);
158956
159262
  }
158957
- console.log(`
158958
- ${c.success("\u25C7")} ${paths.length} snapshots saved to snapshots/`);
159263
+ console.log(
159264
+ `
159265
+ ${c.success("\u25C7")} ${paths.length} snapshots saved to ${args.output ? snapshotDir : "snapshots/"}`
159266
+ );
158959
159267
  for (const p2 of paths) {
158960
159268
  console.log(` ${p2}`);
158961
159269
  }
158962
159270
  try {
158963
159271
  const { createSnapshotContactSheet: createSnapshotContactSheet2 } = await Promise.resolve().then(() => (init_contactSheet(), contactSheet_exports));
158964
- const snapshotDir = join83(project.dir, "snapshots");
158965
159272
  const sheets = await createSnapshotContactSheet2(
158966
159273
  snapshotDir,
158967
159274
  join83(snapshotDir, "contact-sheet.jpg")
@@ -158982,7 +159289,6 @@ ${c.success("\u25C7")} ${paths.length} snapshots saved to snapshots/`);
158982
159289
  const { GoogleGenAI: GoogleGenAI2 } = await Promise.resolve().then(() => (init_node4(), node_exports));
158983
159290
  const ai = new GoogleGenAI2({ apiKey: geminiKey });
158984
159291
  const model = process.env.HYPERFRAMES_GEMINI_MODEL || "gemini-3.1-flash-lite-preview";
158985
- const snapshotDir = join83(project.dir, "snapshots");
158986
159292
  const customQuestion = describeArg === "true" ? "Describe this video composition frame in 1-2 sentences. Be specific and factual: what elements are visible, what text appears, is the frame blank/black/loading, what is the composition. Flag any obvious problems." : describeArg;
158987
159293
  const descriptions = [
158988
159294
  `# Snapshot Frame Descriptions`,
@@ -159000,10 +159306,10 @@ ${c.success("\u25C7")} ${paths.length} snapshots saved to snapshots/`);
159000
159306
  }
159001
159307
  const results = await Promise.allSettled(
159002
159308
  paths.map(async (p2) => {
159003
- const filename = p2.replace("snapshots/", "");
159309
+ const filename = basename18(p2);
159004
159310
  const filePath = join83(snapshotDir, filename);
159005
159311
  if (!existsSync81(filePath)) return { filename, desc: "file not found" };
159006
- const raw = readFileSync54(filePath);
159312
+ const raw = readFileSync53(filePath);
159007
159313
  let imageData;
159008
159314
  let mimeType = "image/png";
159009
159315
  if (sharpFn) {
@@ -159035,7 +159341,7 @@ ${c.success("\u25C7")} ${paths.length} snapshots saved to snapshots/`);
159035
159341
  if (result.status === "fulfilled") {
159036
159342
  descriptions.push(`## ${result.value.filename}`, `${result.value.desc}`, ``);
159037
159343
  } else {
159038
- const errMsg = result.reason instanceof Error ? result.reason.message : String(result.reason);
159344
+ const errMsg = normalizeErrorMessage(result.reason);
159039
159345
  descriptions.push(`## (error)`, `Gemini call failed: ${errMsg.slice(0, 120)}`, ``);
159040
159346
  }
159041
159347
  }
@@ -159044,12 +159350,12 @@ ${c.success("\u25C7")} ${paths.length} snapshots saved to snapshots/`);
159044
159350
  console.log(` ${c.dim("descriptions.md")} (Gemini frame analysis)`);
159045
159351
  }
159046
159352
  } catch (descErr) {
159047
- const msg = descErr instanceof Error ? descErr.message : String(descErr);
159353
+ const msg = normalizeErrorMessage(descErr);
159048
159354
  console.log(` ${c.dim(`--describe failed: ${msg.slice(0, 80)}`)}`);
159049
159355
  }
159050
159356
  }
159051
159357
  } catch (err) {
159052
- const msg = err instanceof Error ? err.message : String(err);
159358
+ const msg = normalizeErrorMessage(err);
159053
159359
  console.error(`
159054
159360
  ${c.error("\u2717")} Snapshot failed: ${msg}`);
159055
159361
  process.exit(1);
@@ -159396,8 +159702,8 @@ __export(video_exports, {
159396
159702
  runVideoMode: () => runVideoMode,
159397
159703
  safeFilename: () => safeFilename
159398
159704
  });
159399
- import { createWriteStream as createWriteStream4, existsSync as existsSync83, mkdirSync as mkdirSync40, readFileSync as readFileSync55, unlinkSync as unlinkSync7 } from "fs";
159400
- import { resolve as resolve54, join as join85, basename as basename18 } from "path";
159705
+ import { createWriteStream as createWriteStream4, existsSync as existsSync83, mkdirSync as mkdirSync40, readFileSync as readFileSync54, unlinkSync as unlinkSync7 } from "fs";
159706
+ import { resolve as resolve55, join as join85, basename as basename19 } from "path";
159401
159707
  async function streamToFile(url, destPath) {
159402
159708
  const r2 = await safeFetch(url, {
159403
159709
  signal: AbortSignal.timeout(12e4),
@@ -159475,9 +159781,9 @@ function safeFilename(name) {
159475
159781
  return decoded.replace(/[^A-Za-z0-9._-]+/g, "_");
159476
159782
  }
159477
159783
  function findFilenameCollision(manifest, selected) {
159478
- const selectedName = safeFilename(selected.filename || basename18(selected.url));
159784
+ const selectedName = safeFilename(selected.filename || basename19(selected.url));
159479
159785
  return manifest.filter(
159480
- (e3) => e3.index !== selected.index && safeFilename(e3.filename || basename18(e3.url)) === selectedName
159786
+ (e3) => e3.index !== selected.index && safeFilename(e3.filename || basename19(e3.url)) === selectedName
159481
159787
  );
159482
159788
  }
159483
159789
  function pickManifestEntry(manifest, args) {
@@ -159515,7 +159821,7 @@ function pickManifestEntry(manifest, args) {
159515
159821
  };
159516
159822
  }
159517
159823
  async function runVideoMode(args) {
159518
- const projectDir = resolve54(args.project);
159824
+ const projectDir = resolve55(args.project);
159519
159825
  const directPath = join85(projectDir, "extracted", "video-manifest.json");
159520
159826
  const w2hPath = join85(projectDir, "capture", "extracted", "video-manifest.json");
159521
159827
  const manifestPath = existsSync83(directPath) ? directPath : w2hPath;
@@ -159530,7 +159836,7 @@ async function runVideoMode(args) {
159530
159836
  }
159531
159837
  let manifest;
159532
159838
  try {
159533
- manifest = JSON.parse(readFileSync55(manifestPath, "utf-8"));
159839
+ manifest = JSON.parse(readFileSync54(manifestPath, "utf-8"));
159534
159840
  } catch (e3) {
159535
159841
  console.error(`${c.error("\u2717")} video-manifest.json is malformed: ${e3.message}`);
159536
159842
  process.exitCode = 1;
@@ -159546,7 +159852,7 @@ async function runVideoMode(args) {
159546
159852
  );
159547
159853
  for (const e3 of manifest) {
159548
159854
  console.log(
159549
- ` ${c.bold(`[${e3.index}]`)} ${e3.filename} \u2014 ${e3.width}\xD7${e3.height}` + (e3.heading ? `
159855
+ ` ${c.bold(`[${e3.index}]`)} ${e3.filename} \u2014 ${e3.sourceWidth || e3.width}\xD7${e3.sourceHeight || e3.height}` + (e3.heading ? `
159550
159856
  heading: "${e3.heading}"` : "") + `
159551
159857
  url: ${e3.url}`
159552
159858
  );
@@ -159566,18 +159872,18 @@ async function runVideoMode(args) {
159566
159872
  const collisions = findFilenameCollision(manifest, entry);
159567
159873
  if (collisions.length > 0) {
159568
159874
  console.error(
159569
- `${c.error("\u2717")} filename "${safeFilename(entry.filename || basename18(entry.url))}" collides with manifest entr${collisions.length === 1 ? "y" : "ies"} ${collisions.map((co) => `[${co.index}]`).join(", ")}. Refusing to download \u2014 the on-disk file's bytes would not match the requested entry.`
159875
+ `${c.error("\u2717")} filename "${safeFilename(entry.filename || basename19(entry.url))}" collides with manifest entr${collisions.length === 1 ? "y" : "ies"} ${collisions.map((co) => `[${co.index}]`).join(", ")}. Refusing to download \u2014 the on-disk file's bytes would not match the requested entry.`
159570
159876
  );
159571
159877
  process.exitCode = 1;
159572
159878
  return;
159573
159879
  }
159574
159880
  const outDir = isW2hLayout ? join85(projectDir, "capture", "assets", "videos") : join85(projectDir, "assets", "videos");
159575
159881
  mkdirSync40(outDir, { recursive: true });
159576
- const fname = safeFilename(entry.filename || basename18(entry.url));
159882
+ const fname = safeFilename(entry.filename || basename19(entry.url));
159577
159883
  const outPath = join85(outDir, fname);
159578
159884
  const relPath = isW2hLayout ? `capture/assets/videos/${fname}` : `assets/videos/${fname}`;
159579
159885
  console.log(
159580
- `${c.accent("\u25B8")} downloading [${entry.index}] ${entry.filename} (${entry.width}\xD7${entry.height})`
159886
+ `${c.accent("\u25B8")} downloading [${entry.index}] ${entry.filename} (${entry.sourceWidth || entry.width}\xD7${entry.sourceHeight || entry.height})`
159581
159887
  );
159582
159888
  console.log(` from: ${entry.url}`);
159583
159889
  try {
@@ -159588,7 +159894,7 @@ async function runVideoMode(args) {
159588
159894
  const snippetId = `video-${entry.index}`;
159589
159895
  console.log(
159590
159896
  ` Reference it from a beat composition as:
159591
- <video id="${snippetId}" src="${relPath}" data-start="0" data-duration="${entry.width === entry.height ? 5 : 4}" data-track-index="0" autoplay muted loop></video>`
159897
+ <video id="${snippetId}" src="${relPath}" data-start="0" data-duration="${(entry.sourceWidth || entry.width) === (entry.sourceHeight || entry.height) ? 5 : 4}" data-track-index="0" autoplay muted loop></video>`
159592
159898
  );
159593
159899
  } catch (e3) {
159594
159900
  if (e3.code === "EEXIST") {
@@ -160602,7 +160908,7 @@ var init_designStyleExtractor = __esm({
160602
160908
  });
160603
160909
 
160604
160910
  // src/capture/fontMetadataExtractor.ts
160605
- import { readdirSync as readdirSync29, readFileSync as readFileSync56, writeFileSync as writeFileSync30, existsSync as existsSync84 } from "fs";
160911
+ import { readdirSync as readdirSync29, readFileSync as readFileSync55, writeFileSync as writeFileSync30, existsSync as existsSync84 } from "fs";
160606
160912
  import { join as join86 } from "path";
160607
160913
  import * as fontkit from "fontkit";
160608
160914
  function isFontCollection(value) {
@@ -160652,7 +160958,7 @@ function readSingleFont(fullPath, filename) {
160652
160958
  identified: false
160653
160959
  };
160654
160960
  try {
160655
- const buf = readFileSync56(fullPath);
160961
+ const buf = readFileSync55(fullPath);
160656
160962
  const created = fontkit.create(buf);
160657
160963
  const font = isFontCollection(created) ? created.fonts[0] : created;
160658
160964
  if (!font) return empty2;
@@ -160908,7 +161214,7 @@ var init_animationCataloger = __esm({
160908
161214
  });
160909
161215
 
160910
161216
  // src/capture/mediaCapture.ts
160911
- import { mkdirSync as mkdirSync41, writeFileSync as writeFileSync31, readdirSync as readdirSync30, readFileSync as readFileSync57, statSync as statSync24 } from "fs";
161217
+ import { mkdirSync as mkdirSync41, writeFileSync as writeFileSync31, readdirSync as readdirSync30, readFileSync as readFileSync56, statSync as statSync25 } from "fs";
160912
161218
  import { join as join87, extname as extname16 } from "path";
160913
161219
  async function saveLottieAnimations(discoveredLotties, lottieDir) {
160914
161220
  let savedCount = 0;
@@ -160974,17 +161280,17 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
160974
161280
  for (const file of readdirSync30(lottieDir)) {
160975
161281
  if (!file.endsWith(".json")) continue;
160976
161282
  try {
160977
- const raw = JSON.parse(readFileSync57(join87(lottieDir, file), "utf-8"));
161283
+ const raw = JSON.parse(readFileSync56(join87(lottieDir, file), "utf-8"));
160978
161284
  const fr = raw.fr || 30;
160979
161285
  const dur = ((raw.op || 0) - (raw.ip || 0)) / fr;
160980
161286
  const previewName = file.replace(".json", "-preview.png");
160981
- const fileSize = statSync24(join87(lottieDir, file)).size;
161287
+ const fileSize = statSync25(join87(lottieDir, file)).size;
160982
161288
  if (fileSize > 2e6) continue;
160983
161289
  let previewPage;
160984
161290
  try {
160985
161291
  previewPage = await chromeBrowser.newPage();
160986
161292
  await previewPage.setViewport({ width: 400, height: 400 });
160987
- const animData = JSON.parse(readFileSync57(join87(lottieDir, file), "utf-8"));
161293
+ const animData = JSON.parse(readFileSync56(join87(lottieDir, file), "utf-8"));
160988
161294
  const midFrame = Math.floor(((raw.op || 0) - (raw.ip || 0)) * 0.3);
160989
161295
  await previewPage.setContent(
160990
161296
  `<!DOCTYPE html>
@@ -161122,6 +161428,8 @@ async function captureVideoManifest(page, outputDir, progress, opts) {
161122
161428
  filename: k2,
161123
161429
  width: 0,
161124
161430
  height: 0,
161431
+ sourceWidth: 0,
161432
+ sourceHeight: 0,
161125
161433
  top: 0,
161126
161434
  left: 0,
161127
161435
  heading: "",
@@ -161179,6 +161487,8 @@ async function captureVideoManifest(page, outputDir, progress, opts) {
161179
161487
  filename: v2.filename,
161180
161488
  width: v2.width,
161181
161489
  height: v2.height,
161490
+ sourceWidth: v2.sourceWidth,
161491
+ sourceHeight: v2.sourceHeight,
161182
161492
  heading: v2.heading,
161183
161493
  caption: v2.caption,
161184
161494
  ariaLabel: v2.ariaLabel,
@@ -161235,8 +161545,14 @@ var init_mediaCapture = __esm({
161235
161545
  if (!ariaLabel && wrapper) ariaLabel = wrapper.getAttribute('aria-label') || '';
161236
161546
  return {
161237
161547
  src: src,
161548
+ // width/height are the DOM display box (what the page laid the element out
161549
+ // at); sourceWidth/Height are the clip's intrinsic resolution. Size planners
161550
+ // off the source dims, not the display box (a 1920x1080 clip can display at
161551
+ // 904x613). 0 when metadata has not loaded yet.
161238
161552
  width: Math.round(rect.width),
161239
161553
  height: Math.round(rect.height),
161554
+ sourceWidth: v.videoWidth || 0,
161555
+ sourceHeight: v.videoHeight || 0,
161240
161556
  top: Math.round(rect.top),
161241
161557
  left: Math.round(rect.left),
161242
161558
  heading: heading,
@@ -161250,8 +161566,8 @@ var init_mediaCapture = __esm({
161250
161566
  });
161251
161567
 
161252
161568
  // src/capture/contentExtractor.ts
161253
- import { existsSync as existsSync85, readdirSync as readdirSync31, statSync as statSync25, readFileSync as readFileSync58 } from "fs";
161254
- import { basename as basename19, join as join88 } from "path";
161569
+ import { existsSync as existsSync85, readdirSync as readdirSync31, statSync as statSync26, readFileSync as readFileSync57 } from "fs";
161570
+ import { basename as basename20, join as join88 } from "path";
161255
161571
  async function detectLibraries(page, capturedShaders) {
161256
161572
  let detectedLibraries = [];
161257
161573
  try {
@@ -161427,9 +161743,9 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
161427
161743
  const results = await Promise.allSettled(
161428
161744
  batch.map(async (file) => {
161429
161745
  const filePath = join88(outputDir, "assets", file);
161430
- const stat3 = statSync25(filePath);
161746
+ const stat3 = statSync26(filePath);
161431
161747
  if (stat3.size > 4e6) return { file, caption: "" };
161432
- const buffer = readFileSync58(filePath);
161748
+ const buffer = readFileSync57(filePath);
161433
161749
  const base64 = buffer.toString("base64");
161434
161750
  const ext = file.split(".").pop()?.toLowerCase() || "png";
161435
161751
  const mimeType = ext === "jpg" ? "image/jpeg" : `image/${ext}`;
@@ -161491,7 +161807,7 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
161491
161807
  const filePath = join88(assetsDir, relPath);
161492
161808
  let pngBase64;
161493
161809
  try {
161494
- const svgSource = readFileSync58(filePath, "utf-8");
161810
+ const svgSource = readFileSync57(filePath, "utf-8");
161495
161811
  const lightFillHits = (svgSource.match(/fill\s*=\s*["'](#fff(fff)?|white|#[ef][ef][ef]|#[ef]{6})["']/gi) || []).length;
161496
161812
  const darkFillHits = (svgSource.match(/fill\s*=\s*["'](#000(000)?|black|#[0-3]{6}|#[0-3]{3})["']/gi) || []).length;
161497
161813
  const bg = lightFillHits > darkFillHits ? { r: 32, g: 32, b: 32 } : { r: 255, g: 255, b: 255 };
@@ -161551,7 +161867,7 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
161551
161867
  for (const file of readdirSync31(assetsPath)) {
161552
161868
  if (file === "svgs" || file === "fonts" || file === "lottie" || file === "videos") continue;
161553
161869
  const filePath = join88(assetsPath, file);
161554
- const stat3 = statSync25(filePath);
161870
+ const stat3 = statSync26(filePath);
161555
161871
  if (!stat3.isFile()) continue;
161556
161872
  const sizeKb = Math.round(stat3.size / 1024);
161557
161873
  const catalogMatch = catalogedAssets.find(
@@ -161607,14 +161923,16 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
161607
161923
  const videoLines = [];
161608
161924
  try {
161609
161925
  const manifest = JSON.parse(
161610
- readFileSync58(join88(outputDir, "extracted", "video-manifest.json"), "utf-8")
161926
+ readFileSync57(join88(outputDir, "extracted", "video-manifest.json"), "utf-8")
161611
161927
  );
161612
161928
  for (const v2 of manifest) {
161613
161929
  if (!v2.localPath) continue;
161614
- const base2 = basename19(v2.localPath) || v2.filename || "";
161930
+ const base2 = basename20(v2.localPath) || v2.filename || "";
161615
161931
  if (!base2) continue;
161616
161932
  const desc = (v2.caption || v2.heading || "").trim().replace(/\s+/g, " ").slice(0, 140) || "motion clip";
161617
- const dims = v2.width && v2.height ? `, ~${v2.width}\xD7${v2.height}` : "";
161933
+ const dimW = v2.sourceWidth || v2.width;
161934
+ const dimH = v2.sourceHeight || v2.height;
161935
+ const dims = dimW && dimH ? `, ~${dimW}\xD7${dimH}` : "";
161618
161936
  videoLines.push(`${base2} \u2014 [video] ${desc}${dims}`);
161619
161937
  }
161620
161938
  } catch {
@@ -161767,15 +162085,15 @@ var init_agentPromptGenerator = __esm({
161767
162085
  });
161768
162086
 
161769
162087
  // src/capture/scaffolding.ts
161770
- import { existsSync as existsSync87, writeFileSync as writeFileSync34, readFileSync as readFileSync59 } from "fs";
161771
- import { join as join90, resolve as resolve55 } from "path";
162088
+ import { existsSync as existsSync87, writeFileSync as writeFileSync34, readFileSync as readFileSync58 } from "fs";
162089
+ import { join as join90, resolve as resolve56 } from "path";
161772
162090
  function loadEnvFile(startDir) {
161773
162091
  try {
161774
- let dir = resolve55(startDir);
162092
+ let dir = resolve56(startDir);
161775
162093
  for (let i2 = 0; i2 < 5; i2++) {
161776
- const envPath = resolve55(dir, ".env");
162094
+ const envPath = resolve56(dir, ".env");
161777
162095
  try {
161778
- const envContent = readFileSync59(envPath, "utf-8");
162096
+ const envContent = readFileSync58(envPath, "utf-8");
161779
162097
  for (const line of envContent.split("\n")) {
161780
162098
  const trimmed = line.trim();
161781
162099
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -161787,7 +162105,7 @@ function loadEnvFile(startDir) {
161787
162105
  }
161788
162106
  break;
161789
162107
  } catch {
161790
- dir = resolve55(dir, "..");
162108
+ dir = resolve56(dir, "..");
161791
162109
  }
161792
162110
  }
161793
162111
  } catch {
@@ -162509,7 +162827,7 @@ async function captureWebsite(opts, onProgress) {
162509
162827
  );
162510
162828
  } catch (err) {
162511
162829
  const errMsg = err instanceof Error ? `${err.message}
162512
- ${err.stack}` : String(err);
162830
+ ${err.stack}` : normalizeErrorMessage(err);
162513
162831
  console.error(` \u26A0 Design style extraction failed: ${errMsg}`);
162514
162832
  warnings.push(`Design style extraction failed: ${errMsg}`);
162515
162833
  }
@@ -162591,10 +162909,7 @@ ${err.stack}` : String(err);
162591
162909
  }
162592
162910
  }
162593
162911
  } catch (err) {
162594
- console.warn(
162595
- "Font metadata extraction failed (non-fatal):",
162596
- err instanceof Error ? err.message : err
162597
- );
162912
+ console.warn("Font metadata extraction failed (non-fatal):", normalizeErrorMessage(err));
162598
162913
  }
162599
162914
  if (animationCatalog) {
162600
162915
  const uniqueAnimNames = /* @__PURE__ */ new Set();
@@ -162755,6 +163070,7 @@ var init_capture = __esm({
162755
163070
  init_designStyleExtractor();
162756
163071
  init_assetDownloader();
162757
163072
  init_fontMetadataExtractor();
163073
+ init_errorMessage();
162758
163074
  init_animationCataloger();
162759
163075
  init_mediaCapture();
162760
163076
  init_contentExtractor();
@@ -162768,12 +163084,13 @@ __export(capture_exports2, {
162768
163084
  default: () => capture_default,
162769
163085
  examples: () => examples27
162770
163086
  });
162771
- import { resolve as resolve56 } from "path";
163087
+ import { resolve as resolve57 } from "path";
162772
163088
  var examples27, capture_default;
162773
163089
  var init_capture2 = __esm({
162774
163090
  "src/commands/capture.ts"() {
162775
163091
  "use strict";
162776
163092
  init_dist();
163093
+ init_errorMessage();
162777
163094
  examples27 = [
162778
163095
  ["Capture a website into ./capture/", "hyperframes capture https://stripe.com"],
162779
163096
  ["Capture to a different directory", "hyperframes capture https://linear.app -o linear-video"],
@@ -162866,13 +163183,13 @@ var init_capture2 = __esm({
162866
163183
  }
162867
163184
  const isDefaultOutput = !args.output;
162868
163185
  let outputName = args.output ?? "capture";
162869
- let outputDir = resolve56(outputName);
163186
+ let outputDir = resolve57(outputName);
162870
163187
  if (isDefaultOutput) {
162871
163188
  const { existsSync: existsSync98 } = await import("fs");
162872
163189
  let n2 = 2;
162873
163190
  while (existsSync98(outputDir) && n2 < 100) {
162874
163191
  outputName = `capture-${n2}`;
162875
- outputDir = resolve56(outputName);
163192
+ outputDir = resolve57(outputName);
162876
163193
  n2++;
162877
163194
  }
162878
163195
  if (existsSync98(outputDir)) {
@@ -162958,7 +163275,7 @@ var init_capture2 = __esm({
162958
163275
  console.log();
162959
163276
  }
162960
163277
  } catch (err) {
162961
- const errMsg = err instanceof Error ? err.message : String(err);
163278
+ const errMsg = normalizeErrorMessage(err);
162962
163279
  try {
162963
163280
  const { mkdirSync: mkdirSync49, writeFileSync: writeFileSync39 } = await import("fs");
162964
163281
  mkdirSync49(outputDir, { recursive: true });
@@ -163007,7 +163324,7 @@ __export(state_exports, {
163007
163324
  stateFilePath: () => stateFilePath,
163008
163325
  writeStackOutputs: () => writeStackOutputs
163009
163326
  });
163010
- import { existsSync as existsSync89, mkdirSync as mkdirSync45, readdirSync as readdirSync34, readFileSync as readFileSync60, rmSync as rmSync19, writeFileSync as writeFileSync37 } from "fs";
163327
+ import { existsSync as existsSync89, mkdirSync as mkdirSync45, readdirSync as readdirSync34, readFileSync as readFileSync59, rmSync as rmSync19, writeFileSync as writeFileSync37 } from "fs";
163011
163328
  import { dirname as dirname39, join as join94 } from "path";
163012
163329
  function stateFilePath(stackName = DEFAULT_STACK_NAME, cwd = process.cwd()) {
163013
163330
  return join94(cwd, STATE_DIR_NAME, `${STATE_FILE_PREFIX}${stackName}.json`);
@@ -163022,7 +163339,7 @@ function readStackOutputs(stackName = DEFAULT_STACK_NAME, cwd = process.cwd()) {
163022
163339
  const path2 = stateFilePath(stackName, cwd);
163023
163340
  if (!existsSync89(path2)) return null;
163024
163341
  try {
163025
- return JSON.parse(readFileSync60(path2, "utf-8"));
163342
+ return JSON.parse(readFileSync59(path2, "utf-8"));
163026
163343
  } catch {
163027
163344
  return null;
163028
163345
  }
@@ -163181,16 +163498,16 @@ var init_sam = __esm({
163181
163498
 
163182
163499
  // src/commands/lambda/repoRoot.ts
163183
163500
  import { existsSync as existsSync91 } from "fs";
163184
- import { dirname as dirname40, resolve as resolve57 } from "path";
163501
+ import { dirname as dirname40, resolve as resolve58 } from "path";
163185
163502
  import { fileURLToPath as fileURLToPath15 } from "url";
163186
163503
  function repoRoot() {
163187
163504
  const override = process.env.HYPERFRAMES_REPO_ROOT;
163188
- if (override && existsSync91(resolve57(override, "packages", "aws-lambda", "package.json"))) {
163505
+ if (override && existsSync91(resolve58(override, "packages", "aws-lambda", "package.json"))) {
163189
163506
  return override;
163190
163507
  }
163191
163508
  let dir = dirname40(fileURLToPath15(import.meta.url));
163192
163509
  for (let depth = 0; depth < 12; depth++) {
163193
- if (existsSync91(resolve57(dir, "packages", "aws-lambda", "package.json"))) {
163510
+ if (existsSync91(resolve58(dir, "packages", "aws-lambda", "package.json"))) {
163194
163511
  return dir;
163195
163512
  }
163196
163513
  const parent = dirname40(dir);
@@ -163214,7 +163531,7 @@ __export(deploy_exports, {
163214
163531
  });
163215
163532
  import { spawnSync as spawnSync5 } from "child_process";
163216
163533
  import { existsSync as existsSync92 } from "fs";
163217
- import { join as join96, resolve as resolve58 } from "path";
163534
+ import { join as join96, resolve as resolve59 } from "path";
163218
163535
  async function runDeploy(args = {}) {
163219
163536
  const resolved = {
163220
163537
  stackName: args.stackName ?? DEFAULT_STACK_NAME,
@@ -163268,7 +163585,7 @@ async function runDeploy(args = {}) {
163268
163585
  console.log(` ${c.dim("Bucket:")} ${outputs.bucketName}`);
163269
163586
  console.log(` ${c.dim("State machine:")} ${outputs.stateMachineArn}`);
163270
163587
  console.log(` ${c.dim("Function:")} ${outputs.functionName}`);
163271
- console.log(` ${c.dim("State file:")} ${resolve58(statePath2)}`);
163588
+ console.log(` ${c.dim("State file:")} ${resolve59(statePath2)}`);
163272
163589
  console.log();
163273
163590
  console.log(c.dim(`Render with: hyperframes lambda render <project-dir>`));
163274
163591
  }
@@ -163344,14 +163661,14 @@ var init_sites = __esm({
163344
163661
  });
163345
163662
 
163346
163663
  // src/commands/lambda/_dimensions.ts
163347
- import { readFileSync as readFileSync61 } from "fs";
163664
+ import { readFileSync as readFileSync60 } from "fs";
163348
163665
  import { join as join97 } from "path";
163349
163666
  function warnOnDimensionMismatch(args) {
163350
163667
  if (args.quiet) return;
163351
163668
  if (args.outputResolution) return;
163352
163669
  let html;
163353
163670
  try {
163354
- html = readFileSync61(join97(args.projectDir, "index.html"), "utf-8");
163671
+ html = readFileSync60(join97(args.projectDir, "index.html"), "utf-8");
163355
163672
  } catch {
163356
163673
  return;
163357
163674
  }
@@ -163521,7 +163838,7 @@ __export(render_batch_exports, {
163521
163838
  runRenderBatch: () => runRenderBatch,
163522
163839
  runWithConcurrencyLimit: () => runWithConcurrencyLimit
163523
163840
  });
163524
- import { existsSync as existsSync94, readFileSync as readFileSync63 } from "fs";
163841
+ import { existsSync as existsSync94, readFileSync as readFileSync61 } from "fs";
163525
163842
  import { join as join99, resolve as resolvePath3 } from "path";
163526
163843
  async function loadSDK3() {
163527
163844
  return import("@hyperframes/aws-lambda/sdk");
@@ -163638,7 +163955,7 @@ async function runRenderBatch(args) {
163638
163955
  outputKey: entry.outputKey,
163639
163956
  executionArn: null,
163640
163957
  status: "failed-to-start",
163641
- error: err instanceof Error ? err.message : String(err)
163958
+ error: normalizeErrorMessage(err)
163642
163959
  };
163643
163960
  }
163644
163961
  };
@@ -163674,7 +163991,7 @@ function makePlaceholderSiteHandle(siteId, bucketName) {
163674
163991
  };
163675
163992
  }
163676
163993
  function parseBatchFile(path2) {
163677
- const raw = readFileSync63(path2, "utf8");
163994
+ const raw = readFileSync61(path2, "utf8");
163678
163995
  const lines = raw.split(/\r?\n/);
163679
163996
  const out = [];
163680
163997
  for (let i2 = 0; i2 < lines.length; i2++) {
@@ -163684,10 +164001,7 @@ function parseBatchFile(path2) {
163684
164001
  try {
163685
164002
  parsed = JSON.parse(line);
163686
164003
  } catch (err) {
163687
- errorBox(
163688
- `Invalid JSON in batch file on line ${i2 + 1}`,
163689
- err instanceof Error ? err.message : String(err)
163690
- );
164004
+ errorBox(`Invalid JSON in batch file on line ${i2 + 1}`, normalizeErrorMessage(err));
163691
164005
  process.exit(1);
163692
164006
  }
163693
164007
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
@@ -163755,6 +164069,7 @@ var init_render_batch = __esm({
163755
164069
  init_colors();
163756
164070
  init_format();
163757
164071
  init_variables();
164072
+ init_errorMessage();
163758
164073
  init_dimensions();
163759
164074
  init_state();
163760
164075
  DEFAULT_MAX_CONCURRENT = 50;
@@ -163868,7 +164183,7 @@ __export(policies_exports, {
163868
164183
  runPolicies: () => runPolicies,
163869
164184
  validatePolicy: () => validatePolicy
163870
164185
  });
163871
- import { readFileSync as readFileSync64 } from "fs";
164186
+ import { readFileSync as readFileSync63 } from "fs";
163872
164187
  function allRequiredActions() {
163873
164188
  const set = /* @__PURE__ */ new Set();
163874
164189
  for (const group of Object.values(REQUIRED_ACTIONS)) {
@@ -163938,7 +164253,7 @@ async function runPolicies(args) {
163938
164253
  try {
163939
164254
  result = validatePolicy(args.inputPath);
163940
164255
  } catch (err) {
163941
- const msg = err instanceof Error ? err.message : String(err);
164256
+ const msg = normalizeErrorMessage(err);
163942
164257
  if (args.json) {
163943
164258
  console.log(JSON.stringify({ ok: false, error: msg }, null, 2));
163944
164259
  process.exitCode = 1;
@@ -163974,7 +164289,7 @@ async function runPolicies(args) {
163974
164289
  }
163975
164290
  }
163976
164291
  function validatePolicy(policyPath) {
163977
- const raw = readFileSync64(policyPath, "utf-8");
164292
+ const raw = readFileSync63(policyPath, "utf-8");
163978
164293
  const parsed = JSON.parse(raw);
163979
164294
  const statements = Array.isArray(parsed.Statement) ? parsed.Statement : parsed.Statement ? [
163980
164295
  parsed.Statement
@@ -164043,6 +164358,7 @@ var init_policies = __esm({
164043
164358
  "src/commands/lambda/policies.ts"() {
164044
164359
  "use strict";
164045
164360
  init_colors();
164361
+ init_errorMessage();
164046
164362
  REQUIRED_ACTIONS = {
164047
164363
  cloudformation: [
164048
164364
  "cloudformation:CreateChangeSet",
@@ -164568,9 +164884,9 @@ __export(cloudrun_exports, {
164568
164884
  });
164569
164885
  import { spawnSync as spawnSync6 } from "child_process";
164570
164886
  import { createRequire as createRequire4 } from "module";
164571
- import { existsSync as existsSync95, mkdirSync as mkdirSync46, readFileSync as readFileSync65, writeFileSync as writeFileSync38 } from "fs";
164887
+ import { existsSync as existsSync95, mkdirSync as mkdirSync46, readFileSync as readFileSync64, writeFileSync as writeFileSync38 } from "fs";
164572
164888
  import { homedir as homedir14 } from "os";
164573
- import { dirname as dirname41, join as join100, resolve as resolve59 } from "path";
164889
+ import { dirname as dirname41, join as join100, resolve as resolve60 } from "path";
164574
164890
  function stateDir() {
164575
164891
  return join100(homedir14(), ".hyperframes");
164576
164892
  }
@@ -164589,7 +164905,7 @@ function readState(args) {
164589
164905
  let base2 = {};
164590
164906
  if (existsSync95(statePath())) {
164591
164907
  try {
164592
- base2 = JSON.parse(readFileSync65(statePath(), "utf8"));
164908
+ base2 = JSON.parse(readFileSync64(statePath(), "utf8"));
164593
164909
  } catch {
164594
164910
  }
164595
164911
  }
@@ -164735,7 +165051,7 @@ function machineVars(args, project, region, image) {
164735
165051
  return vars;
164736
165052
  }
164737
165053
  function findRepoRoot(tfDir) {
164738
- const candidate = resolve59(tfDir, "..", "..", "..");
165054
+ const candidate = resolve60(tfDir, "..", "..", "..");
164739
165055
  if (existsSync95(join100(candidate, "packages", "gcp-cloud-run", "Dockerfile"))) return candidate;
164740
165056
  return null;
164741
165057
  }
@@ -164770,7 +165086,7 @@ async function runSites(args) {
164770
165086
  const state = readState(args);
164771
165087
  const { deploySite } = await import("@hyperframes/gcp-cloud-run/sdk");
164772
165088
  const handle = await deploySite({
164773
- projectDir: resolve59(projectDir),
165089
+ projectDir: resolve60(projectDir),
164774
165090
  bucketName: state.bucketName,
164775
165091
  siteId: args["site-id"]
164776
165092
  });
@@ -164803,11 +165119,11 @@ async function runRender2(args) {
164803
165119
  process.exit(1);
164804
165120
  }
164805
165121
  const state = readState(args);
164806
- const variables = resolveAndValidateVariables(args, resolve59(projectDir));
165122
+ const variables = resolveAndValidateVariables(args, resolve60(projectDir));
164807
165123
  const config = buildRenderConfig(args, fps, width, height, variables);
164808
165124
  const { renderToCloudRun, getRenderProgress } = await import("@hyperframes/gcp-cloud-run/sdk");
164809
165125
  const handle = await renderToCloudRun({
164810
- projectDir: resolve59(projectDir),
165126
+ projectDir: resolve60(projectDir),
164811
165127
  config,
164812
165128
  bucketName: state.bucketName,
164813
165129
  projectId: state.projectId,
@@ -164887,11 +165203,11 @@ async function runRenderBatch2(args) {
164887
165203
  console.error(`[cloudrun render-batch] --fps must be 24, 30, or 60; got ${fps}.`);
164888
165204
  process.exit(1);
164889
165205
  }
164890
- if (!existsSync95(resolve59(batchPath))) {
165206
+ if (!existsSync95(resolve60(batchPath))) {
164891
165207
  console.error(`[cloudrun render-batch] batch file not found: ${batchPath}`);
164892
165208
  process.exit(1);
164893
165209
  }
164894
- const entries2 = parseBatchFile2(resolve59(batchPath));
165210
+ const entries2 = parseBatchFile2(resolve60(batchPath));
164895
165211
  if (entries2.length === 0) {
164896
165212
  console.error("[cloudrun render-batch] batch file has no entries.");
164897
165213
  process.exit(1);
@@ -164910,7 +165226,7 @@ async function runRenderBatch2(args) {
164910
165226
  const maxConcurrent = parsePositiveInt2(args["max-concurrent"], "--max-concurrent") ?? DEFAULT_BATCH_MAX_CONCURRENT;
164911
165227
  const { deploySite, renderToCloudRun } = await import("@hyperframes/gcp-cloud-run/sdk");
164912
165228
  const siteHandle = await deploySite({
164913
- projectDir: resolve59(projectDir),
165229
+ projectDir: resolve60(projectDir),
164914
165230
  bucketName: state.bucketName,
164915
165231
  siteId: args["site-id"]
164916
165232
  });
@@ -164935,7 +165251,7 @@ async function runRenderBatch2(args) {
164935
165251
  } catch (err) {
164936
165252
  return {
164937
165253
  outputKey: entry.outputKey,
164938
- error: err instanceof Error ? err.message : String(err)
165254
+ error: normalizeErrorMessage(err)
164939
165255
  };
164940
165256
  }
164941
165257
  })
@@ -164954,7 +165270,7 @@ async function runRenderBatch2(args) {
164954
165270
  if (failed.length > 0) process.exit(1);
164955
165271
  }
164956
165272
  function parseBatchFile2(path2) {
164957
- const lines = readFileSync65(path2, "utf8").split(/\r?\n/);
165273
+ const lines = readFileSync64(path2, "utf8").split(/\r?\n/);
164958
165274
  const entries2 = [];
164959
165275
  lines.forEach((line, idx) => {
164960
165276
  const trimmed = line.trim();
@@ -164978,7 +165294,7 @@ function parseBatchFile2(path2) {
164978
165294
  }
164979
165295
  function runDestroy2(args) {
164980
165296
  const tfDir = terraformDir();
164981
- const state = existsSync95(statePath()) ? JSON.parse(readFileSync65(statePath(), "utf8")) : {};
165297
+ const state = existsSync95(statePath()) ? JSON.parse(readFileSync64(statePath(), "utf8")) : {};
164982
165298
  const project = args.project ?? state.projectId;
164983
165299
  const region = args.region ?? state.region ?? "us-central1";
164984
165300
  const image = args.image ?? "unused:latest";
@@ -165072,6 +165388,7 @@ var init_cloudrun = __esm({
165072
165388
  init_dist3();
165073
165389
  init_colors();
165074
165390
  init_variables();
165391
+ init_errorMessage();
165075
165392
  examples29 = [
165076
165393
  ["Deploy the Cloud Run render stack", "hyperframes cloudrun deploy --project my-gcp-project"],
165077
165394
  [
@@ -165256,7 +165573,7 @@ ${HELP2}`);
165256
165573
  });
165257
165574
 
165258
165575
  // src/cloud/detectAspectRatio.ts
165259
- import { readFileSync as readFileSync66 } from "fs";
165576
+ import { readFileSync as readFileSync65 } from "fs";
165260
165577
  function extractAttributeNumber(tag, re2) {
165261
165578
  const match = tag.match(re2);
165262
165579
  if (!match) return null;
@@ -165268,9 +165585,9 @@ function extractAttributeNumber(tag, re2) {
165268
165585
  function detectAspectRatioFromHtml(entryHtmlPath) {
165269
165586
  let html;
165270
165587
  try {
165271
- html = readFileSync66(entryHtmlPath, "utf-8");
165588
+ html = readFileSync65(entryHtmlPath, "utf-8");
165272
165589
  } catch (err) {
165273
- return { kind: "read-error", error: err instanceof Error ? err.message : String(err) };
165590
+ return { kind: "read-error", error: normalizeErrorMessage(err) };
165274
165591
  }
165275
165592
  return detectAspectRatioFromHtmlString(html);
165276
165593
  }
@@ -165294,6 +165611,7 @@ var RATIO_TOLERANCE, SUPPORTED_RATIOS, ROOT_COMPOSITION_DIV_RE, DATA_WIDTH_RE, D
165294
165611
  var init_detectAspectRatio = __esm({
165295
165612
  "src/cloud/detectAspectRatio.ts"() {
165296
165613
  "use strict";
165614
+ init_errorMessage();
165297
165615
  RATIO_TOLERANCE = 0.05;
165298
165616
  SUPPORTED_RATIOS = [
165299
165617
  { value: "16:9", ratio: 16 / 9 },
@@ -165337,14 +165655,14 @@ function signalAbortError(signal) {
165337
165655
  return reason instanceof Error ? reason : new Error("Poll aborted");
165338
165656
  }
165339
165657
  function defaultAbortableSleep(signal) {
165340
- return (ms) => new Promise((resolve60, reject) => {
165658
+ return (ms) => new Promise((resolve61, reject) => {
165341
165659
  const onAbort = () => {
165342
165660
  clearTimeout(timer);
165343
165661
  reject(signalAbortError(signal));
165344
165662
  };
165345
165663
  const timer = setTimeout(() => {
165346
165664
  signal?.removeEventListener("abort", onAbort);
165347
- resolve60();
165665
+ resolve61();
165348
165666
  }, ms);
165349
165667
  signal?.addEventListener("abort", onAbort, { once: true });
165350
165668
  });
@@ -165419,7 +165737,7 @@ async function downloadToFile(url, destPath, options = {}) {
165419
165737
  return { path: destPath, bytes };
165420
165738
  }
165421
165739
  function waitForDrain(file, signal) {
165422
- return new Promise((resolve60, reject) => {
165740
+ return new Promise((resolve61, reject) => {
165423
165741
  const cleanup = () => {
165424
165742
  file.off("drain", onDrain);
165425
165743
  file.off("error", onError);
@@ -165428,7 +165746,7 @@ function waitForDrain(file, signal) {
165428
165746
  };
165429
165747
  const onDrain = () => {
165430
165748
  cleanup();
165431
- resolve60();
165749
+ resolve61();
165432
165750
  };
165433
165751
  const onError = (err) => {
165434
165752
  cleanup();
@@ -165450,10 +165768,10 @@ function waitForDrain(file, signal) {
165450
165768
  });
165451
165769
  }
165452
165770
  function closeFile(file) {
165453
- return new Promise((resolve60) => {
165771
+ return new Promise((resolve61) => {
165454
165772
  const done = () => {
165455
165773
  file.off("error", done);
165456
- resolve60();
165774
+ resolve61();
165457
165775
  };
165458
165776
  file.once("error", done);
165459
165777
  file.end(() => done());
@@ -165863,8 +166181,8 @@ async function startLoopback(opts) {
165863
166181
  const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
165864
166182
  let resolveResult;
165865
166183
  let rejectResult;
165866
- const result = new Promise((resolve60, reject) => {
165867
- resolveResult = resolve60;
166184
+ const result = new Promise((resolve61, reject) => {
166185
+ resolveResult = resolve61;
165868
166186
  rejectResult = reject;
165869
166187
  });
165870
166188
  let redirectUri = "";
@@ -165880,7 +166198,7 @@ async function startLoopback(opts) {
165880
166198
  closed = true;
165881
166199
  clearTimeout(timer);
165882
166200
  server.closeAllConnections?.();
165883
- await new Promise((resolve60) => server.close(() => resolve60()));
166201
+ await new Promise((resolve61) => server.close(() => resolve61()));
165884
166202
  };
165885
166203
  const timer = setTimeout(() => {
165886
166204
  rejectResult(new Error(`OAuth callback timed out after ${timeoutMs}ms`));
@@ -165891,11 +166209,11 @@ async function startLoopback(opts) {
165891
166209
  return { result, redirectUri, close };
165892
166210
  }
165893
166211
  async function listen(server, port) {
165894
- await new Promise((resolve60, reject) => {
166212
+ await new Promise((resolve61, reject) => {
165895
166213
  server.once("error", reject);
165896
166214
  server.listen(port, "127.0.0.1", () => {
165897
166215
  server.off("error", reject);
165898
- resolve60();
166216
+ resolve61();
165899
166217
  });
165900
166218
  });
165901
166219
  }
@@ -165985,11 +166303,11 @@ async function openBrowser2(url) {
165985
166303
  return { opened: false };
165986
166304
  }
165987
166305
  try {
165988
- const open2 = (await import("open")).default;
165989
- await open2(url);
166306
+ const open3 = (await import("open")).default;
166307
+ await open3(url);
165990
166308
  return { opened: true };
165991
166309
  } catch (err) {
165992
- printManualInstructions(url, err instanceof Error ? err.message : String(err));
166310
+ printManualInstructions(url, normalizeErrorMessage(err));
165993
166311
  return { opened: false };
165994
166312
  }
165995
166313
  }
@@ -166006,6 +166324,7 @@ var init_browser2 = __esm({
166006
166324
  "src/auth/browser.ts"() {
166007
166325
  "use strict";
166008
166326
  init_colors();
166327
+ init_errorMessage();
166009
166328
  }
166010
166329
  });
166011
166330
 
@@ -166932,7 +167251,7 @@ async function maybeUploadProject(client, source, asJson, idempotencyKey) {
166932
167251
  try {
166933
167252
  archive = createPublishArchive(project.dir);
166934
167253
  } catch (err) {
166935
- const msg = err instanceof Error ? err.message : String(err);
167254
+ const msg = normalizeErrorMessage(err);
166936
167255
  errorBox("Zip failed", msg, "Check the project for missing files or unreadable permissions.");
166937
167256
  process.exit(1);
166938
167257
  }
@@ -167068,7 +167387,7 @@ async function streamVideo(url, destPath, asJson) {
167068
167387
  }
167069
167388
  return { bytes: result.bytes };
167070
167389
  } catch (err) {
167071
- const message = err instanceof Error ? err.message : String(err);
167390
+ const message = normalizeErrorMessage(err);
167072
167391
  errorBox(
167073
167392
  "Download failed",
167074
167393
  message,
@@ -167086,6 +167405,7 @@ var init_render3 = __esm({
167086
167405
  init_colors();
167087
167406
  init_format();
167088
167407
  init_project();
167408
+ init_errorMessage();
167089
167409
  init_publishProject();
167090
167410
  init_variables();
167091
167411
  init_updateCheck();
@@ -167878,7 +168198,7 @@ async function collectApiKey(inline) {
167878
168198
  return await promptForKey();
167879
168199
  }
167880
168200
  async function readAllWithTimeout(stream, timeoutMs) {
167881
- return await new Promise((resolve60, reject) => {
168201
+ return await new Promise((resolve61, reject) => {
167882
168202
  const chunks = [];
167883
168203
  const timer = setTimeout(() => {
167884
168204
  reject(new Error(`Timed out waiting for stdin (${timeoutMs}ms). Pipe the key explicitly.`));
@@ -167888,7 +168208,7 @@ async function readAllWithTimeout(stream, timeoutMs) {
167888
168208
  });
167889
168209
  stream.on("end", () => {
167890
168210
  clearTimeout(timer);
167891
- resolve60(Buffer.concat(chunks).toString("utf8"));
168211
+ resolve61(Buffer.concat(chunks).toString("utf8"));
167892
168212
  });
167893
168213
  stream.on("error", (err) => {
167894
168214
  clearTimeout(timer);
@@ -168258,8 +168578,8 @@ async function confirmInteractive(prompt) {
168258
168578
  if (!process.stdin.isTTY) return false;
168259
168579
  const { createInterface: createInterface3 } = await import("readline");
168260
168580
  const rl = createInterface3({ input: process.stdin, output: process.stdout });
168261
- const answer = await new Promise((resolve60) => {
168262
- rl.question(prompt, (line) => resolve60(line));
168581
+ const answer = await new Promise((resolve61) => {
168582
+ rl.question(prompt, (line) => resolve61(line));
168263
168583
  });
168264
168584
  rl.close();
168265
168585
  return /^y(es)?$/i.test(answer.trim());
@@ -168849,6 +169169,10 @@ var init_help = __esm({
168849
169169
  title: "Project",
168850
169170
  commands: [
168851
169171
  ["lint", "Validate a composition for common mistakes"],
169172
+ [
169173
+ "validate",
169174
+ "Runtime-validate a composition in headless Chrome (JS errors, missing assets, contrast)"
169175
+ ],
168852
169176
  ["beats", "Detect beats in the music track and write beats/<audio>.json"],
168853
169177
  ["inspect", "Inspect rendered visual layout across the timeline"],
168854
169178
  ["snapshot", "Capture key frames as PNG screenshots for visual verification"],
@@ -168978,10 +169302,10 @@ if (rootVersionRequested) {
168978
169302
  process.exit(0);
168979
169303
  }
168980
169304
  try {
168981
- const { readFileSync: readFileSync67 } = await import("fs");
168982
- const { resolve: resolve60 } = await import("path");
168983
- const envPath = resolve60(process.cwd(), ".env");
168984
- const envContent = readFileSync67(envPath, "utf-8");
169305
+ const { readFileSync: readFileSync66 } = await import("fs");
169306
+ const { resolve: resolve61 } = await import("path");
169307
+ const envPath = resolve61(process.cwd(), ".env");
169308
+ const envContent = readFileSync66(envPath, "utf-8");
168985
169309
  for (const rawLine of envContent.split("\n")) {
168986
169310
  let line = rawLine.trim();
168987
169311
  if (!line || line.startsWith("#")) continue;