hyperframes 0.7.34 → 0.7.36

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.34" : "0.0.0-dev";
53
+ VERSION = true ? "0.7.36" : "0.0.0-dev";
54
54
  }
55
55
  });
56
56
 
@@ -4891,7 +4891,7 @@ var require_util = __commonJS({
4891
4891
  return path2;
4892
4892
  }
4893
4893
  exports.normalize = normalize;
4894
- function join113(aRoot, aPath) {
4894
+ function join114(aRoot, aPath) {
4895
4895
  if (aRoot === "") {
4896
4896
  aRoot = ".";
4897
4897
  }
@@ -4923,7 +4923,7 @@ var require_util = __commonJS({
4923
4923
  }
4924
4924
  return joined;
4925
4925
  }
4926
- exports.join = join113;
4926
+ exports.join = join114;
4927
4927
  exports.isAbsolute = function(aPath) {
4928
4928
  return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
4929
4929
  };
@@ -5096,7 +5096,7 @@ var require_util = __commonJS({
5096
5096
  parsed.path = parsed.path.substring(0, index + 1);
5097
5097
  }
5098
5098
  }
5099
- sourceURL = join113(urlGenerate(parsed), sourceURL);
5099
+ sourceURL = join114(urlGenerate(parsed), sourceURL);
5100
5100
  }
5101
5101
  return normalize(sourceURL);
5102
5102
  }
@@ -62126,10 +62126,47 @@ var init_processTracker = __esm({
62126
62126
 
62127
62127
  // ../engine/src/utils/ffmpegBinaries.ts
62128
62128
  import { execFileSync } from "child_process";
62129
- import { existsSync as existsSync5 } from "fs";
62130
- import { resolve as resolve5 } from "path";
62129
+ import { accessSync, constants, existsSync as existsSync5 } from "fs";
62130
+ import { delimiter, join as join7, resolve as resolve5 } from "path";
62131
+ function candidateFileName(candidate) {
62132
+ return candidate.split(/[\\/]/).at(-1)?.toLowerCase() ?? candidate.toLowerCase();
62133
+ }
62134
+ function chooseBestPathCandidate(name, candidates) {
62135
+ const normalized = candidates.map((candidate) => candidate.trim()).filter(Boolean);
62136
+ return normalized.find((candidate) => candidateFileName(candidate) === `${name}.exe`) ?? normalized.find((candidate) => candidateFileName(candidate) === name) ?? normalized.find((candidate) => !candidateFileName(candidate).match(/\.(cmd|bat)$/i)) ?? normalized[0];
62137
+ }
62138
+ function scanPath(name) {
62139
+ const pathValue = process.env.PATH;
62140
+ if (!pathValue) return void 0;
62141
+ const extensions = process.platform === "win32" ? [
62142
+ ".exe",
62143
+ ...new Set(
62144
+ (process.env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").map((ext) => ext.trim().toLowerCase()).filter(Boolean)
62145
+ ),
62146
+ ""
62147
+ ] : [""];
62148
+ const candidates = [];
62149
+ for (const dir of pathValue.split(delimiter)) {
62150
+ if (!dir) continue;
62151
+ for (const ext of extensions) {
62152
+ const candidate = join7(dir, `${name}${ext}`);
62153
+ if (isExecutablePathCandidate(candidate)) candidates.push(candidate);
62154
+ }
62155
+ }
62156
+ return chooseBestPathCandidate(name, candidates);
62157
+ }
62158
+ function isExecutablePathCandidate(candidate) {
62159
+ if (process.platform === "win32") return existsSync5(candidate);
62160
+ try {
62161
+ accessSync(candidate, constants.X_OK);
62162
+ return true;
62163
+ } catch {
62164
+ return false;
62165
+ }
62166
+ }
62131
62167
  function findOnPath(name) {
62132
62168
  if (pathCache.has(name)) return pathCache.get(name);
62169
+ let found;
62133
62170
  try {
62134
62171
  const command2 = process.platform === "win32" ? "where" : "which";
62135
62172
  const output = execFileSync(command2, [name], {
@@ -62137,14 +62174,13 @@ function findOnPath(name) {
62137
62174
  stdio: ["pipe", "pipe", "pipe"],
62138
62175
  timeout: 5e3
62139
62176
  });
62140
- const first = output.split(/\r?\n/).map((s2) => s2.trim()).find(Boolean);
62141
- const resolved = first ? resolve5(first) : void 0;
62142
- pathCache.set(name, resolved);
62143
- return resolved;
62177
+ found = chooseBestPathCandidate(name, output.split(/\r?\n/));
62144
62178
  } catch {
62145
- pathCache.set(name, void 0);
62146
- return void 0;
62179
+ found = scanPath(name);
62147
62180
  }
62181
+ const resolved = found ? resolve5(found) : void 0;
62182
+ pathCache.set(name, resolved);
62183
+ return resolved;
62148
62184
  }
62149
62185
  function getConfiguredBinary(envName, binaryName) {
62150
62186
  const configured = process.env[envName]?.trim();
@@ -62161,16 +62197,20 @@ function assertConfiguredFfmpegBinariesExist() {
62161
62197
  const ffmpegPath = process.env[FFMPEG_PATH_ENV]?.trim();
62162
62198
  if (ffmpegPath && !existsSync5(ffmpegPath)) {
62163
62199
  throw new Error(
62164
- `[FFmpeg] FFmpeg binary not found at ${FFMPEG_PATH_ENV}="${ffmpegPath}". Install FFmpeg or unset the override.`
62200
+ `[FFmpeg] FFmpeg binary not found at ${FFMPEG_PATH_ENV}="${ffmpegPath}". Install FFmpeg or unset the override.${pathEncodingHint(ffmpegPath)}`
62165
62201
  );
62166
62202
  }
62167
62203
  const ffprobePath = process.env[FFPROBE_PATH_ENV]?.trim();
62168
62204
  if (ffprobePath && !existsSync5(ffprobePath)) {
62169
62205
  throw new Error(
62170
- `[FFmpeg] FFprobe binary not found at ${FFPROBE_PATH_ENV}="${ffprobePath}". Install FFmpeg or unset the override.`
62206
+ `[FFmpeg] FFprobe binary not found at ${FFPROBE_PATH_ENV}="${ffprobePath}". Install FFmpeg or unset the override.${pathEncodingHint(ffprobePath)}`
62171
62207
  );
62172
62208
  }
62173
62209
  }
62210
+ function pathEncodingHint(configuredPath) {
62211
+ if (!configuredPath.includes("\uFFFD")) return "";
62212
+ return " The path contains a Unicode replacement character, which usually means it was mangled while being copied or decoded.";
62213
+ }
62174
62214
  var FFMPEG_PATH_ENV, FFPROBE_PATH_ENV, pathCache;
62175
62215
  var init_ffmpegBinaries = __esm({
62176
62216
  "../engine/src/utils/ffmpegBinaries.ts"() {
@@ -62820,7 +62860,7 @@ var init_ffprobe = __esm({
62820
62860
  // ../engine/src/services/chunkEncoder.ts
62821
62861
  import { spawn as spawn4 } from "child_process";
62822
62862
  import { copyFileSync, existsSync as existsSync6, mkdirSync as mkdirSync3, readdirSync as readdirSync2, statSync, writeFileSync as writeFileSync3 } from "fs";
62823
- import { join as join7, dirname as dirname4, extname as extname2 } from "path";
62863
+ import { join as join8, dirname as dirname4, extname as extname2 } from "path";
62824
62864
  function appendEncodeTimeoutMessage(error, timedOut, timeoutMs) {
62825
62865
  if (!timedOut) return error;
62826
62866
  return `${error}
@@ -63067,7 +63107,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
63067
63107
  if (options.useGpu) {
63068
63108
  gpuEncoder = await getCachedGpuEncoder();
63069
63109
  }
63070
- const inputPath = join7(framesDir, framePattern);
63110
+ const inputPath = join8(framesDir, framePattern);
63071
63111
  const inputArgs = ["-framerate", fpsToFfmpegArg(options.fps), "-i", inputPath];
63072
63112
  const args = buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder);
63073
63113
  return new Promise((resolve62) => {
@@ -63155,7 +63195,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
63155
63195
  }
63156
63196
  const chunkSize = Math.max(30, Math.floor(chunkSizeFrames));
63157
63197
  const chunkCount = Math.ceil(files.length / chunkSize);
63158
- const chunkDir = join7(dirname4(outputPath), "chunk-encode");
63198
+ const chunkDir = join8(dirname4(outputPath), "chunk-encode");
63159
63199
  if (!existsSync6(chunkDir)) mkdirSync3(chunkDir, { recursive: true });
63160
63200
  const chunkPaths = [];
63161
63201
  for (let i2 = 0; i2 < chunkCount; i2++) {
@@ -63172,8 +63212,8 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
63172
63212
  const startNumber = i2 * chunkSize;
63173
63213
  const framesInChunk = Math.min(chunkSize, files.length - startNumber);
63174
63214
  const ext = outputPath.endsWith(".webm") ? ".webm" : outputPath.endsWith(".mov") ? ".mov" : ".mp4";
63175
- const chunkPath = join7(chunkDir, `chunk_${String(i2).padStart(4, "0")}${ext}`);
63176
- const inputPath = join7(framesDir, framePattern);
63215
+ const chunkPath = join8(chunkDir, `chunk_${String(i2).padStart(4, "0")}${ext}`);
63216
+ const inputPath = join8(framesDir, framePattern);
63177
63217
  const inputArgs = [
63178
63218
  "-framerate",
63179
63219
  fpsToFfmpegArg(options.fps),
@@ -63238,7 +63278,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
63238
63278
  }
63239
63279
  chunkPaths.push(chunkPath);
63240
63280
  }
63241
- const concatListPath = join7(chunkDir, "concat-list.txt");
63281
+ const concatListPath = join8(chunkDir, "concat-list.txt");
63242
63282
  const concatInput = chunkPaths.map((path2) => `file '${path2.replace(/'/g, "'\\''")}'`).join("\n");
63243
63283
  writeFileSync3(concatListPath, concatInput, "utf-8");
63244
63284
  const concatArgs = [
@@ -63786,7 +63826,7 @@ var init_streamingEncoder = __esm({
63786
63826
  // ../engine/src/utils/urlDownloader.ts
63787
63827
  import { createWriteStream, existsSync as existsSync8, mkdirSync as mkdirSync5 } from "fs";
63788
63828
  import { createHash } from "crypto";
63789
- import { join as join8, extname as extname3 } from "path";
63829
+ import { join as join9, extname as extname3 } from "path";
63790
63830
  import { Readable } from "stream";
63791
63831
  import { finished } from "stream/promises";
63792
63832
  function isBlockedHost(hostname) {
@@ -63838,7 +63878,7 @@ async function downloadToTemp(url, destDir, timeoutMs = 3e5) {
63838
63878
  mkdirSync5(destDir, { recursive: true });
63839
63879
  }
63840
63880
  const filename = getFilenameFromUrl(url);
63841
- const localPath = join8(destDir, filename);
63881
+ const localPath = join9(destDir, filename);
63842
63882
  if (existsSync8(localPath)) {
63843
63883
  downloadPathCache.set(url, localPath);
63844
63884
  return localPath;
@@ -66358,7 +66398,7 @@ __export(dist_exports2, {
66358
66398
  import postcss2 from "postcss";
66359
66399
  import postcss22 from "postcss";
66360
66400
  import { existsSync as existsSync9, readFileSync as readFileSync4, readdirSync as readdirSync3 } from "fs";
66361
- import { dirname as dirname6, extname as extname4, isAbsolute as isAbsolute2, join as join9, posix as posix2, relative as relative2, resolve as resolve7 } from "path";
66401
+ import { dirname as dirname6, extname as extname4, isAbsolute as isAbsolute2, join as join10, posix as posix2, relative as relative2, resolve as resolve7 } from "path";
66362
66402
  function extractOpenTags(source) {
66363
66403
  const tags = [];
66364
66404
  let match;
@@ -67669,7 +67709,7 @@ function collectExternalStyles(projectDir, html, compSrcPath) {
67669
67709
  if (!rel.split(/\s+/).some((part) => part.toLowerCase() === "stylesheet")) continue;
67670
67710
  const href = tag.match(/\bhref\s*=\s*["']([^"']+)["']/i)?.[1] ?? "";
67671
67711
  if (!isLocalStylesheetHref(href)) continue;
67672
- const rootRelative = compSrcPath ? join9(dirname6(compSrcPath), href) : href;
67712
+ const rootRelative = compSrcPath ? join10(dirname6(compSrcPath), href) : href;
67673
67713
  const stylesheet = resolveExistingLocalAsset(projectDir, rootRelative);
67674
67714
  if (!stylesheet) continue;
67675
67715
  styles.push({ href, content: readFileSync4(stylesheet.resolved, "utf-8") });
@@ -67691,7 +67731,7 @@ function collectCssSources(projectDir, html, compSrcPath) {
67691
67731
  if (!rel.split(/\s+/).some((part) => part.toLowerCase() === "stylesheet")) continue;
67692
67732
  const href = readHtmlAttr(tag, "href") ?? "";
67693
67733
  if (!isLocalStylesheetHref(href)) continue;
67694
- const rootRelativePath = compSrcPath ? join9(dirname6(compSrcPath), href) : href;
67734
+ const rootRelativePath = compSrcPath ? join10(dirname6(compSrcPath), href) : href;
67695
67735
  const stylesheet = resolveExistingLocalAsset(projectDir, rootRelativePath);
67696
67736
  if (!stylesheet) continue;
67697
67737
  sources.push({
@@ -67751,7 +67791,7 @@ function resolveExistingLocalAsset(projectDir, url) {
67751
67791
  function resolveCssAssetCandidates(projectDir, url, htmlCompSrcPath, cssRootRelativePath) {
67752
67792
  if (url.startsWith("/")) return resolveLocalAssetCandidates(projectDir, url);
67753
67793
  if (cssRootRelativePath) {
67754
- return resolveLocalAssetCandidates(projectDir, join9(dirname6(cssRootRelativePath), url));
67794
+ return resolveLocalAssetCandidates(projectDir, join10(dirname6(cssRootRelativePath), url));
67755
67795
  }
67756
67796
  if (htmlCompSrcPath) {
67757
67797
  return resolveLocalAssetCandidates(projectDir, rewriteAssetPath(htmlCompSrcPath, url));
@@ -67780,14 +67820,14 @@ async function lintProject(projectDir) {
67780
67820
  const out = [];
67781
67821
  for (const entry of readdirSync3(dir, { withFileTypes: true })) {
67782
67822
  const relPath = rel ? `${rel}/${entry.name}` : entry.name;
67783
- if (entry.isDirectory()) out.push(...collectHtmlFiles(join9(dir, entry.name), relPath));
67823
+ if (entry.isDirectory()) out.push(...collectHtmlFiles(join10(dir, entry.name), relPath));
67784
67824
  else if (entry.isFile() && entry.name.endsWith(".html")) out.push(relPath);
67785
67825
  }
67786
67826
  return out;
67787
67827
  };
67788
67828
  const files = collectHtmlFiles(compositionsDir, "").sort();
67789
67829
  for (const file of files) {
67790
- const filePath = join9(compositionsDir, file);
67830
+ const filePath = join10(compositionsDir, file);
67791
67831
  const html = readFileSync4(filePath, "utf-8");
67792
67832
  const compSrcPath = `compositions/${file}`;
67793
67833
  allHtmlSources.push({ html, compSrcPath });
@@ -67965,7 +68005,7 @@ function lintMultipleRootCompositions(projectDir) {
67965
68005
  const rootCompositions = [];
67966
68006
  for (const file of rootHtmlFiles) {
67967
68007
  if (file === "caption-skin.html") continue;
67968
- const content = readFileSync4(join9(projectDir, file), "utf-8");
68008
+ const content = readFileSync4(join10(projectDir, file), "utf-8");
67969
68009
  if (/data-composition-id/i.test(content)) {
67970
68010
  rootCompositions.push(file);
67971
68011
  }
@@ -70464,7 +70504,7 @@ var init_inlineSubCompositions = __esm({
70464
70504
 
70465
70505
  // ../core/dist/compiler/htmlBundler.js
70466
70506
  import { readFileSync as readFileSync5, existsSync as existsSync10 } from "fs";
70467
- import { join as join10, resolve as resolve8, relative as relative3, dirname as dirname7, isAbsolute as isAbsolute3, sep as sep2 } from "path";
70507
+ import { join as join11, resolve as resolve8, relative as relative3, dirname as dirname7, isAbsolute as isAbsolute3, sep as sep2 } from "path";
70468
70508
  import { transformSync } from "esbuild";
70469
70509
  function getRuntimeScriptUrl() {
70470
70510
  const configured = (process.env.HYPERFRAME_RUNTIME_URL || "").trim();
@@ -70978,7 +71018,7 @@ function hoistCompositionScripts(container, opts) {
70978
71018
  }
70979
71019
  }
70980
71020
  async function bundleToSingleHtml(projectDir, options) {
70981
- const indexPath2 = join10(projectDir, "index.html");
71021
+ const indexPath2 = join11(projectDir, "index.html");
70982
71022
  if (!existsSync10(indexPath2))
70983
71023
  throw new Error("index.html not found in project directory");
70984
71024
  const rawHtml = readFileSync5(indexPath2, "utf-8");
@@ -71366,7 +71406,7 @@ import {
71366
71406
  utimesSync,
71367
71407
  writeFileSync as writeFileSync4
71368
71408
  } from "fs";
71369
- import { join as join11 } from "path";
71409
+ import { join as join12 } from "path";
71370
71410
  function readKeyStat(videoPath) {
71371
71411
  try {
71372
71412
  const stat3 = statSync3(videoPath);
@@ -71397,8 +71437,8 @@ function cacheEntryDirName(keyHash) {
71397
71437
  }
71398
71438
  function lookupCacheEntry(rootDir, input2) {
71399
71439
  const keyHash = computeCacheKey(input2);
71400
- const dir = join11(rootDir, cacheEntryDirName(keyHash));
71401
- const complete = existsSync11(join11(dir, COMPLETE_SENTINEL));
71440
+ const dir = join12(rootDir, cacheEntryDirName(keyHash));
71441
+ const complete = existsSync11(join12(dir, COMPLETE_SENTINEL));
71402
71442
  return { entry: { dir, keyHash }, hit: complete };
71403
71443
  }
71404
71444
  function partialCacheEntryDir(entry) {
@@ -71409,13 +71449,13 @@ function isTargetExistsRenameError(err) {
71409
71449
  return code === "EEXIST" || code === "ENOTEMPTY" || code === "EPERM";
71410
71450
  }
71411
71451
  function adoptPublishedWinner(entry, partialDir) {
71412
- if (!existsSync11(join11(entry.dir, COMPLETE_SENTINEL))) return null;
71452
+ if (!existsSync11(join12(entry.dir, COMPLETE_SENTINEL))) return null;
71413
71453
  removeDir(partialDir);
71414
71454
  return { dir: entry.dir, published: true };
71415
71455
  }
71416
71456
  function publishCacheEntry(entry, partialDir) {
71417
71457
  try {
71418
- writeFileSync4(join11(partialDir, COMPLETE_SENTINEL), "", "utf-8");
71458
+ writeFileSync4(join12(partialDir, COMPLETE_SENTINEL), "", "utf-8");
71419
71459
  } catch {
71420
71460
  return { dir: partialDir, published: false };
71421
71461
  }
@@ -71442,7 +71482,7 @@ function publishCacheEntry(entry, partialDir) {
71442
71482
  function touchCacheEntry(entry) {
71443
71483
  try {
71444
71484
  const now = /* @__PURE__ */ new Date();
71445
- utimesSync(join11(entry.dir, COMPLETE_SENTINEL), now, now);
71485
+ utimesSync(join12(entry.dir, COMPLETE_SENTINEL), now, now);
71446
71486
  } catch {
71447
71487
  }
71448
71488
  }
@@ -71467,7 +71507,7 @@ function directorySizeBytes(path2) {
71467
71507
  return 0;
71468
71508
  }
71469
71509
  for (const child of children) {
71470
- const childPath = join11(path2, child);
71510
+ const childPath = join12(path2, child);
71471
71511
  try {
71472
71512
  const stat3 = lstatSync(childPath);
71473
71513
  if (stat3.isDirectory()) {
@@ -71496,7 +71536,7 @@ function collectGcEntry(dir, name, now, minAgeMs, stats) {
71496
71536
  }
71497
71537
  let lastUseMs = dirStat.mtimeMs;
71498
71538
  try {
71499
- lastUseMs = statSync3(join11(dir, COMPLETE_SENTINEL)).mtimeMs;
71539
+ lastUseMs = statSync3(join12(dir, COMPLETE_SENTINEL)).mtimeMs;
71500
71540
  } catch {
71501
71541
  }
71502
71542
  return { dir, size: directorySizeBytes(dir), lastUseMs, ageMs: now - lastUseMs };
@@ -71506,7 +71546,7 @@ function collectGcEntry(dir, name, now, minAgeMs, stats) {
71506
71546
  }
71507
71547
  function gcSweepDue(rootDir, maxAgeMs) {
71508
71548
  try {
71509
- return Date.now() - statSync3(join11(rootDir, GC_MARKER)).mtimeMs > maxAgeMs;
71549
+ return Date.now() - statSync3(join12(rootDir, GC_MARKER)).mtimeMs > maxAgeMs;
71510
71550
  } catch {
71511
71551
  return true;
71512
71552
  }
@@ -71514,7 +71554,7 @@ function gcSweepDue(rootDir, maxAgeMs) {
71514
71554
  function gcExtractionCache(rootDir, opts) {
71515
71555
  const stats = { evictedEntries: 0, evictedBytes: 0, agedPartialsRemoved: 0 };
71516
71556
  try {
71517
- writeFileSync4(join11(rootDir, GC_MARKER), "", "utf-8");
71557
+ writeFileSync4(join12(rootDir, GC_MARKER), "", "utf-8");
71518
71558
  } catch {
71519
71559
  }
71520
71560
  try {
@@ -71523,7 +71563,7 @@ function gcExtractionCache(rootDir, opts) {
71523
71563
  for (const child of readdirSync4(rootDir, { withFileTypes: true })) {
71524
71564
  if (!child.isDirectory() || !isCacheLikeChild(child.name)) continue;
71525
71565
  const entry = collectGcEntry(
71526
- join11(rootDir, child.name),
71566
+ join12(rootDir, child.name),
71527
71567
  child.name,
71528
71568
  now,
71529
71569
  opts.minAgeMs,
@@ -71552,7 +71592,7 @@ function rehydrateCacheEntry(entry, options) {
71552
71592
  const suffix = `.${options.format}`;
71553
71593
  const files = readdirSync4(entry.dir).filter((f3) => f3.startsWith(FRAME_FILENAME_PREFIX) && f3.endsWith(suffix)).sort();
71554
71594
  files.forEach((file, idx) => {
71555
- framePaths.set(idx, join11(entry.dir, file));
71595
+ framePaths.set(idx, join12(entry.dir, file));
71556
71596
  });
71557
71597
  return {
71558
71598
  videoId: options.videoId,
@@ -71581,7 +71621,7 @@ var init_extractionCache = __esm({
71581
71621
  // ../engine/src/services/videoFrameExtractor.ts
71582
71622
  import { spawn as spawn6 } from "child_process";
71583
71623
  import { copyFileSync as copyFileSync2, existsSync as existsSync12, linkSync, mkdirSync as mkdirSync7, readdirSync as readdirSync5, rmSync as rmSync2 } from "fs";
71584
- import { isAbsolute as isAbsolute4, join as join12, posix as posix3, resolve as resolve9, sep as sep3 } from "path";
71624
+ import { isAbsolute as isAbsolute4, join as join13, posix as posix3, resolve as resolve9, sep as sep3 } from "path";
71585
71625
  function isVideoFrameFormat(value) {
71586
71626
  return typeof value === "string" && VIDEO_FRAME_FORMATS.includes(value);
71587
71627
  }
@@ -71657,12 +71697,12 @@ function parseImageElements(html) {
71657
71697
  async function extractVideoFramesRange(videoPath, videoId, startTime, duration, options, signal, config, outputDirOverride) {
71658
71698
  const ffmpegProcessTimeout = config?.ffmpegProcessTimeout ?? DEFAULT_CONFIG2.ffmpegProcessTimeout;
71659
71699
  const { fps, outputDir, quality = 95 } = options;
71660
- const videoOutputDir = outputDirOverride ?? join12(outputDir, videoId);
71700
+ const videoOutputDir = outputDirOverride ?? join13(outputDir, videoId);
71661
71701
  if (!existsSync12(videoOutputDir)) mkdirSync7(videoOutputDir, { recursive: true });
71662
71702
  const metadata = await extractMediaMetadata(videoPath);
71663
71703
  const format = resolveFrameFormat(metadata, options.format);
71664
71704
  const framePattern = `${FRAME_FILENAME_PREFIX}%05d.${format}`;
71665
- const outputPattern = join12(videoOutputDir, framePattern);
71705
+ const outputPattern = join13(videoOutputDir, framePattern);
71666
71706
  const isHdr = isHdrColorSpace(metadata.colorSpace);
71667
71707
  const isMacOS = process.platform === "darwin";
71668
71708
  const args = [];
@@ -71723,7 +71763,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
71723
71763
  const framePaths = /* @__PURE__ */ new Map();
71724
71764
  const files = readdirSync5(videoOutputDir).filter((f3) => f3.startsWith(FRAME_FILENAME_PREFIX) && f3.endsWith(`.${format}`)).sort();
71725
71765
  files.forEach((file, index) => {
71726
- framePaths.set(index, join12(videoOutputDir, file));
71766
+ framePaths.set(index, join13(videoOutputDir, file));
71727
71767
  });
71728
71768
  resolve62({
71729
71769
  videoId,
@@ -71774,7 +71814,7 @@ function extractedFramesFromDirectory(work, outputDir, srcPath, fps) {
71774
71814
  const framePattern = `${FRAME_FILENAME_PREFIX}%05d.${work.format}`;
71775
71815
  const framePaths = /* @__PURE__ */ new Map();
71776
71816
  extractedFrameFileNames(outputDir, work.format).forEach((file, index) => {
71777
- framePaths.set(index, join12(outputDir, file));
71817
+ framePaths.set(index, join13(outputDir, file));
71778
71818
  });
71779
71819
  return {
71780
71820
  videoId: work.video.id,
@@ -71883,7 +71923,7 @@ function sliceSupersetMember(member, superset, outputDir, fps) {
71883
71923
  for (let i2 = 0; i2 < frameCount; i2 += 1) {
71884
71924
  const sourceFrame = superset.framePaths.get(member.offsetFrames + i2);
71885
71925
  if (!sourceFrame) throw new Error(`superset frame ${member.offsetFrames + i2} missing`);
71886
- linkOrCopyFrame(sourceFrame, join12(outputDir, frameFileName(i2 + 1, work.format)));
71926
+ linkOrCopyFrame(sourceFrame, join13(outputDir, frameFileName(i2 + 1, work.format)));
71887
71927
  }
71888
71928
  return extractedFramesFromDirectory(work, outputDir, work.videoPath, fps);
71889
71929
  }
@@ -71895,22 +71935,22 @@ function resolveProjectRelativeSrc(src, baseDir, compiledDir) {
71895
71935
  if (!candidates.includes(candidate)) candidates.push(candidate);
71896
71936
  };
71897
71937
  for (const variant of decodeUrlPathVariants(cleanSrc)) {
71898
- const fromCompiled = compiledDir ? join12(compiledDir, variant) : null;
71899
- const fromBase = join12(baseDir, variant);
71938
+ const fromCompiled = compiledDir ? join13(compiledDir, variant) : null;
71939
+ const fromBase = join13(baseDir, variant);
71900
71940
  const baseAbs = resolve9(baseDir);
71901
71941
  const fromBaseAbs = resolve9(fromBase);
71902
71942
  if (!fromBaseAbs.startsWith(baseAbs + sep3) && fromBaseAbs !== baseAbs) {
71903
71943
  const normalized = posix3.normalize(variant.replace(/\\/g, "/"));
71904
71944
  const stripped = normalized.replace(/^(\.\.\/)+/, "");
71905
71945
  if (stripped && stripped !== variant && !stripped.startsWith("..")) {
71906
- if (compiledDir) addCandidate2(join12(compiledDir, stripped));
71907
- addCandidate2(join12(baseDir, stripped));
71946
+ if (compiledDir) addCandidate2(join13(compiledDir, stripped));
71947
+ addCandidate2(join13(baseDir, stripped));
71908
71948
  }
71909
71949
  }
71910
71950
  if (fromCompiled) addCandidate2(fromCompiled);
71911
71951
  addCandidate2(fromBase);
71912
71952
  }
71913
- return candidates.find(existsSync12) ?? join12(baseDir, cleanSrc);
71953
+ return candidates.find(existsSync12) ?? join13(baseDir, cleanSrc);
71914
71954
  }
71915
71955
  async function extractAllVideoFrames(videos, baseDir, options, signal, config, compiledDir) {
71916
71956
  const startTime = Date.now();
@@ -71944,7 +71984,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
71944
71984
  videoPath = resolveProjectRelativeSrc(video.src, baseDir, compiledDir);
71945
71985
  }
71946
71986
  if (isHttpUrl(videoPath)) {
71947
- const downloadDir = join12(options.outputDir, "_downloads");
71987
+ const downloadDir = join13(options.outputDir, "_downloads");
71948
71988
  mkdirSync7(downloadDir, { recursive: true });
71949
71989
  videoPath = await downloadToTemp(videoPath, downloadDir);
71950
71990
  }
@@ -72138,7 +72178,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
72138
72178
  return sliceSupersetMember(
72139
72179
  member,
72140
72180
  superset,
72141
- join12(options.outputDir, work.video.id),
72181
+ join13(options.outputDir, work.video.id),
72142
72182
  options.fps
72143
72183
  );
72144
72184
  }
@@ -72154,7 +72194,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
72154
72194
  async function executeSupersetGroup(group) {
72155
72195
  const first = group.members[0]?.miss.work;
72156
72196
  if (!first) return [];
72157
- const tempDir = cacheRootDir ? join12(cacheRootDir, `${group.groupId}.partial-${process.pid}`) : join12(options.outputDir, group.groupId);
72197
+ const tempDir = cacheRootDir ? join13(cacheRootDir, `${group.groupId}.partial-${process.pid}`) : join13(options.outputDir, group.groupId);
72158
72198
  try {
72159
72199
  rmSync2(tempDir, { recursive: true, force: true });
72160
72200
  const superset = await extractVideoFramesRange(
@@ -72997,7 +73037,7 @@ var init_audioVolumeEnvelope = __esm({
72997
73037
 
72998
73038
  // ../engine/src/services/audioMixer.ts
72999
73039
  import { closeSync, existsSync as existsSync13, mkdirSync as mkdirSync8, mkdtempSync, openSync, rmSync as rmSync3, writeFileSync as writeFileSync6 } from "fs";
73000
- import { isAbsolute as isAbsolute5, join as join13, dirname as dirname8 } from "path";
73040
+ import { isAbsolute as isAbsolute5, join as join14, dirname as dirname8 } from "path";
73001
73041
  function clampVolume(volume) {
73002
73042
  if (!Number.isFinite(volume)) return 1;
73003
73043
  return Math.max(0, Math.min(1, volume));
@@ -73259,8 +73299,8 @@ async function mixAudioTracks(tracks, outputPath, totalDuration, signal, config)
73259
73299
  const runMix = (ignoreAutomation) => {
73260
73300
  const inputs = [];
73261
73301
  tracks.forEach((track) => inputs.push("-i", track.srcPath));
73262
- const scriptDir = mkdtempSync(join13(outputDir, ".filter-complex-"));
73263
- const scriptPath = join13(scriptDir, "graph.txt");
73302
+ const scriptDir = mkdtempSync(join14(outputDir, ".filter-complex-"));
73303
+ const scriptPath = join14(scriptDir, "graph.txt");
73264
73304
  const fd = openSync(scriptPath, "wx", 384);
73265
73305
  try {
73266
73306
  writeFileSync6(fd, buildFilterComplex(ignoreAutomation));
@@ -73359,7 +73399,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
73359
73399
  }
73360
73400
  let audioSrcPath = srcPath;
73361
73401
  if (element.type === "video") {
73362
- const extractedPath = join13(workDir, `${element.id}-extracted.wav`);
73402
+ const extractedPath = join14(workDir, `${element.id}-extracted.wav`);
73363
73403
  const extractResult = await extractAudioFromVideo(
73364
73404
  srcPath,
73365
73405
  extractedPath,
@@ -73376,7 +73416,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
73376
73416
  }
73377
73417
  audioSrcPath = extractedPath;
73378
73418
  } else {
73379
- const trimmedPath = join13(workDir, `${element.id}-trimmed.wav`);
73419
+ const trimmedPath = join14(workDir, `${element.id}-trimmed.wav`);
73380
73420
  const prepResult = await prepareAudioTrack(
73381
73421
  srcPath,
73382
73422
  trimmedPath,
@@ -73529,7 +73569,7 @@ var init_readWebGlVendorInfoFromCanvas = __esm({
73529
73569
  import { cpus, freemem } from "os";
73530
73570
  import { existsSync as existsSync14, mkdirSync as mkdirSync9, readdirSync as readdirSync6 } from "fs";
73531
73571
  import { copyFile, rename } from "fs/promises";
73532
- import { join as join14 } from "path";
73572
+ import { join as join15 } from "path";
73533
73573
  function defaultSafeMaxWorkers() {
73534
73574
  return Math.max(6, Math.min(16, Math.floor(cpus().length / 8)));
73535
73575
  }
@@ -73608,7 +73648,7 @@ function distributeFrames(totalFrames, workerCount, workDir, rangeStart = 0) {
73608
73648
  workerId: i2,
73609
73649
  startFrame,
73610
73650
  endFrame,
73611
- outputDir: join14(workDir, `worker-${i2}`),
73651
+ outputDir: join15(workDir, `worker-${i2}`),
73612
73652
  outputFrameOffset: rangeStart
73613
73653
  });
73614
73654
  }
@@ -73746,8 +73786,8 @@ async function mergeWorkerFrames(workDir, tasks, outputDir) {
73746
73786
  }
73747
73787
  const files = readdirSync6(task.outputDir).filter((f3) => f3.startsWith("frame_") && (f3.endsWith(".jpg") || f3.endsWith(".png"))).sort();
73748
73788
  const copyTasks = files.map(async (file) => {
73749
- const sourcePath = join14(task.outputDir, file);
73750
- const targetPath = join14(outputDir, file);
73789
+ const sourcePath = join15(task.outputDir, file);
73790
+ const targetPath = join15(outputDir, file);
73751
73791
  try {
73752
73792
  await rename(sourcePath, targetPath);
73753
73793
  } catch {
@@ -73789,7 +73829,7 @@ var init_parallelCoordinator = __esm({
73789
73829
  import { Hono } from "hono";
73790
73830
  import { serve } from "@hono/node-server";
73791
73831
  import { readFileSync as readFileSync7, existsSync as existsSync15, statSync as statSync4 } from "fs";
73792
- import { join as join15, extname as extname5 } from "path";
73832
+ import { join as join16, extname as extname5 } from "path";
73793
73833
  function createFileServer(options) {
73794
73834
  const { projectDir, compiledDir, port = 0, stripEmbeddedRuntime = true } = options;
73795
73835
  const headScripts = options.headScripts ?? [];
@@ -73799,11 +73839,11 @@ function createFileServer(options) {
73799
73839
  let requestPath = c3.req.path;
73800
73840
  if (requestPath === "/") requestPath = "/index.html";
73801
73841
  const relativePath = requestPath.replace(/^\//, "");
73802
- const compiledPath = compiledDir ? join15(compiledDir, relativePath) : null;
73842
+ const compiledPath = compiledDir ? join16(compiledDir, relativePath) : null;
73803
73843
  const hasCompiledFile = Boolean(
73804
73844
  compiledPath && existsSync15(compiledPath) && statSync4(compiledPath).isFile()
73805
73845
  );
73806
- const filePath = hasCompiledFile ? compiledPath : join15(projectDir, relativePath);
73846
+ const filePath = hasCompiledFile ? compiledPath : join16(projectDir, relativePath);
73807
73847
  if (!existsSync15(filePath) || !statSync4(filePath).isFile()) {
73808
73848
  return c3.text("Not found", 404);
73809
73849
  }
@@ -75118,7 +75158,7 @@ var init_shaderTransitions = __esm({
75118
75158
 
75119
75159
  // ../engine/src/services/hdrCapture.ts
75120
75160
  import { existsSync as existsSync16, readdirSync as readdirSync7 } from "fs";
75121
- import { join as join16 } from "path";
75161
+ import { join as join17 } from "path";
75122
75162
  import { homedir as homedir3 } from "os";
75123
75163
  function linearToPQ(L2) {
75124
75164
  const Lp = Math.max(0, L2 * SDR_NITS / PQ_MAX_NITS);
@@ -75234,12 +75274,12 @@ function float16ToPqRgb(rawBuffer, bytesPerRow, width, height) {
75234
75274
  return output;
75235
75275
  }
75236
75276
  function resolveHeadedChromePath() {
75237
- const baseDir = join16(homedir3(), ".cache", "puppeteer", "chrome");
75277
+ const baseDir = join17(homedir3(), ".cache", "puppeteer", "chrome");
75238
75278
  if (!existsSync16(baseDir)) return void 0;
75239
75279
  const versions = readdirSync7(baseDir).sort().reverse();
75240
75280
  for (const version2 of versions) {
75241
75281
  const candidates = [
75242
- join16(
75282
+ join17(
75243
75283
  baseDir,
75244
75284
  version2,
75245
75285
  "chrome-mac-arm64",
@@ -75248,7 +75288,7 @@ function resolveHeadedChromePath() {
75248
75288
  "MacOS",
75249
75289
  "Google Chrome for Testing"
75250
75290
  ),
75251
- join16(
75291
+ join17(
75252
75292
  baseDir,
75253
75293
  version2,
75254
75294
  "chrome-mac-x64",
@@ -75257,8 +75297,8 @@ function resolveHeadedChromePath() {
75257
75297
  "MacOS",
75258
75298
  "Google Chrome for Testing"
75259
75299
  ),
75260
- join16(baseDir, version2, "chrome-linux64", "chrome"),
75261
- join16(baseDir, version2, "chrome-win64", "chrome.exe")
75300
+ join17(baseDir, version2, "chrome-linux64", "chrome"),
75301
+ join17(baseDir, version2, "chrome-win64", "chrome.exe")
75262
75302
  ];
75263
75303
  for (const binary of candidates) {
75264
75304
  if (existsSync16(binary)) return binary;
@@ -78344,11 +78384,11 @@ var init_banner = __esm({
78344
78384
 
78345
78385
  // src/registry/remote.ts
78346
78386
  import { mkdirSync as mkdirSync10, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "fs";
78347
- import { join as join17, dirname as dirname9 } from "path";
78387
+ import { join as join18, dirname as dirname9 } from "path";
78348
78388
  import { homedir as homedir4 } from "os";
78349
78389
  function cachePath(baseUrl, key2) {
78350
78390
  const slug = baseUrl.replace(/[^a-zA-Z0-9]/g, "_");
78351
- return join17(CACHE_DIR, `${slug}__${key2}.json`);
78391
+ return join18(CACHE_DIR, `${slug}__${key2}.json`);
78352
78392
  }
78353
78393
  function readCache(path2) {
78354
78394
  try {
@@ -78419,7 +78459,7 @@ var init_remote = __esm({
78419
78459
  init_dist3();
78420
78460
  DEFAULT_REGISTRY_URL = "https://raw.githubusercontent.com/heygen-com/hyperframes/main/registry";
78421
78461
  FETCH_TIMEOUT_MS = 1e4;
78422
- CACHE_DIR = join17(homedir4(), ".hyperframes", "cache");
78462
+ CACHE_DIR = join18(homedir4(), ".hyperframes", "cache");
78423
78463
  CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
78424
78464
  }
78425
78465
  });
@@ -78697,7 +78737,7 @@ var init_compatibility = __esm({
78697
78737
 
78698
78738
  // src/templates/remote.ts
78699
78739
  import { existsSync as existsSync19 } from "fs";
78700
- import { join as join18 } from "path";
78740
+ import { join as join19 } from "path";
78701
78741
  async function fetchRemoteTemplate(templateId, destDir) {
78702
78742
  const items = await resolveItemWithDependencies(templateId);
78703
78743
  const warnings = gateRegistryItemsCompatibility(items);
@@ -78708,7 +78748,7 @@ async function fetchRemoteTemplate(templateId, destDir) {
78708
78748
  for (const item of items) {
78709
78749
  await installItem(item, { destDir });
78710
78750
  }
78711
- if (!existsSync19(join18(destDir, "index.html"))) {
78751
+ if (!existsSync19(join19(destDir, "index.html"))) {
78712
78752
  throw new Error(
78713
78753
  `Example "${templateId}" installed but missing index.html. The registry item may be malformed.`
78714
78754
  );
@@ -78946,6 +78986,22 @@ __export(ffmpeg_exports, {
78946
78986
  import { execSync as execSync3 } from "child_process";
78947
78987
  import { existsSync as existsSync21 } from "fs";
78948
78988
  import { resolve as resolve11 } from "path";
78989
+ function chooseBestPathCandidate2(name, candidates) {
78990
+ const normalized = candidates.map((s2) => s2.trim()).filter(Boolean);
78991
+ if (normalized.length === 0) return void 0;
78992
+ const lowerName = name.toLowerCase();
78993
+ const preferredExe = normalized.find(
78994
+ (candidate) => candidate.toLowerCase().endsWith(`${lowerName}.exe`)
78995
+ );
78996
+ if (preferredExe) return preferredExe;
78997
+ const exact = normalized.find((candidate) => candidate.toLowerCase().endsWith(lowerName));
78998
+ if (exact) return exact;
78999
+ const nonShellShim = normalized.find((candidate) => {
79000
+ const lower2 = candidate.toLowerCase();
79001
+ return !lower2.endsWith(".cmd") && !lower2.endsWith(".bat");
79002
+ });
79003
+ return nonShellShim ?? normalized[0];
79004
+ }
78949
79005
  function findOnPath2(name) {
78950
79006
  try {
78951
79007
  const cmd = process.platform === "win32" ? `where ${name}` : `which ${name}`;
@@ -78954,8 +79010,8 @@ function findOnPath2(name) {
78954
79010
  stdio: ["pipe", "pipe", "pipe"],
78955
79011
  timeout: 5e3
78956
79012
  });
78957
- const first = output.split(/\r?\n/).map((s2) => s2.trim()).find(Boolean);
78958
- return first ? resolve11(first) : void 0;
79013
+ const candidate = chooseBestPathCandidate2(name, output.split(/\r?\n/));
79014
+ return candidate ? resolve11(candidate) : void 0;
78959
79015
  } catch {
78960
79016
  return void 0;
78961
79017
  }
@@ -79067,7 +79123,7 @@ __export(manager_exports, {
79067
79123
  import { execFileSync as execFileSync3 } from "child_process";
79068
79124
  import { existsSync as existsSync22, mkdirSync as mkdirSync11, rmSync as rmSync4 } from "fs";
79069
79125
  import { homedir as homedir5, platform as platform4 } from "os";
79070
- import { join as join19 } from "path";
79126
+ import { join as join20 } from "path";
79071
79127
  function isWhisperUnavailable(err) {
79072
79128
  if (err instanceof WhisperUnavailableError) return true;
79073
79129
  return err instanceof Error && "code" in err && err.code === "WHISPER_UNAVAILABLE";
@@ -79110,8 +79166,8 @@ function findFromSystem() {
79110
79166
  }
79111
79167
  function findBuiltBinary() {
79112
79168
  for (const p2 of [
79113
- join19(BUILD_DIR, "build", "bin", "whisper-cli"),
79114
- join19(BUILD_DIR, "build", "whisper-cli")
79169
+ join20(BUILD_DIR, "build", "bin", "whisper-cli"),
79170
+ join20(BUILD_DIR, "build", "whisper-cli")
79115
79171
  ]) {
79116
79172
  if (existsSync22(p2)) return { executablePath: p2, source: "build" };
79117
79173
  }
@@ -79123,7 +79179,7 @@ function buildFromSource(onProgress) {
79123
79179
  }
79124
79180
  if (!existsSync22(BUILD_DIR)) {
79125
79181
  onProgress?.("Downloading whisper.cpp...");
79126
- mkdirSync11(join19(homedir5(), ".cache", "hyperframes", "whisper"), {
79182
+ mkdirSync11(join20(homedir5(), ".cache", "hyperframes", "whisper"), {
79127
79183
  recursive: true
79128
79184
  });
79129
79185
  execFileSync3("git", ["clone", "--depth", "1", WHISPER_REPO, BUILD_DIR], {
@@ -79208,7 +79264,7 @@ async function ensureWhisper(options) {
79208
79264
  throw new WhisperUnavailableError(`whisper-cpp not found. Install: ${getInstallInstructions()}`);
79209
79265
  }
79210
79266
  async function ensureModel(model = DEFAULT_MODEL, options) {
79211
- const modelPath2 = join19(MODELS_DIR, `ggml-${model}.bin`);
79267
+ const modelPath2 = join20(MODELS_DIR, `ggml-${model}.bin`);
79212
79268
  if (existsSync22(modelPath2)) return modelPath2;
79213
79269
  mkdirSync11(MODELS_DIR, { recursive: true });
79214
79270
  options?.onProgress?.(`Downloading model ${model}...`);
@@ -79227,7 +79283,7 @@ var init_manager = __esm({
79227
79283
  "use strict";
79228
79284
  init_ffmpeg();
79229
79285
  init_download();
79230
- MODELS_DIR = join19(homedir5(), ".cache", "hyperframes", "whisper", "models");
79286
+ MODELS_DIR = join20(homedir5(), ".cache", "hyperframes", "whisper", "models");
79231
79287
  DEFAULT_MODEL = "small.en";
79232
79288
  WhisperUnavailableError = class extends Error {
79233
79289
  code = "WHISPER_UNAVAILABLE";
@@ -79236,7 +79292,7 @@ var init_manager = __esm({
79236
79292
  this.name = "WhisperUnavailableError";
79237
79293
  }
79238
79294
  };
79239
- BUILD_DIR = join19(homedir5(), ".cache", "hyperframes", "whisper", "whisper.cpp");
79295
+ BUILD_DIR = join20(homedir5(), ".cache", "hyperframes", "whisper", "whisper.cpp");
79240
79296
  WHISPER_REPO = "https://github.com/ggml-org/whisper.cpp.git";
79241
79297
  }
79242
79298
  });
@@ -79253,7 +79309,7 @@ __export(normalize_exports, {
79253
79309
  wordsToCues: () => wordsToCues
79254
79310
  });
79255
79311
  import { readFileSync as readFileSync14, readdirSync as readdirSync8, writeFileSync as writeFileSync9 } from "fs";
79256
- import { extname as extname6, join as join20 } from "path";
79312
+ import { extname as extname6, join as join21 } from "path";
79257
79313
  function detectFormat(filePath) {
79258
79314
  const ext = extname6(filePath).toLowerCase();
79259
79315
  if (ext === ".srt") return "srt";
@@ -79530,7 +79586,7 @@ function patchCaptionHtml(dir, words) {
79530
79586
  const wordsJson = JSON.stringify(words, null, 2).replace(/\n/g, "\n ");
79531
79587
  let htmlFiles;
79532
79588
  try {
79533
- htmlFiles = readdirSync8(dir, { withFileTypes: true, recursive: true }).filter((e3) => e3.isFile() && e3.name.endsWith(".html")).map((e3) => join20(e3.parentPath, e3.name));
79589
+ htmlFiles = readdirSync8(dir, { withFileTypes: true, recursive: true }).filter((e3) => e3.isFile() && e3.name.endsWith(".html")).map((e3) => join21(e3.parentPath, e3.name));
79534
79590
  } catch {
79535
79591
  return;
79536
79592
  }
@@ -79571,9 +79627,9 @@ __export(projectConfig_exports, {
79571
79627
  writeProjectConfig: () => writeProjectConfig
79572
79628
  });
79573
79629
  import { readFileSync as readFileSync15, writeFileSync as writeFileSync10 } from "fs";
79574
- import { join as join21, resolve as resolve12 } from "path";
79630
+ import { join as join22, resolve as resolve12 } from "path";
79575
79631
  function projectConfigPath(projectDir) {
79576
- return join21(resolve12(projectDir), PROJECT_CONFIG_FILENAME);
79632
+ return join22(resolve12(projectDir), PROJECT_CONFIG_FILENAME);
79577
79633
  }
79578
79634
  function readProjectConfig(projectDir) {
79579
79635
  const path2 = projectConfigPath(projectDir);
@@ -79749,14 +79805,14 @@ import { execFile } from "child_process";
79749
79805
  import { createHash as createHash3 } from "crypto";
79750
79806
  import { existsSync as existsSync23, readdirSync as readdirSync9, readFileSync as readFileSync16, statSync as statSync6 } from "fs";
79751
79807
  import { homedir as homedir6 } from "os";
79752
- import { isAbsolute as isAbsolute7, join as join22, relative as relative5, resolve as resolve13, sep as sep4 } from "path";
79808
+ import { isAbsolute as isAbsolute7, join as join23, relative as relative5, resolve as resolve13, sep as sep4 } from "path";
79753
79809
  import { promisify } from "util";
79754
79810
  function listFilesSorted(dir) {
79755
79811
  const out = [];
79756
79812
  const walk = (d2) => {
79757
79813
  for (const name of readdirSync9(d2)) {
79758
79814
  if (name === ".DS_Store") continue;
79759
- const p2 = join22(d2, name);
79815
+ const p2 = join23(d2, name);
79760
79816
  if (statSync6(p2).isDirectory()) walk(p2);
79761
79817
  else out.push(p2);
79762
79818
  }
@@ -79780,9 +79836,9 @@ function hashSkillBundle(skillDir) {
79780
79836
  return { hash: h3.digest("hex").slice(0, 16), files: files.length };
79781
79837
  }
79782
79838
  function buildManifest(skillsRoot, meta) {
79783
- const names = readdirSync9(skillsRoot).filter((n2) => existsSync23(join22(skillsRoot, n2, "SKILL.md"))).sort();
79839
+ const names = readdirSync9(skillsRoot).filter((n2) => existsSync23(join23(skillsRoot, n2, "SKILL.md"))).sort();
79784
79840
  const skills = {};
79785
- for (const name of names) skills[name] = hashSkillBundle(join22(skillsRoot, name));
79841
+ for (const name of names) skills[name] = hashSkillBundle(join23(skillsRoot, name));
79786
79842
  return { source: meta.source, skills };
79787
79843
  }
79788
79844
  function agentLabel(hostDir) {
@@ -79804,12 +79860,12 @@ function listSubdirs(dir) {
79804
79860
  function discoverSkillRoots(base2, scope) {
79805
79861
  const candidates = [];
79806
79862
  const add2 = (hostBase, host) => {
79807
- const dir = join22(hostBase, host, "skills");
79863
+ const dir = join23(hostBase, host, "skills");
79808
79864
  if (existsSync23(dir) && statSync6(dir).isDirectory())
79809
79865
  candidates.push({ dir, agent: agentLabel(host), scope });
79810
79866
  };
79811
79867
  for (const host of listSubdirs(base2)) add2(base2, host);
79812
- const xdg = join22(base2, ".config");
79868
+ const xdg = join23(base2, ".config");
79813
79869
  for (const host of listSubdirs(xdg)) add2(xdg, host);
79814
79870
  return candidates.sort((a, b2) => {
79815
79871
  if (a.agent !== b2.agent) {
@@ -79843,15 +79899,15 @@ function locateInstall(skillNames, opts = {}) {
79843
79899
  ...discoverSkillRoots(opts.cwd ?? process.cwd(), "project")
79844
79900
  ];
79845
79901
  for (const root of roots) {
79846
- if (skillNames.some((n2) => existsSync23(join22(root.dir, n2, "SKILL.md")))) return root;
79902
+ if (skillNames.some((n2) => existsSync23(join23(root.dir, n2, "SKILL.md")))) return root;
79847
79903
  }
79848
79904
  return null;
79849
79905
  }
79850
79906
  function hashInstalled(root, skillNames) {
79851
79907
  const out = {};
79852
79908
  for (const name of skillNames) {
79853
- const skillDir = join22(root.dir, name);
79854
- if (existsSync23(join22(skillDir, "SKILL.md"))) out[name] = hashSkillBundle(skillDir);
79909
+ const skillDir = join23(root.dir, name);
79910
+ if (existsSync23(join23(skillDir, "SKILL.md"))) out[name] = hashSkillBundle(skillDir);
79855
79911
  }
79856
79912
  return out;
79857
79913
  }
@@ -79892,10 +79948,10 @@ function skillsAttributedToSource(lock, source) {
79892
79948
  return Object.entries(lock.skills).filter(([, e3]) => repoSlug(e3.source) === want || repoSlug(e3.sourceUrl) === want).map(([name]) => name);
79893
79949
  }
79894
79950
  function lockPathForScope(scope, opts) {
79895
- if (scope === "project") return join22(opts.cwd ?? process.cwd(), "skills-lock.json");
79951
+ if (scope === "project") return join23(opts.cwd ?? process.cwd(), "skills-lock.json");
79896
79952
  const xdgStateHome = process.env.XDG_STATE_HOME;
79897
- if (xdgStateHome) return join22(xdgStateHome, "skills", ".skill-lock.json");
79898
- return join22(opts.home ?? homedir6(), ".agents", ".skill-lock.json");
79953
+ if (xdgStateHome) return join23(xdgStateHome, "skills", ".skill-lock.json");
79954
+ return join23(opts.home ?? homedir6(), ".agents", ".skill-lock.json");
79899
79955
  }
79900
79956
  function readSkillLock(path2) {
79901
79957
  try {
@@ -79916,9 +79972,9 @@ function detectRemoved(root, latest, opts) {
79916
79972
  function findRepoManifest(cwd = process.cwd()) {
79917
79973
  let dir = cwd;
79918
79974
  for (let i2 = 0; i2 < 16; i2++) {
79919
- const p2 = join22(dir, MANIFEST_FILE);
79975
+ const p2 = join23(dir, MANIFEST_FILE);
79920
79976
  if (existsSync23(p2)) return p2;
79921
- const parent = join22(dir, "..");
79977
+ const parent = join23(dir, "..");
79922
79978
  if (parent === dir) break;
79923
79979
  dir = parent;
79924
79980
  }
@@ -79956,9 +80012,9 @@ async function remoteHeadSha(repoSlug2) {
79956
80012
  }
79957
80013
  }
79958
80014
  function resolveLocalManifest(source) {
79959
- const direct = source.endsWith(".json") ? source : join22(source, MANIFEST_FILE);
80015
+ const direct = source.endsWith(".json") ? source : join23(source, MANIFEST_FILE);
79960
80016
  if (existsSync23(direct)) return JSON.parse(readFileSync16(direct, "utf8"));
79961
- const skillsRoot = source.endsWith("skills") ? source : join22(source, "skills");
80017
+ const skillsRoot = source.endsWith("skills") ? source : join23(source, "skills");
79962
80018
  if (existsSync23(skillsRoot)) return buildManifest(skillsRoot, { source: skillsRoot });
79963
80019
  throw new Error(`No skills manifest found at: ${source}`);
79964
80020
  }
@@ -80117,22 +80173,22 @@ var init_agentDirs_generated = __esm({
80117
80173
  // src/utils/skillsMirror.ts
80118
80174
  import { cpSync, existsSync as existsSync24, mkdirSync as mkdirSync12, readdirSync as readdirSync10, rmSync as rmSync5, symlinkSync } from "fs";
80119
80175
  import { homedir as homedir7 } from "os";
80120
- import { dirname as dirname10, isAbsolute as isAbsolute8, join as join23, relative as relative6 } from "path";
80176
+ import { dirname as dirname10, isAbsolute as isAbsolute8, join as join24, relative as relative6 } from "path";
80121
80177
  function resolveBases(home, env) {
80122
80178
  const xdg = env["XDG_CONFIG_HOME"]?.trim();
80123
80179
  return {
80124
80180
  home,
80125
- configHome: xdg && isAbsolute8(xdg) ? xdg : join23(home, ".config"),
80126
- codexHome: env["CODEX_HOME"]?.trim() || join23(home, ".codex"),
80127
- claudeHome: env["CLAUDE_CONFIG_DIR"]?.trim() || join23(home, ".claude"),
80128
- vibeHome: env["VIBE_HOME"]?.trim() || join23(home, ".vibe"),
80129
- hermesHome: env["HERMES_HOME"]?.trim() || join23(home, ".hermes"),
80130
- autohandHome: env["AUTOHAND_HOME"]?.trim() || join23(home, ".autohand")
80181
+ configHome: xdg && isAbsolute8(xdg) ? xdg : join24(home, ".config"),
80182
+ codexHome: env["CODEX_HOME"]?.trim() || join24(home, ".codex"),
80183
+ claudeHome: env["CLAUDE_CONFIG_DIR"]?.trim() || join24(home, ".claude"),
80184
+ vibeHome: env["VIBE_HOME"]?.trim() || join24(home, ".vibe"),
80185
+ hermesHome: env["HERMES_HOME"]?.trim() || join24(home, ".hermes"),
80186
+ autohandHome: env["AUTOHAND_HOME"]?.trim() || join24(home, ".autohand")
80131
80187
  };
80132
80188
  }
80133
80189
  function listSkillDirs(store) {
80134
80190
  return readdirSync10(store, { withFileTypes: true }).filter(
80135
- (e3) => (e3.isDirectory() || e3.isSymbolicLink()) && existsSync24(join23(store, e3.name, "SKILL.md"))
80191
+ (e3) => (e3.isDirectory() || e3.isSymbolicLink()) && existsSync24(join24(store, e3.name, "SKILL.md"))
80136
80192
  ).map((e3) => e3.name);
80137
80193
  }
80138
80194
  function linkOrCopy(sourceSkill, targetSkill, platform10) {
@@ -80151,7 +80207,7 @@ function mirrorInto(targetDir, source, skills, platform10) {
80151
80207
  }
80152
80208
  for (const skill of skills) {
80153
80209
  try {
80154
- linkOrCopy(join23(source, skill), join23(targetDir, skill), platform10);
80210
+ linkOrCopy(join24(source, skill), join24(targetDir, skill), platform10);
80155
80211
  } catch {
80156
80212
  }
80157
80213
  }
@@ -80161,15 +80217,15 @@ function mirrorGlobalSkills(opts) {
80161
80217
  const home = opts.home ?? homedir7();
80162
80218
  const platform10 = opts.platform ?? process.platform;
80163
80219
  const bases = resolveBases(home, opts.env ?? process.env);
80164
- const source = join23(bases.claudeHome, "skills");
80165
- const universalStore = join23(home, ".agents", "skills");
80220
+ const source = join24(bases.claudeHome, "skills");
80221
+ const universalStore = join24(home, ".agents", "skills");
80166
80222
  if (!existsSync24(source)) return { source: null, mirrored: [] };
80167
80223
  const allowed = new Set(opts.skills);
80168
80224
  const skills = listSkillDirs(source).filter((name) => allowed.has(name));
80169
80225
  if (skills.length === 0) return { source, mirrored: [] };
80170
80226
  const mirrored = [];
80171
80227
  for (const { agent, base: base2, sub } of AGENT_GLOBAL_DIRS) {
80172
- const targetDir = join23(bases[base2], ...sub.split("/").filter(Boolean));
80228
+ const targetDir = join24(bases[base2], ...sub.split("/").filter(Boolean));
80173
80229
  if (targetDir === source || targetDir === universalStore) continue;
80174
80230
  if (!existsSync24(dirname10(targetDir))) continue;
80175
80231
  if (mirrorInto(targetDir, source, skills, platform10)) mirrored.push({ agent, dir: targetDir });
@@ -80479,7 +80535,7 @@ __export(transcribe_exports, {
80479
80535
  });
80480
80536
  import { execFileSync as execFileSync5 } from "child_process";
80481
80537
  import { existsSync as existsSync25, readFileSync as readFileSync17, mkdirSync as mkdirSync13, unlinkSync as unlinkSync2 } from "fs";
80482
- import { join as join24, extname as extname7 } from "path";
80538
+ import { join as join25, extname as extname7 } from "path";
80483
80539
  import { tmpdir as tmpdir2 } from "os";
80484
80540
  import { randomUUID as randomUUID3 } from "crypto";
80485
80541
  function detectLanguage(whisperPath, modelPath2, wavPath) {
@@ -80559,7 +80615,7 @@ function isVideoFile(filePath) {
80559
80615
  return VIDEO_EXTENSIONS.has(extname7(filePath).toLowerCase());
80560
80616
  }
80561
80617
  function tempWavPath() {
80562
- return join24(tmpdir2(), `hyperframes-audio-${process.pid}-${randomUUID3()}.wav`);
80618
+ return join25(tmpdir2(), `hyperframes-audio-${process.pid}-${randomUUID3()}.wav`);
80563
80619
  }
80564
80620
  function extractAudio(videoPath) {
80565
80621
  const ffmpegPath = findFFmpeg();
@@ -80650,7 +80706,7 @@ async function transcribe(inputPath, outputDir, options) {
80650
80706
  effectiveModel = multilingualModel;
80651
80707
  }
80652
80708
  options?.onProgress?.("Transcribing...");
80653
- const outputBase = join24(outputDir, "transcript");
80709
+ const outputBase = join25(outputDir, "transcript");
80654
80710
  mkdirSync13(outputDir, { recursive: true });
80655
80711
  const whisperArgs = [
80656
80712
  "--model",
@@ -88346,7 +88402,7 @@ var init_hfIds = __esm({
88346
88402
  import { execFileSync as execFileSync6 } from "child_process";
88347
88403
  import { existsSync as existsSync29, lstatSync as lstatSync2, readdirSync as readdirSync11, realpathSync as realpathSync3 } from "fs";
88348
88404
  import { homedir as homedir8, platform as platform5 } from "os";
88349
- import { join as join25, resolve as resolve18 } from "path";
88405
+ import { join as join26, resolve as resolve18 } from "path";
88350
88406
  function getAllowedFontDirs() {
88351
88407
  if (allowedDirsCache)
88352
88408
  return allowedDirsCache;
@@ -88415,7 +88471,7 @@ function fontDirectories() {
88415
88471
  const home = homedir8();
88416
88472
  if (platform5() === "darwin") {
88417
88473
  return [
88418
- join25(home, "Library", "Fonts"),
88474
+ join26(home, "Library", "Fonts"),
88419
88475
  "/Library/Fonts",
88420
88476
  "/System/Library/Fonts",
88421
88477
  "/System/Library/Fonts/Supplemental"
@@ -88423,13 +88479,13 @@ function fontDirectories() {
88423
88479
  }
88424
88480
  if (platform5() === "win32") {
88425
88481
  return [
88426
- join25(process.env.WINDIR || "C:\\Windows", "Fonts"),
88427
- join25(process.env.LOCALAPPDATA || join25(homedir8(), "AppData", "Local"), "Microsoft", "Windows", "Fonts")
88482
+ join26(process.env.WINDIR || "C:\\Windows", "Fonts"),
88483
+ join26(process.env.LOCALAPPDATA || join26(homedir8(), "AppData", "Local"), "Microsoft", "Windows", "Fonts")
88428
88484
  ];
88429
88485
  }
88430
88486
  return [
88431
- join25(home, ".fonts"),
88432
- join25(home, ".local", "share", "fonts"),
88487
+ join26(home, ".fonts"),
88488
+ join26(home, ".local", "share", "fonts"),
88433
88489
  "/usr/local/share/fonts",
88434
88490
  "/usr/share/fonts"
88435
88491
  ];
@@ -88440,7 +88496,7 @@ function collectFontFileEntries(dir, depth = 0) {
88440
88496
  const entries2 = [];
88441
88497
  try {
88442
88498
  for (const entry of readdirSync11(dir, { withFileTypes: true })) {
88443
- const fullPath = join25(dir, entry.name);
88499
+ const fullPath = join26(dir, entry.name);
88444
88500
  if (entry.isDirectory()) {
88445
88501
  entries2.push(...collectFontFileEntries(fullPath, depth + 1));
88446
88502
  continue;
@@ -91251,8 +91307,8 @@ var init_gsapParser = __esm({
91251
91307
  // ../studio-server/dist/index.js
91252
91308
  import { Hono as Hono2 } from "hono";
91253
91309
  import { readFile } from "fs/promises";
91254
- import { join as join26 } from "path";
91255
91310
  import { join as join27 } from "path";
91311
+ import { join as join28 } from "path";
91256
91312
  import { readdirSync as readdirSync12 } from "fs";
91257
91313
  import { existsSync as existsSync30, readFileSync as readFileSync19 } from "fs";
91258
91314
  import { bodyLimit } from "hono/body-limit";
@@ -91297,7 +91353,7 @@ import { join as join112 } from "path";
91297
91353
  import { createHash as createHash22 } from "crypto";
91298
91354
  import { existsSync as existsSync82, readFileSync as readFileSync112, writeFileSync as writeFileSync72, mkdirSync as mkdirSync62 } from "fs";
91299
91355
  import { join as join122 } from "path";
91300
- import { closeSync as closeSync2, constants, fstatSync, openSync as openSync2, readSync } from "fs";
91356
+ import { closeSync as closeSync2, constants as constants2, fstatSync, openSync as openSync2, readSync } from "fs";
91301
91357
  function shouldIgnoreDir(rel) {
91302
91358
  return rel === ".hyperframes/backup";
91303
91359
  }
@@ -91311,7 +91367,7 @@ function walkDir(dir, prefix = "") {
91311
91367
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
91312
91368
  if (IGNORE_DIRS.has(entry.name) || shouldIgnoreDir(rel)) continue;
91313
91369
  if (entry.isDirectory()) {
91314
- files.push(...walkDir(join27(dir, entry.name), rel));
91370
+ files.push(...walkDir(join28(dir, entry.name), rel));
91315
91371
  } else {
91316
91372
  files.push(rel);
91317
91373
  }
@@ -91323,7 +91379,7 @@ async function filterCompositionFiles(projectDir, files) {
91323
91379
  const checks = await Promise.all(
91324
91380
  htmlFiles.map(async (f3) => {
91325
91381
  try {
91326
- const content = await readFile(join26(projectDir, f3), "utf-8");
91382
+ const content = await readFile(join27(projectDir, f3), "utf-8");
91327
91383
  return COMPOSITION_ID_RE.test(content);
91328
91384
  } catch {
91329
91385
  return false;
@@ -95116,7 +95172,7 @@ function registerFontRoutes(api) {
95116
95172
  if (!located) return c3.json({ error: "font not found" }, 404);
95117
95173
  let fd;
95118
95174
  try {
95119
- fd = openSync2(located.path, constants.O_RDONLY | constants.O_NOFOLLOW);
95175
+ fd = openSync2(located.path, constants2.O_RDONLY | constants2.O_NOFOLLOW);
95120
95176
  } catch {
95121
95177
  return c3.json({ error: "font file not accessible" }, 404);
95122
95178
  }
@@ -95530,7 +95586,7 @@ import { execSync as execSync5, spawnSync as spawnSync2 } from "child_process";
95530
95586
  import { existsSync as existsSync31, mkdirSync as mkdirSync15, readdirSync as readdirSync13, rmSync as rmSync7, statSync as statSync9 } from "fs";
95531
95587
  import { basename as basename4 } from "path";
95532
95588
  import { homedir as homedir9 } from "os";
95533
- import { join as join28 } from "path";
95589
+ import { join as join29 } from "path";
95534
95590
  async function loadPuppeteerBrowsers() {
95535
95591
  try {
95536
95592
  return await import("@puppeteer/browsers");
@@ -95685,15 +95741,15 @@ function findFromPuppeteerCache() {
95685
95741
  }
95686
95742
  for (const version2 of versions) {
95687
95743
  const candidates = [
95688
- join28(PUPPETEER_CACHE_DIR, version2, "chrome-headless-shell-linux64", "chrome-headless-shell"),
95689
- join28(
95744
+ join29(PUPPETEER_CACHE_DIR, version2, "chrome-headless-shell-linux64", "chrome-headless-shell"),
95745
+ join29(
95690
95746
  PUPPETEER_CACHE_DIR,
95691
95747
  version2,
95692
95748
  "chrome-headless-shell-mac-arm64",
95693
95749
  "chrome-headless-shell"
95694
95750
  ),
95695
- join28(PUPPETEER_CACHE_DIR, version2, "chrome-headless-shell-mac-x64", "chrome-headless-shell"),
95696
- join28(
95751
+ join29(PUPPETEER_CACHE_DIR, version2, "chrome-headless-shell-mac-x64", "chrome-headless-shell"),
95752
+ join29(
95697
95753
  PUPPETEER_CACHE_DIR,
95698
95754
  version2,
95699
95755
  "chrome-headless-shell-win64",
@@ -95872,11 +95928,11 @@ var init_manager2 = __esm({
95872
95928
  "use strict";
95873
95929
  init_errorMessage();
95874
95930
  CHROME_VERSION = "131.0.6778.85";
95875
- CACHE_ROOT_DIR = join28(homedir9(), ".cache", "hyperframes");
95876
- CACHE_DIR2 = join28(homedir9(), ".cache", "hyperframes", "chrome");
95877
- PUPPETEER_CACHE_DIR = join28(homedir9(), ".cache", "puppeteer", "chrome-headless-shell");
95878
- INSTALL_LOCK_DIR = join28(CACHE_ROOT_DIR, ".chrome.install.lock");
95879
- INSTALL_RECLAIM_LOCK_DIR = join28(CACHE_ROOT_DIR, ".chrome.install.reclaim.lock");
95931
+ CACHE_ROOT_DIR = join29(homedir9(), ".cache", "hyperframes");
95932
+ CACHE_DIR2 = join29(homedir9(), ".cache", "hyperframes", "chrome");
95933
+ PUPPETEER_CACHE_DIR = join29(homedir9(), ".cache", "puppeteer", "chrome-headless-shell");
95934
+ INSTALL_LOCK_DIR = join29(CACHE_ROOT_DIR, ".chrome.install.lock");
95935
+ INSTALL_RECLAIM_LOCK_DIR = join29(CACHE_ROOT_DIR, ".chrome.install.reclaim.lock");
95880
95936
  INSTALL_LOCK_TIMEOUT_MS = 12e4;
95881
95937
  INSTALL_LOCK_POLL_MS = 200;
95882
95938
  SYSTEM_CHROME_PATHS = process.platform === "darwin" ? ["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"] : [
@@ -99161,7 +99217,7 @@ __export(deterministicFonts_exports, {
99161
99217
  import { createHash as createHash6 } from "crypto";
99162
99218
  import { existsSync as existsSync33, mkdirSync as mkdirSync16, readFileSync as readFileSync20, writeFileSync as writeFileSync12 } from "fs";
99163
99219
  import { homedir as homedir10, tmpdir as tmpdir4 } from "os";
99164
- import { join as join29 } from "path";
99220
+ import { join as join30 } from "path";
99165
99221
  import postcss4 from "postcss";
99166
99222
  function parseFontFamilyValue(value) {
99167
99223
  return value.split(",").map((piece) => piece.trim().replace(/^['"]/, "").replace(/['"]$/, "").trim()).filter((piece) => piece.length > 0);
@@ -99478,13 +99534,13 @@ function warnUnresolvedFonts(unresolved) {
99478
99534
  );
99479
99535
  }
99480
99536
  function resolveFontCacheRoot() {
99481
- return process.env.HYPERFRAMES_FONT_CACHE_DIR ?? (process.env.AWS_LAMBDA_FUNCTION_NAME ? join29(tmpdir4(), "hyperframes", "fonts") : join29(homedir10(), ".cache", "hyperframes", "fonts"));
99537
+ return process.env.HYPERFRAMES_FONT_CACHE_DIR ?? (process.env.AWS_LAMBDA_FUNCTION_NAME ? join30(tmpdir4(), "hyperframes", "fonts") : join30(homedir10(), ".cache", "hyperframes", "fonts"));
99482
99538
  }
99483
99539
  function fontSlug(familyName) {
99484
99540
  return familyName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
99485
99541
  }
99486
99542
  function fontCacheDir(slug) {
99487
- const dir = join29(GOOGLE_FONTS_CACHE_DIR, slug);
99543
+ const dir = join30(GOOGLE_FONTS_CACHE_DIR, slug);
99488
99544
  if (!existsSync33(dir)) {
99489
99545
  mkdirSync16(dir, { recursive: true });
99490
99546
  }
@@ -99494,7 +99550,7 @@ function subsetToken(woff2Url) {
99494
99550
  return createHash6("sha1").update(woff2Url).digest("hex").slice(0, 12);
99495
99551
  }
99496
99552
  function cachedWoff2Path(slug, weight, style, subset) {
99497
- return join29(fontCacheDir(slug), `${weight}-${style}-${subset}.woff2`);
99553
+ return join30(fontCacheDir(slug), `${weight}-${style}-${subset}.woff2`);
99498
99554
  }
99499
99555
  function fontFetchError(familyName, url, what, cause) {
99500
99556
  const reason = "status" in cause ? `returned HTTP ${cause.status}` : `failed: ${cause.error.message}`;
@@ -99779,7 +99835,7 @@ import {
99779
99835
  rmSync as rmSync8,
99780
99836
  statSync as statSync10
99781
99837
  } from "fs";
99782
- import { dirname as dirname13, isAbsolute as isAbsolute10, join as join30, resolve as resolve20 } from "path";
99838
+ import { dirname as dirname13, isAbsolute as isAbsolute10, join as join31, resolve as resolve20 } from "path";
99783
99839
  function splitUrlSuffix2(src) {
99784
99840
  const queryIdx = src.indexOf("?");
99785
99841
  const hashIdx = src.indexOf("#");
@@ -100026,7 +100082,7 @@ function replaceImageWithVideo(input2) {
100026
100082
  return video;
100027
100083
  }
100028
100084
  async function prepareAnimatedGifInputs(html, options) {
100029
- const outputDir = options.outputDir ?? join30(options.downloadDir, PREPARED_GIF_SUBDIR);
100085
+ const outputDir = options.outputDir ?? join31(options.downloadDir, PREPARED_GIF_SUBDIR);
100030
100086
  const outputSrcPrefix = normalizeRelPath(options.outputSrcPrefix ?? PREPARED_GIF_SUBDIR);
100031
100087
  const cacheDir = options.cacheDir ?? outputDir;
100032
100088
  const { document: document2 } = parseHTML(html);
@@ -100048,8 +100104,8 @@ async function prepareAnimatedGifInputs(html, options) {
100048
100104
  const { loopIterations, padSeconds } = resolvePreparedPlayback(metadata, loop, windowSeconds);
100049
100105
  const hash2 = computePreparedGifHash(bytes, loopIterations, padSeconds);
100050
100106
  const filename = `${CACHE_SCHEMA}-${hash2.slice(0, 24)}.webm`;
100051
- const cachePath2 = join30(cacheDir, filename);
100052
- const outputPath = join30(outputDir, filename);
100107
+ const cachePath2 = join31(cacheDir, filename);
100108
+ const outputPath = join31(outputDir, filename);
100053
100109
  const outputSrc = `${outputSrcPrefix}/${filename}`;
100054
100110
  await ensurePreparedWebm({
100055
100111
  sourcePath,
@@ -100192,7 +100248,7 @@ import { serve as serve2 } from "@hono/node-server";
100192
100248
  import { existsSync as existsSync36, realpathSync as realpathSync4, statSync as statSync11, createReadStream } from "fs";
100193
100249
  import { readFile as readFile2 } from "fs/promises";
100194
100250
  import { Readable as Readable2 } from "stream";
100195
- import { join as join31, extname as extname9, resolve as resolve23, sep as sep5 } from "path";
100251
+ import { join as join33, extname as extname9, resolve as resolve23, sep as sep5 } from "path";
100196
100252
  function isPathInside2(child, parent, options = {}) {
100197
100253
  const { resolveSymlinks = false, pathModule } = options;
100198
100254
  const resolveFn = pathModule?.resolve ?? resolve23;
@@ -100536,13 +100592,13 @@ function createFileServer2(options) {
100536
100592
  }).join("/");
100537
100593
  let filePath = null;
100538
100594
  if (compiledDir) {
100539
- const candidate = join31(compiledDir, relativePath);
100595
+ const candidate = join33(compiledDir, relativePath);
100540
100596
  if (existsSync36(candidate) && isPathInside2(candidate, compiledDir) && statSync11(candidate).isFile()) {
100541
100597
  filePath = candidate;
100542
100598
  }
100543
100599
  }
100544
100600
  if (!filePath) {
100545
- const candidate = join31(projectDir, relativePath);
100601
+ const candidate = join33(projectDir, relativePath);
100546
100602
  if (existsSync36(candidate) && isPathInside2(candidate, projectDir) && statSync11(candidate).isFile()) {
100547
100603
  filePath = candidate;
100548
100604
  }
@@ -100767,7 +100823,7 @@ var init_fileServer2 = __esm({
100767
100823
  // ../producer/src/utils/paths.ts
100768
100824
  import {
100769
100825
  basename as basename5,
100770
- join as join33,
100826
+ join as join34,
100771
100827
  resolve as nodeResolve,
100772
100828
  relative as nodeRelative,
100773
100829
  isAbsolute as nodeIsAbsolute
@@ -100802,7 +100858,7 @@ function formatExportFrameName(index, ext) {
100802
100858
  function resolveRenderPaths(projectDir, outputPath, rendersDir = DEFAULT_RENDERS_DIR) {
100803
100859
  const absoluteProjectDir = nodeResolve(projectDir);
100804
100860
  const projectName = basename5(absoluteProjectDir);
100805
- const resolvedOutputPath = outputPath ?? join33(rendersDir, `${projectName}.mp4`);
100861
+ const resolvedOutputPath = outputPath ?? join34(rendersDir, `${projectName}.mp4`);
100806
100862
  const absoluteOutputPath = nodeResolve(resolvedOutputPath);
100807
100863
  return { absoluteProjectDir, absoluteOutputPath };
100808
100864
  }
@@ -100818,7 +100874,7 @@ var init_paths = __esm({
100818
100874
 
100819
100875
  // ../producer/src/services/render/shared.ts
100820
100876
  import { copyFileSync as copyFileSync4, cpSync as cpSync2, existsSync as existsSync37, mkdirSync as mkdirSync18, symlinkSync as symlinkSync2, writeFileSync as writeFileSync13 } from "fs";
100821
- import { basename as basename6, dirname as dirname15, isAbsolute as isAbsolute11, join as join34, relative as relative8, resolve as resolve24 } from "path";
100877
+ import { basename as basename6, dirname as dirname15, isAbsolute as isAbsolute11, join as join35, relative as relative8, resolve as resolve24 } from "path";
100822
100878
  function writeFileExclusiveSync(path2, data2) {
100823
100879
  try {
100824
100880
  writeFileSync13(path2, data2, { flag: "wx", mode: 384 });
@@ -100846,16 +100902,16 @@ function resolveDeviceScaleFactor(input2) {
100846
100902
  return target.width / input2.compositionWidth;
100847
100903
  }
100848
100904
  function writeCompiledArtifacts(compiled, workDir, includeSummary) {
100849
- const compileDir = join34(workDir, "compiled");
100905
+ const compileDir = join35(workDir, "compiled");
100850
100906
  mkdirSync18(compileDir, { recursive: true });
100851
- writeFileSync13(join34(compileDir, "index.html"), compiled.html, "utf-8");
100907
+ writeFileSync13(join35(compileDir, "index.html"), compiled.html, "utf-8");
100852
100908
  for (const [srcPath, html] of compiled.subCompositions) {
100853
- const outPath = join34(compileDir, srcPath);
100909
+ const outPath = join35(compileDir, srcPath);
100854
100910
  mkdirSync18(dirname15(outPath), { recursive: true });
100855
100911
  writeFileSync13(outPath, html, "utf-8");
100856
100912
  }
100857
100913
  for (const [relativePath, absolutePath] of compiled.externalAssets) {
100858
- const outPath = resolve24(join34(compileDir, relativePath));
100914
+ const outPath = resolve24(join35(compileDir, relativePath));
100859
100915
  if (!isPathInside3(outPath, compileDir)) {
100860
100916
  console.warn(`[Render] Skipping external asset with unsafe path: ${relativePath}`);
100861
100917
  continue;
@@ -100886,7 +100942,7 @@ function writeCompiledArtifacts(compiled, workDir, includeSummary) {
100886
100942
  renderModeHints: compiled.renderModeHints,
100887
100943
  hasShaderTransitions: compiled.hasShaderTransitions
100888
100944
  };
100889
- writeFileSync13(join34(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
100945
+ writeFileSync13(join35(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
100890
100946
  }
100891
100947
  }
100892
100948
  function applyRenderModeHints(alreadyForced, compiled, log2 = defaultLogger) {
@@ -100977,7 +101033,7 @@ var init_shared = __esm({
100977
101033
  BROWSER_MEDIA_EPSILON = 1e-4;
100978
101034
  materializePathModule = {
100979
101035
  resolve: resolve24,
100980
- join: join34,
101036
+ join: join35,
100981
101037
  dirname: dirname15,
100982
101038
  basename: basename6,
100983
101039
  relative: relative8,
@@ -101351,7 +101407,7 @@ var init_captureBeyondViewport = __esm({
101351
101407
  });
101352
101408
 
101353
101409
  // ../producer/src/services/render/captureCost.ts
101354
- import { join as join35 } from "path";
101410
+ import { join as join36 } from "path";
101355
101411
  function estimateCaptureCostMultiplier(compiled) {
101356
101412
  let multiplier = 1;
101357
101413
  const reasons = [];
@@ -101578,7 +101634,7 @@ async function runCaptureCalibration(input2) {
101578
101634
  });
101579
101635
  let calibration;
101580
101636
  try {
101581
- calibration = await runOneCalibration(join35(workDir, "capture-calibration"), calibrationCfg);
101637
+ calibration = await runOneCalibration(join36(workDir, "capture-calibration"), calibrationCfg);
101582
101638
  } catch (error) {
101583
101639
  const shouldFallback = !forceScreenshot && shouldFallbackToScreenshotAfterCalibrationError(error);
101584
101640
  if (!shouldFallback) {
@@ -101611,7 +101667,7 @@ async function runCaptureCalibration(input2) {
101611
101667
  const screenshotCfg = createCaptureCalibrationConfig({ ...cfg, forceScreenshot: true });
101612
101668
  try {
101613
101669
  calibration = await runOneCalibration(
101614
- join35(workDir, "capture-calibration-screenshot"),
101670
+ join36(workDir, "capture-calibration-screenshot"),
101615
101671
  screenshotCfg
101616
101672
  );
101617
101673
  } catch (fallbackError) {
@@ -102178,7 +102234,7 @@ var init_manualEditsRenderScript = __esm({
102178
102234
 
102179
102235
  // ../producer/src/services/htmlCompiler.ts
102180
102236
  import { readFileSync as readFileSync24, existsSync as existsSync38, mkdirSync as mkdirSync19 } from "fs";
102181
- import { join as join36, dirname as dirname16, resolve as resolve25, basename as basename7 } from "path";
102237
+ import { join as join37, dirname as dirname16, resolve as resolve25, basename as basename7 } from "path";
102182
102238
  function parseSubCompHtmlForValidity(html) {
102183
102239
  return parseHTML(html).document;
102184
102240
  }
@@ -102294,7 +102350,7 @@ async function resolveMediaDuration(src, mediaStart, baseDir, downloadDir, tagNa
102294
102350
  return { duration: 0, resolvedPath: src };
102295
102351
  }
102296
102352
  } else if (!filePath.startsWith("/")) {
102297
- filePath = join36(baseDir, filePath);
102353
+ filePath = join37(baseDir, filePath);
102298
102354
  }
102299
102355
  if (!existsSync38(filePath)) {
102300
102356
  return { duration: 0, resolvedPath: filePath };
@@ -102815,7 +102871,7 @@ async function localizeRemoteMediaSources(html, downloadDir) {
102815
102871
  return downloadAndRewriteUrls(
102816
102872
  urlSet,
102817
102873
  html,
102818
- join36(downloadDir, REMOTE_MEDIA_SUBDIR),
102874
+ join37(downloadDir, REMOTE_MEDIA_SUBDIR),
102819
102875
  "Remote media download failed for",
102820
102876
  "Localized remote media source(s)"
102821
102877
  );
@@ -102830,7 +102886,7 @@ async function localizeRemoteImageSources(html, downloadDir) {
102830
102886
  return downloadAndRewriteUrls(
102831
102887
  urlSet,
102832
102888
  html,
102833
- join36(downloadDir, REMOTE_MEDIA_SUBDIR),
102889
+ join37(downloadDir, REMOTE_MEDIA_SUBDIR),
102834
102890
  "Remote image download failed for",
102835
102891
  "Localized remote image source(s)"
102836
102892
  );
@@ -102979,7 +103035,7 @@ async function localizeRemoteFontFaces(html, downloadDir) {
102979
103035
  return downloadAndRewriteUrls(
102980
103036
  urlSet,
102981
103037
  processed,
102982
- join36(downloadDir, REMOTE_MEDIA_SUBDIR),
103038
+ join37(downloadDir, REMOTE_MEDIA_SUBDIR),
102983
103039
  "Remote font download failed for",
102984
103040
  "Localized remote font face(s)",
102985
103041
  (h3, url, relPath) => h3.replaceAll(`url(${url})`, `url("${relPath}")`)
@@ -103441,7 +103497,7 @@ Check that each file referenced by data-composition-src contains valid HTML with
103441
103497
  });
103442
103498
 
103443
103499
  // ../producer/src/services/render/stages/compileStage.ts
103444
- import { join as join37 } from "path";
103500
+ import { join as join38 } from "path";
103445
103501
  async function runCompileStage(input2) {
103446
103502
  const {
103447
103503
  projectDir,
@@ -103457,11 +103513,11 @@ async function runCompileStage(input2) {
103457
103513
  allowSystemFontCapture
103458
103514
  } = input2;
103459
103515
  const compileStart = Date.now();
103460
- const compiled = await compileForRender(projectDir, htmlPath, join37(workDir, "downloads"), {
103516
+ const compiled = await compileForRender(projectDir, htmlPath, join38(workDir, "downloads"), {
103461
103517
  log: log2,
103462
103518
  failClosedFontFetch: failClosedFontFetch === true,
103463
103519
  allowSystemFontCapture,
103464
- animatedGifCacheDir: cfg.extractCacheDir ? join37(cfg.extractCacheDir, "animated-gif") : void 0,
103520
+ animatedGifCacheDir: cfg.extractCacheDir ? join38(cfg.extractCacheDir, "animated-gif") : void 0,
103465
103521
  ffmpegProcessTimeout: cfg.ffmpegProcessTimeout
103466
103522
  });
103467
103523
  assertNotAborted();
@@ -103526,7 +103582,7 @@ var init_compileStage = __esm({
103526
103582
  });
103527
103583
 
103528
103584
  // ../producer/src/services/render/stages/probeStage.ts
103529
- import { join as join38 } from "path";
103585
+ import { join as join39 } from "path";
103530
103586
  function hasScriptedAudioVolumeAutomation(html, audioCount) {
103531
103587
  if (audioCount <= 0) return false;
103532
103588
  const { document: document2 } = parseHTML(html);
@@ -103574,7 +103630,7 @@ async function runProbeStage(input2) {
103574
103630
  });
103575
103631
  fileServer = await createFileServer2({
103576
103632
  projectDir,
103577
- compiledDir: join38(workDir, "compiled"),
103633
+ compiledDir: join39(workDir, "compiled"),
103578
103634
  port: 0,
103579
103635
  preHeadScripts: [VIRTUAL_TIME_SHIM],
103580
103636
  fps: job.config.fps
@@ -103595,7 +103651,7 @@ async function runProbeStage(input2) {
103595
103651
  log2.info("Creating capture session...", { attempt, maxAttempts: PROBE_MAX_ATTEMPTS });
103596
103652
  probeSession = await createCaptureSession(
103597
103653
  fileServer.url,
103598
- join38(workDir, "probe"),
103654
+ join39(workDir, "probe"),
103599
103655
  captureOpts,
103600
103656
  null,
103601
103657
  probeCfg
@@ -103675,7 +103731,7 @@ async function runProbeStage(input2) {
103675
103731
  compiled,
103676
103732
  resolutions,
103677
103733
  projectDir,
103678
- join38(workDir, "downloads")
103734
+ join39(workDir, "downloads")
103679
103735
  );
103680
103736
  assertNotAborted();
103681
103737
  composition.videos = compiled.videos;
@@ -103893,7 +103949,7 @@ var init_probeStage = __esm({
103893
103949
 
103894
103950
  // ../producer/src/services/render/stages/extractVideosStage.ts
103895
103951
  import { existsSync as existsSync39 } from "fs";
103896
- import { isAbsolute as isAbsolute12, join as join39 } from "path";
103952
+ import { isAbsolute as isAbsolute12, join as join40 } from "path";
103897
103953
  async function runExtractVideosStage(input2) {
103898
103954
  const {
103899
103955
  projectDir,
@@ -103936,7 +103992,7 @@ async function runExtractVideosStage(input2) {
103936
103992
  composition.images.map(async (img) => {
103937
103993
  let imgPath = img.src;
103938
103994
  if (!imgPath.startsWith("/")) {
103939
- const fromCompiled = existsSync39(join39(compiledDir, imgPath)) ? join39(compiledDir, imgPath) : join39(projectDir, imgPath);
103995
+ const fromCompiled = existsSync39(join40(compiledDir, imgPath)) ? join40(compiledDir, imgPath) : join40(projectDir, imgPath);
103940
103996
  imgPath = fromCompiled;
103941
103997
  }
103942
103998
  if (!existsSync39(imgPath)) return null;
@@ -103966,7 +104022,7 @@ async function runExtractVideosStage(input2) {
103966
104022
  // output framerate exact.
103967
104023
  {
103968
104024
  fps: fpsToNumber(job.config.fps),
103969
- outputDir: join39(compiledDir, "__hyperframes_video_frames"),
104025
+ outputDir: join40(compiledDir, "__hyperframes_video_frames"),
103970
104026
  format: job.config.videoFrameFormat ?? "auto"
103971
104027
  },
103972
104028
  abortSignal,
@@ -104032,18 +104088,18 @@ var init_extractVideosStage = __esm({
104032
104088
  });
104033
104089
 
104034
104090
  // ../producer/src/services/render/stages/audioStage.ts
104035
- import { join as join40 } from "path";
104091
+ import { join as join41 } from "path";
104036
104092
  async function runAudioStage(input2) {
104037
104093
  const { projectDir, workDir, compiledDir, duration, audios, abortSignal, assertNotAborted } = input2;
104038
104094
  const stage3Start = Date.now();
104039
- const audioOutputPath = join40(workDir, "audio.aac");
104095
+ const audioOutputPath = join41(workDir, "audio.aac");
104040
104096
  let hasAudio = false;
104041
104097
  let audioError;
104042
104098
  if (audios.length > 0) {
104043
104099
  const audioResult = await processCompositionAudio(
104044
104100
  audios,
104045
104101
  projectDir,
104046
- join40(workDir, "audio-work"),
104102
+ join41(workDir, "audio-work"),
104047
104103
  audioOutputPath,
104048
104104
  duration,
104049
104105
  abortSignal,
@@ -104206,7 +104262,7 @@ var init_captureStage = __esm({
104206
104262
 
104207
104263
  // ../producer/src/services/hdrCompositor.ts
104208
104264
  import { readSync as readSync2, closeSync as closeSync3 } from "fs";
104209
- import { join as join41 } from "path";
104265
+ import { join as join43 } from "path";
104210
104266
  function countNonZeroAlpha(rgba) {
104211
104267
  let n2 = 0;
104212
104268
  for (let p2 = 3; p2 < rgba.length; p2 += 4) {
@@ -104600,7 +104656,7 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
104600
104656
  if (shouldLog && debugDumpDir) {
104601
104657
  const after2 = countNonZeroRgb48(canvas);
104602
104658
  const dumpName = `frame_${String(debugFrameIndex).padStart(4, "0")}_layer_${String(layerIdx).padStart(2, "0")}_dom.png`;
104603
- const dumpPath = join41(debugDumpDir, dumpName);
104659
+ const dumpPath = join43(debugDumpDir, dumpName);
104604
104660
  writeFileExclusiveSync(dumpPath, domPng);
104605
104661
  log2.info("[diag] dom layer blit", {
104606
104662
  frame: debugFrameIndex,
@@ -105144,14 +105200,14 @@ var init_hdrImageTransferCache = __esm({
105144
105200
  // ../producer/src/services/render/stages/captureHdrResources.ts
105145
105201
  import {
105146
105202
  closeSync as closeSync4,
105147
- constants as constants2,
105203
+ constants as constants3,
105148
105204
  fstatSync as fstatSync2,
105149
105205
  mkdirSync as mkdirSync20,
105150
105206
  mkdtempSync as mkdtempSync3,
105151
105207
  openSync as openSync3,
105152
105208
  readFileSync as readFileSync25
105153
105209
  } from "fs";
105154
- import { join as join43 } from "path";
105210
+ import { join as join44 } from "path";
105155
105211
  function tempDirSafePrefix(id) {
105156
105212
  const safe = id.replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 80);
105157
105213
  return safe || "video";
@@ -105164,8 +105220,8 @@ function planHdrResources(args) {
105164
105220
  if (!hdrVideoIds.includes(v2.id)) continue;
105165
105221
  let srcPath = v2.src;
105166
105222
  if (!srcPath.startsWith("/")) {
105167
- const fromCompiled = join43(compiledDir, srcPath);
105168
- srcPath = args.existsSync(fromCompiled) ? fromCompiled : join43(projectDir, srcPath);
105223
+ const fromCompiled = join44(compiledDir, srcPath);
105224
+ srcPath = args.existsSync(fromCompiled) ? fromCompiled : join44(projectDir, srcPath);
105169
105225
  }
105170
105226
  hdrVideoSrcPaths.set(v2.id, srcPath);
105171
105227
  }
@@ -105239,10 +105295,10 @@ async function extractHdrVideoFrames(args) {
105239
105295
  const video = composition.videos.find((v2) => v2.id === videoId);
105240
105296
  if (!video) continue;
105241
105297
  mkdirSync20(framesDir, { recursive: true });
105242
- const frameDir = mkdtempSync3(join43(framesDir, `hdr_${tempDirSafePrefix(videoId)}-`));
105298
+ const frameDir = mkdtempSync3(join44(framesDir, `hdr_${tempDirSafePrefix(videoId)}-`));
105243
105299
  const duration = video.end - video.start;
105244
105300
  const dims = prep.hdrExtractionDims.get(videoId) ?? { width, height };
105245
- const rawPath = join43(frameDir, "frames.rgb48le");
105301
+ const rawPath = join44(frameDir, "frames.rgb48le");
105246
105302
  const ffmpegArgs = [
105247
105303
  "-ss",
105248
105304
  String(video.mediaStart),
@@ -105274,7 +105330,7 @@ async function extractHdrVideoFrames(args) {
105274
105330
  );
105275
105331
  }
105276
105332
  const frameSize = dims.width * dims.height * 6;
105277
- const fd = openSync3(rawPath, constants2.O_RDONLY | NO_FOLLOW_FLAG);
105333
+ const fd = openSync3(rawPath, constants3.O_RDONLY | NO_FOLLOW_FLAG);
105278
105334
  let handedOff = false;
105279
105335
  try {
105280
105336
  const frameCount = Math.floor(fstatSync2(fd).size / frameSize);
@@ -105348,12 +105404,12 @@ var init_captureHdrResources = __esm({
105348
105404
  "use strict";
105349
105405
  init_src();
105350
105406
  init_dist3();
105351
- NO_FOLLOW_FLAG = constants2.O_NOFOLLOW ?? 0;
105407
+ NO_FOLLOW_FLAG = constants3.O_NOFOLLOW ?? 0;
105352
105408
  }
105353
105409
  });
105354
105410
 
105355
105411
  // ../producer/src/services/render/stages/captureHdrSequentialLoop.ts
105356
- import { join as join44 } from "path";
105412
+ import { join as join45 } from "path";
105357
105413
  async function runSequentialLayeredFrameLoop(input2) {
105358
105414
  const {
105359
105415
  job,
@@ -105474,7 +105530,7 @@ async function runSequentialLayeredFrameLoop(input2) {
105474
105530
  );
105475
105531
  if (debugDumpEnabled && debugDumpDir && i2 % 30 === 0) {
105476
105532
  writeFileExclusiveSync(
105477
- join44(debugDumpDir, `frame_${String(i2).padStart(4, "0")}_final_rgb48le.bin`),
105533
+ join45(debugDumpDir, `frame_${String(i2).padStart(4, "0")}_final_rgb48le.bin`),
105478
105534
  normalCanvas
105479
105535
  );
105480
105536
  }
@@ -105521,7 +105577,7 @@ var init_captureHdrSequentialLoop = __esm({
105521
105577
  // ../producer/src/services/shaderTransitionWorkerPool.ts
105522
105578
  import { Worker } from "worker_threads";
105523
105579
  import { fileURLToPath as fileURLToPath4, pathToFileURL } from "url";
105524
- import { dirname as dirname17, join as join45 } from "path";
105580
+ import { dirname as dirname17, join as join46 } from "path";
105525
105581
  import { createRequire } from "module";
105526
105582
  import { existsSync as existsSync40 } from "fs";
105527
105583
  import { cpus as cpus3 } from "os";
@@ -105535,9 +105591,9 @@ function resolveWorkerEntry(explicit) {
105535
105591
  return { path: override, isTs };
105536
105592
  }
105537
105593
  const moduleDir = dirname17(fileURLToPath4(import.meta.url));
105538
- const jsPath = join45(moduleDir, "shaderTransitionWorker.js");
105594
+ const jsPath = join46(moduleDir, "shaderTransitionWorker.js");
105539
105595
  if (existsSync40(jsPath)) return { path: jsPath, isTs: false };
105540
- const tsPath = join45(moduleDir, "shaderTransitionWorker.ts");
105596
+ const tsPath = join46(moduleDir, "shaderTransitionWorker.ts");
105541
105597
  return { path: tsPath, isTs: true };
105542
105598
  }
105543
105599
  function buildExecArgv(entryIsTs) {
@@ -105720,7 +105776,7 @@ var init_shaderTransitionWorkerPool = __esm({
105720
105776
  });
105721
105777
 
105722
105778
  // ../producer/src/services/render/stages/captureHdrHybridLoop.ts
105723
- import { join as join46 } from "path";
105779
+ import { join as join47 } from "path";
105724
105780
  async function runHybridLayeredFrameLoop(input2) {
105725
105781
  const {
105726
105782
  job,
@@ -105913,7 +105969,7 @@ async function runHybridLayeredFrameLoop(input2) {
105913
105969
  );
105914
105970
  if (debugDumpEnabled && debugDumpDir && i2 % 30 === 0) {
105915
105971
  writeFileExclusiveSync(
105916
- join46(debugDumpDir, `frame_${String(i2).padStart(4, "0")}_final_rgb48le.bin`),
105972
+ join47(debugDumpDir, `frame_${String(i2).padStart(4, "0")}_final_rgb48le.bin`),
105917
105973
  canvas
105918
105974
  );
105919
105975
  }
@@ -105958,7 +106014,7 @@ var init_captureHdrHybridLoop = __esm({
105958
106014
 
105959
106015
  // ../producer/src/services/render/stages/captureHdrStage.ts
105960
106016
  import { existsSync as existsSync41, mkdirSync as mkdirSync21 } from "fs";
105961
- import { join as join47 } from "path";
106017
+ import { join as join48 } from "path";
105962
106018
  async function runCaptureHdrStage(input2) {
105963
106019
  const {
105964
106020
  job,
@@ -106117,7 +106173,7 @@ async function runCaptureHdrStage(input2) {
106117
106173
  if (hdrVideoFrameSources.has(v2.id)) hdrVideoEndTimes.set(v2.id, v2.end);
106118
106174
  }
106119
106175
  const debugDumpEnabled = process.env.KEEP_TEMP === "1";
106120
- const debugDumpDir = debugDumpEnabled ? join47(framesDir, "debug-composite") : null;
106176
+ const debugDumpDir = debugDumpEnabled ? join48(framesDir, "debug-composite") : null;
106121
106177
  if (debugDumpDir && !existsSync41(debugDumpDir)) {
106122
106178
  mkdirSync21(debugDumpDir, { recursive: true });
106123
106179
  }
@@ -106279,7 +106335,7 @@ var init_captureHdrStage = __esm({
106279
106335
  });
106280
106336
 
106281
106337
  // ../producer/src/services/render/stages/gifEncodeArgs.ts
106282
- import { join as join48 } from "path";
106338
+ import { join as join49 } from "path";
106283
106339
  function fpsToFfmpegArg2(fps) {
106284
106340
  return fps.den === 1 ? String(fps.num) : `${fps.num}/${fps.den}`;
106285
106341
  }
@@ -106290,7 +106346,7 @@ function buildGifPalettegenArgs(input2) {
106290
106346
  "-framerate",
106291
106347
  fpsArg,
106292
106348
  "-i",
106293
- join48(input2.framesDir, input2.framePattern),
106349
+ join49(input2.framesDir, input2.framePattern),
106294
106350
  "-vf",
106295
106351
  `fps=${fpsArg},palettegen=stats_mode=diff`,
106296
106352
  input2.palettePath
@@ -106303,7 +106359,7 @@ function buildGifPaletteuseArgs(input2) {
106303
106359
  "-framerate",
106304
106360
  fpsArg,
106305
106361
  "-i",
106306
- join48(input2.framesDir, input2.framePattern),
106362
+ join49(input2.framesDir, input2.framePattern),
106307
106363
  "-i",
106308
106364
  input2.palettePath,
106309
106365
  "-lavfi",
@@ -106321,7 +106377,7 @@ var init_gifEncodeArgs = __esm({
106321
106377
 
106322
106378
  // ../producer/src/services/render/stages/encodeStage.ts
106323
106379
  import { copyFileSync as copyFileSync5, existsSync as existsSync43, mkdirSync as mkdirSync23, readdirSync as readdirSync14, rmSync as rmSync11, statSync as statSync12 } from "fs";
106324
- import { dirname as dirname18, join as join49 } from "path";
106380
+ import { dirname as dirname18, join as join50 } from "path";
106325
106381
  function resolveGifLoop(loop) {
106326
106382
  const resolved = loop ?? 0;
106327
106383
  if (!Number.isInteger(resolved) || resolved < 0 || resolved > 65535) {
@@ -106426,11 +106482,11 @@ async function runEncodeStage(input2) {
106426
106482
  );
106427
106483
  }
106428
106484
  captured.forEach((name, i2) => {
106429
- const dst = join49(outputPath, formatExportFrameName(i2, "png"));
106430
- copyFileSync5(join49(framesDir, name), dst);
106485
+ const dst = join50(outputPath, formatExportFrameName(i2, "png"));
106486
+ copyFileSync5(join50(framesDir, name), dst);
106431
106487
  });
106432
106488
  if (hasAudio && audioOutputPath && existsSync43(audioOutputPath)) {
106433
- copyFileSync5(audioOutputPath, join49(outputPath, "audio.aac"));
106489
+ copyFileSync5(audioOutputPath, join50(outputPath, "audio.aac"));
106434
106490
  log2.info(`[Render] png-sequence: audio.aac sidecar written to ${outputPath}/audio.aac`);
106435
106491
  }
106436
106492
  return { encodeMs: Date.now() - stage5Start };
@@ -106446,7 +106502,7 @@ async function runEncodeStage(input2) {
106446
106502
  const encodeResult2 = await encodeGifFromDir(framesDir, framePattern2, outputPath, {
106447
106503
  fps: job.config.fps,
106448
106504
  loop,
106449
- palettePath: join49(dirname18(videoOnlyPath), "gif-palette.png"),
106505
+ palettePath: join50(dirname18(videoOnlyPath), "gif-palette.png"),
106450
106506
  signal: abortSignal,
106451
106507
  timeout: engineCfg.ffmpegEncodeTimeout
106452
106508
  });
@@ -106572,7 +106628,7 @@ import {
106572
106628
  copyFileSync as copyFileSync6,
106573
106629
  appendFileSync
106574
106630
  } from "fs";
106575
- import { join as join50, dirname as dirname19, resolve as resolve26 } from "path";
106631
+ import { join as join51, dirname as dirname19, resolve as resolve26 } from "path";
106576
106632
  import { randomUUID as randomUUID4 } from "crypto";
106577
106633
  import { fileURLToPath as fileURLToPath5 } from "url";
106578
106634
  function sampleDirectoryBytes(dir) {
@@ -106588,7 +106644,7 @@ function sampleDirectoryBytes(dir) {
106588
106644
  continue;
106589
106645
  }
106590
106646
  for (const name of entries2) {
106591
- const full2 = join50(current2, name);
106647
+ const full2 = join51(current2, name);
106592
106648
  try {
106593
106649
  const st3 = statSync13(full2);
106594
106650
  if (st3.isDirectory()) {
@@ -106677,7 +106733,7 @@ function findMissingFrameRanges(totalFrames, framesDir, frameExt) {
106677
106733
  const ranges = [];
106678
106734
  let rangeStart = null;
106679
106735
  for (let frameIndex = 0; frameIndex < totalFrames; frameIndex++) {
106680
- const framePath = join50(framesDir, formatCaptureFrameName(frameIndex, frameExt));
106736
+ const framePath = join51(framesDir, formatCaptureFrameName(frameIndex, frameExt));
106681
106737
  const missing = !existsSync44(framePath);
106682
106738
  if (missing && rangeStart === null) {
106683
106739
  rangeStart = frameIndex;
@@ -106700,7 +106756,7 @@ function buildMissingFrameRetryBatches(ranges, maxWorkers, workDir, attempt, ran
106700
106756
  workerId,
106701
106757
  startFrame: rangeStart + range.startFrame,
106702
106758
  endFrame: rangeStart + range.endFrame,
106703
- outputDir: join50(workDir, `retry-${attempt}-batch-${batchIndex}-worker-${workerId}`),
106759
+ outputDir: join51(workDir, `retry-${attempt}-batch-${batchIndex}-worker-${workerId}`),
106704
106760
  outputFrameOffset: rangeStart
106705
106761
  }));
106706
106762
  batches.push(batch);
@@ -106733,7 +106789,7 @@ The composition is too large for the available memory. To reduce memory pressure
106733
106789
  function countCapturedFrames(totalFrames, framesDir, frameExt) {
106734
106790
  let captured = 0;
106735
106791
  for (let frameIndex = 0; frameIndex < totalFrames; frameIndex++) {
106736
- const framePath = join50(framesDir, formatCaptureFrameName(frameIndex, frameExt));
106792
+ const framePath = join51(framesDir, formatCaptureFrameName(frameIndex, frameExt));
106737
106793
  if (existsSync44(framePath)) captured++;
106738
106794
  }
106739
106795
  return captured;
@@ -106758,7 +106814,7 @@ async function executeDiskCaptureWithAdaptiveRetry(options) {
106758
106814
  reason: attempt === 0 ? "initial" : pendingTransientRetry ? "transient-retry" : "retry"
106759
106815
  });
106760
106816
  pendingTransientRetry = false;
106761
- const attemptWorkDir = join50(options.workDir, `capture-attempt-${attempt}`);
106817
+ const attemptWorkDir = join51(options.workDir, `capture-attempt-${attempt}`);
106762
106818
  const batches = missingRanges ? buildMissingFrameRetryBatches(
106763
106819
  missingRanges,
106764
106820
  currentWorkers,
@@ -106943,10 +106999,10 @@ function extractStandaloneEntryFromIndex(indexHtml, entryFile) {
106943
106999
  async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSignal) {
106944
107000
  const moduleDir = dirname19(fileURLToPath5(import.meta.url));
106945
107001
  const producerRoot = process.env.PRODUCER_RENDERS_DIR ? resolve26(process.env.PRODUCER_RENDERS_DIR, "..") : resolve26(moduleDir, "../..");
106946
- const debugDir = join50(producerRoot, ".debug");
107002
+ const debugDir = join51(producerRoot, ".debug");
106947
107003
  const outputDir = dirname19(outputPath);
106948
107004
  if (!existsSync44(outputDir)) mkdirSync24(outputDir, { recursive: true });
106949
- const workDir = job.config.debug ? join50(debugDir, job.id) : mkdtempSync4(join50(outputDir, `work-${job.id}-`));
107005
+ const workDir = job.config.debug ? join51(debugDir, job.id) : mkdtempSync4(join51(outputDir, `work-${job.id}-`));
106950
107006
  const pipelineStart = Date.now();
106951
107007
  const log2 = job.config.logger ?? defaultLogger;
106952
107008
  let fileServer = null;
@@ -106962,7 +107018,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
106962
107018
  imageDecodeFailures: 0
106963
107019
  };
106964
107020
  let hdrPerf;
106965
- const perfOutputPath = join50(workDir, "perf-summary.json");
107021
+ const perfOutputPath = join51(workDir, "perf-summary.json");
106966
107022
  const cfg = { ...job.config.producerConfig ?? resolveConfig() };
106967
107023
  const observability = new RenderObservabilityRecorder({
106968
107024
  pipelineStartMs: pipelineStart,
@@ -107009,7 +107065,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
107009
107065
  assertConfiguredFfmpegBinariesExist();
107010
107066
  if (!existsSync44(workDir)) mkdirSync24(workDir, { recursive: true });
107011
107067
  if (job.config.debug) {
107012
- const logPath = join50(workDir, "render.log");
107068
+ const logPath = join51(workDir, "render.log");
107013
107069
  restoreLogger = installDebugLogger(logPath, log2);
107014
107070
  log2.info("[Render] Debug artifacts enabled", { workDir, logPath });
107015
107071
  }
@@ -107038,15 +107094,15 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
107038
107094
  requestedWorkers: job.config.workers ?? "auto"
107039
107095
  });
107040
107096
  const entryFile = job.config.entryFile || "index.html";
107041
- let htmlPath = join50(projectDir, entryFile);
107097
+ let htmlPath = join51(projectDir, entryFile);
107042
107098
  if (!existsSync44(htmlPath)) {
107043
107099
  throw new Error(`Entry file not found: ${htmlPath}`);
107044
107100
  }
107045
107101
  assertNotAborted();
107046
107102
  const rawEntry = readFileSync26(htmlPath, "utf-8");
107047
107103
  if (entryFile !== "index.html" && rawEntry.trimStart().startsWith("<template")) {
107048
- const wrapperPath = join50(workDir, "standalone-entry.html");
107049
- const projectIndexPath = join50(projectDir, "index.html");
107104
+ const wrapperPath = join51(workDir, "standalone-entry.html");
107105
+ const projectIndexPath = join51(projectDir, "index.html");
107050
107106
  if (!existsSync44(projectIndexPath)) {
107051
107107
  throw new Error(
107052
107108
  `Template entry file "${entryFile}" requires a project index.html to extract its render shell.`
@@ -107169,7 +107225,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
107169
107225
  compositionHash
107170
107226
  });
107171
107227
  updateJobStatus(job, "preprocessing", "Extracting video frames", 10, onProgress);
107172
- const compiledDir = join50(workDir, "compiled");
107228
+ const compiledDir = join51(workDir, "compiled");
107173
107229
  const extractResult = await observeRenderStage(
107174
107230
  observability,
107175
107231
  "video_extract",
@@ -107253,7 +107309,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
107253
107309
  try {
107254
107310
  fileServer = await createFileServer2({
107255
107311
  projectDir,
107256
- compiledDir: join50(workDir, "compiled"),
107312
+ compiledDir: join51(workDir, "compiled"),
107257
107313
  port: 0,
107258
107314
  preHeadScripts: [VIRTUAL_TIME_SHIM],
107259
107315
  fps: job.config.fps
@@ -107271,7 +107327,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
107271
107327
  if (!activeFileServer) {
107272
107328
  throw new Error("File server failed to initialize before frame capture");
107273
107329
  }
107274
- const framesDir = join50(workDir, "captured-frames");
107330
+ const framesDir = join51(workDir, "captured-frames");
107275
107331
  if (!existsSync44(framesDir)) mkdirSync24(framesDir, { recursive: true });
107276
107332
  const resolvedBrowserGpuMode = await resolveBrowserGpuMode(cfg.browserGpuMode, {
107277
107333
  chromePath: resolveHeadlessShellPath(cfg),
@@ -107381,7 +107437,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
107381
107437
  gif: ".gif"
107382
107438
  };
107383
107439
  const videoExt = FORMAT_EXT3[outputFormat] ?? ".mp4";
107384
- const videoOnlyPath = join50(workDir, `video-only${videoExt}`);
107440
+ const videoOnlyPath = join51(workDir, `video-only${videoExt}`);
107385
107441
  const nativeHdrIds = /* @__PURE__ */ new Set([...nativeHdrVideoIds, ...nativeHdrImageIds]);
107386
107442
  const hasHdrContent = Boolean(effectiveHdr && nativeHdrIds.size > 0);
107387
107443
  const usePageSideCompositingForTransitions = (cfg.enablePageSideCompositing || isGif) && compiled.hasShaderTransitions && !hasHdrContent && !isPngSequence && !needsAlpha;
@@ -107701,7 +107757,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
107701
107757
  }
107702
107758
  if (job.config.debug) {
107703
107759
  if (!isPngSequence && existsSync44(outputPath)) {
107704
- const debugOutput = join50(workDir, `output${videoExt}`);
107760
+ const debugOutput = join51(workDir, `output${videoExt}`);
107705
107761
  copyFileSync6(outputPath, debugOutput);
107706
107762
  }
107707
107763
  } else if (process.env.KEEP_TEMP === "1") {
@@ -107863,7 +107919,7 @@ var init_config3 = __esm({
107863
107919
 
107864
107920
  // ../producer/src/services/hyperframeLint.ts
107865
107921
  import { existsSync as existsSync45, readFileSync as readFileSync27, statSync as statSync14 } from "fs";
107866
- import { resolve as resolve27, join as join51 } from "path";
107922
+ import { resolve as resolve27, join as join53 } from "path";
107867
107923
  function isStringRecord2(value) {
107868
107924
  if (!value || typeof value !== "object" || Array.isArray(value)) {
107869
107925
  return false;
@@ -107911,7 +107967,7 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
107911
107967
  }
107912
107968
  }
107913
107969
  return {
107914
- error: `No HTML entry file found in project directory: ${join51(absProjectDir, preferredEntryFile || "index.html")}`
107970
+ error: `No HTML entry file found in project directory: ${join53(absProjectDir, preferredEntryFile || "index.html")}`
107915
107971
  };
107916
107972
  }
107917
107973
  function prepareHyperframeLintBody(body) {
@@ -107960,7 +108016,7 @@ var init_hyperframeLint = __esm({
107960
108016
  // ../producer/src/services/healthWorker.ts
107961
108017
  import { Worker as Worker2 } from "worker_threads";
107962
108018
  import { fileURLToPath as fileURLToPath6 } from "url";
107963
- import { dirname as dirname20, join as join53 } from "path";
108019
+ import { dirname as dirname20, join as join54 } from "path";
107964
108020
  import { existsSync as existsSync46 } from "fs";
107965
108021
  async function startHealthWorker(options = {}) {
107966
108022
  const log2 = options.logger ?? defaultLogger2();
@@ -108035,7 +108091,7 @@ function defaultLogger2() {
108035
108091
  }
108036
108092
  function resolveWorkerEntry2() {
108037
108093
  const here = dirname20(fileURLToPath6(import.meta.url));
108038
- const candidates = [join53(here, "healthWorkerThread.js"), join53(here, "healthWorkerThread.ts")];
108094
+ const candidates = [join54(here, "healthWorkerThread.js"), join54(here, "healthWorkerThread.ts")];
108039
108095
  for (const candidate of candidates) {
108040
108096
  if (existsSync46(candidate)) return candidate;
108041
108097
  }
@@ -108100,7 +108156,7 @@ import {
108100
108156
  rmSync as rmSync13,
108101
108157
  createReadStream as createReadStream2
108102
108158
  } from "fs";
108103
- import { resolve as resolve28, dirname as dirname21, join as join54 } from "path";
108159
+ import { resolve as resolve28, dirname as dirname21, join as join55 } from "path";
108104
108160
  import { tmpdir as tmpdir5 } from "os";
108105
108161
  import { parseArgs as parseArgs2 } from "util";
108106
108162
  import crypto2 from "crypto";
@@ -108220,8 +108276,8 @@ async function prepareRenderBody(body) {
108220
108276
  }
108221
108277
  }
108222
108278
  const tempRoot = process.env.PRODUCER_TMP_PROJECT_DIR || tmpdir5();
108223
- const tempProjectDir = mkdtempSync5(join54(tempRoot, "producer-project-"));
108224
- writeFileSync15(join54(tempProjectDir, "index.html"), htmlContent, "utf-8");
108279
+ const tempProjectDir = mkdtempSync5(join55(tempRoot, "producer-project-"));
108280
+ writeFileSync15(join55(tempProjectDir, "index.html"), htmlContent, "utf-8");
108225
108281
  return {
108226
108282
  prepared: {
108227
108283
  input: {
@@ -108702,7 +108758,7 @@ var init_planHash = __esm({
108702
108758
 
108703
108759
  // ../producer/src/services/render/stages/freezePlan.ts
108704
108760
  import { existsSync as existsSync48, mkdirSync as mkdirSync26, readFileSync as readFileSync28, readdirSync as readdirSync16, writeFileSync as writeFileSync16 } from "fs";
108705
- import { join as join55, relative as relative9, resolve as resolve29 } from "path";
108761
+ import { join as join56, relative as relative9, resolve as resolve29 } from "path";
108706
108762
  function stripUndefined(value) {
108707
108763
  if (Array.isArray(value)) return value.map(stripUndefined);
108708
108764
  if (value !== null && typeof value === "object") {
@@ -108723,7 +108779,7 @@ function listPlanFiles(planDir) {
108723
108779
  function walk(dir) {
108724
108780
  const entries2 = readdirSync16(dir, { withFileTypes: true });
108725
108781
  for (const entry of entries2) {
108726
- const full2 = join55(dir, entry.name);
108782
+ const full2 = join56(dir, entry.name);
108727
108783
  if (entry.isDirectory()) {
108728
108784
  walk(full2);
108729
108785
  } else if (entry.isFile()) {
@@ -108759,8 +108815,8 @@ function collectPlanAssetShas(planDir) {
108759
108815
  return { compositionHtml, assets };
108760
108816
  }
108761
108817
  function recomputePlanHashFromPlanDir(planDir) {
108762
- const planJsonPath = join55(planDir, "plan.json");
108763
- const encoderJsonPath = join55(planDir, "meta", "encoder.json");
108818
+ const planJsonPath = join56(planDir, "plan.json");
108819
+ const encoderJsonPath = join56(planDir, "meta", "encoder.json");
108764
108820
  if (!existsSync48(planJsonPath)) {
108765
108821
  throw new Error(`[freezePlan] plan.json missing: ${planJsonPath}`);
108766
108822
  }
@@ -108796,18 +108852,18 @@ async function freezePlan(input2) {
108796
108852
  if (!existsSync48(planDir)) {
108797
108853
  throw new Error(`[freezePlan] planDir does not exist: ${planDir}`);
108798
108854
  }
108799
- const metaDir = join55(planDir, "meta");
108855
+ const metaDir = join56(planDir, "meta");
108800
108856
  if (!existsSync48(metaDir)) mkdirSync26(metaDir, { recursive: true });
108801
108857
  writeFileSync16(
108802
- join55(metaDir, "composition.json"),
108858
+ join56(metaDir, "composition.json"),
108803
108859
  `${JSON.stringify(composition, null, 2)}
108804
108860
  `,
108805
108861
  "utf-8"
108806
108862
  );
108807
108863
  const encoderForCanonical = stripUndefined(encoder);
108808
108864
  const encoderConfigCanonicalJson = canonicalJsonStringify(encoderForCanonical);
108809
- writeFileSync16(join55(metaDir, "encoder.json"), encoderConfigCanonicalJson, "utf-8");
108810
- writeFileSync16(join55(metaDir, "chunks.json"), `${JSON.stringify(chunks, null, 2)}
108865
+ writeFileSync16(join56(metaDir, "encoder.json"), encoderConfigCanonicalJson, "utf-8");
108866
+ writeFileSync16(join56(metaDir, "chunks.json"), `${JSON.stringify(chunks, null, 2)}
108811
108867
  `, "utf-8");
108812
108868
  const { compositionHtml, assets } = collectPlanAssetShas(planDir);
108813
108869
  const planHash = computePlanHash({
@@ -108830,7 +108886,7 @@ async function freezePlan(input2) {
108830
108886
  duration: durationSeconds,
108831
108887
  hasAudio
108832
108888
  };
108833
- const planJsonPath = join55(planDir, "plan.json");
108889
+ const planJsonPath = join56(planDir, "plan.json");
108834
108890
  writeFileSync16(planJsonPath, `${JSON.stringify(planJson, null, 2)}
108835
108891
  `, "utf-8");
108836
108892
  return { planJsonPath, planHash };
@@ -108953,7 +109009,7 @@ var init_runtimeEnvSnapshot = __esm({
108953
109009
 
108954
109010
  // ../producer/src/services/distributed/shared.ts
108955
109011
  import { execFile as execFileCallback } from "child_process";
108956
- import { dirname as dirname22, join as join56 } from "path";
109012
+ import { dirname as dirname22, join as join57 } from "path";
108957
109013
  import { existsSync as existsSync49, readFileSync as readFileSync29 } from "fs";
108958
109014
  import { fileURLToPath as fileURLToPath7 } from "url";
108959
109015
  import { promisify as promisify3 } from "util";
@@ -108992,7 +109048,7 @@ function readProducerVersion() {
108992
109048
  const startDir = dirname22(fileURLToPath7(import.meta.url));
108993
109049
  let current2 = startDir;
108994
109050
  for (let i2 = 0; i2 < 10; i2++) {
108995
- const candidate = join56(current2, "package.json");
109051
+ const candidate = join57(current2, "package.json");
108996
109052
  if (existsSync49(candidate)) {
108997
109053
  try {
108998
109054
  const pkg = JSON.parse(readFileSync29(candidate, "utf-8"));
@@ -109034,7 +109090,7 @@ import {
109034
109090
  statSync as statSync16,
109035
109091
  writeFileSync as writeFileSync17
109036
109092
  } from "fs";
109037
- import { join as join57, relative as relative10, sep as sep6 } from "path";
109093
+ import { join as join58, relative as relative10, sep as sep6 } from "path";
109038
109094
  function formatBytes2(bytes) {
109039
109095
  if (bytes < 1024) return `${bytes} B`;
109040
109096
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KiB`;
@@ -109059,7 +109115,7 @@ function measurePlanDirBytes(planDir) {
109059
109115
  return;
109060
109116
  }
109061
109117
  for (const entry of entries2) {
109062
- const full2 = join57(dir, entry.name);
109118
+ const full2 = join58(dir, entry.name);
109063
109119
  if (entry.isDirectory()) {
109064
109120
  walk(full2);
109065
109121
  } else if (entry.isFile()) {
@@ -109227,13 +109283,13 @@ async function plan(projectDir, config, planDir) {
109227
109283
  producerConfig: config.producerConfig
109228
109284
  });
109229
109285
  const entryFile = config.entryFile ?? "index.html";
109230
- const htmlPath = join57(projectDir, entryFile);
109286
+ const htmlPath = join58(projectDir, entryFile);
109231
109287
  if (!existsSync50(htmlPath)) {
109232
109288
  throw new Error(`[plan] entry file not found: ${htmlPath}`);
109233
109289
  }
109234
- const workDir = join57(planDir, ".plan-work");
109290
+ const workDir = join58(planDir, ".plan-work");
109235
109291
  if (!existsSync50(workDir)) mkdirSync27(workDir, { recursive: true });
109236
- const compiledDir = join57(workDir, "compiled");
109292
+ const compiledDir = join58(workDir, "compiled");
109237
109293
  mkdirSync27(compiledDir, { recursive: true });
109238
109294
  cpSync3(projectDir, compiledDir, {
109239
109295
  recursive: true,
@@ -109245,7 +109301,7 @@ async function plan(projectDir, config, planDir) {
109245
109301
  return firstSegment === void 0 || !PLAN_PROJECT_DIR_SKIP_SEGMENTS.has(firstSegment);
109246
109302
  }
109247
109303
  });
109248
- const finalCompiledDir = join57(planDir, "compiled");
109304
+ const finalCompiledDir = join58(planDir, "compiled");
109249
109305
  const needsAlpha = config.format === "png-sequence" || config.format === "mov" || config.format === "webm";
109250
109306
  const compileResult = await runCompileStage({
109251
109307
  projectDir,
@@ -109330,8 +109386,8 @@ async function plan(projectDir, config, planDir) {
109330
109386
  if (audioResult.audioError) {
109331
109387
  log2.warn(`[Render] Audio mix failed \u2014 output will be video-only: ${audioResult.audioError}`);
109332
109388
  }
109333
- const stagedVideoFrames = join57(compiledDir, "__hyperframes_video_frames");
109334
- const videoFramesDst = join57(planDir, "video-frames");
109389
+ const stagedVideoFrames = join58(compiledDir, "__hyperframes_video_frames");
109390
+ const videoFramesDst = join58(planDir, "video-frames");
109335
109391
  if (existsSync50(videoFramesDst)) rmSync14(videoFramesDst, { recursive: true, force: true });
109336
109392
  if (existsSync50(stagedVideoFrames)) {
109337
109393
  renameSync6(stagedVideoFrames, videoFramesDst);
@@ -109351,13 +109407,13 @@ async function plan(projectDir, config, planDir) {
109351
109407
  metadata: ext.metadata
109352
109408
  }))
109353
109409
  };
109354
- mkdirSync27(join57(planDir, "meta"), { recursive: true });
109410
+ mkdirSync27(join58(planDir, "meta"), { recursive: true });
109355
109411
  writeFileSync17(
109356
- join57(planDir, PLAN_VIDEOS_META_RELATIVE_PATH),
109412
+ join58(planDir, PLAN_VIDEOS_META_RELATIVE_PATH),
109357
109413
  JSON.stringify(planVideosJson, null, 2),
109358
109414
  "utf-8"
109359
109415
  );
109360
- const planAudioPath = join57(planDir, "audio.aac");
109416
+ const planAudioPath = join58(planDir, "audio.aac");
109361
109417
  if (audioResult.hasAudio && existsSync50(audioResult.audioOutputPath)) {
109362
109418
  renameSync6(audioResult.audioOutputPath, planAudioPath);
109363
109419
  }
@@ -109502,11 +109558,11 @@ var init_plan = __esm({
109502
109558
  // ../producer/src/services/distributed/renderChunk.ts
109503
109559
  import { randomBytes as randomBytes2 } from "crypto";
109504
109560
  import { existsSync as existsSync51, mkdirSync as mkdirSync28, readFileSync as readFileSync30, readdirSync as readdirSync18, rmSync as rmSync15, writeFileSync as writeFileSync18 } from "fs";
109505
- import { extname as extname10, join as join58 } from "path";
109561
+ import { extname as extname10, join as join59 } from "path";
109506
109562
  function rebuildExtractedFramesFromPlanDir(planDir, videos) {
109507
109563
  const result = [];
109508
109564
  for (const v2 of videos) {
109509
- const outputDir = join58(planDir, "video-frames", v2.videoId);
109565
+ const outputDir = join59(planDir, "video-frames", v2.videoId);
109510
109566
  if (!existsSync51(outputDir)) {
109511
109567
  throw new Error(
109512
109568
  `[renderChunk] planDir missing extracted video frames for ${JSON.stringify(v2.videoId)}: ${outputDir} not present. plan() should have written frames here; the planDir is malformed.`
@@ -109518,7 +109574,7 @@ function rebuildExtractedFramesFromPlanDir(planDir, videos) {
109518
109574
  for (let i2 = 0; i2 < frames.length; i2++) {
109519
109575
  const frameName = frames[i2];
109520
109576
  if (!frameName) continue;
109521
- framePaths.set(i2, join58(outputDir, frameName));
109577
+ framePaths.set(i2, join59(outputDir, frameName));
109522
109578
  }
109523
109579
  result.push({
109524
109580
  videoId: v2.videoId,
@@ -109543,7 +109599,7 @@ function hashChunkOutput(outputPath, kind) {
109543
109599
  if (kind === "file") return sha256Hex(readFileSync30(outputPath));
109544
109600
  const entries2 = readdirSync18(outputPath).filter((name) => /\.(png|jpg|jpeg)$/i.test(name)).sort();
109545
109601
  const lines = entries2.map(
109546
- (name) => `${name}\0${sha256Hex(readFileSync30(join58(outputPath, name)))}`
109602
+ (name) => `${name}\0${sha256Hex(readFileSync30(join59(outputPath, name)))}`
109547
109603
  );
109548
109604
  return sha256Hex(lines.join("\0"));
109549
109605
  }
@@ -109560,9 +109616,9 @@ function resolveLockedVp9CpuUsed(lockedEncoder) {
109560
109616
  async function renderChunk(planDir, chunkIndex, outputChunkPath) {
109561
109617
  const start = Date.now();
109562
109618
  const log2 = defaultLogger;
109563
- const planJsonPath = join58(planDir, "plan.json");
109564
- const encoderJsonPath = join58(planDir, "meta", "encoder.json");
109565
- const chunksJsonPath = join58(planDir, "meta", "chunks.json");
109619
+ const planJsonPath = join59(planDir, "plan.json");
109620
+ const encoderJsonPath = join59(planDir, "meta", "encoder.json");
109621
+ const chunksJsonPath = join59(planDir, "meta", "chunks.json");
109566
109622
  for (const required of [planJsonPath, encoderJsonPath, chunksJsonPath]) {
109567
109623
  if (!existsSync51(required)) {
109568
109624
  throw new RenderChunkValidationError(
@@ -109574,7 +109630,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
109574
109630
  const plan2 = JSON.parse(readFileSync30(planJsonPath, "utf-8"));
109575
109631
  const encoder = JSON.parse(readFileSync30(encoderJsonPath, "utf-8"));
109576
109632
  const chunks = JSON.parse(readFileSync30(chunksJsonPath, "utf-8"));
109577
- const videosJsonPath = join58(planDir, PLAN_VIDEOS_META_RELATIVE_PATH);
109633
+ const videosJsonPath = join59(planDir, PLAN_VIDEOS_META_RELATIVE_PATH);
109578
109634
  let planVideos = null;
109579
109635
  if (existsSync51(videosJsonPath)) {
109580
109636
  try {
@@ -109603,7 +109659,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
109603
109659
  `[renderChunk] chunk ${chunkIndex} has non-positive frame count: ${framesInChunk}`
109604
109660
  );
109605
109661
  }
109606
- const compiledDir = join58(planDir, "compiled");
109662
+ const compiledDir = join59(planDir, "compiled");
109607
109663
  if (!existsSync51(compiledDir)) {
109608
109664
  throw new RenderChunkValidationError(
109609
109665
  MISSING_PLAN_ARTIFACT,
@@ -109668,7 +109724,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
109668
109724
  );
109669
109725
  const workDir = `${outputChunkPath}.work.${process.pid}.${randomBytes2(4).toString("hex")}`;
109670
109726
  mkdirSync28(workDir, { recursive: true });
109671
- const framesDir = join58(workDir, "captured-frames");
109727
+ const framesDir = join59(workDir, "captured-frames");
109672
109728
  mkdirSync28(framesDir, { recursive: true });
109673
109729
  const fileServer = await createFileServer2({
109674
109730
  projectDir: compiledDir,
@@ -109750,7 +109806,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
109750
109806
  if (isPngSequence) {
109751
109807
  if (!existsSync51(outputChunkPath)) mkdirSync28(outputChunkPath, { recursive: true });
109752
109808
  } else {
109753
- const outDir = join58(outputChunkPath, "..");
109809
+ const outDir = join59(outputChunkPath, "..");
109754
109810
  if (!existsSync51(outDir)) mkdirSync28(outDir, { recursive: true });
109755
109811
  }
109756
109812
  const encodeStarted = Date.now();
@@ -110197,14 +110253,14 @@ import {
110197
110253
  statSync as statSync17,
110198
110254
  writeFileSync as writeFileSync19
110199
110255
  } from "fs";
110200
- import { dirname as dirname23, join as join59 } from "path";
110256
+ import { dirname as dirname23, join as join60 } from "path";
110201
110257
  async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
110202
110258
  const start = Date.now();
110203
110259
  const log2 = options?.logger ?? defaultLogger;
110204
110260
  const abortSignal = options?.abortSignal;
110205
110261
  const cfr = options?.cfr === true;
110206
- const planJsonPath = join59(planDir, "plan.json");
110207
- const chunksJsonPath = join59(planDir, "meta", "chunks.json");
110262
+ const planJsonPath = join60(planDir, "plan.json");
110263
+ const chunksJsonPath = join60(planDir, "meta", "chunks.json");
110208
110264
  if (!existsSync53(planJsonPath)) {
110209
110265
  throw new Error(`[assemble] planDir missing plan.json: ${planJsonPath}`);
110210
110266
  }
@@ -110233,7 +110289,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
110233
110289
  if (existsSync53(workDir)) rmSync17(workDir, { recursive: true, force: true });
110234
110290
  mkdirSync29(workDir, { recursive: true });
110235
110291
  try {
110236
- const concatOutputPath = join59(workDir, `concat.${plan2.dimensions.format}`);
110292
+ const concatOutputPath = join60(workDir, `concat.${plan2.dimensions.format}`);
110237
110293
  const fpsArg = fpsToFfmpegArg({
110238
110294
  num: plan2.dimensions.fpsNum,
110239
110295
  den: plan2.dimensions.fpsDen
@@ -110247,7 +110303,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
110247
110303
  );
110248
110304
  }
110249
110305
  } else {
110250
- const concatListPath = join59(workDir, "concat-list.txt");
110306
+ const concatListPath = join60(workDir, "concat-list.txt");
110251
110307
  const concatBody = chunkPaths.map((path2) => `file '${path2.replace(/'/g, "'\\''")}'`).join("\n");
110252
110308
  writeFileSync19(concatListPath, `${concatBody}
110253
110309
  `, "utf-8");
@@ -110279,7 +110335,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
110279
110335
  `[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.`
110280
110336
  );
110281
110337
  }
110282
- const encoderJsonPath = join59(planDir, "meta", "encoder.json");
110338
+ const encoderJsonPath = join60(planDir, "meta", "encoder.json");
110283
110339
  if (!existsSync53(encoderJsonPath)) {
110284
110340
  throw new Error(`[assemble] planDir missing meta/encoder.json: ${encoderJsonPath}`);
110285
110341
  }
@@ -110289,7 +110345,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
110289
110345
  `[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".`
110290
110346
  );
110291
110347
  }
110292
- const cfrOutputPath = join59(workDir, `cfr.${plan2.dimensions.format}`);
110348
+ const cfrOutputPath = join60(workDir, `cfr.${plan2.dimensions.format}`);
110293
110349
  const cfrArgs = [
110294
110350
  "-i",
110295
110351
  concatOutputPath,
@@ -110323,7 +110379,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
110323
110379
  }
110324
110380
  let audioForMux = null;
110325
110381
  if (audioPath !== null && existsSync53(audioPath)) {
110326
- const paddedAudioPath = join59(workDir, "audio-padded.aac");
110382
+ const paddedAudioPath = join60(workDir, "audio-padded.aac");
110327
110383
  const padTrimResult = await padOrTrimAudioToVideoFrameCount({
110328
110384
  videoPath: postConcatPath,
110329
110385
  audioPath,
@@ -110339,7 +110395,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
110339
110395
  sourceDurationSeconds: padTrimResult.sourceDurationSeconds
110340
110396
  });
110341
110397
  }
110342
- const muxOutputPath = audioForMux !== null ? join59(workDir, `mux.${plan2.dimensions.format}`) : postConcatPath;
110398
+ const muxOutputPath = audioForMux !== null ? join60(workDir, `mux.${plan2.dimensions.format}`) : postConcatPath;
110343
110399
  if (audioForMux !== null) {
110344
110400
  const muxResult = await muxVideoWithAudio(
110345
110401
  postConcatPath,
@@ -110399,8 +110455,8 @@ function mergePngFrameDirs(chunkPaths, outputPath, totalFrames, audioPath, start
110399
110455
  throw new Error(`[assemble] png-sequence chunk has no frames: ${chunkDir}`);
110400
110456
  }
110401
110457
  for (const frame of frames) {
110402
- const dst = join59(outputPath, formatExportFrameName(globalIdx, "png"));
110403
- cpSync4(join59(chunkDir, frame), dst);
110458
+ const dst = join60(outputPath, formatExportFrameName(globalIdx, "png"));
110459
+ cpSync4(join60(chunkDir, frame), dst);
110404
110460
  globalIdx += 1;
110405
110461
  }
110406
110462
  }
@@ -110410,13 +110466,13 @@ function mergePngFrameDirs(chunkPaths, outputPath, totalFrames, audioPath, start
110410
110466
  );
110411
110467
  }
110412
110468
  if (audioPath !== null && existsSync53(audioPath)) {
110413
- const sidecar = join59(outputPath, "audio.aac");
110469
+ const sidecar = join60(outputPath, "audio.aac");
110414
110470
  cpSync4(audioPath, sidecar);
110415
110471
  }
110416
110472
  let fileSize = 0;
110417
110473
  for (const name of readdirSync19(outputPath)) {
110418
110474
  try {
110419
- fileSize += statSync17(join59(outputPath, name)).size;
110475
+ fileSize += statSync17(join60(outputPath, name)).size;
110420
110476
  } catch {
110421
110477
  }
110422
110478
  }
@@ -110449,7 +110505,7 @@ var init_renderConfigValidation = __esm({
110449
110505
  // ../producer/src/services/distributed/projectHash.ts
110450
110506
  import { readdirSync as readdirSync20, readFileSync as readFileSync33 } from "fs";
110451
110507
  import { createHash as createHash11 } from "crypto";
110452
- import { join as join60, relative as relative11 } from "path";
110508
+ import { join as join61, relative as relative11 } from "path";
110453
110509
  var init_projectHash = __esm({
110454
110510
  "../producer/src/services/distributed/projectHash.ts"() {
110455
110511
  "use strict";
@@ -110531,7 +110587,7 @@ __export(studioServer_exports, {
110531
110587
  import { Hono as Hono5 } from "hono";
110532
110588
  import { streamSSE as streamSSE3 } from "hono/streaming";
110533
110589
  import { existsSync as existsSync54, readFileSync as readFileSync34, writeFileSync as writeFileSync20, statSync as statSync18 } from "fs";
110534
- import { resolve as resolve30, join as join61, basename as basename8 } from "path";
110590
+ import { resolve as resolve30, join as join63, basename as basename8 } from "path";
110535
110591
  function resolveDistDir() {
110536
110592
  return resolveStudioBundle().dir;
110537
110593
  }
@@ -110576,7 +110632,7 @@ function resolveRuntimePath() {
110576
110632
  return builtPath;
110577
110633
  }
110578
110634
  function readStudioManualEditManifestContent(projectDir) {
110579
- const manifestPath2 = join61(projectDir, STUDIO_MANUAL_EDITS_PATH2);
110635
+ const manifestPath2 = join63(projectDir, STUDIO_MANUAL_EDITS_PATH2);
110580
110636
  if (!existsSync54(manifestPath2)) return "";
110581
110637
  try {
110582
110638
  return readFileSync34(manifestPath2, "utf-8");
@@ -110682,7 +110738,7 @@ async function loadPreviewServerBuildSignature() {
110682
110738
  ]);
110683
110739
  }
110684
110740
  function rewriteWrittenToHostViewport(projectDir, written) {
110685
- const indexPath2 = join61(projectDir, "index.html");
110741
+ const indexPath2 = join63(projectDir, "index.html");
110686
110742
  if (!existsSync54(indexPath2)) return;
110687
110743
  const indexHtml = readFileSync34(indexPath2, "utf-8");
110688
110744
  const hostW = indexHtml.match(/data-width="(\d+)"/)?.[1];
@@ -110739,8 +110795,8 @@ function createStudioServer(options) {
110739
110795
  const { injectDeterministicFontFaces: injectDeterministicFontFaces2 } = await Promise.resolve().then(() => (init_deterministicFonts(), deterministicFonts_exports));
110740
110796
  const { prepareAnimatedGifInputs: prepareAnimatedGifInputs2 } = await Promise.resolve().then(() => (init_animatedGifPrep(), animatedGifPrep_exports));
110741
110797
  const { downloadToTemp: downloadToTemp2 } = await Promise.resolve().then(() => (init_urlDownloader2(), urlDownloader_exports));
110742
- const gifOutputDir = join61(project2.dir, ".hyperframes", "prepared-assets", "gif");
110743
- const gifDownloadDir = join61(project2.dir, ".hyperframes", "prepared-assets", "downloads");
110798
+ const gifOutputDir = join63(project2.dir, ".hyperframes", "prepared-assets", "gif");
110799
+ const gifDownloadDir = join63(project2.dir, ".hyperframes", "prepared-assets", "downloads");
110744
110800
  const prepared = await prepareAnimatedGifInputs2(html, {
110745
110801
  projectDir: project2.dir,
110746
110802
  downloadDir: gifDownloadDir,
@@ -110761,7 +110817,7 @@ function createStudioServer(options) {
110761
110817
  return await lintHyperframeHtml2(html, opts);
110762
110818
  },
110763
110819
  runtimeUrl: "/api/runtime.js",
110764
- rendersDir: () => join61(projectDir, "renders"),
110820
+ rendersDir: () => join63(projectDir, "renders"),
110765
110821
  startRender(opts) {
110766
110822
  const state = {
110767
110823
  id: opts.jobId,
@@ -111098,7 +111154,7 @@ __export(preview_exports, {
111098
111154
  });
111099
111155
  import { spawn as spawn12 } from "child_process";
111100
111156
  import { existsSync as existsSync55, lstatSync as lstatSync4, symlinkSync as symlinkSync3, unlinkSync as unlinkSync4, readlinkSync, mkdirSync as mkdirSync30 } from "fs";
111101
- import { resolve as resolve31, dirname as dirname24, basename as basename9, join as join63 } from "path";
111157
+ import { resolve as resolve31, dirname as dirname24, basename as basename9, join as join64 } from "path";
111102
111158
  import { fileURLToPath as fileURLToPath8 } from "url";
111103
111159
  import { createRequire as createRequire2 } from "module";
111104
111160
  function previewBaseUrl(port, host = "127.0.0.1") {
@@ -111404,7 +111460,7 @@ function printStudioSummary(projectName, url, opts = {}) {
111404
111460
  console.log();
111405
111461
  }
111406
111462
  function linkProjectIntoStudioData(dir, projectsDir, projectName) {
111407
- const symlinkPath = join63(projectsDir, projectName);
111463
+ const symlinkPath = join64(projectsDir, projectName);
111408
111464
  mkdirSync30(projectsDir, { recursive: true });
111409
111465
  let createdSymlink = false;
111410
111466
  if (dir !== symlinkPath) {
@@ -111467,13 +111523,13 @@ function attachStudioReadyHandler(child, spinner, projectName, options) {
111467
111523
  async function runDevMode(dir, options) {
111468
111524
  const thisFile = fileURLToPath8(import.meta.url);
111469
111525
  const repoRoot2 = resolve31(dirname24(thisFile), "..", "..", "..", "..");
111470
- const projectsDir = join63(repoRoot2, "packages", "studio", "data", "projects");
111526
+ const projectsDir = join64(repoRoot2, "packages", "studio", "data", "projects");
111471
111527
  const pName = options?.projectName ?? basename9(dir);
111472
111528
  const { symlinkPath, createdSymlink } = linkProjectIntoStudioData(dir, projectsDir, pName);
111473
111529
  ge(c.bold("hyperframes preview"));
111474
111530
  const s2 = ft();
111475
111531
  s2.start("Starting studio...");
111476
- const studioPkgDir = join63(repoRoot2, "packages", "studio");
111532
+ const studioPkgDir = join64(repoRoot2, "packages", "studio");
111477
111533
  const child = spawn12("bun", ["run", "dev"], {
111478
111534
  cwd: studioPkgDir,
111479
111535
  stdio: ["ignore", "pipe", "pipe"]
@@ -111485,7 +111541,7 @@ async function runDevMode(dir, options) {
111485
111541
  }
111486
111542
  function hasLocalStudio(dir) {
111487
111543
  try {
111488
- const req = createRequire2(join63(dir, "package.json"));
111544
+ const req = createRequire2(join64(dir, "package.json"));
111489
111545
  req.resolve("@hyperframes/studio/package.json");
111490
111546
  return true;
111491
111547
  } catch {
@@ -111493,10 +111549,10 @@ function hasLocalStudio(dir) {
111493
111549
  }
111494
111550
  }
111495
111551
  async function runLocalStudioMode(dir, options) {
111496
- const req = createRequire2(join63(dir, "package.json"));
111552
+ const req = createRequire2(join64(dir, "package.json"));
111497
111553
  const studioPkgPath = dirname24(req.resolve("@hyperframes/studio/package.json"));
111498
111554
  const pName = options?.projectName ?? basename9(dir);
111499
- const projectsDir = join63(studioPkgPath, "data", "projects");
111555
+ const projectsDir = join64(studioPkgPath, "data", "projects");
111500
111556
  const { symlinkPath, createdSymlink } = linkProjectIntoStudioData(dir, projectsDir, pName);
111501
111557
  ge(c.bold("hyperframes preview") + c.dim(" (local studio)"));
111502
111558
  const s2 = ft();
@@ -111859,7 +111915,7 @@ import {
111859
111915
  readFileSync as readFileSync35,
111860
111916
  readdirSync as readdirSync21
111861
111917
  } from "fs";
111862
- import { resolve as resolve33, basename as basename10, join as join64, dirname as dirname25 } from "path";
111918
+ import { resolve as resolve33, basename as basename10, join as join65, dirname as dirname25 } from "path";
111863
111919
  import { fileURLToPath as fileURLToPath9 } from "url";
111864
111920
  import { execFileSync as execFileSync7, spawn as spawn13 } from "child_process";
111865
111921
  function probeVideo(filePath) {
@@ -111993,7 +112049,7 @@ function listHtmlFiles(dir) {
111993
112049
  const ignoredDirs = /* @__PURE__ */ new Set([".git", "dist", "node_modules"]);
111994
112050
  function walk(currentDir) {
111995
112051
  for (const entry of readdirSync21(currentDir, { withFileTypes: true })) {
111996
- const entryPath = join64(currentDir, entry.name);
112052
+ const entryPath = join65(currentDir, entry.name);
111997
112053
  if (entry.isDirectory()) {
111998
112054
  if (!ignoredDirs.has(entry.name)) walk(entryPath);
111999
112055
  continue;
@@ -112038,7 +112094,7 @@ function writeTailwindSupport(destDir) {
112038
112094
  }
112039
112095
  }
112040
112096
  function patchVideoSrc(dir, videoFilename, durationSeconds) {
112041
- const htmlFiles = readdirSync21(dir, { withFileTypes: true, recursive: true }).filter((e3) => e3.isFile() && e3.name.endsWith(".html")).map((e3) => join64(e3.parentPath, e3.name));
112097
+ const htmlFiles = readdirSync21(dir, { withFileTypes: true, recursive: true }).filter((e3) => e3.isFile() && e3.name.endsWith(".html")).map((e3) => join65(e3.parentPath, e3.name));
112042
112098
  for (const file of htmlFiles) {
112043
112099
  let content = readFileSync35(file, "utf-8");
112044
112100
  if (videoFilename) {
@@ -112193,7 +112249,7 @@ function applyResolutionPreset(destDir, resolution) {
112193
112249
  async function scaffoldProject(destDir, name, templateId, localVideoName, durationSeconds, tailwind = false, resolution) {
112194
112250
  mkdirSync31(destDir, { recursive: true });
112195
112251
  const templateDir = getStaticTemplateDir(templateId);
112196
- if (existsSync56(join64(templateDir, "index.html"))) {
112252
+ if (existsSync56(join65(templateDir, "index.html"))) {
112197
112253
  cpSync5(templateDir, destDir, { recursive: true });
112198
112254
  } else {
112199
112255
  await fetchRemoteTemplate(templateId, destDir);
@@ -112222,7 +112278,7 @@ async function scaffoldProject(destDir, name, templateId, localVideoName, durati
112222
112278
  const sharedDir = getSharedTemplateDir();
112223
112279
  if (existsSync56(sharedDir)) {
112224
112280
  for (const entry of readdirSync21(sharedDir, { withFileTypes: true })) {
112225
- const src = join64(sharedDir, entry.name);
112281
+ const src = join65(sharedDir, entry.name);
112226
112282
  const dest = resolve33(destDir, entry.name);
112227
112283
  if (entry.isFile() || entry.isSymbolicLink()) {
112228
112284
  copyFileSync7(src, dest);
@@ -113726,7 +113782,7 @@ var init_present = __esm({
113726
113782
  });
113727
113783
 
113728
113784
  // src/utils/publishProject.ts
113729
- import { basename as basename11, dirname as dirname27, join as join65, posix as posix4, relative as relative13, resolve as resolve39 } from "path";
113785
+ import { basename as basename11, dirname as dirname27, join as join66, posix as posix4, relative as relative13, resolve as resolve39 } from "path";
113730
113786
  import { existsSync as existsSync61, readdirSync as readdirSync23, readFileSync as readFileSync38, statSync as statSync19 } from "fs";
113731
113787
  import AdmZip from "adm-zip";
113732
113788
  function isRecord3(value) {
@@ -113827,7 +113883,7 @@ function shouldIgnoreSegment(segment) {
113827
113883
  function collectProjectFiles(rootDir, currentDir, paths) {
113828
113884
  for (const entry of readdirSync23(currentDir, { withFileTypes: true })) {
113829
113885
  if (shouldIgnoreSegment(entry.name)) continue;
113830
- const absolutePath = join65(currentDir, entry.name);
113886
+ const absolutePath = join66(currentDir, entry.name);
113831
113887
  const relativePath = relative13(rootDir, absolutePath).replaceAll("\\", "/");
113832
113888
  if (!relativePath) continue;
113833
113889
  if (entry.isDirectory()) {
@@ -113957,7 +114013,7 @@ function createPublishArchive(projectDir) {
113957
114013
  }
113958
114014
  const fileContents = /* @__PURE__ */ new Map();
113959
114015
  for (const filePath of filePaths) {
113960
- fileContents.set(filePath, readFileSync38(join65(absProjectDir, filePath)));
114016
+ fileContents.set(filePath, readFileSync38(join66(absProjectDir, filePath)));
113961
114017
  }
113962
114018
  localizeExternalAssets(absProjectDir, fileContents);
113963
114019
  const archive = new AdmZip();
@@ -114090,7 +114146,7 @@ __export(publish_exports, {
114090
114146
  });
114091
114147
  import { resolve as resolve40 } from "path";
114092
114148
  import { existsSync as existsSync63 } from "fs";
114093
- import { join as join66 } from "path";
114149
+ import { join as join67 } from "path";
114094
114150
  var examples8, publish_default;
114095
114151
  var init_publish = __esm({
114096
114152
  "src/commands/publish.ts"() {
@@ -114129,7 +114185,7 @@ var init_publish = __esm({
114129
114185
  async run({ args }) {
114130
114186
  const rawArg = args.dir;
114131
114187
  const dir = resolve40(rawArg ?? ".");
114132
- const indexPath2 = join66(dir, "index.html");
114188
+ const indexPath2 = join67(dir, "index.html");
114133
114189
  if (existsSync63(indexPath2)) {
114134
114190
  const lintResult = await lintProject(dir);
114135
114191
  if (lintResult.totalErrors > 0 || lintResult.totalWarnings > 0) {
@@ -114891,7 +114947,7 @@ __export(batchRender_exports, {
114891
114947
  runBatchRender: () => runBatchRender
114892
114948
  });
114893
114949
  import { mkdirSync as mkdirSync33, readFileSync as readFileSync40, writeFileSync as writeFileSync23 } from "fs";
114894
- import { dirname as dirname28, join as join67, resolve as resolve43, sep as sep8 } from "path";
114950
+ import { dirname as dirname28, join as join68, resolve as resolve43, sep as sep8 } from "path";
114895
114951
  function isRecord4(value) {
114896
114952
  return value !== null && typeof value === "object" && !Array.isArray(value);
114897
114953
  }
@@ -115027,7 +115083,7 @@ function prepareBatchRender(options) {
115027
115083
  variables,
115028
115084
  outputPath: resolve43(resolveOutputTemplate(options.outputTemplate, variables, index))
115029
115085
  }));
115030
- const manifestPath2 = join67(
115086
+ const manifestPath2 = join68(
115031
115087
  commonOutputDirectory(rows.map((row) => row.outputPath)),
115032
115088
  "manifest.json"
115033
115089
  );
@@ -115240,7 +115296,7 @@ __export(render_exports, {
115240
115296
  });
115241
115297
  import { mkdirSync as mkdirSync34, readdirSync as readdirSync24, readFileSync as readFileSync41, statSync as statSync20, writeFileSync as writeFileSync24, rmSync as rmSync18 } from "fs";
115242
115298
  import { cpus as cpus4, freemem as freemem5, tmpdir as tmpdir6 } from "os";
115243
- import { resolve as resolve44, dirname as dirname29, join as join68, basename as basename12 } from "path";
115299
+ import { resolve as resolve44, dirname as dirname29, join as join69, basename as basename12 } from "path";
115244
115300
  import { execFileSync as execFileSync9, spawn as spawn14 } from "child_process";
115245
115301
  function formatFpsParseError(input2, reason) {
115246
115302
  switch (reason) {
@@ -115332,9 +115388,9 @@ function ensureDockerImage(version2, platform10, quiet) {
115332
115388
  }
115333
115389
  if (!quiet) console.log(c.dim(` Building Docker image: ${tag} (${platform10})...`));
115334
115390
  const dockerfilePath = resolveDockerfilePath();
115335
- const tmpDir = join68(tmpdir6(), `hyperframes-docker-${Date.now()}`);
115391
+ const tmpDir = join69(tmpdir6(), `hyperframes-docker-${Date.now()}`);
115336
115392
  mkdirSync34(tmpDir, { recursive: true });
115337
- writeFileSync24(join68(tmpDir, "Dockerfile"), readFileSync41(dockerfilePath));
115393
+ writeFileSync24(join69(tmpDir, "Dockerfile"), readFileSync41(dockerfilePath));
115338
115394
  const targetArch = platform10 === "linux/arm64" ? "arm64" : "amd64";
115339
115395
  try {
115340
115396
  execFileSync9(
@@ -115738,7 +115794,7 @@ function printRenderComplete(outputPath, elapsedMs, quiet, outputDurationSeconds
115738
115794
  for (const entry of readdirSync24(outputPath, { withFileTypes: true })) {
115739
115795
  if (!entry.isFile()) continue;
115740
115796
  try {
115741
- total += statSync20(join68(outputPath, entry.name)).size;
115797
+ total += statSync20(join69(outputPath, entry.name)).size;
115742
115798
  } catch {
115743
115799
  }
115744
115800
  }
@@ -116156,8 +116212,8 @@ var init_render = __esm({
116156
116212
  const now = /* @__PURE__ */ new Date();
116157
116213
  const datePart = now.toISOString().slice(0, 10);
116158
116214
  const timePart = now.toTimeString().slice(0, 8).replace(/:/g, "-");
116159
- const batchOutputTemplate = args.output ? args.output : join68(rendersDir, `${project.name}_${datePart}_${timePart}_{index}${ext}`);
116160
- const outputPath = args.output ? resolve44(args.output) : join68(rendersDir, `${project.name}_${datePart}_${timePart}${ext}`);
116215
+ const batchOutputTemplate = args.output ? args.output : join69(rendersDir, `${project.name}_${datePart}_${timePart}_{index}${ext}`);
116216
+ const outputPath = args.output ? resolve44(args.output) : join69(rendersDir, `${project.name}_${datePart}_${timePart}${ext}`);
116161
116217
  if (!batchPath) mkdirSync34(dirname29(outputPath), { recursive: true });
116162
116218
  const useDocker = args.docker ?? false;
116163
116219
  const useGpu = args.gpu ?? false;
@@ -116650,16 +116706,16 @@ var init_beats = __esm({
116650
116706
  // src/beats/headlessAnalyzer.ts
116651
116707
  import { existsSync as existsSync65, readFileSync as readFileSync43 } from "fs";
116652
116708
  import { createRequire as createRequire3 } from "module";
116653
- import { dirname as dirname30, join as join69 } from "path";
116709
+ import { dirname as dirname30, join as join70 } from "path";
116654
116710
  import { fileURLToPath as fileURLToPath11 } from "url";
116655
116711
  function findPrebuiltBundle() {
116656
116712
  const here = dirname30(fileURLToPath11(import.meta.url));
116657
116713
  const candidates = [
116658
- join69(here, "beat-analyzer.global.js"),
116714
+ join70(here, "beat-analyzer.global.js"),
116659
116715
  // dist root (tsup-bundled cli)
116660
- join69(here, "../beat-analyzer.global.js"),
116716
+ join70(here, "../beat-analyzer.global.js"),
116661
116717
  // dist/beats → dist
116662
- join69(here, "../dist/beat-analyzer.global.js")
116718
+ join70(here, "../dist/beat-analyzer.global.js")
116663
116719
  ];
116664
116720
  for (const p2 of candidates) {
116665
116721
  if (existsSync65(p2)) return p2;
@@ -116669,7 +116725,7 @@ function findPrebuiltBundle() {
116669
116725
  async function buildFromCoreSource() {
116670
116726
  const esbuild = await import("esbuild");
116671
116727
  const coreRoot = dirname30(require2.resolve("@hyperframes/core/package.json"));
116672
- const entry = join69(coreRoot, "src/beats/beatDetection.ts");
116728
+ const entry = join70(coreRoot, "src/beats/beatDetection.ts");
116673
116729
  const result = await esbuild.build({
116674
116730
  stdin: {
116675
116731
  contents: `import { analyzeMusicFromBuffer } from ${JSON.stringify(entry)};
@@ -116770,7 +116826,7 @@ __export(beats_exports, {
116770
116826
  examples: () => examples11
116771
116827
  });
116772
116828
  import { existsSync as existsSync66, readFileSync as readFileSync44, mkdirSync as mkdirSync35, writeFileSync as writeFileSync25 } from "fs";
116773
- import { resolve as resolve45, join as join70, dirname as dirname31 } from "path";
116829
+ import { resolve as resolve45, join as join71, dirname as dirname31 } from "path";
116774
116830
  function fail(message) {
116775
116831
  console.error(c.error(message));
116776
116832
  process.exit(1);
@@ -116840,7 +116896,7 @@ var init_beats2 = __esm({
116840
116896
  if (result.beatTimes.length === 0) {
116841
116897
  fail(`No beats detected in ${rel} \u2014 nothing written. (Track may be silent/ambient.)`);
116842
116898
  }
116843
- const outPath = join70(project.dir, "beats", `${rel}.json`);
116899
+ const outPath = join71(project.dir, "beats", `${rel}.json`);
116844
116900
  mkdirSync35(dirname31(outPath), { recursive: true });
116845
116901
  writeFileSync25(outPath, serializeBeats(result.beatTimes, result.beatStrengths, rel));
116846
116902
  report(`beats/${rel}.json`, result, Boolean(args.json));
@@ -117301,7 +117357,7 @@ var init_motionAudit = __esm({
117301
117357
 
117302
117358
  // src/utils/motionSpec.ts
117303
117359
  import { existsSync as existsSync68, readFileSync as readFileSync45, readdirSync as readdirSync25 } from "fs";
117304
- import { basename as basename13, join as join71 } from "path";
117360
+ import { basename as basename13, join as join73 } from "path";
117305
117361
  function isObject2(value) {
117306
117362
  return typeof value === "object" && value !== null && !Array.isArray(value);
117307
117363
  }
@@ -117347,7 +117403,7 @@ function findMotionSpec(projectDir) {
117347
117403
  const entries2 = readdirSync25(projectDir);
117348
117404
  const sidecars = entries2.filter((name) => name.endsWith(".motion.json")).sort();
117349
117405
  if (!sidecars[0]) return null;
117350
- if (sidecars.length === 1) return join71(projectDir, sidecars[0]);
117406
+ if (sidecars.length === 1) return join73(projectDir, sidecars[0]);
117351
117407
  const htmlBases = new Set(
117352
117408
  entries2.filter((name) => name.endsWith(".html")).map((name) => basename13(name, ".html"))
117353
117409
  );
@@ -117357,7 +117413,7 @@ function findMotionSpec(projectDir) {
117357
117413
  `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`
117358
117414
  );
117359
117415
  }
117360
- return join71(projectDir, matched[0] ?? sidecars[0]);
117416
+ return join73(projectDir, matched[0] ?? sidecars[0]);
117361
117417
  }
117362
117418
  function readMotionSpec(path2) {
117363
117419
  let raw;
@@ -117414,7 +117470,7 @@ __export(layout_exports, {
117414
117470
  examples: () => examples12
117415
117471
  });
117416
117472
  import { existsSync as existsSync69, readFileSync as readFileSync46 } from "fs";
117417
- import { dirname as dirname32, join as join73 } from "path";
117473
+ import { dirname as dirname32, join as join74 } from "path";
117418
117474
  import { fileURLToPath as fileURLToPath12 } from "url";
117419
117475
  function buildMotionSampleTimes(duration) {
117420
117476
  if (!Number.isFinite(duration) || duration <= 0) return [];
@@ -117599,7 +117655,7 @@ async function runLayoutAudit(projectDir, opts) {
117599
117655
  }
117600
117656
  }
117601
117657
  function loadBrowserScript(name) {
117602
- const candidates = [join73(__dirname2, name), join73(__dirname2, "commands", name)];
117658
+ const candidates = [join74(__dirname2, name), join74(__dirname2, "commands", name)];
117603
117659
  for (const candidate of candidates) {
117604
117660
  if (existsSync69(candidate)) return readFileSync46(candidate, "utf-8");
117605
117661
  }
@@ -120750,7 +120806,7 @@ __export(info_exports, {
120750
120806
  orientation: () => orientation
120751
120807
  });
120752
120808
  import { readFileSync as readFileSync48, readdirSync as readdirSync26, statSync as statSync24 } from "fs";
120753
- import { join as join74 } from "path";
120809
+ import { join as join75 } from "path";
120754
120810
  function orientation(width, height) {
120755
120811
  if (width > height) return "landscape";
120756
120812
  if (height > width) return "portrait";
@@ -120764,7 +120820,7 @@ function durationFromHtml(html, fallback) {
120764
120820
  function totalSize(dir) {
120765
120821
  let total = 0;
120766
120822
  for (const entry of readdirSync26(dir, { withFileTypes: true })) {
120767
- const path2 = join74(dir, entry.name);
120823
+ const path2 = join75(dir, entry.name);
120768
120824
  if (entry.isDirectory()) {
120769
120825
  total += totalSize(path2);
120770
120826
  } else {
@@ -121032,7 +121088,7 @@ __export(benchmark_exports, {
121032
121088
  examples: () => examples17
121033
121089
  });
121034
121090
  import { existsSync as existsSync73, statSync as statSync25 } from "fs";
121035
- import { resolve as resolve49, join as join75 } from "path";
121091
+ import { resolve as resolve49, join as join76 } from "path";
121036
121092
  var examples17, FPS_30, FPS_60, DEFAULT_CONFIGS, benchmark_default;
121037
121093
  var init_benchmark = __esm({
121038
121094
  "src/commands/benchmark.ts"() {
@@ -121110,7 +121166,7 @@ var init_benchmark = __esm({
121110
121166
  s2?.start(`Benchmarking ${config.label}...`);
121111
121167
  for (let i2 = 0; i2 < runsPerConfig; i2++) {
121112
121168
  s2?.message(`${config.label} \u2014 run ${i2 + 1}/${runsPerConfig}`);
121113
- const outputPath = join75(
121169
+ const outputPath = join76(
121114
121170
  benchDir,
121115
121171
  `${config.label.replace(/[^a-zA-Z0-9]/g, "_")}_run${i2}.mp4`
121116
121172
  );
@@ -121396,7 +121452,7 @@ __export(manager_exports3, {
121396
121452
  });
121397
121453
  import { existsSync as existsSync74, mkdirSync as mkdirSync36 } from "fs";
121398
121454
  import { homedir as homedir11, platform as platform8, arch } from "os";
121399
- import { join as join76 } from "path";
121455
+ import { join as join77 } from "path";
121400
121456
  function isDevice(value) {
121401
121457
  return typeof value === "string" && DEVICES.includes(value);
121402
121458
  }
@@ -121436,7 +121492,7 @@ function listAvailableProviders() {
121436
121492
  return out;
121437
121493
  }
121438
121494
  function modelPath(model = DEFAULT_MODEL2) {
121439
- return join76(MODELS_DIR2, `${model}.onnx`);
121495
+ return join77(MODELS_DIR2, `${model}.onnx`);
121440
121496
  }
121441
121497
  async function ensureModel2(model = DEFAULT_MODEL2, options) {
121442
121498
  const dest = modelPath(model);
@@ -121454,7 +121510,7 @@ var init_manager3 = __esm({
121454
121510
  "src/background-removal/manager.ts"() {
121455
121511
  "use strict";
121456
121512
  init_download();
121457
- MODELS_DIR2 = join76(homedir11(), ".cache", "hyperframes", "background-removal", "models");
121513
+ MODELS_DIR2 = join77(homedir11(), ".cache", "hyperframes", "background-removal", "models");
121458
121514
  DEFAULT_MODEL2 = "u2net_human_seg";
121459
121515
  MODEL_URLS = {
121460
121516
  u2net_human_seg: "https://github.com/danielgatis/rembg/releases/download/v0.0.0/u2net_human_seg.onnx"
@@ -122165,7 +122221,7 @@ __export(transcribe_exports2, {
122165
122221
  examples: () => examples20
122166
122222
  });
122167
122223
  import { existsSync as existsSync76, writeFileSync as writeFileSync27 } from "fs";
122168
- import { resolve as resolve51, join as join77, extname as extname12, dirname as dirname35 } from "path";
122224
+ import { resolve as resolve51, join as join78, extname as extname12, dirname as dirname35 } from "path";
122169
122225
  function failWith(message, json) {
122170
122226
  trackCommandFailure("transcribe", message);
122171
122227
  if (json) {
@@ -122188,7 +122244,7 @@ async function importTranscript(inputPath, dir, json) {
122188
122244
  const { loadTranscript: loadTranscript2, patchCaptionHtml: patchCaptionHtml2 } = await Promise.resolve().then(() => (init_normalize(), normalize_exports));
122189
122245
  const { words, format } = loadTranscript2(inputPath);
122190
122246
  if (words.length === 0) exitNoWords(json);
122191
- const outPath = join77(dir, "transcript.json");
122247
+ const outPath = join78(dir, "transcript.json");
122192
122248
  writeFileSync27(outPath, JSON.stringify(words, null, 2));
122193
122249
  patchCaptionHtml2(dir, words);
122194
122250
  if (json) {
@@ -122206,7 +122262,7 @@ async function exportTranscript(inputPath, dir, to, output, json, preserveCues)
122206
122262
  const { words, format } = loadTranscript2(inputPath);
122207
122263
  if (words.length === 0) exitNoWords(json);
122208
122264
  const preGrouped = preserveCues || format === "srt" || format === "vtt" || void 0;
122209
- const outPath = resolve51(output ?? join77(dir, `transcript.${to}`));
122265
+ const outPath = resolve51(output ?? join78(dir, `transcript.${to}`));
122210
122266
  const content = to === "srt" ? formatSrt2(words, { preGrouped }) : formatVtt2(words, { preGrouped });
122211
122267
  writeFileSync27(outPath, content);
122212
122268
  if (json) {
@@ -122395,7 +122451,7 @@ var init_transcribe2 = __esm({
122395
122451
  // src/tts/manager.ts
122396
122452
  import { existsSync as existsSync77, mkdirSync as mkdirSync37 } from "fs";
122397
122453
  import { homedir as homedir12 } from "os";
122398
- import { join as join78 } from "path";
122454
+ import { join as join79 } from "path";
122399
122455
  function inferLangFromVoiceId(voiceId) {
122400
122456
  const first = voiceId.charAt(0).toLowerCase();
122401
122457
  return VOICE_PREFIX_LANG[first] ?? "en-us";
@@ -122404,7 +122460,7 @@ function isSupportedLang(value) {
122404
122460
  return SUPPORTED_LANGS.includes(value);
122405
122461
  }
122406
122462
  async function ensureModel3(model = DEFAULT_MODEL3, options) {
122407
- const modelPath2 = join78(MODELS_DIR3, `${model}.onnx`);
122463
+ const modelPath2 = join79(MODELS_DIR3, `${model}.onnx`);
122408
122464
  if (existsSync77(modelPath2)) return modelPath2;
122409
122465
  const url = MODEL_URLS2[model];
122410
122466
  if (!url) {
@@ -122421,7 +122477,7 @@ async function ensureModel3(model = DEFAULT_MODEL3, options) {
122421
122477
  return modelPath2;
122422
122478
  }
122423
122479
  async function ensureVoices(options) {
122424
- const voicesPath = join78(VOICES_DIR, "voices-v1.0.bin");
122480
+ const voicesPath = join79(VOICES_DIR, "voices-v1.0.bin");
122425
122481
  if (existsSync77(voicesPath)) return voicesPath;
122426
122482
  mkdirSync37(VOICES_DIR, { recursive: true });
122427
122483
  options?.onProgress?.("Downloading voice data (~27 MB)...");
@@ -122436,9 +122492,9 @@ var init_manager4 = __esm({
122436
122492
  "src/tts/manager.ts"() {
122437
122493
  "use strict";
122438
122494
  init_download();
122439
- CACHE_DIR3 = join78(homedir12(), ".cache", "hyperframes", "tts");
122440
- MODELS_DIR3 = join78(CACHE_DIR3, "models");
122441
- VOICES_DIR = join78(CACHE_DIR3, "voices");
122495
+ CACHE_DIR3 = join79(homedir12(), ".cache", "hyperframes", "tts");
122496
+ MODELS_DIR3 = join79(CACHE_DIR3, "models");
122497
+ VOICES_DIR = join79(CACHE_DIR3, "voices");
122442
122498
  DEFAULT_MODEL3 = "kokoro-v1.0";
122443
122499
  MODEL_URLS2 = {
122444
122500
  "kokoro-v1.0": "https://github.com/thewh1teagle/kokoro-onnx/releases/download/model-files-v1.0/kokoro-v1.0.onnx"
@@ -122556,7 +122612,7 @@ __export(synthesize_exports, {
122556
122612
  });
122557
122613
  import { execFileSync as execFileSync11 } from "child_process";
122558
122614
  import { existsSync as existsSync78, writeFileSync as writeFileSync28, mkdirSync as mkdirSync38, readdirSync as readdirSync27, unlinkSync as unlinkSync5 } from "fs";
122559
- import { join as join79, dirname as dirname36, basename as basename15 } from "path";
122615
+ import { join as join80, dirname as dirname36, basename as basename15 } from "path";
122560
122616
  import { homedir as homedir13 } from "os";
122561
122617
  function ensureSynthScript() {
122562
122618
  if (!existsSync78(SCRIPT_PATH)) {
@@ -122567,7 +122623,7 @@ function ensureSynthScript() {
122567
122623
  for (const entry of readdirSync27(SCRIPT_DIR)) {
122568
122624
  if (entry !== currentName && /^synth(-v\d+)?\.py$/.test(entry)) {
122569
122625
  try {
122570
- unlinkSync5(join79(SCRIPT_DIR, entry));
122626
+ unlinkSync5(join80(SCRIPT_DIR, entry));
122571
122627
  } catch {
122572
122628
  }
122573
122629
  }
@@ -122678,8 +122734,8 @@ print(json.dumps({
122678
122734
  "langApplied": bool(lang and supports_lang),
122679
122735
  }))
122680
122736
  `;
122681
- SCRIPT_DIR = join79(homedir13(), ".cache", "hyperframes", "tts");
122682
- SCRIPT_PATH = join79(SCRIPT_DIR, "synth-v2.py");
122737
+ SCRIPT_DIR = join80(homedir13(), ".cache", "hyperframes", "tts");
122738
+ SCRIPT_PATH = join80(SCRIPT_DIR, "synth-v2.py");
122683
122739
  }
122684
122740
  });
122685
122741
 
@@ -122893,7 +122949,7 @@ __export(docs_exports, {
122893
122949
  examples: () => examples22
122894
122950
  });
122895
122951
  import { readFileSync as readFileSync51, existsSync as existsSync80 } from "fs";
122896
- import { resolve as resolve53, dirname as dirname37, join as join80 } from "path";
122952
+ import { resolve as resolve53, dirname as dirname37, join as join81 } from "path";
122897
122953
  import { fileURLToPath as fileURLToPath13 } from "url";
122898
122954
  function docsDir() {
122899
122955
  const thisFile = fileURLToPath13(import.meta.url);
@@ -122997,7 +123053,7 @@ var init_docs = __esm({
122997
123053
  }
122998
123054
  process.exit(1);
122999
123055
  }
123000
- const filePath = join80(docsDir(), entry.file);
123056
+ const filePath = join81(docsDir(), entry.file);
123001
123057
  if (!existsSync80(filePath)) {
123002
123058
  console.error(c.error(`Doc file not found: ${filePath}`));
123003
123059
  process.exit(1);
@@ -123828,7 +123884,7 @@ __export(validate_exports, {
123828
123884
  waitForPreferredSeekTarget: () => waitForPreferredSeekTarget
123829
123885
  });
123830
123886
  import { existsSync as existsSync81, readFileSync as readFileSync53 } from "fs";
123831
- import { join as join81, dirname as dirname38 } from "path";
123887
+ import { join as join83, dirname as dirname38 } from "path";
123832
123888
  import { fileURLToPath as fileURLToPath14 } from "url";
123833
123889
  function resolveNavigationTimeoutMs(optTimeout) {
123834
123890
  return Math.max(NAV_TIMEOUT_FLOOR_MS, optTimeout ?? 0);
@@ -123986,8 +124042,8 @@ async function runContrastAudit(page) {
123986
124042
  }
123987
124043
  function loadContrastAuditScript() {
123988
124044
  const candidates = [
123989
- join81(__dirname3, "contrast-audit.browser.js"),
123990
- join81(__dirname3, "commands", "contrast-audit.browser.js")
124045
+ join83(__dirname3, "contrast-audit.browser.js"),
124046
+ join83(__dirname3, "commands", "contrast-audit.browser.js")
123991
124047
  ];
123992
124048
  for (const candidate of candidates) {
123993
124049
  if (existsSync81(candidate)) return readFileSync53(candidate, "utf-8");
@@ -124222,7 +124278,7 @@ __export(contactSheet_exports, {
124222
124278
  });
124223
124279
  import sharp from "sharp";
124224
124280
  import { readdirSync as readdirSync28, readFileSync as readFileSync54, writeFileSync as writeFileSync29, unlinkSync as unlinkSync6, existsSync as existsSync83 } from "fs";
124225
- import { join as join83, extname as extname14, basename as basename16, dirname as dirname39 } from "path";
124281
+ import { join as join84, extname as extname14, basename as basename16, dirname as dirname39 } from "path";
124226
124282
  async function createContactSheet(imagePaths, outputPath, opts = {}) {
124227
124283
  const {
124228
124284
  cols = 3,
@@ -124304,7 +124360,7 @@ async function createScrollContactSheet(screenshotsDir, outputPath) {
124304
124360
  if (!existsSync83(screenshotsDir)) return [];
124305
124361
  const scrollFiles = readdirSync28(screenshotsDir).filter((f3) => f3.startsWith("scroll-") && f3.endsWith(".png")).sort();
124306
124362
  if (scrollFiles.length === 0) return [];
124307
- const paths = scrollFiles.map((f3) => join83(screenshotsDir, f3));
124363
+ const paths = scrollFiles.map((f3) => join84(screenshotsDir, f3));
124308
124364
  const labels = scrollFiles.map((f3) => {
124309
124365
  const m2 = f3.match(/scroll-(\d+)\.png/);
124310
124366
  return m2 ? `${m2[1]}% scroll` : f3;
@@ -124321,7 +124377,7 @@ async function createSnapshotContactSheet(snapshotsDir, outputPath) {
124321
124377
  if (!existsSync83(snapshotsDir)) return [];
124322
124378
  const snapshotFiles = readdirSync28(snapshotsDir).filter((f3) => f3.startsWith("frame-") && f3.endsWith(".png")).sort();
124323
124379
  if (snapshotFiles.length === 0) return [];
124324
- const paths = snapshotFiles.map((f3) => join83(snapshotsDir, f3));
124380
+ const paths = snapshotFiles.map((f3) => join84(snapshotsDir, f3));
124325
124381
  const labels = snapshotFiles.map((f3) => {
124326
124382
  const m2 = f3.match(/at-([\d.]+)s/);
124327
124383
  return m2 ? `${m2[1]}s` : f3;
@@ -124339,7 +124395,7 @@ async function createAssetContactSheet(assetsDir, outputPath) {
124339
124395
  const imageExts = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".webp"]);
124340
124396
  const assetFiles = readdirSync28(assetsDir).filter((f3) => imageExts.has(extname14(f3).toLowerCase()) && !f3.includes("contact-sheet")).sort();
124341
124397
  if (assetFiles.length === 0) return [];
124342
- const paths = assetFiles.map((f3) => join83(assetsDir, f3));
124398
+ const paths = assetFiles.map((f3) => join84(assetsDir, f3));
124343
124399
  return createContactSheetPages(paths, outputPath, {
124344
124400
  cols: 4,
124345
124401
  cellWidth: 480,
@@ -124358,7 +124414,7 @@ async function createSvgContactSheet(svgsDir, outputPath, assetsRootDir) {
124358
124414
  for (const f3 of readdirSync28(dir).filter((f4) => f4.endsWith(".svg")).sort()) {
124359
124415
  if (!seen.has(f3)) {
124360
124416
  seen.add(f3);
124361
- svgPaths.push(join83(dir, f3));
124417
+ svgPaths.push(join84(dir, f3));
124362
124418
  }
124363
124419
  }
124364
124420
  }
@@ -124370,7 +124426,7 @@ async function createSvgContactSheet(svgsDir, outputPath, assetsRootDir) {
124370
124426
  const labels = [];
124371
124427
  for (let i2 = 0; i2 < svgPaths.length; i2++) {
124372
124428
  const svgPath = svgPaths[i2];
124373
- const tmpPath = join83(tmpDir, `.thumb-${i2}.png`);
124429
+ const tmpPath = join84(tmpDir, `.thumb-${i2}.png`);
124374
124430
  try {
124375
124431
  const svgBuf = readFileSync54(svgPath);
124376
124432
  const thumb = await sharp(svgBuf).resize(thumbSize, thumbSize, {
@@ -155728,10 +155784,10 @@ function iterBinaryChunks(iterator) {
155728
155784
  }
155729
155785
  });
155730
155786
  }
155731
- function partition(str, delimiter) {
155732
- const index = str.indexOf(delimiter);
155787
+ function partition(str, delimiter2) {
155788
+ const index = str.indexOf(delimiter2);
155733
155789
  if (index !== -1) {
155734
- return [str.substring(0, index), delimiter, str.substring(index + delimiter.length)];
155790
+ return [str.substring(0, index), delimiter2, str.substring(index + delimiter2.length)];
155735
155791
  }
155736
155792
  return [str, "", ""];
155737
155793
  }
@@ -159532,11 +159588,11 @@ var init_node4 = __esm({
159532
159588
  while (true) {
159533
159589
  delimiterIndex = -1;
159534
159590
  delimiterLength = 0;
159535
- for (const delimiter of delimiters) {
159536
- const index = buffer.indexOf(delimiter);
159591
+ for (const delimiter2 of delimiters) {
159592
+ const index = buffer.indexOf(delimiter2);
159537
159593
  if (index !== -1 && (delimiterIndex === -1 || index < delimiterIndex)) {
159538
159594
  delimiterIndex = index;
159539
- delimiterLength = delimiter.length;
159595
+ delimiterLength = delimiter2.length;
159540
159596
  }
159541
159597
  }
159542
159598
  if (delimiterIndex === -1) {
@@ -164154,7 +164210,7 @@ __export(snapshot_exports, {
164154
164210
  import { spawn as spawn16 } from "child_process";
164155
164211
  import { existsSync as existsSync84, mkdtempSync as mkdtempSync6, readFileSync as readFileSync55, mkdirSync as mkdirSync39, rmSync as rmSync19, writeFileSync as writeFileSync30 } from "fs";
164156
164212
  import { tmpdir as tmpdir7 } from "os";
164157
- import { resolve as resolve55, join as join84, relative as relative15, isAbsolute as isAbsolute14, basename as basename19 } from "path";
164213
+ import { resolve as resolve55, join as join85, relative as relative15, isAbsolute as isAbsolute14, basename as basename19 } from "path";
164158
164214
  function orbitStageSource() {
164159
164215
  return `function(cam) {
164160
164216
  var root = document.querySelector("[data-composition-id]")
@@ -164177,8 +164233,8 @@ function orbitStageSource() {
164177
164233
  }`;
164178
164234
  }
164179
164235
  async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDecoder = false) {
164180
- const tmp = mkdtempSync6(join84(tmpdir7(), "hf-snapshot-frame-"));
164181
- const outPath = join84(tmp, "frame.png");
164236
+ const tmp = mkdtempSync6(join85(tmpdir7(), "hf-snapshot-frame-"));
164237
+ const outPath = join85(tmp, "frame.png");
164182
164238
  try {
164183
164239
  const ffmpegPath = findFFmpeg();
164184
164240
  if (!ffmpegPath) return null;
@@ -164353,13 +164409,13 @@ async function captureSnapshots(projectDir, opts) {
164353
164409
  );
164354
164410
  }
164355
164411
  const cameraExpr = opts.angle && (opts.angle.yaw !== 0 || opts.angle.pitch !== 0) ? `(${orbitStageSource()})(${JSON.stringify(opts.angle)})` : null;
164356
- const snapshotDir = opts.outputDir ?? join84(projectDir, "snapshots");
164412
+ const snapshotDir = opts.outputDir ?? join85(projectDir, "snapshots");
164357
164413
  mkdirSync39(snapshotDir, { recursive: true });
164358
164414
  try {
164359
164415
  const { readdirSync: readdirSync35 } = await import("fs");
164360
164416
  for (const file of readdirSync35(snapshotDir)) {
164361
164417
  if (/\.(png|jpg|jpeg)$/i.test(file)) {
164362
- rmSync19(join84(snapshotDir, file), { force: true });
164418
+ rmSync19(join85(snapshotDir, file), { force: true });
164363
164419
  }
164364
164420
  }
164365
164421
  } catch {
@@ -164476,7 +164532,7 @@ async function captureSnapshots(projectDir, opts) {
164476
164532
  }
164477
164533
  const timeLabel = `${time.toFixed(1)}s`;
164478
164534
  const filename = `frame-${String(i2).padStart(2, "0")}-at-${timeLabel}.png`;
164479
- const framePath = join84(snapshotDir, filename);
164535
+ const framePath = join85(snapshotDir, filename);
164480
164536
  await page.screenshot({ path: framePath, type: "png" });
164481
164537
  const rel = relative15(projectDir, framePath);
164482
164538
  savedPaths.push(rel.startsWith("..") || isAbsolute14(rel) ? framePath : rel);
@@ -164562,7 +164618,7 @@ var init_snapshot = __esm({
164562
164618
  const angleLabel = camera && (camera.yaw !== 0 || camera.pitch !== 0) ? ` ${c.dim(`(angle yaw ${camera.yaw}\xB0 pitch ${camera.pitch}\xB0)`)}` : "";
164563
164619
  console.log(`${c.accent("\u25C6")} Capturing ${label2} from ${c.accent(project.name)}${angleLabel}`);
164564
164620
  try {
164565
- const snapshotDir = args.output ? resolve55(String(args.output)) : join84(project.dir, "snapshots");
164621
+ const snapshotDir = args.output ? resolve55(String(args.output)) : join85(project.dir, "snapshots");
164566
164622
  const paths = await captureSnapshots(project.dir, {
164567
164623
  frames,
164568
164624
  timeout,
@@ -164589,7 +164645,7 @@ ${c.success("\u25C7")} ${paths.length} snapshots saved to ${args.output ? snaps
164589
164645
  const { createSnapshotContactSheet: createSnapshotContactSheet2 } = await Promise.resolve().then(() => (init_contactSheet(), contactSheet_exports));
164590
164646
  const sheets = await createSnapshotContactSheet2(
164591
164647
  snapshotDir,
164592
- join84(snapshotDir, "contact-sheet.jpg")
164648
+ join85(snapshotDir, "contact-sheet.jpg")
164593
164649
  );
164594
164650
  if (sheets.length > 0) {
164595
164651
  const label3 = sheets.length === 1 ? "contact-sheet.jpg" : `contact-sheet-1..${sheets.length}.jpg`;
@@ -164625,7 +164681,7 @@ ${c.success("\u25C7")} ${paths.length} snapshots saved to ${args.output ? snaps
164625
164681
  const results = await Promise.allSettled(
164626
164682
  paths.map(async (p2) => {
164627
164683
  const filename = basename19(p2);
164628
- const filePath = join84(snapshotDir, filename);
164684
+ const filePath = join85(snapshotDir, filename);
164629
164685
  if (!existsSync84(filePath)) return { filename, desc: "file not found" };
164630
164686
  const raw = readFileSync55(filePath);
164631
164687
  let imageData;
@@ -164663,7 +164719,7 @@ ${c.success("\u25C7")} ${paths.length} snapshots saved to ${args.output ? snaps
164663
164719
  descriptions.push(`## (error)`, `Gemini call failed: ${errMsg.slice(0, 120)}`, ``);
164664
164720
  }
164665
164721
  }
164666
- const descPath = join84(snapshotDir, "descriptions.md");
164722
+ const descPath = join85(snapshotDir, "descriptions.md");
164667
164723
  writeFileSync30(descPath, descriptions.join("\n"));
164668
164724
  console.log(` ${c.dim("descriptions.md")} (Gemini frame analysis)`);
164669
164725
  }
@@ -164685,18 +164741,18 @@ ${c.error("\u2717")} Snapshot failed: ${msg}`);
164685
164741
 
164686
164742
  // src/capture/assetDownloader.ts
164687
164743
  import { writeFileSync as writeFileSync31, mkdirSync as mkdirSync40 } from "fs";
164688
- import { join as join85, extname as extname15 } from "path";
164744
+ import { join as join86, extname as extname15 } from "path";
164689
164745
  import { createHash as createHash12 } from "crypto";
164690
164746
  function svgContentHashSlug(svgSource, isLogo) {
164691
164747
  const hash2 = createHash12("sha1").update(svgSource).digest("hex").slice(0, 8);
164692
164748
  return isLogo ? `logo-${hash2}` : `svg-${hash2}`;
164693
164749
  }
164694
164750
  async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks) {
164695
- const assetsDir = join85(outputDir, "assets");
164751
+ const assetsDir = join86(outputDir, "assets");
164696
164752
  mkdirSync40(assetsDir, { recursive: true });
164697
164753
  const assets = [];
164698
164754
  const downloadedUrls = /* @__PURE__ */ new Set();
164699
- mkdirSync40(join85(outputDir, "assets", "svgs"), { recursive: true });
164755
+ mkdirSync40(join86(outputDir, "assets", "svgs"), { recursive: true });
164700
164756
  const usedSvgNames = /* @__PURE__ */ new Set();
164701
164757
  for (let i2 = 0; i2 < tokens.svgs.length && i2 < 30; i2++) {
164702
164758
  const svg = tokens.svgs[i2];
@@ -164712,7 +164768,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
164712
164768
  const name = `${finalSlug}.svg`;
164713
164769
  const localPath = `assets/svgs/${name}`;
164714
164770
  try {
164715
- writeFileSync31(join85(outputDir, localPath), svg.outerHTML, "utf-8");
164771
+ writeFileSync31(join86(outputDir, localPath), svg.outerHTML, "utf-8");
164716
164772
  assets.push({ url: "", localPath, type: "svg" });
164717
164773
  } catch {
164718
164774
  }
@@ -164725,7 +164781,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
164725
164781
  const localPath = `assets/${name}`;
164726
164782
  const buffer = await fetchBuffer(icon.href);
164727
164783
  if (buffer) {
164728
- writeFileSync31(join85(outputDir, localPath), buffer);
164784
+ writeFileSync31(join86(outputDir, localPath), buffer);
164729
164785
  assets.push({ url: icon.href, localPath, type: "favicon" });
164730
164786
  break;
164731
164787
  }
@@ -164790,7 +164846,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
164790
164846
  const name = `${slug}${ext}`;
164791
164847
  usedNames.add(slug);
164792
164848
  const localPath = `assets/${name}`;
164793
- writeFileSync31(join85(outputDir, localPath), buffer);
164849
+ writeFileSync31(join86(outputDir, localPath), buffer);
164794
164850
  assets.push({ url, localPath, type: "image" });
164795
164851
  imgIdx++;
164796
164852
  } catch {
@@ -164803,7 +164859,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
164803
164859
  const localPath = `assets/og-image${ext}`;
164804
164860
  const buffer = await fetchBuffer(tokens.ogImage);
164805
164861
  if (buffer && buffer.length > 5e3) {
164806
- writeFileSync31(join85(outputDir, localPath), buffer);
164862
+ writeFileSync31(join86(outputDir, localPath), buffer);
164807
164863
  assets.push({ url: tokens.ogImage, localPath, type: "image" });
164808
164864
  }
164809
164865
  } catch {
@@ -164826,7 +164882,7 @@ function normalizeUrl(u) {
164826
164882
  }
164827
164883
  }
164828
164884
  async function downloadAndRewriteFonts(css, outputDir) {
164829
- const assetsDir = join85(outputDir, "assets", "fonts");
164885
+ const assetsDir = join86(outputDir, "assets", "fonts");
164830
164886
  mkdirSync40(assetsDir, { recursive: true });
164831
164887
  const fontUrlRegex = /url\(['"]?(https?:\/\/[^'")\s]+\.(?:woff2?|ttf|otf)[^'")\s]*?)['"]?\)/g;
164832
164888
  const fontUrls = /* @__PURE__ */ new Set();
@@ -164862,7 +164918,7 @@ async function downloadAndRewriteFonts(css, outputDir) {
164862
164918
  try {
164863
164919
  const urlObj = new URL(fontUrl);
164864
164920
  const filename = urlObj.pathname.split("/").pop() || `font-${count}.woff2`;
164865
- const localPath = join85(assetsDir, filename);
164921
+ const localPath = join86(assetsDir, filename);
164866
164922
  const relativePath = `assets/fonts/${filename}`;
164867
164923
  const buffer = await fetchBuffer(fontUrl);
164868
164924
  if (buffer) {
@@ -165021,7 +165077,7 @@ __export(video_exports, {
165021
165077
  safeFilename: () => safeFilename
165022
165078
  });
165023
165079
  import { createWriteStream as createWriteStream4, existsSync as existsSync85, mkdirSync as mkdirSync41, readFileSync as readFileSync56, unlinkSync as unlinkSync7 } from "fs";
165024
- import { resolve as resolve56, join as join86, basename as basename20 } from "path";
165080
+ import { resolve as resolve56, join as join87, basename as basename20 } from "path";
165025
165081
  async function streamToFile(url, destPath) {
165026
165082
  const r2 = await safeFetch(url, {
165027
165083
  signal: AbortSignal.timeout(12e4),
@@ -165140,8 +165196,8 @@ function pickManifestEntry(manifest, args) {
165140
165196
  }
165141
165197
  async function runVideoMode(args) {
165142
165198
  const projectDir = resolve56(args.project);
165143
- const directPath = join86(projectDir, "extracted", "video-manifest.json");
165144
- const w2hPath = join86(projectDir, "capture", "extracted", "video-manifest.json");
165199
+ const directPath = join87(projectDir, "extracted", "video-manifest.json");
165200
+ const w2hPath = join87(projectDir, "capture", "extracted", "video-manifest.json");
165145
165201
  const manifestPath2 = existsSync85(directPath) ? directPath : w2hPath;
165146
165202
  const isW2hLayout = manifestPath2 === w2hPath;
165147
165203
  if (!existsSync85(manifestPath2)) {
@@ -165195,10 +165251,10 @@ async function runVideoMode(args) {
165195
165251
  process.exitCode = 1;
165196
165252
  return;
165197
165253
  }
165198
- const outDir = isW2hLayout ? join86(projectDir, "capture", "assets", "videos") : join86(projectDir, "assets", "videos");
165254
+ const outDir = isW2hLayout ? join87(projectDir, "capture", "assets", "videos") : join87(projectDir, "assets", "videos");
165199
165255
  mkdirSync41(outDir, { recursive: true });
165200
165256
  const fname = safeFilename(entry.filename || basename20(entry.url));
165201
- const outPath = join86(outDir, fname);
165257
+ const outPath = join87(outDir, fname);
165202
165258
  const relPath = isW2hLayout ? `capture/assets/videos/${fname}` : `assets/videos/${fname}`;
165203
165259
  console.log(
165204
165260
  `${c.accent("\u25B8")} downloading [${entry.index}] ${entry.filename} (${entry.sourceWidth || entry.width}\xD7${entry.sourceHeight || entry.height})`
@@ -166442,7 +166498,7 @@ var init_designStyleExtractor = __esm({
166442
166498
 
166443
166499
  // src/capture/fontMetadataExtractor.ts
166444
166500
  import { readdirSync as readdirSync29, readFileSync as readFileSync57, writeFileSync as writeFileSync33, existsSync as existsSync86 } from "fs";
166445
- import { join as join87 } from "path";
166501
+ import { join as join88 } from "path";
166446
166502
  import * as fontkit from "fontkit";
166447
166503
  function isFontCollection(value) {
166448
166504
  return value.type === "TTC" || value.type === "DFont";
@@ -166453,7 +166509,7 @@ function extractFontMetadata(fontsDir, outputPath) {
166453
166509
  if (existsSync86(fontsDir)) {
166454
166510
  const fontFiles = readdirSync29(fontsDir).filter((f3) => /\.(woff2?|ttf|otf)$/i.test(f3));
166455
166511
  for (const filename of fontFiles) {
166456
- const fullPath = join87(fontsDir, filename);
166512
+ const fullPath = join88(fontsDir, filename);
166457
166513
  const meta = readSingleFont(fullPath, filename);
166458
166514
  if (meta.identified) {
166459
166515
  files.push(meta);
@@ -166765,7 +166821,7 @@ var init_animationCataloger = __esm({
166765
166821
 
166766
166822
  // src/capture/mediaCapture.ts
166767
166823
  import { mkdirSync as mkdirSync43, writeFileSync as writeFileSync34, readdirSync as readdirSync30, readFileSync as readFileSync58, statSync as statSync27 } from "fs";
166768
- import { join as join88, extname as extname16 } from "path";
166824
+ import { join as join89, extname as extname16 } from "path";
166769
166825
  async function saveLottieAnimations(discoveredLotties, lottieDir) {
166770
166826
  let savedCount = 0;
166771
166827
  const savedHashes = /* @__PURE__ */ new Set();
@@ -166797,7 +166853,7 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
166797
166853
  const hash2 = buf.toString("base64").slice(0, 100);
166798
166854
  if (savedHashes.has(hash2)) continue;
166799
166855
  savedHashes.add(hash2);
166800
- writeFileSync34(join88(lottieDir, `animation-${savedCount}.lottie`), buf);
166856
+ writeFileSync34(join89(lottieDir, `animation-${savedCount}.lottie`), buf);
166801
166857
  savedCount++;
166802
166858
  continue;
166803
166859
  }
@@ -166815,7 +166871,7 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
166815
166871
  } catch {
166816
166872
  continue;
166817
166873
  }
166818
- writeFileSync34(join88(lottieDir, `animation-${savedCount}.json`), jsonData, "utf-8");
166874
+ writeFileSync34(join89(lottieDir, `animation-${savedCount}.json`), jsonData, "utf-8");
166819
166875
  savedCount++;
166820
166876
  }
166821
166877
  } catch {
@@ -166825,22 +166881,22 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
166825
166881
  }
166826
166882
  async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
166827
166883
  const manifest = [];
166828
- const previewDir = join88(lottieDir, "previews");
166884
+ const previewDir = join89(lottieDir, "previews");
166829
166885
  mkdirSync43(previewDir, { recursive: true });
166830
166886
  for (const file of readdirSync30(lottieDir)) {
166831
166887
  if (!file.endsWith(".json")) continue;
166832
166888
  try {
166833
- const raw = JSON.parse(readFileSync58(join88(lottieDir, file), "utf-8"));
166889
+ const raw = JSON.parse(readFileSync58(join89(lottieDir, file), "utf-8"));
166834
166890
  const fr = raw.fr || 30;
166835
166891
  const dur = ((raw.op || 0) - (raw.ip || 0)) / fr;
166836
166892
  const previewName = file.replace(".json", "-preview.png");
166837
- const fileSize = statSync27(join88(lottieDir, file)).size;
166893
+ const fileSize = statSync27(join89(lottieDir, file)).size;
166838
166894
  if (fileSize > 2e6) continue;
166839
166895
  let previewPage;
166840
166896
  try {
166841
166897
  previewPage = await chromeBrowser.newPage();
166842
166898
  await previewPage.setViewport({ width: 400, height: 400 });
166843
- const animData = JSON.parse(readFileSync58(join88(lottieDir, file), "utf-8"));
166899
+ const animData = JSON.parse(readFileSync58(join89(lottieDir, file), "utf-8"));
166844
166900
  const midFrame = Math.floor(((raw.op || 0) - (raw.ip || 0)) * 0.3);
166845
166901
  await previewPage.setContent(
166846
166902
  `<!DOCTYPE html>
@@ -166870,7 +166926,7 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
166870
166926
  await previewPage.waitForFunction(() => window.__READY === true, { timeout: 5e3 }).catch(() => {
166871
166927
  });
166872
166928
  await previewPage.screenshot({
166873
- path: join88(previewDir, previewName),
166929
+ path: join89(previewDir, previewName),
166874
166930
  type: "png",
166875
166931
  omitBackground: true
166876
166932
  });
@@ -166894,7 +166950,7 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
166894
166950
  }
166895
166951
  if (manifest.length > 0) {
166896
166952
  writeFileSync34(
166897
- join88(outputDir, "extracted", "lottie-manifest.json"),
166953
+ join89(outputDir, "extracted", "lottie-manifest.json"),
166898
166954
  JSON.stringify(manifest, null, 2),
166899
166955
  "utf-8"
166900
166956
  );
@@ -166929,7 +166985,7 @@ async function downloadVideoBody(srcUrl, filename, videosDir) {
166929
166985
  }
166930
166986
  if (total < 1024) return null;
166931
166987
  const safe = /\.[a-z0-9]+$/i.test(filename) ? filename.replace(/[^\w.-]/g, "_") : `video${ext}`;
166932
- writeFileSync34(join88(videosDir, safe), Buffer.concat(chunks));
166988
+ writeFileSync34(join89(videosDir, safe), Buffer.concat(chunks));
166933
166989
  return `assets/videos/${safe}`;
166934
166990
  } catch {
166935
166991
  return null;
@@ -166991,9 +167047,9 @@ async function captureVideoManifest(page, outputDir, progress, opts) {
166991
167047
  }
166992
167048
  const merged = [...byKey.values()];
166993
167049
  if (merged.length === 0) return;
166994
- const videoManifestDir = join88(outputDir, "assets", "videos");
167050
+ const videoManifestDir = join89(outputDir, "assets", "videos");
166995
167051
  mkdirSync43(videoManifestDir, { recursive: true });
166996
- const previewDir = join88(videoManifestDir, "previews");
167052
+ const previewDir = join89(videoManifestDir, "previews");
166997
167053
  mkdirSync43(previewDir, { recursive: true });
166998
167054
  const videoManifest = [];
166999
167055
  const dlStart = Date.now();
@@ -167016,7 +167072,7 @@ async function captureVideoManifest(page, outputDir, progress, opts) {
167016
167072
  if (rect && rect.width >= 10) {
167017
167073
  await new Promise((r2) => setTimeout(r2, 200));
167018
167074
  await page.screenshot({
167019
- path: join88(previewDir, previewName),
167075
+ path: join89(previewDir, previewName),
167020
167076
  clip: {
167021
167077
  x: Math.max(0, rect.x),
167022
167078
  y: Math.max(0, rect.y),
@@ -167048,7 +167104,7 @@ async function captureVideoManifest(page, outputDir, progress, opts) {
167048
167104
  }
167049
167105
  if (videoManifest.length > 0) {
167050
167106
  writeFileSync34(
167051
- join88(outputDir, "extracted", "video-manifest.json"),
167107
+ join89(outputDir, "extracted", "video-manifest.json"),
167052
167108
  JSON.stringify(videoManifest, null, 2),
167053
167109
  "utf-8"
167054
167110
  );
@@ -167117,7 +167173,7 @@ var init_mediaCapture = __esm({
167117
167173
 
167118
167174
  // src/capture/contentExtractor.ts
167119
167175
  import { existsSync as existsSync87, readdirSync as readdirSync31, statSync as statSync28, readFileSync as readFileSync59 } from "fs";
167120
- import { basename as basename21, join as join89 } from "path";
167176
+ import { basename as basename21, join as join90 } from "path";
167121
167177
  async function detectLibraries(page, capturedShaders) {
167122
167178
  let detectedLibraries = [];
167123
167179
  try {
@@ -167284,7 +167340,7 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
167284
167340
  return response.text?.trim() || "";
167285
167341
  };
167286
167342
  }
167287
- const imageFiles = readdirSync31(join89(outputDir, "assets")).filter(
167343
+ const imageFiles = readdirSync31(join90(outputDir, "assets")).filter(
167288
167344
  (f3) => /\.(png|jpg|jpeg|webp|gif)$/i.test(f3)
167289
167345
  );
167290
167346
  const BATCH_SIZE = 20;
@@ -167292,7 +167348,7 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
167292
167348
  const batch = imageFiles.slice(i2, i2 + BATCH_SIZE);
167293
167349
  const results = await Promise.allSettled(
167294
167350
  batch.map(async (file) => {
167295
- const filePath = join89(outputDir, "assets", file);
167351
+ const filePath = join90(outputDir, "assets", file);
167296
167352
  const stat3 = statSync28(filePath);
167297
167353
  if (stat3.size > 4e6) return { file, caption: "" };
167298
167354
  const buffer = readFileSync59(filePath);
@@ -167326,11 +167382,11 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
167326
167382
  `${Object.keys(geminiCaptions).length} images captioned with ${providerName}`
167327
167383
  );
167328
167384
  const svgFiles = [];
167329
- const assetsDir = join89(outputDir, "assets");
167385
+ const assetsDir = join90(outputDir, "assets");
167330
167386
  for (const f3 of readdirSync31(assetsDir)) {
167331
167387
  if (/\.svg$/i.test(f3)) svgFiles.push({ file: f3, relPath: f3 });
167332
167388
  }
167333
- const svgsSubdir = join89(assetsDir, "svgs");
167389
+ const svgsSubdir = join90(assetsDir, "svgs");
167334
167390
  if (existsSync87(svgsSubdir)) {
167335
167391
  for (const f3 of readdirSync31(svgsSubdir)) {
167336
167392
  if (/\.svg$/i.test(f3)) svgFiles.push({ file: f3, relPath: `svgs/${f3}` });
@@ -167354,7 +167410,7 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
167354
167410
  const batch = svgFiles.slice(i2, i2 + SVG_BATCH);
167355
167411
  const results = await Promise.allSettled(
167356
167412
  batch.map(async ({ relPath }) => {
167357
- const filePath = join89(assetsDir, relPath);
167413
+ const filePath = join90(assetsDir, relPath);
167358
167414
  let pngBase64;
167359
167415
  try {
167360
167416
  const svgSource = readFileSync59(filePath, "utf-8");
@@ -167412,11 +167468,11 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
167412
167468
  const uncaptionedLines = [];
167413
167469
  const svgLines = [];
167414
167470
  const fontLines = [];
167415
- const assetsPath = join89(outputDir, "assets");
167471
+ const assetsPath = join90(outputDir, "assets");
167416
167472
  try {
167417
167473
  for (const file of readdirSync31(assetsPath)) {
167418
167474
  if (file === "svgs" || file === "fonts" || file === "lottie" || file === "videos") continue;
167419
- const filePath = join89(assetsPath, file);
167475
+ const filePath = join90(assetsPath, file);
167420
167476
  const stat3 = statSync28(filePath);
167421
167477
  if (!stat3.isFile()) continue;
167422
167478
  const sizeKb = Math.round(stat3.size / 1024);
@@ -167445,7 +167501,7 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
167445
167501
  } catch {
167446
167502
  }
167447
167503
  try {
167448
- const svgsPath = join89(assetsPath, "svgs");
167504
+ const svgsPath = join90(assetsPath, "svgs");
167449
167505
  for (const file of readdirSync31(svgsPath)) {
167450
167506
  if (!file.endsWith(".svg")) continue;
167451
167507
  const svgMatch = tokens.svgs.find(
@@ -167464,7 +167520,7 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
167464
167520
  } catch {
167465
167521
  }
167466
167522
  try {
167467
- const fontsPath = join89(assetsPath, "fonts");
167523
+ const fontsPath = join90(assetsPath, "fonts");
167468
167524
  for (const file of readdirSync31(fontsPath)) {
167469
167525
  fontLines.push(`fonts/${file} \u2014 font file`);
167470
167526
  }
@@ -167473,7 +167529,7 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
167473
167529
  const videoLines = [];
167474
167530
  try {
167475
167531
  const manifest = JSON.parse(
167476
- readFileSync59(join89(outputDir, "extracted", "video-manifest.json"), "utf-8")
167532
+ readFileSync59(join90(outputDir, "extracted", "video-manifest.json"), "utf-8")
167477
167533
  );
167478
167534
  for (const v2 of manifest) {
167479
167535
  if (!v2.localPath) continue;
@@ -167501,7 +167557,7 @@ __export(agentPromptGenerator_exports, {
167501
167557
  generateAgentPrompt: () => generateAgentPrompt
167502
167558
  });
167503
167559
  import { writeFileSync as writeFileSync35, readdirSync as readdirSync33, existsSync as existsSync88 } from "fs";
167504
- import { join as join90 } from "path";
167560
+ import { join as join91 } from "path";
167505
167561
  function inferColorRole(hex) {
167506
167562
  const r2 = parseInt(hex.slice(1, 3), 16) / 255;
167507
167563
  const g = parseInt(hex.slice(3, 5), 16) / 255;
@@ -167520,9 +167576,9 @@ function inferColorRole(hex) {
167520
167576
  }
167521
167577
  function generateAgentPrompt(outputDir, url, tokens, _animations, hasScreenshot, hasLottie, hasShaders, _catalogedAssets, _detectedLibraries) {
167522
167578
  const prompt = buildPrompt(outputDir, url, tokens, hasScreenshot, hasLottie, hasShaders);
167523
- writeFileSync35(join90(outputDir, "AGENTS.md"), prompt, "utf-8");
167524
- writeFileSync35(join90(outputDir, "CLAUDE.md"), prompt, "utf-8");
167525
- writeFileSync35(join90(outputDir, ".cursorrules"), prompt, "utf-8");
167579
+ writeFileSync35(join91(outputDir, "AGENTS.md"), prompt, "utf-8");
167580
+ writeFileSync35(join91(outputDir, "CLAUDE.md"), prompt, "utf-8");
167581
+ writeFileSync35(join91(outputDir, ".cursorrules"), prompt, "utf-8");
167526
167582
  }
167527
167583
  function buildPrompt(outputDir, url, tokens, hasScreenshot, hasLottie, hasShaders) {
167528
167584
  const title = tokens.title || new URL(url).hostname.replace(/^www\./, "");
@@ -167531,7 +167587,7 @@ function buildPrompt(outputDir, url, tokens, hasScreenshot, hasLottie, hasShader
167531
167587
  (f3) => f3.family + (f3.variable && f3.weightRange ? ` (${f3.weightRange[0]}-${f3.weightRange[1]} variable)` : f3.weights.length > 0 ? ` (${f3.weights.join(",")})` : "")
167532
167588
  ).join(", ") || "none detected";
167533
167589
  function contactSheetRows(dir, baseFile, label2) {
167534
- const fullDir = join90(outputDir, dir);
167590
+ const fullDir = join91(outputDir, dir);
167535
167591
  if (!existsSync88(fullDir)) return [];
167536
167592
  const baseName = baseFile.replace(/\.jpg$/, "");
167537
167593
  const escapedBase = baseName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -167564,7 +167620,7 @@ function buildPrompt(outputDir, url, tokens, hasScreenshot, hasLottie, hasShader
167564
167620
  tableRows.push(
167565
167621
  `| \`extracted/tokens.json\` | Design tokens: ${tokens.colors.length} colors, ${tokens.fonts.length} fonts, ${tokens.headings?.length ?? 0} headings, ${tokens.ctas?.length ?? 0} CTAs |`
167566
167622
  );
167567
- if (existsSync88(join90(outputDir, "extracted", "design-styles.json"))) {
167623
+ if (existsSync88(join91(outputDir, "extracted", "design-styles.json"))) {
167568
167624
  tableRows.push(
167569
167625
  "| `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. |"
167570
167626
  );
@@ -167636,7 +167692,7 @@ var init_agentPromptGenerator = __esm({
167636
167692
 
167637
167693
  // src/capture/scaffolding.ts
167638
167694
  import { existsSync as existsSync89, writeFileSync as writeFileSync36, readFileSync as readFileSync60 } from "fs";
167639
- import { join as join91, resolve as resolve57 } from "path";
167695
+ import { join as join93, resolve as resolve57 } from "path";
167640
167696
  function loadEnvFile(startDir) {
167641
167697
  try {
167642
167698
  let dir = resolve57(startDir);
@@ -167662,7 +167718,7 @@ function loadEnvFile(startDir) {
167662
167718
  }
167663
167719
  }
167664
167720
  async function generateProjectScaffold(outputDir, url, tokens, animationCatalog, hasScreenshots, hasLotties, hasShaders, catalogedAssets, progress, warnings, detectedLibraries) {
167665
- const metaPath = join91(outputDir, "meta.json");
167721
+ const metaPath = join93(outputDir, "meta.json");
167666
167722
  if (!existsSync89(metaPath)) {
167667
167723
  const hostname = new URL(url).hostname.replace(/^www\./, "");
167668
167724
  writeFileSync36(
@@ -167701,9 +167757,9 @@ __export(screenshotCapture_exports, {
167701
167757
  captureScrollScreenshots: () => captureScrollScreenshots
167702
167758
  });
167703
167759
  import { writeFileSync as writeFileSync37, mkdirSync as mkdirSync44 } from "fs";
167704
- import { join as join93 } from "path";
167760
+ import { join as join94 } from "path";
167705
167761
  async function captureScrollScreenshots(page, outputDir) {
167706
- const screenshotsDir = join93(outputDir, "screenshots");
167762
+ const screenshotsDir = join94(outputDir, "screenshots");
167707
167763
  mkdirSync44(screenshotsDir, { recursive: true });
167708
167764
  const MAX_SCREENSHOTS = 20;
167709
167765
  const filePaths = [];
@@ -167795,7 +167851,7 @@ async function captureScrollScreenshots(page, outputDir) {
167795
167851
  finalPositions[i2] / Math.max(1, scrollHeight - viewportHeight) * 100
167796
167852
  );
167797
167853
  const filename = `scroll-${String(Math.min(pct, 100)).padStart(3, "0")}.png`;
167798
- const filePath = join93(screenshotsDir, filename);
167854
+ const filePath = join94(screenshotsDir, filename);
167799
167855
  const buffer = await page.screenshot({ type: "png" });
167800
167856
  writeFileSync37(filePath, buffer);
167801
167857
  filePaths.push(`screenshots/${filename}`);
@@ -168145,7 +168201,7 @@ __export(capture_exports, {
168145
168201
  captureWebsite: () => captureWebsite
168146
168202
  });
168147
168203
  import { mkdirSync as mkdirSync45, writeFileSync as writeFileSync38, existsSync as existsSync90 } from "fs";
168148
- import { join as join94 } from "path";
168204
+ import { join as join95 } from "path";
168149
168205
  async function captureWebsite(opts, onProgress) {
168150
168206
  const {
168151
168207
  url,
@@ -168162,9 +168218,9 @@ async function captureWebsite(opts, onProgress) {
168162
168218
  onProgress?.(stage, detail);
168163
168219
  };
168164
168220
  loadEnvFile(outputDir);
168165
- mkdirSync45(join94(outputDir, "extracted"), { recursive: true });
168166
- mkdirSync45(join94(outputDir, "screenshots"), { recursive: true });
168167
- mkdirSync45(join94(outputDir, "assets"), { recursive: true });
168221
+ mkdirSync45(join95(outputDir, "extracted"), { recursive: true });
168222
+ mkdirSync45(join95(outputDir, "screenshots"), { recursive: true });
168223
+ mkdirSync45(join95(outputDir, "assets"), { recursive: true });
168168
168224
  progress("browser", "Launching headless Chrome...");
168169
168225
  const { ensureBrowser: ensureBrowser2 } = await Promise.resolve().then(() => (init_manager2(), manager_exports2));
168170
168226
  const browser = await ensureBrowser2();
@@ -168324,7 +168380,7 @@ async function captureWebsite(opts, onProgress) {
168324
168380
  } catch {
168325
168381
  }
168326
168382
  if (discoveredLotties.length > 0) {
168327
- const lottieDir = join94(outputDir, "assets", "lottie");
168383
+ const lottieDir = join95(outputDir, "assets", "lottie");
168328
168384
  mkdirSync45(lottieDir, { recursive: true });
168329
168385
  const savedCount = await saveLottieAnimations(discoveredLotties, lottieDir);
168330
168386
  if (savedCount > 0) {
@@ -168344,7 +168400,7 @@ async function captureWebsite(opts, onProgress) {
168344
168400
  });
168345
168401
  capturedShaders = unique;
168346
168402
  writeFileSync38(
168347
- join94(outputDir, "extracted", "shaders.json"),
168403
+ join95(outputDir, "extracted", "shaders.json"),
168348
168404
  JSON.stringify(unique, null, 2),
168349
168405
  "utf-8"
168350
168406
  );
@@ -168359,7 +168415,7 @@ async function captureWebsite(opts, onProgress) {
168359
168415
  svgs: tokens.svgs.map(({ outerHTML: _, ...rest }) => rest)
168360
168416
  };
168361
168417
  writeFileSync38(
168362
- join94(outputDir, "extracted", "tokens.json"),
168418
+ join95(outputDir, "extracted", "tokens.json"),
168363
168419
  JSON.stringify(tokensForDisk, null, 2),
168364
168420
  "utf-8"
168365
168421
  );
@@ -168367,7 +168423,7 @@ async function captureWebsite(opts, onProgress) {
168367
168423
  try {
168368
168424
  const designStyles = await extractDesignStyles(page1);
168369
168425
  writeFileSync38(
168370
- join94(outputDir, "extracted", "design-styles.json"),
168426
+ join95(outputDir, "extracted", "design-styles.json"),
168371
168427
  JSON.stringify(designStyles, null, 2),
168372
168428
  "utf-8"
168373
168429
  );
@@ -168446,8 +168502,8 @@ ${err.stack}` : normalizeErrorMessage(err);
168446
168502
  extracted.headHtml = await downloadAndRewriteFonts(extracted.headHtml, outputDir);
168447
168503
  try {
168448
168504
  const fontsManifest = extractFontMetadata(
168449
- join94(outputDir, "assets", "fonts"),
168450
- join94(outputDir, "extracted", "fonts-manifest.json")
168505
+ join95(outputDir, "assets", "fonts"),
168506
+ join95(outputDir, "extracted", "fonts-manifest.json")
168451
168507
  );
168452
168508
  if (fontsManifest.families.length > 0) {
168453
168509
  const summary = fontsManifest.families.map((f3) => `${f3.family}${f3.variable ? " (variable)" : ""} \xD7 ${f3.fileCount}`).join(", ");
@@ -168474,7 +168530,7 @@ ${err.stack}` : normalizeErrorMessage(err);
168474
168530
  representativeAnimations: representativeAnims
168475
168531
  };
168476
168532
  writeFileSync38(
168477
- join94(outputDir, "extracted", "animations.json"),
168533
+ join95(outputDir, "extracted", "animations.json"),
168478
168534
  JSON.stringify(leanCatalog, null, 2),
168479
168535
  "utf-8"
168480
168536
  );
@@ -168505,7 +168561,7 @@ ${err.stack}` : normalizeErrorMessage(err);
168505
168561
  svgs: tokens.svgs.map(({ outerHTML: _, ...rest }) => rest)
168506
168562
  };
168507
168563
  writeFileSync38(
168508
- join94(outputDir, "extracted", "tokens.json"),
168564
+ join95(outputDir, "extracted", "tokens.json"),
168509
168565
  JSON.stringify(tokensForDisk2, null, 2),
168510
168566
  "utf-8"
168511
168567
  );
@@ -168521,12 +168577,12 @@ ${extracted.bodyHtml}
168521
168577
  </body>
168522
168578
  </html>
168523
168579
  `;
168524
- writeFileSync38(join94(outputDir, "extracted", "page.html"), pageHtml, "utf-8");
168580
+ writeFileSync38(join95(outputDir, "extracted", "page.html"), pageHtml, "utf-8");
168525
168581
  } catch (err) {
168526
168582
  warnings.push(`page.html write failed: ${err}`);
168527
168583
  }
168528
168584
  if (visibleTextContent) {
168529
- writeFileSync38(join94(outputDir, "extracted", "visible-text.txt"), visibleTextContent, "utf-8");
168585
+ writeFileSync38(join95(outputDir, "extracted", "visible-text.txt"), visibleTextContent, "utf-8");
168530
168586
  }
168531
168587
  const geminiCaptions = await captionImagesWithGemini(outputDir, progress, warnings);
168532
168588
  progress("design", "Generating asset descriptions...");
@@ -168536,7 +168592,7 @@ ${extracted.bodyHtml}
168536
168592
  const hasGeminiKey = !!(process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY);
168537
168593
  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";
168538
168594
  writeFileSync38(
168539
- join94(outputDir, "extracted", "asset-descriptions.md"),
168595
+ join95(outputDir, "extracted", "asset-descriptions.md"),
168540
168596
  header + lines.map((l) => "- " + l).join("\n") + "\n",
168541
168597
  "utf-8"
168542
168598
  );
@@ -168551,19 +168607,19 @@ ${extracted.bodyHtml}
168551
168607
  try {
168552
168608
  const { createScrollContactSheet: createScrollContactSheet2, createAssetContactSheet: createAssetContactSheet2, createSvgContactSheet: createSvgContactSheet2 } = await Promise.resolve().then(() => (init_contactSheet(), contactSheet_exports));
168553
168609
  const scrollSheets = await createScrollContactSheet2(
168554
- join94(outputDir, "screenshots"),
168555
- join94(outputDir, "screenshots", "contact-sheet.jpg")
168610
+ join95(outputDir, "screenshots"),
168611
+ join95(outputDir, "screenshots", "contact-sheet.jpg")
168556
168612
  );
168557
168613
  if (scrollSheets.length > 0)
168558
168614
  progress(
168559
168615
  "design",
168560
168616
  `Screenshot contact sheet generated (${scrollSheets.length} page${scrollSheets.length > 1 ? "s" : ""})`
168561
168617
  );
168562
- const assetsImgDir = join94(outputDir, "assets");
168618
+ const assetsImgDir = join95(outputDir, "assets");
168563
168619
  if (existsSync90(assetsImgDir)) {
168564
168620
  const assetSheets = await createAssetContactSheet2(
168565
168621
  assetsImgDir,
168566
- join94(outputDir, "assets", "contact-sheet.jpg")
168622
+ join95(outputDir, "assets", "contact-sheet.jpg")
168567
168623
  );
168568
168624
  if (assetSheets.length > 0)
168569
168625
  progress(
@@ -168571,9 +168627,9 @@ ${extracted.bodyHtml}
168571
168627
  `Asset contact sheet generated (${assetSheets.length} page${assetSheets.length > 1 ? "s" : ""})`
168572
168628
  );
168573
168629
  }
168574
- const svgsDir = join94(outputDir, "assets", "svgs");
168575
- const assetsRootDir = join94(outputDir, "assets");
168576
- const svgOutputPath = existsSync90(svgsDir) ? join94(outputDir, "assets", "svgs", "contact-sheet.jpg") : join94(outputDir, "assets", "contact-sheet-svgs.jpg");
168630
+ const svgsDir = join95(outputDir, "assets", "svgs");
168631
+ const assetsRootDir = join95(outputDir, "assets");
168632
+ const svgOutputPath = existsSync90(svgsDir) ? join95(outputDir, "assets", "svgs", "contact-sheet.jpg") : join95(outputDir, "assets", "contact-sheet-svgs.jpg");
168577
168633
  const svgSheets = await createSvgContactSheet2(svgsDir, svgOutputPath, assetsRootDir);
168578
168634
  if (svgSheets.length > 0)
168579
168635
  progress(
@@ -168589,7 +168645,7 @@ ${extracted.bodyHtml}
168589
168645
  animationCatalog,
168590
168646
  screenshots.length > 0,
168591
168647
  discoveredLotties.length > 0,
168592
- existsSync90(join94(outputDir, "extracted", "shaders.json")),
168648
+ existsSync90(join95(outputDir, "extracted", "shaders.json")),
168593
168649
  catalogedAssets,
168594
168650
  progress,
168595
168651
  warnings,
@@ -168875,9 +168931,9 @@ __export(state_exports, {
168875
168931
  writeStackOutputs: () => writeStackOutputs
168876
168932
  });
168877
168933
  import { existsSync as existsSync91, mkdirSync as mkdirSync46, readdirSync as readdirSync34, readFileSync as readFileSync61, rmSync as rmSync20, writeFileSync as writeFileSync39 } from "fs";
168878
- import { dirname as dirname40, join as join95 } from "path";
168934
+ import { dirname as dirname40, join as join96 } from "path";
168879
168935
  function stateFilePath(stackName = DEFAULT_STACK_NAME, cwd = process.cwd()) {
168880
- return join95(cwd, STATE_DIR_NAME, `${STATE_FILE_PREFIX}${stackName}.json`);
168936
+ return join96(cwd, STATE_DIR_NAME, `${STATE_FILE_PREFIX}${stackName}.json`);
168881
168937
  }
168882
168938
  function writeStackOutputs(outputs, cwd = process.cwd()) {
168883
168939
  const path2 = stateFilePath(outputs.stackName, cwd);
@@ -168899,7 +168955,7 @@ function deleteStackOutputs(stackName = DEFAULT_STACK_NAME, cwd = process.cwd())
168899
168955
  if (existsSync91(path2)) rmSync20(path2);
168900
168956
  }
168901
168957
  function listStackNames(cwd = process.cwd()) {
168902
- const dir = join95(cwd, STATE_DIR_NAME);
168958
+ const dir = join96(cwd, STATE_DIR_NAME);
168903
168959
  if (!existsSync91(dir)) return [];
168904
168960
  return readdirSync34(dir).filter((f3) => f3.startsWith(STATE_FILE_PREFIX) && f3.endsWith(".json")).map((f3) => f3.slice(STATE_FILE_PREFIX.length, -".json".length));
168905
168961
  }
@@ -168931,7 +168987,7 @@ var init_state = __esm({
168931
168987
  // src/commands/lambda/sam.ts
168932
168988
  import { execFileSync as execFileSync13, spawnSync as spawnSync4 } from "child_process";
168933
168989
  import { existsSync as existsSync92 } from "fs";
168934
- import { join as join96 } from "path";
168990
+ import { join as join97 } from "path";
168935
168991
  function assertSamAvailable() {
168936
168992
  try {
168937
168993
  execFileSync13("sam", ["--version"], { stdio: "ignore" });
@@ -168951,7 +169007,7 @@ function assertAwsCliAvailable() {
168951
169007
  }
168952
169008
  }
168953
169009
  function locateSamTemplate(repoRoot2) {
168954
- const candidate = join96(repoRoot2, "examples", "aws-lambda", "template.yaml");
169010
+ const candidate = join97(repoRoot2, "examples", "aws-lambda", "template.yaml");
168955
169011
  if (!existsSync92(candidate)) {
168956
169012
  throw new Error(
168957
169013
  `[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.`
@@ -168985,7 +169041,7 @@ function samDeploy(opts) {
168985
169041
  if (opts.awsProfile) {
168986
169042
  args.push("--profile", opts.awsProfile);
168987
169043
  }
168988
- const samDir = join96(opts.repoRoot, "examples", "aws-lambda");
169044
+ const samDir = join97(opts.repoRoot, "examples", "aws-lambda");
168989
169045
  const result = spawnSync4("sam", args, { cwd: samDir, stdio: opts.stdio ?? "inherit" });
168990
169046
  if (result.status !== 0) {
168991
169047
  throw new Error(`[lambda] sam deploy exited with code ${result.status ?? "unknown"}`);
@@ -168997,7 +169053,7 @@ function samDelete(opts) {
168997
169053
  if (opts.awsProfile) {
168998
169054
  args.push("--profile", opts.awsProfile);
168999
169055
  }
169000
- const samDir = join96(opts.repoRoot, "examples", "aws-lambda");
169056
+ const samDir = join97(opts.repoRoot, "examples", "aws-lambda");
169001
169057
  const result = spawnSync4("sam", args, { cwd: samDir, stdio: opts.stdio ?? "inherit" });
169002
169058
  if (result.status !== 0) {
169003
169059
  throw new Error(`[lambda] sam delete exited with code ${result.status ?? "unknown"}`);
@@ -169081,7 +169137,7 @@ __export(deploy_exports, {
169081
169137
  });
169082
169138
  import { spawnSync as spawnSync5 } from "child_process";
169083
169139
  import { existsSync as existsSync94 } from "fs";
169084
- import { join as join97, resolve as resolve60 } from "path";
169140
+ import { join as join98, resolve as resolve60 } from "path";
169085
169141
  async function runDeploy(args = {}) {
169086
169142
  const resolved = {
169087
169143
  stackName: args.stackName ?? DEFAULT_STACK_NAME,
@@ -169098,7 +169154,7 @@ async function runDeploy(args = {}) {
169098
169154
  console.log(c.dim("\u2192 Building handler ZIP"));
169099
169155
  buildHandlerZip(root);
169100
169156
  } else {
169101
- const zip = join97(root, "packages", "aws-lambda", "dist", "handler.zip");
169157
+ const zip = join98(root, "packages", "aws-lambda", "dist", "handler.zip");
169102
169158
  if (!existsSync94(zip)) {
169103
169159
  throw new Error(
169104
169160
  `--skip-build set but ${zip} does not exist. Run \`bun run --cwd packages/aws-lambda build:zip\` first or drop --skip-build.`
@@ -169142,7 +169198,7 @@ async function runDeploy(args = {}) {
169142
169198
  function buildHandlerZip(root) {
169143
169199
  const result = spawnSync5(
169144
169200
  "bun",
169145
- ["run", "--cwd", join97(root, "packages", "aws-lambda"), "build:zip"],
169201
+ ["run", "--cwd", join98(root, "packages", "aws-lambda"), "build:zip"],
169146
169202
  { stdio: "inherit" }
169147
169203
  );
169148
169204
  if (result.status !== 0) {
@@ -169212,13 +169268,13 @@ var init_sites = __esm({
169212
169268
 
169213
169269
  // src/commands/lambda/_dimensions.ts
169214
169270
  import { readFileSync as readFileSync63 } from "fs";
169215
- import { join as join98 } from "path";
169271
+ import { join as join99 } from "path";
169216
169272
  function warnOnDimensionMismatch(args) {
169217
169273
  if (args.quiet) return;
169218
169274
  if (args.outputResolution) return;
169219
169275
  let html;
169220
169276
  try {
169221
- html = readFileSync63(join98(args.projectDir, "index.html"), "utf-8");
169277
+ html = readFileSync63(join99(args.projectDir, "index.html"), "utf-8");
169222
169278
  } catch {
169223
169279
  return;
169224
169280
  }
@@ -169247,7 +169303,7 @@ __export(render_exports2, {
169247
169303
  runRender: () => runRender
169248
169304
  });
169249
169305
  import { existsSync as existsSync95 } from "fs";
169250
- import { join as join99, resolve as resolvePath2 } from "path";
169306
+ import { join as join100, resolve as resolvePath2 } from "path";
169251
169307
  async function loadSDK2() {
169252
169308
  return import("@hyperframes/aws-lambda/sdk");
169253
169309
  }
@@ -169263,7 +169319,7 @@ async function runRender(args) {
169263
169319
  });
169264
169320
  const variables = resolveVariablesArg(args.variables, args.variablesFile);
169265
169321
  if (variables && Object.keys(variables).length > 0) {
169266
- const indexPath2 = join99(projectDir, "index.html");
169322
+ const indexPath2 = join100(projectDir, "index.html");
169267
169323
  if (existsSync95(indexPath2)) {
169268
169324
  const issues = validateVariablesAgainstProject(indexPath2, variables);
169269
169325
  reportVariableIssues(issues, { strict: args.strictVariables ?? false, quiet: args.json });
@@ -169389,7 +169445,7 @@ __export(render_batch_exports, {
169389
169445
  runWithConcurrencyLimit: () => runWithConcurrencyLimit
169390
169446
  });
169391
169447
  import { existsSync as existsSync96, readFileSync as readFileSync64 } from "fs";
169392
- import { join as join100, resolve as resolvePath3 } from "path";
169448
+ import { join as join101, resolve as resolvePath3 } from "path";
169393
169449
  async function loadSDK3() {
169394
169450
  return import("@hyperframes/aws-lambda/sdk");
169395
169451
  }
@@ -169413,7 +169469,7 @@ async function runRenderBatch(args) {
169413
169469
  outputResolution: args.outputResolution,
169414
169470
  quiet: args.json
169415
169471
  });
169416
- const schema = loadProjectVariableSchema(join100(projectDir, "index.html"));
169472
+ const schema = loadProjectVariableSchema(join101(projectDir, "index.html"));
169417
169473
  const strict = args.strictVariables ?? false;
169418
169474
  let hadStrictIssue = false;
169419
169475
  for (const { entry, lineNumber } of entries2) {
@@ -170436,12 +170492,12 @@ import { spawnSync as spawnSync6 } from "child_process";
170436
170492
  import { createRequire as createRequire4 } from "module";
170437
170493
  import { existsSync as existsSync97, mkdirSync as mkdirSync47, readFileSync as readFileSync66, writeFileSync as writeFileSync40 } from "fs";
170438
170494
  import { homedir as homedir14 } from "os";
170439
- import { dirname as dirname42, join as join101, resolve as resolve61 } from "path";
170495
+ import { dirname as dirname42, join as join103, resolve as resolve61 } from "path";
170440
170496
  function stateDir() {
170441
- return join101(homedir14(), ".hyperframes");
170497
+ return join103(homedir14(), ".hyperframes");
170442
170498
  }
170443
170499
  function statePath() {
170444
- return join101(stateDir(), "cloudrun-state.json");
170500
+ return join103(stateDir(), "cloudrun-state.json");
170445
170501
  }
170446
170502
  function writeState(state) {
170447
170503
  mkdirSync47(stateDir(), { recursive: true });
@@ -170475,7 +170531,7 @@ function stripUndefined2(o) {
170475
170531
  function terraformDir() {
170476
170532
  const require3 = createRequire4(import.meta.url);
170477
170533
  const pkgJson = require3.resolve("@hyperframes/gcp-cloud-run/package.json");
170478
- return join101(dirname42(pkgJson), "terraform");
170534
+ return join103(dirname42(pkgJson), "terraform");
170479
170535
  }
170480
170536
  function run(cmd, cmdArgs, opts = {}) {
170481
170537
  const res = spawnSync6(cmd, cmdArgs, { stdio: "inherit", cwd: opts.cwd });
@@ -170602,11 +170658,11 @@ function machineVars(args, project, region, image) {
170602
170658
  }
170603
170659
  function findRepoRoot(tfDir) {
170604
170660
  const candidate = resolve61(tfDir, "..", "..", "..");
170605
- if (existsSync97(join101(candidate, "packages", "gcp-cloud-run", "Dockerfile"))) return candidate;
170661
+ if (existsSync97(join103(candidate, "packages", "gcp-cloud-run", "Dockerfile"))) return candidate;
170606
170662
  return null;
170607
170663
  }
170608
170664
  function writeCloudBuildConfig(image) {
170609
- const cfgPath = join101(stateDir(), "cloudrun-cloudbuild.yaml");
170665
+ const cfgPath = join103(stateDir(), "cloudrun-cloudbuild.yaml");
170610
170666
  mkdirSync47(stateDir(), { recursive: true });
170611
170667
  writeFileSync40(
170612
170668
  cfgPath,
@@ -170892,7 +170948,7 @@ function resolveAndValidateVariables(args, projectDir) {
170892
170948
  args["variables-file"]
170893
170949
  );
170894
170950
  if (variables && Object.keys(variables).length > 0) {
170895
- const indexPath2 = join101(projectDir, "index.html");
170951
+ const indexPath2 = join103(projectDir, "index.html");
170896
170952
  if (existsSync97(indexPath2)) {
170897
170953
  const issues = validateVariablesAgainstProject(indexPath2, variables);
170898
170954
  reportVariableIssues(issues, {
@@ -171907,14 +171963,14 @@ var init_browser2 = __esm({
171907
171963
 
171908
171964
  // src/auth/paths.ts
171909
171965
  import { homedir as homedir15 } from "os";
171910
- import { join as join103 } from "path";
171966
+ import { join as join104 } from "path";
171911
171967
  function configDir() {
171912
171968
  const override = process.env["HEYGEN_CONFIG_DIR"];
171913
171969
  if (override && override.length > 0) return override;
171914
- return join103(homedir15(), ".heygen");
171970
+ return join104(homedir15(), ".heygen");
171915
171971
  }
171916
171972
  function credentialPath() {
171917
- return join103(configDir(), CREDENTIAL_FILENAME);
171973
+ return join104(configDir(), CREDENTIAL_FILENAME);
171918
171974
  }
171919
171975
  var CREDENTIAL_FILENAME;
171920
171976
  var init_paths2 = __esm({
@@ -174613,15 +174669,15 @@ var init_jsonl = __esm({
174613
174669
 
174614
174670
  // ../core/dist/figma/manifest.js
174615
174671
  import { appendFileSync as appendFileSync2, existsSync as existsSync100, mkdirSync as mkdirSync50, readFileSync as readFileSync69, writeFileSync as writeFileSync43 } from "fs";
174616
- import { join as join104 } from "path";
174672
+ import { join as join105 } from "path";
174617
174673
  function mediaDir(projectDir) {
174618
- return join104(projectDir, ".media");
174674
+ return join105(projectDir, ".media");
174619
174675
  }
174620
174676
  function manifestPath(projectDir) {
174621
- return join104(mediaDir(projectDir), MANIFEST_FILE2);
174677
+ return join105(mediaDir(projectDir), MANIFEST_FILE2);
174622
174678
  }
174623
174679
  function typeDirPath(projectDir, type) {
174624
- return join104(mediaDir(projectDir), TYPE_DIRS[type]);
174680
+ return join105(mediaDir(projectDir), TYPE_DIRS[type]);
174625
174681
  }
174626
174682
  function isFigmaManifestRecord(value) {
174627
174683
  if (typeof value !== "object" || value === null)
@@ -174708,12 +174764,12 @@ var init_manifest = __esm({
174708
174764
 
174709
174765
  // ../core/dist/figma/mediaIndex.js
174710
174766
  import { mkdirSync as mkdirSync51, writeFileSync as writeFileSync44 } from "fs";
174711
- import { dirname as dirname46, join as join105 } from "path";
174767
+ import { dirname as dirname46, join as join106 } from "path";
174712
174768
  function isRow(value) {
174713
174769
  return typeof value === "object" && value !== null;
174714
174770
  }
174715
174771
  function indexPath(projectDir) {
174716
- return join105(mediaDir(projectDir), "index.md");
174772
+ return join106(mediaDir(projectDir), "index.md");
174717
174773
  }
174718
174774
  function pad(str, len2) {
174719
174775
  return String(str ?? "").padEnd(len2);
@@ -174825,9 +174881,9 @@ var init_sanitizeSvg = __esm({
174825
174881
 
174826
174882
  // ../core/dist/figma/bindings.js
174827
174883
  import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync53, writeFileSync as writeFileSync45 } from "fs";
174828
- import { join as join106 } from "path";
174884
+ import { join as join107 } from "path";
174829
174885
  function bindingsPath(projectDir) {
174830
- return join106(mediaDir(projectDir), BINDINGS_FILE);
174886
+ return join107(mediaDir(projectDir), BINDINGS_FILE);
174831
174887
  }
174832
174888
  function isRecord6(value) {
174833
174889
  return typeof value === "object" && value !== null;
@@ -175382,7 +175438,7 @@ __export(asset_exports, {
175382
175438
  runAssetImport: () => runAssetImport
175383
175439
  });
175384
175440
  import { existsSync as existsSync101 } from "fs";
175385
- import { join as join107, relative as relative16 } from "path";
175441
+ import { join as join108, relative as relative16 } from "path";
175386
175442
  async function runAssetImport(refInput, opts, deps) {
175387
175443
  const ref2 = parseFigmaRef(refInput);
175388
175444
  if (!ref2.nodeId)
@@ -175393,7 +175449,7 @@ async function runAssetImport(refInput, opts, deps) {
175393
175449
  const description = normalizeMeta(opts.description);
175394
175450
  const entity = normalizeMeta(opts.entity);
175395
175451
  const existing = findAllByFigmaNode(deps.projectDir, ref2.fileKey, ref2.nodeId).find(
175396
- (r2) => r2.provenance.format === opts.format && (r2.provenance.scale ?? 1) === (opts.scale ?? 1) && r2.provenance.version === version2 && existsSync101(join107(deps.projectDir, r2.path))
175452
+ (r2) => r2.provenance.format === opts.format && (r2.provenance.scale ?? 1) === (opts.scale ?? 1) && r2.provenance.version === version2 && existsSync101(join108(deps.projectDir, r2.path))
175397
175453
  );
175398
175454
  if (existing) {
175399
175455
  let record2 = existing;
@@ -175417,7 +175473,7 @@ async function runAssetImport(refInput, opts, deps) {
175417
175473
  bytes = new TextEncoder().encode(sanitizeSvg(new TextDecoder().decode(bytes)));
175418
175474
  }
175419
175475
  const id = nextId(deps.projectDir, "image");
175420
- const destAbs = join107(typeDirPath(deps.projectDir, "image"), `${id}.${rendered.ext}`);
175476
+ const destAbs = join108(typeDirPath(deps.projectDir, "image"), `${id}.${rendered.ext}`);
175421
175477
  freezeBytes(bytes, destAbs);
175422
175478
  const record = {
175423
175479
  id,
@@ -175514,11 +175570,11 @@ __export(tokens_exports, {
175514
175570
  runTokensImport: () => runTokensImport
175515
175571
  });
175516
175572
  import { writeFileSync as writeFileSync46 } from "fs";
175517
- import { join as join108 } from "path";
175573
+ import { join as join109 } from "path";
175518
175574
  async function runTokensImport(refInput, deps) {
175519
175575
  const { fileKey } = parseFigmaRef(refInput);
175520
175576
  const { version: version2 } = await deps.client.fileVersion(fileKey);
175521
- const sidecarPath = join108(deps.projectDir, "figma-tokens.json");
175577
+ const sidecarPath = join109(deps.projectDir, "figma-tokens.json");
175522
175578
  let vars = null;
175523
175579
  try {
175524
175580
  vars = await deps.client.variables(fileKey);
@@ -175585,7 +175641,7 @@ __export(component_exports, {
175585
175641
  runComponentImport: () => runComponentImport
175586
175642
  });
175587
175643
  import { existsSync as existsSync102, mkdirSync as mkdirSync54, writeFileSync as writeFileSync47 } from "fs";
175588
- import { join as join109, relative as relative17 } from "path";
175644
+ import { join as join110, relative as relative17 } from "path";
175589
175645
  function escapeAttr2(value) {
175590
175646
  return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
175591
175647
  }
@@ -175596,7 +175652,7 @@ async function runComponentImport(refInput, deps) {
175596
175652
  const bindings = resolveBindings(tree, readBindings(deps.projectDir));
175597
175653
  const mapped = nodeToHtml(tree, bindings);
175598
175654
  const name = slugify2(tree.name);
175599
- const componentDir = join109(deps.projectDir, "compositions", "components", name);
175655
+ const componentDir = join110(deps.projectDir, "compositions", "components", name);
175600
175656
  if (existsSync102(componentDir))
175601
175657
  console.warn(
175602
175658
  `component dir compositions/components/${name} already exists \u2014 overwriting (rename the figma frame for a separate import)`
@@ -175611,7 +175667,7 @@ async function runComponentImport(refInput, deps) {
175611
175667
  { projectDir: deps.projectDir, client: deps.client, download: deps.download }
175612
175668
  );
175613
175669
  frozenAssets.push(asset.record.path);
175614
- const srcRel = relative17(componentDir, join109(deps.projectDir, asset.record.path)).replaceAll(
175670
+ const srcRel = relative17(componentDir, join110(deps.projectDir, asset.record.path)).replaceAll(
175615
175671
  "\\",
175616
175672
  "/"
175617
175673
  );
@@ -175621,7 +175677,7 @@ async function runComponentImport(refInput, deps) {
175621
175677
  `data-figma-rasterize="${emittedId}" src="${escapeAttr2(srcRel)}" `
175622
175678
  );
175623
175679
  }
175624
- const htmlFile = join109(componentDir, `${name}.html`);
175680
+ const htmlFile = join110(componentDir, `${name}.html`);
175625
175681
  writeFileSync47(htmlFile, html + "\n");
175626
175682
  const registryItem = {
175627
175683
  name,
@@ -175643,7 +175699,7 @@ async function runComponentImport(refInput, deps) {
175643
175699
  ]
175644
175700
  };
175645
175701
  writeFileSync47(
175646
- join109(componentDir, "registry-item.json"),
175702
+ join110(componentDir, "registry-item.json"),
175647
175703
  JSON.stringify(registryItem, null, 2) + "\n"
175648
175704
  );
175649
175705
  return {
@@ -175885,7 +175941,7 @@ __export(autoUpdate_exports, {
175885
175941
  import { spawn as spawn17 } from "child_process";
175886
175942
  import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync55, openSync as openSync4 } from "fs";
175887
175943
  import { homedir as homedir16 } from "os";
175888
- import { join as join110 } from "path";
175944
+ import { join as join111 } from "path";
175889
175945
  import { compareVersions as compareVersions3 } from "compare-versions";
175890
175946
  function isAutoInstallDisabled() {
175891
175947
  if (isDevMode()) return true;
@@ -175908,7 +175964,7 @@ function log(line2) {
175908
175964
  }
175909
175965
  function launchDetachedInstall(installCommand, version2) {
175910
175966
  mkdirSync55(CONFIG_DIR2, { recursive: true, mode: 448 });
175911
- const configFile = join110(CONFIG_DIR2, "config.json");
175967
+ const configFile = join111(CONFIG_DIR2, "config.json");
175912
175968
  const nodeScript = `
175913
175969
  const { exec } = require("node:child_process");
175914
175970
  const { readFileSync, renameSync, writeFileSync } = require("node:fs");
@@ -176027,8 +176083,8 @@ var init_autoUpdate = __esm({
176027
176083
  init_config();
176028
176084
  init_env();
176029
176085
  init_installerDetection();
176030
- CONFIG_DIR2 = join110(homedir16(), ".hyperframes");
176031
- LOG_FILE = join110(CONFIG_DIR2, "auto-update.log");
176086
+ CONFIG_DIR2 = join111(homedir16(), ".hyperframes");
176087
+ LOG_FILE = join111(CONFIG_DIR2, "auto-update.log");
176032
176088
  PENDING_TIMEOUT_MS = 10 * 60 * 1e3;
176033
176089
  }
176034
176090
  });
@@ -176276,7 +176332,7 @@ var init_help = __esm({
176276
176332
  // src/cli.ts
176277
176333
  init_version();
176278
176334
  init_dist();
176279
- import { dirname as dirname47, join as join111 } from "path";
176335
+ import { dirname as dirname47, join as join113 } from "path";
176280
176336
  import { fileURLToPath as fileURLToPath16 } from "url";
176281
176337
  import { existsSync as existsSync103 } from "fs";
176282
176338
 
@@ -176321,7 +176377,7 @@ for (const stream of [process.stdout, process.stderr]) {
176321
176377
  }
176322
176378
  (() => {
176323
176379
  const here = dirname47(fileURLToPath16(import.meta.url));
176324
- const shader = join111(here, "shaderTransitionWorker.js");
176380
+ const shader = join113(here, "shaderTransitionWorker.js");
176325
176381
  if (!process.env.HF_SHADER_WORKER_ENTRY && existsSync103(shader)) {
176326
176382
  process.env.HF_SHADER_WORKER_ENTRY = shader;
176327
176383
  }