hyperframes 0.7.69 → 0.7.70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -50,7 +50,7 @@ var VERSION;
50
50
  var init_version = __esm({
51
51
  "src/version.ts"() {
52
52
  "use strict";
53
- VERSION = true ? "0.7.69" : "0.0.0-dev";
53
+ VERSION = true ? "0.7.70" : "0.0.0-dev";
54
54
  }
55
55
  });
56
56
 
@@ -4852,7 +4852,7 @@ var require_util = __commonJS({
4852
4852
  return path2;
4853
4853
  }
4854
4854
  exports.normalize = normalize;
4855
- function join129(aRoot, aPath) {
4855
+ function join130(aRoot, aPath) {
4856
4856
  if (aRoot === "") {
4857
4857
  aRoot = ".";
4858
4858
  }
@@ -4884,7 +4884,7 @@ var require_util = __commonJS({
4884
4884
  }
4885
4885
  return joined;
4886
4886
  }
4887
- exports.join = join129;
4887
+ exports.join = join130;
4888
4888
  exports.isAbsolute = function(aPath) {
4889
4889
  return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
4890
4890
  };
@@ -5057,7 +5057,7 @@ var require_util = __commonJS({
5057
5057
  parsed.path = parsed.path.substring(0, index + 1);
5058
5058
  }
5059
5059
  }
5060
- sourceURL = join129(urlGenerate(parsed), sourceURL);
5060
+ sourceURL = join130(urlGenerate(parsed), sourceURL);
5061
5061
  }
5062
5062
  return normalize(sourceURL);
5063
5063
  }
@@ -83647,6 +83647,43 @@ var init_audioMixer = __esm({
83647
83647
  }
83648
83648
  });
83649
83649
 
83650
+ // ../engine/src/utils/psnr.ts
83651
+ import { execFile as execFile2 } from "child_process";
83652
+ import { mkdtemp, rm, writeFile } from "fs/promises";
83653
+ import { tmpdir as tmpdir2 } from "os";
83654
+ import { join as join14 } from "path";
83655
+ import { promisify } from "util";
83656
+ async function psnrDb(a, b2) {
83657
+ const execFileP = promisify(execFile2);
83658
+ const dir = await mkdtemp(join14(tmpdir2(), "hf-de-verify-"));
83659
+ try {
83660
+ const pa = join14(dir, "a.jpg");
83661
+ const pb = join14(dir, "b.jpg");
83662
+ await Promise.all([writeFile(pa, a), writeFile(pb, b2)]);
83663
+ const { stderr } = await execFileP(
83664
+ getFfmpegBinary(),
83665
+ ["-hide_banner", "-i", pa, "-i", pb, "-lavfi", "psnr", "-f", "null", "-"],
83666
+ { maxBuffer: 4 * 1024 * 1024 }
83667
+ );
83668
+ const m2 = /average:(inf|[\d.]+)/.exec(stderr);
83669
+ if (!m2) throw new Error(`psnr parse failed: ${stderr.slice(-300)}`);
83670
+ return m2[1] === "inf" ? Infinity : Number(m2[1]);
83671
+ } finally {
83672
+ await rm(dir, { recursive: true, force: true }).catch(() => {
83673
+ });
83674
+ }
83675
+ }
83676
+ function resolveDeVerifyMinDb() {
83677
+ const raw = Number(process.env.HF_DE_VERIFY_MIN_DB ?? "32");
83678
+ return Number.isFinite(raw) && raw >= 10 && raw <= 60 ? raw : 32;
83679
+ }
83680
+ var init_psnr = __esm({
83681
+ "../engine/src/utils/psnr.ts"() {
83682
+ "use strict";
83683
+ init_ffmpegBinaries();
83684
+ }
83685
+ });
83686
+
83650
83687
  // ../engine/src/utils/assertSwiftShader.ts
83651
83688
  async function readWebGlVendorInfo(page) {
83652
83689
  await page.goto("chrome://gpu", { waitUntil: "domcontentloaded", timeout: 3e4 });
@@ -83731,8 +83768,8 @@ var init_readWebGlVendorInfoFromCanvas = __esm({
83731
83768
  // ../engine/src/services/parallelCoordinator.ts
83732
83769
  import { cpus, freemem } from "os";
83733
83770
  import { existsSync as existsSync16, mkdirSync as mkdirSync9, readdirSync as readdirSync6 } from "fs";
83734
- import { copyFile, rename } from "fs/promises";
83735
- import { join as join14 } from "path";
83771
+ import { copyFile, readFile, rename } from "fs/promises";
83772
+ import { join as join15 } from "path";
83736
83773
  import { getHeapStatistics } from "v8";
83737
83774
  function defaultSafeMaxWorkers() {
83738
83775
  return Math.max(6, Math.min(16, Math.floor(cpus().length / 8)));
@@ -83861,7 +83898,7 @@ function distributeFrames(totalFrames, workerCount, workDir, rangeStart = 0) {
83861
83898
  workerId: i2,
83862
83899
  startFrame,
83863
83900
  endFrame,
83864
- outputDir: join14(workDir, `worker-${i2}`),
83901
+ outputDir: join15(workDir, `worker-${i2}`),
83865
83902
  outputFrameOffset: rangeStart
83866
83903
  });
83867
83904
  }
@@ -83875,7 +83912,7 @@ function distributeFramesInterleaved(totalFrames, workerCount, workDir, rangeSta
83875
83912
  startFrame: rangeStart + i2,
83876
83913
  endFrame: rangeStart + totalFrames,
83877
83914
  frameStride: workerCount,
83878
- outputDir: join14(workDir, `worker-${i2}`),
83915
+ outputDir: join15(workDir, `worker-${i2}`),
83879
83916
  outputFrameOffset: rangeStart
83880
83917
  });
83881
83918
  }
@@ -83948,6 +83985,56 @@ async function captureFrameRange(session, task, captureOptions, signal, onFrameC
83948
83985
  }
83949
83986
  return framesCaptured;
83950
83987
  }
83988
+ function selectVerifySampleIndicesForTask(sampleIndices, task) {
83989
+ const stride = task.frameStride ?? 1;
83990
+ const selected = [];
83991
+ for (const idx of sampleIndices) {
83992
+ if (idx < task.startFrame || idx >= task.endFrame) continue;
83993
+ if ((idx - task.startFrame) % stride !== 0) continue;
83994
+ selected.push(idx);
83995
+ }
83996
+ return selected.sort((a, b2) => a - b2);
83997
+ }
83998
+ function logParDebug(message) {
83999
+ if (process.env.HF_DE_PAR_DEBUG === "1") console.log(message());
84000
+ }
84001
+ function assertDiskSampleAboveFloor(db, verifyMinDb, idx, workerId) {
84002
+ if (db < verifyMinDb) {
84003
+ throw new DrawElementVerificationError(
84004
+ `drawElement self-verify failed at frame ${idx} (disk path, worker ${workerId}): ${db.toFixed(1)}dB < ${verifyMinDb}dB vs pre-injection screenshot`,
84005
+ { kind: "psnr", frameIndex: idx, failedDb: db, verifyThresholdDb: verifyMinDb }
84006
+ );
84007
+ }
84008
+ console.log(
84009
+ `[Parallel] drawElement disk self-verify passed (worker ${workerId}, frame ${idx}, ${db === Infinity ? "inf" : db.toFixed(1)}dB)`
84010
+ );
84011
+ }
84012
+ async function psnrForDiskSample(framePath, truth, workerId, idx) {
84013
+ try {
84014
+ return await psnrDb(await readFile(framePath), truth);
84015
+ } catch (err) {
84016
+ console.warn(
84017
+ `[Parallel] drawElement disk self-verify sample skipped (worker ${workerId}, frame ${idx}): ${err instanceof Error ? err.message : String(err)}`
84018
+ );
84019
+ return null;
84020
+ }
84021
+ }
84022
+ async function verifyDiskDrawElementSamples(session, task, streaming) {
84023
+ if (streaming || session.captureMode !== "drawelement") return;
84024
+ const truths = session.deVerifyFrames;
84025
+ if (!truths || truths.size === 0) return;
84026
+ const verifyMinDb = resolveDeVerifyMinDb();
84027
+ const ext = session.options.format === "png" ? "png" : "jpg";
84028
+ const offset2 = task.outputFrameOffset ?? 0;
84029
+ for (const idx of selectVerifySampleIndicesForTask(truths.keys(), task)) {
84030
+ const truth = truths.get(idx);
84031
+ if (!truth) continue;
84032
+ const framePath = join15(task.outputDir, `frame_${String(idx - offset2).padStart(6, "0")}.${ext}`);
84033
+ const db = await psnrForDiskSample(framePath, truth, task.workerId, idx);
84034
+ if (db === null) continue;
84035
+ assertDiskSampleAboveFloor(db, verifyMinDb, idx, task.workerId);
84036
+ }
84037
+ }
83951
84038
  async function executeWorkerTask(task, serverUrl, captureOptions, createBeforeCaptureHook, signal, onFrameCaptured, onFrameBuffer, config, parallel, onFailure) {
83952
84039
  const startTime = Date.now();
83953
84040
  let framesCaptured = 0;
@@ -83970,18 +84057,14 @@ async function executeWorkerTask(task, serverUrl, captureOptions, createBeforeCa
83970
84057
  createBeforeCaptureHook(),
83971
84058
  workerConfig
83972
84059
  );
83973
- if (process.env.HF_DE_PAR_DEBUG === "1") {
83974
- console.log(`[par:w${task.workerId}] session created`);
83975
- }
84060
+ logParDebug(() => `[par:w${task.workerId}] session created`);
83976
84061
  if (shouldVerifyWorkerGpu(task.workerId, workerConfig)) {
83977
84062
  await assertSwiftShader(session.page, readWebGlVendorInfoFromCanvas);
83978
84063
  }
83979
84064
  await initializeSession(session);
83980
- if (process.env.HF_DE_PAR_DEBUG === "1") {
83981
- console.log(
83982
- `[par:w${task.workerId}] init done (mode=${session.captureMode} workerEncode=${session.workerEncodeEnabled === true})`
83983
- );
83984
- }
84065
+ logParDebug(
84066
+ () => `[par:w${task.workerId}] init done (mode=${session?.captureMode} workerEncode=${session?.workerEncodeEnabled === true})`
84067
+ );
83985
84068
  framesCaptured = await captureFrameRange(
83986
84069
  session,
83987
84070
  task,
@@ -83990,6 +84073,7 @@ async function executeWorkerTask(task, serverUrl, captureOptions, createBeforeCa
83990
84073
  onFrameCaptured,
83991
84074
  onFrameBuffer
83992
84075
  );
84076
+ await verifyDiskDrawElementSamples(session, task, Boolean(onFrameBuffer));
83993
84077
  perf = getCapturePerfSummary(session);
83994
84078
  return {
83995
84079
  workerId: task.workerId,
@@ -84111,8 +84195,8 @@ async function mergeWorkerFrames(workDir, tasks, outputDir) {
84111
84195
  }
84112
84196
  const files = readdirSync6(task.outputDir).filter((f3) => f3.startsWith("frame_") && (f3.endsWith(".jpg") || f3.endsWith(".png"))).sort();
84113
84197
  const copyTasks = files.map(async (file) => {
84114
- const sourcePath = join14(task.outputDir, file);
84115
- const targetPath = join14(outputDir, file);
84198
+ const sourcePath = join15(task.outputDir, file);
84199
+ const targetPath = join15(outputDir, file);
84116
84200
  try {
84117
84201
  await rename(sourcePath, targetPath);
84118
84202
  } catch {
@@ -84137,6 +84221,7 @@ var init_parallelCoordinator = __esm({
84137
84221
  "../engine/src/services/parallelCoordinator.ts"() {
84138
84222
  "use strict";
84139
84223
  init_frameCapture();
84224
+ init_psnr();
84140
84225
  init_config2();
84141
84226
  init_assertSwiftShader();
84142
84227
  init_readWebGlVendorInfoFromCanvas();
@@ -84157,7 +84242,7 @@ var init_parallelCoordinator = __esm({
84157
84242
  import { Hono } from "hono";
84158
84243
  import { serve } from "@hono/node-server";
84159
84244
  import { readFileSync as readFileSync7, existsSync as existsSync17, statSync as statSync4 } from "fs";
84160
- import { join as join15, extname as extname5 } from "path";
84245
+ import { join as join16, extname as extname5 } from "path";
84161
84246
  function createFileServer(options) {
84162
84247
  const { projectDir, compiledDir, port = 0, stripEmbeddedRuntime = true } = options;
84163
84248
  const headScripts = options.headScripts ?? [];
@@ -84167,11 +84252,11 @@ function createFileServer(options) {
84167
84252
  let requestPath = c3.req.path;
84168
84253
  if (requestPath === "/") requestPath = "/index.html";
84169
84254
  const relativePath = requestPath.replace(/^\//, "");
84170
- const compiledPath = compiledDir ? join15(compiledDir, relativePath) : null;
84255
+ const compiledPath = compiledDir ? join16(compiledDir, relativePath) : null;
84171
84256
  const hasCompiledFile = Boolean(
84172
84257
  compiledPath && existsSync17(compiledPath) && statSync4(compiledPath).isFile()
84173
84258
  );
84174
- const filePath = hasCompiledFile ? compiledPath : join15(projectDir, relativePath);
84259
+ const filePath = hasCompiledFile ? compiledPath : join16(projectDir, relativePath);
84175
84260
  if (!existsSync17(filePath) || !statSync4(filePath).isFile()) {
84176
84261
  return c3.text("Not found", 404);
84177
84262
  }
@@ -85624,7 +85709,7 @@ var init_shaderTransitions = __esm({
85624
85709
 
85625
85710
  // ../engine/src/services/hdrCapture.ts
85626
85711
  import { existsSync as existsSync18, readdirSync as readdirSync7 } from "fs";
85627
- import { join as join16 } from "path";
85712
+ import { join as join17 } from "path";
85628
85713
  import { homedir as homedir3 } from "os";
85629
85714
  function linearToPQ(L2) {
85630
85715
  const Lp = Math.max(0, L2 * SDR_NITS / PQ_MAX_NITS);
@@ -85740,12 +85825,12 @@ function float16ToPqRgb(rawBuffer, bytesPerRow, width, height) {
85740
85825
  return output;
85741
85826
  }
85742
85827
  function resolveHeadedChromePath() {
85743
- const baseDir = join16(homedir3(), ".cache", "puppeteer", "chrome");
85828
+ const baseDir = join17(homedir3(), ".cache", "puppeteer", "chrome");
85744
85829
  if (!existsSync18(baseDir)) return void 0;
85745
85830
  const versions = readdirSync7(baseDir).sort().reverse();
85746
85831
  for (const version2 of versions) {
85747
85832
  const candidates = [
85748
- join16(
85833
+ join17(
85749
85834
  baseDir,
85750
85835
  version2,
85751
85836
  "chrome-mac-arm64",
@@ -85754,7 +85839,7 @@ function resolveHeadedChromePath() {
85754
85839
  "MacOS",
85755
85840
  "Google Chrome for Testing"
85756
85841
  ),
85757
- join16(
85842
+ join17(
85758
85843
  baseDir,
85759
85844
  version2,
85760
85845
  "chrome-mac-x64",
@@ -85763,8 +85848,8 @@ function resolveHeadedChromePath() {
85763
85848
  "MacOS",
85764
85849
  "Google Chrome for Testing"
85765
85850
  ),
85766
- join16(baseDir, version2, "chrome-linux64", "chrome"),
85767
- join16(baseDir, version2, "chrome-win64", "chrome.exe")
85851
+ join17(baseDir, version2, "chrome-linux64", "chrome"),
85852
+ join17(baseDir, version2, "chrome-win64", "chrome.exe")
85768
85853
  ];
85769
85854
  for (const binary of candidates) {
85770
85855
  if (existsSync18(binary)) return binary;
@@ -85964,6 +86049,7 @@ __export(src_exports, {
85964
86049
  prepareCaptureSessionForReuse: () => prepareCaptureSessionForReuse,
85965
86050
  probeBeginFrameLiveness: () => probeBeginFrameLiveness,
85966
86051
  processCompositionAudio: () => processCompositionAudio,
86052
+ psnrDb: () => psnrDb,
85967
86053
  quantizeTimeToFrame: () => quantizeTimeToFrame,
85968
86054
  queryElementStacking: () => queryElementStacking,
85969
86055
  queryVideoElementBounds: () => queryVideoElementBounds,
@@ -85975,6 +86061,7 @@ __export(src_exports, {
85975
86061
  resampleRgb48leObjectFit: () => resampleRgb48leObjectFit,
85976
86062
  resolveBrowserGpuMode: () => resolveBrowserGpuMode,
85977
86063
  resolveConfig: () => resolveConfig,
86064
+ resolveDeVerifyMinDb: () => resolveDeVerifyMinDb,
85978
86065
  resolveExtractCacheDir: () => resolveExtractCacheDir,
85979
86066
  resolveHeadlessShellPath: () => resolveHeadlessShellPath,
85980
86067
  resolveProjectRelativeSrc: () => resolveProjectRelativeSrc,
@@ -85982,6 +86069,7 @@ __export(src_exports, {
85982
86069
  runFfmpeg: () => runFfmpeg,
85983
86070
  sampleRgb48le: () => sampleRgb48le,
85984
86071
  scaleProtocolTimeoutForComposition: () => scaleProtocolTimeoutForComposition,
86072
+ selectVerifySampleIndicesForTask: () => selectVerifySampleIndicesForTask,
85985
86073
  shouldClampToScreenshotForConcreteGpu: () => shouldClampToScreenshotForConcreteGpu,
85986
86074
  showVideoElements: () => showVideoElements,
85987
86075
  spawnStreamingEncoder: () => spawnStreamingEncoder,
@@ -85989,6 +86077,7 @@ __export(src_exports, {
85989
86077
  trackChildProcess: () => trackChildProcess,
85990
86078
  uploadAndReadbackHdrFrame: () => uploadAndReadbackHdrFrame,
85991
86079
  validateEngineConfigSnapshot: () => validateEngineConfigSnapshot,
86080
+ verifyDiskDrawElementSamples: () => verifyDiskDrawElementSamples,
85992
86081
  verifyGpuParity: () => verifyGpuParity,
85993
86082
  writeCapturedFrame: () => writeCapturedFrame
85994
86083
  });
@@ -86020,6 +86109,7 @@ var init_src = __esm({
86020
86109
  init_managedChildProcess();
86021
86110
  init_ffmpegBinaries();
86022
86111
  init_processTracker();
86112
+ init_psnr();
86023
86113
  init_alphaBlit();
86024
86114
  init_layerCompositor();
86025
86115
  init_gpuParityDiff();
@@ -89226,11 +89316,11 @@ var init_banner = __esm({
89226
89316
 
89227
89317
  // src/registry/remote.ts
89228
89318
  import { mkdirSync as mkdirSync10, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "fs";
89229
- import { join as join17, dirname as dirname9 } from "path";
89319
+ import { join as join18, dirname as dirname9 } from "path";
89230
89320
  import { homedir as homedir4 } from "os";
89231
89321
  function cachePath(baseUrl, key2) {
89232
89322
  const slug = baseUrl.replace(/[^a-zA-Z0-9]/g, "_");
89233
- return join17(CACHE_DIR, `${slug}__${key2}.json`);
89323
+ return join18(CACHE_DIR, `${slug}__${key2}.json`);
89234
89324
  }
89235
89325
  function readCache(path2) {
89236
89326
  try {
@@ -89301,7 +89391,7 @@ var init_remote = __esm({
89301
89391
  init_dist3();
89302
89392
  DEFAULT_REGISTRY_URL = "https://raw.githubusercontent.com/heygen-com/hyperframes/main/registry";
89303
89393
  FETCH_TIMEOUT_MS = 1e4;
89304
- CACHE_DIR = join17(homedir4(), ".hyperframes", "cache");
89394
+ CACHE_DIR = join18(homedir4(), ".hyperframes", "cache");
89305
89395
  CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
89306
89396
  }
89307
89397
  });
@@ -89579,7 +89669,7 @@ var init_compatibility = __esm({
89579
89669
 
89580
89670
  // src/templates/remote.ts
89581
89671
  import { existsSync as existsSync21 } from "fs";
89582
- import { join as join18 } from "path";
89672
+ import { join as join19 } from "path";
89583
89673
  async function fetchRemoteTemplate(templateId, destDir) {
89584
89674
  const items = await resolveItemWithDependencies(templateId);
89585
89675
  const warnings = gateRegistryItemsCompatibility(items);
@@ -89590,7 +89680,7 @@ async function fetchRemoteTemplate(templateId, destDir) {
89590
89680
  for (const item of items) {
89591
89681
  await installItem(item, { destDir });
89592
89682
  }
89593
- if (!existsSync21(join18(destDir, "index.html"))) {
89683
+ if (!existsSync21(join19(destDir, "index.html"))) {
89594
89684
  throw new Error(
89595
89685
  `Example "${templateId}" installed but missing index.html. The registry item may be malformed.`
89596
89686
  );
@@ -89945,7 +90035,7 @@ __export(manager_exports, {
89945
90035
  import { execFileSync as execFileSync4 } from "child_process";
89946
90036
  import { existsSync as existsSync23, mkdirSync as mkdirSync11, rmSync as rmSync4 } from "fs";
89947
90037
  import { homedir as homedir5, platform as platform4 } from "os";
89948
- import { join as join19 } from "path";
90038
+ import { join as join20 } from "path";
89949
90039
  function isWhisperUnavailable(err) {
89950
90040
  if (err instanceof WhisperUnavailableError) return true;
89951
90041
  return err instanceof Error && "code" in err && err.code === "WHISPER_UNAVAILABLE";
@@ -89986,8 +90076,8 @@ function findFromSystem() {
89986
90076
  }
89987
90077
  function findBuiltBinary() {
89988
90078
  for (const p2 of [
89989
- join19(BUILD_DIR, "build", "bin", "whisper-cli"),
89990
- join19(BUILD_DIR, "build", "whisper-cli")
90079
+ join20(BUILD_DIR, "build", "bin", "whisper-cli"),
90080
+ join20(BUILD_DIR, "build", "whisper-cli")
89991
90081
  ]) {
89992
90082
  if (existsSync23(p2)) return { executablePath: p2, source: "build" };
89993
90083
  }
@@ -89999,7 +90089,7 @@ function buildFromSource(onProgress) {
89999
90089
  }
90000
90090
  if (!existsSync23(BUILD_DIR)) {
90001
90091
  onProgress?.("Downloading whisper.cpp...");
90002
- mkdirSync11(join19(homedir5(), ".cache", "hyperframes", "whisper"), {
90092
+ mkdirSync11(join20(homedir5(), ".cache", "hyperframes", "whisper"), {
90003
90093
  recursive: true
90004
90094
  });
90005
90095
  execFileSync4("git", ["clone", "--depth", "1", WHISPER_REPO, BUILD_DIR], {
@@ -90084,7 +90174,7 @@ async function ensureWhisper(options) {
90084
90174
  throw new WhisperUnavailableError(`whisper-cpp not found. Install: ${getInstallInstructions()}`);
90085
90175
  }
90086
90176
  async function ensureModel(model = DEFAULT_MODEL, options) {
90087
- const modelPath2 = join19(MODELS_DIR, `ggml-${model}.bin`);
90177
+ const modelPath2 = join20(MODELS_DIR, `ggml-${model}.bin`);
90088
90178
  if (existsSync23(modelPath2)) return modelPath2;
90089
90179
  mkdirSync11(MODELS_DIR, { recursive: true });
90090
90180
  options?.onProgress?.(`Downloading model ${model}...`);
@@ -90103,7 +90193,7 @@ var init_manager = __esm({
90103
90193
  "use strict";
90104
90194
  init_ffmpeg();
90105
90195
  init_download();
90106
- MODELS_DIR = join19(homedir5(), ".cache", "hyperframes", "whisper", "models");
90196
+ MODELS_DIR = join20(homedir5(), ".cache", "hyperframes", "whisper", "models");
90107
90197
  DEFAULT_MODEL = "small.en";
90108
90198
  WhisperUnavailableError = class extends Error {
90109
90199
  code = "WHISPER_UNAVAILABLE";
@@ -90112,7 +90202,7 @@ var init_manager = __esm({
90112
90202
  this.name = "WhisperUnavailableError";
90113
90203
  }
90114
90204
  };
90115
- BUILD_DIR = join19(homedir5(), ".cache", "hyperframes", "whisper", "whisper.cpp");
90205
+ BUILD_DIR = join20(homedir5(), ".cache", "hyperframes", "whisper", "whisper.cpp");
90116
90206
  WHISPER_REPO = "https://github.com/ggml-org/whisper.cpp.git";
90117
90207
  }
90118
90208
  });
@@ -90132,8 +90222,8 @@ __export(transcribe_exports, {
90132
90222
  });
90133
90223
  import { execFileSync as execFileSync5 } from "child_process";
90134
90224
  import { existsSync as existsSync24, readFileSync as readFileSync14, mkdirSync as mkdirSync12, unlinkSync as unlinkSync2 } from "fs";
90135
- import { join as join20, extname as extname6 } from "path";
90136
- import { tmpdir as tmpdir2 } from "os";
90225
+ import { join as join21, extname as extname6 } from "path";
90226
+ import { tmpdir as tmpdir3 } from "os";
90137
90227
  import { randomUUID as randomUUID4 } from "crypto";
90138
90228
  function detectLanguage(whisperPath, modelPath2, wavPath) {
90139
90229
  try {
@@ -90275,7 +90365,7 @@ function isVideoFile(filePath) {
90275
90365
  return VIDEO_EXTENSIONS.has(extname6(filePath).toLowerCase());
90276
90366
  }
90277
90367
  function tempWavPath() {
90278
- return join20(tmpdir2(), `hyperframes-audio-${process.pid}-${randomUUID4()}.wav`);
90368
+ return join21(tmpdir3(), `hyperframes-audio-${process.pid}-${randomUUID4()}.wav`);
90279
90369
  }
90280
90370
  function extractAudio(videoPath) {
90281
90371
  const ffmpegPath = findFFmpeg();
@@ -90382,7 +90472,7 @@ async function transcribe(inputPath, outputDir, options) {
90382
90472
  effectiveModel = multilingualModel;
90383
90473
  }
90384
90474
  options?.onProgress?.("Transcribing...");
90385
- const outputBase = join20(outputDir, "transcript");
90475
+ const outputBase = join21(outputDir, "transcript");
90386
90476
  mkdirSync12(outputDir, { recursive: true });
90387
90477
  const whisperArgs = [
90388
90478
  "--model",
@@ -90504,7 +90594,7 @@ __export(normalize_exports, {
90504
90594
  wordsToCues: () => wordsToCues
90505
90595
  });
90506
90596
  import { readFileSync as readFileSync15, readdirSync as readdirSync8, writeFileSync as writeFileSync9 } from "fs";
90507
- import { extname as extname7, join as join21 } from "path";
90597
+ import { extname as extname7, join as join22 } from "path";
90508
90598
  function detectFormat(filePath) {
90509
90599
  const ext = extname7(filePath).toLowerCase();
90510
90600
  if (ext === ".srt") return "srt";
@@ -90781,7 +90871,7 @@ function patchCaptionHtml(dir, words) {
90781
90871
  const wordsJson = JSON.stringify(words, null, 2).replace(/\n/g, "\n ");
90782
90872
  let htmlFiles;
90783
90873
  try {
90784
- htmlFiles = readdirSync8(dir, { withFileTypes: true, recursive: true }).filter((e3) => e3.isFile() && e3.name.endsWith(".html")).map((e3) => join21(e3.parentPath, e3.name));
90874
+ htmlFiles = readdirSync8(dir, { withFileTypes: true, recursive: true }).filter((e3) => e3.isFile() && e3.name.endsWith(".html")).map((e3) => join22(e3.parentPath, e3.name));
90785
90875
  } catch {
90786
90876
  return;
90787
90877
  }
@@ -90823,9 +90913,9 @@ __export(projectConfig_exports, {
90823
90913
  writeProjectConfig: () => writeProjectConfig
90824
90914
  });
90825
90915
  import { readFileSync as readFileSync16, writeFileSync as writeFileSync10 } from "fs";
90826
- import { join as join22, resolve as resolve12 } from "path";
90916
+ import { join as join23, resolve as resolve12 } from "path";
90827
90917
  function projectConfigPath(projectDir) {
90828
- return join22(resolve12(projectDir), PROJECT_CONFIG_FILENAME);
90918
+ return join23(resolve12(projectDir), PROJECT_CONFIG_FILENAME);
90829
90919
  }
90830
90920
  function readProjectConfig(projectDir) {
90831
90921
  const path2 = projectConfigPath(projectDir);
@@ -91063,7 +91153,7 @@ __export(updateCheck_exports, {
91063
91153
  withMeta: () => withMeta
91064
91154
  });
91065
91155
  import { existsSync as existsSync25, readFileSync as readFileSync17 } from "fs";
91066
- import { join as join23 } from "path";
91156
+ import { join as join24 } from "path";
91067
91157
  import { compareVersions as compareVersions2 } from "compare-versions";
91068
91158
  function isNewerSemver(a, b2) {
91069
91159
  try {
@@ -91164,7 +91254,7 @@ function printStalePinNotice(cwd = process.cwd()) {
91164
91254
  if (!latest || !isSafeVersion(latest)) return;
91165
91255
  let scripts = {};
91166
91256
  try {
91167
- const pkgPath = join23(cwd, "package.json");
91257
+ const pkgPath = join24(cwd, "package.json");
91168
91258
  if (!existsSync25(pkgPath)) return;
91169
91259
  scripts = JSON.parse(readFileSync17(pkgPath, "utf-8")).scripts ?? {};
91170
91260
  } catch {
@@ -91210,7 +91300,7 @@ var init_updateCheck = __esm({
91210
91300
  });
91211
91301
 
91212
91302
  // src/utils/skillsManifest.ts
91213
- import { execFile as execFile2 } from "child_process";
91303
+ import { execFile as execFile3 } from "child_process";
91214
91304
  import { createHash as createHash3 } from "crypto";
91215
91305
  import {
91216
91306
  existsSync as existsSync26,
@@ -91221,8 +91311,8 @@ import {
91221
91311
  writeFileSync as writeFileSync11
91222
91312
  } from "fs";
91223
91313
  import { homedir as homedir6 } from "os";
91224
- import { isAbsolute as isAbsolute6, join as join24, relative as relative6, resolve as resolve13, sep as sep4 } from "path";
91225
- import { promisify } from "util";
91314
+ import { isAbsolute as isAbsolute6, join as join25, relative as relative6, resolve as resolve13, sep as sep4 } from "path";
91315
+ import { promisify as promisify2 } from "util";
91226
91316
  function isCoreSkill(name) {
91227
91317
  return name === ENTRY_SKILL || name.startsWith("hyperframes-") || name === "media-use";
91228
91318
  }
@@ -91231,7 +91321,7 @@ function listFilesSorted(dir) {
91231
91321
  const walk = (d2) => {
91232
91322
  for (const name of readdirSync9(d2)) {
91233
91323
  if (name === ".DS_Store") continue;
91234
- const p2 = join24(d2, name);
91324
+ const p2 = join25(d2, name);
91235
91325
  if (statSync6(p2).isDirectory()) walk(p2);
91236
91326
  else out.push(p2);
91237
91327
  }
@@ -91255,9 +91345,9 @@ function hashSkillBundle(skillDir) {
91255
91345
  return { hash: h3.digest("hex").slice(0, 16), files: files.length };
91256
91346
  }
91257
91347
  function buildManifest(skillsRoot, meta) {
91258
- const names = readdirSync9(skillsRoot).filter((n2) => existsSync26(join24(skillsRoot, n2, "SKILL.md"))).sort();
91348
+ const names = readdirSync9(skillsRoot).filter((n2) => existsSync26(join25(skillsRoot, n2, "SKILL.md"))).sort();
91259
91349
  const skills = {};
91260
- for (const name of names) skills[name] = hashSkillBundle(join24(skillsRoot, name));
91350
+ for (const name of names) skills[name] = hashSkillBundle(join25(skillsRoot, name));
91261
91351
  return { source: meta.source, skills };
91262
91352
  }
91263
91353
  function agentLabel(hostDir) {
@@ -91279,12 +91369,12 @@ function listSubdirs(dir) {
91279
91369
  function discoverSkillRoots(base2, scope) {
91280
91370
  const candidates = [];
91281
91371
  const add2 = (hostBase, host) => {
91282
- const dir = join24(hostBase, host, "skills");
91372
+ const dir = join25(hostBase, host, "skills");
91283
91373
  if (existsSync26(dir) && statSync6(dir).isDirectory())
91284
91374
  candidates.push({ dir, agent: agentLabel(host), scope });
91285
91375
  };
91286
91376
  for (const host of listSubdirs(base2)) add2(base2, host);
91287
- const xdg = join24(base2, ".config");
91377
+ const xdg = join25(base2, ".config");
91288
91378
  for (const host of listSubdirs(xdg)) add2(xdg, host);
91289
91379
  return candidates.sort((a, b2) => {
91290
91380
  if (a.agent !== b2.agent) {
@@ -91318,20 +91408,20 @@ function locateInstall(skillNames, opts = {}) {
91318
91408
  ...discoverSkillRoots(opts.cwd ?? process.cwd(), "project")
91319
91409
  ];
91320
91410
  for (const root of roots) {
91321
- if (skillNames.some((n2) => existsSync26(join24(root.dir, n2, "SKILL.md")))) return root;
91411
+ if (skillNames.some((n2) => existsSync26(join25(root.dir, n2, "SKILL.md")))) return root;
91322
91412
  }
91323
91413
  return null;
91324
91414
  }
91325
91415
  function presentSkills(skillNames, opts = {}) {
91326
91416
  const root = locateInstall([...skillNames], opts);
91327
91417
  if (!root) return [];
91328
- return skillNames.filter((name) => existsSync26(join24(root.dir, name, "SKILL.md")));
91418
+ return skillNames.filter((name) => existsSync26(join25(root.dir, name, "SKILL.md")));
91329
91419
  }
91330
91420
  function hashInstalled(root, skillNames) {
91331
91421
  const out = {};
91332
91422
  for (const name of skillNames) {
91333
- const skillDir = join24(root.dir, name);
91334
- if (existsSync26(join24(skillDir, "SKILL.md"))) out[name] = hashSkillBundle(skillDir);
91423
+ const skillDir = join25(root.dir, name);
91424
+ if (existsSync26(join25(skillDir, "SKILL.md"))) out[name] = hashSkillBundle(skillDir);
91335
91425
  }
91336
91426
  return out;
91337
91427
  }
@@ -91380,10 +91470,10 @@ function skillsAttributedToSource(lock, source) {
91380
91470
  return Object.entries(lock.skills).filter(([, e3]) => repoSlug(e3.source) === want || repoSlug(e3.sourceUrl) === want).map(([name]) => name);
91381
91471
  }
91382
91472
  function lockPathForScope(scope, opts) {
91383
- if (scope === "project") return join24(opts.cwd ?? process.cwd(), "skills-lock.json");
91473
+ if (scope === "project") return join25(opts.cwd ?? process.cwd(), "skills-lock.json");
91384
91474
  const xdgStateHome = process.env.XDG_STATE_HOME;
91385
- if (xdgStateHome) return join24(xdgStateHome, "skills", ".skill-lock.json");
91386
- return join24(opts.home ?? homedir6(), ".agents", ".skill-lock.json");
91475
+ if (xdgStateHome) return join25(xdgStateHome, "skills", ".skill-lock.json");
91476
+ return join25(opts.home ?? homedir6(), ".agents", ".skill-lock.json");
91387
91477
  }
91388
91478
  function readSkillLock(path2) {
91389
91479
  try {
@@ -91417,9 +91507,9 @@ function pruneOrphanedLockEntries(names, scope, opts = {}) {
91417
91507
  function findRepoManifest(cwd = process.cwd()) {
91418
91508
  let dir = cwd;
91419
91509
  for (let i2 = 0; i2 < 16; i2++) {
91420
- const p2 = join24(dir, MANIFEST_FILE);
91510
+ const p2 = join25(dir, MANIFEST_FILE);
91421
91511
  if (existsSync26(p2)) return p2;
91422
- const parent = join24(dir, "..");
91512
+ const parent = join25(dir, "..");
91423
91513
  if (parent === dir) break;
91424
91514
  dir = parent;
91425
91515
  }
@@ -91457,9 +91547,9 @@ async function remoteHeadSha(repoSlug2) {
91457
91547
  }
91458
91548
  }
91459
91549
  function resolveLocalManifest(source) {
91460
- const direct = source.endsWith(".json") ? source : join24(source, MANIFEST_FILE);
91550
+ const direct = source.endsWith(".json") ? source : join25(source, MANIFEST_FILE);
91461
91551
  if (existsSync26(direct)) return JSON.parse(readFileSync18(direct, "utf8"));
91462
- const skillsRoot = source.endsWith("skills") ? source : join24(source, "skills");
91552
+ const skillsRoot = source.endsWith("skills") ? source : join25(source, "skills");
91463
91553
  if (existsSync26(skillsRoot)) return buildManifest(skillsRoot, { source: skillsRoot });
91464
91554
  throw new Error(`No skills manifest found at: ${source}`);
91465
91555
  }
@@ -91511,7 +91601,7 @@ var execFileAsync2, TEXT_EXT, DEFAULT_REPO_SLUG, MANIFEST_FILE, FETCH_TIMEOUT_MS
91511
91601
  var init_skillsManifest = __esm({
91512
91602
  "src/utils/skillsManifest.ts"() {
91513
91603
  "use strict";
91514
- execFileAsync2 = promisify(execFile2);
91604
+ execFileAsync2 = promisify2(execFile3);
91515
91605
  TEXT_EXT = /* @__PURE__ */ new Set([
91516
91606
  ".md",
91517
91607
  ".txt",
@@ -91629,22 +91719,22 @@ var init_agentDirs_generated = __esm({
91629
91719
  // src/utils/skillsMirror.ts
91630
91720
  import { cpSync, existsSync as existsSync27, mkdirSync as mkdirSync13, readdirSync as readdirSync10, rmSync as rmSync5, symlinkSync } from "fs";
91631
91721
  import { homedir as homedir7 } from "os";
91632
- import { dirname as dirname10, isAbsolute as isAbsolute7, join as join25, relative as relative7 } from "path";
91722
+ import { dirname as dirname10, isAbsolute as isAbsolute7, join as join26, relative as relative7 } from "path";
91633
91723
  function resolveBases(home, env) {
91634
91724
  const xdg = env["XDG_CONFIG_HOME"]?.trim();
91635
91725
  return {
91636
91726
  home,
91637
- configHome: xdg && isAbsolute7(xdg) ? xdg : join25(home, ".config"),
91638
- codexHome: env["CODEX_HOME"]?.trim() || join25(home, ".codex"),
91639
- claudeHome: env["CLAUDE_CONFIG_DIR"]?.trim() || join25(home, ".claude"),
91640
- vibeHome: env["VIBE_HOME"]?.trim() || join25(home, ".vibe"),
91641
- hermesHome: env["HERMES_HOME"]?.trim() || join25(home, ".hermes"),
91642
- autohandHome: env["AUTOHAND_HOME"]?.trim() || join25(home, ".autohand")
91727
+ configHome: xdg && isAbsolute7(xdg) ? xdg : join26(home, ".config"),
91728
+ codexHome: env["CODEX_HOME"]?.trim() || join26(home, ".codex"),
91729
+ claudeHome: env["CLAUDE_CONFIG_DIR"]?.trim() || join26(home, ".claude"),
91730
+ vibeHome: env["VIBE_HOME"]?.trim() || join26(home, ".vibe"),
91731
+ hermesHome: env["HERMES_HOME"]?.trim() || join26(home, ".hermes"),
91732
+ autohandHome: env["AUTOHAND_HOME"]?.trim() || join26(home, ".autohand")
91643
91733
  };
91644
91734
  }
91645
91735
  function listSkillDirs(store) {
91646
91736
  return readdirSync10(store, { withFileTypes: true }).filter(
91647
- (e3) => (e3.isDirectory() || e3.isSymbolicLink()) && existsSync27(join25(store, e3.name, "SKILL.md"))
91737
+ (e3) => (e3.isDirectory() || e3.isSymbolicLink()) && existsSync27(join26(store, e3.name, "SKILL.md"))
91648
91738
  ).map((e3) => e3.name);
91649
91739
  }
91650
91740
  function linkOrCopy(sourceSkill, targetSkill, platform10) {
@@ -91663,7 +91753,7 @@ function mirrorInto(targetDir, source, skills, platform10) {
91663
91753
  }
91664
91754
  for (const skill of skills) {
91665
91755
  try {
91666
- linkOrCopy(join25(source, skill), join25(targetDir, skill), platform10);
91756
+ linkOrCopy(join26(source, skill), join26(targetDir, skill), platform10);
91667
91757
  } catch {
91668
91758
  }
91669
91759
  }
@@ -91673,15 +91763,15 @@ function mirrorGlobalSkills(opts) {
91673
91763
  const home = opts.home ?? homedir7();
91674
91764
  const platform10 = opts.platform ?? process.platform;
91675
91765
  const bases = resolveBases(home, opts.env ?? process.env);
91676
- const source = join25(bases.claudeHome, "skills");
91677
- const universalStore = join25(home, ".agents", "skills");
91766
+ const source = join26(bases.claudeHome, "skills");
91767
+ const universalStore = join26(home, ".agents", "skills");
91678
91768
  if (!existsSync27(source)) return { source: null, mirrored: [] };
91679
91769
  const allowed = new Set(opts.skills);
91680
91770
  const skills = listSkillDirs(source).filter((name) => allowed.has(name));
91681
91771
  if (skills.length === 0) return { source, mirrored: [] };
91682
91772
  const mirrored = [];
91683
91773
  for (const { agent, base: base2, sub } of AGENT_GLOBAL_DIRS) {
91684
- const targetDir = join25(bases[base2], ...sub.split("/").filter(Boolean));
91774
+ const targetDir = join26(bases[base2], ...sub.split("/").filter(Boolean));
91685
91775
  if (targetDir === source || targetDir === universalStore) continue;
91686
91776
  if (!existsSync27(dirname10(targetDir))) continue;
91687
91777
  if (mirrorInto(targetDir, source, skills, platform10)) mirrored.push({ agent, dir: targetDir });
@@ -92634,8 +92724,8 @@ var init_lintFormat = __esm({
92634
92724
  // src/server/portUtils.ts
92635
92725
  import net from "net";
92636
92726
  import http from "http";
92637
- import { execFile as execFile3 } from "child_process";
92638
- import { promisify as promisify2 } from "util";
92727
+ import { execFile as execFile4 } from "child_process";
92728
+ import { promisify as promisify3 } from "util";
92639
92729
  import { resolve as resolve14 } from "path";
92640
92730
  async function isPortAvailableOnHost(port, host) {
92641
92731
  const probe = net.createServer();
@@ -92869,7 +92959,7 @@ var init_portUtils = __esm({
92869
92959
  "src/server/portUtils.ts"() {
92870
92960
  "use strict";
92871
92961
  init_colors();
92872
- execFileAsync3 = promisify2(execFile3);
92962
+ execFileAsync3 = promisify3(execFile4);
92873
92963
  MAX_PORT_SCAN = 100;
92874
92964
  PROBE_TIMEOUT_MS2 = 300;
92875
92965
  PROBE_MAX_BYTES = 4096;
@@ -93101,20 +93191,20 @@ import {
93101
93191
  writeFileSync as writeFileSync12
93102
93192
  } from "fs";
93103
93193
  import { homedir as homedir8 } from "os";
93104
- import { dirname as dirname11, join as join26, resolve as resolve16 } from "path";
93194
+ import { dirname as dirname11, join as join27, resolve as resolve16 } from "path";
93105
93195
  function defaultStateHome() {
93106
- return process.env.XDG_STATE_HOME || join26(homedir8(), ".local", "state");
93196
+ return process.env.XDG_STATE_HOME || join27(homedir8(), ".local", "state");
93107
93197
  }
93108
93198
  function normalized(path2) {
93109
93199
  const resolved2 = resolve16(path2).replace(/\\/g, "/");
93110
93200
  return process.platform === "win32" ? resolved2.toLowerCase() : resolved2;
93111
93201
  }
93112
93202
  function sessionDirectory(stateHome = defaultStateHome()) {
93113
- return join26(stateHome, "hyperframes", "previews");
93203
+ return join27(stateHome, "hyperframes", "previews");
93114
93204
  }
93115
93205
  function previewSessionPath(projectDir, stateHome = defaultStateHome()) {
93116
93206
  const key2 = createHash4("sha256").update(normalized(projectDir)).digest("hex").slice(0, 16);
93117
- return join26(sessionDirectory(stateHome), `${key2}.json`);
93207
+ return join27(sessionDirectory(stateHome), `${key2}.json`);
93118
93208
  }
93119
93209
  function previewLogPath(projectDir, stateHome = defaultStateHome()) {
93120
93210
  return previewSessionPath(projectDir, stateHome).replace(/\.json$/, ".log");
@@ -94436,7 +94526,7 @@ var init_chunk_W2SBTCO2 = __esm({
94436
94526
  // ../studio-server/dist/chunk-7Q5AFHU6.js
94437
94527
  import { existsSync as existsSync32, statSync as statSync8 } from "fs";
94438
94528
  import { relative as relative8, resolve as resolve19, sep as sep5 } from "path";
94439
- import { execFile as execFile4 } from "child_process";
94529
+ import { execFile as execFile5 } from "child_process";
94440
94530
  import { extname as extname8 } from "path";
94441
94531
  function lower(value) {
94442
94532
  return value?.toLowerCase() ?? "";
@@ -94642,7 +94732,7 @@ var init_chunk_7Q5AFHU6 = __esm({
94642
94732
  init_assetResolution();
94643
94733
  init_ffBinaries();
94644
94734
  execFileRunner = (command2, args, options) => new Promise((resolvePromise) => {
94645
- execFile4(
94735
+ execFile5(
94646
94736
  command2,
94647
94737
  args,
94648
94738
  { timeout: options?.timeout, maxBuffer: options?.maxBuffer },
@@ -94707,9 +94797,9 @@ import {
94707
94797
  unlinkSync as unlinkSync22,
94708
94798
  utimesSync as utimesSync2
94709
94799
  } from "fs";
94710
- import { basename as basename3, dirname as dirname13, isAbsolute as isAbsolute8, join as join27, relative as relative9, sep as sep6 } from "path";
94800
+ import { basename as basename3, dirname as dirname13, isAbsolute as isAbsolute8, join as join28, relative as relative9, sep as sep6 } from "path";
94711
94801
  import { existsSync as existsSync33, readdirSync as readdirSync11, statSync as statSync9, unlinkSync as unlinkSync3 } from "fs";
94712
- import { extname as extname9, join as join28 } from "path";
94802
+ import { extname as extname9, join as join29 } from "path";
94713
94803
  function positiveEnvNumber(name, fallback) {
94714
94804
  const parsed = Number(process.env[name]);
94715
94805
  return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
@@ -94736,7 +94826,7 @@ function readCacheInventory(cacheDir, protectedPaths, now, staleTempMs) {
94736
94826
  const staleTemps = [];
94737
94827
  for (const dirent of readdirSync11(cacheDir, { withFileTypes: true })) {
94738
94828
  if (!dirent.isFile()) continue;
94739
- const path2 = join28(cacheDir, dirent.name);
94829
+ const path2 = join29(cacheDir, dirent.name);
94740
94830
  const stat3 = statSync9(path2);
94741
94831
  const entry = {
94742
94832
  path: path2,
@@ -94835,7 +94925,7 @@ function buildProxyCacheKey(source, variant) {
94835
94925
  }
94836
94926
  function getCanonicalProxyCachePath(source, variant) {
94837
94927
  const key2 = buildProxyCacheKey(source, variant);
94838
- return join27(
94928
+ return join28(
94839
94929
  source.projectDir,
94840
94930
  CACHE_DIR_NAME,
94841
94931
  `${key2}${PROXY_VARIANT_CONFIG[variant].extension}`
@@ -95014,7 +95104,7 @@ async function transcodeToCache(absoluteSourcePath, cachePath2, variant) {
95014
95104
  if (existsSync210(cachePath2)) return cachePath2;
95015
95105
  const cacheDir = dirname13(cachePath2);
95016
95106
  mkdirSync15(cacheDir, { recursive: true });
95017
- const tempPath = join27(cacheDir, `.tmp-${randomUUID5()}-${basename3(cachePath2)}`);
95107
+ const tempPath = join28(cacheDir, `.tmp-${randomUUID5()}-${basename3(cachePath2)}`);
95018
95108
  try {
95019
95109
  await runFfmpeg2(absoluteSourcePath, tempPath, variant);
95020
95110
  renameSync6(tempPath, cachePath2);
@@ -98771,7 +98861,7 @@ var init_gsapWriterAcorn = __esm({
98771
98861
  import { execFileSync as execFileSync7 } from "child_process";
98772
98862
  import { existsSync as existsSync34, lstatSync as lstatSync2, readdirSync as readdirSync12, realpathSync as realpathSync5 } from "fs";
98773
98863
  import { homedir as homedir9, platform as platform5 } from "os";
98774
- import { join as join29, resolve as resolve21 } from "path";
98864
+ import { join as join30, resolve as resolve21 } from "path";
98775
98865
  function getAllowedFontDirs() {
98776
98866
  if (allowedDirsCache)
98777
98867
  return allowedDirsCache;
@@ -98840,7 +98930,7 @@ function fontDirectories() {
98840
98930
  const home = homedir9();
98841
98931
  if (platform5() === "darwin") {
98842
98932
  return [
98843
- join29(home, "Library", "Fonts"),
98933
+ join30(home, "Library", "Fonts"),
98844
98934
  "/Library/Fonts",
98845
98935
  "/System/Library/Fonts",
98846
98936
  "/System/Library/Fonts/Supplemental"
@@ -98848,13 +98938,13 @@ function fontDirectories() {
98848
98938
  }
98849
98939
  if (platform5() === "win32") {
98850
98940
  return [
98851
- join29(process.env.WINDIR || "C:\\Windows", "Fonts"),
98852
- join29(process.env.LOCALAPPDATA || join29(homedir9(), "AppData", "Local"), "Microsoft", "Windows", "Fonts")
98941
+ join30(process.env.WINDIR || "C:\\Windows", "Fonts"),
98942
+ join30(process.env.LOCALAPPDATA || join30(homedir9(), "AppData", "Local"), "Microsoft", "Windows", "Fonts")
98853
98943
  ];
98854
98944
  }
98855
98945
  return [
98856
- join29(home, ".fonts"),
98857
- join29(home, ".local", "share", "fonts"),
98946
+ join30(home, ".fonts"),
98947
+ join30(home, ".local", "share", "fonts"),
98858
98948
  "/usr/local/share/fonts",
98859
98949
  "/usr/share/fonts"
98860
98950
  ];
@@ -98865,7 +98955,7 @@ function collectFontFileEntries(dir, depth = 0) {
98865
98955
  const entries2 = [];
98866
98956
  try {
98867
98957
  for (const entry of readdirSync12(dir, { withFileTypes: true })) {
98868
- const fullPath = join29(dir, entry.name);
98958
+ const fullPath = join30(dir, entry.name);
98869
98959
  if (entry.isDirectory()) {
98870
98960
  entries2.push(...collectFontFileEntries(fullPath, depth + 1));
98871
98961
  continue;
@@ -101687,9 +101777,9 @@ var init_gsapParser = __esm({
101687
101777
 
101688
101778
  // ../studio-server/dist/index.js
101689
101779
  import { Hono as Hono2 } from "hono";
101690
- import { readFile } from "fs/promises";
101780
+ import { readFile as readFile2 } from "fs/promises";
101691
101781
  import { join as join210 } from "path";
101692
- import { join as join30 } from "path";
101782
+ import { join as join31 } from "path";
101693
101783
  import { readdirSync as readdirSync13 } from "fs";
101694
101784
  import { createHash as createHash7 } from "crypto";
101695
101785
  import { lstatSync as lstatSync3, readFileSync as readFileSync21, readdirSync as readdirSync22 } from "fs";
@@ -101717,7 +101807,7 @@ import { existsSync as existsSync211, writeFileSync as writeFileSync13, mkdirSyn
101717
101807
  import { join as join32 } from "path";
101718
101808
  import { spawnSync } from "child_process";
101719
101809
  import { mkdtempSync as mkdtempSync2, rmSync as rmSync7, writeFileSync as writeFileSync22 } from "fs";
101720
- import { tmpdir as tmpdir3 } from "os";
101810
+ import { tmpdir as tmpdir4 } from "os";
101721
101811
  import { basename as basename4, join as join42 } from "path";
101722
101812
  import { mkdirSync as mkdirSync22, readdirSync as readdirSync32, readFileSync as readFileSync32, unlinkSync as unlinkSync4, writeFileSync as writeFileSync32 } from "fs";
101723
101813
  import { Buffer as Buffer2 } from "buffer";
@@ -101771,7 +101861,7 @@ function walkDir(dir, prefix = "") {
101771
101861
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
101772
101862
  if (IGNORE_DIRS.has(entry.name) || shouldIgnoreDir(rel)) continue;
101773
101863
  if (entry.isDirectory()) {
101774
- files.push(...walkDir(join30(dir, entry.name), rel));
101864
+ files.push(...walkDir(join31(dir, entry.name), rel));
101775
101865
  } else {
101776
101866
  files.push(rel);
101777
101867
  }
@@ -101894,7 +101984,7 @@ async function filterCompositionFiles(projectDir, files) {
101894
101984
  const checks = await Promise.all(
101895
101985
  htmlFiles.map(async (f3) => {
101896
101986
  try {
101897
- const content = await readFile(join210(projectDir, f3), "utf-8");
101987
+ const content = await readFile2(join210(projectDir, f3), "utf-8");
101898
101988
  return COMPOSITION_ID_RE.test(content);
101899
101989
  } catch {
101900
101990
  return false;
@@ -102098,7 +102188,7 @@ function validateUploadedMedia(filePath, runner = spawnSync) {
102098
102188
  }
102099
102189
  }
102100
102190
  function validateUploadedMediaBuffer(fileName, buffer, runner = spawnSync) {
102101
- const tempDir = mkdtempSync2(join42(tmpdir3(), "hyperframes-upload-"));
102191
+ const tempDir = mkdtempSync2(join42(tmpdir4(), "hyperframes-upload-"));
102102
102192
  const tempPath = join42(tempDir, basename4(fileName));
102103
102193
  try {
102104
102194
  writeFileSync22(tempPath, buffer);
@@ -102446,7 +102536,7 @@ function foldElementPatches(originalContent, patches) {
102446
102536
  }
102447
102537
  return { content, matched };
102448
102538
  }
102449
- function commitElementPatchBatches(projectDir, batches, writeFile3 = writeFileSync42) {
102539
+ function commitElementPatchBatches(projectDir, batches, writeFile4 = writeFileSync42) {
102450
102540
  const resolvedPaths = /* @__PURE__ */ new Set();
102451
102541
  const prepared = [];
102452
102542
  for (const batch of batches) {
@@ -102501,7 +102591,7 @@ function commitElementPatchBatches(projectDir, batches, writeFile3 = writeFileSy
102501
102591
  throw new Error(`Failed to create backup for ${file.sourceFile}: ${backup.error}`);
102502
102592
  }
102503
102593
  attemptedWrites.push(file);
102504
- writeFile3(file.absPath, file.after, "utf-8");
102594
+ writeFile4(file.absPath, file.after, "utf-8");
102505
102595
  files.push({
102506
102596
  sourceFile: file.sourceFile,
102507
102597
  changed: true,
@@ -102515,7 +102605,7 @@ function commitElementPatchBatches(projectDir, batches, writeFile3 = writeFileSy
102515
102605
  const rollbackErrors = [];
102516
102606
  for (const file of attemptedWrites.reverse()) {
102517
102607
  try {
102518
- writeFile3(file.absPath, file.before, "utf-8");
102608
+ writeFile4(file.absPath, file.before, "utf-8");
102519
102609
  } catch (rollbackError) {
102520
102610
  rollbackErrors.push(rollbackError);
102521
102611
  }
@@ -106289,9 +106379,9 @@ var init_logger = __esm({
106289
106379
  import { Hono as Hono3 } from "hono";
106290
106380
  import { serve as serve2 } from "@hono/node-server";
106291
106381
  import { existsSync as existsSync38, realpathSync as realpathSync7, statSync as statSync11, createReadStream } from "fs";
106292
- import { readFile as readFile2 } from "fs/promises";
106382
+ import { readFile as readFile3 } from "fs/promises";
106293
106383
  import { Readable as Readable2 } from "stream";
106294
- import { join as join31, extname as extname11, resolve as resolve25, sep as sep8 } from "path";
106384
+ import { join as join33, extname as extname11, resolve as resolve25, sep as sep8 } from "path";
106295
106385
  function isPathInside2(child, parent, options = {}) {
106296
106386
  const { resolveSymlinks = false, pathModule } = options;
106297
106387
  const resolveFn = pathModule?.resolve ?? resolve25;
@@ -106635,13 +106725,13 @@ function createFileServer2(options) {
106635
106725
  }).join("/");
106636
106726
  let filePath = null;
106637
106727
  if (compiledDir) {
106638
- const candidate = join31(compiledDir, relativePath);
106728
+ const candidate = join33(compiledDir, relativePath);
106639
106729
  if (existsSync38(candidate) && isPathInside2(candidate, compiledDir) && statSync11(candidate).isFile()) {
106640
106730
  filePath = candidate;
106641
106731
  }
106642
106732
  }
106643
106733
  if (!filePath) {
106644
- const candidate = join31(projectDir, relativePath);
106734
+ const candidate = join33(projectDir, relativePath);
106645
106735
  if (existsSync38(candidate) && isPathInside2(candidate, projectDir) && statSync11(candidate).isFile()) {
106646
106736
  filePath = candidate;
106647
106737
  }
@@ -106655,7 +106745,7 @@ function createFileServer2(options) {
106655
106745
  const ext = extname11(filePath).toLowerCase();
106656
106746
  const contentType = MIME_TYPES3[ext] || "application/octet-stream";
106657
106747
  if (ext === ".html") {
106658
- const rawHtml = await readFile2(filePath, "utf-8");
106748
+ const rawHtml = await readFile3(filePath, "utf-8");
106659
106749
  const isIndex = relativePath === "index.html";
106660
106750
  let html = rawHtml;
106661
106751
  if (preHeadScripts.length > 0) {
@@ -106867,7 +106957,7 @@ var init_fileServer2 = __esm({
106867
106957
  // ../producer/src/utils/paths.ts
106868
106958
  import {
106869
106959
  basename as basename5,
106870
- join as join33,
106960
+ join as join34,
106871
106961
  resolve as nodeResolve,
106872
106962
  relative as nodeRelative,
106873
106963
  isAbsolute as nodeIsAbsolute
@@ -106902,7 +106992,7 @@ function formatExportFrameName(index, ext) {
106902
106992
  function resolveRenderPaths(projectDir, outputPath, rendersDir = DEFAULT_RENDERS_DIR) {
106903
106993
  const absoluteProjectDir = nodeResolve(projectDir);
106904
106994
  const projectName = basename5(absoluteProjectDir);
106905
- const resolvedOutputPath = outputPath ?? join33(rendersDir, `${projectName}.mp4`);
106995
+ const resolvedOutputPath = outputPath ?? join34(rendersDir, `${projectName}.mp4`);
106906
106996
  const absoluteOutputPath = nodeResolve(resolvedOutputPath);
106907
106997
  return { absoluteProjectDir, absoluteOutputPath };
106908
106998
  }
@@ -106926,7 +107016,7 @@ import {
106926
107016
  symlinkSync as symlinkSync2,
106927
107017
  writeFileSync as writeFileSync14
106928
107018
  } from "fs";
106929
- import { basename as basename6, dirname as dirname16, isAbsolute as isAbsolute10, join as join34, relative as relative11, resolve as resolve26 } from "path";
107019
+ import { basename as basename6, dirname as dirname16, isAbsolute as isAbsolute10, join as join35, relative as relative11, resolve as resolve26 } from "path";
106930
107020
  function resolveBrowserMediaEnd(start, end, duration) {
106931
107021
  return Number.isFinite(duration) && duration > 0 ? start + duration : end;
106932
107022
  }
@@ -106957,16 +107047,16 @@ function resolveDeviceScaleFactor(input2) {
106957
107047
  return target.width / input2.compositionWidth;
106958
107048
  }
106959
107049
  function writeCompiledArtifacts(compiled, workDir, includeSummary) {
106960
- const compileDir = join34(workDir, "compiled");
107050
+ const compileDir = join35(workDir, "compiled");
106961
107051
  mkdirSync17(compileDir, { recursive: true });
106962
- writeFileSync14(join34(compileDir, "index.html"), compiled.html, "utf-8");
107052
+ writeFileSync14(join35(compileDir, "index.html"), compiled.html, "utf-8");
106963
107053
  for (const [srcPath, html] of compiled.subCompositions) {
106964
- const outPath = join34(compileDir, srcPath);
107054
+ const outPath = join35(compileDir, srcPath);
106965
107055
  mkdirSync17(dirname16(outPath), { recursive: true });
106966
107056
  writeFileSync14(outPath, html, "utf-8");
106967
107057
  }
106968
107058
  for (const [relativePath, absolutePath] of compiled.externalAssets) {
106969
- const outPath = resolve26(join34(compileDir, relativePath));
107059
+ const outPath = resolve26(join35(compileDir, relativePath));
106970
107060
  if (!isPathInside3(outPath, compileDir)) {
106971
107061
  console.warn(`[Render] Skipping external asset with unsafe path: ${relativePath}`);
106972
107062
  continue;
@@ -106997,7 +107087,7 @@ function writeCompiledArtifacts(compiled, workDir, includeSummary) {
106997
107087
  renderModeHints: compiled.renderModeHints,
106998
107088
  hasShaderTransitions: compiled.hasShaderTransitions
106999
107089
  };
107000
- writeFileSync14(join34(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
107090
+ writeFileSync14(join35(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
107001
107091
  }
107002
107092
  }
107003
107093
  function applyRenderModeHints(alreadyForced, compiled, log2 = defaultLogger) {
@@ -107125,7 +107215,7 @@ var init_shared = __esm({
107125
107215
  BROWSER_MEDIA_EPSILON = 1e-4;
107126
107216
  materializePathModule = {
107127
107217
  resolve: resolve26,
107128
- join: join34,
107218
+ join: join35,
107129
107219
  dirname: dirname16,
107130
107220
  basename: basename6,
107131
107221
  relative: relative11,
@@ -107330,12 +107420,12 @@ import {
107330
107420
  renameSync as renameSync8,
107331
107421
  rmSync as rmSync9
107332
107422
  } from "fs";
107333
- import { basename as basename7, dirname as dirname17, extname as extname12, join as join35, resolve as resolve27 } from "path";
107423
+ import { basename as basename7, dirname as dirname17, extname as extname12, join as join36, resolve as resolve27 } from "path";
107334
107424
  function createSiblingTransactionDirectory(destination) {
107335
107425
  const parent = dirname17(destination);
107336
107426
  const extension2 = extname12(destination);
107337
107427
  const stem = extension2 ? basename7(destination, extension2) : basename7(destination);
107338
- return mkdtempSync3(join35(parent, `.${stem}.hf-transaction-`));
107428
+ return mkdtempSync3(join36(parent, `.${stem}.hf-transaction-`));
107339
107429
  }
107340
107430
  function assertReadableNonEmptyFile(path2) {
107341
107431
  const fd = openSync4(path2, "r");
@@ -107353,7 +107443,7 @@ function collectDirectoryFiles(root) {
107353
107443
  const files = [];
107354
107444
  const visit = (directory) => {
107355
107445
  for (const entry of readdirSync14(directory, { withFileTypes: true })) {
107356
- const path2 = join35(directory, entry.name);
107446
+ const path2 = join36(directory, entry.name);
107357
107447
  if (entry.isDirectory()) visit(path2);
107358
107448
  else if (entry.isFile()) files.push(path2);
107359
107449
  }
@@ -107376,8 +107466,8 @@ var init_artifactTransaction = __esm({
107376
107466
  this.fileSystem = fileSystem;
107377
107467
  this.destinationPath = resolve27(destinationPath);
107378
107468
  this.transactionDirectory = createSiblingTransactionDirectory(this.destinationPath);
107379
- this.stagingPath = join35(this.transactionDirectory, basename7(this.destinationPath));
107380
- this.backupPath = join35(this.transactionDirectory, "backup");
107469
+ this.stagingPath = join36(this.transactionDirectory, basename7(this.destinationPath));
107470
+ this.backupPath = join36(this.transactionDirectory, "backup");
107381
107471
  }
107382
107472
  kind;
107383
107473
  fileSystem;
@@ -107507,6 +107597,15 @@ function revertedRouting(routing) {
107507
107597
  return freezeRouting({ ...routing, state: "reverted" });
107508
107598
  }
107509
107599
  function replanAfterFailure(plan2, failure) {
107600
+ if (plan2.kind === "sdr_disk" && failure.kind === "draw_element_verification") {
107601
+ return createCapturePlan({
107602
+ ...plan2,
107603
+ forceScreenshot: true,
107604
+ useStreamingEncode: false,
107605
+ useLayeredComposite: false,
107606
+ forceParallelStream: false
107607
+ });
107608
+ }
107510
107609
  if (plan2.kind !== "sdr_streaming") {
107511
107610
  throw new Error(`Cannot apply ${failure.kind} to ${plan2.kind} capture plan`);
107512
107611
  }
@@ -107882,7 +107981,7 @@ var init_captureBeyondViewport = __esm({
107882
107981
  });
107883
107982
 
107884
107983
  // ../producer/src/services/render/captureCost.ts
107885
- import { join as join36 } from "path";
107984
+ import { join as join37 } from "path";
107886
107985
  function estimateCaptureCostMultiplier(compiled) {
107887
107986
  let multiplier = 1;
107888
107987
  const reasons = [];
@@ -108115,7 +108214,7 @@ async function runCaptureCalibration(input2) {
108115
108214
  });
108116
108215
  let calibration;
108117
108216
  try {
108118
- calibration = await runOneCalibration(join36(workDir, "capture-calibration"), calibrationCfg);
108217
+ calibration = await runOneCalibration(join37(workDir, "capture-calibration"), calibrationCfg);
108119
108218
  } catch (error) {
108120
108219
  const shouldFallback = !forceScreenshot && shouldFallbackToScreenshotAfterCalibrationError(error);
108121
108220
  if (!shouldFallback) {
@@ -108148,7 +108247,7 @@ async function runCaptureCalibration(input2) {
108148
108247
  const screenshotCfg = createCaptureCalibrationConfig({ ...cfg, forceScreenshot: true });
108149
108248
  try {
108150
108249
  calibration = await runOneCalibration(
108151
- join36(workDir, "capture-calibration-screenshot"),
108250
+ join37(workDir, "capture-calibration-screenshot"),
108152
108251
  screenshotCfg
108153
108252
  );
108154
108253
  } catch (fallbackError) {
@@ -111779,8 +111878,8 @@ __export(fontCompression_exports, {
111779
111878
  });
111780
111879
  import { createHash as createHash10 } from "crypto";
111781
111880
  import { existsSync as existsSync41, mkdirSync as mkdirSync18, readFileSync as readFileSync24, renameSync as renameSync9, rmSync as rmSync10, writeFileSync as writeFileSync15 } from "fs";
111782
- import { homedir as homedir11, tmpdir as tmpdir4 } from "os";
111783
- import { dirname as dirname18, join as join37 } from "path";
111881
+ import { homedir as homedir11, tmpdir as tmpdir5 } from "os";
111882
+ import { dirname as dirname18, join as join38 } from "path";
111784
111883
  async function compressToWoff2(input2) {
111785
111884
  return Buffer.from(await compress(input2));
111786
111885
  }
@@ -111788,12 +111887,12 @@ function rawMimeType(format) {
111788
111887
  return RAW_MIME_TYPES[format] ?? "font/ttf";
111789
111888
  }
111790
111889
  function defaultCacheDir() {
111791
- const root = process.env.HYPERFRAMES_FONT_CACHE_DIR ?? (process.env.AWS_LAMBDA_FUNCTION_NAME ? join37(tmpdir4(), "hyperframes", "fonts") : join37(homedir11(), ".cache", "hyperframes", "fonts"));
111792
- return join37(root, "local-compression-v1");
111890
+ const root = process.env.HYPERFRAMES_FONT_CACHE_DIR ?? (process.env.AWS_LAMBDA_FUNCTION_NAME ? join38(tmpdir5(), "hyperframes", "fonts") : join38(homedir11(), ".cache", "hyperframes", "fonts"));
111891
+ return join38(root, "local-compression-v1");
111793
111892
  }
111794
111893
  function cachedCompressionPath(input2, originalFormat, cacheDir) {
111795
111894
  const digest = createHash10("sha256").update("hyperframes-local-font-compression-v1\0").update(originalFormat).update("\0").update(input2).digest("hex");
111796
- return join37(cacheDir, `${digest}.woff2`);
111895
+ return join38(cacheDir, `${digest}.woff2`);
111797
111896
  }
111798
111897
  function readCachedCompression(path2) {
111799
111898
  try {
@@ -111874,8 +111973,8 @@ __export(deterministicFonts_exports, {
111874
111973
  });
111875
111974
  import { createHash as createHash11 } from "crypto";
111876
111975
  import { existsSync as existsSync43, mkdirSync as mkdirSync19, readFileSync as readFileSync25, writeFileSync as writeFileSync16 } from "fs";
111877
- import { homedir as homedir12, tmpdir as tmpdir5 } from "os";
111878
- import { join as join38 } from "path";
111976
+ import { homedir as homedir12, tmpdir as tmpdir6 } from "os";
111977
+ import { join as join39 } from "path";
111879
111978
  import postcss4 from "postcss";
111880
111979
  function parseFontFamilyValue(value) {
111881
111980
  return value.split(",").map((piece) => piece.trim().replace(/^['"]/, "").replace(/['"]$/, "").trim()).filter((piece) => piece.length > 0);
@@ -112195,13 +112294,13 @@ function warnUnresolvedFonts(unresolved) {
112195
112294
  );
112196
112295
  }
112197
112296
  function resolveFontCacheRoot() {
112198
- return process.env.HYPERFRAMES_FONT_CACHE_DIR ?? (process.env.AWS_LAMBDA_FUNCTION_NAME ? join38(tmpdir5(), "hyperframes", "fonts") : join38(homedir12(), ".cache", "hyperframes", "fonts"));
112297
+ return process.env.HYPERFRAMES_FONT_CACHE_DIR ?? (process.env.AWS_LAMBDA_FUNCTION_NAME ? join39(tmpdir6(), "hyperframes", "fonts") : join39(homedir12(), ".cache", "hyperframes", "fonts"));
112199
112298
  }
112200
112299
  function fontSlug(familyName) {
112201
112300
  return familyName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
112202
112301
  }
112203
112302
  function fontCacheDir(slug) {
112204
- const dir = join38(GOOGLE_FONTS_CACHE_DIR, slug);
112303
+ const dir = join39(GOOGLE_FONTS_CACHE_DIR, slug);
112205
112304
  if (!existsSync43(dir)) {
112206
112305
  mkdirSync19(dir, { recursive: true });
112207
112306
  }
@@ -112211,7 +112310,7 @@ function subsetToken(woff2Url) {
112211
112310
  return createHash11("sha1").update(woff2Url).digest("hex").slice(0, 12);
112212
112311
  }
112213
112312
  function cachedWoff2Path(slug, weight, style, subset) {
112214
- return join38(fontCacheDir(slug), `${weight}-${style}-${subset}.woff2`);
112313
+ return join39(fontCacheDir(slug), `${weight}-${style}-${subset}.woff2`);
112215
112314
  }
112216
112315
  function fontFetchError(familyName, url, what, cause) {
112217
112316
  const reason = "status" in cause ? `returned HTTP ${cause.status}` : `failed: ${cause.error.message}`;
@@ -112496,7 +112595,7 @@ import {
112496
112595
  rmSync as rmSync11,
112497
112596
  statSync as statSync12
112498
112597
  } from "fs";
112499
- import { dirname as dirname19, isAbsolute as isAbsolute11, join as join39, resolve as resolve28 } from "path";
112598
+ import { dirname as dirname19, isAbsolute as isAbsolute11, join as join40, resolve as resolve28 } from "path";
112500
112599
  function splitUrlSuffix2(src) {
112501
112600
  const queryIdx = src.indexOf("?");
112502
112601
  const hashIdx = src.indexOf("#");
@@ -112726,7 +112825,7 @@ function replaceImageWithVideo(input2) {
112726
112825
  return video;
112727
112826
  }
112728
112827
  async function prepareAnimatedGifInputs(html, options) {
112729
- const outputDir = options.outputDir ?? join39(options.downloadDir, PREPARED_GIF_SUBDIR);
112828
+ const outputDir = options.outputDir ?? join40(options.downloadDir, PREPARED_GIF_SUBDIR);
112730
112829
  const outputSrcPrefix = normalizeRelPath(options.outputSrcPrefix ?? PREPARED_GIF_SUBDIR);
112731
112830
  const cacheDir = options.cacheDir ?? outputDir;
112732
112831
  const { document: document2 } = parseHTML(html);
@@ -112748,8 +112847,8 @@ async function prepareAnimatedGifInputs(html, options) {
112748
112847
  const { loopIterations, padSeconds } = resolvePreparedPlayback(metadata, loop, windowSeconds);
112749
112848
  const hash2 = computePreparedGifHash(bytes, loopIterations, padSeconds);
112750
112849
  const filename = `${CACHE_SCHEMA}-${hash2.slice(0, 24)}.webm`;
112751
- const cachePath2 = join39(cacheDir, filename);
112752
- const outputPath = join39(outputDir, filename);
112850
+ const cachePath2 = join40(cacheDir, filename);
112851
+ const outputPath = join40(outputDir, filename);
112753
112852
  const outputSrc = `${outputSrcPrefix}/${filename}`;
112754
112853
  await ensurePreparedWebm({
112755
112854
  sourcePath,
@@ -112817,7 +112916,7 @@ var init_position_edits_render_inline = __esm({
112817
112916
 
112818
112917
  // ../producer/src/services/htmlCompiler.ts
112819
112918
  import { readFileSync as readFileSync27, existsSync as existsSync45, mkdirSync as mkdirSync21 } from "fs";
112820
- import { join as join40, dirname as dirname20, resolve as resolve29, basename as basename8 } from "path";
112919
+ import { join as join41, dirname as dirname20, resolve as resolve29, basename as basename8 } from "path";
112821
112920
  function parseSubCompHtmlForValidity(html) {
112822
112921
  return parseHTML(html).document;
112823
112922
  }
@@ -112982,7 +113081,7 @@ async function resolveMediaDuration(src, mediaStart, baseDir, downloadDir, tagNa
112982
113081
  return { duration: 0, resolvedPath: src };
112983
113082
  }
112984
113083
  } else if (!filePath.startsWith("/")) {
112985
- filePath = join40(baseDir, filePath);
113084
+ filePath = join41(baseDir, filePath);
112986
113085
  }
112987
113086
  if (!existsSync45(filePath)) {
112988
113087
  return { duration: 0, resolvedPath: filePath };
@@ -113526,7 +113625,7 @@ async function localizeRemoteMediaSources(html, downloadDir) {
113526
113625
  return downloadAndRewriteUrls(
113527
113626
  urlSet,
113528
113627
  html,
113529
- join40(downloadDir, REMOTE_MEDIA_SUBDIR),
113628
+ join41(downloadDir, REMOTE_MEDIA_SUBDIR),
113530
113629
  "Remote media download failed for",
113531
113630
  "Localized remote media source(s)"
113532
113631
  );
@@ -113541,7 +113640,7 @@ async function localizeRemoteImageSources(html, downloadDir) {
113541
113640
  return downloadAndRewriteUrls(
113542
113641
  urlSet,
113543
113642
  html,
113544
- join40(downloadDir, REMOTE_MEDIA_SUBDIR),
113643
+ join41(downloadDir, REMOTE_MEDIA_SUBDIR),
113545
113644
  "Remote image download failed for",
113546
113645
  "Localized remote image source(s)"
113547
113646
  );
@@ -113556,7 +113655,7 @@ async function localizeRemoteBackgroundImages(html, downloadDir) {
113556
113655
  return downloadAndRewriteUrls(
113557
113656
  urlSet,
113558
113657
  html,
113559
- join40(downloadDir, REMOTE_MEDIA_SUBDIR),
113658
+ join41(downloadDir, REMOTE_MEDIA_SUBDIR),
113560
113659
  "Remote background-image download failed for",
113561
113660
  "Localized remote background-image(s)",
113562
113661
  // Quoted url('..')/url("..") are rewritten by downloadAndRewriteUrls' default
@@ -113708,7 +113807,7 @@ async function localizeRemoteFontFaces(html, downloadDir) {
113708
113807
  return downloadAndRewriteUrls(
113709
113808
  urlSet,
113710
113809
  processed,
113711
- join40(downloadDir, REMOTE_MEDIA_SUBDIR),
113810
+ join41(downloadDir, REMOTE_MEDIA_SUBDIR),
113712
113811
  "Remote font download failed for",
113713
113812
  "Localized remote font face(s)",
113714
113813
  (h3, url, relPath) => h3.replaceAll(`url(${url})`, `url("${relPath}")`)
@@ -114230,7 +114329,7 @@ Check that each file referenced by data-composition-src contains valid HTML with
114230
114329
  });
114231
114330
 
114232
114331
  // ../producer/src/services/render/stages/compileStage.ts
114233
- import { join as join41 } from "path";
114332
+ import { join as join43 } from "path";
114234
114333
  function adaptAspectAgnosticResolution(requested, aspectAgnostic, width, height, log2) {
114235
114334
  if (!requested || !aspectAgnostic) return requested;
114236
114335
  const flipped = suggestMatchingPreset(width, height, requested);
@@ -114258,12 +114357,12 @@ async function runCompileStage(input2) {
114258
114357
  allowSystemFontCapture
114259
114358
  } = input2;
114260
114359
  const compileStart = Date.now();
114261
- const compiled = await compileForRender(projectDir, htmlPath, join41(workDir, "downloads"), {
114360
+ const compiled = await compileForRender(projectDir, htmlPath, join43(workDir, "downloads"), {
114262
114361
  log: log2,
114263
114362
  failClosedFontFetch: failClosedFontFetch === true,
114264
114363
  allowSystemFontCapture,
114265
114364
  variables: input2.variables,
114266
- animatedGifCacheDir: cfg.extractCacheDir ? join41(cfg.extractCacheDir, "animated-gif") : void 0,
114365
+ animatedGifCacheDir: cfg.extractCacheDir ? join43(cfg.extractCacheDir, "animated-gif") : void 0,
114267
114366
  ffmpegProcessTimeout: cfg.ffmpegProcessTimeout
114268
114367
  });
114269
114368
  assertNotAborted();
@@ -114384,7 +114483,7 @@ var init_probeFailures = __esm({
114384
114483
  });
114385
114484
 
114386
114485
  // ../producer/src/services/render/stages/probeStage.ts
114387
- import { join as join43 } from "path";
114486
+ import { join as join44 } from "path";
114388
114487
  function durationToFrameCount(duration, fps) {
114389
114488
  const rawFrameCount = duration * fps;
114390
114489
  const nearestFrame = Math.round(rawFrameCount);
@@ -114462,7 +114561,7 @@ async function runProbeStage(input2) {
114462
114561
  });
114463
114562
  fileServer = await createFileServer2({
114464
114563
  projectDir,
114465
- compiledDir: join43(workDir, "compiled"),
114564
+ compiledDir: join44(workDir, "compiled"),
114466
114565
  port: 0,
114467
114566
  preHeadScripts: [VIRTUAL_TIME_SHIM],
114468
114567
  fps: job.config.fps
@@ -114484,7 +114583,7 @@ async function runProbeStage(input2) {
114484
114583
  log2.info("Creating capture session...", { attempt, maxAttempts: PROBE_MAX_ATTEMPTS });
114485
114584
  probeSession = await createCaptureSession(
114486
114585
  fileServer.url,
114487
- join43(workDir, "probe"),
114586
+ join44(workDir, "probe"),
114488
114587
  captureOpts,
114489
114588
  null,
114490
114589
  probeCfg
@@ -114569,7 +114668,7 @@ async function runProbeStage(input2) {
114569
114668
  });
114570
114669
  probeSession = await createCaptureSession(
114571
114670
  fileServer.url,
114572
- join43(workDir, "probe-screenshot"),
114671
+ join44(workDir, "probe-screenshot"),
114573
114672
  captureOpts,
114574
114673
  null,
114575
114674
  { ...probeCfg, forceScreenshot: true }
@@ -114605,7 +114704,7 @@ async function runProbeStage(input2) {
114605
114704
  compiled,
114606
114705
  resolutions,
114607
114706
  projectDir,
114608
- join43(workDir, "downloads")
114707
+ join44(workDir, "downloads")
114609
114708
  );
114610
114709
  assertNotAborted();
114611
114710
  composition.videos = compiled.videos;
@@ -114906,7 +115005,7 @@ var init_planValidation = __esm({
114906
115005
 
114907
115006
  // ../producer/src/services/render/stages/extractVideosStage.ts
114908
115007
  import { existsSync as existsSync46 } from "fs";
114909
- import { isAbsolute as isAbsolute12, join as join44 } from "path";
115008
+ import { isAbsolute as isAbsolute12, join as join45 } from "path";
114910
115009
  function shouldCopyExtractedFrames(platform10) {
114911
115010
  return platform10 === "win32";
114912
115011
  }
@@ -114952,7 +115051,7 @@ async function runExtractVideosStage(input2) {
114952
115051
  composition.images.map(async (img) => {
114953
115052
  let imgPath = img.src;
114954
115053
  if (!imgPath.startsWith("/")) {
114955
- const fromCompiled = existsSync46(join44(compiledDir, imgPath)) ? join44(compiledDir, imgPath) : join44(projectDir, imgPath);
115054
+ const fromCompiled = existsSync46(join45(compiledDir, imgPath)) ? join45(compiledDir, imgPath) : join45(projectDir, imgPath);
114956
115055
  imgPath = fromCompiled;
114957
115056
  }
114958
115057
  if (!existsSync46(imgPath)) return null;
@@ -114982,7 +115081,7 @@ async function runExtractVideosStage(input2) {
114982
115081
  // output framerate exact.
114983
115082
  {
114984
115083
  fps: fpsToNumber(job.config.fps),
114985
- outputDir: join44(compiledDir, "__hyperframes_video_frames"),
115084
+ outputDir: join45(compiledDir, "__hyperframes_video_frames"),
114986
115085
  format: job.config.videoFrameFormat ?? "auto"
114987
115086
  },
114988
115087
  abortSignal,
@@ -115048,18 +115147,18 @@ var init_extractVideosStage = __esm({
115048
115147
  });
115049
115148
 
115050
115149
  // ../producer/src/services/render/stages/audioStage.ts
115051
- import { join as join45 } from "path";
115150
+ import { join as join46 } from "path";
115052
115151
  async function runAudioStage(input2) {
115053
115152
  const { projectDir, workDir, compiledDir, duration, audios, abortSignal, assertNotAborted } = input2;
115054
115153
  const stage3Start = Date.now();
115055
- const audioOutputPath = join45(workDir, "audio.aac");
115154
+ const audioOutputPath = join46(workDir, "audio.aac");
115056
115155
  let hasAudio = false;
115057
115156
  let audioError;
115058
115157
  if (audios.length > 0) {
115059
115158
  const audioResult = await processCompositionAudio(
115060
115159
  audios,
115061
115160
  projectDir,
115062
- join45(workDir, "audio-work"),
115161
+ join46(workDir, "audio-work"),
115063
115162
  audioOutputPath,
115064
115163
  duration,
115065
115164
  abortSignal,
@@ -115226,6 +115325,17 @@ async function runCaptureStage(input2) {
115226
115325
  reportFrame(i2);
115227
115326
  }
115228
115327
  }
115328
+ await verifyDiskDrawElementSamples(
115329
+ session,
115330
+ {
115331
+ workerId: 0,
115332
+ startFrame: rangeStart,
115333
+ endFrame: rangeEnd,
115334
+ outputDir: framesDir,
115335
+ outputFrameOffset: rangeStart
115336
+ },
115337
+ false
115338
+ );
115229
115339
  dedupPerfs.push(getCapturePerfSummary(session));
115230
115340
  } catch (error) {
115231
115341
  lastBrowserConsole = session.browserConsoleBuffer;
@@ -115249,7 +115359,7 @@ var init_captureStage = __esm({
115249
115359
 
115250
115360
  // ../producer/src/services/hdrCompositor.ts
115251
115361
  import { readSync as readSync3, closeSync as closeSync5 } from "fs";
115252
- import { join as join46 } from "path";
115362
+ import { join as join47 } from "path";
115253
115363
  function countNonZeroAlpha(rgba) {
115254
115364
  let n2 = 0;
115255
115365
  for (let p2 = 3; p2 < rgba.length; p2 += 4) {
@@ -115643,7 +115753,7 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
115643
115753
  if (shouldLog && debugDumpDir) {
115644
115754
  const after2 = countNonZeroRgb48(canvas);
115645
115755
  const dumpName = `frame_${String(debugFrameIndex).padStart(4, "0")}_layer_${String(layerIdx).padStart(2, "0")}_dom.png`;
115646
- const dumpPath = join46(debugDumpDir, dumpName);
115756
+ const dumpPath = join47(debugDumpDir, dumpName);
115647
115757
  writeFileExclusiveSync(dumpPath, domPng);
115648
115758
  log2.info("[diag] dom layer blit", {
115649
115759
  frame: debugFrameIndex,
@@ -115942,11 +116052,9 @@ var init_captureHdrFrameShared = __esm({
115942
116052
  });
115943
116053
 
115944
116054
  // ../producer/src/services/render/stages/captureStreamingStage.ts
115945
- import { execFile as execFile5 } from "child_process";
115946
- import { mkdtemp, rm, writeFile } from "fs/promises";
115947
- import { tmpdir as tmpdir6 } from "os";
115948
- import { join as join47 } from "path";
115949
- import { promisify as promisify3 } from "util";
116055
+ import { mkdtemp as mkdtemp2, writeFile as writeFile2 } from "fs/promises";
116056
+ import { tmpdir as tmpdir7 } from "os";
116057
+ import { join as join48 } from "path";
115950
116058
  function resolveDeStallTimeoutMs() {
115951
116059
  const raw = process.env.HF_DE_STALL_MS ?? process.env.HF_DE_PARALLEL_STALL_MS;
115952
116060
  const parsed = raw ? Number(raw) : Number.NaN;
@@ -115976,32 +116084,13 @@ function raceAgainstStall(promise, deadlineMs, message, signal) {
115976
116084
  );
115977
116085
  });
115978
116086
  }
115979
- async function psnrDb(a, b2) {
115980
- const dir = await mkdtemp(join47(tmpdir6(), "hf-de-verify-"));
115981
- try {
115982
- const pa = join47(dir, "a.jpg");
115983
- const pb = join47(dir, "b.jpg");
115984
- await Promise.all([writeFile(pa, a), writeFile(pb, b2)]);
115985
- const { stderr } = await execFileP(
115986
- getFfmpegBinary(),
115987
- ["-hide_banner", "-i", pa, "-i", pb, "-lavfi", "psnr", "-f", "null", "-"],
115988
- { maxBuffer: 4 * 1024 * 1024 }
115989
- );
115990
- const m2 = /average:(inf|[\d.]+)/.exec(stderr);
115991
- if (!m2) throw new Error(`psnr parse failed: ${stderr.slice(-300)}`);
115992
- return m2[1] === "inf" ? Infinity : Number(m2[1]);
115993
- } finally {
115994
- await rm(dir, { recursive: true, force: true }).catch(() => {
115995
- });
115996
- }
115997
- }
115998
116087
  function createDrainFrameGuard(args) {
115999
116088
  const { log: log2, stats, frameTime } = args;
116000
- const verifyMinDbRaw = Number(process.env.HF_DE_VERIFY_MIN_DB ?? "32");
116001
- const verifyMinDb = Number.isFinite(verifyMinDbRaw) && verifyMinDbRaw >= 10 && verifyMinDbRaw <= 60 ? verifyMinDbRaw : 32;
116002
- if (process.env.HF_DE_VERIFY_MIN_DB !== void 0 && verifyMinDb !== verifyMinDbRaw) {
116003
- log2.warn("[Render] HF_DE_VERIFY_MIN_DB out of range [10,60]; using 32", {
116004
- raw: process.env.HF_DE_VERIFY_MIN_DB
116089
+ const verifyMinDb = resolveDeVerifyMinDb();
116090
+ const rawEnv = process.env.HF_DE_VERIFY_MIN_DB;
116091
+ if (rawEnv !== void 0 && Number(rawEnv) !== verifyMinDb) {
116092
+ log2.warn(`[Render] HF_DE_VERIFY_MIN_DB out of range [10,60]; using ${verifyMinDb}`, {
116093
+ raw: rawEnv
116005
116094
  });
116006
116095
  }
116007
116096
  const sizes = [];
@@ -116069,11 +116158,11 @@ function createDrainFrameGuard(args) {
116069
116158
  return buf;
116070
116159
  }
116071
116160
  if (db < verifyMinDb) {
116072
- const dumpDir = await mkdtemp(join47(tmpdir6(), "hf-de-verify-fail-")).catch(() => null);
116161
+ const dumpDir = await mkdtemp2(join48(tmpdir7(), "hf-de-verify-fail-")).catch(() => null);
116073
116162
  if (dumpDir) {
116074
116163
  await Promise.all([
116075
- writeFile(join47(dumpDir, `frame-${idx}-de.jpg`), buf),
116076
- writeFile(join47(dumpDir, `frame-${idx}-truth.jpg`), truth)
116164
+ writeFile2(join48(dumpDir, `frame-${idx}-de.jpg`), buf),
116165
+ writeFile2(join48(dumpDir, `frame-${idx}-truth.jpg`), truth)
116077
116166
  ]).catch(() => {
116078
116167
  });
116079
116168
  }
@@ -116463,7 +116552,7 @@ async function runCaptureStreamingStage(input2) {
116463
116552
  }
116464
116553
  }
116465
116554
  }
116466
- var DEFAULT_DE_STALL_MS, DE_STALL_POLL_MS, execFileP;
116555
+ var DEFAULT_DE_STALL_MS, DE_STALL_POLL_MS;
116467
116556
  var init_captureStreamingStage = __esm({
116468
116557
  "../producer/src/services/render/stages/captureStreamingStage.ts"() {
116469
116558
  "use strict";
@@ -116474,7 +116563,6 @@ var init_captureStreamingStage = __esm({
116474
116563
  init_shared();
116475
116564
  DEFAULT_DE_STALL_MS = 6e4;
116476
116565
  DE_STALL_POLL_MS = 5e3;
116477
- execFileP = promisify3(execFile5);
116478
116566
  }
116479
116567
  });
116480
116568
 
@@ -116555,7 +116643,7 @@ import {
116555
116643
  readFileSync as readFileSync28,
116556
116644
  statfsSync as statfsSync2
116557
116645
  } from "fs";
116558
- import { join as join48 } from "path";
116646
+ import { join as join49 } from "path";
116559
116647
  function tempDirSafePrefix(id) {
116560
116648
  const safe = id.replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 80);
116561
116649
  return safe || "video";
@@ -116568,8 +116656,8 @@ function planHdrResources(args) {
116568
116656
  if (!hdrVideoIds.includes(v2.id)) continue;
116569
116657
  let srcPath = v2.src;
116570
116658
  if (!srcPath.startsWith("/")) {
116571
- const fromCompiled = join48(compiledDir, srcPath);
116572
- srcPath = args.existsSync(fromCompiled) ? fromCompiled : join48(projectDir, srcPath);
116659
+ const fromCompiled = join49(compiledDir, srcPath);
116660
+ srcPath = args.existsSync(fromCompiled) ? fromCompiled : join49(projectDir, srcPath);
116573
116661
  }
116574
116662
  hdrVideoSrcPaths.set(v2.id, srcPath);
116575
116663
  }
@@ -116686,10 +116774,10 @@ async function extractHdrVideoFrames(args) {
116686
116774
  const video = composition.videos.find((v2) => v2.id === videoId);
116687
116775
  if (!video) continue;
116688
116776
  mkdirSync23(framesDir, { recursive: true });
116689
- const frameDir = mkdtempSync4(join48(framesDir, `hdr_${tempDirSafePrefix(videoId)}-`));
116777
+ const frameDir = mkdtempSync4(join49(framesDir, `hdr_${tempDirSafePrefix(videoId)}-`));
116690
116778
  const duration = video.end - video.start;
116691
116779
  const dims = prep.hdrExtractionDims.get(videoId) ?? { width, height };
116692
- const rawPath = join48(frameDir, "frames.rgb48le");
116780
+ const rawPath = join49(frameDir, "frames.rgb48le");
116693
116781
  const ffmpegArgs = [
116694
116782
  "-ss",
116695
116783
  String(video.mediaStart),
@@ -116802,7 +116890,7 @@ var init_captureHdrResources = __esm({
116802
116890
  });
116803
116891
 
116804
116892
  // ../producer/src/services/render/stages/captureHdrSequentialLoop.ts
116805
- import { join as join49 } from "path";
116893
+ import { join as join50 } from "path";
116806
116894
  async function runSequentialLayeredFrameLoop(input2) {
116807
116895
  const {
116808
116896
  job,
@@ -116923,7 +117011,7 @@ async function runSequentialLayeredFrameLoop(input2) {
116923
117011
  );
116924
117012
  if (debugDumpEnabled && debugDumpDir && i2 % 30 === 0) {
116925
117013
  writeFileExclusiveSync(
116926
- join49(debugDumpDir, `frame_${String(i2).padStart(4, "0")}_final_rgb48le.bin`),
117014
+ join50(debugDumpDir, `frame_${String(i2).padStart(4, "0")}_final_rgb48le.bin`),
116927
117015
  normalCanvas
116928
117016
  );
116929
117017
  }
@@ -116970,7 +117058,7 @@ var init_captureHdrSequentialLoop = __esm({
116970
117058
  // ../producer/src/services/shaderTransitionWorkerPool.ts
116971
117059
  import { Worker as Worker2 } from "worker_threads";
116972
117060
  import { fileURLToPath as fileURLToPath4, pathToFileURL } from "url";
116973
- import { dirname as dirname21, join as join50 } from "path";
117061
+ import { dirname as dirname21, join as join51 } from "path";
116974
117062
  import { createRequire } from "module";
116975
117063
  import { existsSync as existsSync47 } from "fs";
116976
117064
  import { cpus as cpus3 } from "os";
@@ -116984,9 +117072,9 @@ function resolveWorkerEntry(explicit) {
116984
117072
  return { path: override, isTs };
116985
117073
  }
116986
117074
  const moduleDir = dirname21(fileURLToPath4(import.meta.url));
116987
- const jsPath = join50(moduleDir, "shaderTransitionWorker.js");
117075
+ const jsPath = join51(moduleDir, "shaderTransitionWorker.js");
116988
117076
  if (existsSync47(jsPath)) return { path: jsPath, isTs: false };
116989
- const tsPath = join50(moduleDir, "shaderTransitionWorker.ts");
117077
+ const tsPath = join51(moduleDir, "shaderTransitionWorker.ts");
116990
117078
  return { path: tsPath, isTs: true };
116991
117079
  }
116992
117080
  function buildExecArgv(entryIsTs) {
@@ -117169,7 +117257,7 @@ var init_shaderTransitionWorkerPool = __esm({
117169
117257
  });
117170
117258
 
117171
117259
  // ../producer/src/services/render/stages/captureHdrHybridLoop.ts
117172
- import { join as join51 } from "path";
117260
+ import { join as join53 } from "path";
117173
117261
  async function runHybridLayeredFrameLoop(input2) {
117174
117262
  const {
117175
117263
  job,
@@ -117362,7 +117450,7 @@ async function runHybridLayeredFrameLoop(input2) {
117362
117450
  );
117363
117451
  if (debugDumpEnabled && debugDumpDir && i2 % 30 === 0) {
117364
117452
  writeFileExclusiveSync(
117365
- join51(debugDumpDir, `frame_${String(i2).padStart(4, "0")}_final_rgb48le.bin`),
117453
+ join53(debugDumpDir, `frame_${String(i2).padStart(4, "0")}_final_rgb48le.bin`),
117366
117454
  canvas
117367
117455
  );
117368
117456
  }
@@ -117407,7 +117495,7 @@ var init_captureHdrHybridLoop = __esm({
117407
117495
 
117408
117496
  // ../producer/src/services/render/stages/captureHdrStage.ts
117409
117497
  import { existsSync as existsSync48, mkdirSync as mkdirSync24 } from "fs";
117410
- import { join as join53 } from "path";
117498
+ import { join as join54 } from "path";
117411
117499
  function cloneCaptureWarnings(warnings) {
117412
117500
  return warnings.map((warning) => ({
117413
117501
  ...warning,
@@ -117570,7 +117658,7 @@ async function runCaptureHdrStage(input2) {
117570
117658
  if (hdrVideoFrameSources.has(v2.id)) hdrVideoEndTimes.set(v2.id, v2.end);
117571
117659
  }
117572
117660
  const debugDumpEnabled = process.env.KEEP_TEMP === "1";
117573
- const debugDumpDir = debugDumpEnabled ? join53(framesDir, "debug-composite") : null;
117661
+ const debugDumpDir = debugDumpEnabled ? join54(framesDir, "debug-composite") : null;
117574
117662
  if (debugDumpDir && !existsSync48(debugDumpDir)) {
117575
117663
  mkdirSync24(debugDumpDir, { recursive: true });
117576
117664
  }
@@ -117733,7 +117821,7 @@ var init_captureHdrStage = __esm({
117733
117821
  });
117734
117822
 
117735
117823
  // ../producer/src/services/render/stages/gifEncodeArgs.ts
117736
- import { join as join54 } from "path";
117824
+ import { join as join55 } from "path";
117737
117825
  function fpsToFfmpegArg2(fps) {
117738
117826
  return fps.den === 1 ? String(fps.num) : `${fps.num}/${fps.den}`;
117739
117827
  }
@@ -117744,7 +117832,7 @@ function buildGifPalettegenArgs(input2) {
117744
117832
  "-framerate",
117745
117833
  fpsArg,
117746
117834
  "-i",
117747
- join54(input2.framesDir, input2.framePattern),
117835
+ join55(input2.framesDir, input2.framePattern),
117748
117836
  "-vf",
117749
117837
  `fps=${fpsArg},palettegen=stats_mode=diff`,
117750
117838
  input2.palettePath
@@ -117757,7 +117845,7 @@ function buildGifPaletteuseArgs(input2) {
117757
117845
  "-framerate",
117758
117846
  fpsArg,
117759
117847
  "-i",
117760
- join54(input2.framesDir, input2.framePattern),
117848
+ join55(input2.framesDir, input2.framePattern),
117761
117849
  "-i",
117762
117850
  input2.palettePath,
117763
117851
  "-lavfi",
@@ -117775,7 +117863,7 @@ var init_gifEncodeArgs = __esm({
117775
117863
 
117776
117864
  // ../producer/src/services/render/stages/encodeStage.ts
117777
117865
  import { copyFileSync as copyFileSync5, existsSync as existsSync49, mkdirSync as mkdirSync25, readdirSync as readdirSync15, rmSync as rmSync13, statSync as statSync13 } from "fs";
117778
- import { dirname as dirname23, join as join55 } from "path";
117866
+ import { dirname as dirname23, join as join56 } from "path";
117779
117867
  function resolveGifLoop(loop) {
117780
117868
  const resolved2 = loop ?? 0;
117781
117869
  if (!Number.isInteger(resolved2) || resolved2 < 0 || resolved2 > 65535) {
@@ -117880,11 +117968,11 @@ async function runEncodeStage(input2) {
117880
117968
  );
117881
117969
  }
117882
117970
  captured.forEach((name, i2) => {
117883
- const dst = join55(outputPath, formatExportFrameName(i2, "png"));
117884
- copyFileSync5(join55(framesDir, name), dst);
117971
+ const dst = join56(outputPath, formatExportFrameName(i2, "png"));
117972
+ copyFileSync5(join56(framesDir, name), dst);
117885
117973
  });
117886
117974
  if (hasAudio && audioOutputPath && existsSync49(audioOutputPath)) {
117887
- copyFileSync5(audioOutputPath, join55(outputPath, "audio.aac"));
117975
+ copyFileSync5(audioOutputPath, join56(outputPath, "audio.aac"));
117888
117976
  log2.info(`[Render] png-sequence: audio.aac sidecar written to ${outputPath}/audio.aac`);
117889
117977
  }
117890
117978
  return { encodeMs: Date.now() - stage5Start };
@@ -117900,7 +117988,7 @@ async function runEncodeStage(input2) {
117900
117988
  const encodeResult2 = await encodeGifFromDir(framesDir, framePattern2, outputPath, {
117901
117989
  fps: job.config.fps,
117902
117990
  loop,
117903
- palettePath: join55(dirname23(videoOnlyPath), "gif-palette.png"),
117991
+ palettePath: join56(dirname23(videoOnlyPath), "gif-palette.png"),
117904
117992
  signal: abortSignal,
117905
117993
  timeout: engineCfg.ffmpegEncodeTimeout
117906
117994
  });
@@ -118319,8 +118407,8 @@ import {
118319
118407
  copyFileSync as copyFileSync6,
118320
118408
  appendFileSync
118321
118409
  } from "fs";
118322
- import { tmpdir as tmpdir7 } from "os";
118323
- import { join as join56, dirname as dirname24, resolve as resolve30 } from "path";
118410
+ import { tmpdir as tmpdir8 } from "os";
118411
+ import { join as join57, dirname as dirname24, resolve as resolve30 } from "path";
118324
118412
  import { totalmem as totalmem2 } from "os";
118325
118413
  import { randomUUID as randomUUID7 } from "crypto";
118326
118414
  import { fileURLToPath as fileURLToPath5 } from "url";
@@ -118337,7 +118425,7 @@ function sampleDirectoryBytes(dir) {
118337
118425
  continue;
118338
118426
  }
118339
118427
  for (const name of entries2) {
118340
- const full2 = join56(current2, name);
118428
+ const full2 = join57(current2, name);
118341
118429
  try {
118342
118430
  const st3 = statSync14(full2);
118343
118431
  if (st3.isDirectory()) {
@@ -118458,7 +118546,7 @@ function findMissingFrameRanges(totalFrames, framesDir, frameExt) {
118458
118546
  const ranges = [];
118459
118547
  let rangeStart = null;
118460
118548
  for (let frameIndex = 0; frameIndex < totalFrames; frameIndex++) {
118461
- const framePath = join56(framesDir, formatCaptureFrameName(frameIndex, frameExt));
118549
+ const framePath = join57(framesDir, formatCaptureFrameName(frameIndex, frameExt));
118462
118550
  const missing = !existsSync50(framePath) || statSync14(framePath).size <= 8;
118463
118551
  if (missing && rangeStart === null) {
118464
118552
  rangeStart = frameIndex;
@@ -118481,7 +118569,7 @@ function buildMissingFrameRetryBatches(ranges, maxWorkers, workDir, attempt, ran
118481
118569
  workerId,
118482
118570
  startFrame: rangeStart + range.startFrame,
118483
118571
  endFrame: rangeStart + range.endFrame,
118484
- outputDir: join56(workDir, `retry-${attempt}-batch-${batchIndex}-worker-${workerId}`),
118572
+ outputDir: join57(workDir, `retry-${attempt}-batch-${batchIndex}-worker-${workerId}`),
118485
118573
  outputFrameOffset: rangeStart
118486
118574
  }));
118487
118575
  batches.push(batch);
@@ -118491,9 +118579,9 @@ function buildMissingFrameRetryBatches(ranges, maxWorkers, workDir, attempt, ran
118491
118579
  function getNextRetryWorkerCount(currentWorkers) {
118492
118580
  return Math.max(1, Math.floor(currentWorkers / 2));
118493
118581
  }
118494
- function resolveRenderWorkDirPrefix(outputPath, jobId, platform10 = process.platform, systemTempDir = tmpdir7()) {
118495
- if (platform10 === "win32") return join56(systemTempDir, "hf-render-");
118496
- return join56(dirname24(outputPath), `work-${jobId}-`);
118582
+ function resolveRenderWorkDirPrefix(outputPath, jobId, platform10 = process.platform, systemTempDir = tmpdir8()) {
118583
+ if (platform10 === "win32") return join57(systemTempDir, "hf-render-");
118584
+ return join57(dirname24(outputPath), `work-${jobId}-`);
118497
118585
  }
118498
118586
  function captureAttemptMadeProgress(attemptTargetFrameCount, remainingFrameCount) {
118499
118587
  return remainingFrameCount < attemptTargetFrameCount;
@@ -118521,7 +118609,7 @@ The composition is too large for the available memory. To reduce memory pressure
118521
118609
  function countCapturedFrames(totalFrames, framesDir, frameExt) {
118522
118610
  let captured = 0;
118523
118611
  for (let frameIndex = 0; frameIndex < totalFrames; frameIndex++) {
118524
- const framePath = join56(framesDir, formatCaptureFrameName(frameIndex, frameExt));
118612
+ const framePath = join57(framesDir, formatCaptureFrameName(frameIndex, frameExt));
118525
118613
  if (existsSync50(framePath)) captured++;
118526
118614
  }
118527
118615
  return captured;
@@ -118546,7 +118634,7 @@ async function executeDiskCaptureWithAdaptiveRetry(options) {
118546
118634
  reason: attempt === 0 ? "initial" : pendingTransientRetry ? "transient-retry" : "retry"
118547
118635
  });
118548
118636
  pendingTransientRetry = false;
118549
- const attemptWorkDir = join56(options.workDir, `capture-attempt-${attempt}`);
118637
+ const attemptWorkDir = join57(options.workDir, `capture-attempt-${attempt}`);
118550
118638
  const batches = missingRanges ? buildMissingFrameRetryBatches(
118551
118639
  missingRanges,
118552
118640
  currentWorkers,
@@ -118621,6 +118709,9 @@ async function executeDiskCaptureWithAdaptiveRetry(options) {
118621
118709
  if (failure.kind === "cancelled") {
118622
118710
  throw error;
118623
118711
  }
118712
+ if (isDrawElementVerificationError(error)) {
118713
+ throw error;
118714
+ }
118624
118715
  const remaining = findMissingFrameRanges(
118625
118716
  options.totalFrames,
118626
118717
  options.framesDir,
@@ -118769,6 +118860,15 @@ function shouldRetryViaPinnedFallback(args) {
118769
118860
  if (args.isVerifyError) return true;
118770
118861
  return args.deWorkerInversion === "inverted" || args.deParallelRouter === "routed";
118771
118862
  }
118863
+ async function closeOrphanedProbeForRetry(probe, closer, log2, retryContext) {
118864
+ try {
118865
+ await closer(probe);
118866
+ } catch (closeErr) {
118867
+ log2.warn(`[Render] probe close before ${retryContext} retry failed; continuing with retry`, {
118868
+ error: closeErr instanceof Error ? closeErr.message : String(closeErr)
118869
+ });
118870
+ }
118871
+ }
118772
118872
  function shouldStreamParallelCapture(args) {
118773
118873
  return args.routerEnabled && args.workerCount > 1 && !args.useDrawElement && args.outputFormat === "mp4" && args.streamingOk && !args.layeredOrEffectRoute;
118774
118874
  }
@@ -118797,16 +118897,25 @@ function extractStandaloneEntryFromIndex(indexHtml, entryFile, entryHtml) {
118797
118897
  replaceBodyWithRenderClone(body, renderClone);
118798
118898
  return document2.toString();
118799
118899
  }
118900
+ function deVerifyFallbackTelemetry(err) {
118901
+ const details = getDrawElementVerificationDetails(err);
118902
+ return {
118903
+ reason: details?.kind ?? "psnr",
118904
+ failedDb: roundDb(details?.failedDb),
118905
+ frameIndex: details?.frameIndex,
118906
+ thresholdDb: roundDb(details?.verifyThresholdDb)
118907
+ };
118908
+ }
118800
118909
  async function executeRenderJob(job, projectDir, outputPath, progressSink, abortSignal) {
118801
118910
  const moduleDir = dirname24(fileURLToPath5(import.meta.url));
118802
118911
  const producerRoot = process.env.PRODUCER_RENDERS_DIR ? resolve30(process.env.PRODUCER_RENDERS_DIR, "..") : resolve30(moduleDir, "../..");
118803
- const debugDir = join56(producerRoot, ".debug");
118912
+ const debugDir = join57(producerRoot, ".debug");
118804
118913
  const outputDir = dirname24(outputPath);
118805
118914
  if (!existsSync50(outputDir)) mkdirSync26(outputDir, { recursive: true });
118806
- const workDir = job.config.debug ? join56(debugDir, job.id) : mkdtempSync5(resolveRenderWorkDirPrefix(outputPath, job.id));
118915
+ const workDir = job.config.debug ? join57(debugDir, job.id) : mkdtempSync5(resolveRenderWorkDirPrefix(outputPath, job.id));
118807
118916
  const pipelineStart = Date.now();
118808
118917
  const baseLog = job.config.logger ?? defaultLogger;
118809
- const logPath = job.config.debug ? join56(workDir, "render.log") : null;
118918
+ const logPath = job.config.debug ? join57(workDir, "render.log") : null;
118810
118919
  const execution = new RenderExecutionContext({
118811
118920
  request: { renderJobId: job.id, projectDir, outputPath },
118812
118921
  logger: logPath ? createRenderFileLogger(logPath, baseLog) : baseLog,
@@ -118854,7 +118963,7 @@ async function executeRenderPipeline(input2) {
118854
118963
  imageDecodeFailures: 0
118855
118964
  };
118856
118965
  let hdrPerf;
118857
- const perfOutputPath = join56(workDir, "perf-summary.json");
118966
+ const perfOutputPath = join57(workDir, "perf-summary.json");
118858
118967
  const cfg = { ...job.config.producerConfig ?? resolveConfig() };
118859
118968
  const observability = new RenderObservabilityRecorder({
118860
118969
  pipelineStartMs: pipelineStart,
@@ -118951,15 +119060,15 @@ async function executeRenderPipeline(input2) {
118951
119060
  requestedWorkers: job.config.workers ?? "auto"
118952
119061
  });
118953
119062
  const entryFile = job.config.entryFile || "index.html";
118954
- let htmlPath = join56(projectDir, entryFile);
119063
+ let htmlPath = join57(projectDir, entryFile);
118955
119064
  if (!existsSync50(htmlPath)) {
118956
119065
  throw new Error(`Entry file not found: ${htmlPath}`);
118957
119066
  }
118958
119067
  assertNotAborted();
118959
119068
  const rawEntry = readFileSync29(htmlPath, "utf-8");
118960
119069
  if (entryFile !== "index.html" && rawEntry.trimStart().startsWith("<template")) {
118961
- const wrapperPath = join56(workDir, "standalone-entry.html");
118962
- const projectIndexPath = join56(projectDir, "index.html");
119070
+ const wrapperPath = join57(workDir, "standalone-entry.html");
119071
+ const projectIndexPath = join57(projectDir, "index.html");
118963
119072
  if (!existsSync50(projectIndexPath)) {
118964
119073
  throw new Error(
118965
119074
  `Template entry file "${entryFile}" requires a project index.html to extract its render shell.`
@@ -119109,7 +119218,7 @@ async function executeRenderPipeline(input2) {
119109
119218
  beginFrameStalled: probeResult.beginFrameStalled
119110
119219
  });
119111
119220
  updateJobStatus(job, "preprocessing", "Extracting video frames", 10, onProgress);
119112
- const compiledDir = join56(workDir, "compiled");
119221
+ const compiledDir = join57(workDir, "compiled");
119113
119222
  const extractResult = await observeRenderStage(
119114
119223
  observability,
119115
119224
  "video_extract",
@@ -119218,7 +119327,7 @@ async function executeRenderPipeline(input2) {
119218
119327
  try {
119219
119328
  fileServer = await createFileServer2({
119220
119329
  projectDir,
119221
- compiledDir: join56(workDir, "compiled"),
119330
+ compiledDir: join57(workDir, "compiled"),
119222
119331
  port: 0,
119223
119332
  preHeadScripts: [VIRTUAL_TIME_SHIM],
119224
119333
  fps: job.config.fps
@@ -119236,7 +119345,7 @@ async function executeRenderPipeline(input2) {
119236
119345
  if (!activeFileServer) {
119237
119346
  throw new Error("File server failed to initialize before frame capture");
119238
119347
  }
119239
- const framesDir = join56(workDir, "captured-frames");
119348
+ const framesDir = join57(workDir, "captured-frames");
119240
119349
  if (!existsSync50(framesDir)) mkdirSync26(framesDir, { recursive: true });
119241
119350
  const resolvedBrowserGpuMode = await resolveBrowserGpuMode(cfg.browserGpuMode, {
119242
119351
  chromePath: resolveHeadlessShellPath(cfg),
@@ -119521,7 +119630,7 @@ async function executeRenderPipeline(input2) {
119521
119630
  gif: ".gif"
119522
119631
  };
119523
119632
  const videoExt = FORMAT_EXT3[outputFormat] ?? ".mp4";
119524
- const videoOnlyPath = join56(workDir, `video-only${videoExt}`);
119633
+ const videoOnlyPath = join57(workDir, `video-only${videoExt}`);
119525
119634
  const usePageSideCompositingForTransitions = (cfg.enablePageSideCompositing || isGif) && compiled.hasShaderTransitions && !hasHdrContent && !isPngSequence && !needsAlpha;
119526
119635
  if (usePageSideCompositingForTransitions) {
119527
119636
  activeFileServer.addPreHeadScript(HF_PAGE_SIDE_COMPOSITING_STUB);
@@ -119774,12 +119883,14 @@ async function executeRenderPipeline(input2) {
119774
119883
  throw err;
119775
119884
  const isMemoryExhaustion = !isVerifyError && isMemoryExhaustionError(err);
119776
119885
  deSelfVerifyFallback = isVerifyError;
119777
- const verifyDetails = isVerifyError ? getDrawElementVerificationDetails(err) : void 0;
119778
- deFallbackReason = isVerifyError ? verifyDetails?.kind ?? "psnr" : isMemoryExhaustion ? "oom" : "capture_error";
119779
119886
  if (isVerifyError) {
119780
- deFallbackFailedDb = roundDb(verifyDetails?.failedDb);
119781
- deFallbackFrameIndex = verifyDetails?.frameIndex;
119782
- deFallbackThresholdDb = roundDb(verifyDetails?.verifyThresholdDb);
119887
+ const t2 = deVerifyFallbackTelemetry(err);
119888
+ deFallbackReason = t2.reason;
119889
+ deFallbackFailedDb = t2.failedDb;
119890
+ deFallbackFrameIndex = t2.frameIndex;
119891
+ deFallbackThresholdDb = t2.thresholdDb;
119892
+ } else {
119893
+ deFallbackReason = isMemoryExhaustion ? "oom" : "capture_error";
119783
119894
  }
119784
119895
  log2.warn(
119785
119896
  isVerifyError ? "[Render] drawElement self-verification failed; re-rendering via screenshot" : "[Render] capture failed on the pinned worker count; re-rendering via screenshot",
@@ -119807,7 +119918,12 @@ async function executeRenderPipeline(input2) {
119807
119918
  deWorkerInversion,
119808
119919
  deParallelRouter
119809
119920
  });
119810
- probeSession = null;
119921
+ if (probeSession) {
119922
+ lastBrowserConsole = probeSession.browserConsoleBuffer;
119923
+ const orphaned = probeSession;
119924
+ probeSession = null;
119925
+ await closeOrphanedProbeForRetry(orphaned, closeCaptureSession, log2, "streaming");
119926
+ }
119811
119927
  if (failedRouting === "worker_inversion") {
119812
119928
  log2.info(
119813
119929
  `[Render] Reverting worker inversion for the retry: ${capturePlan.workerCount} workers, plan=${capturePlan.kind}.`
@@ -119866,10 +119982,9 @@ async function executeRenderPipeline(input2) {
119866
119982
  if (capturePlan.kind !== "sdr_disk") {
119867
119983
  throw new Error(`Disk capture requires sdr_disk plan; got ${capturePlan.kind}`);
119868
119984
  }
119869
- const diskPlan = capturePlan;
119870
119985
  resetCaptureAttemptProgress(job);
119871
119986
  const captureFrameStart = Date.now();
119872
- const captureRes = await observeRenderStage(
119987
+ const invokeDiskCapture = (diskPlan) => observeRenderStage(
119873
119988
  observability,
119874
119989
  "capture_disk",
119875
119990
  captureStageObservationData({ needsAlpha: diskPlan.needsAlpha }),
@@ -119892,6 +120007,54 @@ async function executeRenderPipeline(input2) {
119892
120007
  onProgress
119893
120008
  })
119894
120009
  );
120010
+ let captureRes;
120011
+ try {
120012
+ captureRes = await invokeDiskCapture(capturePlan);
120013
+ } catch (err) {
120014
+ if (!isDrawElementVerificationError(err) || err instanceof RenderCancelledError || executionSignal?.aborted === true) {
120015
+ throw err;
120016
+ }
120017
+ deSelfVerifyFallback = true;
120018
+ const t2 = deVerifyFallbackTelemetry(err);
120019
+ deFallbackReason = t2.reason;
120020
+ deFallbackFailedDb = t2.failedDb;
120021
+ deFallbackFrameIndex = t2.frameIndex;
120022
+ deFallbackThresholdDb = t2.thresholdDb;
120023
+ log2.warn(
120024
+ "[Render] drawElement self-verification failed on the parallel disk path; re-rendering via screenshot",
120025
+ { error: err instanceof Error ? err.message : String(err) }
120026
+ );
120027
+ observability.checkpoint(
120028
+ "capture_disk",
120029
+ "drawElement self-verify failed; retrying with forceScreenshot"
120030
+ );
120031
+ rmSync15(framesDir, { recursive: true, force: true });
120032
+ mkdirSync26(framesDir, { recursive: true });
120033
+ resetCaptureAttemptProgress(job);
120034
+ dedupPerfs.length = 0;
120035
+ cfg.useDrawElement = false;
120036
+ if (probeSession) {
120037
+ lastBrowserConsole = probeSession.browserConsoleBuffer;
120038
+ const orphaned = probeSession;
120039
+ probeSession = null;
120040
+ await closeOrphanedProbeForRetry(orphaned, closeCaptureSession, log2, "disk verify");
120041
+ }
120042
+ capturePlan = replanAfterFailure(capturePlan, { kind: "draw_element_verification" });
120043
+ syncCapturePlan();
120044
+ updateCaptureObservability({
120045
+ forceScreenshot: capturePlan.forceScreenshot,
120046
+ deSelfVerifyFallback,
120047
+ deFallbackReason,
120048
+ deFallbackFailedDb,
120049
+ deFallbackFrameIndex,
120050
+ deFallbackThresholdDb
120051
+ });
120052
+ if (capturePlan.kind !== "sdr_disk") {
120053
+ throw new Error(`Disk verify retry requires sdr_disk plan; got ${capturePlan.kind}`);
120054
+ }
120055
+ captureRes = await invokeDiskCapture(capturePlan);
120056
+ observability.clearFailure("capture_disk");
120057
+ }
119895
120058
  const captureFrameMs = Date.now() - captureFrameStart;
119896
120059
  workerCount = captureRes.workerCount;
119897
120060
  updateCaptureObservability({ workerCount });
@@ -120039,7 +120202,7 @@ async function executeRenderPipeline(input2) {
120039
120202
  }
120040
120203
  if (job.config.debug) {
120041
120204
  if (!isPngSequence && existsSync50(stagedOutputPath)) {
120042
- const debugOutput = join56(workDir, `output${videoExt}`);
120205
+ const debugOutput = join57(workDir, `output${videoExt}`);
120043
120206
  copyFileSync6(stagedOutputPath, debugOutput);
120044
120207
  }
120045
120208
  }
@@ -120687,7 +120850,7 @@ var init_config3 = __esm({
120687
120850
 
120688
120851
  // ../producer/src/services/hyperframeLint.ts
120689
120852
  import { existsSync as existsSync51, readFileSync as readFileSync30, statSync as statSync15 } from "fs";
120690
- import { resolve as resolve31, join as join57 } from "path";
120853
+ import { resolve as resolve31, join as join58 } from "path";
120691
120854
  function isStringRecord2(value) {
120692
120855
  if (!value || typeof value !== "object" || Array.isArray(value)) {
120693
120856
  return false;
@@ -120735,7 +120898,7 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
120735
120898
  }
120736
120899
  }
120737
120900
  return {
120738
- error: `No HTML entry file found in project directory: ${join57(absProjectDir, preferredEntryFile || "index.html")}`
120901
+ error: `No HTML entry file found in project directory: ${join58(absProjectDir, preferredEntryFile || "index.html")}`
120739
120902
  };
120740
120903
  }
120741
120904
  function prepareHyperframeLintBody(body) {
@@ -120784,7 +120947,7 @@ var init_hyperframeLint = __esm({
120784
120947
  // ../producer/src/services/healthWorker.ts
120785
120948
  import { Worker as Worker3 } from "worker_threads";
120786
120949
  import { fileURLToPath as fileURLToPath6 } from "url";
120787
- import { dirname as dirname25, join as join58 } from "path";
120950
+ import { dirname as dirname25, join as join59 } from "path";
120788
120951
  import { existsSync as existsSync53 } from "fs";
120789
120952
  async function startHealthWorker(options = {}) {
120790
120953
  const log2 = options.logger ?? defaultLogger2();
@@ -120859,7 +121022,7 @@ function defaultLogger2() {
120859
121022
  }
120860
121023
  function resolveWorkerEntry2() {
120861
121024
  const here = dirname25(fileURLToPath6(import.meta.url));
120862
- const candidates = [join58(here, "healthWorkerThread.js"), join58(here, "healthWorkerThread.ts")];
121025
+ const candidates = [join59(here, "healthWorkerThread.js"), join59(here, "healthWorkerThread.ts")];
120863
121026
  for (const candidate of candidates) {
120864
121027
  if (existsSync53(candidate)) return candidate;
120865
121028
  }
@@ -120924,8 +121087,8 @@ import {
120924
121087
  rmSync as rmSync16,
120925
121088
  createReadStream as createReadStream2
120926
121089
  } from "fs";
120927
- import { resolve as resolve33, dirname as dirname26, join as join59 } from "path";
120928
- import { tmpdir as tmpdir8 } from "os";
121090
+ import { resolve as resolve33, dirname as dirname26, join as join60 } from "path";
121091
+ import { tmpdir as tmpdir9 } from "os";
120929
121092
  import { parseArgs as parseArgs2 } from "util";
120930
121093
  import crypto2 from "crypto";
120931
121094
  import { Hono as Hono4 } from "hono";
@@ -121068,9 +121231,9 @@ async function resolveInlineRenderHtml(body) {
121068
121231
  }
121069
121232
  }
121070
121233
  function materializeInlineProject(html, options) {
121071
- const tempRoot = process.env.PRODUCER_TMP_PROJECT_DIR || tmpdir8();
121072
- const tempProjectDir = mkdtempSync6(join59(tempRoot, "producer-project-"));
121073
- writeFileSync19(join59(tempProjectDir, "index.html"), html, "utf-8");
121234
+ const tempRoot = process.env.PRODUCER_TMP_PROJECT_DIR || tmpdir9();
121235
+ const tempProjectDir = mkdtempSync6(join60(tempRoot, "producer-project-"));
121236
+ writeFileSync19(join60(tempProjectDir, "index.html"), html, "utf-8");
121074
121237
  return {
121075
121238
  prepared: {
121076
121239
  input: { projectDir: tempProjectDir, ...options },
@@ -121593,7 +121756,7 @@ var init_planHash = __esm({
121593
121756
 
121594
121757
  // ../producer/src/services/render/stages/freezePlan.ts
121595
121758
  import { existsSync as existsSync55, mkdirSync as mkdirSync28, readFileSync as readFileSync31, readdirSync as readdirSync17, writeFileSync as writeFileSync20 } from "fs";
121596
- import { join as join60, relative as relative12, resolve as resolve34 } from "path";
121759
+ import { join as join61, relative as relative12, resolve as resolve34 } from "path";
121597
121760
  function stripUndefined(value) {
121598
121761
  if (Array.isArray(value)) return value.map(stripUndefined);
121599
121762
  if (value !== null && typeof value === "object") {
@@ -121614,7 +121777,7 @@ function listPlanFiles(planDir) {
121614
121777
  function walk(dir) {
121615
121778
  const entries2 = readdirSync17(dir, { withFileTypes: true });
121616
121779
  for (const entry of entries2) {
121617
- const full2 = join60(dir, entry.name);
121780
+ const full2 = join61(dir, entry.name);
121618
121781
  if (entry.isDirectory()) {
121619
121782
  walk(full2);
121620
121783
  } else if (entry.isFile()) {
@@ -121650,8 +121813,8 @@ function collectPlanAssetShas(planDir) {
121650
121813
  return { compositionHtml, assets };
121651
121814
  }
121652
121815
  function recomputePlanHashFromPlanDir(planDir) {
121653
- const planJsonPath = join60(planDir, "plan.json");
121654
- const encoderJsonPath = join60(planDir, "meta", "encoder.json");
121816
+ const planJsonPath = join61(planDir, "plan.json");
121817
+ const encoderJsonPath = join61(planDir, "meta", "encoder.json");
121655
121818
  if (!existsSync55(planJsonPath)) {
121656
121819
  throw new Error(`[freezePlan] plan.json missing: ${planJsonPath}`);
121657
121820
  }
@@ -121687,18 +121850,18 @@ async function freezePlan(input2) {
121687
121850
  if (!existsSync55(planDir)) {
121688
121851
  throw new Error(`[freezePlan] planDir does not exist: ${planDir}`);
121689
121852
  }
121690
- const metaDir = join60(planDir, "meta");
121853
+ const metaDir = join61(planDir, "meta");
121691
121854
  if (!existsSync55(metaDir)) mkdirSync28(metaDir, { recursive: true });
121692
121855
  writeFileSync20(
121693
- join60(metaDir, "composition.json"),
121856
+ join61(metaDir, "composition.json"),
121694
121857
  `${JSON.stringify(composition, null, 2)}
121695
121858
  `,
121696
121859
  "utf-8"
121697
121860
  );
121698
121861
  const encoderForCanonical = stripUndefined(encoder);
121699
121862
  const encoderConfigCanonicalJson = canonicalJsonStringify(encoderForCanonical);
121700
- writeFileSync20(join60(metaDir, "encoder.json"), encoderConfigCanonicalJson, "utf-8");
121701
- writeFileSync20(join60(metaDir, "chunks.json"), `${JSON.stringify(chunks, null, 2)}
121863
+ writeFileSync20(join61(metaDir, "encoder.json"), encoderConfigCanonicalJson, "utf-8");
121864
+ writeFileSync20(join61(metaDir, "chunks.json"), `${JSON.stringify(chunks, null, 2)}
121702
121865
  `, "utf-8");
121703
121866
  const { compositionHtml, assets } = collectPlanAssetShas(planDir);
121704
121867
  const planHash = computePlanHash({
@@ -121721,7 +121884,7 @@ async function freezePlan(input2) {
121721
121884
  duration: durationSeconds,
121722
121885
  hasAudio
121723
121886
  };
121724
- const planJsonPath = join60(planDir, "plan.json");
121887
+ const planJsonPath = join61(planDir, "plan.json");
121725
121888
  writeFileSync20(planJsonPath, `${JSON.stringify(planJson, null, 2)}
121726
121889
  `, "utf-8");
121727
121890
  return { planJsonPath, planHash };
@@ -121783,7 +121946,7 @@ var init_runtimeEnvSnapshot = __esm({
121783
121946
 
121784
121947
  // ../producer/src/services/distributed/shared.ts
121785
121948
  import { execFile as execFileCallback } from "child_process";
121786
- import { dirname as dirname27, join as join61 } from "path";
121949
+ import { dirname as dirname27, join as join63 } from "path";
121787
121950
  import { existsSync as existsSync56, readFileSync as readFileSync33 } from "fs";
121788
121951
  import { fileURLToPath as fileURLToPath7 } from "url";
121789
121952
  import { promisify as promisify4 } from "util";
@@ -121825,7 +121988,7 @@ function readProducerVersion() {
121825
121988
  const startDir = dirname27(fileURLToPath7(import.meta.url));
121826
121989
  let current2 = startDir;
121827
121990
  for (let i2 = 0; i2 < 10; i2++) {
121828
- const candidate = join61(current2, "package.json");
121991
+ const candidate = join63(current2, "package.json");
121829
121992
  if (existsSync56(candidate)) {
121830
121993
  try {
121831
121994
  const pkg = JSON.parse(readFileSync33(candidate, "utf-8"));
@@ -121867,7 +122030,7 @@ import {
121867
122030
  statSync as statSync17,
121868
122031
  writeFileSync as writeFileSync21
121869
122032
  } from "fs";
121870
- import { join as join63, relative as relative13, sep as sep9 } from "path";
122033
+ import { join as join64, relative as relative13, sep as sep9 } from "path";
121871
122034
  function applyDistributedAudioWarningPolicy(job, audioError, log2 = defaultLogger) {
121872
122035
  applyRenderWarningPolicy(
121873
122036
  job,
@@ -121905,7 +122068,7 @@ function measurePlanDirBytes(planDir) {
121905
122068
  return;
121906
122069
  }
121907
122070
  for (const entry of entries2) {
121908
- const full2 = join63(dir, entry.name);
122071
+ const full2 = join64(dir, entry.name);
121909
122072
  if (entry.isDirectory()) {
121910
122073
  walk(full2);
121911
122074
  } else if (entry.isFile()) {
@@ -122076,13 +122239,13 @@ async function plan(projectDir, config, planDir) {
122076
122239
  variables: config.variables
122077
122240
  });
122078
122241
  const entryFile = config.entryFile ?? "index.html";
122079
- const htmlPath = join63(projectDir, entryFile);
122242
+ const htmlPath = join64(projectDir, entryFile);
122080
122243
  if (!existsSync57(htmlPath)) {
122081
122244
  throw new Error(`[plan] entry file not found: ${htmlPath}`);
122082
122245
  }
122083
- const workDir = join63(planDir, ".plan-work");
122246
+ const workDir = join64(planDir, ".plan-work");
122084
122247
  if (!existsSync57(workDir)) mkdirSync29(workDir, { recursive: true });
122085
- const compiledDir = join63(workDir, "compiled");
122248
+ const compiledDir = join64(workDir, "compiled");
122086
122249
  mkdirSync29(compiledDir, { recursive: true });
122087
122250
  cpSync3(projectDir, compiledDir, {
122088
122251
  recursive: true,
@@ -122094,7 +122257,7 @@ async function plan(projectDir, config, planDir) {
122094
122257
  return firstSegment === void 0 || !PLAN_PROJECT_DIR_SKIP_SEGMENTS.has(firstSegment);
122095
122258
  }
122096
122259
  });
122097
- const finalCompiledDir = join63(planDir, "compiled");
122260
+ const finalCompiledDir = join64(planDir, "compiled");
122098
122261
  const needsAlpha = config.format === "png-sequence" || config.format === "mov" || config.format === "webm";
122099
122262
  const compileResult = await runCompileStage({
122100
122263
  projectDir,
@@ -122180,8 +122343,8 @@ async function plan(projectDir, config, planDir) {
122180
122343
  if (audioResult.audioError) {
122181
122344
  applyDistributedAudioWarningPolicy(job, audioResult.audioError, log2);
122182
122345
  }
122183
- const stagedVideoFrames = join63(compiledDir, "__hyperframes_video_frames");
122184
- const videoFramesDst = join63(planDir, "video-frames");
122346
+ const stagedVideoFrames = join64(compiledDir, "__hyperframes_video_frames");
122347
+ const videoFramesDst = join64(planDir, "video-frames");
122185
122348
  if (existsSync57(videoFramesDst)) rmSync17(videoFramesDst, { recursive: true, force: true });
122186
122349
  if (existsSync57(stagedVideoFrames)) {
122187
122350
  renameSync11(stagedVideoFrames, videoFramesDst);
@@ -122201,13 +122364,13 @@ async function plan(projectDir, config, planDir) {
122201
122364
  metadata: ext.metadata
122202
122365
  }))
122203
122366
  };
122204
- mkdirSync29(join63(planDir, "meta"), { recursive: true });
122367
+ mkdirSync29(join64(planDir, "meta"), { recursive: true });
122205
122368
  writeFileSync21(
122206
- join63(planDir, PLAN_VIDEOS_META_RELATIVE_PATH),
122369
+ join64(planDir, PLAN_VIDEOS_META_RELATIVE_PATH),
122207
122370
  JSON.stringify(planVideosJson, null, 2),
122208
122371
  "utf-8"
122209
122372
  );
122210
- const planAudioPath = join63(planDir, "audio.aac");
122373
+ const planAudioPath = join64(planDir, "audio.aac");
122211
122374
  if (audioResult.hasAudio && existsSync57(audioResult.audioOutputPath)) {
122212
122375
  renameSync11(audioResult.audioOutputPath, planAudioPath);
122213
122376
  }
@@ -122354,11 +122517,11 @@ var init_plan = __esm({
122354
122517
  // ../producer/src/services/distributed/renderChunk.ts
122355
122518
  import { randomBytes as randomBytes2 } from "crypto";
122356
122519
  import { existsSync as existsSync58, mkdirSync as mkdirSync30, readFileSync as readFileSync34, readdirSync as readdirSync19, rmSync as rmSync18, writeFileSync as writeFileSync23 } from "fs";
122357
- import { extname as extname14, join as join64 } from "path";
122520
+ import { extname as extname14, join as join65 } from "path";
122358
122521
  function rebuildExtractedFramesFromPlanDir(planDir, videos) {
122359
122522
  const result = [];
122360
122523
  for (const v2 of videos) {
122361
- const outputDir = join64(planDir, "video-frames", v2.videoId);
122524
+ const outputDir = join65(planDir, "video-frames", v2.videoId);
122362
122525
  if (!existsSync58(outputDir)) {
122363
122526
  throw new Error(
122364
122527
  `[renderChunk] planDir missing extracted video frames for ${JSON.stringify(v2.videoId)}: ${outputDir} not present. plan() should have written frames here; the planDir is malformed.`
@@ -122370,7 +122533,7 @@ function rebuildExtractedFramesFromPlanDir(planDir, videos) {
122370
122533
  for (let i2 = 0; i2 < frames.length; i2++) {
122371
122534
  const frameName = frames[i2];
122372
122535
  if (!frameName) continue;
122373
- framePaths.set(i2, join64(outputDir, frameName));
122536
+ framePaths.set(i2, join65(outputDir, frameName));
122374
122537
  }
122375
122538
  result.push({
122376
122539
  videoId: v2.videoId,
@@ -122395,7 +122558,7 @@ function hashChunkOutput(outputPath, kind) {
122395
122558
  if (kind === "file") return sha256Hex(readFileSync34(outputPath));
122396
122559
  const entries2 = readdirSync19(outputPath).filter((name) => /\.(png|jpg|jpeg)$/i.test(name)).sort();
122397
122560
  const lines = entries2.map(
122398
- (name) => `${name}\0${sha256Hex(readFileSync34(join64(outputPath, name)))}`
122561
+ (name) => `${name}\0${sha256Hex(readFileSync34(join65(outputPath, name)))}`
122399
122562
  );
122400
122563
  return sha256Hex(lines.join("\0"));
122401
122564
  }
@@ -122412,9 +122575,9 @@ function resolveLockedVp9CpuUsed(lockedEncoder) {
122412
122575
  async function renderChunk(planDir, chunkIndex, outputChunkPath) {
122413
122576
  const start = Date.now();
122414
122577
  const log2 = defaultLogger;
122415
- const planJsonPath = join64(planDir, "plan.json");
122416
- const encoderJsonPath = join64(planDir, "meta", "encoder.json");
122417
- const chunksJsonPath = join64(planDir, "meta", "chunks.json");
122578
+ const planJsonPath = join65(planDir, "plan.json");
122579
+ const encoderJsonPath = join65(planDir, "meta", "encoder.json");
122580
+ const chunksJsonPath = join65(planDir, "meta", "chunks.json");
122418
122581
  for (const required of [planJsonPath, encoderJsonPath, chunksJsonPath]) {
122419
122582
  if (!existsSync58(required)) {
122420
122583
  throw new RenderChunkValidationError(
@@ -122426,7 +122589,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
122426
122589
  const plan2 = JSON.parse(readFileSync34(planJsonPath, "utf-8"));
122427
122590
  const encoder = JSON.parse(readFileSync34(encoderJsonPath, "utf-8"));
122428
122591
  const chunks = JSON.parse(readFileSync34(chunksJsonPath, "utf-8"));
122429
- const videosJsonPath = join64(planDir, PLAN_VIDEOS_META_RELATIVE_PATH);
122592
+ const videosJsonPath = join65(planDir, PLAN_VIDEOS_META_RELATIVE_PATH);
122430
122593
  let planVideos = null;
122431
122594
  if (existsSync58(videosJsonPath)) {
122432
122595
  try {
@@ -122455,7 +122618,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
122455
122618
  `[renderChunk] chunk ${chunkIndex} has non-positive frame count: ${framesInChunk}`
122456
122619
  );
122457
122620
  }
122458
- const compiledDir = join64(planDir, "compiled");
122621
+ const compiledDir = join65(planDir, "compiled");
122459
122622
  if (!existsSync58(compiledDir)) {
122460
122623
  throw new RenderChunkValidationError(
122461
122624
  MISSING_PLAN_ARTIFACT,
@@ -122519,7 +122682,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
122519
122682
  );
122520
122683
  const workDir = `${outputChunkPath}.work.${process.pid}.${randomBytes2(4).toString("hex")}`;
122521
122684
  mkdirSync30(workDir, { recursive: true });
122522
- const framesDir = join64(workDir, "captured-frames");
122685
+ const framesDir = join65(workDir, "captured-frames");
122523
122686
  mkdirSync30(framesDir, { recursive: true });
122524
122687
  const fileServer = await createFileServer2({
122525
122688
  projectDir: compiledDir,
@@ -122611,7 +122774,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
122611
122774
  if (isPngSequence) {
122612
122775
  if (!existsSync58(outputChunkPath)) mkdirSync30(outputChunkPath, { recursive: true });
122613
122776
  } else {
122614
- const outDir = join64(outputChunkPath, "..");
122777
+ const outDir = join65(outputChunkPath, "..");
122615
122778
  if (!existsSync58(outDir)) mkdirSync30(outDir, { recursive: true });
122616
122779
  }
122617
122780
  const encodeStarted = Date.now();
@@ -122758,14 +122921,14 @@ import {
122758
122921
  statSync as statSync18,
122759
122922
  writeFileSync as writeFileSync24
122760
122923
  } from "fs";
122761
- import { dirname as dirname28, join as join65 } from "path";
122924
+ import { dirname as dirname28, join as join66 } from "path";
122762
122925
  async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
122763
122926
  const start = Date.now();
122764
122927
  const log2 = options?.logger ?? defaultLogger;
122765
122928
  const abortSignal = options?.abortSignal;
122766
122929
  const cfr = options?.cfr === true;
122767
- const planJsonPath = join65(planDir, "plan.json");
122768
- const chunksJsonPath = join65(planDir, "meta", "chunks.json");
122930
+ const planJsonPath = join66(planDir, "plan.json");
122931
+ const chunksJsonPath = join66(planDir, "meta", "chunks.json");
122769
122932
  if (!existsSync59(planJsonPath)) {
122770
122933
  throw new Error(`[assemble] planDir missing plan.json: ${planJsonPath}`);
122771
122934
  }
@@ -122794,7 +122957,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
122794
122957
  if (existsSync59(workDir)) rmSync19(workDir, { recursive: true, force: true });
122795
122958
  mkdirSync31(workDir, { recursive: true });
122796
122959
  try {
122797
- const concatOutputPath = join65(workDir, `concat.${plan2.dimensions.format}`);
122960
+ const concatOutputPath = join66(workDir, `concat.${plan2.dimensions.format}`);
122798
122961
  const fpsArg = fpsToFfmpegArg({
122799
122962
  num: plan2.dimensions.fpsNum,
122800
122963
  den: plan2.dimensions.fpsDen
@@ -122808,7 +122971,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
122808
122971
  );
122809
122972
  }
122810
122973
  } else {
122811
- const concatListPath = join65(workDir, "concat-list.txt");
122974
+ const concatListPath = join66(workDir, "concat-list.txt");
122812
122975
  const concatBody = chunkPaths.map((path2) => `file '${path2.replace(/'/g, "'\\''")}'`).join("\n");
122813
122976
  writeFileSync24(concatListPath, `${concatBody}
122814
122977
  `, "utf-8");
@@ -122840,7 +123003,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
122840
123003
  `[assemble] cfr=true is only supported for format="mp4" (got "${plan2.dimensions.format}"). Stream-copy paths for webm and mov already produce exact avg_frame_rate; cfr re-encode is not needed.`
122841
123004
  );
122842
123005
  }
122843
- const encoderJsonPath = join65(planDir, "meta", "encoder.json");
123006
+ const encoderJsonPath = join66(planDir, "meta", "encoder.json");
122844
123007
  if (!existsSync59(encoderJsonPath)) {
122845
123008
  throw new Error(`[assemble] planDir missing meta/encoder.json: ${encoderJsonPath}`);
122846
123009
  }
@@ -122850,7 +123013,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
122850
123013
  `[assemble] cfr=true is not yet supported with codec: "h265". The cfr re-encode pass uses libx264 and would silently transcode the h265 chunks. Either disable cfr or render with codec: "h264".`
122851
123014
  );
122852
123015
  }
122853
- const cfrOutputPath = join65(workDir, `cfr.${plan2.dimensions.format}`);
123016
+ const cfrOutputPath = join66(workDir, `cfr.${plan2.dimensions.format}`);
122854
123017
  const cfrArgs = [
122855
123018
  "-i",
122856
123019
  concatOutputPath,
@@ -122884,7 +123047,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
122884
123047
  }
122885
123048
  let audioForMux = null;
122886
123049
  if (audioPath !== null && existsSync59(audioPath)) {
122887
- const paddedAudioPath = join65(workDir, "audio-padded.aac");
123050
+ const paddedAudioPath = join66(workDir, "audio-padded.aac");
122888
123051
  const padTrimResult = await padOrTrimAudioToVideoFrameCount({
122889
123052
  videoPath: postConcatPath,
122890
123053
  audioPath,
@@ -122901,7 +123064,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
122901
123064
  sourceDurationSeconds: padTrimResult.sourceDurationSeconds
122902
123065
  });
122903
123066
  }
122904
- const muxOutputPath = audioForMux !== null ? join65(workDir, `mux.${plan2.dimensions.format}`) : postConcatPath;
123067
+ const muxOutputPath = audioForMux !== null ? join66(workDir, `mux.${plan2.dimensions.format}`) : postConcatPath;
122905
123068
  if (audioForMux !== null) {
122906
123069
  const muxResult = await muxVideoWithAudio(
122907
123070
  postConcatPath,
@@ -122961,8 +123124,8 @@ function mergePngFrameDirs(chunkPaths, outputPath, totalFrames, audioPath, start
122961
123124
  throw new Error(`[assemble] png-sequence chunk has no frames: ${chunkDir}`);
122962
123125
  }
122963
123126
  for (const frame of frames) {
122964
- const dst = join65(outputPath, formatExportFrameName(globalIdx, "png"));
122965
- cpSync4(join65(chunkDir, frame), dst);
123127
+ const dst = join66(outputPath, formatExportFrameName(globalIdx, "png"));
123128
+ cpSync4(join66(chunkDir, frame), dst);
122966
123129
  globalIdx += 1;
122967
123130
  }
122968
123131
  }
@@ -122972,13 +123135,13 @@ function mergePngFrameDirs(chunkPaths, outputPath, totalFrames, audioPath, start
122972
123135
  );
122973
123136
  }
122974
123137
  if (audioPath !== null && existsSync59(audioPath)) {
122975
- const sidecar = join65(outputPath, "audio.aac");
123138
+ const sidecar = join66(outputPath, "audio.aac");
122976
123139
  cpSync4(audioPath, sidecar);
122977
123140
  }
122978
123141
  let fileSize = 0;
122979
123142
  for (const name of readdirSync20(outputPath)) {
122980
123143
  try {
122981
- fileSize += statSync18(join65(outputPath, name)).size;
123144
+ fileSize += statSync18(join66(outputPath, name)).size;
122982
123145
  } catch {
122983
123146
  }
122984
123147
  }
@@ -123003,7 +123166,7 @@ var init_assemble = __esm({
123003
123166
  // ../producer/src/services/distributed/projectHash.ts
123004
123167
  import { readdirSync as readdirSync21, readFileSync as readFileSync36 } from "fs";
123005
123168
  import { createHash as createHash14 } from "crypto";
123006
- import { join as join66, relative as relative14 } from "path";
123169
+ import { join as join67, relative as relative14 } from "path";
123007
123170
  var init_projectHash = __esm({
123008
123171
  "../producer/src/services/distributed/projectHash.ts"() {
123009
123172
  "use strict";
@@ -123109,7 +123272,7 @@ import { execSync as execSync4, spawnSync as spawnSync2 } from "child_process";
123109
123272
  import { existsSync as existsSync60, mkdirSync as mkdirSync33, readdirSync as readdirSync23, rmSync as rmSync20, statSync as statSync19, utimesSync as utimesSync3 } from "fs";
123110
123273
  import { basename as basename9 } from "path";
123111
123274
  import { homedir as homedir13 } from "os";
123112
- import { join as join67 } from "path";
123275
+ import { join as join68 } from "path";
123113
123276
  async function loadPuppeteerBrowsers() {
123114
123277
  try {
123115
123278
  return await import("@puppeteer/browsers");
@@ -123305,15 +123468,15 @@ function findFromPuppeteerCache() {
123305
123468
  }
123306
123469
  for (const version2 of versions) {
123307
123470
  const candidates = [
123308
- join67(PUPPETEER_CACHE_DIR, version2, "chrome-headless-shell-linux64", "chrome-headless-shell"),
123309
- join67(
123471
+ join68(PUPPETEER_CACHE_DIR, version2, "chrome-headless-shell-linux64", "chrome-headless-shell"),
123472
+ join68(
123310
123473
  PUPPETEER_CACHE_DIR,
123311
123474
  version2,
123312
123475
  "chrome-headless-shell-mac-arm64",
123313
123476
  "chrome-headless-shell"
123314
123477
  ),
123315
- join67(PUPPETEER_CACHE_DIR, version2, "chrome-headless-shell-mac-x64", "chrome-headless-shell"),
123316
- join67(
123478
+ join68(PUPPETEER_CACHE_DIR, version2, "chrome-headless-shell-mac-x64", "chrome-headless-shell"),
123479
+ join68(
123317
123480
  PUPPETEER_CACHE_DIR,
123318
123481
  version2,
123319
123482
  "chrome-headless-shell-win64",
@@ -123544,11 +123707,11 @@ var init_manager2 = __esm({
123544
123707
  "use strict";
123545
123708
  init_errorMessage();
123546
123709
  CHROME_VERSION = "152.0.7928.2";
123547
- CACHE_ROOT_DIR = join67(homedir13(), ".cache", "hyperframes");
123548
- CACHE_DIR2 = join67(homedir13(), ".cache", "hyperframes", "chrome");
123549
- PUPPETEER_CACHE_DIR = join67(homedir13(), ".cache", "puppeteer", "chrome-headless-shell");
123550
- INSTALL_LOCK_DIR = join67(CACHE_ROOT_DIR, ".chrome.install.lock");
123551
- INSTALL_RECLAIM_LOCK_DIR = join67(CACHE_ROOT_DIR, ".chrome.install.reclaim.lock");
123710
+ CACHE_ROOT_DIR = join68(homedir13(), ".cache", "hyperframes");
123711
+ CACHE_DIR2 = join68(homedir13(), ".cache", "hyperframes", "chrome");
123712
+ PUPPETEER_CACHE_DIR = join68(homedir13(), ".cache", "puppeteer", "chrome-headless-shell");
123713
+ INSTALL_LOCK_DIR = join68(CACHE_ROOT_DIR, ".chrome.install.lock");
123714
+ INSTALL_RECLAIM_LOCK_DIR = join68(CACHE_ROOT_DIR, ".chrome.install.reclaim.lock");
123552
123715
  INSTALL_LOCK_TIMINGS = {
123553
123716
  staleMs: 12e4,
123554
123717
  pollMs: 200,
@@ -123580,7 +123743,7 @@ __export(manager_exports3, {
123580
123743
  });
123581
123744
  import { existsSync as existsSync61, mkdirSync as mkdirSync34 } from "fs";
123582
123745
  import { homedir as homedir14, platform as platform6, arch } from "os";
123583
- import { join as join68 } from "path";
123746
+ import { join as join69 } from "path";
123584
123747
  function isDevice(value) {
123585
123748
  return typeof value === "string" && DEVICES2.includes(value);
123586
123749
  }
@@ -123620,7 +123783,7 @@ function listAvailableProviders() {
123620
123783
  return out;
123621
123784
  }
123622
123785
  function modelPath(model = DEFAULT_MODEL2) {
123623
- return join68(MODELS_DIR2, `${model}.onnx`);
123786
+ return join69(MODELS_DIR2, `${model}.onnx`);
123624
123787
  }
123625
123788
  async function ensureModel2(model = DEFAULT_MODEL2, options) {
123626
123789
  const dest = modelPath(model);
@@ -123638,7 +123801,7 @@ var init_manager3 = __esm({
123638
123801
  "src/background-removal/manager.ts"() {
123639
123802
  "use strict";
123640
123803
  init_download();
123641
- MODELS_DIR2 = join68(homedir14(), ".cache", "hyperframes", "background-removal", "models");
123804
+ MODELS_DIR2 = join69(homedir14(), ".cache", "hyperframes", "background-removal", "models");
123642
123805
  DEFAULT_MODEL2 = "u2net_human_seg";
123643
123806
  MODEL_URLS = {
123644
123807
  u2net_human_seg: "https://github.com/danielgatis/rembg/releases/download/v0.0.0/u2net_human_seg.onnx"
@@ -124138,7 +124301,7 @@ __export(studioServer_exports, {
124138
124301
  import { Hono as Hono5 } from "hono";
124139
124302
  import { streamSSE as streamSSE4 } from "hono/streaming";
124140
124303
  import { existsSync as existsSync63, readFileSync as readFileSync37, writeFileSync as writeFileSync25, statSync as statSync20, unlinkSync as unlinkSync5 } from "fs";
124141
- import { resolve as resolve35, join as join69, basename as basename10 } from "path";
124304
+ import { resolve as resolve35, join as join70, basename as basename10 } from "path";
124142
124305
  async function loadStudioProducer() {
124143
124306
  return isDevMode() ? await Promise.resolve().then(() => (init_src2(), src_exports2)) : await Promise.resolve().then(() => (init_src2(), src_exports2));
124144
124307
  }
@@ -124186,7 +124349,7 @@ function resolveRuntimePath() {
124186
124349
  return builtPath;
124187
124350
  }
124188
124351
  function readStudioManualEditManifestContent(projectDir) {
124189
- const manifestPath2 = join69(projectDir, STUDIO_MANUAL_EDITS_PATH2);
124352
+ const manifestPath2 = join70(projectDir, STUDIO_MANUAL_EDITS_PATH2);
124190
124353
  if (!existsSync63(manifestPath2)) return "";
124191
124354
  try {
124192
124355
  return readFileSync37(manifestPath2, "utf-8");
@@ -124293,7 +124456,7 @@ async function loadPreviewServerBuildSignature() {
124293
124456
  ]);
124294
124457
  }
124295
124458
  function rewriteWrittenToHostViewport(projectDir, written) {
124296
- const indexPath2 = join69(projectDir, "index.html");
124459
+ const indexPath2 = join70(projectDir, "index.html");
124297
124460
  if (!existsSync63(indexPath2)) return;
124298
124461
  const indexHtml = readFileSync37(indexPath2, "utf-8");
124299
124462
  const hostW = indexHtml.match(/data-width="(\d+)"/)?.[1];
@@ -124358,8 +124521,8 @@ function createStudioServer(options) {
124358
124521
  const { injectDeterministicFontFaces: injectDeterministicFontFaces2 } = await Promise.resolve().then(() => (init_deterministicFonts(), deterministicFonts_exports));
124359
124522
  const { prepareAnimatedGifInputs: prepareAnimatedGifInputs2 } = await Promise.resolve().then(() => (init_animatedGifPrep(), animatedGifPrep_exports));
124360
124523
  const { downloadToTemp: downloadToTemp2 } = await Promise.resolve().then(() => (init_urlDownloader2(), urlDownloader_exports));
124361
- const gifOutputDir = join69(project2.dir, ".hyperframes", "prepared-assets", "gif");
124362
- const gifDownloadDir = join69(project2.dir, ".hyperframes", "prepared-assets", "downloads");
124524
+ const gifOutputDir = join70(project2.dir, ".hyperframes", "prepared-assets", "gif");
124525
+ const gifDownloadDir = join70(project2.dir, ".hyperframes", "prepared-assets", "downloads");
124363
124526
  const prepared = await prepareAnimatedGifInputs2(html, {
124364
124527
  projectDir: project2.dir,
124365
124528
  downloadDir: gifDownloadDir,
@@ -124380,7 +124543,7 @@ function createStudioServer(options) {
124380
124543
  return await lintHyperframeHtml2(html, opts);
124381
124544
  },
124382
124545
  runtimeUrl: "/api/runtime.js",
124383
- rendersDir: () => join69(projectDir, "renders"),
124546
+ rendersDir: () => join70(projectDir, "renders"),
124384
124547
  startRender(opts) {
124385
124548
  const abortController = new AbortController();
124386
124549
  const state = {
@@ -124766,7 +124929,7 @@ import {
124766
124929
  symlinkSync as symlinkSync3,
124767
124930
  unlinkSync as unlinkSync6
124768
124931
  } from "fs";
124769
- import { resolve as resolve36, dirname as dirname29, basename as basename11, join as join70 } from "path";
124932
+ import { resolve as resolve36, dirname as dirname29, basename as basename11, join as join71 } from "path";
124770
124933
  import { fileURLToPath as fileURLToPath8 } from "url";
124771
124934
  import { createRequire as createRequire2 } from "module";
124772
124935
  function previewBaseUrl(port, host = "127.0.0.1") {
@@ -125052,7 +125215,7 @@ function compactSelectionPayload(selection) {
125052
125215
  };
125053
125216
  }
125054
125217
  function studioLandingSearch(projectDir) {
125055
- const storyboardPath = join70(projectDir, STORYBOARD_FILENAME);
125218
+ const storyboardPath = join71(projectDir, STORYBOARD_FILENAME);
125056
125219
  if (!existsSync64(storyboardPath)) return "";
125057
125220
  let frames;
125058
125221
  try {
@@ -125062,7 +125225,7 @@ function studioLandingSearch(projectDir) {
125062
125225
  }
125063
125226
  if (frames.some((f3) => f3.status === "built")) return "?view=storyboard";
125064
125227
  const srcs = frames.map((f3) => f3.src).filter((s2) => typeof s2 === "string" && s2.length > 0);
125065
- const planning = frames.length > 0 && frames.every((f3) => f3.status === "outline") && srcs.length > 0 && !srcs.some((s2) => existsSync64(join70(projectDir, s2)));
125228
+ const planning = frames.length > 0 && frames.every((f3) => f3.status === "outline") && srcs.length > 0 && !srcs.some((s2) => existsSync64(join71(projectDir, s2)));
125066
125229
  return planning ? "?view=storyboard" : "";
125067
125230
  }
125068
125231
  function studioDeepLink(url, projectName, projectDir) {
@@ -125090,7 +125253,7 @@ function printStudioSummary(projectName, url, opts = {}) {
125090
125253
  console.log();
125091
125254
  }
125092
125255
  function linkProjectIntoStudioData(dir, projectsDir, projectName) {
125093
- const symlinkPath = join70(projectsDir, projectName);
125256
+ const symlinkPath = join71(projectsDir, projectName);
125094
125257
  mkdirSync35(projectsDir, { recursive: true });
125095
125258
  let createdSymlink = false;
125096
125259
  if (dir !== symlinkPath) {
@@ -125153,13 +125316,13 @@ function attachStudioReadyHandler(child, spinner, projectName, projectDir, optio
125153
125316
  async function runDevMode(dir, options) {
125154
125317
  const thisFile = fileURLToPath8(import.meta.url);
125155
125318
  const repoRoot2 = resolve36(dirname29(thisFile), "..", "..", "..", "..");
125156
- const projectsDir = join70(repoRoot2, "packages", "studio", "data", "projects");
125319
+ const projectsDir = join71(repoRoot2, "packages", "studio", "data", "projects");
125157
125320
  const pName = options?.projectName ?? basename11(dir);
125158
125321
  const { symlinkPath, createdSymlink } = linkProjectIntoStudioData(dir, projectsDir, pName);
125159
125322
  ge(c.bold("hyperframes preview"));
125160
125323
  const s2 = ft();
125161
125324
  s2.start("Starting studio...");
125162
- const studioPkgDir = join70(repoRoot2, "packages", "studio");
125325
+ const studioPkgDir = join71(repoRoot2, "packages", "studio");
125163
125326
  const child = spawn12("bun", ["run", "dev"], {
125164
125327
  cwd: studioPkgDir,
125165
125328
  stdio: ["ignore", "pipe", "pipe"],
@@ -125172,7 +125335,7 @@ async function runDevMode(dir, options) {
125172
125335
  }
125173
125336
  function hasLocalStudio(dir) {
125174
125337
  try {
125175
- const req = createRequire2(join70(dir, "package.json"));
125338
+ const req = createRequire2(join71(dir, "package.json"));
125176
125339
  req.resolve("@hyperframes/studio/package.json");
125177
125340
  return true;
125178
125341
  } catch {
@@ -125180,10 +125343,10 @@ function hasLocalStudio(dir) {
125180
125343
  }
125181
125344
  }
125182
125345
  async function runLocalStudioMode(dir, options) {
125183
- const req = createRequire2(join70(dir, "package.json"));
125346
+ const req = createRequire2(join71(dir, "package.json"));
125184
125347
  const studioPkgPath = dirname29(req.resolve("@hyperframes/studio/package.json"));
125185
125348
  const pName = options?.projectName ?? basename11(dir);
125186
- const projectsDir = join70(studioPkgPath, "data", "projects");
125349
+ const projectsDir = join71(studioPkgPath, "data", "projects");
125187
125350
  const { symlinkPath, createdSymlink } = linkProjectIntoStudioData(dir, projectsDir, pName);
125188
125351
  ge(c.bold("hyperframes preview") + c.dim(" (local studio)"));
125189
125352
  const s2 = ft();
@@ -125672,7 +125835,7 @@ import {
125672
125835
  readFileSync as readFileSync39,
125673
125836
  readdirSync as readdirSync24
125674
125837
  } from "fs";
125675
- import { resolve as resolve37, basename as basename12, join as join71, dirname as dirname30 } from "path";
125838
+ import { resolve as resolve37, basename as basename12, join as join73, dirname as dirname30 } from "path";
125676
125839
  import { fileURLToPath as fileURLToPath9 } from "url";
125677
125840
  import { execFileSync as execFileSync8, spawn as spawn13 } from "child_process";
125678
125841
  function resolveVideoDurationSeconds({
@@ -125822,7 +125985,7 @@ function listHtmlFiles(dir) {
125822
125985
  const ignoredDirs = /* @__PURE__ */ new Set([".git", "dist", "node_modules"]);
125823
125986
  function walk(currentDir) {
125824
125987
  for (const entry of readdirSync24(currentDir, { withFileTypes: true })) {
125825
- const entryPath = join71(currentDir, entry.name);
125988
+ const entryPath = join73(currentDir, entry.name);
125826
125989
  if (entry.isDirectory()) {
125827
125990
  if (!ignoredDirs.has(entry.name)) walk(entryPath);
125828
125991
  continue;
@@ -125867,7 +126030,7 @@ function writeTailwindSupport(destDir) {
125867
126030
  }
125868
126031
  }
125869
126032
  function patchVideoSrc(dir, videoFilename, durationSeconds) {
125870
- const htmlFiles = readdirSync24(dir, { withFileTypes: true, recursive: true }).filter((e3) => e3.isFile() && e3.name.endsWith(".html")).map((e3) => join71(e3.parentPath, e3.name));
126033
+ const htmlFiles = readdirSync24(dir, { withFileTypes: true, recursive: true }).filter((e3) => e3.isFile() && e3.name.endsWith(".html")).map((e3) => join73(e3.parentPath, e3.name));
125871
126034
  for (const file of htmlFiles) {
125872
126035
  let content = readFileSync39(file, "utf-8");
125873
126036
  if (videoFilename) {
@@ -126022,7 +126185,7 @@ function applyResolutionPreset(destDir, resolution) {
126022
126185
  async function scaffoldProject(destDir, name, templateId, localVideoName, durationSeconds, tailwind = false, resolution) {
126023
126186
  mkdirSync36(destDir, { recursive: true });
126024
126187
  const templateDir = getStaticTemplateDir(templateId);
126025
- if (existsSync65(join71(templateDir, "index.html"))) {
126188
+ if (existsSync65(join73(templateDir, "index.html"))) {
126026
126189
  cpSync5(templateDir, destDir, { recursive: true });
126027
126190
  } else {
126028
126191
  await fetchRemoteTemplate(templateId, destDir);
@@ -126051,7 +126214,7 @@ async function scaffoldProject(destDir, name, templateId, localVideoName, durati
126051
126214
  const sharedDir = getSharedTemplateDir();
126052
126215
  if (existsSync65(sharedDir)) {
126053
126216
  for (const entry of readdirSync24(sharedDir, { withFileTypes: true })) {
126054
- const src = join71(sharedDir, entry.name);
126217
+ const src = join73(sharedDir, entry.name);
126055
126218
  const dest = resolve37(destDir, entry.name);
126056
126219
  if (entry.isFile() || entry.isSymbolicLink()) {
126057
126220
  copyFileSync7(src, dest);
@@ -127888,14 +128051,14 @@ var init_client2 = __esm({
127888
128051
 
127889
128052
  // src/auth/paths.ts
127890
128053
  import { homedir as homedir15 } from "os";
127891
- import { join as join73 } from "path";
128054
+ import { join as join74 } from "path";
127892
128055
  function configDir() {
127893
128056
  const override = process.env["HEYGEN_CONFIG_DIR"];
127894
128057
  if (override && override.length > 0) return override;
127895
- return join73(homedir15(), ".heygen");
128058
+ return join74(homedir15(), ".heygen");
127896
128059
  }
127897
128060
  function credentialPath() {
127898
- return join73(configDir(), CREDENTIAL_FILENAME);
128061
+ return join74(configDir(), CREDENTIAL_FILENAME);
127899
128062
  }
127900
128063
  var CREDENTIAL_FILENAME;
127901
128064
  var init_paths2 = __esm({
@@ -128712,7 +128875,7 @@ var init_auth = __esm({
128712
128875
  import { randomUUID as randomUUID8 } from "crypto";
128713
128876
  import { existsSync as existsSync70, mkdirSync as mkdirSync37, readFileSync as readFileSync43, writeFileSync as writeFileSync27 } from "fs";
128714
128877
  import { homedir as homedir16 } from "os";
128715
- import { join as join74, resolve as resolve43 } from "path";
128878
+ import { join as join75, resolve as resolve43 } from "path";
128716
128879
  function readJsonRecord(path2) {
128717
128880
  try {
128718
128881
  if (!existsSync70(path2)) return null;
@@ -128766,7 +128929,7 @@ function ensureProjectId(absDir) {
128766
128929
  return projectId;
128767
128930
  }
128768
128931
  function teamProjectPath(projectDir) {
128769
- return join74(resolve43(projectDir), TEAM_PROJECT_DIR, TEAM_PROJECT_FILE);
128932
+ return join75(resolve43(projectDir), TEAM_PROJECT_DIR, TEAM_PROJECT_FILE);
128770
128933
  }
128771
128934
  function readTeamProject(projectDir) {
128772
128935
  const record = readJsonRecord(teamProjectPath(projectDir));
@@ -128780,7 +128943,7 @@ function writeTeamProject(projectDir, team) {
128780
128943
  projectId: team.projectId,
128781
128944
  ...team.spaceId ? { spaceId: team.spaceId } : {}
128782
128945
  };
128783
- mkdirSync37(join74(resolve43(projectDir), TEAM_PROJECT_DIR), { recursive: true });
128946
+ mkdirSync37(join75(resolve43(projectDir), TEAM_PROJECT_DIR), { recursive: true });
128784
128947
  writeFileSync27(file, `${JSON.stringify(body, null, 2)}
128785
128948
  `);
128786
128949
  return file;
@@ -128789,15 +128952,15 @@ var CONFIG_DIR2, PROJECTS_FILE, TEAM_PROJECT_DIR, TEAM_PROJECT_FILE;
128789
128952
  var init_projectLink = __esm({
128790
128953
  "src/utils/projectLink.ts"() {
128791
128954
  "use strict";
128792
- CONFIG_DIR2 = join74(homedir16(), ".hyperframes");
128793
- PROJECTS_FILE = join74(CONFIG_DIR2, "projects.json");
128955
+ CONFIG_DIR2 = join75(homedir16(), ".hyperframes");
128956
+ PROJECTS_FILE = join75(CONFIG_DIR2, "projects.json");
128794
128957
  TEAM_PROJECT_DIR = ".hyperframes";
128795
128958
  TEAM_PROJECT_FILE = "project.json";
128796
128959
  }
128797
128960
  });
128798
128961
 
128799
128962
  // src/utils/publishProject.ts
128800
- import { basename as basename13, dirname as dirname34, join as join75, posix as posix5, relative as relative16, resolve as resolve44 } from "path";
128963
+ import { basename as basename13, dirname as dirname34, join as join76, posix as posix5, relative as relative16, resolve as resolve44 } from "path";
128801
128964
  import { existsSync as existsSync71, readdirSync as readdirSync25, readFileSync as readFileSync44, statSync as statSync24 } from "fs";
128802
128965
  import AdmZip from "adm-zip";
128803
128966
  import ignore2 from "ignore";
@@ -128903,7 +129066,7 @@ function shouldIgnoreSegment(segment) {
128903
129066
  }
128904
129067
  function createProjectIgnore(rootDir) {
128905
129068
  const matcher = ignore2().add(DEFAULT_PROJECT_IGNORE);
128906
- const ignorePath = join75(rootDir, HYPERFRAMES_IGNORE_FILE);
129069
+ const ignorePath = join76(rootDir, HYPERFRAMES_IGNORE_FILE);
128907
129070
  if (existsSync71(ignorePath)) {
128908
129071
  matcher.add(readFileSync44(ignorePath, "utf-8"));
128909
129072
  }
@@ -128912,7 +129075,7 @@ function createProjectIgnore(rootDir) {
128912
129075
  function collectProjectFiles(rootDir, currentDir, paths, matcher) {
128913
129076
  for (const entry of readdirSync25(currentDir, { withFileTypes: true })) {
128914
129077
  if (shouldIgnoreSegment(entry.name)) continue;
128915
- const absolutePath = join75(currentDir, entry.name);
129078
+ const absolutePath = join76(currentDir, entry.name);
128916
129079
  const relativePath = relative16(rootDir, absolutePath).replaceAll("\\", "/");
128917
129080
  if (!relativePath) continue;
128918
129081
  if (entry.isDirectory()) {
@@ -129053,7 +129216,7 @@ function buildPublishFileMap(projectDir) {
129053
129216
  }
129054
129217
  const fileContents = /* @__PURE__ */ new Map();
129055
129218
  for (const filePath of filePaths) {
129056
- fileContents.set(filePath, readFileSync44(join75(absProjectDir, filePath)));
129219
+ fileContents.set(filePath, readFileSync44(join76(absProjectDir, filePath)));
129057
129220
  }
129058
129221
  localizeExternalAssets(absProjectDir, fileContents);
129059
129222
  return fileContents;
@@ -129219,7 +129382,7 @@ var init_publishProject = __esm({
129219
129382
  });
129220
129383
 
129221
129384
  // src/utils/publishProxyBake.ts
129222
- import { readFile as readFile3 } from "fs/promises";
129385
+ import { readFile as readFile4 } from "fs/promises";
129223
129386
  import { basename as basename14, dirname as dirname35, resolve as resolve45 } from "path";
129224
129387
  function emptyManifest() {
129225
129388
  return { proxied: [], skippedAlpha: [], failed: [] };
@@ -129249,7 +129412,7 @@ async function bakeMediaProxies(projectDir, fileContents) {
129249
129412
  TRANSCODE_TIMEOUT_MS
129250
129413
  );
129251
129414
  const archivePath = `${PROXY_ARCHIVE_PREFIX}/${basename14(proxyPath)}`;
129252
- fileContents.set(archivePath, await readFile3(proxyPath));
129415
+ fileContents.set(archivePath, await readFile4(proxyPath));
129253
129416
  proxyByAbsolutePath.set(absoluteSourcePath, archivePath);
129254
129417
  manifest.proxied.push(pathname);
129255
129418
  } catch (err) {
@@ -129316,7 +129479,7 @@ __export(publish_exports, {
129316
129479
  examples: () => examples8,
129317
129480
  parseUpdateTarget: () => parseUpdateTarget
129318
129481
  });
129319
- import { join as join76, relative as relative17, resolve as resolve46 } from "path";
129482
+ import { join as join77, relative as relative17, resolve as resolve46 } from "path";
129320
129483
  import { existsSync as existsSync73 } from "fs";
129321
129484
  function parseUpdateTarget(value) {
129322
129485
  const trimmed = value.trim();
@@ -129387,7 +129550,7 @@ var init_publish = __esm({
129387
129550
  async run({ args }) {
129388
129551
  const rawArg = args.dir;
129389
129552
  const dir = resolve46(rawArg ?? ".");
129390
- const indexPath2 = join76(dir, "index.html");
129553
+ const indexPath2 = join77(dir, "index.html");
129391
129554
  if (existsSync73(indexPath2)) {
129392
129555
  const lintResult = await lintProject(dir);
129393
129556
  if (lintResult.totalErrors > 0 || lintResult.totalWarnings > 0) {
@@ -129529,7 +129692,7 @@ var init_publish = __esm({
129529
129692
 
129530
129693
  // src/utils/compositionFps.ts
129531
129694
  import { readFileSync as readFileSync45 } from "fs";
129532
- import { join as join77 } from "path";
129695
+ import { join as join78 } from "path";
129533
129696
  function readCompositionFps(html) {
129534
129697
  let doc;
129535
129698
  try {
@@ -129547,7 +129710,7 @@ function readCompositionFps(html) {
129547
129710
  function readAllowedCompositionFpsFromDir(projectDir, allowed) {
129548
129711
  let html;
129549
129712
  try {
129550
- html = readFileSync45(join77(projectDir, "index.html"), "utf8");
129713
+ html = readFileSync45(join78(projectDir, "index.html"), "utf8");
129551
129714
  } catch {
129552
129715
  return null;
129553
129716
  }
@@ -129734,7 +129897,7 @@ var init_skill = __esm({
129734
129897
 
129735
129898
  // src/commands/render/plan.ts
129736
129899
  import { statSync as statSync25 } from "fs";
129737
- import { dirname as dirname36, join as join78, resolve as resolve48 } from "path";
129900
+ import { dirname as dirname36, join as join79, resolve as resolve48 } from "path";
129738
129901
  function formatFpsParseError(input2, reason) {
129739
129902
  switch (reason) {
129740
129903
  case "empty":
@@ -129903,8 +130066,8 @@ function createRenderPlan(args, now = /* @__PURE__ */ new Date()) {
129903
130066
  const rendersDir = resolve48("renders");
129904
130067
  const ext = FORMAT_EXT[format];
129905
130068
  const timestamp = formatRenderOutputTimestamp(now);
129906
- const batchOutputTemplate = args.output ? args.output : join78(rendersDir, `${project.name}_${timestamp}_{index}${ext}`);
129907
- const outputPath = args.output ? resolve48(args.output) : join78(rendersDir, `${project.name}_${timestamp}${ext}`);
130069
+ const batchOutputTemplate = args.output ? args.output : join79(rendersDir, `${project.name}_${timestamp}_{index}${ext}`);
130070
+ const outputPath = args.output ? resolve48(args.output) : join79(rendersDir, `${project.name}_${timestamp}${ext}`);
129908
130071
  const useDocker = args.docker ?? false;
129909
130072
  const useGpu = args.gpu ?? false;
129910
130073
  const browserGpuMode = resolveBrowserGpuForCli(useDocker, args["browser-gpu"]);
@@ -130113,7 +130276,7 @@ var init_dom = __esm({
130113
130276
  // src/utils/variables.ts
130114
130277
  import { readFileSync as readFileSync48 } from "fs";
130115
130278
  import { resolve as resolve49 } from "path";
130116
- function parseVariablesArg(inline, filePath, readFile4 = (p2) => readFileSync48(resolve49(p2), "utf8")) {
130279
+ function parseVariablesArg(inline, filePath, readFile5 = (p2) => readFileSync48(resolve49(p2), "utf8")) {
130117
130280
  if (inline != null && filePath != null) {
130118
130281
  return { ok: false, error: { kind: "conflict" } };
130119
130282
  }
@@ -130124,7 +130287,7 @@ function parseVariablesArg(inline, filePath, readFile4 = (p2) => readFileSync48(
130124
130287
  source = "inline";
130125
130288
  } else if (filePath != null) {
130126
130289
  try {
130127
- raw = readFile4(filePath);
130290
+ raw = readFile5(filePath);
130128
130291
  source = "file";
130129
130292
  } catch (error) {
130130
130293
  return {
@@ -130252,7 +130415,7 @@ __export(batchRender_exports, {
130252
130415
  runBatchRender: () => runBatchRender
130253
130416
  });
130254
130417
  import { mkdirSync as mkdirSync38, readFileSync as readFileSync49, writeFileSync as writeFileSync28 } from "fs";
130255
- import { dirname as dirname37, join as join79, resolve as resolve50, sep as sep11 } from "path";
130418
+ import { dirname as dirname37, join as join80, resolve as resolve50, sep as sep11 } from "path";
130256
130419
  function isRecord5(value) {
130257
130420
  return value !== null && typeof value === "object" && !Array.isArray(value);
130258
130421
  }
@@ -130393,7 +130556,7 @@ function prepareBatchRender(options) {
130393
130556
  variables,
130394
130557
  outputPath: resolve50(resolveOutputTemplate(options.outputTemplate, variables, index))
130395
130558
  }));
130396
- const manifestPath2 = join79(
130559
+ const manifestPath2 = join80(
130397
130560
  commonOutputDirectory(rows.map((row) => row.outputPath)),
130398
130561
  "manifest.json"
130399
130562
  );
@@ -131376,8 +131539,8 @@ __export(render_exports, {
131376
131539
  resolveBrowserGpuForCli: () => resolveBrowserGpuForCli
131377
131540
  });
131378
131541
  import { mkdirSync as mkdirSync40, readdirSync as readdirSync26, readFileSync as readFileSync51, statSync as statSync26, writeFileSync as writeFileSync29, rmSync as rmSync21 } from "fs";
131379
- import { freemem as freemem5, tmpdir as tmpdir9 } from "os";
131380
- import { resolve as resolve51, dirname as dirname38, join as join80, basename as basename15 } from "path";
131542
+ import { freemem as freemem5, tmpdir as tmpdir10 } from "os";
131543
+ import { resolve as resolve51, dirname as dirname38, join as join81, basename as basename15 } from "path";
131381
131544
  import { execFileSync as execFileSync11, spawn as spawn14 } from "child_process";
131382
131545
  async function readCompositionDimensions(compositionHtml) {
131383
131546
  try {
@@ -131443,9 +131606,9 @@ function ensureDockerImage(version2, platform10, quiet) {
131443
131606
  }
131444
131607
  if (!quiet) console.log(c.dim(` Building Docker image: ${tag} (${platform10})...`));
131445
131608
  const dockerfilePath = resolveDockerfilePath();
131446
- const tmpDir = join80(tmpdir9(), `hyperframes-docker-${Date.now()}`);
131609
+ const tmpDir = join81(tmpdir10(), `hyperframes-docker-${Date.now()}`);
131447
131610
  mkdirSync40(tmpDir, { recursive: true });
131448
- writeFileSync29(join80(tmpDir, "Dockerfile"), readFileSync51(dockerfilePath));
131611
+ writeFileSync29(join81(tmpDir, "Dockerfile"), readFileSync51(dockerfilePath));
131449
131612
  const targetArch = platform10 === "linux/arm64" ? "arm64" : "amd64";
131450
131613
  try {
131451
131614
  execFileSync11(
@@ -131602,7 +131765,7 @@ async function renderLocal(projectDir, outputPath, options) {
131602
131765
  }
131603
131766
  const preflight = await runEnvironmentChecks({
131604
131767
  projectDir,
131605
- diskPaths: [tmpdir9(), dirname38(outputPath)],
131768
+ diskPaths: [tmpdir10(), dirname38(outputPath)],
131606
131769
  browserPath: options.browserPath,
131607
131770
  includeBrowser: true,
131608
131771
  includeDisk: true,
@@ -132054,7 +132217,7 @@ function printRenderComplete(outputPath, elapsedMs, quiet, outputDurationSeconds
132054
132217
  for (const entry of readdirSync26(outputPath, { withFileTypes: true })) {
132055
132218
  if (!entry.isFile()) continue;
132056
132219
  try {
132057
- total += statSync26(join80(outputPath, entry.name)).size;
132220
+ total += statSync26(join81(outputPath, entry.name)).size;
132058
132221
  } catch {
132059
132222
  }
132060
132223
  }
@@ -133034,7 +133197,7 @@ var init_motionAudit = __esm({
133034
133197
 
133035
133198
  // src/utils/motionSpec.ts
133036
133199
  import { existsSync as existsSync76, readFileSync as readFileSync53, readdirSync as readdirSync27 } from "fs";
133037
- import { basename as basename16, join as join81 } from "path";
133200
+ import { basename as basename16, join as join83 } from "path";
133038
133201
  function isObject2(value) {
133039
133202
  return typeof value === "object" && value !== null && !Array.isArray(value);
133040
133203
  }
@@ -133080,7 +133243,7 @@ function findMotionSpec(projectDir) {
133080
133243
  const entries2 = readdirSync27(projectDir);
133081
133244
  const sidecars = entries2.filter((name) => name.endsWith(".motion.json")).sort();
133082
133245
  if (!sidecars[0]) return null;
133083
- if (sidecars.length === 1) return join81(projectDir, sidecars[0]);
133246
+ if (sidecars.length === 1) return join83(projectDir, sidecars[0]);
133084
133247
  const htmlBases = new Set(
133085
133248
  entries2.filter((name) => name.endsWith(".html")).map((name) => basename16(name, ".html"))
133086
133249
  );
@@ -133090,7 +133253,7 @@ function findMotionSpec(projectDir) {
133090
133253
  `ambiguous motion sidecars in ${projectDir}: ${matched.join(", ")} each match a composition \u2014 remove the sidecars you do not need, or use one composition per project`
133091
133254
  );
133092
133255
  }
133093
- return join81(projectDir, matched[0] ?? sidecars[0]);
133256
+ return join83(projectDir, matched[0] ?? sidecars[0]);
133094
133257
  }
133095
133258
  function readMotionSpec(path2) {
133096
133259
  let raw;
@@ -133466,7 +133629,7 @@ __export(layout_exports, {
133466
133629
  parseAt: () => parseAt
133467
133630
  });
133468
133631
  import { existsSync as existsSync77, readFileSync as readFileSync54 } from "fs";
133469
- import { dirname as dirname39, join as join83 } from "path";
133632
+ import { dirname as dirname39, join as join84 } from "path";
133470
133633
  import { fileURLToPath as fileURLToPath11 } from "url";
133471
133634
  function buildMotionSampleTimes(duration) {
133472
133635
  if (!Number.isFinite(duration) || duration <= 0) return [];
@@ -133614,7 +133777,7 @@ async function runLayoutAudit(projectDir, opts) {
133614
133777
  }
133615
133778
  }
133616
133779
  function loadBrowserScript(name) {
133617
- const candidates = [join83(__dirname2, name), join83(__dirname2, "commands", name)];
133780
+ const candidates = [join84(__dirname2, name), join84(__dirname2, "commands", name)];
133618
133781
  for (const candidate of candidates) {
133619
133782
  if (existsSync77(candidate)) return readFileSync54(candidate, "utf-8");
133620
133783
  }
@@ -134014,8 +134177,8 @@ __export(validate_exports, {
134014
134177
  shouldIgnoreRequestFailure: () => shouldIgnoreRequestFailure
134015
134178
  });
134016
134179
  import { existsSync as existsSync78, mkdtempSync as mkdtempSync7, readFileSync as readFileSync55, rmSync as rmSync23 } from "fs";
134017
- import { tmpdir as tmpdir10 } from "os";
134018
- import { join as join84, dirname as dirname40 } from "path";
134180
+ import { tmpdir as tmpdir11 } from "os";
134181
+ import { join as join85, dirname as dirname40 } from "path";
134019
134182
  import { fileURLToPath as fileURLToPath12 } from "url";
134020
134183
  function resolveNavigationTimeoutMs(optTimeout) {
134021
134184
  return Math.max(NAV_TIMEOUT_FLOOR_MS, optTimeout ?? 0);
@@ -134164,8 +134327,8 @@ async function runContrastAudit(page) {
134164
134327
  }
134165
134328
  function loadContrastAuditScript() {
134166
134329
  const candidates = [
134167
- join84(__dirname3, "contrast-audit.browser.js"),
134168
- join84(__dirname3, "commands", "contrast-audit.browser.js")
134330
+ join85(__dirname3, "contrast-audit.browser.js"),
134331
+ join85(__dirname3, "commands", "contrast-audit.browser.js")
134169
134332
  ];
134170
134333
  for (const candidate of candidates) {
134171
134334
  if (existsSync78(candidate)) return readFileSync55(candidate, "utf-8");
@@ -134180,7 +134343,7 @@ async function localizeRemoteAssets(html) {
134180
134343
  try {
134181
134344
  const { loadProducer: loadProducer2 } = await Promise.resolve().then(() => (init_producer(), producer_exports));
134182
134345
  const { localizeRemoteMediaSources: localizeRemoteMediaSources2, localizeRemoteImageSources: localizeRemoteImageSources2, localizeRemoteFontFaces: localizeRemoteFontFaces2 } = await loadProducer2();
134183
- dir = mkdtempSync7(join84(tmpdir10(), "hf-validate-assets-"));
134346
+ dir = mkdtempSync7(join85(tmpdir11(), "hf-validate-assets-"));
134184
134347
  const assetDir = dir;
134185
134348
  const media = await localizeRemoteMediaSources2(html, assetDir);
134186
134349
  const images = await localizeRemoteImageSources2(media.html, assetDir);
@@ -134492,7 +134655,7 @@ __export(checkBrowser_exports, {
134492
134655
  runBrowserCheck: () => runBrowserCheck
134493
134656
  });
134494
134657
  import { mkdirSync as mkdirSync41, writeFileSync as writeFileSync30 } from "fs";
134495
- import { join as join85, resolve as resolve53 } from "path";
134658
+ import { join as join86, resolve as resolve53 } from "path";
134496
134659
  async function preResolveHostileMediaProxies(projectDir, html, autoProxyOverride) {
134497
134660
  if (!resolveAutoProxy(projectDir, autoProxyOverride)) return;
134498
134661
  let codecMap;
@@ -134590,7 +134753,7 @@ async function captureFindingCrops(project, options, requests) {
134590
134753
  chromeBrowser = session.browser;
134591
134754
  const page = session.page;
134592
134755
  await waitForPreferredSeekTarget(page);
134593
- const snapshotDir = join85(project.dir, "snapshots");
134756
+ const snapshotDir = join86(project.dir, "snapshots");
134594
134757
  mkdirSync41(snapshotDir, { recursive: true });
134595
134758
  for (const request of requests) {
134596
134759
  await seekCompositionTimeline(page, request.time, AUDIT_SEEK_OPTIONS);
@@ -134600,8 +134763,8 @@ async function captureFindingCrops(project, options, requests) {
134600
134763
  }));
134601
134764
  const region = padCropRegion(request.bbox, canvas, DEFAULT_ZOOM_PADDING_PX);
134602
134765
  const buffer = await captureRegionCrop(page, region, DEFAULT_ZOOM_SCALE);
134603
- writeFileSync30(join85(snapshotDir, request.filename), buffer);
134604
- written.push(join85("snapshots", request.filename));
134766
+ writeFileSync30(join86(snapshotDir, request.filename), buffer);
134767
+ written.push(join86("snapshots", request.filename));
134605
134768
  }
134606
134769
  return written;
134607
134770
  } finally {
@@ -135323,7 +135486,7 @@ var init_checkBrowser = __esm({
135323
135486
 
135324
135487
  // src/utils/checkPipeline.ts
135325
135488
  import { mkdirSync as mkdirSync43, writeFileSync as writeFileSync31 } from "fs";
135326
- import { join as join86, relative as relative19 } from "path";
135489
+ import { join as join87, relative as relative19 } from "path";
135327
135490
  function selectContrastTimes(grid) {
135328
135491
  if (grid.length <= 5) return [...grid];
135329
135492
  return Array.from({ length: 5 }, (_, index) => {
@@ -136027,12 +136190,12 @@ async function runBrowserCheck2(project, options, motion) {
136027
136190
  return module.runBrowserCheck(project, options, motion, runAuditGrid);
136028
136191
  }
136029
136192
  async function writeSnapshot(projectDir, index, time, pngBase64) {
136030
- const snapshotDir = join86(projectDir, "snapshots");
136193
+ const snapshotDir = join87(projectDir, "snapshots");
136031
136194
  mkdirSync43(snapshotDir, { recursive: true });
136032
136195
  const filename = `frame-${String(index).padStart(2, "0")}-at-${time.toFixed(1)}s.png`;
136033
- const path2 = join86(snapshotDir, filename);
136196
+ const path2 = join87(snapshotDir, filename);
136034
136197
  writeFileSync31(path2, Buffer.from(pngBase64, "base64"));
136035
- return join86("snapshots", filename);
136198
+ return join87("snapshots", filename);
136036
136199
  }
136037
136200
  async function captureFindingCrops2(project, options, requests) {
136038
136201
  const module = await Promise.resolve().then(() => (init_checkBrowser(), checkBrowser_exports));
@@ -136549,16 +136712,16 @@ var init_beats = __esm({
136549
136712
  // src/beats/headlessAnalyzer.ts
136550
136713
  import { existsSync as existsSync79, readFileSync as readFileSync56 } from "fs";
136551
136714
  import { createRequire as createRequire3 } from "module";
136552
- import { dirname as dirname41, join as join87 } from "path";
136715
+ import { dirname as dirname41, join as join88 } from "path";
136553
136716
  import { fileURLToPath as fileURLToPath13 } from "url";
136554
136717
  function findPrebuiltBundle() {
136555
136718
  const here = dirname41(fileURLToPath13(import.meta.url));
136556
136719
  const candidates = [
136557
- join87(here, "beat-analyzer.global.js"),
136720
+ join88(here, "beat-analyzer.global.js"),
136558
136721
  // dist root (tsup-bundled cli)
136559
- join87(here, "../beat-analyzer.global.js"),
136722
+ join88(here, "../beat-analyzer.global.js"),
136560
136723
  // dist/beats → dist
136561
- join87(here, "../dist/beat-analyzer.global.js")
136724
+ join88(here, "../dist/beat-analyzer.global.js")
136562
136725
  ];
136563
136726
  for (const p2 of candidates) {
136564
136727
  if (existsSync79(p2)) return p2;
@@ -136568,7 +136731,7 @@ function findPrebuiltBundle() {
136568
136731
  async function buildFromCoreSource() {
136569
136732
  const esbuild = await import("esbuild");
136570
136733
  const coreRoot = dirname41(require2.resolve("@hyperframes/core/package.json"));
136571
- const entry = join87(coreRoot, "src/beats/beatDetection.ts");
136734
+ const entry = join88(coreRoot, "src/beats/beatDetection.ts");
136572
136735
  const result = await esbuild.build({
136573
136736
  stdin: {
136574
136737
  contents: `import { analyzeMusicFromBuffer } from ${JSON.stringify(entry)};
@@ -136669,7 +136832,7 @@ __export(beats_exports, {
136669
136832
  examples: () => examples13
136670
136833
  });
136671
136834
  import { existsSync as existsSync80, readFileSync as readFileSync57, mkdirSync as mkdirSync44, writeFileSync as writeFileSync33 } from "fs";
136672
- import { resolve as resolve54, join as join88, dirname as dirname42 } from "path";
136835
+ import { resolve as resolve54, join as join89, dirname as dirname42 } from "path";
136673
136836
  function fail(message) {
136674
136837
  console.error(c.error(message));
136675
136838
  failCommand();
@@ -136740,7 +136903,7 @@ var init_beats2 = __esm({
136740
136903
  if (result.beatTimes.length === 0) {
136741
136904
  fail(`No beats detected in ${rel} \u2014 nothing written. (Track may be silent/ambient.)`);
136742
136905
  }
136743
- const outPath = join88(project.dir, "beats", `${rel}.json`);
136906
+ const outPath = join89(project.dir, "beats", `${rel}.json`);
136744
136907
  mkdirSync44(dirname42(outPath), { recursive: true });
136745
136908
  writeFileSync33(outPath, serializeBeats(result.beatTimes, result.beatStrengths, rel));
136746
136909
  report(`beats/${rel}.json`, result, Boolean(args.json));
@@ -139031,7 +139194,7 @@ __export(keyframes_exports, {
139031
139194
  surfaceComposition: () => surfaceComposition
139032
139195
  });
139033
139196
  import { existsSync as existsSync81, readFileSync as readFileSync58, statSync as statSync28 } from "fs";
139034
- import { resolve as resolve55, dirname as dirname44, basename as basename17, join as join89, relative as relative20, sep as sep12 } from "path";
139197
+ import { resolve as resolve55, dirname as dirname44, basename as basename17, join as join90, relative as relative20, sep as sep12 } from "path";
139035
139198
  function queryIncludingTemplates(html, selector) {
139036
139199
  const doc = new DOMParser().parseFromString(html, "text/html");
139037
139200
  const roots = [doc];
@@ -139553,8 +139716,8 @@ function findProjectRoot(entryPath) {
139553
139716
  const entryDir = dirname44(entryPath);
139554
139717
  let candidate = entryDir;
139555
139718
  for (; ; ) {
139556
- if (existsSync81(join89(candidate, "index.html"))) return candidate;
139557
- if (existsSync81(join89(candidate, ".git"))) return entryDir;
139719
+ if (existsSync81(join90(candidate, "index.html"))) return candidate;
139720
+ if (existsSync81(join90(candidate, ".git"))) return entryDir;
139558
139721
  const parent = dirname44(candidate);
139559
139722
  if (parent === candidate) return entryDir;
139560
139723
  candidate = parent;
@@ -139745,7 +139908,7 @@ __export(info_exports, {
139745
139908
  orientation: () => orientation
139746
139909
  });
139747
139910
  import { readFileSync as readFileSync59, readdirSync as readdirSync28, statSync as statSync29 } from "fs";
139748
- import { join as join90 } from "path";
139911
+ import { join as join91 } from "path";
139749
139912
  function orientation(width, height) {
139750
139913
  if (width > height) return "landscape";
139751
139914
  if (height > width) return "portrait";
@@ -139759,7 +139922,7 @@ function durationFromHtml(html, fallback) {
139759
139922
  function totalSize(dir) {
139760
139923
  let total = 0;
139761
139924
  for (const entry of readdirSync28(dir, { withFileTypes: true })) {
139762
- const path2 = join90(dir, entry.name);
139925
+ const path2 = join91(dir, entry.name);
139763
139926
  if (entry.isDirectory()) {
139764
139927
  total += totalSize(path2);
139765
139928
  } else {
@@ -140077,7 +140240,7 @@ __export(benchmark_exports, {
140077
140240
  examples: () => examples18
140078
140241
  });
140079
140242
  import { existsSync as existsSync84, statSync as statSync30 } from "fs";
140080
- import { resolve as resolve57, join as join91 } from "path";
140243
+ import { resolve as resolve57, join as join93 } from "path";
140081
140244
  var examples18, FPS_30, FPS_60, DEFAULT_CONFIGS, benchmark_default;
140082
140245
  var init_benchmark = __esm({
140083
140246
  "src/commands/benchmark.ts"() {
@@ -140156,7 +140319,7 @@ var init_benchmark = __esm({
140156
140319
  s2?.start(`Benchmarking ${config.label}...`);
140157
140320
  for (let i2 = 0; i2 < runsPerConfig; i2++) {
140158
140321
  s2?.message(`${config.label} \u2014 run ${i2 + 1}/${runsPerConfig}`);
140159
- const outputPath = join91(
140322
+ const outputPath = join93(
140160
140323
  benchDir,
140161
140324
  `${config.label.replace(/[^a-zA-Z0-9]/g, "_")}_run${i2}.mp4`
140162
140325
  );
@@ -140657,8 +140820,8 @@ var init_remove_background = __esm({
140657
140820
  // src/whisper/parakeet.ts
140658
140821
  import { execFileSync as execFileSync12 } from "child_process";
140659
140822
  import { existsSync as existsSync86, mkdtempSync as mkdtempSync8, readFileSync as readFileSync61, rmSync as rmSync24, writeFileSync as writeFileSync35 } from "fs";
140660
- import { homedir as homedir17, tmpdir as tmpdir11 } from "os";
140661
- import { basename as basename18, extname as extname16, join as join93 } from "path";
140823
+ import { homedir as homedir17, tmpdir as tmpdir12 } from "os";
140824
+ import { basename as basename18, extname as extname16, join as join94 } from "path";
140662
140825
  function isRunnable(bin) {
140663
140826
  try {
140664
140827
  execFileSync12(bin, ["--help"], { stdio: ["ignore", "ignore", "ignore"], timeout: 1e4 });
@@ -140670,7 +140833,7 @@ function isRunnable(bin) {
140670
140833
  function findParakeet() {
140671
140834
  const candidates = [
140672
140835
  process.env.HYPERFRAMES_PARAKEET,
140673
- join93(homedir17(), ".venvs", "parakeet", "bin", "parakeet-mlx")
140836
+ join94(homedir17(), ".venvs", "parakeet", "bin", "parakeet-mlx")
140674
140837
  ].filter((p2) => Boolean(p2));
140675
140838
  for (const path2 of candidates) {
140676
140839
  if (existsSync86(path2) && isRunnable(path2)) return path2;
@@ -140721,20 +140884,20 @@ function transcribeWithParakeet(inputPath, dir, options) {
140721
140884
  }
140722
140885
  const model = options?.model ?? DEFAULT_MODEL3;
140723
140886
  const cached2 = existsSync86(
140724
- join93(homedir17(), ".cache", "huggingface", "hub", `models--${model.replace(/\//g, "--")}`)
140887
+ join94(homedir17(), ".cache", "huggingface", "hub", `models--${model.replace(/\//g, "--")}`)
140725
140888
  );
140726
140889
  options?.onProgress?.(
140727
140890
  cached2 ? "Transcribing with Parakeet..." : "Downloading Parakeet model (first run, ~600MB)..."
140728
140891
  );
140729
- const workDir = mkdtempSync8(join93(tmpdir11(), "hyperframes-parakeet-"));
140892
+ const workDir = mkdtempSync8(join94(tmpdir12(), "hyperframes-parakeet-"));
140730
140893
  try {
140731
140894
  const argv2 = [inputPath, "--model", model, "--output-format", "json", "--output-dir", workDir];
140732
140895
  if (options?.language) argv2.push("--language", options.language);
140733
140896
  execFileSync12(runner, argv2, { stdio: ["ignore", "pipe", "pipe"], timeout: 18e5 });
140734
- const produced = join93(workDir, `${basename18(inputPath, extname16(inputPath))}.json`);
140897
+ const produced = join94(workDir, `${basename18(inputPath, extname16(inputPath))}.json`);
140735
140898
  if (!existsSync86(produced)) throw new Error("Parakeet did not produce output.");
140736
140899
  const words = mergeTokensToWords(JSON.parse(readFileSync61(produced, "utf-8")));
140737
- const transcriptPath = join93(dir, "transcript.json");
140900
+ const transcriptPath = join94(dir, "transcript.json");
140738
140901
  writeFileSync35(transcriptPath, JSON.stringify(words, null, 2));
140739
140902
  const durationSeconds = words.length > 0 ? words[words.length - 1].end : 0;
140740
140903
  return { transcriptPath, wordCount: words.length, durationSeconds, speechOnsetSeconds: null };
@@ -140758,7 +140921,7 @@ __export(transcribe_exports2, {
140758
140921
  examples: () => examples21
140759
140922
  });
140760
140923
  import { existsSync as existsSync87, writeFileSync as writeFileSync36 } from "fs";
140761
- import { resolve as resolve59, join as join94, extname as extname17, dirname as dirname46 } from "path";
140924
+ import { resolve as resolve59, join as join95, extname as extname17, dirname as dirname46 } from "path";
140762
140925
  function parseTimeoutMs(raw, json) {
140763
140926
  const source = raw ?? process.env["HYPERFRAMES_TRANSCRIBE_TIMEOUT_MS"];
140764
140927
  if (source == null || source === "") return void 0;
@@ -140794,7 +140957,7 @@ async function importTranscript(inputPath, dir, json) {
140794
140957
  const { loadTranscript: loadTranscript2, patchCaptionHtml: patchCaptionHtml2 } = await Promise.resolve().then(() => (init_normalize(), normalize_exports));
140795
140958
  const { words, format } = loadTranscript2(inputPath);
140796
140959
  if (words.length === 0) exitNoWords(json);
140797
- const outPath = join94(dir, "transcript.json");
140960
+ const outPath = join95(dir, "transcript.json");
140798
140961
  writeFileSync36(outPath, JSON.stringify(words, null, 2));
140799
140962
  patchCaptionHtml2(dir, words);
140800
140963
  if (json) {
@@ -140812,7 +140975,7 @@ async function exportTranscript(inputPath, dir, to, output, json, preserveCues)
140812
140975
  const { words, format } = loadTranscript2(inputPath);
140813
140976
  if (words.length === 0) exitNoWords(json);
140814
140977
  const preGrouped = preserveCues || format === "srt" || format === "vtt" || void 0;
140815
- const outPath = resolve59(output ?? join94(dir, `transcript.${to}`));
140978
+ const outPath = resolve59(output ?? join95(dir, `transcript.${to}`));
140816
140979
  const content = to === "srt" ? formatSrt2(words, { preGrouped }) : formatVtt2(words, { preGrouped });
140817
140980
  writeFileSync36(outPath, content);
140818
140981
  if (json) {
@@ -141035,7 +141198,7 @@ var init_transcribe2 = __esm({
141035
141198
  // src/tts/manager.ts
141036
141199
  import { existsSync as existsSync88, mkdirSync as mkdirSync46 } from "fs";
141037
141200
  import { homedir as homedir18 } from "os";
141038
- import { join as join95 } from "path";
141201
+ import { join as join96 } from "path";
141039
141202
  function inferLangFromVoiceId(voiceId) {
141040
141203
  const first = voiceId.charAt(0).toLowerCase();
141041
141204
  return VOICE_PREFIX_LANG[first] ?? "en-us";
@@ -141044,7 +141207,7 @@ function isSupportedLang(value) {
141044
141207
  return SUPPORTED_LANGS.includes(value);
141045
141208
  }
141046
141209
  async function ensureModel3(model = DEFAULT_MODEL4, options) {
141047
- const modelPath2 = join95(MODELS_DIR3, `${model}.onnx`);
141210
+ const modelPath2 = join96(MODELS_DIR3, `${model}.onnx`);
141048
141211
  if (existsSync88(modelPath2)) return modelPath2;
141049
141212
  const url = MODEL_URLS2[model];
141050
141213
  if (!url) {
@@ -141061,7 +141224,7 @@ async function ensureModel3(model = DEFAULT_MODEL4, options) {
141061
141224
  return modelPath2;
141062
141225
  }
141063
141226
  async function ensureVoices(options) {
141064
- const voicesPath = join95(VOICES_DIR, "voices-v1.0.bin");
141227
+ const voicesPath = join96(VOICES_DIR, "voices-v1.0.bin");
141065
141228
  if (existsSync88(voicesPath)) return voicesPath;
141066
141229
  mkdirSync46(VOICES_DIR, { recursive: true });
141067
141230
  options?.onProgress?.("Downloading voice data (~27 MB)...");
@@ -141076,9 +141239,9 @@ var init_manager4 = __esm({
141076
141239
  "src/tts/manager.ts"() {
141077
141240
  "use strict";
141078
141241
  init_download();
141079
- CACHE_DIR3 = join95(homedir18(), ".cache", "hyperframes", "tts");
141080
- MODELS_DIR3 = join95(CACHE_DIR3, "models");
141081
- VOICES_DIR = join95(CACHE_DIR3, "voices");
141242
+ CACHE_DIR3 = join96(homedir18(), ".cache", "hyperframes", "tts");
141243
+ MODELS_DIR3 = join96(CACHE_DIR3, "models");
141244
+ VOICES_DIR = join96(CACHE_DIR3, "voices");
141082
141245
  DEFAULT_MODEL4 = "kokoro-v1.0";
141083
141246
  MODEL_URLS2 = {
141084
141247
  "kokoro-v1.0": "https://github.com/thewh1teagle/kokoro-onnx/releases/download/model-files-v1.0/kokoro-v1.0.onnx"
@@ -141208,7 +141371,7 @@ __export(synthesize_exports, {
141208
141371
  });
141209
141372
  import { execFileSync as execFileSync14 } from "child_process";
141210
141373
  import { existsSync as existsSync89, writeFileSync as writeFileSync37, mkdirSync as mkdirSync47, readdirSync as readdirSync29, unlinkSync as unlinkSync7 } from "fs";
141211
- import { join as join96, dirname as dirname47, basename as basename19 } from "path";
141374
+ import { join as join97, dirname as dirname47, basename as basename19 } from "path";
141212
141375
  import { homedir as homedir19 } from "os";
141213
141376
  function ensureSynthScript() {
141214
141377
  if (!existsSync89(SCRIPT_PATH)) {
@@ -141219,7 +141382,7 @@ function ensureSynthScript() {
141219
141382
  for (const entry of readdirSync29(SCRIPT_DIR)) {
141220
141383
  if (entry !== currentName && /^synth(-v\d+)?\.py$/.test(entry)) {
141221
141384
  try {
141222
- unlinkSync7(join96(SCRIPT_DIR, entry));
141385
+ unlinkSync7(join97(SCRIPT_DIR, entry));
141223
141386
  } catch {
141224
141387
  }
141225
141388
  }
@@ -141334,8 +141497,8 @@ print(json.dumps({
141334
141497
  ESPEAK_LANG_OVERRIDES = {
141335
141498
  zh: "cmn"
141336
141499
  };
141337
- SCRIPT_DIR = join96(homedir19(), ".cache", "hyperframes", "tts");
141338
- SCRIPT_PATH = join96(SCRIPT_DIR, "synth-v2.py");
141500
+ SCRIPT_DIR = join97(homedir19(), ".cache", "hyperframes", "tts");
141501
+ SCRIPT_PATH = join97(SCRIPT_DIR, "synth-v2.py");
141339
141502
  }
141340
141503
  });
141341
141504
 
@@ -141556,7 +141719,7 @@ __export(docs_exports, {
141556
141719
  examples: () => examples23
141557
141720
  });
141558
141721
  import { readFileSync as readFileSync64, existsSync as existsSync91 } from "fs";
141559
- import { resolve as resolve61, dirname as dirname48, join as join97 } from "path";
141722
+ import { resolve as resolve61, dirname as dirname48, join as join98 } from "path";
141560
141723
  import { fileURLToPath as fileURLToPath14 } from "url";
141561
141724
  function docsDir() {
141562
141725
  const thisFile = fileURLToPath14(import.meta.url);
@@ -141661,7 +141824,7 @@ var init_docs = __esm({
141661
141824
  }
141662
141825
  failCommand();
141663
141826
  }
141664
- const filePath = join97(docsDir(), entry.file);
141827
+ const filePath = join98(docsDir(), entry.file);
141665
141828
  if (!existsSync91(filePath)) {
141666
141829
  console.error(c.error(`Doc file not found: ${filePath}`));
141667
141830
  failCommand();
@@ -142757,7 +142920,7 @@ __export(contactSheet_exports, {
142757
142920
  });
142758
142921
  import sharp from "sharp";
142759
142922
  import { readdirSync as readdirSync30, readFileSync as readFileSync66, writeFileSync as writeFileSync39, unlinkSync as unlinkSync8, existsSync as existsSync95 } from "fs";
142760
- import { join as join98, extname as extname19, basename as basename20, dirname as dirname50 } from "path";
142923
+ import { join as join99, extname as extname19, basename as basename20, dirname as dirname50 } from "path";
142761
142924
  async function createContactSheet(imagePaths, outputPath, opts = {}) {
142762
142925
  const {
142763
142926
  cols = 3,
@@ -142844,7 +143007,7 @@ async function createScrollContactSheet(screenshotsDir, outputPath) {
142844
143007
  if (!existsSync95(screenshotsDir)) return [];
142845
143008
  const scrollFiles = readdirSync30(screenshotsDir).filter((f3) => f3.startsWith("scroll-") && f3.endsWith(".png")).sort();
142846
143009
  if (scrollFiles.length === 0) return [];
142847
- const paths = scrollFiles.map((f3) => join98(screenshotsDir, f3));
143010
+ const paths = scrollFiles.map((f3) => join99(screenshotsDir, f3));
142848
143011
  const labels = scrollFiles.map((f3) => {
142849
143012
  const m2 = f3.match(/scroll-(\d+)\.png/);
142850
143013
  return m2 ? `${m2[1]}% scroll` : f3;
@@ -142861,7 +143024,7 @@ async function createSnapshotContactSheet(snapshotsDir, outputPath) {
142861
143024
  if (!existsSync95(snapshotsDir)) return [];
142862
143025
  const snapshotFiles = readdirSync30(snapshotsDir).filter((f3) => f3.startsWith("frame-") && f3.endsWith(".png")).sort();
142863
143026
  if (snapshotFiles.length === 0) return [];
142864
- const paths = snapshotFiles.map((f3) => join98(snapshotsDir, f3));
143027
+ const paths = snapshotFiles.map((f3) => join99(snapshotsDir, f3));
142865
143028
  const labels = snapshotFiles.map((f3) => {
142866
143029
  const m2 = f3.match(/at-([\d.]+)s/);
142867
143030
  return m2 ? `${m2[1]}s` : f3;
@@ -142879,7 +143042,7 @@ async function createAssetContactSheet(assetsDir, outputPath) {
142879
143042
  const imageExts = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".webp"]);
142880
143043
  const assetFiles = readdirSync30(assetsDir).filter((f3) => imageExts.has(extname19(f3).toLowerCase()) && !f3.includes("contact-sheet")).sort();
142881
143044
  if (assetFiles.length === 0) return [];
142882
- const paths = assetFiles.map((f3) => join98(assetsDir, f3));
143045
+ const paths = assetFiles.map((f3) => join99(assetsDir, f3));
142883
143046
  return createContactSheetPages(paths, outputPath, {
142884
143047
  cols: 4,
142885
143048
  cellWidth: 480,
@@ -142898,7 +143061,7 @@ async function createSvgContactSheet(svgsDir, outputPath, assetsRootDir) {
142898
143061
  for (const f3 of readdirSync30(dir).filter((f4) => f4.endsWith(".svg")).sort()) {
142899
143062
  if (!seen.has(f3)) {
142900
143063
  seen.add(f3);
142901
- svgPaths.push(join98(dir, f3));
143064
+ svgPaths.push(join99(dir, f3));
142902
143065
  }
142903
143066
  }
142904
143067
  }
@@ -142910,7 +143073,7 @@ async function createSvgContactSheet(svgsDir, outputPath, assetsRootDir) {
142910
143073
  const labels = [];
142911
143074
  for (let i2 = 0; i2 < svgPaths.length; i2++) {
142912
143075
  const svgPath = svgPaths[i2];
142913
- const tmpPath = join98(tmpDir, `.thumb-${i2}.png`);
143076
+ const tmpPath = join99(tmpDir, `.thumb-${i2}.png`);
142914
143077
  try {
142915
143078
  const svgBuf = readFileSync66(svgPath);
142916
143079
  const thumb = await sharp(svgBuf).resize(thumbSize, thumbSize, {
@@ -156385,7 +156548,7 @@ var require_getCredentials = __commonJS({
156385
156548
  var fs5 = __require("fs");
156386
156549
  var util_1 = __require("util");
156387
156550
  var errorWithCode_1 = require_errorWithCode();
156388
- var readFile4 = fs5.readFile ? (0, util_1.promisify)(fs5.readFile) : async () => {
156551
+ var readFile5 = fs5.readFile ? (0, util_1.promisify)(fs5.readFile) : async () => {
156389
156552
  throw new errorWithCode_1.ErrorWithCode("use key rather than keyFile.", "MISSING_CREDENTIALS");
156390
156553
  };
156391
156554
  var ExtensionFiles;
@@ -156407,7 +156570,7 @@ var require_getCredentials = __commonJS({
156407
156570
  * @returns A promise that resolves with the credentials.
156408
156571
  */
156409
156572
  async getCredentials() {
156410
- const key2 = await readFile4(this.keyFilePath, "utf8");
156573
+ const key2 = await readFile5(this.keyFilePath, "utf8");
156411
156574
  let body;
156412
156575
  try {
156413
156576
  body = JSON.parse(key2);
@@ -156433,7 +156596,7 @@ var require_getCredentials = __commonJS({
156433
156596
  * @returns A promise that resolves with the private key.
156434
156597
  */
156435
156598
  async getCredentials() {
156436
- const privateKey = await readFile4(this.keyFilePath, "utf8");
156599
+ const privateKey = await readFile5(this.keyFilePath, "utf8");
156437
156600
  return { privateKey };
156438
156601
  }
156439
156602
  };
@@ -158063,7 +158226,7 @@ var require_filesubjecttokensupplier = __commonJS({
158063
158226
  exports.FileSubjectTokenSupplier = void 0;
158064
158227
  var util_1 = __require("util");
158065
158228
  var fs5 = __require("fs");
158066
- var readFile4 = (0, util_1.promisify)(fs5.readFile ?? (() => {
158229
+ var readFile5 = (0, util_1.promisify)(fs5.readFile ?? (() => {
158067
158230
  }));
158068
158231
  var realpath = (0, util_1.promisify)(fs5.realpath ?? (() => {
158069
158232
  }));
@@ -158103,7 +158266,7 @@ var require_filesubjecttokensupplier = __commonJS({
158103
158266
  throw err;
158104
158267
  }
158105
158268
  let subjectToken;
158106
- const rawText = await readFile4(parsedFilePath, { encoding: "utf8" });
158269
+ const rawText = await readFile5(parsedFilePath, { encoding: "utf8" });
158107
158270
  if (this.formatType === "text") {
158108
158271
  subjectToken = rawText;
158109
158272
  } else if (this.formatType === "json" && this.subjectTokenFieldName) {
@@ -164496,7 +164659,7 @@ __export(node_exports, {
164496
164659
  });
164497
164660
  import { createWriteStream as createWriteStream3 } from "fs";
164498
164661
  import * as fs4 from "fs/promises";
164499
- import { writeFile as writeFile2 } from "fs/promises";
164662
+ import { writeFile as writeFile3 } from "fs/promises";
164500
164663
  import { Readable as Readable4 } from "stream";
164501
164664
  import { finished as finished2 } from "stream/promises";
164502
164665
  import * as path$1 from "path";
@@ -182008,7 +182171,7 @@ ${underline2}`);
182008
182171
  await finished2(writer);
182009
182172
  } else {
182010
182173
  try {
182011
- await writeFile2(params.downloadPath, response, {
182174
+ await writeFile3(params.downloadPath, response, {
182012
182175
  encoding: "base64"
182013
182176
  });
182014
182177
  } catch (error) {
@@ -182696,8 +182859,8 @@ __export(snapshot_exports, {
182696
182859
  tailFrameTime: () => tailFrameTime
182697
182860
  });
182698
182861
  import { existsSync as existsSync96, mkdtempSync as mkdtempSync9, readFileSync as readFileSync67, mkdirSync as mkdirSync48, rmSync as rmSync25, writeFileSync as writeFileSync40 } from "fs";
182699
- import { tmpdir as tmpdir12 } from "os";
182700
- import { resolve as resolve64, join as join99, relative as relative21, isAbsolute as isAbsolute14, basename as basename24 } from "path";
182862
+ import { tmpdir as tmpdir13 } from "os";
182863
+ import { resolve as resolve64, join as join100, relative as relative21, isAbsolute as isAbsolute14, basename as basename24 } from "path";
182701
182864
  function orbitStageSource() {
182702
182865
  return `function(cam) {
182703
182866
  var root = document.querySelector("[data-composition-id]")
@@ -182740,8 +182903,8 @@ function requireSnapshotFfmpeg(ffmpegPath) {
182740
182903
  );
182741
182904
  }
182742
182905
  async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDecoder = false) {
182743
- const tmp = mkdtempSync9(join99(tmpdir12(), "hf-snapshot-frame-"));
182744
- const outPath = join99(tmp, "frame.png");
182906
+ const tmp = mkdtempSync9(join100(tmpdir13(), "hf-snapshot-frame-"));
182907
+ const outPath = join100(tmp, "frame.png");
182745
182908
  try {
182746
182909
  const ffmpegPath = requireSnapshotFfmpeg(findFFmpeg());
182747
182910
  const args = ["-hide_banner", "-loglevel", "error"];
@@ -182853,13 +183016,13 @@ async function captureSnapshots(projectDir, opts) {
182853
183016
  );
182854
183017
  }
182855
183018
  const cameraExpr = opts.angle && (opts.angle.yaw !== 0 || opts.angle.pitch !== 0) ? `(${orbitStageSource()})(${JSON.stringify(opts.angle)})` : null;
182856
- const snapshotDir = opts.outputDir ?? join99(projectDir, "snapshots");
183019
+ const snapshotDir = opts.outputDir ?? join100(projectDir, "snapshots");
182857
183020
  mkdirSync48(snapshotDir, { recursive: true });
182858
183021
  try {
182859
183022
  const { readdirSync: readdirSync37 } = await import("fs");
182860
183023
  for (const file of readdirSync37(snapshotDir)) {
182861
183024
  if (/\.(png|jpg|jpeg)$/i.test(file)) {
182862
- rmSync25(join99(snapshotDir, file), { force: true });
183025
+ rmSync25(join100(snapshotDir, file), { force: true });
182863
183026
  }
182864
183027
  }
182865
183028
  } catch {
@@ -182982,7 +183145,7 @@ async function captureSnapshots(projectDir, opts) {
182982
183145
  }
182983
183146
  const timeLabel = formatSnapshotTimestamp(time);
182984
183147
  const filename = `frame-${String(i2).padStart(2, "0")}-at-${timeLabel}.png`;
182985
- const framePath = join99(snapshotDir, filename);
183148
+ const framePath = join100(snapshotDir, filename);
182986
183149
  if (opts.zoom) {
182987
183150
  const canvas = await page.evaluate(() => ({
182988
183151
  width: window.innerWidth,
@@ -183110,7 +183273,7 @@ var init_snapshot = __esm({
183110
183273
  const angleLabel = camera && (camera.yaw !== 0 || camera.pitch !== 0) ? ` ${c.dim(`(angle yaw ${camera.yaw}\xB0 pitch ${camera.pitch}\xB0)`)}` : "";
183111
183274
  console.log(`${c.accent("\u25C6")} Capturing ${label2} from ${c.accent(project.name)}${angleLabel}`);
183112
183275
  try {
183113
- const snapshotDir = args.output ? resolve64(String(args.output)) : join99(project.dir, "snapshots");
183276
+ const snapshotDir = args.output ? resolve64(String(args.output)) : join100(project.dir, "snapshots");
183114
183277
  const paths = await captureSnapshots(project.dir, {
183115
183278
  frames,
183116
183279
  timeout,
@@ -183140,7 +183303,7 @@ ${c.success("\u25C7")} ${paths.length} snapshots saved to ${args.output ? snaps
183140
183303
  const { createSnapshotContactSheet: createSnapshotContactSheet2 } = await Promise.resolve().then(() => (init_contactSheet(), contactSheet_exports));
183141
183304
  const sheets = await createSnapshotContactSheet2(
183142
183305
  snapshotDir,
183143
- join99(snapshotDir, "contact-sheet.jpg")
183306
+ join100(snapshotDir, "contact-sheet.jpg")
183144
183307
  );
183145
183308
  if (sheets.length > 0) {
183146
183309
  const label3 = sheets.length === 1 ? "contact-sheet.jpg" : `contact-sheet-1..${sheets.length}.jpg`;
@@ -183176,7 +183339,7 @@ ${c.success("\u25C7")} ${paths.length} snapshots saved to ${args.output ? snaps
183176
183339
  const results = await Promise.allSettled(
183177
183340
  paths.map(async (p2) => {
183178
183341
  const filename = basename24(p2);
183179
- const filePath = join99(snapshotDir, filename);
183342
+ const filePath = join100(snapshotDir, filename);
183180
183343
  if (!existsSync96(filePath)) return { filename, desc: "file not found" };
183181
183344
  const raw = readFileSync67(filePath);
183182
183345
  let imageData;
@@ -183214,7 +183377,7 @@ ${c.success("\u25C7")} ${paths.length} snapshots saved to ${args.output ? snaps
183214
183377
  descriptions.push(`## (error)`, `Gemini call failed: ${errMsg.slice(0, 120)}`, ``);
183215
183378
  }
183216
183379
  }
183217
- const descPath = join99(snapshotDir, "descriptions.md");
183380
+ const descPath = join100(snapshotDir, "descriptions.md");
183218
183381
  writeFileSync40(descPath, descriptions.join("\n"));
183219
183382
  console.log(` ${c.dim("descriptions.md")} (Gemini frame analysis)`);
183220
183383
  }
@@ -183282,8 +183445,8 @@ import {
183282
183445
  rmSync as rmSync26,
183283
183446
  writeFileSync as writeFileSync41
183284
183447
  } from "fs";
183285
- import { tmpdir as tmpdir13 } from "os";
183286
- import { basename as basename25, dirname as dirname51, extname as extname20, join as join100, resolve as resolve66 } from "path";
183448
+ import { tmpdir as tmpdir14 } from "os";
183449
+ import { basename as basename25, dirname as dirname51, extname as extname20, join as join101, resolve as resolve66 } from "path";
183287
183450
  import sharp2 from "sharp";
183288
183451
  function isRecord7(value) {
183289
183452
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -183539,10 +183702,10 @@ function frameFileNameForPath(framePath) {
183539
183702
  return "frame.png";
183540
183703
  }
183541
183704
  async function prepareGradeCompareTempProject(opts) {
183542
- const tempDir = mkdtempSync10(join100(tmpdir13(), "hf-grade-compare-"));
183705
+ const tempDir = mkdtempSync10(join101(tmpdir14(), "hf-grade-compare-"));
183543
183706
  try {
183544
183707
  const frameFileName2 = opts.frameFileName ?? frameFileNameForPath(opts.framePath);
183545
- writeFileSync41(join100(tempDir, frameFileName2), opts.frameBuffer);
183708
+ writeFileSync41(join101(tempDir, frameFileName2), opts.frameBuffer);
183546
183709
  let lutIndex = 0;
183547
183710
  const stagedCells = opts.cells.map((cell) => {
183548
183711
  const lutSrc = lutSrcFromGrading(cell.grading);
@@ -183562,7 +183725,7 @@ async function prepareGradeCompareTempProject(opts) {
183562
183725
  const lutExt = extname20(sourcePath) || ".cube";
183563
183726
  const stagedName = `lut-${lutIndex}${lutExt}`;
183564
183727
  lutIndex += 1;
183565
- copyFileSync8(sourcePath, join100(tempDir, stagedName));
183728
+ copyFileSync8(sourcePath, join101(tempDir, stagedName));
183566
183729
  return {
183567
183730
  label: cell.label,
183568
183731
  grading: rewriteGradingLutSrc(cell.grading, stagedName)
@@ -183574,7 +183737,7 @@ async function prepareGradeCompareTempProject(opts) {
183574
183737
  frameWidth: opts.frameWidth,
183575
183738
  frameHeight: opts.frameHeight
183576
183739
  });
183577
- writeFileSync41(join100(tempDir, "index.html"), html);
183740
+ writeFileSync41(join101(tempDir, "index.html"), html);
183578
183741
  return { tempDir, html, cells: stagedCells };
183579
183742
  } catch (err) {
183580
183743
  rmSync26(tempDir, { recursive: true, force: true });
@@ -183586,8 +183749,8 @@ function isVideoPath2(filePath) {
183586
183749
  return [".mp4", ".mov", ".m4v", ".webm", ".mkv", ".avi", ".mpeg", ".mpg", ".ogv"].includes(ext);
183587
183750
  }
183588
183751
  async function extractVideoFrameToBuffer2(videoPath) {
183589
- const tmp = mkdtempSync10(join100(tmpdir13(), "hf-grade-compare-frame-"));
183590
- const outPath = join100(tmp, "frame.png");
183752
+ const tmp = mkdtempSync10(join101(tmpdir14(), "hf-grade-compare-frame-"));
183753
+ const outPath = join101(tmp, "frame.png");
183591
183754
  try {
183592
183755
  const ffmpegPath = findFFmpeg();
183593
183756
  if (!ffmpegPath) return null;
@@ -183642,7 +183805,7 @@ async function captureGradeCompareSheet(projectDir, timeoutMs) {
183642
183805
  const { bundleToSingleHtml: bundleToSingleHtml2 } = await Promise.resolve().then(() => (init_compiler(), compiler_exports));
183643
183806
  const html = await bundleToSingleHtml2(projectDir);
183644
183807
  const server = await serveStaticProjectHtml(projectDir, html);
183645
- const sheetPath = join100(projectDir, "grade-compare.png");
183808
+ const sheetPath = join101(projectDir, "grade-compare.png");
183646
183809
  try {
183647
183810
  const {
183648
183811
  browser: chromeBrowser,
@@ -183829,8 +183992,8 @@ __export(compare_exports, {
183829
183992
  prepareCompareVariantProjects: () => prepareCompareVariantProjects
183830
183993
  });
183831
183994
  import { cpSync as cpSync6, existsSync as existsSync98, mkdirSync as mkdirSync50, mkdtempSync as mkdtempSync11, renameSync as renameSync13, rmSync as rmSync27, statSync as statSync33 } from "fs";
183832
- import { tmpdir as tmpdir14 } from "os";
183833
- import { basename as basename26, dirname as dirname52, extname as extname21, join as join101 } from "path";
183995
+ import { tmpdir as tmpdir15 } from "os";
183996
+ import { basename as basename26, dirname as dirname52, extname as extname21, join as join103 } from "path";
183834
183997
  function defaultLabelForPath(input2) {
183835
183998
  const name = basename26(input2);
183836
183999
  return extname21(name).toLowerCase() === ".html" ? basename26(name, extname21(name)) : name;
@@ -183929,7 +184092,7 @@ function inputError(variant) {
183929
184092
  );
183930
184093
  }
183931
184094
  function stageHtmlVariant(variant) {
183932
- const stagedDir = mkdtempSync11(join101(tmpdir14(), "hf-compare-variant-"));
184095
+ const stagedDir = mkdtempSync11(join103(tmpdir15(), "hf-compare-variant-"));
183933
184096
  try {
183934
184097
  cpSync6(dirname52(variant.inputPath), stagedDir, {
183935
184098
  recursive: true,
@@ -183940,7 +184103,7 @@ function stageHtmlVariant(variant) {
183940
184103
  });
183941
184104
  const sourceName = basename26(variant.inputPath);
183942
184105
  if (sourceName !== "index.html") {
183943
- renameSync13(join101(stagedDir, sourceName), join101(stagedDir, "index.html"));
184106
+ renameSync13(join103(stagedDir, sourceName), join103(stagedDir, "index.html"));
183944
184107
  }
183945
184108
  return {
183946
184109
  ...variant,
@@ -183960,7 +184123,7 @@ function prepareCompareVariantProjects(variants) {
183960
184123
  throw inputError(variant);
183961
184124
  }
183962
184125
  const stat3 = statSync33(variant.inputPath);
183963
- if (stat3.isDirectory() && existsSync98(join101(variant.inputPath, "index.html"))) {
184126
+ if (stat3.isDirectory() && existsSync98(join103(variant.inputPath, "index.html"))) {
183964
184127
  prepared.push({
183965
184128
  ...variant,
183966
184129
  projectDir: variant.inputPath
@@ -184026,13 +184189,13 @@ async function renderCompareSheet(parsed) {
184026
184189
  const capResult = capCompareVariants(parsed.variants);
184027
184190
  const variants = capResult.variants;
184028
184191
  const prepared = prepareCompareVariantProjects(variants);
184029
- const frameDir = mkdtempSync11(join101(tmpdir14(), "hf-compare-frames-"));
184192
+ const frameDir = mkdtempSync11(join103(tmpdir15(), "hf-compare-frames-"));
184030
184193
  const framePaths = [];
184031
184194
  try {
184032
184195
  let renderReadyTimedOut = false;
184033
184196
  for (let i2 = 0; i2 < prepared.length; i2++) {
184034
184197
  const variant = prepared[i2];
184035
- const framePath = join101(frameDir, `variant-${String(i2 + 1).padStart(2, "0")}.png`);
184198
+ const framePath = join103(frameDir, `variant-${String(i2 + 1).padStart(2, "0")}.png`);
184036
184199
  const rendered = await renderCompareVariant(variant, {
184037
184200
  atSeconds: parsed.atSeconds,
184038
184201
  framePath,
@@ -184161,18 +184324,18 @@ ${c.error("\u2717")} Compare failed: ${message}`);
184161
184324
 
184162
184325
  // src/capture/assetDownloader.ts
184163
184326
  import { writeFileSync as writeFileSync43, mkdirSync as mkdirSync51 } from "fs";
184164
- import { join as join103, extname as extname23 } from "path";
184327
+ import { join as join104, extname as extname23 } from "path";
184165
184328
  import { createHash as createHash16 } from "crypto";
184166
184329
  function svgContentHashSlug(svgSource, isLogo) {
184167
184330
  const hash2 = createHash16("sha1").update(svgSource).digest("hex").slice(0, 8);
184168
184331
  return isLogo ? `logo-${hash2}` : `svg-${hash2}`;
184169
184332
  }
184170
184333
  async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks) {
184171
- const assetsDir = join103(outputDir, "assets");
184334
+ const assetsDir = join104(outputDir, "assets");
184172
184335
  mkdirSync51(assetsDir, { recursive: true });
184173
184336
  const assets = [];
184174
184337
  const downloadedUrls = /* @__PURE__ */ new Set();
184175
- mkdirSync51(join103(outputDir, "assets", "svgs"), { recursive: true });
184338
+ mkdirSync51(join104(outputDir, "assets", "svgs"), { recursive: true });
184176
184339
  const usedSvgNames = /* @__PURE__ */ new Set();
184177
184340
  for (let i2 = 0; i2 < tokens.svgs.length && i2 < 30; i2++) {
184178
184341
  const svg = tokens.svgs[i2];
@@ -184188,7 +184351,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
184188
184351
  const name = `${finalSlug}.svg`;
184189
184352
  const localPath = `assets/svgs/${name}`;
184190
184353
  try {
184191
- writeFileSync43(join103(outputDir, localPath), svg.outerHTML, "utf-8");
184354
+ writeFileSync43(join104(outputDir, localPath), svg.outerHTML, "utf-8");
184192
184355
  assets.push({ url: "", localPath, type: "svg" });
184193
184356
  } catch {
184194
184357
  }
@@ -184201,7 +184364,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
184201
184364
  const localPath = `assets/${name}`;
184202
184365
  const buffer = await fetchBuffer(icon.href);
184203
184366
  if (buffer) {
184204
- writeFileSync43(join103(outputDir, localPath), buffer);
184367
+ writeFileSync43(join104(outputDir, localPath), buffer);
184205
184368
  assets.push({ url: icon.href, localPath, type: "favicon" });
184206
184369
  break;
184207
184370
  }
@@ -184266,7 +184429,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
184266
184429
  const name = `${slug}${ext}`;
184267
184430
  usedNames.add(slug);
184268
184431
  const localPath = `assets/${name}`;
184269
- writeFileSync43(join103(outputDir, localPath), buffer);
184432
+ writeFileSync43(join104(outputDir, localPath), buffer);
184270
184433
  assets.push({ url, localPath, type: "image" });
184271
184434
  imgIdx++;
184272
184435
  } catch {
@@ -184279,7 +184442,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
184279
184442
  const localPath = `assets/og-image${ext}`;
184280
184443
  const buffer = await fetchBuffer(tokens.ogImage);
184281
184444
  if (buffer && buffer.length > 5e3) {
184282
- writeFileSync43(join103(outputDir, localPath), buffer);
184445
+ writeFileSync43(join104(outputDir, localPath), buffer);
184283
184446
  assets.push({ url: tokens.ogImage, localPath, type: "image" });
184284
184447
  }
184285
184448
  } catch {
@@ -184302,7 +184465,7 @@ function normalizeUrl(u) {
184302
184465
  }
184303
184466
  }
184304
184467
  async function downloadAndRewriteFonts(css, outputDir) {
184305
- const assetsDir = join103(outputDir, "assets", "fonts");
184468
+ const assetsDir = join104(outputDir, "assets", "fonts");
184306
184469
  mkdirSync51(assetsDir, { recursive: true });
184307
184470
  const fontUrlRegex = /url\(['"]?(https?:\/\/[^'")\s]+\.(?:woff2?|ttf|otf)[^'")\s]*?)['"]?\)/g;
184308
184471
  const fontUrls = /* @__PURE__ */ new Set();
@@ -184338,7 +184501,7 @@ async function downloadAndRewriteFonts(css, outputDir) {
184338
184501
  try {
184339
184502
  const urlObj = new URL(fontUrl);
184340
184503
  const filename = urlObj.pathname.split("/").pop() || `font-${count}.woff2`;
184341
- const localPath = join103(assetsDir, filename);
184504
+ const localPath = join104(assetsDir, filename);
184342
184505
  const relativePath = `assets/fonts/${filename}`;
184343
184506
  const buffer = await fetchBuffer(fontUrl);
184344
184507
  if (buffer) {
@@ -184497,7 +184660,7 @@ __export(video_exports, {
184497
184660
  safeFilename: () => safeFilename
184498
184661
  });
184499
184662
  import { createWriteStream as createWriteStream4, existsSync as existsSync99, mkdirSync as mkdirSync53, readFileSync as readFileSync69, unlinkSync as unlinkSync9 } from "fs";
184500
- import { resolve as resolve67, join as join104, basename as basename27 } from "path";
184663
+ import { resolve as resolve67, join as join105, basename as basename27 } from "path";
184501
184664
  async function streamToFile(url, destPath) {
184502
184665
  const r2 = await safeFetch(url, {
184503
184666
  signal: AbortSignal.timeout(12e4),
@@ -184616,8 +184779,8 @@ function pickManifestEntry(manifest, args) {
184616
184779
  }
184617
184780
  async function runVideoMode(args) {
184618
184781
  const projectDir = resolve67(args.project);
184619
- const directPath = join104(projectDir, "extracted", "video-manifest.json");
184620
- const w2hPath = join104(projectDir, "capture", "extracted", "video-manifest.json");
184782
+ const directPath = join105(projectDir, "extracted", "video-manifest.json");
184783
+ const w2hPath = join105(projectDir, "capture", "extracted", "video-manifest.json");
184621
184784
  const manifestPath2 = existsSync99(directPath) ? directPath : w2hPath;
184622
184785
  const isW2hLayout = manifestPath2 === w2hPath;
184623
184786
  if (!existsSync99(manifestPath2)) {
@@ -184671,10 +184834,10 @@ async function runVideoMode(args) {
184671
184834
  setCommandExitCode(1);
184672
184835
  return;
184673
184836
  }
184674
- const outDir = isW2hLayout ? join104(projectDir, "capture", "assets", "videos") : join104(projectDir, "assets", "videos");
184837
+ const outDir = isW2hLayout ? join105(projectDir, "capture", "assets", "videos") : join105(projectDir, "assets", "videos");
184675
184838
  mkdirSync53(outDir, { recursive: true });
184676
184839
  const fname = safeFilename(entry.filename || basename27(entry.url));
184677
- const outPath = join104(outDir, fname);
184840
+ const outPath = join105(outDir, fname);
184678
184841
  const relPath = isW2hLayout ? `capture/assets/videos/${fname}` : `assets/videos/${fname}`;
184679
184842
  console.log(
184680
184843
  `${c.accent("\u25B8")} downloading [${entry.index}] ${entry.filename} (${entry.sourceWidth || entry.width}\xD7${entry.sourceHeight || entry.height})`
@@ -185919,7 +186082,7 @@ var init_designStyleExtractor = __esm({
185919
186082
 
185920
186083
  // src/capture/fontMetadataExtractor.ts
185921
186084
  import { readdirSync as readdirSync31, readFileSync as readFileSync70, writeFileSync as writeFileSync44, existsSync as existsSync100 } from "fs";
185922
- import { join as join105 } from "path";
186085
+ import { join as join106 } from "path";
185923
186086
  import * as fontkit from "fontkit";
185924
186087
  function isFontCollection(value) {
185925
186088
  return value.type === "TTC" || value.type === "DFont";
@@ -185930,7 +186093,7 @@ function extractFontMetadata(fontsDir, outputPath) {
185930
186093
  if (existsSync100(fontsDir)) {
185931
186094
  const fontFiles = readdirSync31(fontsDir).filter((f3) => /\.(woff2?|ttf|otf)$/i.test(f3));
185932
186095
  for (const filename of fontFiles) {
185933
- const fullPath = join105(fontsDir, filename);
186096
+ const fullPath = join106(fontsDir, filename);
185934
186097
  const meta = readSingleFont(fullPath, filename);
185935
186098
  if (meta.identified) {
185936
186099
  files.push(meta);
@@ -186242,7 +186405,7 @@ var init_animationCataloger = __esm({
186242
186405
 
186243
186406
  // src/capture/mediaCapture.ts
186244
186407
  import { mkdirSync as mkdirSync54, writeFileSync as writeFileSync45, readdirSync as readdirSync33, readFileSync as readFileSync71, statSync as statSync34 } from "fs";
186245
- import { join as join106, extname as extname24 } from "path";
186408
+ import { join as join107, extname as extname24 } from "path";
186246
186409
  async function saveLottieAnimations(discoveredLotties, lottieDir) {
186247
186410
  let savedCount = 0;
186248
186411
  const savedHashes = /* @__PURE__ */ new Set();
@@ -186274,7 +186437,7 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
186274
186437
  const hash2 = buf.toString("base64").slice(0, 100);
186275
186438
  if (savedHashes.has(hash2)) continue;
186276
186439
  savedHashes.add(hash2);
186277
- writeFileSync45(join106(lottieDir, `animation-${savedCount}.lottie`), buf);
186440
+ writeFileSync45(join107(lottieDir, `animation-${savedCount}.lottie`), buf);
186278
186441
  savedCount++;
186279
186442
  continue;
186280
186443
  }
@@ -186292,7 +186455,7 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
186292
186455
  } catch {
186293
186456
  continue;
186294
186457
  }
186295
- writeFileSync45(join106(lottieDir, `animation-${savedCount}.json`), jsonData, "utf-8");
186458
+ writeFileSync45(join107(lottieDir, `animation-${savedCount}.json`), jsonData, "utf-8");
186296
186459
  savedCount++;
186297
186460
  }
186298
186461
  } catch {
@@ -186302,22 +186465,22 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
186302
186465
  }
186303
186466
  async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
186304
186467
  const manifest = [];
186305
- const previewDir = join106(lottieDir, "previews");
186468
+ const previewDir = join107(lottieDir, "previews");
186306
186469
  mkdirSync54(previewDir, { recursive: true });
186307
186470
  for (const file of readdirSync33(lottieDir)) {
186308
186471
  if (!file.endsWith(".json")) continue;
186309
186472
  try {
186310
- const raw = JSON.parse(readFileSync71(join106(lottieDir, file), "utf-8"));
186473
+ const raw = JSON.parse(readFileSync71(join107(lottieDir, file), "utf-8"));
186311
186474
  const fr = raw.fr || 30;
186312
186475
  const dur = ((raw.op || 0) - (raw.ip || 0)) / fr;
186313
186476
  const previewName = file.replace(".json", "-preview.png");
186314
- const fileSize = statSync34(join106(lottieDir, file)).size;
186477
+ const fileSize = statSync34(join107(lottieDir, file)).size;
186315
186478
  if (fileSize > 2e6) continue;
186316
186479
  let previewPage;
186317
186480
  try {
186318
186481
  previewPage = await chromeBrowser.newPage();
186319
186482
  await previewPage.setViewport({ width: 400, height: 400 });
186320
- const animData = JSON.parse(readFileSync71(join106(lottieDir, file), "utf-8"));
186483
+ const animData = JSON.parse(readFileSync71(join107(lottieDir, file), "utf-8"));
186321
186484
  const midFrame = Math.floor(((raw.op || 0) - (raw.ip || 0)) * 0.3);
186322
186485
  await previewPage.setContent(
186323
186486
  `<!DOCTYPE html>
@@ -186347,7 +186510,7 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
186347
186510
  await previewPage.waitForFunction(() => window.__READY === true, { timeout: 5e3 }).catch(() => {
186348
186511
  });
186349
186512
  await previewPage.screenshot({
186350
- path: join106(previewDir, previewName),
186513
+ path: join107(previewDir, previewName),
186351
186514
  type: "png",
186352
186515
  omitBackground: true
186353
186516
  });
@@ -186371,7 +186534,7 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
186371
186534
  }
186372
186535
  if (manifest.length > 0) {
186373
186536
  writeFileSync45(
186374
- join106(outputDir, "extracted", "lottie-manifest.json"),
186537
+ join107(outputDir, "extracted", "lottie-manifest.json"),
186375
186538
  JSON.stringify(manifest, null, 2),
186376
186539
  "utf-8"
186377
186540
  );
@@ -186406,7 +186569,7 @@ async function downloadVideoBody(srcUrl, filename, videosDir) {
186406
186569
  }
186407
186570
  if (total < 1024) return null;
186408
186571
  const safe = /\.[a-z0-9]+$/i.test(filename) ? filename.replace(/[^\w.-]/g, "_") : `video${ext}`;
186409
- writeFileSync45(join106(videosDir, safe), Buffer.concat(chunks));
186572
+ writeFileSync45(join107(videosDir, safe), Buffer.concat(chunks));
186410
186573
  return `assets/videos/${safe}`;
186411
186574
  } catch {
186412
186575
  return null;
@@ -186468,9 +186631,9 @@ async function captureVideoManifest(page, outputDir, progress, opts) {
186468
186631
  }
186469
186632
  const merged = [...byKey.values()];
186470
186633
  if (merged.length === 0) return;
186471
- const videoManifestDir = join106(outputDir, "assets", "videos");
186634
+ const videoManifestDir = join107(outputDir, "assets", "videos");
186472
186635
  mkdirSync54(videoManifestDir, { recursive: true });
186473
- const previewDir = join106(videoManifestDir, "previews");
186636
+ const previewDir = join107(videoManifestDir, "previews");
186474
186637
  mkdirSync54(previewDir, { recursive: true });
186475
186638
  const videoManifest = [];
186476
186639
  const dlStart = Date.now();
@@ -186493,7 +186656,7 @@ async function captureVideoManifest(page, outputDir, progress, opts) {
186493
186656
  if (rect && rect.width >= 10) {
186494
186657
  await new Promise((r2) => setTimeout(r2, 200));
186495
186658
  await page.screenshot({
186496
- path: join106(previewDir, previewName),
186659
+ path: join107(previewDir, previewName),
186497
186660
  clip: {
186498
186661
  x: Math.max(0, rect.x),
186499
186662
  y: Math.max(0, rect.y),
@@ -186525,7 +186688,7 @@ async function captureVideoManifest(page, outputDir, progress, opts) {
186525
186688
  }
186526
186689
  if (videoManifest.length > 0) {
186527
186690
  writeFileSync45(
186528
- join106(outputDir, "extracted", "video-manifest.json"),
186691
+ join107(outputDir, "extracted", "video-manifest.json"),
186529
186692
  JSON.stringify(videoManifest, null, 2),
186530
186693
  "utf-8"
186531
186694
  );
@@ -186594,7 +186757,7 @@ var init_mediaCapture = __esm({
186594
186757
 
186595
186758
  // src/capture/contentExtractor.ts
186596
186759
  import { existsSync as existsSync101, readdirSync as readdirSync34, statSync as statSync35, readFileSync as readFileSync73 } from "fs";
186597
- import { basename as basename28, join as join107 } from "path";
186760
+ import { basename as basename28, join as join108 } from "path";
186598
186761
  async function detectLibraries(page, capturedShaders) {
186599
186762
  let detectedLibraries = [];
186600
186763
  try {
@@ -186761,7 +186924,7 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
186761
186924
  return response.text?.trim() || "";
186762
186925
  };
186763
186926
  }
186764
- const imageFiles = readdirSync34(join107(outputDir, "assets")).filter(
186927
+ const imageFiles = readdirSync34(join108(outputDir, "assets")).filter(
186765
186928
  (f3) => /\.(png|jpg|jpeg|webp|gif)$/i.test(f3)
186766
186929
  );
186767
186930
  const BATCH_SIZE = 20;
@@ -186769,7 +186932,7 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
186769
186932
  const batch = imageFiles.slice(i2, i2 + BATCH_SIZE);
186770
186933
  const results = await Promise.allSettled(
186771
186934
  batch.map(async (file) => {
186772
- const filePath = join107(outputDir, "assets", file);
186935
+ const filePath = join108(outputDir, "assets", file);
186773
186936
  const stat3 = statSync35(filePath);
186774
186937
  if (stat3.size > 4e6) return { file, caption: "" };
186775
186938
  const buffer = readFileSync73(filePath);
@@ -186803,11 +186966,11 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
186803
186966
  `${Object.keys(geminiCaptions).length} images captioned with ${providerName}`
186804
186967
  );
186805
186968
  const svgFiles = [];
186806
- const assetsDir = join107(outputDir, "assets");
186969
+ const assetsDir = join108(outputDir, "assets");
186807
186970
  for (const f3 of readdirSync34(assetsDir)) {
186808
186971
  if (/\.svg$/i.test(f3)) svgFiles.push({ file: f3, relPath: f3 });
186809
186972
  }
186810
- const svgsSubdir = join107(assetsDir, "svgs");
186973
+ const svgsSubdir = join108(assetsDir, "svgs");
186811
186974
  if (existsSync101(svgsSubdir)) {
186812
186975
  for (const f3 of readdirSync34(svgsSubdir)) {
186813
186976
  if (/\.svg$/i.test(f3)) svgFiles.push({ file: f3, relPath: `svgs/${f3}` });
@@ -186831,7 +186994,7 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
186831
186994
  const batch = svgFiles.slice(i2, i2 + SVG_BATCH);
186832
186995
  const results = await Promise.allSettled(
186833
186996
  batch.map(async ({ relPath }) => {
186834
- const filePath = join107(assetsDir, relPath);
186997
+ const filePath = join108(assetsDir, relPath);
186835
186998
  let pngBase64;
186836
186999
  try {
186837
187000
  const svgSource = readFileSync73(filePath, "utf-8");
@@ -186889,11 +187052,11 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
186889
187052
  const uncaptionedLines = [];
186890
187053
  const svgLines = [];
186891
187054
  const fontLines = [];
186892
- const assetsPath = join107(outputDir, "assets");
187055
+ const assetsPath = join108(outputDir, "assets");
186893
187056
  try {
186894
187057
  for (const file of readdirSync34(assetsPath)) {
186895
187058
  if (file === "svgs" || file === "fonts" || file === "lottie" || file === "videos") continue;
186896
- const filePath = join107(assetsPath, file);
187059
+ const filePath = join108(assetsPath, file);
186897
187060
  const stat3 = statSync35(filePath);
186898
187061
  if (!stat3.isFile()) continue;
186899
187062
  const sizeKb = Math.round(stat3.size / 1024);
@@ -186922,7 +187085,7 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
186922
187085
  } catch {
186923
187086
  }
186924
187087
  try {
186925
- const svgsPath = join107(assetsPath, "svgs");
187088
+ const svgsPath = join108(assetsPath, "svgs");
186926
187089
  for (const file of readdirSync34(svgsPath)) {
186927
187090
  if (!file.endsWith(".svg")) continue;
186928
187091
  const svgMatch = tokens.svgs.find(
@@ -186941,7 +187104,7 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
186941
187104
  } catch {
186942
187105
  }
186943
187106
  try {
186944
- const fontsPath = join107(assetsPath, "fonts");
187107
+ const fontsPath = join108(assetsPath, "fonts");
186945
187108
  for (const file of readdirSync34(fontsPath)) {
186946
187109
  fontLines.push(`fonts/${file} \u2014 font file`);
186947
187110
  }
@@ -186950,7 +187113,7 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
186950
187113
  const videoLines = [];
186951
187114
  try {
186952
187115
  const manifest = JSON.parse(
186953
- readFileSync73(join107(outputDir, "extracted", "video-manifest.json"), "utf-8")
187116
+ readFileSync73(join108(outputDir, "extracted", "video-manifest.json"), "utf-8")
186954
187117
  );
186955
187118
  for (const v2 of manifest) {
186956
187119
  if (!v2.localPath) continue;
@@ -186978,7 +187141,7 @@ __export(agentPromptGenerator_exports, {
186978
187141
  generateAgentPrompt: () => generateAgentPrompt
186979
187142
  });
186980
187143
  import { writeFileSync as writeFileSync46, readdirSync as readdirSync35, existsSync as existsSync103 } from "fs";
186981
- import { join as join108 } from "path";
187144
+ import { join as join109 } from "path";
186982
187145
  function inferColorRole(hex) {
186983
187146
  const r2 = parseInt(hex.slice(1, 3), 16) / 255;
186984
187147
  const g = parseInt(hex.slice(3, 5), 16) / 255;
@@ -186997,9 +187160,9 @@ function inferColorRole(hex) {
186997
187160
  }
186998
187161
  function generateAgentPrompt(outputDir, url, tokens, _animations, hasScreenshot, hasLottie, hasShaders, _catalogedAssets, _detectedLibraries) {
186999
187162
  const prompt = buildPrompt(outputDir, url, tokens, hasScreenshot, hasLottie, hasShaders);
187000
- writeFileSync46(join108(outputDir, "AGENTS.md"), prompt, "utf-8");
187001
- writeFileSync46(join108(outputDir, "CLAUDE.md"), prompt, "utf-8");
187002
- writeFileSync46(join108(outputDir, ".cursorrules"), prompt, "utf-8");
187163
+ writeFileSync46(join109(outputDir, "AGENTS.md"), prompt, "utf-8");
187164
+ writeFileSync46(join109(outputDir, "CLAUDE.md"), prompt, "utf-8");
187165
+ writeFileSync46(join109(outputDir, ".cursorrules"), prompt, "utf-8");
187003
187166
  }
187004
187167
  function buildPrompt(outputDir, url, tokens, hasScreenshot, hasLottie, hasShaders) {
187005
187168
  const title = tokens.title || new URL(url).hostname.replace(/^www\./, "");
@@ -187008,7 +187171,7 @@ function buildPrompt(outputDir, url, tokens, hasScreenshot, hasLottie, hasShader
187008
187171
  (f3) => f3.family + (f3.variable && f3.weightRange ? ` (${f3.weightRange[0]}-${f3.weightRange[1]} variable)` : f3.weights.length > 0 ? ` (${f3.weights.join(",")})` : "")
187009
187172
  ).join(", ") || "none detected";
187010
187173
  function contactSheetRows(dir, baseFile, label2) {
187011
- const fullDir = join108(outputDir, dir);
187174
+ const fullDir = join109(outputDir, dir);
187012
187175
  if (!existsSync103(fullDir)) return [];
187013
187176
  const baseName = baseFile.replace(/\.jpg$/, "");
187014
187177
  const escapedBase = baseName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -187041,7 +187204,7 @@ function buildPrompt(outputDir, url, tokens, hasScreenshot, hasLottie, hasShader
187041
187204
  tableRows.push(
187042
187205
  `| \`extracted/tokens.json\` | Design tokens: ${tokens.colors.length} colors, ${tokens.fonts.length} fonts, ${tokens.headings?.length ?? 0} headings, ${tokens.ctas?.length ?? 0} CTAs |`
187043
187206
  );
187044
- if (existsSync103(join108(outputDir, "extracted", "design-styles.json"))) {
187207
+ if (existsSync103(join109(outputDir, "extracted", "design-styles.json"))) {
187045
187208
  tableRows.push(
187046
187209
  "| `extracted/design-styles.json` | Computed styles from live DOM: typography hierarchy, button/card/nav styles, spacing scale, border-radius, box shadows. Primary data source for DESIGN.md. |"
187047
187210
  );
@@ -187113,7 +187276,7 @@ var init_agentPromptGenerator = __esm({
187113
187276
 
187114
187277
  // src/capture/scaffolding.ts
187115
187278
  import { existsSync as existsSync104, writeFileSync as writeFileSync47, readFileSync as readFileSync74 } from "fs";
187116
- import { join as join109, resolve as resolve68 } from "path";
187279
+ import { join as join110, resolve as resolve68 } from "path";
187117
187280
  function loadEnvFile(startDir) {
187118
187281
  try {
187119
187282
  let dir = resolve68(startDir);
@@ -187139,7 +187302,7 @@ function loadEnvFile(startDir) {
187139
187302
  }
187140
187303
  }
187141
187304
  async function generateProjectScaffold(outputDir, url, tokens, animationCatalog, hasScreenshots, hasLotties, hasShaders, catalogedAssets, progress, warnings, detectedLibraries) {
187142
- const metaPath = join109(outputDir, "meta.json");
187305
+ const metaPath = join110(outputDir, "meta.json");
187143
187306
  if (!existsSync104(metaPath)) {
187144
187307
  const hostname = new URL(url).hostname.replace(/^www\./, "");
187145
187308
  writeFileSync47(
@@ -187178,9 +187341,9 @@ __export(screenshotCapture_exports, {
187178
187341
  captureScrollScreenshots: () => captureScrollScreenshots
187179
187342
  });
187180
187343
  import { writeFileSync as writeFileSync48, mkdirSync as mkdirSync55 } from "fs";
187181
- import { join as join110 } from "path";
187344
+ import { join as join111 } from "path";
187182
187345
  async function captureScrollScreenshots(page, outputDir) {
187183
- const screenshotsDir = join110(outputDir, "screenshots");
187346
+ const screenshotsDir = join111(outputDir, "screenshots");
187184
187347
  mkdirSync55(screenshotsDir, { recursive: true });
187185
187348
  const MAX_SCREENSHOTS = 20;
187186
187349
  const filePaths = [];
@@ -187272,7 +187435,7 @@ async function captureScrollScreenshots(page, outputDir) {
187272
187435
  finalPositions[i2] / Math.max(1, scrollHeight - viewportHeight) * 100
187273
187436
  );
187274
187437
  const filename = `scroll-${String(Math.min(pct, 100)).padStart(3, "0")}.png`;
187275
- const filePath = join110(screenshotsDir, filename);
187438
+ const filePath = join111(screenshotsDir, filename);
187276
187439
  const buffer = await page.screenshot({ type: "png" });
187277
187440
  writeFileSync48(filePath, buffer);
187278
187441
  filePaths.push(`screenshots/${filename}`);
@@ -187622,7 +187785,7 @@ __export(capture_exports, {
187622
187785
  captureWebsite: () => captureWebsite
187623
187786
  });
187624
187787
  import { mkdirSync as mkdirSync56, writeFileSync as writeFileSync49, existsSync as existsSync105 } from "fs";
187625
- import { join as join111 } from "path";
187788
+ import { join as join113 } from "path";
187626
187789
  async function captureWebsite(opts, onProgress) {
187627
187790
  const {
187628
187791
  url,
@@ -187639,9 +187802,9 @@ async function captureWebsite(opts, onProgress) {
187639
187802
  onProgress?.(stage, detail);
187640
187803
  };
187641
187804
  loadEnvFile(outputDir);
187642
- mkdirSync56(join111(outputDir, "extracted"), { recursive: true });
187643
- mkdirSync56(join111(outputDir, "screenshots"), { recursive: true });
187644
- mkdirSync56(join111(outputDir, "assets"), { recursive: true });
187805
+ mkdirSync56(join113(outputDir, "extracted"), { recursive: true });
187806
+ mkdirSync56(join113(outputDir, "screenshots"), { recursive: true });
187807
+ mkdirSync56(join113(outputDir, "assets"), { recursive: true });
187645
187808
  progress("browser", "Launching headless Chrome...");
187646
187809
  const { ensureBrowser: ensureBrowser2 } = await Promise.resolve().then(() => (init_manager2(), manager_exports2));
187647
187810
  const browser = await ensureBrowser2();
@@ -187801,7 +187964,7 @@ async function captureWebsite(opts, onProgress) {
187801
187964
  } catch {
187802
187965
  }
187803
187966
  if (discoveredLotties.length > 0) {
187804
- const lottieDir = join111(outputDir, "assets", "lottie");
187967
+ const lottieDir = join113(outputDir, "assets", "lottie");
187805
187968
  mkdirSync56(lottieDir, { recursive: true });
187806
187969
  const savedCount = await saveLottieAnimations(discoveredLotties, lottieDir);
187807
187970
  if (savedCount > 0) {
@@ -187821,7 +187984,7 @@ async function captureWebsite(opts, onProgress) {
187821
187984
  });
187822
187985
  capturedShaders = unique;
187823
187986
  writeFileSync49(
187824
- join111(outputDir, "extracted", "shaders.json"),
187987
+ join113(outputDir, "extracted", "shaders.json"),
187825
187988
  JSON.stringify(unique, null, 2),
187826
187989
  "utf-8"
187827
187990
  );
@@ -187836,7 +187999,7 @@ async function captureWebsite(opts, onProgress) {
187836
187999
  svgs: tokens.svgs.map(({ outerHTML: _, ...rest }) => rest)
187837
188000
  };
187838
188001
  writeFileSync49(
187839
- join111(outputDir, "extracted", "tokens.json"),
188002
+ join113(outputDir, "extracted", "tokens.json"),
187840
188003
  JSON.stringify(tokensForDisk, null, 2),
187841
188004
  "utf-8"
187842
188005
  );
@@ -187844,7 +188007,7 @@ async function captureWebsite(opts, onProgress) {
187844
188007
  try {
187845
188008
  const designStyles = await extractDesignStyles(page1);
187846
188009
  writeFileSync49(
187847
- join111(outputDir, "extracted", "design-styles.json"),
188010
+ join113(outputDir, "extracted", "design-styles.json"),
187848
188011
  JSON.stringify(designStyles, null, 2),
187849
188012
  "utf-8"
187850
188013
  );
@@ -187923,8 +188086,8 @@ ${err.stack}` : normalizeErrorMessage(err);
187923
188086
  extracted.headHtml = await downloadAndRewriteFonts(extracted.headHtml, outputDir);
187924
188087
  try {
187925
188088
  const fontsManifest = extractFontMetadata(
187926
- join111(outputDir, "assets", "fonts"),
187927
- join111(outputDir, "extracted", "fonts-manifest.json")
188089
+ join113(outputDir, "assets", "fonts"),
188090
+ join113(outputDir, "extracted", "fonts-manifest.json")
187928
188091
  );
187929
188092
  if (fontsManifest.families.length > 0) {
187930
188093
  const summary = fontsManifest.families.map((f3) => `${f3.family}${f3.variable ? " (variable)" : ""} \xD7 ${f3.fileCount}`).join(", ");
@@ -187951,7 +188114,7 @@ ${err.stack}` : normalizeErrorMessage(err);
187951
188114
  representativeAnimations: representativeAnims
187952
188115
  };
187953
188116
  writeFileSync49(
187954
- join111(outputDir, "extracted", "animations.json"),
188117
+ join113(outputDir, "extracted", "animations.json"),
187955
188118
  JSON.stringify(leanCatalog, null, 2),
187956
188119
  "utf-8"
187957
188120
  );
@@ -187982,7 +188145,7 @@ ${err.stack}` : normalizeErrorMessage(err);
187982
188145
  svgs: tokens.svgs.map(({ outerHTML: _, ...rest }) => rest)
187983
188146
  };
187984
188147
  writeFileSync49(
187985
- join111(outputDir, "extracted", "tokens.json"),
188148
+ join113(outputDir, "extracted", "tokens.json"),
187986
188149
  JSON.stringify(tokensForDisk2, null, 2),
187987
188150
  "utf-8"
187988
188151
  );
@@ -187998,12 +188161,12 @@ ${extracted.bodyHtml}
187998
188161
  </body>
187999
188162
  </html>
188000
188163
  `;
188001
- writeFileSync49(join111(outputDir, "extracted", "page.html"), pageHtml, "utf-8");
188164
+ writeFileSync49(join113(outputDir, "extracted", "page.html"), pageHtml, "utf-8");
188002
188165
  } catch (err) {
188003
188166
  warnings.push(`page.html write failed: ${err}`);
188004
188167
  }
188005
188168
  if (visibleTextContent) {
188006
- writeFileSync49(join111(outputDir, "extracted", "visible-text.txt"), visibleTextContent, "utf-8");
188169
+ writeFileSync49(join113(outputDir, "extracted", "visible-text.txt"), visibleTextContent, "utf-8");
188007
188170
  }
188008
188171
  const geminiCaptions = await captionImagesWithGemini(outputDir, progress, warnings);
188009
188172
  progress("design", "Generating asset descriptions...");
@@ -188013,7 +188176,7 @@ ${extracted.bodyHtml}
188013
188176
  const hasGeminiKey = !!(process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY);
188014
188177
  const header = hasGeminiKey ? "# Asset Descriptions\n\nOne line per file. Read this instead of opening every image individually.\n\nTo find a specific brand or icon, **grep this file for the brand name in the description text** (e.g. `grep -i 'autodesk' asset-descriptions.md`). The Gemini Vision captions identify what's actually in each file \u2014 that's the agent's selector.\n\nThe `logo-<hash>.svg` filename prefix is a cheap structural hint (DOM said this SVG was inside a `<header>`, home-link `<a>`, or had an aria-label matching the page brand). It is NOT a content claim \u2014 many `logo-*` files are nav icons or decorative shapes. Trust the captions, not the filename prefix.\n\n" : "# Asset Descriptions\n\n\u26A0\uFE0F GEMINI_API_KEY not set \u2014 descriptions below are catalog-derived (alt text, headings, section context, filename) instead of Vision-generated. To get richer Vision descriptions on the next capture, set GEMINI_API_KEY (or GOOGLE_API_KEY) and re-run.\n\nThe `logo-<hash>.svg` filename prefix is a structural hint (DOM said this SVG was inside a `<header>`, home-link `<a>`, or had an aria-label matching the page brand). To pick the actual brand logo without Vision, open the `logo-*` candidates in a previewer or rasterize them with `sharp` before referencing \u2014 composing a fake logo ships off-brand in the final video.\n\n";
188015
188178
  writeFileSync49(
188016
- join111(outputDir, "extracted", "asset-descriptions.md"),
188179
+ join113(outputDir, "extracted", "asset-descriptions.md"),
188017
188180
  header + lines.map((l) => "- " + l).join("\n") + "\n",
188018
188181
  "utf-8"
188019
188182
  );
@@ -188028,19 +188191,19 @@ ${extracted.bodyHtml}
188028
188191
  try {
188029
188192
  const { createScrollContactSheet: createScrollContactSheet2, createAssetContactSheet: createAssetContactSheet2, createSvgContactSheet: createSvgContactSheet2 } = await Promise.resolve().then(() => (init_contactSheet(), contactSheet_exports));
188030
188193
  const scrollSheets = await createScrollContactSheet2(
188031
- join111(outputDir, "screenshots"),
188032
- join111(outputDir, "screenshots", "contact-sheet.jpg")
188194
+ join113(outputDir, "screenshots"),
188195
+ join113(outputDir, "screenshots", "contact-sheet.jpg")
188033
188196
  );
188034
188197
  if (scrollSheets.length > 0)
188035
188198
  progress(
188036
188199
  "design",
188037
188200
  `Screenshot contact sheet generated (${scrollSheets.length} page${scrollSheets.length > 1 ? "s" : ""})`
188038
188201
  );
188039
- const assetsImgDir = join111(outputDir, "assets");
188202
+ const assetsImgDir = join113(outputDir, "assets");
188040
188203
  if (existsSync105(assetsImgDir)) {
188041
188204
  const assetSheets = await createAssetContactSheet2(
188042
188205
  assetsImgDir,
188043
- join111(outputDir, "assets", "contact-sheet.jpg")
188206
+ join113(outputDir, "assets", "contact-sheet.jpg")
188044
188207
  );
188045
188208
  if (assetSheets.length > 0)
188046
188209
  progress(
@@ -188048,9 +188211,9 @@ ${extracted.bodyHtml}
188048
188211
  `Asset contact sheet generated (${assetSheets.length} page${assetSheets.length > 1 ? "s" : ""})`
188049
188212
  );
188050
188213
  }
188051
- const svgsDir = join111(outputDir, "assets", "svgs");
188052
- const assetsRootDir = join111(outputDir, "assets");
188053
- const svgOutputPath = existsSync105(svgsDir) ? join111(outputDir, "assets", "svgs", "contact-sheet.jpg") : join111(outputDir, "assets", "contact-sheet-svgs.jpg");
188214
+ const svgsDir = join113(outputDir, "assets", "svgs");
188215
+ const assetsRootDir = join113(outputDir, "assets");
188216
+ const svgOutputPath = existsSync105(svgsDir) ? join113(outputDir, "assets", "svgs", "contact-sheet.jpg") : join113(outputDir, "assets", "contact-sheet-svgs.jpg");
188054
188217
  const svgSheets = await createSvgContactSheet2(svgsDir, svgOutputPath, assetsRootDir);
188055
188218
  if (svgSheets.length > 0)
188056
188219
  progress(
@@ -188066,7 +188229,7 @@ ${extracted.bodyHtml}
188066
188229
  animationCatalog,
188067
188230
  screenshots.length > 0,
188068
188231
  discoveredLotties.length > 0,
188069
- existsSync105(join111(outputDir, "extracted", "shaders.json")),
188232
+ existsSync105(join113(outputDir, "extracted", "shaders.json")),
188070
188233
  catalogedAssets,
188071
188234
  progress,
188072
188235
  warnings,
@@ -188375,9 +188538,9 @@ __export(state_exports, {
188375
188538
  writeStackOutputs: () => writeStackOutputs
188376
188539
  });
188377
188540
  import { existsSync as existsSync106, mkdirSync as mkdirSync57, readdirSync as readdirSync36, readFileSync as readFileSync75, rmSync as rmSync28, writeFileSync as writeFileSync50 } from "fs";
188378
- import { dirname as dirname53, join as join113 } from "path";
188541
+ import { dirname as dirname53, join as join114 } from "path";
188379
188542
  function stateFilePath(stackName = DEFAULT_STACK_NAME, cwd = process.cwd()) {
188380
- return join113(cwd, STATE_DIR_NAME, `${STATE_FILE_PREFIX}${stackName}.json`);
188543
+ return join114(cwd, STATE_DIR_NAME, `${STATE_FILE_PREFIX}${stackName}.json`);
188381
188544
  }
188382
188545
  function writeStackOutputs(outputs, cwd = process.cwd()) {
188383
188546
  const path2 = stateFilePath(outputs.stackName, cwd);
@@ -188399,7 +188562,7 @@ function deleteStackOutputs(stackName = DEFAULT_STACK_NAME, cwd = process.cwd())
188399
188562
  if (existsSync106(path2)) rmSync28(path2);
188400
188563
  }
188401
188564
  function listStackNames(cwd = process.cwd()) {
188402
- const dir = join113(cwd, STATE_DIR_NAME);
188565
+ const dir = join114(cwd, STATE_DIR_NAME);
188403
188566
  if (!existsSync106(dir)) return [];
188404
188567
  return readdirSync36(dir).filter((f3) => f3.startsWith(STATE_FILE_PREFIX) && f3.endsWith(".json")).map((f3) => f3.slice(STATE_FILE_PREFIX.length, -".json".length));
188405
188568
  }
@@ -188432,7 +188595,7 @@ var init_state = __esm({
188432
188595
  // src/commands/lambda/sam.ts
188433
188596
  import { execFileSync as execFileSync17, spawnSync as spawnSync4 } from "child_process";
188434
188597
  import { existsSync as existsSync107 } from "fs";
188435
- import { join as join114 } from "path";
188598
+ import { join as join115 } from "path";
188436
188599
  function assertSamAvailable() {
188437
188600
  try {
188438
188601
  execFileSync17("sam", ["--version"], { stdio: "ignore" });
@@ -188452,7 +188615,7 @@ function assertAwsCliAvailable() {
188452
188615
  }
188453
188616
  }
188454
188617
  function locateSamTemplate(repoRoot2) {
188455
- const candidate = join114(repoRoot2, "examples", "aws-lambda", "template.yaml");
188618
+ const candidate = join115(repoRoot2, "examples", "aws-lambda", "template.yaml");
188456
188619
  if (!existsSync107(candidate)) {
188457
188620
  throw new Error(
188458
188621
  `[lambda] SAM template not found at ${candidate}. If you're running from an installed package, point --sam-template at your local copy of examples/aws-lambda/template.yaml.`
@@ -188486,7 +188649,7 @@ function samDeploy(opts) {
188486
188649
  if (opts.awsProfile) {
188487
188650
  args.push("--profile", opts.awsProfile);
188488
188651
  }
188489
- const samDir = join114(opts.repoRoot, "examples", "aws-lambda");
188652
+ const samDir = join115(opts.repoRoot, "examples", "aws-lambda");
188490
188653
  const result = spawnSync4("sam", args, { cwd: samDir, stdio: opts.stdio ?? "inherit" });
188491
188654
  if (result.status !== 0) {
188492
188655
  throw new Error(
@@ -188504,7 +188667,7 @@ function samDelete(opts) {
188504
188667
  if (opts.awsProfile) {
188505
188668
  args.push("--profile", opts.awsProfile);
188506
188669
  }
188507
- const samDir = join114(opts.repoRoot, "examples", "aws-lambda");
188670
+ const samDir = join115(opts.repoRoot, "examples", "aws-lambda");
188508
188671
  const result = spawnSync4("sam", args, { cwd: samDir, stdio: opts.stdio ?? "inherit" });
188509
188672
  if (result.status !== 0) {
188510
188673
  throw new Error(`[lambda] sam delete exited with code ${result.status ?? "unknown"}`);
@@ -188588,7 +188751,7 @@ __export(deploy_exports, {
188588
188751
  });
188589
188752
  import { spawnSync as spawnSync5 } from "child_process";
188590
188753
  import { existsSync as existsSync109 } from "fs";
188591
- import { join as join115, resolve as resolve71 } from "path";
188754
+ import { join as join116, resolve as resolve71 } from "path";
188592
188755
  async function runDeploy(args = {}) {
188593
188756
  const resolved2 = {
188594
188757
  stackName: args.stackName ?? DEFAULT_STACK_NAME,
@@ -188605,7 +188768,7 @@ async function runDeploy(args = {}) {
188605
188768
  console.log(c.dim("\u2192 Building handler ZIP"));
188606
188769
  buildHandlerZip(root);
188607
188770
  } else {
188608
- const zip = join115(root, "packages", "aws-lambda", "dist", "handler.zip");
188771
+ const zip = join116(root, "packages", "aws-lambda", "dist", "handler.zip");
188609
188772
  if (!existsSync109(zip)) {
188610
188773
  throw new Error(
188611
188774
  `--skip-build set but ${zip} does not exist. Run \`bun run --cwd packages/aws-lambda build:zip\` first or drop --skip-build.`
@@ -188649,7 +188812,7 @@ async function runDeploy(args = {}) {
188649
188812
  function buildHandlerZip(root) {
188650
188813
  const result = spawnSync5(
188651
188814
  "bun",
188652
- ["run", "--cwd", join115(root, "packages", "aws-lambda"), "build:zip"],
188815
+ ["run", "--cwd", join116(root, "packages", "aws-lambda"), "build:zip"],
188653
188816
  { stdio: "inherit" }
188654
188817
  );
188655
188818
  if (result.status !== 0) {
@@ -188719,13 +188882,13 @@ var init_sites = __esm({
188719
188882
 
188720
188883
  // src/commands/lambda/_dimensions.ts
188721
188884
  import { readFileSync as readFileSync76 } from "fs";
188722
- import { join as join116 } from "path";
188885
+ import { join as join117 } from "path";
188723
188886
  function warnOnDimensionMismatch(args) {
188724
188887
  if (args.quiet) return;
188725
188888
  if (args.outputResolution) return;
188726
188889
  let html;
188727
188890
  try {
188728
- html = readFileSync76(join116(args.projectDir, "index.html"), "utf-8");
188891
+ html = readFileSync76(join117(args.projectDir, "index.html"), "utf-8");
188729
188892
  } catch {
188730
188893
  return;
188731
188894
  }
@@ -188755,7 +188918,7 @@ __export(render_exports2, {
188755
188918
  runRender: () => runRender
188756
188919
  });
188757
188920
  import { existsSync as existsSync110 } from "fs";
188758
- import { join as join117, resolve as resolvePath2 } from "path";
188921
+ import { join as join118, resolve as resolvePath2 } from "path";
188759
188922
  async function loadSDK2() {
188760
188923
  return import("@hyperframes/aws-lambda/sdk");
188761
188924
  }
@@ -188771,7 +188934,7 @@ async function runRender(args) {
188771
188934
  });
188772
188935
  const variables = resolveVariablesArg(args.variables, args.variablesFile);
188773
188936
  if (variables && Object.keys(variables).length > 0) {
188774
- const indexPath2 = join117(projectDir, "index.html");
188937
+ const indexPath2 = join118(projectDir, "index.html");
188775
188938
  if (existsSync110(indexPath2)) {
188776
188939
  const issues = validateVariablesAgainstProject(indexPath2, variables);
188777
188940
  reportVariableIssues(issues, { strict: args.strictVariables ?? false, quiet: args.json });
@@ -188906,7 +189069,7 @@ __export(render_batch_exports, {
188906
189069
  runWithConcurrencyLimit: () => runWithConcurrencyLimit
188907
189070
  });
188908
189071
  import { existsSync as existsSync111, readFileSync as readFileSync77 } from "fs";
188909
- import { join as join118, resolve as resolvePath3 } from "path";
189072
+ import { join as join119, resolve as resolvePath3 } from "path";
188910
189073
  async function loadSDK3() {
188911
189074
  return import("@hyperframes/aws-lambda/sdk");
188912
189075
  }
@@ -188930,7 +189093,7 @@ async function runRenderBatch(args) {
188930
189093
  outputResolution: args.outputResolution,
188931
189094
  quiet: args.json
188932
189095
  });
188933
- const schema = loadProjectVariableSchema(join118(projectDir, "index.html"));
189096
+ const schema = loadProjectVariableSchema(join119(projectDir, "index.html"));
188934
189097
  const strict = args.strictVariables ?? false;
188935
189098
  let hadStrictIssue = false;
188936
189099
  for (const { entry, lineNumber } of entries2) {
@@ -189978,7 +190141,7 @@ __export(cloudrun_exports, {
189978
190141
  import { spawnSync as spawnSync6 } from "child_process";
189979
190142
  import { existsSync as existsSync113, mkdirSync as mkdirSync58, readFileSync as readFileSync79, writeFileSync as writeFileSync51 } from "fs";
189980
190143
  import { homedir as homedir20 } from "os";
189981
- import { join as join119, resolve as resolve72 } from "path";
190144
+ import { join as join120, resolve as resolve72 } from "path";
189982
190145
  function loadCloudRunAdapter() {
189983
190146
  cloudRunAdapterPromise ??= Promise.all([
189984
190147
  import("@hyperframes/gcp-cloud-run/sdk"),
@@ -189997,10 +190160,10 @@ Or, for an opt-in project setup:
189997
190160
  ${c.accent("npm install @hyperframes/gcp-cloud-run")}`;
189998
190161
  }
189999
190162
  function stateDir() {
190000
- return join119(homedir20(), ".hyperframes");
190163
+ return join120(homedir20(), ".hyperframes");
190001
190164
  }
190002
190165
  function statePath() {
190003
- return join119(stateDir(), "cloudrun-state.json");
190166
+ return join120(stateDir(), "cloudrun-state.json");
190004
190167
  }
190005
190168
  function writeState(state) {
190006
190169
  mkdirSync58(stateDir(), { recursive: true });
@@ -190157,11 +190320,11 @@ function machineVars(args, project, region, image) {
190157
190320
  }
190158
190321
  function findRepoRoot(tfDir) {
190159
190322
  const candidate = resolve72(tfDir, "..", "..", "..");
190160
- if (existsSync113(join119(candidate, "packages", "gcp-cloud-run", "Dockerfile"))) return candidate;
190323
+ if (existsSync113(join120(candidate, "packages", "gcp-cloud-run", "Dockerfile"))) return candidate;
190161
190324
  return null;
190162
190325
  }
190163
190326
  function writeCloudBuildConfig(image) {
190164
- const cfgPath = join119(stateDir(), "cloudrun-cloudbuild.yaml");
190327
+ const cfgPath = join120(stateDir(), "cloudrun-cloudbuild.yaml");
190165
190328
  mkdirSync58(stateDir(), { recursive: true });
190166
190329
  writeFileSync51(
190167
190330
  cfgPath,
@@ -190453,7 +190616,7 @@ function resolveAndValidateVariables(args, projectDir) {
190453
190616
  args["variables-file"]
190454
190617
  );
190455
190618
  if (variables && Object.keys(variables).length > 0) {
190456
- const indexPath2 = join119(projectDir, "index.html");
190619
+ const indexPath2 = join120(projectDir, "index.html");
190457
190620
  if (existsSync113(indexPath2)) {
190458
190621
  const issues = validateVariablesAgainstProject(indexPath2, variables);
190459
190622
  reportVariableIssues(issues, {
@@ -193438,15 +193601,15 @@ var init_jsonl = __esm({
193438
193601
 
193439
193602
  // ../core/dist/figma/manifest.js
193440
193603
  import { appendFileSync as appendFileSync2, existsSync as existsSync116, mkdirSync as mkdirSync61, readFileSync as readFileSync83, writeFileSync as writeFileSync54 } from "fs";
193441
- import { join as join120 } from "path";
193604
+ import { join as join121 } from "path";
193442
193605
  function mediaDir(projectDir) {
193443
- return join120(projectDir, ".media");
193606
+ return join121(projectDir, ".media");
193444
193607
  }
193445
193608
  function manifestPath(projectDir) {
193446
- return join120(mediaDir(projectDir), MANIFEST_FILE2);
193609
+ return join121(mediaDir(projectDir), MANIFEST_FILE2);
193447
193610
  }
193448
193611
  function typeDirPath(projectDir, type) {
193449
- return join120(mediaDir(projectDir), TYPE_DIRS[type]);
193612
+ return join121(mediaDir(projectDir), TYPE_DIRS[type]);
193450
193613
  }
193451
193614
  function isFigmaManifestRecord(value) {
193452
193615
  if (typeof value !== "object" || value === null)
@@ -193533,12 +193696,12 @@ var init_manifest = __esm({
193533
193696
 
193534
193697
  // ../core/dist/figma/mediaIndex.js
193535
193698
  import { mkdirSync as mkdirSync63, writeFileSync as writeFileSync55 } from "fs";
193536
- import { dirname as dirname57, join as join121 } from "path";
193699
+ import { dirname as dirname57, join as join123 } from "path";
193537
193700
  function isRow(value) {
193538
193701
  return typeof value === "object" && value !== null;
193539
193702
  }
193540
193703
  function indexPath(projectDir) {
193541
- return join121(mediaDir(projectDir), "index.md");
193704
+ return join123(mediaDir(projectDir), "index.md");
193542
193705
  }
193543
193706
  function pad(str, len2) {
193544
193707
  return String(str ?? "").padEnd(len2);
@@ -193650,9 +193813,9 @@ var init_sanitizeSvg = __esm({
193650
193813
 
193651
193814
  // ../core/dist/figma/bindings.js
193652
193815
  import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync64, writeFileSync as writeFileSync56 } from "fs";
193653
- import { join as join123 } from "path";
193816
+ import { join as join124 } from "path";
193654
193817
  function bindingsPath(projectDir) {
193655
- return join123(mediaDir(projectDir), BINDINGS_FILE);
193818
+ return join124(mediaDir(projectDir), BINDINGS_FILE);
193656
193819
  }
193657
193820
  function isRecord9(value) {
193658
193821
  return typeof value === "object" && value !== null;
@@ -194253,7 +194416,7 @@ __export(asset_exports, {
194253
194416
  runAssetImportMany: () => runAssetImportMany
194254
194417
  });
194255
194418
  import { existsSync as existsSync117 } from "fs";
194256
- import { join as join124, relative as relative25 } from "path";
194419
+ import { join as join125, relative as relative25 } from "path";
194257
194420
  function gatherAssetRefs(positionals) {
194258
194421
  return positionals.flatMap((r2) => /^https?:/i.test(r2.trim()) ? [r2] : r2.split(",")).map((r2) => r2.trim()).filter((r2) => r2.length > 0);
194259
194422
  }
@@ -194267,7 +194430,7 @@ function requireNodeRef(refInput) {
194267
194430
  }
194268
194431
  function reuseExisting(fileKey, nodeId, opts, version2, deps, description, entity) {
194269
194432
  const existing = findAllByFigmaNode(deps.projectDir, fileKey, nodeId).find(
194270
- (r2) => r2.provenance.format === opts.format && (r2.provenance.scale ?? 1) === (opts.scale ?? 1) && r2.provenance.version === version2 && existsSync117(join124(deps.projectDir, r2.path))
194433
+ (r2) => r2.provenance.format === opts.format && (r2.provenance.scale ?? 1) === (opts.scale ?? 1) && r2.provenance.version === version2 && existsSync117(join125(deps.projectDir, r2.path))
194271
194434
  );
194272
194435
  if (!existing) return null;
194273
194436
  let record = existing;
@@ -194290,7 +194453,7 @@ async function freezeAndRecord(fileKey, nodeId, url, ext, opts, version2, deps,
194290
194453
  bytes = new TextEncoder().encode(sanitizeSvg(new TextDecoder().decode(bytes)));
194291
194454
  }
194292
194455
  const id = nextId(deps.projectDir, "image");
194293
- const destAbs = join124(typeDirPath(deps.projectDir, "image"), `${id}.${ext}`);
194456
+ const destAbs = join125(typeDirPath(deps.projectDir, "image"), `${id}.${ext}`);
194294
194457
  freezeBytes(bytes, destAbs);
194295
194458
  const record = {
194296
194459
  id,
@@ -194460,11 +194623,11 @@ __export(tokens_exports, {
194460
194623
  runTokensImport: () => runTokensImport
194461
194624
  });
194462
194625
  import { writeFileSync as writeFileSync57 } from "fs";
194463
- import { join as join125 } from "path";
194626
+ import { join as join126 } from "path";
194464
194627
  async function runTokensImport(refInput, deps) {
194465
194628
  const { fileKey } = parseFigmaRef(refInput);
194466
194629
  const { version: version2 } = await deps.client.fileVersion(fileKey);
194467
- const sidecarPath = join125(deps.projectDir, "figma-tokens.json");
194630
+ const sidecarPath = join126(deps.projectDir, "figma-tokens.json");
194468
194631
  let vars = null;
194469
194632
  try {
194470
194633
  vars = await deps.client.variables(fileKey);
@@ -194539,7 +194702,7 @@ __export(component_exports, {
194539
194702
  runComponentImport: () => runComponentImport
194540
194703
  });
194541
194704
  import { existsSync as existsSync118, mkdirSync as mkdirSync65, writeFileSync as writeFileSync58 } from "fs";
194542
- import { join as join126, relative as relative26 } from "path";
194705
+ import { join as join127, relative as relative26 } from "path";
194543
194706
  function escapeAttr2(value) {
194544
194707
  return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
194545
194708
  }
@@ -194550,7 +194713,7 @@ async function runComponentImport(refInput, deps) {
194550
194713
  const bindings = resolveBindings(tree, readBindings(deps.projectDir));
194551
194714
  const mapped = nodeToHtml(tree, bindings, { rootName: deps.name });
194552
194715
  const name = slugify(deps.name ?? tree.name);
194553
- const componentDir = join126(deps.projectDir, "compositions", "components", name);
194716
+ const componentDir = join127(deps.projectDir, "compositions", "components", name);
194554
194717
  if (existsSync118(componentDir))
194555
194718
  console.warn(
194556
194719
  `component dir compositions/components/${name} already exists \u2014 overwriting (rename the figma frame for a separate import)`
@@ -194562,7 +194725,7 @@ async function runComponentImport(refInput, deps) {
194562
194725
  componentDir,
194563
194726
  deps
194564
194727
  );
194565
- const htmlFile = join126(componentDir, `${name}.html`);
194728
+ const htmlFile = join127(componentDir, `${name}.html`);
194566
194729
  writeFileSync58(htmlFile, html + "\n");
194567
194730
  const registryItem = {
194568
194731
  name,
@@ -194584,7 +194747,7 @@ async function runComponentImport(refInput, deps) {
194584
194747
  ]
194585
194748
  };
194586
194749
  writeFileSync58(
194587
- join126(componentDir, "registry-item.json"),
194750
+ join127(componentDir, "registry-item.json"),
194588
194751
  JSON.stringify(registryItem, null, 2) + "\n"
194589
194752
  );
194590
194753
  return {
@@ -194609,7 +194772,7 @@ async function rasterizeFallback(mapped, fileKey, componentDir, deps) {
194609
194772
  continue;
194610
194773
  }
194611
194774
  frozenAssets.push(asset.record.path);
194612
- const srcRel = relative26(componentDir, join126(deps.projectDir, asset.record.path)).replaceAll(
194775
+ const srcRel = relative26(componentDir, join127(deps.projectDir, asset.record.path)).replaceAll(
194613
194776
  "\\",
194614
194777
  "/"
194615
194778
  );
@@ -194758,7 +194921,7 @@ __export(autoUpdate_exports, {
194758
194921
  import { spawn as spawn16 } from "child_process";
194759
194922
  import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync66, openSync as openSync6 } from "fs";
194760
194923
  import { homedir as homedir21 } from "os";
194761
- import { join as join127 } from "path";
194924
+ import { join as join128 } from "path";
194762
194925
  import { compareVersions as compareVersions3 } from "compare-versions";
194763
194926
  function isAutoInstallDisabled() {
194764
194927
  if (isDevMode()) return true;
@@ -194781,7 +194944,7 @@ function log(line2) {
194781
194944
  }
194782
194945
  function launchDetachedInstall(invocation, displayCommand, version2) {
194783
194946
  mkdirSync66(CONFIG_DIR3, { recursive: true, mode: 448 });
194784
- const configFile = join127(CONFIG_DIR3, "config.json");
194947
+ const configFile = join128(CONFIG_DIR3, "config.json");
194785
194948
  const nodeScript = `
194786
194949
  const { execFile } = require("node:child_process");
194787
194950
  const { readFileSync, renameSync, writeFileSync } = require("node:fs");
@@ -194902,8 +195065,8 @@ var init_autoUpdate = __esm({
194902
195065
  init_config();
194903
195066
  init_env();
194904
195067
  init_installerDetection();
194905
- CONFIG_DIR3 = join127(homedir21(), ".hyperframes");
194906
- LOG_FILE = join127(CONFIG_DIR3, "auto-update.log");
195068
+ CONFIG_DIR3 = join128(homedir21(), ".hyperframes");
195069
+ LOG_FILE = join128(CONFIG_DIR3, "auto-update.log");
194907
195070
  PENDING_TIMEOUT_MS = 10 * 60 * 1e3;
194908
195071
  }
194909
195072
  });
@@ -195090,7 +195253,7 @@ var init_help = __esm({
195090
195253
  init_version();
195091
195254
  init_dist();
195092
195255
  init_runId();
195093
- import { dirname as dirname58, join as join128 } from "path";
195256
+ import { dirname as dirname58, join as join129 } from "path";
195094
195257
  import { fileURLToPath as fileURLToPath16 } from "url";
195095
195258
  import { existsSync as existsSync119 } from "fs";
195096
195259
 
@@ -195210,7 +195373,7 @@ for (const stream of [process.stdout, process.stderr]) {
195210
195373
  }
195211
195374
  (() => {
195212
195375
  const here = dirname58(fileURLToPath16(import.meta.url));
195213
- const shader = join128(here, "shaderTransitionWorker.js");
195376
+ const shader = join129(here, "shaderTransitionWorker.js");
195214
195377
  if (!process.env.HF_SHADER_WORKER_ENTRY && existsSync119(shader)) {
195215
195378
  process.env.HF_SHADER_WORKER_ENTRY = shader;
195216
195379
  }