hyperframes 0.8.51 → 0.8.53-desktop.0

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.8.51" : "0.0.0-dev";
53
+ VERSION = true ? "0.8.53-desktop.0" : "0.0.0-dev";
54
54
  }
55
55
  });
56
56
 
@@ -17372,9 +17372,9 @@ var require_main2 = __commonJS({
17372
17372
  }
17373
17373
  });
17374
17374
 
17375
- // ../../node_modules/.bun/@babel+parser@7.29.3/node_modules/@babel/parser/lib/index.js
17375
+ // ../../node_modules/.bun/@babel+parser@7.29.9/node_modules/@babel/parser/lib/index.js
17376
17376
  var require_lib = __commonJS({
17377
- "../../node_modules/.bun/@babel+parser@7.29.3/node_modules/@babel/parser/lib/index.js"(exports) {
17377
+ "../../node_modules/.bun/@babel+parser@7.29.9/node_modules/@babel/parser/lib/index.js"(exports) {
17378
17378
  "use strict";
17379
17379
  Object.defineProperty(exports, "__esModule", {
17380
17380
  value: true
@@ -17616,6 +17616,7 @@ var require_lib = __commonJS({
17616
17616
  SloppyFunctionAnnexB: "In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement.",
17617
17617
  SourcePhaseImportRequiresDefault: 'Only `import source x from "./module"` is valid.',
17618
17618
  StaticPrototype: "Classes may not have static property named prototype.",
17619
+ SuperCallNotNewExpression: "Cannot use new with super(...).",
17619
17620
  SuperNotAllowed: "`super()` is only valid inside a class constructor of a subclass. Maybe a typo in the method name ('constructor') or not extending another class?",
17620
17621
  SuperPrivateField: "Private fields can't be accessed on super.",
17621
17622
  TrailingDecorator: "Decorators must be attached to a class element.",
@@ -17645,7 +17646,6 @@ var require_lib = __commonJS({
17645
17646
  UnexpectedTokenUnaryExponentiation: "Illegal expression. Wrap left hand side or entire exponentiation in parentheses.",
17646
17647
  UnexpectedUsingDeclaration: "Using declaration cannot appear in the top level when source type is `script` or in the bare case statement.",
17647
17648
  UnexpectedVoidPattern: "Unexpected void binding.",
17648
- UnsupportedBind: "Binding should be performed on object property.",
17649
17649
  UnsupportedDecoratorExport: "A decorated export must export a class declaration.",
17650
17650
  UnsupportedDefaultExport: "Only expressions, functions or classes are allowed as the `default` export.",
17651
17651
  UnsupportedImport: "`import` can only be used in `import()` or `import.meta`.",
@@ -17713,6 +17713,10 @@ var require_lib = __commonJS({
17713
17713
  PrimaryTopicNotAllowed: "Topic reference was used in a lexical context without topic binding.",
17714
17714
  PrimaryTopicRequiresSmartPipeline: 'Topic reference is used, but the pipelineOperator plugin was not passed a "proposal": "hack" or "smart" option.'
17715
17715
  });
17716
+ var FunctionBindErrors = {
17717
+ UnsupportedBind: "Binding should be performed on object property.",
17718
+ UnsupportedBindRHS: "The right-hand side of binding can not be super or import."
17719
+ };
17716
17720
  var _excluded = ["message"];
17717
17721
  function defineHidden(obj, key2, value) {
17718
17722
  Object.defineProperty(obj, key2, {
@@ -17801,7 +17805,7 @@ var require_lib = __commonJS({
17801
17805
  }
17802
17806
  return ParseErrorConstructors;
17803
17807
  }
17804
- var Errors = Object.assign({}, ParseErrorEnum(ModuleErrors), ParseErrorEnum(StandardErrors), ParseErrorEnum(StrictModeErrors), ParseErrorEnum(ParseExpressionErrors), ParseErrorEnum`pipelineOperator`(PipelineOperatorErrors));
17808
+ var Errors = Object.assign({}, ParseErrorEnum(ModuleErrors), ParseErrorEnum(StandardErrors), ParseErrorEnum(StrictModeErrors), ParseErrorEnum(ParseExpressionErrors), ParseErrorEnum`pipelineOperator`(PipelineOperatorErrors), ParseErrorEnum`functionBind`(FunctionBindErrors));
17805
17809
  function createDefaultOptions() {
17806
17810
  return {
17807
17811
  sourceType: "script",
@@ -20422,13 +20426,15 @@ var require_lib = __commonJS({
20422
20426
  const arrows = [];
20423
20427
  while (stack.length !== 0) {
20424
20428
  const node2 = stack.pop();
20425
- if (node2.type === "ArrowFunctionExpression" && node2.body.type !== "BlockStatement") {
20429
+ if (node2.type === "ArrowFunctionExpression") {
20426
20430
  if (node2.typeParameters || !node2.returnType) {
20427
20431
  this.finishArrowValidation(node2);
20428
20432
  } else {
20429
20433
  arrows.push(node2);
20430
20434
  }
20431
- stack.push(node2.body);
20435
+ if (node2.body.type !== "BlockStatement") {
20436
+ stack.push(node2.body);
20437
+ }
20432
20438
  } else if (node2.type === "ConditionalExpression") {
20433
20439
  stack.push(node2.consequent);
20434
20440
  stack.push(node2.alternate);
@@ -27584,8 +27590,11 @@ var require_lib = __commonJS({
27584
27590
  }
27585
27591
  }
27586
27592
  fillOptionalPropertiesForTSESLint(node) {
27587
- var _node$directive, _node$decorators, _node$optional, _node$typeAnnotation, _node$accessibility, _node$decorators2, _node$override, _node$readonly, _node$static, _node$declare, _node$returnType, _node$typeParameters, _node$optional2, _node$optional3, _node$accessibility2, _node$readonly2, _node$static2, _node$declare2, _node$definite, _node$readonly3, _node$typeAnnotation2, _node$accessibility3, _node$decorators3, _node$override2, _node$optional4, _node$id, _node$abstract, _node$declare3, _node$decorators4, _node$implements, _node$superTypeArgume, _node$typeParameters2, _node$declare4, _node$definite2, _node$const, _node$declare5, _node$computed, _node$qualifier, _node$options, _node$declare6, _node$extends, _node$optional5, _node$readonly4, _node$declare7, _node$global, _node$const2, _node$in, _node$out;
27593
+ var _node$phase, _node$directive, _node$decorators, _node$optional, _node$typeAnnotation, _node$accessibility, _node$decorators2, _node$override, _node$readonly, _node$static, _node$declare, _node$returnType, _node$typeParameters, _node$optional2, _node$optional3, _node$accessibility2, _node$readonly2, _node$static2, _node$declare2, _node$definite, _node$readonly3, _node$typeAnnotation2, _node$accessibility3, _node$decorators3, _node$override2, _node$optional4, _node$id, _node$abstract, _node$declare3, _node$decorators4, _node$implements, _node$superTypeArgume, _node$typeParameters2, _node$declare4, _node$definite2, _node$const, _node$declare5, _node$computed, _node$qualifier, _node$options, _node$declare6, _node$extends, _node$optional5, _node$readonly4, _node$declare7, _node$global, _node$const2, _node$in, _node$out;
27588
27594
  switch (node.type) {
27595
+ case "ImportDeclaration":
27596
+ (_node$phase = node.phase) != null ? _node$phase : node.phase = null;
27597
+ return;
27589
27598
  case "ExpressionStatement":
27590
27599
  (_node$directive = node.directive) != null ? _node$directive : node.directive = void 0;
27591
27600
  return;
@@ -28482,7 +28491,7 @@ var require_lib = __commonJS({
28482
28491
  type
28483
28492
  } = this.state;
28484
28493
  if (!noCalls && type === 15) {
28485
- return this.parseBind(base2, startLoc, noCalls, state);
28494
+ return this.parseBind(base2, startLoc, state);
28486
28495
  } else if (tokenIsTemplate(type)) {
28487
28496
  return this.parseTaggedTemplateExpression(base2, startLoc, state);
28488
28497
  }
@@ -28535,13 +28544,18 @@ var require_lib = __commonJS({
28535
28544
  return this.finishNode(node, "MemberExpression");
28536
28545
  }
28537
28546
  }
28538
- parseBind(base2, startLoc, noCalls, state) {
28547
+ parseBind(base2, startLoc, state) {
28539
28548
  const node = this.startNodeAt(startLoc);
28540
28549
  node.object = base2;
28541
28550
  this.next();
28542
- node.callee = this.parseNoCallExpr();
28551
+ const isImport = this.match(83);
28552
+ const callee = this.parseNoCallExpr();
28553
+ if (callee.type === "Super" || isImport && callee.type === "ImportExpression" || callee.type === "Import") {
28554
+ throw this.raise(Errors.UnsupportedBindRHS, callee);
28555
+ }
28556
+ node.callee = callee;
28543
28557
  state.stop = true;
28544
- return this.parseSubscripts(this.finishNode(node, "BindExpression"), startLoc, noCalls);
28558
+ return this.parseSubscripts(this.finishNode(node, "BindExpression"), startLoc, false);
28545
28559
  }
28546
28560
  parseCoverCallAndAsyncArrowHead(base2, startLoc, state, optional) {
28547
28561
  const oldMaybeInArrowParameters = this.state.maybeInArrowParameters;
@@ -29124,9 +29138,12 @@ var require_lib = __commonJS({
29124
29138
  const isImport = this.match(83);
29125
29139
  const callee = this.parseNoCallExpr();
29126
29140
  node.callee = callee;
29127
- if (isImport && (callee.type === "Import" || callee.type === "ImportExpression")) {
29141
+ if (isImport && callee.type === "ImportExpression" || callee.type === "Import") {
29128
29142
  this.raise(Errors.ImportCallNotNewExpression, callee);
29129
29143
  }
29144
+ if (callee.type === "Super") {
29145
+ this.raise(Errors.SuperCallNotNewExpression, callee);
29146
+ }
29130
29147
  }
29131
29148
  parseTemplateElement(isTagged) {
29132
29149
  const {
@@ -65480,6 +65497,25 @@ var init_diagnostics2 = __esm({
65480
65497
  }
65481
65498
  });
65482
65499
 
65500
+ // ../engine/src/services/chromeHostCeiling.ts
65501
+ import { release } from "os";
65502
+ function chromeMajorCeiling(hostPlatform = process.platform, hostRelease = release()) {
65503
+ if (hostPlatform !== "darwin") return void 0;
65504
+ return Number.parseInt(hostRelease, 10) < 22 ? MACOS_12_LAST_CHROME_MAJOR : void 0;
65505
+ }
65506
+ function exceedsChromeCeiling(versionName, ceiling) {
65507
+ if (ceiling === void 0) return false;
65508
+ const major = Number.parseInt(versionName.slice(versionName.indexOf("-") + 1), 10);
65509
+ return major > ceiling;
65510
+ }
65511
+ var MACOS_12_LAST_CHROME_MAJOR;
65512
+ var init_chromeHostCeiling = __esm({
65513
+ "../engine/src/services/chromeHostCeiling.ts"() {
65514
+ "use strict";
65515
+ MACOS_12_LAST_CHROME_MAJOR = 150;
65516
+ }
65517
+ });
65518
+
65483
65519
  // ../engine/src/services/systemMemory.ts
65484
65520
  import { readFileSync as readFileSync2 } from "fs";
65485
65521
  import { totalmem } from "os";
@@ -65763,11 +65799,13 @@ function isDrawElementPlatform(platform11) {
65763
65799
  function resolveDefaultDrawElement(args) {
65764
65800
  if (!args.useDrawElement) return false;
65765
65801
  if (args.explicitOptIn) return true;
65802
+ if (args.chromeCeiling !== void 0) return false;
65766
65803
  if (!isDrawElementPlatform(args.platform) || args.browserGpuMode === "software") return false;
65767
65804
  return args.workerEncode;
65768
65805
  }
65769
65806
  function explainDrawElementDisabled(args) {
65770
65807
  if (!isDrawElementPlatform(args.platform)) return "unsupported_platform";
65808
+ if (args.chromeCeiling !== void 0) return "old_chrome";
65771
65809
  if (args.browserGpuMode === "software") return "software_gpu";
65772
65810
  if (!args.workerEncode) return "worker_encode_off";
65773
65811
  return "disabled";
@@ -65909,7 +65947,8 @@ function resolveConfig(overrides) {
65909
65947
  explicitOptIn: explicitDrawElementOptIn,
65910
65948
  platform: process.platform,
65911
65949
  browserGpuMode: merged.browserGpuMode,
65912
- workerEncode: merged.enableDrawElementWorkerEncode
65950
+ workerEncode: merged.enableDrawElementWorkerEncode,
65951
+ chromeCeiling: chromeMajorCeiling()
65913
65952
  });
65914
65953
  const explicitForceScreenshotOptOut = env("PRODUCER_FORCE_SCREENSHOT") === "false" || overrides?.forceScreenshot === false;
65915
65954
  if (explicitForceScreenshotOptOut) {
@@ -65958,6 +65997,7 @@ var DEFAULT_CONFIG2, OPTIONAL_ENGINE_CONFIG_FIELDS, BOOLEAN_ENGINE_CONFIG_FIELDS
65958
65997
  var init_config2 = __esm({
65959
65998
  "../engine/src/config.ts"() {
65960
65999
  "use strict";
66000
+ init_chromeHostCeiling();
65961
66001
  init_systemMemory();
65962
66002
  init_vp9Options();
65963
66003
  DEFAULT_CONFIG2 = {
@@ -66345,8 +66385,10 @@ function findCachedHeadlessShell(baseDir) {
66345
66385
  const executable = cachedHeadlessShellExecutable();
66346
66386
  if (!executable) return void 0;
66347
66387
  try {
66388
+ const ceiling = chromeMajorCeiling();
66348
66389
  const versions = readdirSync(baseDir).sort(compareBrowserVersionsDescending);
66349
66390
  for (const version2 of versions) {
66391
+ if (exceedsChromeCeiling(version2, ceiling)) continue;
66350
66392
  const binary = join5(baseDir, version2, ...executable);
66351
66393
  if (existsSync3(binary)) return binary;
66352
66394
  }
@@ -66838,6 +66880,7 @@ var _puppeteer, CACHED_HEADLESS_SHELL_EXECUTABLES, ENABLE_BROWSER_POOL, BEGINFRA
66838
66880
  var init_browserManager = __esm({
66839
66881
  "../engine/src/services/browserManager.ts"() {
66840
66882
  "use strict";
66883
+ init_chromeHostCeiling();
66841
66884
  init_config2();
66842
66885
  init_systemMemory();
66843
66886
  init_browserLeasePool();
@@ -70502,7 +70545,7 @@ async function initDrawElementOrTransparentBackground(session, page, logInitPhas
70502
70545
  session.deGateReason = "unsupported_chrome";
70503
70546
  session.deFallbackTrigger = "unsupported_chrome";
70504
70547
  console.log(
70505
- `[engine] fast capture: falling back to ${session.launchCaptureMode} capture \u2014 this Chrome build does not implement canvas.drawElementImage (Dev/Canary-only feature, ~151+); run \`hyperframes browser ensure --force\` to fetch a supported build, or set HYPERFRAMES_BROWSER_PATH to one.`
70548
+ `[engine] fast capture: falling back to ${session.launchCaptureMode} capture \u2014 this Chrome build does not implement canvas.drawElementImage (Dev/Canary-only feature); run \`hyperframes browser ensure --force\` to fetch a supported build, or set HYPERFRAMES_BROWSER_PATH to one.`
70506
70549
  );
70507
70550
  await routeToFallback();
70508
70551
  return;
@@ -89611,7 +89654,9 @@ function warnAssetTooLargeToInline(assetPath, byteLength) {
89611
89654
  const mb = (byteLength / (1024 * 1024)).toFixed(1);
89612
89655
  console.warn(`[HyperFrames] Not inlining "${assetPath}" (${mb} MB exceeds the ${MAX_INLINE_ASSET_BYTES / (1024 * 1024)} MB inline limit). The bundle may not be self-contained.`);
89613
89656
  }
89614
- function maybeInlineRelativeAssetUrl(urlValue, projectDir) {
89657
+ function maybeInlineRelativeAssetUrl(urlValue, projectDir, inlineAssets) {
89658
+ if (!inlineAssets)
89659
+ return null;
89615
89660
  if (!urlValue || !isRelativeUrl(urlValue))
89616
89661
  return null;
89617
89662
  const { basePath, suffix } = splitUrlSuffix(urlValue.trim());
@@ -89667,7 +89712,7 @@ function rewriteColorGradingLutWithInlinedAssets(value, projectDir) {
89667
89712
  return value;
89668
89713
  const lut = Reflect.get(parsed, "lut");
89669
89714
  if (typeof lut === "string") {
89670
- const inlined2 = maybeInlineRelativeAssetUrl(lut, projectDir);
89715
+ const inlined2 = maybeInlineRelativeAssetUrl(lut, projectDir, true);
89671
89716
  if (!inlined2) {
89672
89717
  warnColorGradingLutNotInlined(lut);
89673
89718
  return value;
@@ -89680,7 +89725,7 @@ function rewriteColorGradingLutWithInlinedAssets(value, projectDir) {
89680
89725
  const lutSrc = Reflect.get(lut, "src");
89681
89726
  if (typeof lutSrc !== "string")
89682
89727
  return value;
89683
- const inlined = maybeInlineRelativeAssetUrl(lutSrc, projectDir);
89728
+ const inlined = maybeInlineRelativeAssetUrl(lutSrc, projectDir, true);
89684
89729
  if (!inlined) {
89685
89730
  warnColorGradingLutNotInlined(lutSrc);
89686
89731
  return value;
@@ -89688,7 +89733,7 @@ function rewriteColorGradingLutWithInlinedAssets(value, projectDir) {
89688
89733
  Reflect.set(lut, "src", inlined);
89689
89734
  return JSON.stringify(parsed);
89690
89735
  }
89691
- function rewriteSrcsetWithInlinedAssets(srcsetValue, projectDir) {
89736
+ function rewriteSrcsetWithInlinedAssets(srcsetValue, projectDir, inlineAssets) {
89692
89737
  if (!srcsetValue)
89693
89738
  return srcsetValue;
89694
89739
  return srcsetValue.split(",").map((rawCandidate) => {
@@ -89698,17 +89743,17 @@ function rewriteSrcsetWithInlinedAssets(srcsetValue, projectDir) {
89698
89743
  const parts = candidate.split(/\s+/);
89699
89744
  if (parts.length === 0)
89700
89745
  return candidate;
89701
- const maybeInlined = maybeInlineRelativeAssetUrl(parts[0] ?? "", projectDir);
89746
+ const maybeInlined = maybeInlineRelativeAssetUrl(parts[0] ?? "", projectDir, inlineAssets);
89702
89747
  if (maybeInlined)
89703
89748
  parts[0] = maybeInlined;
89704
89749
  return parts.join(" ");
89705
89750
  }).join(", ");
89706
89751
  }
89707
- function rewriteCssUrlsWithInlinedAssets(cssText, projectDir) {
89752
+ function rewriteCssUrlsWithInlinedAssets(cssText, projectDir, inlineAssets) {
89708
89753
  if (!cssText)
89709
89754
  return cssText;
89710
89755
  return cssText.replace(/\burl\(\s*(["']?)([^)"']+)\1\s*\)/g, (_full, quote, rawUrl) => {
89711
- const maybeInlined = maybeInlineRelativeAssetUrl((rawUrl || "").trim(), projectDir);
89756
+ const maybeInlined = maybeInlineRelativeAssetUrl((rawUrl || "").trim(), projectDir, inlineAssets);
89712
89757
  if (!maybeInlined)
89713
89758
  return _full;
89714
89759
  return `url(${quote || ""}${maybeInlined}${quote || ""})`;
@@ -90243,6 +90288,7 @@ async function bundleToSingleHtml(projectDir, options) {
90243
90288
  autoHealMissingCompositionIds(document2);
90244
90289
  coalesceHeadStylesAndBodyScripts(document2);
90245
90290
  injectTextRenderingRule(document2);
90291
+ const inlineAssets = options?.inlineAssets !== false;
90246
90292
  for (const el of [...document2.querySelectorAll("[src], [href], [poster], [xlink\\:href]")]) {
90247
90293
  for (const attr2 of ["src", "href", "poster", "xlink:href"]) {
90248
90294
  const value = el.getAttribute(attr2);
@@ -90250,7 +90296,7 @@ async function bundleToSingleHtml(projectDir, options) {
90250
90296
  continue;
90251
90297
  if (isExternalSvgFragmentUse(el, attr2, value))
90252
90298
  continue;
90253
- const inlined = maybeInlineRelativeAssetUrl(value, projectDir);
90299
+ const inlined = maybeInlineRelativeAssetUrl(value, projectDir, inlineAssets);
90254
90300
  if (inlined)
90255
90301
  el.setAttribute(attr2, inlined);
90256
90302
  }
@@ -90258,15 +90304,15 @@ async function bundleToSingleHtml(projectDir, options) {
90258
90304
  for (const el of [...document2.querySelectorAll("[srcset]")]) {
90259
90305
  const srcset = el.getAttribute("srcset");
90260
90306
  if (srcset)
90261
- el.setAttribute("srcset", rewriteSrcsetWithInlinedAssets(srcset, projectDir));
90307
+ el.setAttribute("srcset", rewriteSrcsetWithInlinedAssets(srcset, projectDir, inlineAssets));
90262
90308
  }
90263
90309
  for (const styleEl of document2.querySelectorAll("style")) {
90264
- styleEl.textContent = rewriteCssUrlsWithInlinedAssets(styleEl.textContent || "", projectDir);
90310
+ styleEl.textContent = rewriteCssUrlsWithInlinedAssets(styleEl.textContent || "", projectDir, inlineAssets);
90265
90311
  }
90266
90312
  for (const el of [...document2.querySelectorAll("[style]")]) {
90267
- el.setAttribute("style", rewriteCssUrlsWithInlinedAssets(el.getAttribute("style") || "", projectDir));
90313
+ el.setAttribute("style", rewriteCssUrlsWithInlinedAssets(el.getAttribute("style") || "", projectDir, inlineAssets));
90268
90314
  }
90269
- if (options?.inlineColorGradingLuts !== false) {
90315
+ if (inlineAssets && options?.inlineColorGradingLuts !== false) {
90270
90316
  for (const el of [...document2.querySelectorAll(`[${HF_COLOR_GRADING_ATTR}]`)]) {
90271
90317
  const value = el.getAttribute(HF_COLOR_GRADING_ATTR);
90272
90318
  if (value) {
@@ -96523,6 +96569,7 @@ __export(src_exports, {
96523
96569
  captureFramesBatchPipelined: () => captureFramesBatchPipelined,
96524
96570
  captureScreenshotWithAlpha: () => captureScreenshotWithAlpha,
96525
96571
  cdpSessionCache: () => cdpSessionCache,
96572
+ chromeMajorCeiling: () => chromeMajorCeiling,
96526
96573
  classifyCaptureFailure: () => classifyCaptureFailure,
96527
96574
  classifyVideoExtractionError: () => classifyVideoExtractionError,
96528
96575
  cloneCaptureWarning: () => cloneCaptureWarning,
@@ -96675,6 +96722,7 @@ var init_src = __esm({
96675
96722
  init_config2();
96676
96723
  init_vp9Options();
96677
96724
  init_systemMemory();
96725
+ init_chromeHostCeiling();
96678
96726
  init_browserManager();
96679
96727
  init_protocolTimeoutErrorHint();
96680
96728
  init_pageNavigationTimeoutErrorHint();
@@ -96717,12 +96765,12 @@ var init_src = __esm({
96717
96765
  });
96718
96766
 
96719
96767
  // src/telemetry/platform.ts
96720
- import { platform, release } from "os";
96768
+ import { platform, release as release2 } from "os";
96721
96769
  import { readFileSync as readFileSync10 } from "fs";
96722
96770
  function detectWSL() {
96723
96771
  if (platform() !== "linux") return false;
96724
96772
  try {
96725
- const osRelease = release().toLowerCase();
96773
+ const osRelease = release2().toLowerCase();
96726
96774
  if (osRelease.includes("microsoft") || osRelease.includes("wsl")) return true;
96727
96775
  const procVersion = readFileSync10("/proc/version", "utf-8").toLowerCase();
96728
96776
  return procVersion.includes("microsoft") || procVersion.includes("wsl");
@@ -96738,7 +96786,7 @@ var init_platform = __esm({
96738
96786
 
96739
96787
  // src/telemetry/agent_runtime.ts
96740
96788
  import { existsSync as existsSync19, readFileSync as readFileSync11, statSync as statSync8 } from "fs";
96741
- import { platform as platform2, release as release2 } from "os";
96789
+ import { platform as platform2, release as release3 } from "os";
96742
96790
  function detectSandboxRuntime() {
96743
96791
  if (platform2() === "win32") return null;
96744
96792
  if (detectWSL()) return "wsl";
@@ -96797,7 +96845,7 @@ function detectAgentHints() {
96797
96845
  return { agent_hint, term_program, agent_env_hints };
96798
96846
  }
96799
96847
  function isGVisor() {
96800
- const kernel = release2();
96848
+ const kernel = release3();
96801
96849
  if (kernel.includes("gvisor")) return true;
96802
96850
  if (platform2() !== "linux") return false;
96803
96851
  try {
@@ -97017,7 +97065,7 @@ __export(system_exports, {
97017
97065
  getSystemMeta: () => getSystemMeta,
97018
97066
  parsePmsetPowerSource: () => parsePmsetPowerSource
97019
97067
  });
97020
- import { cpus as cpus2, freemem as freemem2, platform as platform3, release as release3 } from "os";
97068
+ import { cpus as cpus2, freemem as freemem2, platform as platform3, release as release4 } from "os";
97021
97069
  import { existsSync as existsSync20, readFileSync as readFileSync12, statfsSync } from "fs";
97022
97070
  import { execSync as execSync2 } from "child_process";
97023
97071
  function bytesToMb(bytes) {
@@ -97030,7 +97078,7 @@ function getSystemMeta() {
97030
97078
  const agent_runtime = detectAgentRuntime();
97031
97079
  const hints = agent_runtime === null ? detectAgentHints() : { agent_hint: null, term_program: null, agent_env_hints: null };
97032
97080
  cached2 = {
97033
- os_release: release3(),
97081
+ os_release: release4(),
97034
97082
  cpu_count: cpuInfo.length,
97035
97083
  cpu_model: firstCpu?.model?.trim() ?? null,
97036
97084
  cpu_speed: firstCpu?.speed ?? null,
@@ -97562,7 +97610,11 @@ function renderOutputShapeEventProperties(props) {
97562
97610
  function renderEnvironmentEventProperties(props) {
97563
97611
  return {
97564
97612
  ffmpeg_version_major: props.ffmpegVersionMajor,
97565
- browser_version_major: props.browserVersionMajor
97613
+ browser_version_major: props.browserVersionMajor,
97614
+ browser_build: props.browserInstall?.build,
97615
+ browser_path_ascii: props.browserInstall?.pathAscii,
97616
+ browser_path_length: props.browserInstall?.pathLength,
97617
+ browser_path_drive: props.browserInstall?.drive
97566
97618
  };
97567
97619
  }
97568
97620
  function redactTelemetryMessage(value) {
@@ -126139,7 +126191,7 @@ var init_dist9 = __esm({
126139
126191
  lease(entry, signal) {
126140
126192
  return new Promise((resolve510, reject2) => {
126141
126193
  let released = false;
126142
- const release4 = () => {
126194
+ const release5 = () => {
126143
126195
  if (released) return;
126144
126196
  released = true;
126145
126197
  signal.removeEventListener("abort", onAbort);
@@ -126154,17 +126206,17 @@ var init_dist9 = __esm({
126154
126206
  }
126155
126207
  };
126156
126208
  const onAbort = () => {
126157
- release4();
126209
+ release5();
126158
126210
  reject2(new DOMException("Aborted", "AbortError"));
126159
126211
  };
126160
126212
  signal.addEventListener("abort", onAbort, { once: true });
126161
126213
  entry.promise.then(
126162
126214
  (value) => {
126163
- release4();
126215
+ release5();
126164
126216
  resolve510(value);
126165
126217
  },
126166
126218
  (reason) => {
126167
- release4();
126219
+ release5();
126168
126220
  reject2(reason);
126169
126221
  }
126170
126222
  );
@@ -126724,301 +126776,10 @@ var init_studioRenderTelemetry = __esm({
126724
126776
  }
126725
126777
  });
126726
126778
 
126727
- // ../studio-server/dist/helpers/screenshotClip.js
126728
- var init_screenshotClip = __esm({
126729
- "../studio-server/dist/helpers/screenshotClip.js"() {
126730
- "use strict";
126731
- init_chunk_W2SBTCO2();
126732
- }
126733
- });
126734
-
126735
- // src/browser/windowsCrash.ts
126736
- function isWindowsChromeCrashError(errorMessage2) {
126737
- if (!/Failed to launch the browser process/i.test(errorMessage2)) return false;
126738
- return errorMessage2.includes(STATUS_STACK_BUFFER_OVERRUN_DEC) || STATUS_STACK_BUFFER_OVERRUN_HEX.test(errorMessage2) || STATUS_STACK_BUFFER_OVERRUN_NAME.test(errorMessage2);
126739
- }
126740
- function windowsChromeCrashRemediation(errorMessage2) {
126741
- if (process.platform !== "win32") return void 0;
126742
- if (!isWindowsChromeCrashError(errorMessage2)) return void 0;
126743
- return [
126744
- "chrome-headless-shell crashed at launch (Windows STATUS_STACK_BUFFER_OVERRUN, exit 0xC0000409 / 3221225595).",
126745
- "The pinned Chromium build is not stable on this Windows host; point hyperframes at your installed Chrome instead:",
126746
- "",
126747
- ' set HYPERFRAMES_BROWSER_PATH="C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe"',
126748
- "",
126749
- "Then re-run your command. Any Chrome build works for the screenshot capture path; install a real chrome-headless-shell later if you need the perf-optimized BeginFrame path."
126750
- ].join("\n");
126751
- }
126752
- var STATUS_STACK_BUFFER_OVERRUN_DEC, STATUS_STACK_BUFFER_OVERRUN_HEX, STATUS_STACK_BUFFER_OVERRUN_NAME;
126753
- var init_windowsCrash = __esm({
126754
- "src/browser/windowsCrash.ts"() {
126755
- "use strict";
126756
- STATUS_STACK_BUFFER_OVERRUN_DEC = "3221225595";
126757
- STATUS_STACK_BUFFER_OVERRUN_HEX = /0x[cC]0000409/;
126758
- STATUS_STACK_BUFFER_OVERRUN_NAME = /STATUS_STACK_BUFFER_OVERRUN/i;
126759
- }
126760
- });
126761
-
126762
- // src/utils/dom.ts
126763
- var dom_exports = {};
126764
- __export(dom_exports, {
126765
- ensureDOMParser: () => ensureDOMParser
126766
- });
126767
- function ensureDOMParser() {
126768
- if (typeof globalThis.DOMParser === "undefined") {
126769
- globalThis.DOMParser = DOMParser2;
126770
- }
126771
- }
126772
- var init_dom = __esm({
126773
- "src/utils/dom.ts"() {
126774
- "use strict";
126775
- init_esm10();
126776
- }
126777
- });
126778
-
126779
- // src/utils/compositionViewport.ts
126780
- function parseViewportDimension(value) {
126781
- if (!value) return null;
126782
- const parsed = Number.parseInt(value, 10);
126783
- if (!Number.isFinite(parsed) || parsed <= 0) return null;
126784
- return Math.min(parsed, MAX_VIEWPORT_DIMENSION);
126785
- }
126786
- function findCompositionDimensions(html) {
126787
- ensureDOMParser();
126788
- const doc = new DOMParser().parseFromString(html, "text/html");
126789
- const root = doc.querySelector("[data-composition-id][data-width][data-height]");
126790
- if (!root) return null;
126791
- const width = parseViewportDimension(root.getAttribute("data-width"));
126792
- const height = parseViewportDimension(root.getAttribute("data-height"));
126793
- if (width === null || height === null) return null;
126794
- return { width, height };
126795
- }
126796
- function resolveCompositionViewportFromHtml(html) {
126797
- return findCompositionDimensions(html) ?? DEFAULT_VIEWPORT;
126798
- }
126799
- var DEFAULT_VIEWPORT, MAX_VIEWPORT_DIMENSION;
126800
- var init_compositionViewport = __esm({
126801
- "src/utils/compositionViewport.ts"() {
126802
- "use strict";
126803
- init_dom();
126804
- DEFAULT_VIEWPORT = { width: 1920, height: 1080 };
126805
- MAX_VIEWPORT_DIMENSION = 4096;
126806
- }
126807
- });
126808
-
126809
- // src/utils/compositionFps.ts
126810
- import { readFileSync as readFileSync27 } from "fs";
126811
- import { join as join41 } from "path";
126812
- function readCompositionFps(html) {
126813
- let doc;
126814
- try {
126815
- doc = parseHTML(html).document;
126816
- } catch {
126817
- return null;
126818
- }
126819
- const explicitRoot = doc.querySelector('[data-composition-id][data-root="true"]');
126820
- const root = explicitRoot ?? Array.from(doc.querySelectorAll("[data-composition-id]")).find(
126821
- (el) => !el.parentElement?.closest("[data-composition-id]")
126822
- ) ?? null;
126823
- const raw = root?.getAttribute("data-fps")?.trim();
126824
- return raw ? raw : null;
126825
- }
126826
- function readAllowedCompositionFpsFromDir(projectDir, allowed) {
126827
- let html;
126828
- try {
126829
- html = readFileSync27(join41(projectDir, "index.html"), "utf8");
126830
- } catch {
126831
- return null;
126832
- }
126833
- const raw = readCompositionFps(html);
126834
- if (raw == null) return null;
126835
- const n3 = Number(raw);
126836
- return Number.isInteger(n3) && allowed.includes(n3) ? n3 : null;
126837
- }
126838
- var init_compositionFps = __esm({
126839
- "src/utils/compositionFps.ts"() {
126840
- "use strict";
126841
- init_esm10();
126842
- }
126843
- });
126844
-
126845
- // src/utils/renderArgs.ts
126846
- import { readFileSync as readFileSync28 } from "fs";
126847
- import { resolve as resolve26, sep as sep10 } from "path";
126848
- function parseBrowserTimeoutMsArg(raw) {
126849
- if (raw == null) return { ok: true, value: void 0 };
126850
- const parsed = Number(raw);
126851
- if (!Number.isFinite(parsed)) {
126852
- return { ok: false, error: { kind: "not-a-number", raw } };
126853
- }
126854
- if (parsed <= 0) {
126855
- return { ok: false, error: { kind: "not-positive", raw } };
126856
- }
126857
- if (parsed > MAX_PAGE_NAVIGATION_TIMEOUT_SECONDS) {
126858
- return { ok: false, error: { kind: "too-large", raw } };
126859
- }
126860
- const ms = Math.round(parsed * 1e3);
126861
- if (ms < MIN_PAGE_NAVIGATION_TIMEOUT_MS) {
126862
- return { ok: false, error: { kind: "too-small", raw } };
126863
- }
126864
- return { ok: true, value: ms };
126865
- }
126866
- function browserTimeoutErrorMessage(error) {
126867
- const title = "Invalid browser-timeout";
126868
- switch (error.kind) {
126869
- case "not-a-number":
126870
- return {
126871
- title,
126872
- message: `Got "${error.raw}", which is not a number. Pass a positive number of seconds (e.g. 180).`
126873
- };
126874
- case "not-positive":
126875
- return {
126876
- title,
126877
- message: `Got "${error.raw}" seconds, which is not positive. Pass a positive number of seconds (e.g. 180).`
126878
- };
126879
- case "too-small":
126880
- return {
126881
- title,
126882
- message: `Got "${error.raw}" seconds, which rounds to 0 ms. Puppeteer treats 0 as 'no timeout' \u2014 pass a value that rounds to at least 1 ms.`
126883
- };
126884
- case "too-large":
126885
- return {
126886
- title,
126887
- message: `Got "${error.raw}" seconds, which exceeds the ${MAX_PAGE_NAVIGATION_TIMEOUT_SECONDS}s (24h) cap. Node's setTimeout overflows for larger values.`
126888
- };
126889
- }
126890
- }
126891
- function resolveBrowserTimeoutMsArg(raw) {
126892
- const result = parseBrowserTimeoutMsArg(raw);
126893
- if (!result.ok) {
126894
- const { title, message, hint: hint2 } = browserTimeoutErrorMessage(result.error);
126895
- errorBox(title, message, hint2);
126896
- failUsage();
126897
- }
126898
- return result.value;
126899
- }
126900
- function resolveDiagnosticNavigationTimeoutMs(env = process.env, minimumTimeoutMs = 0) {
126901
- const parsed = Number(env.PRODUCER_PAGE_NAVIGATION_TIMEOUT_MS);
126902
- const configured = Number.isFinite(parsed) && parsed > 0 ? parsed : 1e4;
126903
- return Math.max(configured, minimumTimeoutMs);
126904
- }
126905
- function normalizeCompositionEntryArg(raw) {
126906
- const trimmed = raw?.trim().replace(/^\.\//, "") || void 0;
126907
- return !trimmed || trimmed === "." ? void 0 : trimmed;
126908
- }
126909
- function hasExplicitCompositionArg(raw) {
126910
- return normalizeCompositionEntryArg(raw) !== void 0;
126911
- }
126912
- function parseCompositionEntryArg(raw, projectDir, stat) {
126913
- const trimmed = normalizeCompositionEntryArg(raw);
126914
- if (!trimmed) return { ok: true, value: void 0 };
126915
- const absProjectDir = resolve26(projectDir);
126916
- const entryPath = resolve26(absProjectDir, trimmed);
126917
- if (entryPath !== absProjectDir && !entryPath.startsWith(absProjectDir + sep10)) {
126918
- return { ok: false, error: { kind: "outside-project", entryFile: trimmed } };
126919
- }
126920
- let entryStat;
126921
- try {
126922
- entryStat = stat(entryPath);
126923
- } catch {
126924
- return { ok: false, error: { kind: "not-found", entryFile: trimmed } };
126925
- }
126926
- if (!entryStat.isFile()) {
126927
- return { ok: false, error: { kind: "not-a-file", entryFile: trimmed } };
126928
- }
126929
- return { ok: true, value: trimmed };
126930
- }
126931
- function compositionEntryErrorMessage(error) {
126932
- switch (error.kind) {
126933
- case "outside-project":
126934
- return {
126935
- title: "Invalid composition path",
126936
- message: `Entry file must stay inside the project directory: ${error.entryFile}`
126937
- };
126938
- case "not-found":
126939
- return {
126940
- title: "Composition not found",
126941
- message: `"${error.entryFile}" does not exist in the project directory.`,
126942
- hint: "Pass a path to a .html file relative to the project root (e.g. compositions/intro.html)."
126943
- };
126944
- case "not-a-file":
126945
- return {
126946
- title: "Invalid composition path",
126947
- message: `"${error.entryFile}" is a directory, not an .html file.`,
126948
- hint: "Pass a path to a .html file (e.g. compositions/intro.html), or omit --composition to render index.html."
126949
- };
126950
- }
126951
- }
126952
- function resolveCompositionEntryArg(raw, projectDir, stat) {
126953
- const result = parseCompositionEntryArg(raw, projectDir, stat);
126954
- if (!result.ok) {
126955
- const { title, message, hint: hint2 } = compositionEntryErrorMessage(result.error);
126956
- errorBox(title, message, hint2);
126957
- failUsage();
126958
- }
126959
- return result.value;
126960
- }
126961
- function resolveDefaultFpsArg(explicitFps, projectDir, indexPath2, entryFile) {
126962
- if (explicitFps != null) return explicitFps;
126963
- try {
126964
- const fpsSourcePath = entryFile ? resolve26(projectDir, entryFile) : indexPath2;
126965
- const declared = readCompositionFps(readFileSync28(fpsSourcePath, "utf8"));
126966
- if (declared != null && parseFps(declared).ok) {
126967
- return declared;
126968
- }
126969
- } catch {
126970
- }
126971
- return void 0;
126972
- }
126973
- function parseGifLoopArg(raw) {
126974
- if (raw === void 0) return { ok: true, value: void 0 };
126975
- const trimmed = raw.trim();
126976
- if (trimmed.length === 0) {
126977
- return { ok: false, message: "GIF loop count must not be empty." };
126978
- }
126979
- const parsed = Number(trimmed);
126980
- if (!Number.isInteger(parsed) || parsed < 0 || parsed > 65535) {
126981
- return {
126982
- ok: false,
126983
- message: `Got "${raw}". GIF loop count must be an integer between 0 and 65535.`
126984
- };
126985
- }
126986
- return { ok: true, value: parsed };
126987
- }
126988
- function parseHlsSegmentSecondsArg(raw) {
126989
- if (raw === void 0) return { ok: true, value: void 0 };
126990
- const trimmed = raw.trim();
126991
- if (trimmed.length === 0) {
126992
- return { ok: false, message: "HLS segment length must not be empty." };
126993
- }
126994
- const parsed = Number(trimmed);
126995
- if (!Number.isInteger(parsed) || parsed < 1 || parsed > MAX_HLS_SEGMENT_SECONDS) {
126996
- return {
126997
- ok: false,
126998
- message: `Got "${raw}". HLS segment length must be a whole number of seconds between 1 and ${MAX_HLS_SEGMENT_SECONDS}.`
126999
- };
127000
- }
127001
- return { ok: true, value: parsed };
127002
- }
127003
- var MIN_PAGE_NAVIGATION_TIMEOUT_MS, MAX_PAGE_NAVIGATION_TIMEOUT_SECONDS, MAX_HLS_SEGMENT_SECONDS;
127004
- var init_renderArgs = __esm({
127005
- "src/utils/renderArgs.ts"() {
127006
- "use strict";
127007
- init_commandResult();
127008
- init_dist3();
127009
- init_format();
127010
- init_compositionFps();
127011
- MIN_PAGE_NAVIGATION_TIMEOUT_MS = 1;
127012
- MAX_PAGE_NAVIGATION_TIMEOUT_SECONDS = 86400;
127013
- MAX_HLS_SEGMENT_SECONDS = 60;
127014
- }
127015
- });
127016
-
127017
126779
  // src/browser/manager.ts
127018
126780
  var manager_exports2 = {};
127019
126781
  __export(manager_exports2, {
127020
126782
  CACHE_DIR: () => CACHE_DIR2,
127021
- CHROME_VERSION: () => CHROME_VERSION,
127022
126783
  _resetSystemFallbackWarnForTests: () => _resetSystemFallbackWarnForTests,
127023
126784
  clearBrowser: () => clearBrowser,
127024
126785
  ensureBrowser: () => ensureBrowser,
@@ -127027,6 +126788,7 @@ __export(manager_exports2, {
127027
126788
  installWithCorruptArchiveRecovery: () => installWithCorruptArchiveRecovery,
127028
126789
  isCorruptArchiveError: () => isCorruptArchiveError,
127029
126790
  isLinuxArm: () => isLinuxArm,
126791
+ managedChromeVersion: () => managedChromeVersion,
127030
126792
  releaseOwnedBrowserInstallLock: () => releaseOwnedBrowserInstallLock,
127031
126793
  withInstallLock: () => withInstallLock
127032
126794
  });
@@ -127035,7 +126797,7 @@ import { randomUUID as randomUUID10 } from "crypto";
127035
126797
  import {
127036
126798
  existsSync as existsSync40,
127037
126799
  mkdirSync as mkdirSync17,
127038
- readFileSync as readFileSync29,
126800
+ readFileSync as readFileSync27,
127039
126801
  readdirSync as readdirSync18,
127040
126802
  rmSync as rmSync14,
127041
126803
  statSync as statSync17,
@@ -127044,7 +126806,7 @@ import {
127044
126806
  } from "fs";
127045
126807
  import { basename as basename9 } from "path";
127046
126808
  import { homedir as homedir11 } from "os";
127047
- import { join as join43 } from "path";
126809
+ import { join as join41 } from "path";
127048
126810
  async function loadPuppeteerBrowsers() {
127049
126811
  try {
127050
126812
  return await import("@puppeteer/browsers");
@@ -127056,6 +126818,9 @@ Fix: run \`npm install\` or \`bun install\` to restore missing packages, then re
127056
126818
  );
127057
126819
  }
127058
126820
  }
126821
+ function managedChromeVersion() {
126822
+ return chromeMajorCeiling() === void 0 ? CHROME_VERSION : MACOS_12_CHROME_VERSION;
126823
+ }
127059
126824
  function isErrno(err, code) {
127060
126825
  return err.code === code;
127061
126826
  }
@@ -127161,7 +126926,7 @@ function releaseOwnedBrowserInstallLock() {
127161
126926
  function releaseBrowserInstallLock(ownerToken) {
127162
126927
  if (ownedInstallLockToken === ownerToken) ownedInstallLockToken = void 0;
127163
126928
  try {
127164
- if (readFileSync29(INSTALL_LOCK_OWNER_FILE, "utf8") !== ownerToken) return;
126929
+ if (readFileSync27(INSTALL_LOCK_OWNER_FILE, "utf8") !== ownerToken) return;
127165
126930
  } catch {
127166
126931
  return;
127167
126932
  }
@@ -127208,7 +126973,7 @@ async function findFromHyperframesCache() {
127208
126973
  }
127209
126974
  const hostPlatform = detectBrowserPlatform();
127210
126975
  const match = installed.find(
127211
- (b2) => b2.browser === Browser.CHROMEHEADLESSSHELL && b2.buildId === CHROME_VERSION && b2.platform === hostPlatform
126976
+ (b2) => b2.browser === Browser.CHROMEHEADLESSSHELL && b2.buildId === managedChromeVersion() && b2.platform === hostPlatform
127212
126977
  );
127213
126978
  if (match && existsSync40(match.executablePath)) {
127214
126979
  return { result: { executablePath: match.executablePath, source: "cache" } };
@@ -127266,8 +127031,10 @@ function findFromPuppeteerCache() {
127266
127031
  } catch {
127267
127032
  return void 0;
127268
127033
  }
127034
+ const ceiling = chromeMajorCeiling();
127269
127035
  for (const version2 of versions) {
127270
- const binary = join43(PUPPETEER_CACHE_DIR, version2, ...executable);
127036
+ if (exceedsChromeCeiling(version2, ceiling)) continue;
127037
+ const binary = join41(PUPPETEER_CACHE_DIR, version2, ...executable);
127271
127038
  if (existsSync40(binary)) {
127272
127039
  return { executablePath: binary, source: "cache" };
127273
127040
  }
@@ -127457,7 +127224,7 @@ function browserPathHintForPlatform() {
127457
127224
  function wrapDownloadFailureWithBrowserPathHint(cause) {
127458
127225
  const original = normalizeErrorMessage(cause);
127459
127226
  const example = browserPathHintForPlatform();
127460
- const message = `Failed to download chrome-headless-shell ${CHROME_VERSION}: ${original}
127227
+ const message = `Failed to download chrome-headless-shell ${managedChromeVersion()}: ${original}
127461
127228
 
127462
127229
  Point hyperframes at an already-installed Chrome/Chromium instead:
127463
127230
 
@@ -127478,7 +127245,7 @@ async function downloadBrowser(options) {
127478
127245
  const runInstall = () => install2({
127479
127246
  cacheDir: CACHE_DIR2,
127480
127247
  browser: Browser.CHROMEHEADLESSSHELL,
127481
- buildId: CHROME_VERSION,
127248
+ buildId: managedChromeVersion(),
127482
127249
  platform: platform11,
127483
127250
  downloadProgressCallback: options?.onProgress
127484
127251
  });
@@ -127509,19 +127276,21 @@ function clearBrowser() {
127509
127276
  function isLinuxArm() {
127510
127277
  return process.platform === "linux" && process.arch === "arm64";
127511
127278
  }
127512
- var CHROME_VERSION, CACHE_ROOT_DIR, CACHE_DIR2, PUPPETEER_CACHE_DIR, INSTALL_LOCK_DIR, INSTALL_RECLAIM_LOCK_DIR, INSTALL_LOCK_OWNER_FILE, INSTALL_LOCK_OWNER_ENV, ownedInstallLockToken, INSTALL_LOCK_TIMINGS, SYSTEM_CHROME_PATHS, CACHED_HEADLESS_SHELL_EXECUTABLES2, _warnedSystemFallback;
127279
+ var CHROME_VERSION, MACOS_12_CHROME_VERSION, CACHE_ROOT_DIR, CACHE_DIR2, PUPPETEER_CACHE_DIR, INSTALL_LOCK_DIR, INSTALL_RECLAIM_LOCK_DIR, INSTALL_LOCK_OWNER_FILE, INSTALL_LOCK_OWNER_ENV, ownedInstallLockToken, INSTALL_LOCK_TIMINGS, SYSTEM_CHROME_PATHS, CACHED_HEADLESS_SHELL_EXECUTABLES2, _warnedSystemFallback;
127513
127280
  var init_manager2 = __esm({
127514
127281
  "src/browser/manager.ts"() {
127515
127282
  "use strict";
127283
+ init_chromeHostCeiling();
127516
127284
  init_errorMessage();
127517
127285
  init_cancellableProcess();
127518
127286
  CHROME_VERSION = "152.0.7977.30";
127519
- CACHE_ROOT_DIR = join43(homedir11(), ".cache", "hyperframes");
127520
- CACHE_DIR2 = join43(homedir11(), ".cache", "hyperframes", "chrome");
127521
- PUPPETEER_CACHE_DIR = join43(homedir11(), ".cache", "puppeteer", "chrome-headless-shell");
127522
- INSTALL_LOCK_DIR = join43(CACHE_ROOT_DIR, ".chrome.install.lock");
127523
- INSTALL_RECLAIM_LOCK_DIR = join43(CACHE_ROOT_DIR, ".chrome.install.reclaim.lock");
127524
- INSTALL_LOCK_OWNER_FILE = join43(INSTALL_LOCK_DIR, "owner");
127287
+ MACOS_12_CHROME_VERSION = "150.0.7871.124";
127288
+ CACHE_ROOT_DIR = join41(homedir11(), ".cache", "hyperframes");
127289
+ CACHE_DIR2 = join41(homedir11(), ".cache", "hyperframes", "chrome");
127290
+ PUPPETEER_CACHE_DIR = join41(homedir11(), ".cache", "puppeteer", "chrome-headless-shell");
127291
+ INSTALL_LOCK_DIR = join41(CACHE_ROOT_DIR, ".chrome.install.lock");
127292
+ INSTALL_RECLAIM_LOCK_DIR = join41(CACHE_ROOT_DIR, ".chrome.install.reclaim.lock");
127293
+ INSTALL_LOCK_OWNER_FILE = join41(INSTALL_LOCK_DIR, "owner");
127525
127294
  INSTALL_LOCK_OWNER_ENV = "HYPERFRAMES_BROWSER_LOCK_OWNER";
127526
127295
  INSTALL_LOCK_TIMINGS = {
127527
127296
  staleMs: 12e4,
@@ -127530,21 +127299,21 @@ var init_manager2 = __esm({
127530
127299
  waitNoticeMs: 1e4
127531
127300
  };
127532
127301
  SYSTEM_CHROME_PATHS = process.platform === "darwin" ? ["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"] : process.platform === "win32" ? [
127533
- join43(
127302
+ join41(
127534
127303
  process.env["ProgramW6432"] ?? process.env["PROGRAMFILES"] ?? "C:\\Program Files",
127535
127304
  "Google",
127536
127305
  "Chrome",
127537
127306
  "Application",
127538
127307
  "chrome.exe"
127539
127308
  ),
127540
- join43(
127309
+ join41(
127541
127310
  process.env["PROGRAMFILES(X86)"] ?? "C:\\Program Files (x86)",
127542
127311
  "Google",
127543
127312
  "Chrome",
127544
127313
  "Application",
127545
127314
  "chrome.exe"
127546
127315
  ),
127547
- ...process.env["LOCALAPPDATA"] ? [join43(process.env["LOCALAPPDATA"], "Google", "Chrome", "Application", "chrome.exe")] : []
127316
+ ...process.env["LOCALAPPDATA"] ? [join41(process.env["LOCALAPPDATA"], "Google", "Chrome", "Application", "chrome.exe")] : []
127548
127317
  ] : [
127549
127318
  "/usr/bin/google-chrome",
127550
127319
  "/usr/bin/google-chrome-stable",
@@ -127562,6 +127331,650 @@ var init_manager2 = __esm({
127562
127331
  }
127563
127332
  });
127564
127333
 
127334
+ // src/browser/installFacts.ts
127335
+ function driveOf(path) {
127336
+ if (path.startsWith("\\\\") || path.startsWith("//")) return "unc";
127337
+ const letter = /^([A-Za-z]):[\\/]/.exec(path)?.[1];
127338
+ if (!letter) return "posix";
127339
+ return letter.toUpperCase() === "C" ? "windows_c" : "windows_other";
127340
+ }
127341
+ function lengthBucket(length) {
127342
+ if (length < 120) return "under_120";
127343
+ if (length < 200) return "120_to_199";
127344
+ return length < 260 ? "200_to_259" : "260_plus";
127345
+ }
127346
+ function describeBrowserInstall(executablePath) {
127347
+ const build = BUILD_IN_PATH.exec(executablePath)?.[1];
127348
+ return {
127349
+ ...build ? { build } : {},
127350
+ pathAscii: new RegExp("^\\p{ASCII}*$", "u").test(executablePath),
127351
+ pathLength: lengthBucket(executablePath.length),
127352
+ drive: driveOf(executablePath)
127353
+ };
127354
+ }
127355
+ var BUILD_IN_PATH;
127356
+ var init_installFacts = __esm({
127357
+ "src/browser/installFacts.ts"() {
127358
+ "use strict";
127359
+ BUILD_IN_PATH = /[\\/]chrome(?:-headless-shell)?[\\/][a-z0-9_]+-(\d+\.\d+\.\d+\.\d+)[\\/]/i;
127360
+ }
127361
+ });
127362
+
127363
+ // src/browser/preflight.ts
127364
+ var preflight_exports = {};
127365
+ __export(preflight_exports, {
127366
+ checkDisk: () => checkDisk,
127367
+ extractMajorVersion: () => extractMajorVersion,
127368
+ parseToolVersion: () => parseToolVersion,
127369
+ resolveRenderBrowser: () => resolveRenderBrowser,
127370
+ runEnvironmentChecks: () => runEnvironmentChecks
127371
+ });
127372
+ import { existsSync as existsSync41 } from "fs";
127373
+ import { platform as platform6 } from "os";
127374
+ function parseToolVersion(raw) {
127375
+ const m = raw.match(/(ffmpeg|ffprobe)\s+version\s+([\d][\d.\-\w]*)/i);
127376
+ return m ? `${m[1]} ${m[2]}` : raw.trim();
127377
+ }
127378
+ function extractMajorVersion(raw) {
127379
+ const m = raw.match(/\b(\d+)\.\d+/);
127380
+ return m?.[1] ? Number(m[1]) : void 0;
127381
+ }
127382
+ function configuredMissingDetail(envName) {
127383
+ const configured = process.env[envName]?.trim();
127384
+ if (!configured || existsSync41(configured)) return void 0;
127385
+ return `Configured path does not exist: ${envName}="${configured}"`;
127386
+ }
127387
+ async function readToolVersion(binaryPath, signal) {
127388
+ try {
127389
+ const output = (await runCancellableProcess(binaryPath, ["-version"], {
127390
+ signal,
127391
+ timeoutMs: 5e3
127392
+ })).stdout;
127393
+ const raw = output.split("\n")[0] ?? "";
127394
+ const version2 = parseToolVersion(raw);
127395
+ return {
127396
+ ok: true,
127397
+ detail: version2 ? `${version2} at ${binaryPath}` : binaryPath,
127398
+ majorVersion: extractMajorVersion(raw)
127399
+ };
127400
+ } catch (error) {
127401
+ if (signal?.aborted) signal.throwIfAborted();
127402
+ const status = typeof error === "object" && error !== null && "status" in error ? error.status : void 0;
127403
+ const exitDetail = typeof status === "number" ? ` (exit code ${status})` : "";
127404
+ return {
127405
+ ok: false,
127406
+ detail: `Failed to run "${binaryPath}" -version${exitDetail}.`
127407
+ };
127408
+ }
127409
+ }
127410
+ async function checkFFmpeg(signal) {
127411
+ const missingConfigured = configuredMissingDetail(FFMPEG_PATH_ENV);
127412
+ if (missingConfigured) {
127413
+ return {
127414
+ name: "FFmpeg",
127415
+ ok: false,
127416
+ level: "error",
127417
+ title: "FFmpeg not found",
127418
+ detail: missingConfigured,
127419
+ hint: getFFmpegInstallHint()
127420
+ };
127421
+ }
127422
+ const path = findFfBinary("ffmpeg", { configuredMustExist: true });
127423
+ if (path) {
127424
+ const version2 = await readToolVersion(path, signal);
127425
+ if (!version2.ok) {
127426
+ return {
127427
+ name: "FFmpeg",
127428
+ ok: false,
127429
+ level: "error",
127430
+ title: "FFmpeg cannot start",
127431
+ detail: version2.detail,
127432
+ hint: "Install a working 64-bit FFmpeg build with all required runtime DLLs.",
127433
+ path
127434
+ };
127435
+ }
127436
+ return {
127437
+ name: "FFmpeg",
127438
+ ok: true,
127439
+ level: "ok",
127440
+ detail: version2.detail,
127441
+ path,
127442
+ versionMajor: version2.majorVersion
127443
+ };
127444
+ }
127445
+ return {
127446
+ name: "FFmpeg",
127447
+ ok: false,
127448
+ level: "error",
127449
+ title: "FFmpeg not found",
127450
+ // Second sentence dropped: "the render cannot proceed" is already said by
127451
+ // the error this accompanies, and in Studio by the disabled Export button.
127452
+ detail: "FFmpeg is required to encode video.",
127453
+ hint: getFFmpegInstallHint()
127454
+ };
127455
+ }
127456
+ async function checkFFprobe(signal) {
127457
+ const missingConfigured = configuredMissingDetail(FFPROBE_PATH_ENV);
127458
+ if (missingConfigured) {
127459
+ return {
127460
+ name: "FFprobe",
127461
+ ok: false,
127462
+ level: "error",
127463
+ title: "FFprobe not found",
127464
+ detail: missingConfigured,
127465
+ hint: getFFmpegInstallHint()
127466
+ };
127467
+ }
127468
+ const path = findFfBinary("ffprobe", { configuredMustExist: true });
127469
+ if (path) {
127470
+ const version2 = await readToolVersion(path, signal);
127471
+ return { name: "FFprobe", ok: true, level: "ok", detail: version2.detail, path };
127472
+ }
127473
+ return {
127474
+ name: "FFprobe",
127475
+ ok: false,
127476
+ level: "error",
127477
+ title: "FFprobe not found",
127478
+ detail: "FFprobe is required to probe media assets. It ships with FFmpeg but was not found on PATH.",
127479
+ hint: getFFmpegInstallHint()
127480
+ };
127481
+ }
127482
+ async function chromeSharedLibOutcome(executablePath, found, signal) {
127483
+ if (process.platform !== "linux") return found;
127484
+ let probe2;
127485
+ if (!existsSync41(executablePath)) {
127486
+ probe2 = { ok: true, missing: [], probeUnavailable: true };
127487
+ } else {
127488
+ try {
127489
+ const result = await runCancellableProcess("ldd", [executablePath], {
127490
+ signal,
127491
+ timeoutMs: 5e3
127492
+ });
127493
+ probe2 = parseLddMissingLibs(result.stdout);
127494
+ } catch (error) {
127495
+ if (signal?.aborted) signal.throwIfAborted();
127496
+ const stdout2 = typeof error === "object" && error !== null && "stdout" in error ? String(error.stdout ?? "") : "";
127497
+ const killed = typeof error === "object" && error !== null && "killed" in error && error.killed === true;
127498
+ probe2 = stdout2 && !killed ? parseLddMissingLibs(stdout2) : { ok: true, missing: [], probeUnavailable: true };
127499
+ }
127500
+ }
127501
+ if (probe2.probeUnavailable || probe2.ok) return found;
127502
+ const distro = detectLinuxDistro();
127503
+ return {
127504
+ name: "Chrome",
127505
+ ok: false,
127506
+ level: "error",
127507
+ title: "Chrome cannot launch (missing system libraries)",
127508
+ detail: `Chrome at ${executablePath} is missing shared libraries on ${distroLabel(distro)}: ${probe2.missing.join(", ")}`,
127509
+ hint: chromeDepsInstallCommand(distro.family),
127510
+ path: executablePath
127511
+ };
127512
+ }
127513
+ function chromeLaunchFailureDetails(error) {
127514
+ if (typeof error !== "object" || error === null) return "";
127515
+ const status = "status" in error ? error.status : void 0;
127516
+ const signal = "signal" in error ? error.signal : void 0;
127517
+ const code = "code" in error ? error.code : void 0;
127518
+ return [
127519
+ typeof status === "number" ? `exit code ${status}` : "",
127520
+ typeof signal === "string" ? `signal ${signal}` : "",
127521
+ typeof code === "string" ? code : ""
127522
+ ].filter(Boolean).join(", ");
127523
+ }
127524
+ async function chromeLaunchOutcome(executablePath, found, signal) {
127525
+ const libraries = await chromeSharedLibOutcome(executablePath, found, signal);
127526
+ if (!libraries.ok) return libraries;
127527
+ try {
127528
+ const { stdout: stdout2 } = await runCancellableProcess(executablePath, ["--version"], {
127529
+ signal,
127530
+ timeoutMs: 5e3,
127531
+ maxBufferBytes: 64 * 1024
127532
+ });
127533
+ return { ...found, versionMajor: extractMajorVersion(stdout2) };
127534
+ } catch (error) {
127535
+ if (signal?.aborted) signal.throwIfAborted();
127536
+ const details2 = chromeLaunchFailureDetails(error);
127537
+ return {
127538
+ name: "Chrome",
127539
+ ok: false,
127540
+ level: "error",
127541
+ title: "Chrome cannot start",
127542
+ detail: `Failed to run "${executablePath}" --version${details2 ? ` (${details2})` : ""}.`,
127543
+ hint: "Select a working Chrome/Chromium binary for this OS and architecture with HYPERFRAMES_BROWSER_PATH, or reinstall with: npx hyperframes browser ensure --force",
127544
+ path: executablePath
127545
+ };
127546
+ }
127547
+ }
127548
+ async function checkChrome(browserPath, signal) {
127549
+ if (browserPath) {
127550
+ if (existsSync41(browserPath)) {
127551
+ return chromeLaunchOutcome(
127552
+ browserPath,
127553
+ {
127554
+ name: "Chrome",
127555
+ ok: true,
127556
+ level: "ok",
127557
+ detail: `explicit: ${browserPath}`,
127558
+ path: browserPath
127559
+ },
127560
+ signal
127561
+ );
127562
+ }
127563
+ return {
127564
+ name: "Chrome",
127565
+ ok: false,
127566
+ level: "error",
127567
+ title: "Chrome not found",
127568
+ detail: `Chrome binary not found at "${browserPath}".`,
127569
+ hint: "Run: npx hyperframes browser ensure"
127570
+ };
127571
+ }
127572
+ let info;
127573
+ try {
127574
+ info = signal ? await ensureBrowser({ preferManagedChrome: true, signal }) : await findBrowser();
127575
+ } catch {
127576
+ if (signal?.aborted) signal.throwIfAborted();
127577
+ info = void 0;
127578
+ }
127579
+ if (info) {
127580
+ return chromeLaunchOutcome(
127581
+ info.executablePath,
127582
+ {
127583
+ name: "Chrome",
127584
+ ok: true,
127585
+ level: "ok",
127586
+ detail: `${info.source}: ${info.executablePath}`,
127587
+ path: info.executablePath
127588
+ },
127589
+ signal
127590
+ );
127591
+ }
127592
+ return {
127593
+ name: "Chrome",
127594
+ ok: false,
127595
+ level: "error",
127596
+ title: "Chrome not found",
127597
+ detail: "Chrome Headless Shell is required for local rendering.",
127598
+ hint: "Run: npx hyperframes browser ensure"
127599
+ };
127600
+ }
127601
+ async function resolveRenderBrowser(signal) {
127602
+ const { outcomes, browser } = await runEnvironmentChecks({ includeBrowser: true, signal });
127603
+ if (browser) return browser;
127604
+ const chrome = outcomes.find((outcome) => outcome.name === "Chrome");
127605
+ const headline = [chrome?.title, chrome?.detail].filter(Boolean).join(": ");
127606
+ throw new Error(
127607
+ [headline, chrome?.hint].filter(Boolean).join(" ") || "Chrome Headless Shell could not be resolved for rendering."
127608
+ );
127609
+ }
127610
+ function checkDisk(path = ".", freeDiskMb = getFreeDiskMb) {
127611
+ const freeMb = freeDiskMb(path);
127612
+ if (freeMb === null) {
127613
+ return { name: "Disk", ok: true, level: "ok", detail: "Unable to check" };
127614
+ }
127615
+ const freeGb = (freeMb / 1024).toFixed(1);
127616
+ if (freeMb < 1024) {
127617
+ return {
127618
+ name: "Disk",
127619
+ ok: false,
127620
+ level: "error",
127621
+ title: "Low disk space",
127622
+ detail: `${freeGb} GB free at ${path}`,
127623
+ hint: "Renders produce large temp files. Free disk space before rendering."
127624
+ };
127625
+ }
127626
+ return { name: "Disk", ok: true, level: "ok", detail: `${freeGb} GB free at ${path}` };
127627
+ }
127628
+ function checkWindowsUncPath(projectDir = process.cwd()) {
127629
+ if (platform6() !== "win32") return void 0;
127630
+ if (!projectDir.startsWith("\\\\")) return void 0;
127631
+ return {
127632
+ name: "Windows path",
127633
+ ok: true,
127634
+ level: "warn",
127635
+ detail: `UNC path: ${projectDir}`,
127636
+ hint: "Chrome may fail to launch from a network share. Use a local drive if render startup fails."
127637
+ };
127638
+ }
127639
+ async function runEnvironmentChecks(options = {}) {
127640
+ const outcomes = [];
127641
+ const ffmpeg = await checkFFmpeg(options.signal);
127642
+ outcomes.push(ffmpeg);
127643
+ const ffprobe = await checkFFprobe(options.signal);
127644
+ outcomes.push(ffprobe);
127645
+ let browser;
127646
+ let browserVersionMajor;
127647
+ if (options.includeBrowser) {
127648
+ const chrome = await checkChrome(options.browserPath, options.signal);
127649
+ outcomes.push(chrome);
127650
+ if (chrome.ok && chrome.path) {
127651
+ browser = {
127652
+ executablePath: chrome.path,
127653
+ source: options.browserPath ? "env" : "cache"
127654
+ };
127655
+ }
127656
+ browserVersionMajor = chrome.versionMajor;
127657
+ }
127658
+ if (options.includeDisk) {
127659
+ const diskPaths = [...new Set(options.diskPaths ?? [options.projectDir ?? "."])];
127660
+ outcomes.push(...diskPaths.map((path) => checkDisk(path)));
127661
+ }
127662
+ if (options.includeWindowsUnc) {
127663
+ const unc = checkWindowsUncPath(options.projectDir);
127664
+ if (unc) outcomes.push(unc);
127665
+ }
127666
+ return {
127667
+ outcomes,
127668
+ ...ffmpeg.ok && ffmpeg.path ? { ffmpegPath: ffmpeg.path } : {},
127669
+ ...ffprobe.path ? { ffprobePath: ffprobe.path } : {},
127670
+ ...browser ? { browser, browserInstall: describeBrowserInstall(browser.executablePath) } : {},
127671
+ ...ffmpeg.versionMajor != null ? { ffmpegVersionMajor: ffmpeg.versionMajor } : {},
127672
+ ...browserVersionMajor != null ? { browserVersionMajor } : {}
127673
+ };
127674
+ }
127675
+ var init_preflight = __esm({
127676
+ "src/browser/preflight.ts"() {
127677
+ "use strict";
127678
+ init_ffBinaries();
127679
+ init_manager2();
127680
+ init_installFacts();
127681
+ init_ffmpeg();
127682
+ init_linuxDeps();
127683
+ init_system();
127684
+ init_cancellableProcess();
127685
+ }
127686
+ });
127687
+
127688
+ // ../studio-server/dist/helpers/screenshotClip.js
127689
+ var init_screenshotClip = __esm({
127690
+ "../studio-server/dist/helpers/screenshotClip.js"() {
127691
+ "use strict";
127692
+ init_chunk_W2SBTCO2();
127693
+ }
127694
+ });
127695
+
127696
+ // src/browser/windowsCrash.ts
127697
+ function isWindowsChromeCrashError(errorMessage2) {
127698
+ if (!/Failed to launch the browser process/i.test(errorMessage2)) return false;
127699
+ return errorMessage2.includes(STATUS_STACK_BUFFER_OVERRUN_DEC) || STATUS_STACK_BUFFER_OVERRUN_HEX.test(errorMessage2) || STATUS_STACK_BUFFER_OVERRUN_NAME.test(errorMessage2);
127700
+ }
127701
+ function windowsChromeCrashRemediation(errorMessage2) {
127702
+ if (process.platform !== "win32") return void 0;
127703
+ if (!isWindowsChromeCrashError(errorMessage2)) return void 0;
127704
+ return [
127705
+ "chrome-headless-shell crashed at launch (Windows STATUS_STACK_BUFFER_OVERRUN, exit 0xC0000409 / 3221225595).",
127706
+ "The pinned Chromium build is not stable on this Windows host; point hyperframes at your installed Chrome instead:",
127707
+ "",
127708
+ ' set HYPERFRAMES_BROWSER_PATH="C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe"',
127709
+ "",
127710
+ "Then re-run your command. Any Chrome build works for the screenshot capture path; install a real chrome-headless-shell later if you need the perf-optimized BeginFrame path."
127711
+ ].join("\n");
127712
+ }
127713
+ var STATUS_STACK_BUFFER_OVERRUN_DEC, STATUS_STACK_BUFFER_OVERRUN_HEX, STATUS_STACK_BUFFER_OVERRUN_NAME;
127714
+ var init_windowsCrash = __esm({
127715
+ "src/browser/windowsCrash.ts"() {
127716
+ "use strict";
127717
+ STATUS_STACK_BUFFER_OVERRUN_DEC = "3221225595";
127718
+ STATUS_STACK_BUFFER_OVERRUN_HEX = /0x[cC]0000409/;
127719
+ STATUS_STACK_BUFFER_OVERRUN_NAME = /STATUS_STACK_BUFFER_OVERRUN/i;
127720
+ }
127721
+ });
127722
+
127723
+ // src/utils/dom.ts
127724
+ var dom_exports = {};
127725
+ __export(dom_exports, {
127726
+ ensureDOMParser: () => ensureDOMParser
127727
+ });
127728
+ function ensureDOMParser() {
127729
+ if (typeof globalThis.DOMParser === "undefined") {
127730
+ globalThis.DOMParser = DOMParser2;
127731
+ }
127732
+ }
127733
+ var init_dom = __esm({
127734
+ "src/utils/dom.ts"() {
127735
+ "use strict";
127736
+ init_esm10();
127737
+ }
127738
+ });
127739
+
127740
+ // src/utils/compositionViewport.ts
127741
+ function parseViewportDimension(value) {
127742
+ if (!value) return null;
127743
+ const parsed = Number.parseInt(value, 10);
127744
+ if (!Number.isFinite(parsed) || parsed <= 0) return null;
127745
+ return Math.min(parsed, MAX_VIEWPORT_DIMENSION);
127746
+ }
127747
+ function findCompositionDimensions(html) {
127748
+ ensureDOMParser();
127749
+ const doc = new DOMParser().parseFromString(html, "text/html");
127750
+ const root = doc.querySelector("[data-composition-id][data-width][data-height]");
127751
+ if (!root) return null;
127752
+ const width = parseViewportDimension(root.getAttribute("data-width"));
127753
+ const height = parseViewportDimension(root.getAttribute("data-height"));
127754
+ if (width === null || height === null) return null;
127755
+ return { width, height };
127756
+ }
127757
+ function resolveCompositionViewportFromHtml(html) {
127758
+ return findCompositionDimensions(html) ?? DEFAULT_VIEWPORT;
127759
+ }
127760
+ var DEFAULT_VIEWPORT, MAX_VIEWPORT_DIMENSION;
127761
+ var init_compositionViewport = __esm({
127762
+ "src/utils/compositionViewport.ts"() {
127763
+ "use strict";
127764
+ init_dom();
127765
+ DEFAULT_VIEWPORT = { width: 1920, height: 1080 };
127766
+ MAX_VIEWPORT_DIMENSION = 4096;
127767
+ }
127768
+ });
127769
+
127770
+ // src/utils/compositionFps.ts
127771
+ import { readFileSync as readFileSync28 } from "fs";
127772
+ import { join as join43 } from "path";
127773
+ function readCompositionFps(html) {
127774
+ let doc;
127775
+ try {
127776
+ doc = parseHTML(html).document;
127777
+ } catch {
127778
+ return null;
127779
+ }
127780
+ const explicitRoot = doc.querySelector('[data-composition-id][data-root="true"]');
127781
+ const root = explicitRoot ?? Array.from(doc.querySelectorAll("[data-composition-id]")).find(
127782
+ (el) => !el.parentElement?.closest("[data-composition-id]")
127783
+ ) ?? null;
127784
+ const raw = root?.getAttribute("data-fps")?.trim();
127785
+ return raw ? raw : null;
127786
+ }
127787
+ function readAllowedCompositionFpsFromDir(projectDir, allowed) {
127788
+ let html;
127789
+ try {
127790
+ html = readFileSync28(join43(projectDir, "index.html"), "utf8");
127791
+ } catch {
127792
+ return null;
127793
+ }
127794
+ const raw = readCompositionFps(html);
127795
+ if (raw == null) return null;
127796
+ const n3 = Number(raw);
127797
+ return Number.isInteger(n3) && allowed.includes(n3) ? n3 : null;
127798
+ }
127799
+ var init_compositionFps = __esm({
127800
+ "src/utils/compositionFps.ts"() {
127801
+ "use strict";
127802
+ init_esm10();
127803
+ }
127804
+ });
127805
+
127806
+ // src/utils/renderArgs.ts
127807
+ import { readFileSync as readFileSync29 } from "fs";
127808
+ import { resolve as resolve26, sep as sep10 } from "path";
127809
+ function parseBrowserTimeoutMsArg(raw) {
127810
+ if (raw == null) return { ok: true, value: void 0 };
127811
+ const parsed = Number(raw);
127812
+ if (!Number.isFinite(parsed)) {
127813
+ return { ok: false, error: { kind: "not-a-number", raw } };
127814
+ }
127815
+ if (parsed <= 0) {
127816
+ return { ok: false, error: { kind: "not-positive", raw } };
127817
+ }
127818
+ if (parsed > MAX_PAGE_NAVIGATION_TIMEOUT_SECONDS) {
127819
+ return { ok: false, error: { kind: "too-large", raw } };
127820
+ }
127821
+ const ms = Math.round(parsed * 1e3);
127822
+ if (ms < MIN_PAGE_NAVIGATION_TIMEOUT_MS) {
127823
+ return { ok: false, error: { kind: "too-small", raw } };
127824
+ }
127825
+ return { ok: true, value: ms };
127826
+ }
127827
+ function browserTimeoutErrorMessage(error) {
127828
+ const title = "Invalid browser-timeout";
127829
+ switch (error.kind) {
127830
+ case "not-a-number":
127831
+ return {
127832
+ title,
127833
+ message: `Got "${error.raw}", which is not a number. Pass a positive number of seconds (e.g. 180).`
127834
+ };
127835
+ case "not-positive":
127836
+ return {
127837
+ title,
127838
+ message: `Got "${error.raw}" seconds, which is not positive. Pass a positive number of seconds (e.g. 180).`
127839
+ };
127840
+ case "too-small":
127841
+ return {
127842
+ title,
127843
+ message: `Got "${error.raw}" seconds, which rounds to 0 ms. Puppeteer treats 0 as 'no timeout' \u2014 pass a value that rounds to at least 1 ms.`
127844
+ };
127845
+ case "too-large":
127846
+ return {
127847
+ title,
127848
+ message: `Got "${error.raw}" seconds, which exceeds the ${MAX_PAGE_NAVIGATION_TIMEOUT_SECONDS}s (24h) cap. Node's setTimeout overflows for larger values.`
127849
+ };
127850
+ }
127851
+ }
127852
+ function resolveBrowserTimeoutMsArg(raw) {
127853
+ const result = parseBrowserTimeoutMsArg(raw);
127854
+ if (!result.ok) {
127855
+ const { title, message, hint: hint2 } = browserTimeoutErrorMessage(result.error);
127856
+ errorBox(title, message, hint2);
127857
+ failUsage();
127858
+ }
127859
+ return result.value;
127860
+ }
127861
+ function resolveDiagnosticNavigationTimeoutMs(env = process.env, minimumTimeoutMs = 0) {
127862
+ const parsed = Number(env.PRODUCER_PAGE_NAVIGATION_TIMEOUT_MS);
127863
+ const configured = Number.isFinite(parsed) && parsed > 0 ? parsed : 1e4;
127864
+ return Math.max(configured, minimumTimeoutMs);
127865
+ }
127866
+ function normalizeCompositionEntryArg(raw) {
127867
+ const trimmed = raw?.trim().replace(/^\.\//, "") || void 0;
127868
+ return !trimmed || trimmed === "." ? void 0 : trimmed;
127869
+ }
127870
+ function hasExplicitCompositionArg(raw) {
127871
+ return normalizeCompositionEntryArg(raw) !== void 0;
127872
+ }
127873
+ function parseCompositionEntryArg(raw, projectDir, stat) {
127874
+ const trimmed = normalizeCompositionEntryArg(raw);
127875
+ if (!trimmed) return { ok: true, value: void 0 };
127876
+ const absProjectDir = resolve26(projectDir);
127877
+ const entryPath = resolve26(absProjectDir, trimmed);
127878
+ if (entryPath !== absProjectDir && !entryPath.startsWith(absProjectDir + sep10)) {
127879
+ return { ok: false, error: { kind: "outside-project", entryFile: trimmed } };
127880
+ }
127881
+ let entryStat;
127882
+ try {
127883
+ entryStat = stat(entryPath);
127884
+ } catch {
127885
+ return { ok: false, error: { kind: "not-found", entryFile: trimmed } };
127886
+ }
127887
+ if (!entryStat.isFile()) {
127888
+ return { ok: false, error: { kind: "not-a-file", entryFile: trimmed } };
127889
+ }
127890
+ return { ok: true, value: trimmed };
127891
+ }
127892
+ function compositionEntryErrorMessage(error) {
127893
+ switch (error.kind) {
127894
+ case "outside-project":
127895
+ return {
127896
+ title: "Invalid composition path",
127897
+ message: `Entry file must stay inside the project directory: ${error.entryFile}`
127898
+ };
127899
+ case "not-found":
127900
+ return {
127901
+ title: "Composition not found",
127902
+ message: `"${error.entryFile}" does not exist in the project directory.`,
127903
+ hint: "Pass a path to a .html file relative to the project root (e.g. compositions/intro.html)."
127904
+ };
127905
+ case "not-a-file":
127906
+ return {
127907
+ title: "Invalid composition path",
127908
+ message: `"${error.entryFile}" is a directory, not an .html file.`,
127909
+ hint: "Pass a path to a .html file (e.g. compositions/intro.html), or omit --composition to render index.html."
127910
+ };
127911
+ }
127912
+ }
127913
+ function resolveCompositionEntryArg(raw, projectDir, stat) {
127914
+ const result = parseCompositionEntryArg(raw, projectDir, stat);
127915
+ if (!result.ok) {
127916
+ const { title, message, hint: hint2 } = compositionEntryErrorMessage(result.error);
127917
+ errorBox(title, message, hint2);
127918
+ failUsage();
127919
+ }
127920
+ return result.value;
127921
+ }
127922
+ function resolveDefaultFpsArg(explicitFps, projectDir, indexPath2, entryFile) {
127923
+ if (explicitFps != null) return explicitFps;
127924
+ try {
127925
+ const fpsSourcePath = entryFile ? resolve26(projectDir, entryFile) : indexPath2;
127926
+ const declared = readCompositionFps(readFileSync29(fpsSourcePath, "utf8"));
127927
+ if (declared != null && parseFps(declared).ok) {
127928
+ return declared;
127929
+ }
127930
+ } catch {
127931
+ }
127932
+ return void 0;
127933
+ }
127934
+ function parseGifLoopArg(raw) {
127935
+ if (raw === void 0) return { ok: true, value: void 0 };
127936
+ const trimmed = raw.trim();
127937
+ if (trimmed.length === 0) {
127938
+ return { ok: false, message: "GIF loop count must not be empty." };
127939
+ }
127940
+ const parsed = Number(trimmed);
127941
+ if (!Number.isInteger(parsed) || parsed < 0 || parsed > 65535) {
127942
+ return {
127943
+ ok: false,
127944
+ message: `Got "${raw}". GIF loop count must be an integer between 0 and 65535.`
127945
+ };
127946
+ }
127947
+ return { ok: true, value: parsed };
127948
+ }
127949
+ function parseHlsSegmentSecondsArg(raw) {
127950
+ if (raw === void 0) return { ok: true, value: void 0 };
127951
+ const trimmed = raw.trim();
127952
+ if (trimmed.length === 0) {
127953
+ return { ok: false, message: "HLS segment length must not be empty." };
127954
+ }
127955
+ const parsed = Number(trimmed);
127956
+ if (!Number.isInteger(parsed) || parsed < 1 || parsed > MAX_HLS_SEGMENT_SECONDS) {
127957
+ return {
127958
+ ok: false,
127959
+ message: `Got "${raw}". HLS segment length must be a whole number of seconds between 1 and ${MAX_HLS_SEGMENT_SECONDS}.`
127960
+ };
127961
+ }
127962
+ return { ok: true, value: parsed };
127963
+ }
127964
+ var MIN_PAGE_NAVIGATION_TIMEOUT_MS, MAX_PAGE_NAVIGATION_TIMEOUT_SECONDS, MAX_HLS_SEGMENT_SECONDS;
127965
+ var init_renderArgs = __esm({
127966
+ "src/utils/renderArgs.ts"() {
127967
+ "use strict";
127968
+ init_commandResult();
127969
+ init_dist3();
127970
+ init_format();
127971
+ init_compositionFps();
127972
+ MIN_PAGE_NAVIGATION_TIMEOUT_MS = 1;
127973
+ MAX_PAGE_NAVIGATION_TIMEOUT_SECONDS = 86400;
127974
+ MAX_HLS_SEGMENT_SECONDS = 60;
127975
+ }
127976
+ });
127977
+
127565
127978
  // src/capture/captureCompositionFrame.ts
127566
127979
  import { spawn as spawn12 } from "child_process";
127567
127980
  function resolveCliChromeGpuMode(envMode = process.env.PRODUCER_BROWSER_GPU_MODE) {
@@ -127898,7 +128311,7 @@ var init_captureCompositionFrame = __esm({
127898
128311
 
127899
128312
  // ../producer/src/services/hyperframeRuntimeLoader.ts
127900
128313
  import { createHash as createHash11 } from "crypto";
127901
- import { existsSync as existsSync41, readFileSync as readFileSync30 } from "fs";
128314
+ import { existsSync as existsSync43, readFileSync as readFileSync30 } from "fs";
127902
128315
  import { dirname as dirname19, resolve as resolve27 } from "path";
127903
128316
  import { fileURLToPath as fileURLToPath3 } from "url";
127904
128317
  function resolveHyperframeManifestPath() {
@@ -127906,7 +128319,7 @@ function resolveHyperframeManifestPath() {
127906
128319
  if (envOverride) {
127907
128320
  return envOverride;
127908
128321
  }
127909
- const found = MANIFEST_CANDIDATES.find((candidate) => existsSync41(candidate));
128322
+ const found = MANIFEST_CANDIDATES.find((candidate) => existsSync43(candidate));
127910
128323
  return found ?? MODULE_RELATIVE_MANIFEST_PATH;
127911
128324
  }
127912
128325
  function triedManifestPaths() {
@@ -127917,7 +128330,7 @@ function getVerifiedHyperframeRuntimeSource() {
127917
128330
  }
127918
128331
  function resolveVerifiedHyperframeRuntime() {
127919
128332
  const manifestPath3 = resolveHyperframeManifestPath();
127920
- if (!existsSync41(manifestPath3)) {
128333
+ if (!existsSync43(manifestPath3)) {
127921
128334
  const tried = triedManifestPaths().join(", ");
127922
128335
  throw new Error(
127923
128336
  `[HyperframeRuntimeLoader] Missing manifest. Tried: ${tried}. Searched from cwd=${process.cwd()}. Build core runtime artifacts before rendering.`
@@ -127932,7 +128345,7 @@ function resolveVerifiedHyperframeRuntime() {
127932
128345
  );
127933
128346
  }
127934
128347
  const runtimePath = resolve27(dirname19(manifestPath3), runtimeFileName);
127935
- if (!existsSync41(runtimePath)) {
128348
+ if (!existsSync43(runtimePath)) {
127936
128349
  throw new Error(`[HyperframeRuntimeLoader] Missing runtime artifact at ${runtimePath}.`);
127937
128350
  }
127938
128351
  const runtimeSource = readFileSync30(runtimePath, "utf8");
@@ -128031,7 +128444,7 @@ var init_logger = __esm({
128031
128444
  import { Hono as Hono3 } from "hono";
128032
128445
  import { serve as serve2 } from "@hono/node-server";
128033
128446
  import {
128034
- existsSync as existsSync43,
128447
+ existsSync as existsSync44,
128035
128448
  realpathSync as realpathSync9,
128036
128449
  statSync as statSync18,
128037
128450
  createReadStream as createReadStream4,
@@ -128050,8 +128463,8 @@ function isPathInside2(child, parent, options = {}) {
128050
128463
  const separator = pathModule?.sep ?? sep11;
128051
128464
  const resolvedChild = resolveFn(child);
128052
128465
  const resolvedParent = resolveFn(parent);
128053
- const normalizedChild = resolveSymlinks && existsSync43(resolvedChild) ? realpathSync9.native(resolvedChild) : resolvedChild;
128054
- const normalizedParent = resolveSymlinks && existsSync43(resolvedParent) ? realpathSync9.native(resolvedParent) : resolvedParent;
128466
+ const normalizedChild = resolveSymlinks && existsSync44(resolvedChild) ? realpathSync9.native(resolvedChild) : resolvedChild;
128467
+ const normalizedParent = resolveSymlinks && existsSync44(resolvedParent) ? realpathSync9.native(resolvedParent) : resolvedParent;
128055
128468
  if (normalizedChild === normalizedParent) return true;
128056
128469
  const parentWithSep = normalizedParent.endsWith(separator) ? normalizedParent : normalizedParent + separator;
128057
128470
  return normalizedChild.startsWith(parentWithSep);
@@ -128758,7 +129171,7 @@ var init_paths = __esm({
128758
129171
  import {
128759
129172
  copyFileSync as copyFileSync3,
128760
129173
  cpSync as cpSync2,
128761
- existsSync as existsSync44,
129174
+ existsSync as existsSync45,
128762
129175
  mkdirSync as mkdirSync18,
128763
129176
  rmSync as rmSync15,
128764
129177
  symlinkSync as symlinkSync2,
@@ -128986,7 +129399,7 @@ var init_shared = __esm({
128986
129399
  isAbsolute: isAbsolute11
128987
129400
  };
128988
129401
  materializeFileSystem = {
128989
- existsSync: existsSync44,
129402
+ existsSync: existsSync45,
128990
129403
  mkdirSync: mkdirSync18,
128991
129404
  symlinkSync: symlinkSync2,
128992
129405
  cpSync: cpSync2,
@@ -129203,7 +129616,7 @@ var init_ffprobe2 = __esm({
129203
129616
  // ../producer/src/services/render/artifactTransaction.ts
129204
129617
  import {
129205
129618
  closeSync as closeSync10,
129206
- existsSync as existsSync45,
129619
+ existsSync as existsSync46,
129207
129620
  fstatSync as fstatSync6,
129208
129621
  mkdtempSync as mkdtempSync9,
129209
129622
  openSync as openSync10,
@@ -129305,7 +129718,7 @@ var init_artifactTransaction = __esm({
129305
129718
  init_src();
129306
129719
  init_ffprobe2();
129307
129720
  defaultFileSystem = {
129308
- existsSync: existsSync45,
129721
+ existsSync: existsSync46,
129309
129722
  renameSync: renameSync10,
129310
129723
  rmSync: rmSync16
129311
129724
  };
@@ -129358,7 +129771,7 @@ var init_artifactTransaction = __esm({
129358
129771
  async assertDirectoryExpectation(expected) {
129359
129772
  for (const required of expected.requiredFiles ?? []) {
129360
129773
  const path = join47(this.stagingPath, required);
129361
- if (!existsSync45(path)) {
129774
+ if (!existsSync46(path)) {
129362
129775
  throw new Error(`Render artifact directory is missing ${required}: ${this.stagingPath}`);
129363
129776
  }
129364
129777
  assertReadableNonEmptyFile(path);
@@ -130882,7 +131295,7 @@ var init_segmentRecycle = __esm({
130882
131295
  });
130883
131296
 
130884
131297
  // ../producer/src/services/render/perfSummary.ts
130885
- import { arch, cpus as cpus3, platform as platform6, totalmem as totalmem2 } from "os";
131298
+ import { arch, cpus as cpus3, platform as platform7, totalmem as totalmem2 } from "os";
130886
131299
  function worstSubTimelineWaitOutcome(perfs) {
130887
131300
  const outcomes = perfs.map((p2) => p2.subTimelineWaitOutcome).filter((o) => !!o);
130888
131301
  if (outcomes.length === 0) return void 0;
@@ -131076,7 +131489,7 @@ function buildRenderPerfSummary(input2) {
131076
131489
  input2.drawElement ?? { selfVerifyFallback: false }
131077
131490
  ),
131078
131491
  host: {
131079
- platform: platform6(),
131492
+ platform: platform7(),
131080
131493
  arch: arch(),
131081
131494
  cpuCount: cpus3().length,
131082
131495
  totalMemMb: Math.round(totalmem2() / (1024 * 1024)),
@@ -131688,7 +132101,7 @@ var init_captureStreamingStage = __esm({
131688
132101
  });
131689
132102
 
131690
132103
  // ../producer/src/services/render/stages/captureSegmentedStage.ts
131691
- import { existsSync as existsSync46, mkdirSync as mkdirSync20, rmSync as rmSync18, statSync as statSync19 } from "fs";
132104
+ import { existsSync as existsSync47, mkdirSync as mkdirSync20, rmSync as rmSync18, statSync as statSync19 } from "fs";
131692
132105
  import { join as join51 } from "path";
131693
132106
  function segmentOutputPath(segmentDir, index) {
131694
132107
  return join51(segmentDir, `segment_${String(index).padStart(5, "0")}.mp4`);
@@ -131758,7 +132171,7 @@ async function captureSegment(ctx, segment) {
131758
132171
  path: segmentPath,
131759
132172
  // Recorded so resume can prove the file on disk is the one that
131760
132173
  // finished; absent only in unit tests, whose fake encoder writes none.
131761
- bytes: existsSync46(segmentPath) ? statSync19(segmentPath).size : 0
132174
+ bytes: existsSync47(segmentPath) ? statSync19(segmentPath).size : 0
131762
132175
  });
131763
132176
  return encodeResult.durationMs;
131764
132177
  } finally {
@@ -132024,7 +132437,7 @@ var init_captureSegmentedStage = __esm({
132024
132437
 
132025
132438
  // ../producer/src/services/render/segmentManifest.ts
132026
132439
  import { createHash as createHash12 } from "crypto";
132027
- import { existsSync as existsSync47, mkdirSync as mkdirSync21, readFileSync as readFileSync33, renameSync as renameSync11, statSync as statSync20, writeFileSync as writeFileSync17 } from "fs";
132440
+ import { existsSync as existsSync48, mkdirSync as mkdirSync21, readFileSync as readFileSync33, renameSync as renameSync11, statSync as statSync20, writeFileSync as writeFileSync17 } from "fs";
132028
132441
  import { join as join53 } from "path";
132029
132442
  function computeSegmentPlanHash(input2) {
132030
132443
  const ordered = [
@@ -132066,7 +132479,7 @@ function isManifest2(value) {
132066
132479
  }
132067
132480
  function readSegmentManifest(segmentDir) {
132068
132481
  const path = join53(segmentDir, MANIFEST_FILENAME);
132069
- if (!existsSync47(path)) return null;
132482
+ if (!existsSync48(path)) return null;
132070
132483
  try {
132071
132484
  const parsed = JSON.parse(readFileSync33(path, "utf-8"));
132072
132485
  return isManifest2(parsed) ? parsed : null;
@@ -132095,7 +132508,7 @@ async function validateCompletedSegments(manifest, expectedHash, probeFrames) {
132095
132508
  const ok = /* @__PURE__ */ new Set();
132096
132509
  if (manifest.planHash !== expectedHash) return ok;
132097
132510
  for (const entry of manifest.completed) {
132098
- if (!existsSync47(entry.path)) continue;
132511
+ if (!existsSync48(entry.path)) continue;
132099
132512
  const size = statSync20(entry.path).size;
132100
132513
  if (size <= 0 || size !== entry.bytes) continue;
132101
132514
  const frames = await probeFrames(entry.path);
@@ -136213,7 +136626,7 @@ __export(fontCompression_exports, {
136213
136626
  });
136214
136627
  import { createHash as createHash14 } from "crypto";
136215
136628
  import {
136216
- existsSync as existsSync48,
136629
+ existsSync as existsSync49,
136217
136630
  mkdirSync as mkdirSync23,
136218
136631
  mkdtempSync as mkdtempSync11,
136219
136632
  readFileSync as readFileSync34,
@@ -136239,7 +136652,7 @@ function cachedCompressionPath(input2, originalFormat, cacheDir) {
136239
136652
  }
136240
136653
  function readCachedCompression(path) {
136241
136654
  try {
136242
- if (!existsSync48(path)) return null;
136655
+ if (!existsSync49(path)) return null;
136243
136656
  const cached3 = readFileSync34(path);
136244
136657
  return cached3.length > 0 ? cached3 : null;
136245
136658
  } catch {
@@ -136320,7 +136733,7 @@ __export(deterministicFonts_exports, {
136320
136733
  resolveFontFamilyDeclarationFamilies: () => resolveFontFamilyDeclarationFamilies
136321
136734
  });
136322
136735
  import { createHash as createHash15 } from "crypto";
136323
- import { existsSync as existsSync49, mkdirSync as mkdirSync24, mkdtempSync as mkdtempSync12, readFileSync as readFileSync35, writeFileSync as writeFileSync19 } from "fs";
136736
+ import { existsSync as existsSync50, mkdirSync as mkdirSync24, mkdtempSync as mkdtempSync12, readFileSync as readFileSync35, writeFileSync as writeFileSync19 } from "fs";
136324
136737
  import { homedir as homedir13, tmpdir as tmpdir8 } from "os";
136325
136738
  import { join as join56 } from "path";
136326
136739
  import postcss4 from "postcss";
@@ -136770,7 +137183,7 @@ function fontSlug(familyName) {
136770
137183
  }
136771
137184
  function fontCacheDir(slug) {
136772
137185
  const dir = join56(resolveFontCacheRoot(), slug);
136773
- if (!existsSync49(dir)) {
137186
+ if (!existsSync50(dir)) {
136774
137187
  try {
136775
137188
  mkdirSync24(dir, { recursive: true });
136776
137189
  } catch {
@@ -137328,7 +137741,7 @@ __export(animatedGifPrep_exports, {
137328
137741
  import { createHash as createHash16 } from "crypto";
137329
137742
  import {
137330
137743
  copyFileSync as copyFileSync4,
137331
- existsSync as existsSync50,
137744
+ existsSync as existsSync51,
137332
137745
  mkdirSync as mkdirSync25,
137333
137746
  readFileSync as readFileSync36,
137334
137747
  renameSync as renameSync13,
@@ -137368,14 +137781,14 @@ function resolveGifSourcePath(src, options) {
137368
137781
  const { basePath } = splitUrlSuffix2(trimmed);
137369
137782
  const normalizedBase = normalizeRelPath(basePath);
137370
137783
  const mapped = options.sourceAssets?.get(trimmed) ?? options.sourceAssets?.get(basePath) ?? options.sourceAssets?.get(normalizedBase);
137371
- if (mapped && existsSync50(mapped)) return mapped;
137784
+ if (mapped && existsSync51(mapped)) return mapped;
137372
137785
  if (isHttpUrl(trimmed)) return null;
137373
137786
  const projectRelative = basePath.startsWith("/") ? basePath.slice(1) : basePath;
137374
137787
  const candidates = [
137375
137788
  isAbsolute12(basePath) ? basePath : resolve31(options.projectDir, projectRelative),
137376
137789
  resolve31(options.downloadDir, normalizedBase)
137377
137790
  ];
137378
- return candidates.find((candidate) => existsSync50(candidate)) ?? null;
137791
+ return candidates.find((candidate) => existsSync51(candidate)) ?? null;
137379
137792
  }
137380
137793
  function isUsableFile(path) {
137381
137794
  try {
@@ -137484,10 +137897,10 @@ async function runAnimatedGifTranscode(request) {
137484
137897
  throw result.error ?? new Error(`Animated GIF transcode failed (${result.exitCode}): ${result.stderr.slice(-500)}`);
137485
137898
  }
137486
137899
  async function ensurePreparedWebm(input2) {
137487
- if (!existsSync50(dirname24(input2.cachePath))) {
137900
+ if (!existsSync51(dirname24(input2.cachePath))) {
137488
137901
  mkdirSync25(dirname24(input2.cachePath), { recursive: true });
137489
137902
  }
137490
- if (!existsSync50(dirname24(input2.outputPath))) {
137903
+ if (!existsSync51(dirname24(input2.outputPath))) {
137491
137904
  mkdirSync25(dirname24(input2.outputPath), { recursive: true });
137492
137905
  }
137493
137906
  if (!isUsableFile(input2.cachePath)) {
@@ -137704,11 +138117,11 @@ var init_semaphore = __esm({
137704
138117
 
137705
138118
  // ../producer/src/utils/mediaProbeConcurrency.ts
137706
138119
  async function withMediaProbeSlot(operation) {
137707
- const release4 = await sharedMediaProbeSemaphore.acquire();
138120
+ const release5 = await sharedMediaProbeSemaphore.acquire();
137708
138121
  try {
137709
138122
  return await operation();
137710
138123
  } finally {
137711
- release4();
138124
+ release5();
137712
138125
  }
137713
138126
  }
137714
138127
  var MEDIA_PROBE_CONCURRENCY, sharedMediaProbeSemaphore;
@@ -137722,7 +138135,7 @@ var init_mediaProbeConcurrency = __esm({
137722
138135
  });
137723
138136
 
137724
138137
  // ../producer/src/services/assetMediaType.ts
137725
- import { existsSync as existsSync51 } from "fs";
138138
+ import { existsSync as existsSync53 } from "fs";
137726
138139
  function detectedAssetMediaType(profile) {
137727
138140
  if (profile.visualKind === "moving") return "video";
137728
138141
  if (profile.visualKind === "still") return "image";
@@ -137773,7 +138186,7 @@ async function preflightCompositionAssetMediaTypes(input2) {
137773
138186
  input2.projectDir,
137774
138187
  input2.compiledDir
137775
138188
  );
137776
- if (!existsSync51(resolvedPath)) continue;
138189
+ if (!existsSync53(resolvedPath)) continue;
137777
138190
  byPath.set(resolvedPath, [...byPath.get(resolvedPath) ?? [], reference]);
137778
138191
  }
137779
138192
  const mismatches = [];
@@ -137836,7 +138249,7 @@ var init_assetMediaType = __esm({
137836
138249
 
137837
138250
  // ../producer/src/services/htmlCompiler.ts
137838
138251
  import { createHash as createHash17 } from "crypto";
137839
- import { createReadStream as createReadStream5, existsSync as existsSync53, mkdirSync as mkdirSync26, readFileSync as readFileSync37 } from "fs";
138252
+ import { createReadStream as createReadStream5, existsSync as existsSync54, mkdirSync as mkdirSync26, readFileSync as readFileSync37 } from "fs";
137840
138253
  import { join as join58, dirname as dirname25, resolve as resolve33, basename as basename13, relative as relative14 } from "path";
137841
138254
  function logRemoteDownloadTelemetry(event) {
137842
138255
  defaultLogger.info("[Compiler] Remote asset download integrity", { ...event });
@@ -137864,7 +138277,7 @@ function assertSubCompositionsUsable(html, projectDir, visited = /* @__PURE__ */
137864
138277
  if (isUnresolvedAssetPlaceholder(srcPath)) continue;
137865
138278
  const filePath = resolve33(projectDir, srcPath);
137866
138279
  if (visited.has(filePath)) continue;
137867
- if (!existsSync53(filePath)) {
138280
+ if (!existsSync54(filePath)) {
137868
138281
  problems.push({ srcPath, detail: "the file does not exist" });
137869
138282
  continue;
137870
138283
  }
@@ -137991,7 +138404,7 @@ function detectShaderTransitionUsage(html) {
137991
138404
  async function resolveMediaDuration2(src, mediaStart, playbackRate, baseDir, downloadDir, tagName19, elementIdentity, log2) {
137992
138405
  let filePath = src;
137993
138406
  if (isHttpUrl(src)) {
137994
- if (!existsSync53(downloadDir)) mkdirSync26(downloadDir, { recursive: true });
138407
+ if (!existsSync54(downloadDir)) mkdirSync26(downloadDir, { recursive: true });
137995
138408
  try {
137996
138409
  filePath = await downloadToTemp(src, downloadDir, void 0, void 0, void 0, {
137997
138410
  onTelemetry: logRemoteDownloadTelemetry
@@ -138002,7 +138415,7 @@ async function resolveMediaDuration2(src, mediaStart, playbackRate, baseDir, dow
138002
138415
  } else if (!filePath.startsWith("/")) {
138003
138416
  filePath = join58(baseDir, filePath);
138004
138417
  }
138005
- if (!existsSync53(filePath)) {
138418
+ if (!existsSync54(filePath)) {
138006
138419
  return { duration: null, resolvedPath: filePath };
138007
138420
  }
138008
138421
  const withSrcContext = (error) => {
@@ -138135,7 +138548,7 @@ async function parseSubCompositions(html, projectDir, downloadDir, visited = /*
138135
138548
  if (visited.has(filePath)) {
138136
138549
  continue;
138137
138550
  }
138138
- if (!existsSync53(filePath)) {
138551
+ if (!existsSync54(filePath)) {
138139
138552
  continue;
138140
138553
  }
138141
138554
  const rawSubHtml = readFileSync37(filePath, "utf-8");
@@ -138289,7 +138702,7 @@ function inlineSubCompositions2(html, subCompositions, projectDir, variableOverr
138289
138702
  let compHtml = subCompositions.get(srcPath) || null;
138290
138703
  if (!compHtml) {
138291
138704
  const filePath = resolve33(projectDir, srcPath);
138292
- if (existsSync53(filePath)) {
138705
+ if (existsSync54(filePath)) {
138293
138706
  compHtml = readFileSync37(filePath, "utf-8");
138294
138707
  }
138295
138708
  }
@@ -138298,7 +138711,7 @@ function inlineSubCompositions2(html, subCompositions, projectDir, variableOverr
138298
138711
  parseHtml: (htmlStr) => parseHTML(htmlStr).document,
138299
138712
  // Mirrors the preview bundler: a sub-composition's SIBLING assets resolve
138300
138713
  // against its own directory, project-root refs stay as authored.
138301
- assetExists: (path) => existsSync53(resolve33(projectDir, path)),
138714
+ assetExists: (path) => existsSync54(resolve33(projectDir, path)),
138302
138715
  scriptErrorLabel: "[Compiler] Composition script failed",
138303
138716
  // Preserve the authored root wrapper as a child of the host, matching
138304
138717
  // the preview bundler's shape (htmlBundler.ts's prepareFlattenedInnerRoot,
@@ -138471,7 +138884,7 @@ function collectExternalAssets(html, projectDir) {
138471
138884
  if (isPathInside3(absPath, absProjectDir)) {
138472
138885
  return null;
138473
138886
  }
138474
- if (!existsSync53(absPath)) return null;
138887
+ if (!existsSync54(absPath)) return null;
138475
138888
  const safeKey2 = toExternalAssetKey(absPath);
138476
138889
  externalAssets.set(safeKey2, absPath);
138477
138890
  return safeKey2;
@@ -138517,7 +138930,7 @@ function collectExternalAssets(html, projectDir) {
138517
138930
  }
138518
138931
  async function downloadAndRewriteUrls(urlSet, html, remoteDir, warnLabel, logLabel, extraRewrite) {
138519
138932
  if (urlSet.size === 0) return { html, remoteMediaAssets: /* @__PURE__ */ new Map() };
138520
- if (!existsSync53(remoteDir)) mkdirSync26(remoteDir, { recursive: true });
138933
+ if (!existsSync54(remoteDir)) mkdirSync26(remoteDir, { recursive: true });
138521
138934
  const urlToLocal = /* @__PURE__ */ new Map();
138522
138935
  await Promise.all(
138523
138936
  [...urlSet].map(async (url) => {
@@ -138813,7 +139226,7 @@ function rewriteUnresolvableGsapToCdn(html, projectDir) {
138813
139226
  (full2, prefix, src, file, suffix) => {
138814
139227
  if (/^https?:\/\//i.test(src)) return full2;
138815
139228
  const absPath = resolve33(projectDir, src);
138816
- if (existsSync53(absPath)) return full2;
139229
+ if (existsSync54(absPath)) return full2;
138817
139230
  defaultLogger.info(
138818
139231
  `[Compiler] Rewriting missing gsap script to CDN: ${src} \u2192 ${GSAP_CDN_BASE}${file}`
138819
139232
  );
@@ -138826,7 +139239,7 @@ function rebaseDirectEntryAssetPaths(html, projectDir, htmlPath) {
138826
139239
  const entryPath = relative14(projectDir, htmlPath).replace(/\\/g, "/");
138827
139240
  if (!entryPath.includes("/")) return html;
138828
139241
  const { document: document2 } = parseHTML(html);
138829
- const assetExists = (path) => existsSync53(resolve33(projectDir, path));
139242
+ const assetExists = (path) => existsSync54(resolve33(projectDir, path));
138830
139243
  rewriteAssetPaths(
138831
139244
  document2.querySelectorAll("[src], [href]"),
138832
139245
  entryPath,
@@ -140240,7 +140653,7 @@ var init_extractionFailureMetadata = __esm({
140240
140653
  });
140241
140654
 
140242
140655
  // ../producer/src/services/render/stages/extractVideosStage.ts
140243
- import { existsSync as existsSync54 } from "fs";
140656
+ import { existsSync as existsSync55 } from "fs";
140244
140657
  import { join as join61 } from "path";
140245
140658
  function buildExtractionFailureMetadata(inputs) {
140246
140659
  const kindCounts = /* @__PURE__ */ new Map();
@@ -140407,7 +140820,7 @@ async function runExtractVideosStage(input2) {
140407
140820
  const probeFailures = await Promise.all(
140408
140821
  composition.videos.map(async (v2) => {
140409
140822
  const videoPath = resolveProjectRelativeSrc(v2.src, projectDir, compiledDir);
140410
- if (!existsSync54(videoPath)) return null;
140823
+ if (!existsSync55(videoPath)) return null;
140411
140824
  try {
140412
140825
  const attempted = extractionPolicy.maxTransientRetries === 0 ? { result: await extractMediaMetadata(videoPath), retries: 0 } : await runVideoExtractionWithRetry(() => extractMediaMetadata(videoPath), {
140413
140826
  signal: abortSignal,
@@ -140445,7 +140858,7 @@ async function runExtractVideosStage(input2) {
140445
140858
  const probed = await Promise.all(
140446
140859
  composition.images.map(async (img) => {
140447
140860
  const imgPath = resolveProjectRelativeSrc(img.src, projectDir, compiledDir);
140448
- if (!existsSync54(imgPath)) return null;
140861
+ if (!existsSync55(imgPath)) return null;
140449
140862
  const colorSpace = await probeColorSpaceSafely(imgPath, log2);
140450
140863
  if (isHdrColorSpace(colorSpace)) {
140451
140864
  nativeHdrImageIds.add(img.id);
@@ -140681,7 +141094,7 @@ var init_audioStage = __esm({
140681
141094
  });
140682
141095
 
140683
141096
  // ../producer/src/services/render/stages/captureStage.ts
140684
- import { existsSync as existsSync55, readdirSync as readdirSync20, statfsSync as statfsSync3 } from "fs";
141097
+ import { existsSync as existsSync56, readdirSync as readdirSync20, statfsSync as statfsSync3 } from "fs";
140685
141098
  import { join as join64 } from "path";
140686
141099
  function shouldAllowAdaptiveCaptureRetry(workerCount, _explicitlyConfigured) {
140687
141100
  return workerCount > 1;
@@ -140732,7 +141145,7 @@ function assertDiskCaptureHeadroom(framesDir, totalFrames, captureOptions, freeD
140732
141145
  }
140733
141146
  function measureCaptureFrameBytes(workDir, framesDir) {
140734
141147
  let total = sampleDirectoryBytes(framesDir);
140735
- if (!existsSync55(workDir)) return total;
141148
+ if (!existsSync56(workDir)) return total;
140736
141149
  for (const attempt of readdirSync20(workDir)) {
140737
141150
  if (/^retry-\d+-batch-\d+-worker-\d+$/.test(attempt)) {
140738
141151
  total += sampleDirectoryBytes(join64(workDir, attempt));
@@ -141262,7 +141675,7 @@ import { Worker as Worker2 } from "worker_threads";
141262
141675
  import { fileURLToPath as fileURLToPath5, pathToFileURL as pathToFileURL2 } from "url";
141263
141676
  import { dirname as dirname26, join as join66 } from "path";
141264
141677
  import { createRequire as createRequire2 } from "module";
141265
- import { existsSync as existsSync56 } from "fs";
141678
+ import { existsSync as existsSync57 } from "fs";
141266
141679
  import { cpus as cpus4 } from "os";
141267
141680
  function resolveWorkerEntry(explicit) {
141268
141681
  if (explicit && explicit.length > 0) {
@@ -141275,7 +141688,7 @@ function resolveWorkerEntry(explicit) {
141275
141688
  }
141276
141689
  const moduleDir = dirname26(fileURLToPath5(import.meta.url));
141277
141690
  const jsPath = join66(moduleDir, "shaderTransitionWorker.js");
141278
- if (existsSync56(jsPath)) return { path: jsPath, isTs: false };
141691
+ if (existsSync57(jsPath)) return { path: jsPath, isTs: false };
141279
141692
  const tsPath = join66(moduleDir, "shaderTransitionWorker.ts");
141280
141693
  return { path: tsPath, isTs: true };
141281
141694
  }
@@ -141696,7 +142109,7 @@ var init_captureHdrHybridLoop = __esm({
141696
142109
  });
141697
142110
 
141698
142111
  // ../producer/src/services/render/stages/captureHdrStage.ts
141699
- import { existsSync as existsSync57, mkdirSync as mkdirSync27 } from "fs";
142112
+ import { existsSync as existsSync58, mkdirSync as mkdirSync27 } from "fs";
141700
142113
  import { join as join68 } from "path";
141701
142114
  async function runCaptureHdrStage(input2) {
141702
142115
  const {
@@ -141853,7 +142266,7 @@ async function runCaptureHdrStage(input2) {
141853
142266
  }
141854
142267
  const debugDumpEnabled = process.env.KEEP_TEMP === "1";
141855
142268
  const debugDumpDir = debugDumpEnabled ? join68(framesDir, "debug-composite") : null;
141856
- if (debugDumpDir && !existsSync57(debugDumpDir)) {
142269
+ if (debugDumpDir && !existsSync58(debugDumpDir)) {
141857
142270
  mkdirSync27(debugDumpDir, { recursive: true });
141858
142271
  }
141859
142272
  const compositeTransfer = resolveCompositeTransfer(hasHdrContent, effectiveHdr);
@@ -142061,7 +142474,7 @@ var init_gifEncodeArgs = __esm({
142061
142474
  });
142062
142475
 
142063
142476
  // ../producer/src/services/render/stages/encodeStage.ts
142064
- import { copyFileSync as copyFileSync5, existsSync as existsSync58, mkdirSync as mkdirSync28, readdirSync as readdirSync21, rmSync as rmSync21, statSync as statSync24 } from "fs";
142477
+ import { copyFileSync as copyFileSync5, existsSync as existsSync59, mkdirSync as mkdirSync28, readdirSync as readdirSync21, rmSync as rmSync21, statSync as statSync24 } from "fs";
142065
142478
  import { dirname as dirname27, join as join70 } from "path";
142066
142479
  function resolveGifLoop(loop) {
142067
142480
  const resolved2 = loop ?? 0;
@@ -142124,7 +142537,7 @@ async function encodeGifFromDir(framesDir, framePattern, outputPath, input2) {
142124
142537
  failureReason: gifResult.failureReason
142125
142538
  };
142126
142539
  }
142127
- const fileSize = existsSync58(outputPath) ? statSync24(outputPath).size : 0;
142540
+ const fileSize = existsSync59(outputPath) ? statSync24(outputPath).size : 0;
142128
142541
  return {
142129
142542
  success: true,
142130
142543
  outputPath,
@@ -142162,7 +142575,7 @@ async function runEncodeStage(input2) {
142162
142575
  const stage5Start = Date.now();
142163
142576
  if (isPngSequence) {
142164
142577
  updateJobStatus(job, "encoding", "Writing PNG sequence", 75, onProgress);
142165
- if (!existsSync58(outputPath)) mkdirSync28(outputPath, { recursive: true });
142578
+ if (!existsSync59(outputPath)) mkdirSync28(outputPath, { recursive: true });
142166
142579
  const captured = readdirSync21(framesDir).filter((name) => name.endsWith(".png")).sort();
142167
142580
  if (captured.length === 0) {
142168
142581
  throw new Error(
@@ -142173,7 +142586,7 @@ async function runEncodeStage(input2) {
142173
142586
  const dst = join70(outputPath, formatExportFrameName(i, "png"));
142174
142587
  copyFileSync5(join70(framesDir, name), dst);
142175
142588
  });
142176
- if (hasAudio && audioOutputPath && existsSync58(audioOutputPath)) {
142589
+ if (hasAudio && audioOutputPath && existsSync59(audioOutputPath)) {
142177
142590
  copyFileSync5(audioOutputPath, join70(outputPath, MIXED_AUDIO_FILENAME));
142178
142591
  log2.info(
142179
142592
  `[Render] png-sequence: ${MIXED_AUDIO_FILENAME} sidecar written to ${outputPath}/${MIXED_AUDIO_FILENAME}`
@@ -142783,7 +143196,7 @@ var init_motionBlurRoute = __esm({
142783
143196
 
142784
143197
  // ../producer/src/services/renderOrchestrator.ts
142785
143198
  import {
142786
- existsSync as existsSync59,
143199
+ existsSync as existsSync60,
142787
143200
  mkdirSync as mkdirSync29,
142788
143201
  mkdtempSync as mkdtempSync14,
142789
143202
  readFileSync as readFileSync38,
@@ -142943,7 +143356,7 @@ function findMissingFrameRanges(totalFrames, framesDir, frameExt) {
142943
143356
  let rangeStart = null;
142944
143357
  for (let frameIndex = 0; frameIndex < totalFrames; frameIndex++) {
142945
143358
  const framePath = join73(framesDir, formatCaptureFrameName(frameIndex, frameExt));
142946
- const missing = !existsSync59(framePath) || statSync25(framePath).size <= 8;
143359
+ const missing = !existsSync60(framePath) || statSync25(framePath).size <= 8;
142947
143360
  if (missing && rangeStart === null) {
142948
143361
  rangeStart = frameIndex;
142949
143362
  } else if (!missing && rangeStart !== null) {
@@ -143026,7 +143439,7 @@ function countCapturedFrames(totalFrames, framesDir, frameExt) {
143026
143439
  let captured = 0;
143027
143440
  for (let frameIndex = 0; frameIndex < totalFrames; frameIndex++) {
143028
143441
  const framePath = join73(framesDir, formatCaptureFrameName(frameIndex, frameExt));
143029
- if (existsSync59(framePath)) captured++;
143442
+ if (existsSync60(framePath)) captured++;
143030
143443
  }
143031
143444
  return captured;
143032
143445
  }
@@ -143608,7 +144021,7 @@ async function executeRenderJob(job, projectDir, outputPath, progressSink, abort
143608
144021
  const producerRoot = process.env.PRODUCER_RENDERS_DIR ? resolve34(process.env.PRODUCER_RENDERS_DIR, "..") : resolve34(moduleDir, "../..");
143609
144022
  const debugDir = join73(producerRoot, ".debug");
143610
144023
  const outputDir = dirname29(outputPath);
143611
- if (!existsSync59(outputDir)) mkdirSync29(outputDir, { recursive: true });
144024
+ if (!existsSync60(outputDir)) mkdirSync29(outputDir, { recursive: true });
143612
144025
  const workDir = job.config.debug ? join73(debugDir, job.id) : mkdtempSync14(resolveRenderWorkDirPrefix(outputPath, job.id));
143613
144026
  const pipelineStart = Date.now();
143614
144027
  const baseLog = job.config.logger ?? defaultLogger;
@@ -143740,7 +144153,7 @@ async function executeRenderPipeline(input2) {
143740
144153
  job.startedAt = /* @__PURE__ */ new Date();
143741
144154
  assertNotAborted();
143742
144155
  assertConfiguredFfmpegBinariesExist();
143743
- if (!existsSync59(workDir)) mkdirSync29(workDir, { recursive: true });
144156
+ if (!existsSync60(workDir)) mkdirSync29(workDir, { recursive: true });
143744
144157
  if (job.config.debug) {
143745
144158
  log2.info("[Render] Debug artifacts enabled", { workDir, logPath });
143746
144159
  }
@@ -143770,7 +144183,7 @@ async function executeRenderPipeline(input2) {
143770
144183
  });
143771
144184
  const entryFile = job.config.entryFile || "index.html";
143772
144185
  let htmlPath = join73(projectDir, entryFile);
143773
- if (!existsSync59(htmlPath)) {
144186
+ if (!existsSync60(htmlPath)) {
143774
144187
  throw new Error(`Entry file not found: ${htmlPath}`);
143775
144188
  }
143776
144189
  assertNotAborted();
@@ -143778,7 +144191,7 @@ async function executeRenderPipeline(input2) {
143778
144191
  if (entryFile !== "index.html" && rawEntry.trimStart().startsWith("<template")) {
143779
144192
  const wrapperPath = join73(workDir, "standalone-entry.html");
143780
144193
  const projectIndexPath = join73(projectDir, "index.html");
143781
- if (!existsSync59(projectIndexPath)) {
144194
+ if (!existsSync60(projectIndexPath)) {
143782
144195
  throw new Error(
143783
144196
  `Template entry file "${entryFile}" requires a project index.html to extract its render shell.`
143784
144197
  );
@@ -143831,7 +144244,8 @@ async function executeRenderPipeline(input2) {
143831
144244
  let deClampReason = cfg.useDrawElement ? void 0 : explainDrawElementDisabled({
143832
144245
  platform: process.platform,
143833
144246
  browserGpuMode: cfg.browserGpuMode,
143834
- workerEncode: cfg.enableDrawElementWorkerEncode
144247
+ workerEncode: cfg.enableDrawElementWorkerEncode,
144248
+ chromeCeiling: chromeMajorCeiling()
143835
144249
  });
143836
144250
  let deWorkerInversion;
143837
144251
  let deParallelStreamForced = false;
@@ -144077,7 +144491,7 @@ async function executeRenderPipeline(input2) {
144077
144491
  throw new Error("File server failed to initialize before frame capture");
144078
144492
  }
144079
144493
  const framesDir = join73(workDir, "captured-frames");
144080
- if (!existsSync59(framesDir)) mkdirSync29(framesDir, { recursive: true });
144494
+ if (!existsSync60(framesDir)) mkdirSync29(framesDir, { recursive: true });
144081
144495
  const resolvedBrowserGpuMode = await resolveBrowserGpuMode(cfg.browserGpuMode, {
144082
144496
  chromePath: resolveHeadlessShellPath(cfg),
144083
144497
  browserTimeout: cfg.browserTimeout
@@ -145190,7 +145604,7 @@ async function executeRenderPipeline(input2) {
145190
145604
  })
145191
145605
  );
145192
145606
  const totalElapsed = Date.now() - pipelineStart;
145193
- const tmpPeakBytes = existsSync59(workDir) ? sampleDirectoryBytes(workDir) : 0;
145607
+ const tmpPeakBytes = existsSync60(workDir) ? sampleDirectoryBytes(workDir) : 0;
145194
145608
  recordTransientRetryObservability();
145195
145609
  observability.checkpoint("pipeline", "artifact validated", { totalElapsedMs: totalElapsed });
145196
145610
  const observabilitySummary = observability.summary({
@@ -145267,7 +145681,7 @@ async function executeRenderPipeline(input2) {
145267
145681
  }
145268
145682
  }
145269
145683
  if (job.config.debug) {
145270
- if (!isPngSequence && !isHls && existsSync59(stagedOutputPath)) {
145684
+ if (!isPngSequence && !isHls && existsSync60(stagedOutputPath)) {
145271
145685
  const debugOutput = join73(workDir, `output${videoExt}`);
145272
145686
  copyFileSync6(stagedOutputPath, debugOutput);
145273
145687
  }
@@ -145973,7 +146387,7 @@ var init_config3 = __esm({
145973
146387
 
145974
146388
  // ../producer/src/services/hyperframeLint.ts
145975
146389
  import {
145976
- existsSync as existsSync60,
146390
+ existsSync as existsSync61,
145977
146391
  readFileSync as readFileSync39,
145978
146392
  statSync as statSync26,
145979
146393
  openSync as openSync12,
@@ -146026,7 +146440,7 @@ function readEntryHtml(filePath) {
146026
146440
  }
146027
146441
  function readProjectEntryFile(projectDir, preferredEntryFile) {
146028
146442
  const absProjectDir = resolve35(projectDir);
146029
- if (!existsSync60(absProjectDir) || !statSync26(absProjectDir).isDirectory()) {
146443
+ if (!existsSync61(absProjectDir) || !statSync26(absProjectDir).isDirectory()) {
146030
146444
  return { error: `Project directory not found: ${absProjectDir}` };
146031
146445
  }
146032
146446
  const entryCandidates = [preferredEntryFile, "index.html", "src/index.html"].filter(
@@ -146098,7 +146512,7 @@ var init_hyperframeLint = __esm({
146098
146512
  import { Worker as Worker3 } from "worker_threads";
146099
146513
  import { fileURLToPath as fileURLToPath7 } from "url";
146100
146514
  import { dirname as dirname30, join as join75 } from "path";
146101
- import { existsSync as existsSync61 } from "fs";
146515
+ import { existsSync as existsSync63 } from "fs";
146102
146516
  async function startHealthWorker(options = {}) {
146103
146517
  const log2 = options.logger ?? defaultLogger2();
146104
146518
  const port = options.port ?? parseInt(process.env.PRODUCER_HEALTH_PORT ?? String(DEFAULT_HEALTH_PORT), 10);
@@ -146174,7 +146588,7 @@ function resolveWorkerEntry2() {
146174
146588
  const here = dirname30(fileURLToPath7(import.meta.url));
146175
146589
  const candidates = [join75(here, "healthWorkerThread.js"), join75(here, "healthWorkerThread.ts")];
146176
146590
  for (const candidate of candidates) {
146177
- if (existsSync61(candidate)) return candidate;
146591
+ if (existsSync63(candidate)) return candidate;
146178
146592
  }
146179
146593
  return void 0;
146180
146594
  }
@@ -146188,7 +146602,7 @@ var init_healthWorker = __esm({
146188
146602
 
146189
146603
  // ../producer/src/server.ts
146190
146604
  import {
146191
- existsSync as existsSync63,
146605
+ existsSync as existsSync64,
146192
146606
  mkdirSync as mkdirSync30,
146193
146607
  statSync as statSync27,
146194
146608
  mkdtempSync as mkdtempSync15,
@@ -146322,7 +146736,7 @@ function resolvePreparedRenderOutput(prepared, rendersDir, log2) {
146322
146736
  const { input: input2, cleanupProjectDir } = prepared;
146323
146737
  const absoluteOutputPath = resolveOutputPath(input2.projectDir, input2.outputPath, rendersDir, log2);
146324
146738
  const outputDir = dirname31(absoluteOutputPath);
146325
- if (!existsSync63(outputDir)) mkdirSync30(outputDir, { recursive: true });
146739
+ if (!existsSync64(outputDir)) mkdirSync30(outputDir, { recursive: true });
146326
146740
  return { input: input2, cleanupProjectDir, absoluteOutputPath };
146327
146741
  }
146328
146742
  function validateRenderOverrides(body) {
@@ -146360,11 +146774,11 @@ function prepareProjectDirectory(projectDir, options) {
146360
146774
  const candidate = nonEmptyString2(projectDir);
146361
146775
  if (!candidate) return null;
146362
146776
  const absProjectDir = resolve36(candidate);
146363
- if (!existsSync63(absProjectDir) || !statSync27(absProjectDir).isDirectory()) {
146777
+ if (!existsSync64(absProjectDir) || !statSync27(absProjectDir).isDirectory()) {
146364
146778
  return { error: `Project directory not found: ${absProjectDir}` };
146365
146779
  }
146366
146780
  const entry = options.entryFile || "index.html";
146367
- if (!existsSync63(resolve36(absProjectDir, entry))) {
146781
+ if (!existsSync64(resolve36(absProjectDir, entry))) {
146368
146782
  return { error: `Entry file "${entry}" not found in project directory: ${absProjectDir}` };
146369
146783
  }
146370
146784
  return { prepared: { input: { projectDir: absProjectDir, ...options } } };
@@ -146456,7 +146870,7 @@ function cleanupTempDir(dir, log2) {
146456
146870
  }
146457
146871
  }
146458
146872
  function outputFileSize(path) {
146459
- return existsSync63(path) ? statSync27(path).size : 0;
146873
+ return existsSync64(path) ? statSync27(path).size : 0;
146460
146874
  }
146461
146875
  function createBlockingProgressReporter(log2, requestId) {
146462
146876
  let lastLoggedPct = -10;
@@ -146610,7 +147024,7 @@ function createRenderHandlers(options = {}) {
146610
147024
  rendersDir,
146611
147025
  log2
146612
147026
  );
146613
- const release4 = await renderSemaphore.acquire();
147027
+ const release5 = await renderSemaphore.acquire();
146614
147028
  log2.info("render started", {
146615
147029
  requestId,
146616
147030
  projectDir: input2.projectDir,
@@ -146674,7 +147088,7 @@ function createRenderHandlers(options = {}) {
146674
147088
  500
146675
147089
  );
146676
147090
  } finally {
146677
- release4();
147091
+ release5();
146678
147092
  cleanupTempDir(cleanupProjectDir, log2);
146679
147093
  }
146680
147094
  };
@@ -146703,7 +147117,7 @@ function createRenderHandlers(options = {}) {
146703
147117
  })
146704
147118
  });
146705
147119
  }
146706
- const release4 = await renderSemaphore.acquire();
147120
+ const release5 = await renderSemaphore.acquire();
146707
147121
  try {
146708
147122
  await executeRenderJob(
146709
147123
  job,
@@ -146740,7 +147154,7 @@ function createRenderHandlers(options = {}) {
146740
147154
  log: log2
146741
147155
  });
146742
147156
  } finally {
146743
- release4();
147157
+ release5();
146744
147158
  c3.req.raw.signal.removeEventListener("abort", onRequestAbort);
146745
147159
  cleanupTempDir(cleanupProjectDir, log2);
146746
147160
  }
@@ -146752,7 +147166,7 @@ function createRenderHandlers(options = {}) {
146752
147166
  if (!artifact) {
146753
147167
  return c3.json({ success: false, error: "Output artifact not found or expired" }, 404);
146754
147168
  }
146755
- if (!existsSync63(artifact.path)) {
147169
+ if (!existsSync64(artifact.path)) {
146756
147170
  store.delete(token);
146757
147171
  return c3.json({ success: false, error: "Output artifact file missing" }, 404);
146758
147172
  }
@@ -147030,7 +147444,7 @@ var init_planHash = __esm({
147030
147444
  });
147031
147445
 
147032
147446
  // ../producer/src/services/render/stages/freezePlan.ts
147033
- import { existsSync as existsSync64, mkdirSync as mkdirSync31, readFileSync as readFileSync40, readdirSync as readdirSync24, writeFileSync as writeFileSync23 } from "fs";
147447
+ import { existsSync as existsSync65, mkdirSync as mkdirSync31, readFileSync as readFileSync40, readdirSync as readdirSync24, writeFileSync as writeFileSync23 } from "fs";
147034
147448
  import { join as join77, relative as relative16, resolve as resolve37 } from "path";
147035
147449
  function stripUndefined(value) {
147036
147450
  if (Array.isArray(value)) return value.map(stripUndefined);
@@ -147090,10 +147504,10 @@ function collectPlanAssetShas(planDir) {
147090
147504
  function recomputePlanHashFromPlanDir(planDir) {
147091
147505
  const planJsonPath = join77(planDir, "plan.json");
147092
147506
  const encoderJsonPath = join77(planDir, "meta", "encoder.json");
147093
- if (!existsSync64(planJsonPath)) {
147507
+ if (!existsSync65(planJsonPath)) {
147094
147508
  throw new Error(`[freezePlan] plan.json missing: ${planJsonPath}`);
147095
147509
  }
147096
- if (!existsSync64(encoderJsonPath)) {
147510
+ if (!existsSync65(encoderJsonPath)) {
147097
147511
  throw new Error(`[freezePlan] meta/encoder.json missing: ${encoderJsonPath}`);
147098
147512
  }
147099
147513
  const planJson = JSON.parse(readFileSync40(planJsonPath, "utf-8"));
@@ -147122,11 +147536,11 @@ async function freezePlan(input2) {
147122
147536
  totalFrames,
147123
147537
  hasAudio
147124
147538
  } = input2;
147125
- if (!existsSync64(planDir)) {
147539
+ if (!existsSync65(planDir)) {
147126
147540
  throw new Error(`[freezePlan] planDir does not exist: ${planDir}`);
147127
147541
  }
147128
147542
  const metaDir = join77(planDir, "meta");
147129
- if (!existsSync64(metaDir)) mkdirSync31(metaDir, { recursive: true });
147543
+ if (!existsSync65(metaDir)) mkdirSync31(metaDir, { recursive: true });
147130
147544
  writeFileSync23(
147131
147545
  join77(metaDir, "composition.json"),
147132
147546
  `${JSON.stringify(composition, null, 2)}
@@ -147224,7 +147638,7 @@ var init_runtimeEnvSnapshot = __esm({
147224
147638
  // ../producer/src/services/distributed/shared.ts
147225
147639
  import { execFile as execFileCallback } from "child_process";
147226
147640
  import { dirname as dirname33, join as join78 } from "path";
147227
- import { existsSync as existsSync65, readFileSync as readFileSync41 } from "fs";
147641
+ import { existsSync as existsSync66, readFileSync as readFileSync41 } from "fs";
147228
147642
  import { fileURLToPath as fileURLToPath8 } from "url";
147229
147643
  import { promisify as promisify7 } from "util";
147230
147644
  function isPlanAudioArtifactPath(path) {
@@ -147425,7 +147839,7 @@ function readProducerVersion() {
147425
147839
  let current2 = startDir;
147426
147840
  for (let i = 0; i < 10; i++) {
147427
147841
  const candidate = join78(current2, "package.json");
147428
- if (existsSync65(candidate)) {
147842
+ if (existsSync66(candidate)) {
147429
147843
  try {
147430
147844
  const pkg = JSON.parse(readFileSync41(candidate, "utf-8"));
147431
147845
  if (pkg.name === "@hyperframes/producer" && typeof pkg.version === "string") {
@@ -147610,7 +148024,7 @@ var init_planSize = __esm({
147610
148024
  });
147611
148025
 
147612
148026
  // ../producer/src/services/distributed/plan.ts
147613
- import { cpSync as cpSync3, existsSync as existsSync66, mkdirSync as mkdirSync33, renameSync as renameSync15, rmSync as rmSync26, writeFileSync as writeFileSync24 } from "fs";
148027
+ import { cpSync as cpSync3, existsSync as existsSync67, mkdirSync as mkdirSync33, renameSync as renameSync15, rmSync as rmSync26, writeFileSync as writeFileSync24 } from "fs";
147614
148028
  import { join as join80, relative as relative18, sep as sep13 } from "path";
147615
148029
  function applyDistributedAudioWarningPolicy(job, audioError, audioFailures = [], log2 = defaultLogger) {
147616
148030
  const failureOwner = audioFailures.length === 0 ? void 0 : audioFailures.some((failure) => failure.owner === "system") ? "system" : "user";
@@ -147809,7 +148223,7 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
147809
148223
  useGpu: false,
147810
148224
  browserGpuMode: "software"
147811
148225
  });
147812
- if (!existsSync66(planDir)) mkdirSync33(planDir, { recursive: true });
148226
+ if (!existsSync67(planDir)) mkdirSync33(planDir, { recursive: true });
147813
148227
  const log2 = config.logger ?? defaultLogger;
147814
148228
  const sizeLimitBytes = options.executionPlanSizeLimitBytes ?? config.planDirSizeLimitBytes ?? PLAN_DIR_SIZE_LIMIT_BYTES;
147815
148229
  const abortSignal = config.abortSignal;
@@ -147839,7 +148253,7 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
147839
148253
  });
147840
148254
  const entryFile = config.entryFile ?? "index.html";
147841
148255
  const htmlPath = join80(projectDir, entryFile);
147842
- if (!existsSync66(htmlPath)) {
148256
+ if (!existsSync67(htmlPath)) {
147843
148257
  throw new Error(`[plan] entry file not found: ${htmlPath}`);
147844
148258
  }
147845
148259
  const workDir = join80(planDir, ".plan-work");
@@ -147960,13 +148374,13 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
147960
148374
  }
147961
148375
  const stagedVideoFrames = join80(compiledDir, "__hyperframes_video_frames");
147962
148376
  const videoFramesDst = join80(planDir, "video-frames");
147963
- if (existsSync66(videoFramesDst)) rmSync26(videoFramesDst, { recursive: true, force: true });
147964
- if (existsSync66(stagedVideoFrames)) {
148377
+ if (existsSync67(videoFramesDst)) rmSync26(videoFramesDst, { recursive: true, force: true });
148378
+ if (existsSync67(stagedVideoFrames)) {
147965
148379
  renameSync15(stagedVideoFrames, videoFramesDst);
147966
148380
  } else {
147967
148381
  mkdirSync33(videoFramesDst, { recursive: true });
147968
148382
  }
147969
- if (existsSync66(finalCompiledDir)) rmSync26(finalCompiledDir, { recursive: true, force: true });
148383
+ if (existsSync67(finalCompiledDir)) rmSync26(finalCompiledDir, { recursive: true, force: true });
147970
148384
  renameSync15(compiledDir, finalCompiledDir);
147971
148385
  const planVideosJson = buildPlanVideosJson({
147972
148386
  videos: composition.videos,
@@ -147987,7 +148401,7 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
147987
148401
  "utf-8"
147988
148402
  );
147989
148403
  const planAudioPath = join80(planDir, PLAN_AUDIO_RELATIVE_PATH);
147990
- if (audioResult.hasAudio && existsSync66(audioResult.audioOutputPath)) {
148404
+ if (audioResult.hasAudio && existsSync67(audioResult.audioOutputPath)) {
147991
148405
  renameSync15(audioResult.audioOutputPath, planAudioPath);
147992
148406
  }
147993
148407
  const maxParallel = config.maxParallelChunks ?? DEFAULT_MAX_PARALLEL_CHUNKS;
@@ -148213,7 +148627,7 @@ var init_planV2Layout = __esm({
148213
148627
  // ../producer/src/services/distributed/planV2Publisher.ts
148214
148628
  import {
148215
148629
  copyFileSync as copyFileSync7,
148216
- existsSync as existsSync67,
148630
+ existsSync as existsSync68,
148217
148631
  linkSync as linkSync4,
148218
148632
  mkdirSync as mkdirSync34,
148219
148633
  mkdtempSync as mkdtempSync16,
@@ -148260,7 +148674,7 @@ var init_planV2Publisher = __esm({
148260
148674
  #linkFile;
148261
148675
  #committed = false;
148262
148676
  constructor(destinationDir, options = {}) {
148263
- if (existsSync67(destinationDir)) {
148677
+ if (existsSync68(destinationDir)) {
148264
148678
  throw new PlanV2IntegrityError(`output directory already exists: ${destinationDir}`);
148265
148679
  }
148266
148680
  this.destinationDir = destinationDir;
@@ -148277,7 +148691,7 @@ var init_planV2Publisher = __esm({
148277
148691
  );
148278
148692
  }
148279
148693
  const destinationPath = planV2BlobPath(this.temporaryDir, digest2);
148280
- if (existsSync67(destinationPath)) return;
148694
+ if (existsSync68(destinationPath)) return;
148281
148695
  mkdirSync34(dirname34(destinationPath), { recursive: true });
148282
148696
  const stagingDir = mkdtempSync16(join83(dirname34(destinationPath), ".plan-v2-blob-"));
148283
148697
  const temporaryPath = join83(stagingDir, "blob");
@@ -148295,7 +148709,7 @@ var init_planV2Publisher = __esm({
148295
148709
  }
148296
148710
  async commitManifest(manifestBytes) {
148297
148711
  for (const digest2 of new Set(manifestDigests(manifestBytes))) {
148298
- if (!existsSync67(planV2BlobPath(this.temporaryDir, digest2))) {
148712
+ if (!existsSync68(planV2BlobPath(this.temporaryDir, digest2))) {
148299
148713
  throw new PlanV2IntegrityError(
148300
148714
  `cannot commit manifest before referenced blob is durable: ${digest2}`
148301
148715
  );
@@ -148318,7 +148732,7 @@ var init_planV2Publisher = __esm({
148318
148732
  import {
148319
148733
  closeSync as closeSync14,
148320
148734
  copyFileSync as copyFileSync8,
148321
- existsSync as existsSync68,
148735
+ existsSync as existsSync69,
148322
148736
  lstatSync as lstatSync9,
148323
148737
  mkdirSync as mkdirSync35,
148324
148738
  mkdtempSync as mkdtempSync17,
@@ -148407,7 +148821,7 @@ function assertValidExtractionCacheCompleteSentinel(path) {
148407
148821
  }
148408
148822
  function validateExtractionCacheCompleteSentinels(executionPlanDir) {
148409
148823
  const videoRoot = join84(executionPlanDir, "video-frames");
148410
- if (!existsSync68(videoRoot)) return;
148824
+ if (!existsSync69(videoRoot)) return;
148411
148825
  for (const videoEntry of readdirSync26(videoRoot, { withFileTypes: true })) {
148412
148826
  if (!videoEntry.isDirectory()) continue;
148413
148827
  const videoDir = join84(videoRoot, videoEntry.name);
@@ -148493,7 +148907,7 @@ function parsePlanVideosJson2(value) {
148493
148907
  }
148494
148908
  function materializeExtractedVideoDirectories(planDir) {
148495
148909
  const videosPath = join84(planDir, PLAN_VIDEOS_META_RELATIVE_PATH);
148496
- if (!existsSync68(videosPath)) return;
148910
+ if (!existsSync69(videosPath)) return;
148497
148911
  const videos = parsePlanVideosJson2(readJsonFile(videosPath, PLAN_VIDEOS_META_RELATIVE_PATH));
148498
148912
  for (const video of videos.extracted) {
148499
148913
  mkdirSync35(resolveExtractedVideoOutputDir(planDir, video.videoId), { recursive: true });
@@ -148522,9 +148936,9 @@ function parseChunkSlices(value) {
148522
148936
  }
148523
148937
  function buildVideoChunkDependencies(executionPlanDir, dimensions) {
148524
148938
  const videoRoot = join84(executionPlanDir, "video-frames");
148525
- const hasExtractedFrames = existsSync68(videoRoot) && listFiles(videoRoot).length > 0;
148939
+ const hasExtractedFrames = existsSync69(videoRoot) && listFiles(videoRoot).length > 0;
148526
148940
  const videosPath = join84(executionPlanDir, PLAN_VIDEOS_META_RELATIVE_PATH);
148527
- if (!existsSync68(videosPath)) {
148941
+ if (!existsSync69(videosPath)) {
148528
148942
  return hasExtractedFrames ? { mode: "full-source-pack", dependencies: null } : { mode: "exact-rendered-frames", dependencies: /* @__PURE__ */ new Map() };
148529
148943
  }
148530
148944
  const chunksPath = join84(executionPlanDir, "meta", "chunks.json");
@@ -148563,7 +148977,7 @@ function computeManifestHash(manifest) {
148563
148977
  return sha256Hex(`${PLAN_V2_HASH_PREFIX}${canonicalJsonStringify(manifestPayload(manifest))}`);
148564
148978
  }
148565
148979
  function writeBlob(sourcePath, destinationPath) {
148566
- if (existsSync68(destinationPath)) return;
148980
+ if (existsSync69(destinationPath)) return;
148567
148981
  mkdirSync35(dirname35(destinationPath), { recursive: true });
148568
148982
  const temporaryDir = mkdtempSync17(join84(dirname35(destinationPath), ".plan-v2-blob-"));
148569
148983
  const temporaryPath = join84(temporaryDir, "blob");
@@ -148576,7 +148990,7 @@ function writeBlob(sourcePath, destinationPath) {
148576
148990
  }
148577
148991
  function buildPlanV2Publication(executionPlanDir) {
148578
148992
  const executionPlanPath = join84(executionPlanDir, "plan.json");
148579
- if (!existsSync68(executionPlanPath)) {
148993
+ if (!existsSync69(executionPlanPath)) {
148580
148994
  throw new PlanV2IntegrityError(`execution plan is missing plan.json: ${executionPlanPath}`);
148581
148995
  }
148582
148996
  const executionPlanValue = readJsonFile(executionPlanPath, "execution plan.json");
@@ -148646,7 +149060,7 @@ function buildPlanV2Publication(executionPlanDir) {
148646
149060
  };
148647
149061
  }
148648
149062
  function createPlanV2FromExecutionPlan(executionPlanDir, planV2Dir) {
148649
- if (existsSync68(planV2Dir)) {
149063
+ if (existsSync69(planV2Dir)) {
148650
149064
  throw new PlanV2IntegrityError(`output directory already exists: ${planV2Dir}`);
148651
149065
  }
148652
149066
  const publication = buildPlanV2Publication(executionPlanDir);
@@ -148713,7 +149127,7 @@ async function planV2WithPublisher(projectDir, config, publisher, options = {})
148713
149127
  }
148714
149128
  }
148715
149129
  async function planV2(projectDir, config, planV2Dir) {
148716
- if (existsSync68(planV2Dir)) {
149130
+ if (existsSync69(planV2Dir)) {
148717
149131
  throw new PlanV2IntegrityError(`output directory already exists: ${planV2Dir}`);
148718
149132
  }
148719
149133
  const publisher = new LocalPlanV2ArtifactPublisher(planV2Dir);
@@ -148860,7 +149274,7 @@ function parsePlanV2Manifest(value) {
148860
149274
  }
148861
149275
  function readPlanV2Manifest(planV2Dir) {
148862
149276
  const manifestPath3 = join84(planV2Dir, "plan.json");
148863
- if (!existsSync68(manifestPath3)) {
149277
+ if (!existsSync69(manifestPath3)) {
148864
149278
  throw new PlanV2IntegrityError(`missing v2 manifest: ${manifestPath3}`);
148865
149279
  }
148866
149280
  const value = readJsonFile(manifestPath3, "v2 manifest");
@@ -148879,7 +149293,7 @@ function listPlanV2ArtifactsForTarget(manifest, target) {
148879
149293
  }
148880
149294
  function verifyBlob(planV2Dir, artifact) {
148881
149295
  const sourcePath = planV2BlobPath(planV2Dir, artifact.sha256);
148882
- if (!existsSync68(sourcePath)) {
149296
+ if (!existsSync69(sourcePath)) {
148883
149297
  throw new PlanV2IntegrityError(`missing content-addressed artifact ${artifact.sha256}`);
148884
149298
  }
148885
149299
  const stats = statSync29(sourcePath);
@@ -148892,7 +149306,7 @@ function verifyBlob(planV2Dir, artifact) {
148892
149306
  return sourcePath;
148893
149307
  }
148894
149308
  function materializePlanV2Target(planV2Dir, target, destinationDir) {
148895
- if (existsSync68(destinationDir)) {
149309
+ if (existsSync69(destinationDir)) {
148896
149310
  throw new PlanV2IntegrityError(`materialization destination already exists: ${destinationDir}`);
148897
149311
  }
148898
149312
  const manifest = readPlanV2Manifest(planV2Dir);
@@ -148936,7 +149350,7 @@ function materializePlanV2Target(planV2Dir, target, destinationDir) {
148936
149350
  }
148937
149351
  function validatePlanV2MaterializedTarget(planDir, expectedTarget) {
148938
149352
  const markerPath = join84(planDir, PLAN_V2_MATERIALIZATION_MARKER);
148939
- if (!existsSync68(markerPath)) return null;
149353
+ if (!existsSync69(markerPath)) return null;
148940
149354
  const marker = readJsonFile(markerPath, "materialization marker");
148941
149355
  if (!isRecord8(marker) || !isRecord8(marker.manifest) || !isRecord8(marker.target)) {
148942
149356
  throw new PlanV2IntegrityError("malformed materialization marker");
@@ -148951,7 +149365,7 @@ function validatePlanV2MaterializedTarget(planDir, expectedTarget) {
148951
149365
  const required = listPlanV2ArtifactsForTarget(manifest, expectedTarget);
148952
149366
  for (const artifact of required) {
148953
149367
  const path = join84(planDir, ...artifact.path.split("/"));
148954
- if (!existsSync68(path) || statSync29(path).size !== artifact.sizeBytes) {
149368
+ if (!existsSync69(path) || statSync29(path).size !== artifact.sizeBytes) {
148955
149369
  throw new PlanV2IntegrityError(
148956
149370
  `materialized artifact missing or truncated: ${artifact.path}`
148957
149371
  );
@@ -148984,7 +149398,7 @@ var init_planV2 = __esm({
148984
149398
  // ../producer/src/services/distributed/assemble.ts
148985
149399
  import {
148986
149400
  cpSync as cpSync4,
148987
- existsSync as existsSync69,
149401
+ existsSync as existsSync70,
148988
149402
  mkdirSync as mkdirSync36,
148989
149403
  mkdtempSync as mkdtempSync18,
148990
149404
  readFileSync as readFileSync44,
@@ -149001,13 +149415,13 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
149001
149415
  const cfr = options?.cfr === true;
149002
149416
  const planJsonPath = join85(planDir, "plan.json");
149003
149417
  const chunksJsonPath = join85(planDir, "meta", "chunks.json");
149004
- if (!existsSync69(planJsonPath)) {
149418
+ if (!existsSync70(planJsonPath)) {
149005
149419
  throw new Error(`[assemble] planDir missing plan.json: ${planJsonPath}`);
149006
149420
  }
149007
149421
  const plan2 = JSON.parse(readFileSync44(planJsonPath, "utf-8"));
149008
149422
  readPlanProtocolV1(plan2, DISTRIBUTED_RENDER_CAPABILITIES.roles.assembler);
149009
149423
  validatePlanV2MaterializedTarget(planDir, { role: "assembler" });
149010
- if (!existsSync69(chunksJsonPath)) {
149424
+ if (!existsSync70(chunksJsonPath)) {
149011
149425
  throw new Error(`[assemble] planDir missing meta/chunks.json: ${chunksJsonPath}`);
149012
149426
  }
149013
149427
  const chunks = JSON.parse(readFileSync44(chunksJsonPath, "utf-8"));
@@ -149017,14 +149431,14 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
149017
149431
  );
149018
149432
  }
149019
149433
  for (const path of chunkPaths) {
149020
- if (!existsSync69(path)) {
149434
+ if (!existsSync70(path)) {
149021
149435
  throw new Error(`[assemble] chunk path does not exist: ${path}`);
149022
149436
  }
149023
149437
  }
149024
149438
  if (plan2.dimensions.format === "png-sequence") {
149025
149439
  return mergePngFrameDirs(chunkPaths, outputPath, plan2.totalFrames, audioPath, start);
149026
149440
  }
149027
- if (!existsSync69(dirname36(outputPath))) {
149441
+ if (!existsSync70(dirname36(outputPath))) {
149028
149442
  mkdirSync36(dirname36(outputPath), { recursive: true });
149029
149443
  }
149030
149444
  const workDir = mkdtempSync18(`${outputPath}.assemble-work-`);
@@ -149080,7 +149494,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
149080
149494
  );
149081
149495
  }
149082
149496
  const encoderJsonPath = join85(planDir, "meta", "encoder.json");
149083
- if (!existsSync69(encoderJsonPath)) {
149497
+ if (!existsSync70(encoderJsonPath)) {
149084
149498
  throw new Error(`[assemble] planDir missing meta/encoder.json: ${encoderJsonPath}`);
149085
149499
  }
149086
149500
  const encoderJson = JSON.parse(readFileSync44(encoderJsonPath, "utf-8"));
@@ -149123,7 +149537,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
149123
149537
  });
149124
149538
  }
149125
149539
  let normalizedAudioPath = null;
149126
- if (audioPath !== null && existsSync69(audioPath)) {
149540
+ if (audioPath !== null && existsSync70(audioPath)) {
149127
149541
  const paddedAudioPath = join85(workDir, "audio-padded.m4a");
149128
149542
  const padTrimResult = await padOrTrimAudioToVideoFrameCount({
149129
149543
  videoPath: postConcatPath,
@@ -149180,7 +149594,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
149180
149594
  });
149181
149595
  }
149182
149596
  }
149183
- const fileSize = existsSync69(outputPath) ? statSync30(outputPath).size : 0;
149597
+ const fileSize = existsSync70(outputPath) ? statSync30(outputPath).size : 0;
149184
149598
  return {
149185
149599
  outputPath,
149186
149600
  durationMs: Date.now() - start,
@@ -149189,7 +149603,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
149189
149603
  };
149190
149604
  }
149191
149605
  function mergePngFrameDirs(chunkPaths, outputPath, totalFrames, audioPath, startTimeMs) {
149192
- if (existsSync69(outputPath)) rmSync29(outputPath, { recursive: true, force: true });
149606
+ if (existsSync70(outputPath)) rmSync29(outputPath, { recursive: true, force: true });
149193
149607
  mkdirSync36(outputPath, { recursive: true });
149194
149608
  let globalIdx = 0;
149195
149609
  for (const chunkDir of chunkPaths) {
@@ -149213,7 +149627,7 @@ function mergePngFrameDirs(chunkPaths, outputPath, totalFrames, audioPath, start
149213
149627
  `[assemble] png-sequence frame count mismatch: merged ${globalIdx} frames vs plan.totalFrames=${totalFrames}. Using on-disk count.`
149214
149628
  );
149215
149629
  }
149216
- if (audioPath !== null && existsSync69(audioPath)) {
149630
+ if (audioPath !== null && existsSync70(audioPath)) {
149217
149631
  const sidecar = join85(outputPath, MIXED_AUDIO_FILENAME);
149218
149632
  cpSync4(audioPath, sidecar);
149219
149633
  }
@@ -149247,7 +149661,7 @@ var init_assemble = __esm({
149247
149661
 
149248
149662
  // ../producer/src/services/distributed/renderChunk.ts
149249
149663
  import { randomBytes } from "crypto";
149250
- import { existsSync as existsSync70, mkdirSync as mkdirSync37, readFileSync as readFileSync45, readdirSync as readdirSync28, rmSync as rmSync30, writeFileSync as writeFileSync28 } from "fs";
149664
+ import { existsSync as existsSync71, mkdirSync as mkdirSync37, readFileSync as readFileSync45, readdirSync as readdirSync28, rmSync as rmSync30, writeFileSync as writeFileSync28 } from "fs";
149251
149665
  import { extname as extname14, join as join86 } from "path";
149252
149666
  function validatePlanVideosForChunk(value) {
149253
149667
  try {
@@ -149317,7 +149731,7 @@ function rebuildExtractedFramesFromPlanDir(planDir, videos, indexMode = "dense-v
149317
149731
  const result = [];
149318
149732
  for (const v2 of videos) {
149319
149733
  const outputDir = join86(planDir, "video-frames", v2.videoId);
149320
- if (!existsSync70(outputDir)) {
149734
+ if (!existsSync71(outputDir)) {
149321
149735
  throw new Error(
149322
149736
  `[renderChunk] planDir missing extracted video frames for ${JSON.stringify(v2.videoId)}: ${outputDir} not present. plan() should have written frames here; the planDir is malformed.`
149323
149737
  );
@@ -149380,7 +149794,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
149380
149794
  const planJsonPath = join86(planDir, "plan.json");
149381
149795
  const encoderJsonPath = join86(planDir, "meta", "encoder.json");
149382
149796
  const chunksJsonPath = join86(planDir, "meta", "chunks.json");
149383
- if (!existsSync70(planJsonPath)) {
149797
+ if (!existsSync71(planJsonPath)) {
149384
149798
  throw new RenderChunkValidationError(
149385
149799
  MISSING_PLAN_ARTIFACT,
149386
149800
  `[renderChunk] planDir is missing required artifact: ${planJsonPath}`
@@ -149394,7 +149808,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
149394
149808
  chunkIndex
149395
149809
  });
149396
149810
  for (const required of [encoderJsonPath, chunksJsonPath]) {
149397
- if (!existsSync70(required)) {
149811
+ if (!existsSync71(required)) {
149398
149812
  throw new RenderChunkValidationError(
149399
149813
  MISSING_PLAN_ARTIFACT,
149400
149814
  `[renderChunk] planDir is missing required artifact: ${required}`
@@ -149405,7 +149819,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
149405
149819
  const chunks = JSON.parse(readFileSync45(chunksJsonPath, "utf-8"));
149406
149820
  const videosJsonPath = join86(planDir, PLAN_VIDEOS_META_RELATIVE_PATH);
149407
149821
  let planVideos = null;
149408
- if (existsSync70(videosJsonPath)) {
149822
+ if (existsSync71(videosJsonPath)) {
149409
149823
  try {
149410
149824
  planVideos = validatePlanVideosForChunk(JSON.parse(readFileSync45(videosJsonPath, "utf-8")));
149411
149825
  } catch (err) {
@@ -149434,7 +149848,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
149434
149848
  );
149435
149849
  }
149436
149850
  const compiledDir = join86(planDir, "compiled");
149437
- if (!existsSync70(compiledDir)) {
149851
+ if (!existsSync71(compiledDir)) {
149438
149852
  throw new RenderChunkValidationError(
149439
149853
  MISSING_PLAN_ARTIFACT,
149440
149854
  `[renderChunk] planDir missing compiled/ directory: ${compiledDir}`
@@ -149690,10 +150104,10 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
149690
150104
  const effectiveBitrate = encoder.crf != null ? void 0 : encoder.bitrate;
149691
150105
  const videoOnlyPath = outputChunkPath;
149692
150106
  if (isPngSequence) {
149693
- if (!existsSync70(outputChunkPath)) mkdirSync37(outputChunkPath, { recursive: true });
150107
+ if (!existsSync71(outputChunkPath)) mkdirSync37(outputChunkPath, { recursive: true });
149694
150108
  } else {
149695
150109
  const outDir = join86(outputChunkPath, "..");
149696
- if (!existsSync70(outDir)) mkdirSync37(outDir, { recursive: true });
150110
+ if (!existsSync71(outDir)) mkdirSync37(outDir, { recursive: true });
149697
150111
  }
149698
150112
  const encodeStarted = Date.now();
149699
150113
  await runEncodeStage({
@@ -150024,7 +150438,7 @@ var init_src2 = __esm({
150024
150438
  import { spawn as spawn14 } from "child_process";
150025
150439
  import { randomUUID as randomUUID12 } from "crypto";
150026
150440
  import {
150027
- existsSync as existsSync71,
150441
+ existsSync as existsSync73,
150028
150442
  mkdirSync as mkdirSync38,
150029
150443
  readdirSync as readdirSync30,
150030
150444
  readFileSync as readFileSync47,
@@ -150068,7 +150482,7 @@ function manifestPath(dir, name) {
150068
150482
  return join89(dir, "node_modules", name, "package.json");
150069
150483
  }
150070
150484
  function isInstalled(dir, name) {
150071
- return existsSync71(manifestPath(dir, name));
150485
+ return existsSync73(manifestPath(dir, name));
150072
150486
  }
150073
150487
  function loadInstalled(dir, name) {
150074
150488
  if (!isInstalled(dir, name)) return null;
@@ -150099,7 +150513,7 @@ function isProcessAlive(pid) {
150099
150513
  function sweepStaleStaging(dir) {
150100
150514
  const prefix = `${basename14(dir)}.tmp-`;
150101
150515
  const parent = dirname37(dir);
150102
- if (!existsSync71(parent)) return;
150516
+ if (!existsSync73(parent)) return;
150103
150517
  for (const entry of readdirSync30(parent)) {
150104
150518
  if (!entry.startsWith(prefix)) continue;
150105
150519
  const pid = /^(\d+)(?:-|$)/.exec(entry.slice(prefix.length))?.[1];
@@ -150173,8 +150587,8 @@ __export(manager_exports3, {
150173
150587
  modelPath: () => modelPath,
150174
150588
  selectProviders: () => selectProviders
150175
150589
  });
150176
- import { existsSync as existsSync73, mkdirSync as mkdirSync39 } from "fs";
150177
- import { homedir as homedir15, platform as platform7, arch as arch2 } from "os";
150590
+ import { existsSync as existsSync74, mkdirSync as mkdirSync39 } from "fs";
150591
+ import { homedir as homedir15, platform as platform8, arch as arch2 } from "os";
150178
150592
  import { join as join90 } from "path";
150179
150593
  function isDevice(value) {
150180
150594
  return typeof value === "string" && DEVICES2.includes(value);
@@ -150200,7 +150614,7 @@ function selectProviders(device = "auto") {
150200
150614
  }
150201
150615
  return { providers: ["cuda", "cpu"], label: "CUDA" };
150202
150616
  }
150203
- if (hasCoreML && platform7() === "darwin" && arch2() === "arm64") {
150617
+ if (hasCoreML && platform8() === "darwin" && arch2() === "arm64") {
150204
150618
  return { providers: ["coreml", "cpu"], label: "CoreML" };
150205
150619
  }
150206
150620
  if (hasCUDA) return { providers: ["cuda", "cpu"], label: "CUDA" };
@@ -150209,7 +150623,7 @@ function selectProviders(device = "auto") {
150209
150623
  function listAvailableProviders() {
150210
150624
  if (_cachedProviders) return _cachedProviders;
150211
150625
  const out = ["cpu"];
150212
- if (platform7() === "darwin" && arch2() === "arm64") out.push("coreml");
150626
+ if (platform8() === "darwin" && arch2() === "arm64") out.push("coreml");
150213
150627
  if (process.env["HYPERFRAMES_CUDA"] === "1") out.push("cuda");
150214
150628
  _cachedProviders = out;
150215
150629
  return out;
@@ -150219,11 +150633,11 @@ function modelPath(model = DEFAULT_MODEL2) {
150219
150633
  }
150220
150634
  async function ensureModel2(model = DEFAULT_MODEL2, options) {
150221
150635
  const dest = modelPath(model);
150222
- if (existsSync73(dest)) return dest;
150636
+ if (existsSync74(dest)) return dest;
150223
150637
  mkdirSync39(MODELS_DIR2, { recursive: true });
150224
150638
  options?.onProgress?.(`Downloading ${model} weights (~168 MB)...`);
150225
150639
  await downloadFile(MODEL_URLS[model], dest);
150226
- if (!existsSync73(dest)) {
150640
+ if (!existsSync74(dest)) {
150227
150641
  throw new Error(`Model download failed: ${model}`);
150228
150642
  }
150229
150643
  return dest;
@@ -150725,320 +151139,6 @@ var init_pipeline = __esm({
150725
151139
  }
150726
151140
  });
150727
151141
 
150728
- // src/browser/preflight.ts
150729
- var preflight_exports = {};
150730
- __export(preflight_exports, {
150731
- checkDisk: () => checkDisk,
150732
- extractMajorVersion: () => extractMajorVersion,
150733
- parseToolVersion: () => parseToolVersion,
150734
- runEnvironmentChecks: () => runEnvironmentChecks
150735
- });
150736
- import { existsSync as existsSync74 } from "fs";
150737
- import { platform as platform8 } from "os";
150738
- function parseToolVersion(raw) {
150739
- const m = raw.match(/(ffmpeg|ffprobe)\s+version\s+([\d][\d.\-\w]*)/i);
150740
- return m ? `${m[1]} ${m[2]}` : raw.trim();
150741
- }
150742
- function extractMajorVersion(raw) {
150743
- const m = raw.match(/\b(\d+)\.\d+/);
150744
- return m?.[1] ? Number(m[1]) : void 0;
150745
- }
150746
- function configuredMissingDetail(envName) {
150747
- const configured = process.env[envName]?.trim();
150748
- if (!configured || existsSync74(configured)) return void 0;
150749
- return `Configured path does not exist: ${envName}="${configured}"`;
150750
- }
150751
- async function readToolVersion(binaryPath, signal) {
150752
- try {
150753
- const output = (await runCancellableProcess(binaryPath, ["-version"], {
150754
- signal,
150755
- timeoutMs: 5e3
150756
- })).stdout;
150757
- const raw = output.split("\n")[0] ?? "";
150758
- const version2 = parseToolVersion(raw);
150759
- return {
150760
- ok: true,
150761
- detail: version2 ? `${version2} at ${binaryPath}` : binaryPath,
150762
- majorVersion: extractMajorVersion(raw)
150763
- };
150764
- } catch (error) {
150765
- if (signal?.aborted) signal.throwIfAborted();
150766
- const status = typeof error === "object" && error !== null && "status" in error ? error.status : void 0;
150767
- const exitDetail = typeof status === "number" ? ` (exit code ${status})` : "";
150768
- return {
150769
- ok: false,
150770
- detail: `Failed to run "${binaryPath}" -version${exitDetail}.`
150771
- };
150772
- }
150773
- }
150774
- async function checkFFmpeg(signal) {
150775
- const missingConfigured = configuredMissingDetail(FFMPEG_PATH_ENV);
150776
- if (missingConfigured) {
150777
- return {
150778
- name: "FFmpeg",
150779
- ok: false,
150780
- level: "error",
150781
- title: "FFmpeg not found",
150782
- detail: missingConfigured,
150783
- hint: getFFmpegInstallHint()
150784
- };
150785
- }
150786
- const path = findFfBinary("ffmpeg", { configuredMustExist: true });
150787
- if (path) {
150788
- const version2 = await readToolVersion(path, signal);
150789
- if (!version2.ok) {
150790
- return {
150791
- name: "FFmpeg",
150792
- ok: false,
150793
- level: "error",
150794
- title: "FFmpeg cannot start",
150795
- detail: version2.detail,
150796
- hint: "Install a working 64-bit FFmpeg build with all required runtime DLLs.",
150797
- path
150798
- };
150799
- }
150800
- return {
150801
- name: "FFmpeg",
150802
- ok: true,
150803
- level: "ok",
150804
- detail: version2.detail,
150805
- path,
150806
- versionMajor: version2.majorVersion
150807
- };
150808
- }
150809
- return {
150810
- name: "FFmpeg",
150811
- ok: false,
150812
- level: "error",
150813
- title: "FFmpeg not found",
150814
- // Second sentence dropped: "the render cannot proceed" is already said by
150815
- // the error this accompanies, and in Studio by the disabled Export button.
150816
- detail: "FFmpeg is required to encode video.",
150817
- hint: getFFmpegInstallHint()
150818
- };
150819
- }
150820
- async function checkFFprobe(signal) {
150821
- const missingConfigured = configuredMissingDetail(FFPROBE_PATH_ENV);
150822
- if (missingConfigured) {
150823
- return {
150824
- name: "FFprobe",
150825
- ok: false,
150826
- level: "error",
150827
- title: "FFprobe not found",
150828
- detail: missingConfigured,
150829
- hint: getFFmpegInstallHint()
150830
- };
150831
- }
150832
- const path = findFfBinary("ffprobe", { configuredMustExist: true });
150833
- if (path) {
150834
- const version2 = await readToolVersion(path, signal);
150835
- return { name: "FFprobe", ok: true, level: "ok", detail: version2.detail, path };
150836
- }
150837
- return {
150838
- name: "FFprobe",
150839
- ok: false,
150840
- level: "error",
150841
- title: "FFprobe not found",
150842
- detail: "FFprobe is required to probe media assets. It ships with FFmpeg but was not found on PATH.",
150843
- hint: getFFmpegInstallHint()
150844
- };
150845
- }
150846
- async function chromeSharedLibOutcome(executablePath, found, signal) {
150847
- if (process.platform !== "linux") return found;
150848
- let probe2;
150849
- if (!existsSync74(executablePath)) {
150850
- probe2 = { ok: true, missing: [], probeUnavailable: true };
150851
- } else {
150852
- try {
150853
- const result = await runCancellableProcess("ldd", [executablePath], {
150854
- signal,
150855
- timeoutMs: 5e3
150856
- });
150857
- probe2 = parseLddMissingLibs(result.stdout);
150858
- } catch (error) {
150859
- if (signal?.aborted) signal.throwIfAborted();
150860
- const stdout2 = typeof error === "object" && error !== null && "stdout" in error ? String(error.stdout ?? "") : "";
150861
- const killed = typeof error === "object" && error !== null && "killed" in error && error.killed === true;
150862
- probe2 = stdout2 && !killed ? parseLddMissingLibs(stdout2) : { ok: true, missing: [], probeUnavailable: true };
150863
- }
150864
- }
150865
- if (probe2.probeUnavailable || probe2.ok) return found;
150866
- const distro = detectLinuxDistro();
150867
- return {
150868
- name: "Chrome",
150869
- ok: false,
150870
- level: "error",
150871
- title: "Chrome cannot launch (missing system libraries)",
150872
- detail: `Chrome at ${executablePath} is missing shared libraries on ${distroLabel(distro)}: ${probe2.missing.join(", ")}`,
150873
- hint: chromeDepsInstallCommand(distro.family),
150874
- path: executablePath
150875
- };
150876
- }
150877
- function chromeLaunchFailureDetails(error) {
150878
- if (typeof error !== "object" || error === null) return "";
150879
- const status = "status" in error ? error.status : void 0;
150880
- const signal = "signal" in error ? error.signal : void 0;
150881
- const code = "code" in error ? error.code : void 0;
150882
- return [
150883
- typeof status === "number" ? `exit code ${status}` : "",
150884
- typeof signal === "string" ? `signal ${signal}` : "",
150885
- typeof code === "string" ? code : ""
150886
- ].filter(Boolean).join(", ");
150887
- }
150888
- async function chromeLaunchOutcome(executablePath, found, signal) {
150889
- const libraries = await chromeSharedLibOutcome(executablePath, found, signal);
150890
- if (!libraries.ok) return libraries;
150891
- try {
150892
- const { stdout: stdout2 } = await runCancellableProcess(executablePath, ["--version"], {
150893
- signal,
150894
- timeoutMs: 5e3,
150895
- maxBufferBytes: 64 * 1024
150896
- });
150897
- return { ...found, versionMajor: extractMajorVersion(stdout2) };
150898
- } catch (error) {
150899
- if (signal?.aborted) signal.throwIfAborted();
150900
- const details2 = chromeLaunchFailureDetails(error);
150901
- return {
150902
- name: "Chrome",
150903
- ok: false,
150904
- level: "error",
150905
- title: "Chrome cannot start",
150906
- detail: `Failed to run "${executablePath}" --version${details2 ? ` (${details2})` : ""}.`,
150907
- hint: "Select a working Chrome/Chromium binary for this OS and architecture with HYPERFRAMES_BROWSER_PATH, or reinstall with: npx hyperframes browser ensure --force",
150908
- path: executablePath
150909
- };
150910
- }
150911
- }
150912
- async function checkChrome(browserPath, signal) {
150913
- if (browserPath) {
150914
- if (existsSync74(browserPath)) {
150915
- return chromeLaunchOutcome(
150916
- browserPath,
150917
- {
150918
- name: "Chrome",
150919
- ok: true,
150920
- level: "ok",
150921
- detail: `explicit: ${browserPath}`,
150922
- path: browserPath
150923
- },
150924
- signal
150925
- );
150926
- }
150927
- return {
150928
- name: "Chrome",
150929
- ok: false,
150930
- level: "error",
150931
- title: "Chrome not found",
150932
- detail: `Chrome binary not found at "${browserPath}".`,
150933
- hint: "Run: npx hyperframes browser ensure"
150934
- };
150935
- }
150936
- let info;
150937
- try {
150938
- info = signal ? await ensureBrowser({ preferManagedChrome: true, signal }) : await findBrowser();
150939
- } catch {
150940
- if (signal?.aborted) signal.throwIfAborted();
150941
- info = void 0;
150942
- }
150943
- if (info) {
150944
- return chromeLaunchOutcome(
150945
- info.executablePath,
150946
- {
150947
- name: "Chrome",
150948
- ok: true,
150949
- level: "ok",
150950
- detail: `${info.source}: ${info.executablePath}`,
150951
- path: info.executablePath
150952
- },
150953
- signal
150954
- );
150955
- }
150956
- return {
150957
- name: "Chrome",
150958
- ok: false,
150959
- level: "error",
150960
- title: "Chrome not found",
150961
- detail: "Chrome Headless Shell is required for local rendering.",
150962
- hint: "Run: npx hyperframes browser ensure"
150963
- };
150964
- }
150965
- function checkDisk(path = ".", freeDiskMb = getFreeDiskMb) {
150966
- const freeMb = freeDiskMb(path);
150967
- if (freeMb === null) {
150968
- return { name: "Disk", ok: true, level: "ok", detail: "Unable to check" };
150969
- }
150970
- const freeGb = (freeMb / 1024).toFixed(1);
150971
- if (freeMb < 1024) {
150972
- return {
150973
- name: "Disk",
150974
- ok: false,
150975
- level: "error",
150976
- title: "Low disk space",
150977
- detail: `${freeGb} GB free at ${path}`,
150978
- hint: "Renders produce large temp files. Free disk space before rendering."
150979
- };
150980
- }
150981
- return { name: "Disk", ok: true, level: "ok", detail: `${freeGb} GB free at ${path}` };
150982
- }
150983
- function checkWindowsUncPath(projectDir = process.cwd()) {
150984
- if (platform8() !== "win32") return void 0;
150985
- if (!projectDir.startsWith("\\\\")) return void 0;
150986
- return {
150987
- name: "Windows path",
150988
- ok: true,
150989
- level: "warn",
150990
- detail: `UNC path: ${projectDir}`,
150991
- hint: "Chrome may fail to launch from a network share. Use a local drive if render startup fails."
150992
- };
150993
- }
150994
- async function runEnvironmentChecks(options = {}) {
150995
- const outcomes = [];
150996
- const ffmpeg = await checkFFmpeg(options.signal);
150997
- outcomes.push(ffmpeg);
150998
- const ffprobe = await checkFFprobe(options.signal);
150999
- outcomes.push(ffprobe);
151000
- let browser;
151001
- let browserVersionMajor;
151002
- if (options.includeBrowser) {
151003
- const chrome = await checkChrome(options.browserPath, options.signal);
151004
- outcomes.push(chrome);
151005
- if (chrome.ok && chrome.path) {
151006
- browser = {
151007
- executablePath: chrome.path,
151008
- source: options.browserPath ? "env" : "cache"
151009
- };
151010
- }
151011
- browserVersionMajor = chrome.versionMajor;
151012
- }
151013
- if (options.includeDisk) {
151014
- const diskPaths = [...new Set(options.diskPaths ?? [options.projectDir ?? "."])];
151015
- outcomes.push(...diskPaths.map((path) => checkDisk(path)));
151016
- }
151017
- if (options.includeWindowsUnc) {
151018
- const unc = checkWindowsUncPath(options.projectDir);
151019
- if (unc) outcomes.push(unc);
151020
- }
151021
- return {
151022
- outcomes,
151023
- ...ffmpeg.ok && ffmpeg.path ? { ffmpegPath: ffmpeg.path } : {},
151024
- ...ffprobe.path ? { ffprobePath: ffprobe.path } : {},
151025
- ...browser ? { browser } : {},
151026
- ...ffmpeg.versionMajor != null ? { ffmpegVersionMajor: ffmpeg.versionMajor } : {},
151027
- ...browserVersionMajor != null ? { browserVersionMajor } : {}
151028
- };
151029
- }
151030
- var init_preflight = __esm({
151031
- "src/browser/preflight.ts"() {
151032
- "use strict";
151033
- init_ffBinaries();
151034
- init_manager2();
151035
- init_ffmpeg();
151036
- init_linuxDeps();
151037
- init_system();
151038
- init_cancellableProcess();
151039
- }
151040
- });
151041
-
151042
151142
  // src/server/studioServer.ts
151043
151143
  var studioServer_exports = {};
151044
151144
  __export(studioServer_exports, {
@@ -151355,13 +151455,9 @@ function createStudioServer(options) {
151355
151455
  };
151356
151456
  try {
151357
151457
  const { createRenderJob: createRenderJob2, executeRenderJob: executeRenderJob2 } = await loadStudioProducer();
151358
- const { ensureBrowser: ensureBrowser2 } = await Promise.resolve().then(() => (init_manager2(), manager_exports2));
151359
- try {
151360
- const browser = await ensureBrowser2({ preferManagedChrome: true });
151361
- if (browser.executablePath && !process.env.PRODUCER_HEADLESS_SHELL_PATH) {
151362
- process.env.PRODUCER_HEADLESS_SHELL_PATH = browser.executablePath;
151363
- }
151364
- } catch {
151458
+ const browser = await resolveRenderBrowser(abortController.signal);
151459
+ if (!process.env.PRODUCER_HEADLESS_SHELL_PATH) {
151460
+ process.env.PRODUCER_HEADLESS_SHELL_PATH = browser.executablePath;
151365
151461
  }
151366
151462
  const manifestContent = readStudioManualEditManifestContent(opts.project.dir);
151367
151463
  const manualEditsRenderScript = createStudioManualEditsRenderBodyScript(manifestContent);
@@ -151744,6 +151840,7 @@ var init_studioServer = __esm({
151744
151840
  init_telemetryIdentity();
151745
151841
  init_studioRenderTelemetry();
151746
151842
  init_env();
151843
+ init_preflight();
151747
151844
  init_dist9();
151748
151845
  init_projectConfig();
151749
151846
  init_screenshotClip();
@@ -159851,17 +159948,17 @@ function macosOldChromeCrashRemediation(errorMessage2) {
159851
159948
  if (!isMacosOldChromeCrashError(errorMessage2)) return void 0;
159852
159949
  return [
159853
159950
  "chrome-headless-shell crashed at launch (macOS dyld: Symbol not found in VideoToolbox).",
159854
- "The pinned Chromium build requires macOS 13+; on macOS 12 or older, install an older",
159855
- "chrome-headless-shell and point hyperframes at it:",
159951
+ "The pinned Chromium build requires macOS 13+. HyperFrames installs Chrome 150 on macOS 12 by",
159952
+ "itself, so this crash means a newer browser was supplied. Unset the override, or point it at",
159953
+ "an older chrome-headless-shell:",
159856
159954
  "",
159857
159955
  " npx @puppeteer/browsers install chrome-headless-shell@150",
159858
- ' export HYPERFRAMES_BROWSER_PATH="$HOME/.cache/puppeteer/chrome-headless-shell/mac-150.0.7422.0/chrome-headless-shell-mac-x64/chrome-headless-shell"',
159956
+ ' export HYPERFRAMES_BROWSER_PATH="$HOME/.cache/puppeteer/chrome-headless-shell/mac-150.0.7871.124/chrome-headless-shell-mac-x64/chrome-headless-shell"',
159859
159957
  "",
159860
159958
  "(PRODUCER_HEADLESS_SHELL_PATH works as an alias for the same override.)",
159861
- "Any working chrome-headless-shell build resolves this \u2014 the exact version above is one",
159862
- "known-good macOS-12 combination. Alternatively, point HYPERFRAMES_BROWSER_PATH at your",
159863
- 'installed Google Chrome ("/Applications/Google Chrome.app/Contents/MacOS/Google Chrome")',
159864
- "to fall back to the screenshot capture path."
159959
+ "Alternatively, point HYPERFRAMES_BROWSER_PATH at your installed Google Chrome",
159960
+ '("/Applications/Google Chrome.app/Contents/MacOS/Google Chrome") to fall back to the screenshot',
159961
+ "capture path."
159865
159962
  ].join("\n");
159866
159963
  }
159867
159964
  var DYLD_SYMBOL_NOT_FOUND, MACOS_13_ONLY_SYMBOL, VIDEO_TOOLBOX;
@@ -160254,7 +160351,8 @@ async function executeLocalRender(projectDir, outputPath, options, cancellation)
160254
160351
  options = {
160255
160352
  ...options,
160256
160353
  ffmpegVersionMajor: preflight.ffmpegVersionMajor,
160257
- browserVersionMajor: preflight.browserVersionMajor
160354
+ browserVersionMajor: preflight.browserVersionMajor,
160355
+ browserInstall: preflight.browserInstall
160258
160356
  };
160259
160357
  cancellation.checkAncestors();
160260
160358
  cancellation.signal.throwIfAborted();
@@ -160460,7 +160558,8 @@ function renderOutputShapeTelemetryPayload(options) {
160460
160558
  function renderEnvironmentTelemetryPayload(options) {
160461
160559
  return {
160462
160560
  ffmpegVersionMajor: options.ffmpegVersionMajor,
160463
- browserVersionMajor: options.browserVersionMajor
160561
+ browserVersionMajor: options.browserVersionMajor,
160562
+ browserInstall: options.browserInstall
160464
160563
  };
160465
160564
  }
160466
160565
  function metaString(meta, key2) {
@@ -170669,7 +170768,7 @@ async function runEnsure(options) {
170669
170768
  if (pct > lastPct2) {
170670
170769
  lastPct2 = pct;
170671
170770
  s.message(
170672
- `Downloading Chrome Headless Shell ${c.dim("v" + CHROME_VERSION)} \u2014 ${c.progress(pct + "%")} ${c.dim("(" + formatBytes(downloaded) + " / " + formatBytes(total) + ")")}`
170771
+ `Downloading Chrome Headless Shell ${c.dim("v" + managedChromeVersion())} \u2014 ${c.progress(pct + "%")} ${c.dim("(" + formatBytes(downloaded) + " / " + formatBytes(total) + ")")}`
170673
170772
  );
170674
170773
  }
170675
170774
  }
@@ -170685,7 +170784,9 @@ async function runEnsure(options) {
170685
170784
  }
170686
170785
  s.start("Purging cached download and re-downloading...");
170687
170786
  const downloadSpinner = ft();
170688
- downloadSpinner.start(`Downloading Chrome Headless Shell ${c.dim("v" + CHROME_VERSION)}...`);
170787
+ downloadSpinner.start(
170788
+ `Downloading Chrome Headless Shell ${c.dim("v" + managedChromeVersion())}...`
170789
+ );
170689
170790
  let lastPct = -1;
170690
170791
  const result = await ensureBrowser({
170691
170792
  force: options?.force,
@@ -170695,7 +170796,7 @@ async function runEnsure(options) {
170695
170796
  if (pct > lastPct) {
170696
170797
  lastPct = pct;
170697
170798
  downloadSpinner.message(
170698
- `Downloading Chrome Headless Shell ${c.dim("v" + CHROME_VERSION)} \u2014 ${c.progress(pct + "%")} ${c.dim("(" + formatBytes(downloaded) + " / " + formatBytes(total) + ")")}`
170799
+ `Downloading Chrome Headless Shell ${c.dim("v" + managedChromeVersion())} \u2014 ${c.progress(pct + "%")} ${c.dim("(" + formatBytes(downloaded) + " / " + formatBytes(total) + ")")}`
170699
170800
  );
170700
170801
  }
170701
170802
  }