hyperframes 0.4.27 → 0.4.29

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
@@ -54,7 +54,7 @@ var VERSION;
54
54
  var init_version = __esm({
55
55
  "src/version.ts"() {
56
56
  "use strict";
57
- VERSION = true ? "0.4.27" : "0.0.0-dev";
57
+ VERSION = true ? "0.4.29" : "0.0.0-dev";
58
58
  }
59
59
  });
60
60
 
@@ -9838,8 +9838,8 @@ function flushSync() {
9838
9838
  eventQueue = [];
9839
9839
  const payload = JSON.stringify({ api_key: POSTHOG_API_KEY, batch });
9840
9840
  try {
9841
- const { spawn: spawn13 } = __require("child_process");
9842
- const child = spawn13(
9841
+ const { spawn: spawn14 } = __require("child_process");
9842
+ const child = spawn14(
9843
9843
  process.execPath,
9844
9844
  [
9845
9845
  "-e",
@@ -10491,9 +10491,9 @@ function findWavDataChunk(buf) {
10491
10491
  return null;
10492
10492
  }
10493
10493
  function detectSpeechOnset(wavPath) {
10494
- const SAMPLE_RATE = 16e3;
10494
+ const SAMPLE_RATE2 = 16e3;
10495
10495
  const WINDOW_SECONDS = 0.5;
10496
- const WINDOW_SAMPLES = SAMPLE_RATE * WINDOW_SECONDS;
10496
+ const WINDOW_SAMPLES = SAMPLE_RATE2 * WINDOW_SECONDS;
10497
10497
  const SUSTAINED_WINDOWS = 3;
10498
10498
  const SILENCE_THRESHOLD_RATIO = 0.6;
10499
10499
  const MIN_INTRO_SECONDS = 3;
@@ -11390,11 +11390,138 @@ var init_projects = __esm({
11390
11390
  }
11391
11391
  });
11392
11392
 
11393
+ // ../core/src/studio-api/helpers/mime.ts
11394
+ function getMimeType(path2) {
11395
+ const ext = path2.slice(path2.lastIndexOf(".")).toLowerCase();
11396
+ return MIME_TYPES[ext] || "application/octet-stream";
11397
+ }
11398
+ function isAudioFile2(name) {
11399
+ return (getMimeType(name) ?? "").startsWith("audio/");
11400
+ }
11401
+ var MIME_TYPES;
11402
+ var init_mime = __esm({
11403
+ "../core/src/studio-api/helpers/mime.ts"() {
11404
+ "use strict";
11405
+ MIME_TYPES = {
11406
+ ".html": "text/html",
11407
+ ".css": "text/css",
11408
+ ".js": "text/javascript",
11409
+ ".mjs": "text/javascript",
11410
+ ".json": "application/json",
11411
+ ".svg": "image/svg+xml",
11412
+ ".png": "image/png",
11413
+ ".jpg": "image/jpeg",
11414
+ ".jpeg": "image/jpeg",
11415
+ ".gif": "image/gif",
11416
+ ".webp": "image/webp",
11417
+ ".ico": "image/x-icon",
11418
+ ".mp4": "video/mp4",
11419
+ ".mov": "video/quicktime",
11420
+ ".webm": "video/webm",
11421
+ ".mp3": "audio/mpeg",
11422
+ ".wav": "audio/wav",
11423
+ ".ogg": "audio/ogg",
11424
+ ".m4a": "audio/mp4",
11425
+ ".aac": "audio/aac",
11426
+ ".flac": "audio/flac",
11427
+ ".opus": "audio/ogg",
11428
+ ".woff": "font/woff",
11429
+ ".woff2": "font/woff2",
11430
+ ".ttf": "font/ttf",
11431
+ ".otf": "font/otf",
11432
+ ".txt": "text/plain",
11433
+ ".md": "text/markdown"
11434
+ };
11435
+ }
11436
+ });
11437
+
11438
+ // ../core/src/studio-api/helpers/waveform.ts
11439
+ import { spawn as spawn2 } from "child_process";
11440
+ import { existsSync as existsSync9, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5 } from "fs";
11441
+ import { join as join11 } from "path";
11442
+ function buildWaveformCacheKey(assetPath) {
11443
+ return `${WAVEFORM_CACHE_VERSION}_${assetPath.replace(/[/\\]/g, "_")}.json`;
11444
+ }
11445
+ function computePeaks(floats, count) {
11446
+ const step = floats.length / count;
11447
+ const peaks = [];
11448
+ for (let i2 = 0; i2 < count; i2++) {
11449
+ const start = Math.floor(i2 * step);
11450
+ const end = Math.min(Math.floor((i2 + 1) * step), floats.length);
11451
+ let max = 0;
11452
+ for (let j2 = start; j2 < end; j2++) {
11453
+ const abs = Math.abs(floats[j2] ?? 0);
11454
+ if (abs > max) max = abs;
11455
+ }
11456
+ peaks.push(max);
11457
+ }
11458
+ const maxPeak = Math.max(...peaks, 1e-3);
11459
+ return peaks.map((p) => p / maxPeak);
11460
+ }
11461
+ function decodeAudioPeaks(audioPath) {
11462
+ return new Promise((resolve39, reject) => {
11463
+ const proc = spawn2(
11464
+ "ffmpeg",
11465
+ [
11466
+ "-i",
11467
+ audioPath,
11468
+ "-af",
11469
+ "atrim=start_sample=1152",
11470
+ "-f",
11471
+ "f32le",
11472
+ "-ac",
11473
+ "1",
11474
+ "-ar",
11475
+ String(SAMPLE_RATE),
11476
+ "-vn",
11477
+ "pipe:1"
11478
+ ],
11479
+ { stdio: ["ignore", "pipe", "ignore"] }
11480
+ );
11481
+ const chunks = [];
11482
+ proc.stdout?.on("data", (chunk) => chunks.push(chunk));
11483
+ proc.on("close", (code) => {
11484
+ if (code !== 0 && chunks.length === 0) {
11485
+ reject(new Error(`ffmpeg exited with code ${code}`));
11486
+ return;
11487
+ }
11488
+ const buf = Buffer.concat(chunks);
11489
+ const numSamples = Math.floor(buf.length / 4);
11490
+ if (numSamples === 0) {
11491
+ reject(new Error("ffmpeg produced no audio samples"));
11492
+ return;
11493
+ }
11494
+ const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + numSamples * 4);
11495
+ resolve39(computePeaks(new Float32Array(ab), PEAK_COUNT));
11496
+ });
11497
+ proc.on("error", reject);
11498
+ });
11499
+ }
11500
+ async function generateWaveformCache(projectDir, assetPath) {
11501
+ const audioPath = join11(projectDir, assetPath);
11502
+ if (!existsSync9(audioPath)) return;
11503
+ const cacheDir = join11(projectDir, ".waveform-cache");
11504
+ const cachePath2 = join11(cacheDir, buildWaveformCacheKey(assetPath));
11505
+ if (existsSync9(cachePath2)) return;
11506
+ const peaks = await decodeAudioPeaks(audioPath);
11507
+ mkdirSync5(cacheDir, { recursive: true });
11508
+ writeFileSync5(cachePath2, JSON.stringify(peaks));
11509
+ }
11510
+ var SAMPLE_RATE, PEAK_COUNT, WAVEFORM_CACHE_VERSION;
11511
+ var init_waveform = __esm({
11512
+ "../core/src/studio-api/helpers/waveform.ts"() {
11513
+ "use strict";
11514
+ SAMPLE_RATE = 4e3;
11515
+ PEAK_COUNT = 4e3;
11516
+ WAVEFORM_CACHE_VERSION = "v2";
11517
+ }
11518
+ });
11519
+
11393
11520
  // ../core/src/studio-api/helpers/mediaValidation.ts
11394
11521
  import { spawnSync } from "child_process";
11395
- import { mkdtempSync, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "fs";
11522
+ import { mkdtempSync, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "fs";
11396
11523
  import { tmpdir as tmpdir2 } from "os";
11397
- import { basename, join as join11 } from "path";
11524
+ import { basename, join as join12 } from "path";
11398
11525
  function validateUploadedMedia(filePath, runner = spawnSync) {
11399
11526
  const isVideo2 = VIDEO_EXT.test(filePath);
11400
11527
  const isAudio = AUDIO_EXT.test(filePath);
@@ -11433,10 +11560,10 @@ function validateUploadedMedia(filePath, runner = spawnSync) {
11433
11560
  }
11434
11561
  }
11435
11562
  function validateUploadedMediaBuffer(fileName, buffer, runner = spawnSync) {
11436
- const tempDir = mkdtempSync(join11(tmpdir2(), "hyperframes-upload-"));
11437
- const tempPath = join11(tempDir, basename(fileName));
11563
+ const tempDir = mkdtempSync(join12(tmpdir2(), "hyperframes-upload-"));
11564
+ const tempPath = join12(tempDir, basename(fileName));
11438
11565
  try {
11439
- writeFileSync5(tempPath, buffer);
11566
+ writeFileSync6(tempPath, buffer);
11440
11567
  return validateUploadedMedia(tempPath, runner);
11441
11568
  } finally {
11442
11569
  rmSync2(tempDir, { recursive: true, force: true });
@@ -23289,7 +23416,7 @@ var init_html_classes = __esm({
23289
23416
 
23290
23417
  // ../../node_modules/.bun/linkedom@0.18.12/node_modules/linkedom/esm/shared/mime.js
23291
23418
  var voidElements2, Mime;
23292
- var init_mime = __esm({
23419
+ var init_mime2 = __esm({
23293
23420
  "../../node_modules/.bun/linkedom@0.18.12/node_modules/linkedom/esm/shared/mime.js"() {
23294
23421
  "use strict";
23295
23422
  voidElements2 = { test: () => true };
@@ -23554,7 +23681,7 @@ var init_document = __esm({
23554
23681
  init_symbols();
23555
23682
  init_facades();
23556
23683
  init_html_classes();
23557
- init_mime();
23684
+ init_mime2();
23558
23685
  init_utils2();
23559
23686
  init_object();
23560
23687
  init_non_element_parent_node();
@@ -24093,17 +24220,17 @@ var init_sourceMutation = __esm({
24093
24220
  // ../core/src/studio-api/routes/files.ts
24094
24221
  import { bodyLimit } from "hono/body-limit";
24095
24222
  import {
24096
- existsSync as existsSync9,
24223
+ existsSync as existsSync10,
24097
24224
  readFileSync as readFileSync9,
24098
- writeFileSync as writeFileSync6,
24099
- mkdirSync as mkdirSync5,
24225
+ writeFileSync as writeFileSync7,
24226
+ mkdirSync as mkdirSync6,
24100
24227
  unlinkSync as unlinkSync3,
24101
24228
  rmSync as rmSync3,
24102
24229
  statSync,
24103
24230
  renameSync as renameSync2,
24104
24231
  readdirSync as readdirSync4
24105
24232
  } from "fs";
24106
- import { resolve as resolve9, dirname as dirname5, join as join12 } from "path";
24233
+ import { resolve as resolve9, dirname as dirname5, join as join13 } from "path";
24107
24234
  async function resolveProjectFile(c2, adapter2, opts) {
24108
24235
  const id = c2.req.param("id");
24109
24236
  const project = await adapter2.resolveProject(id);
@@ -24118,14 +24245,14 @@ async function resolveProjectFile(c2, adapter2, opts) {
24118
24245
  if (!isSafePath(project.dir, absPath)) {
24119
24246
  return { error: c2.json({ error: "forbidden" }, 403) };
24120
24247
  }
24121
- if (opts?.mustExist && !existsSync9(absPath)) {
24248
+ if (opts?.mustExist && !existsSync10(absPath)) {
24122
24249
  return { error: c2.json({ error: "not found" }, 404) };
24123
24250
  }
24124
24251
  return { project, filePath, absPath };
24125
24252
  }
24126
24253
  function ensureDir(filePath) {
24127
24254
  const dir = dirname5(filePath);
24128
- if (!existsSync9(dir)) mkdirSync5(dir, { recursive: true });
24255
+ if (!existsSync10(dir)) mkdirSync6(dir, { recursive: true });
24129
24256
  }
24130
24257
  function generateCopyPath(projectDir, originalPath) {
24131
24258
  const ext = originalPath.includes(".") ? "." + originalPath.split(".").pop() : "";
@@ -24134,7 +24261,7 @@ function generateCopyPath(projectDir, originalPath) {
24134
24261
  const cleanBase = copyMatch ? base.slice(0, -copyMatch[0].length) : base;
24135
24262
  let num = copyMatch ? copyMatch[1] ? parseInt(copyMatch[1]) + 1 : 2 : 1;
24136
24263
  let candidate = num === 1 ? `${cleanBase} (copy)${ext}` : `${cleanBase} (copy ${num})${ext}`;
24137
- while (existsSync9(resolve9(projectDir, candidate))) {
24264
+ while (existsSync10(resolve9(projectDir, candidate))) {
24138
24265
  num++;
24139
24266
  candidate = `${cleanBase} (copy ${num})${ext}`;
24140
24267
  }
@@ -24143,7 +24270,7 @@ function generateCopyPath(projectDir, originalPath) {
24143
24270
  function walkFiles(dir, filter2) {
24144
24271
  const results = [];
24145
24272
  for (const entry of readdirSync4(dir, { withFileTypes: true })) {
24146
- const full = join12(dir, entry.name);
24273
+ const full = join13(dir, entry.name);
24147
24274
  if (entry.isDirectory()) {
24148
24275
  if (entry.name === "node_modules" || entry.name === ".thumbnails" || entry.name === "renders")
24149
24276
  continue;
@@ -24165,7 +24292,7 @@ function updateReferences(projectDir, oldPath, newPath) {
24165
24292
  if (!content.includes(oldPath)) continue;
24166
24293
  const updated = content.split(oldPath).join(newPath);
24167
24294
  if (updated !== content) {
24168
- writeFileSync6(file, updated, "utf-8");
24295
+ writeFileSync7(file, updated, "utf-8");
24169
24296
  updatedCount++;
24170
24297
  }
24171
24298
  }
@@ -24183,18 +24310,18 @@ function registerFileRoutes(api, adapter2) {
24183
24310
  if ("error" in res) return res.error;
24184
24311
  ensureDir(res.absPath);
24185
24312
  const body = await c2.req.text();
24186
- writeFileSync6(res.absPath, body, "utf-8");
24313
+ writeFileSync7(res.absPath, body, "utf-8");
24187
24314
  return c2.json({ ok: true });
24188
24315
  });
24189
24316
  api.post("/projects/:id/files/*", async (c2) => {
24190
24317
  const res = await resolveProjectFile(c2, adapter2);
24191
24318
  if ("error" in res) return res.error;
24192
- if (existsSync9(res.absPath)) {
24319
+ if (existsSync10(res.absPath)) {
24193
24320
  return c2.json({ error: "already exists" }, 409);
24194
24321
  }
24195
24322
  ensureDir(res.absPath);
24196
24323
  const body = await c2.req.text().catch(() => "");
24197
- writeFileSync6(res.absPath, body, "utf-8");
24324
+ writeFileSync7(res.absPath, body, "utf-8");
24198
24325
  return c2.json({ ok: true, path: res.filePath }, 201);
24199
24326
  });
24200
24327
  api.delete("/projects/:id/files/*", async (c2) => {
@@ -24222,7 +24349,7 @@ function registerFileRoutes(api, adapter2) {
24222
24349
  if (!isSafePath(project.dir, absPath)) {
24223
24350
  return c2.json({ error: "forbidden" }, 403);
24224
24351
  }
24225
- if (!existsSync9(absPath)) {
24352
+ if (!existsSync10(absPath)) {
24226
24353
  return c2.json({ error: "not found" }, 404);
24227
24354
  }
24228
24355
  const body = await c2.req.json().catch(() => null);
@@ -24234,7 +24361,7 @@ function registerFileRoutes(api, adapter2) {
24234
24361
  if (patchedContent === originalContent) {
24235
24362
  return c2.json({ ok: true, changed: false, content: originalContent });
24236
24363
  }
24237
- writeFileSync6(absPath, patchedContent, "utf-8");
24364
+ writeFileSync7(absPath, patchedContent, "utf-8");
24238
24365
  return c2.json({ ok: true, changed: true, content: patchedContent });
24239
24366
  });
24240
24367
  api.patch("/projects/:id/files/*", async (c2) => {
@@ -24248,7 +24375,7 @@ function registerFileRoutes(api, adapter2) {
24248
24375
  if (!isSafePath(res.project.dir, newAbs)) {
24249
24376
  return c2.json({ error: "forbidden" }, 403);
24250
24377
  }
24251
- if (existsSync9(newAbs)) {
24378
+ if (existsSync10(newAbs)) {
24252
24379
  return c2.json({ error: "already exists" }, 409);
24253
24380
  }
24254
24381
  ensureDir(newAbs);
@@ -24264,7 +24391,7 @@ function registerFileRoutes(api, adapter2) {
24264
24391
  return c2.json({ error: "path required" }, 400);
24265
24392
  }
24266
24393
  const srcAbs = resolve9(project.dir, body.path);
24267
- if (!isSafePath(project.dir, srcAbs) || !existsSync9(srcAbs)) {
24394
+ if (!isSafePath(project.dir, srcAbs) || !existsSync10(srcAbs)) {
24268
24395
  return c2.json({ error: "not found" }, 404);
24269
24396
  }
24270
24397
  const copyPath = generateCopyPath(project.dir, body.path);
@@ -24273,7 +24400,7 @@ function registerFileRoutes(api, adapter2) {
24273
24400
  return c2.json({ error: "forbidden" }, 403);
24274
24401
  }
24275
24402
  ensureDir(destAbs);
24276
- writeFileSync6(destAbs, readFileSync9(srcAbs));
24403
+ writeFileSync7(destAbs, readFileSync9(srcAbs));
24277
24404
  return c2.json({ ok: true, path: copyPath }, 201);
24278
24405
  });
24279
24406
  const MAX_UPLOAD_BYTES = 500 * 1024 * 1024;
@@ -24289,7 +24416,7 @@ function registerFileRoutes(api, adapter2) {
24289
24416
  const subDir = c2.req.query("dir") ?? "";
24290
24417
  const targetDir = subDir ? resolve9(project.dir, subDir) : project.dir;
24291
24418
  if (!isSafePath(project.dir, targetDir)) return c2.json({ error: "forbidden" }, 403);
24292
- if (subDir && !existsSync9(targetDir)) mkdirSync5(targetDir, { recursive: true });
24419
+ if (subDir && !existsSync10(targetDir)) mkdirSync6(targetDir, { recursive: true });
24293
24420
  const formData = await c2.req.formData();
24294
24421
  const uploaded = [];
24295
24422
  const skipped = [];
@@ -24306,12 +24433,12 @@ function registerFileRoutes(api, adapter2) {
24306
24433
  if (!isSafePath(project.dir, destPath)) continue;
24307
24434
  let finalPath = destPath;
24308
24435
  let finalName = name;
24309
- if (existsSync9(finalPath)) {
24436
+ if (existsSync10(finalPath)) {
24310
24437
  const dotIdx = name.indexOf(".", name.startsWith(".") ? 1 : 0);
24311
24438
  const ext = dotIdx > 0 ? name.slice(dotIdx) : "";
24312
24439
  const base = dotIdx > 0 ? name.slice(0, dotIdx) : name;
24313
24440
  let n = 2;
24314
- while (n < 1e4 && existsSync9(resolve9(targetDir, `${base} (${n})${ext}`))) n++;
24441
+ while (n < 1e4 && existsSync10(resolve9(targetDir, `${base} (${n})${ext}`))) n++;
24315
24442
  if (n >= 1e4) {
24316
24443
  skipped.push(name);
24317
24444
  continue;
@@ -24325,8 +24452,13 @@ function registerFileRoutes(api, adapter2) {
24325
24452
  invalid.push({ name: finalName, reason: validation.reason });
24326
24453
  continue;
24327
24454
  }
24328
- writeFileSync6(finalPath, buffer);
24329
- uploaded.push(subDir ? join12(subDir, finalName) : finalName);
24455
+ writeFileSync7(finalPath, buffer);
24456
+ const relativePath = subDir ? join13(subDir, finalName) : finalName;
24457
+ uploaded.push(relativePath);
24458
+ if (isAudioFile2(finalName)) {
24459
+ generateWaveformCache(project.dir, relativePath).catch(() => {
24460
+ });
24461
+ }
24330
24462
  }
24331
24463
  return c2.json({ ok: true, files: uploaded, skipped, invalid }, 201);
24332
24464
  }
@@ -24335,57 +24467,20 @@ function registerFileRoutes(api, adapter2) {
24335
24467
  var init_files = __esm({
24336
24468
  "../core/src/studio-api/routes/files.ts"() {
24337
24469
  "use strict";
24470
+ init_mime();
24471
+ init_waveform();
24338
24472
  init_mediaValidation();
24339
24473
  init_safePath();
24340
24474
  init_sourceMutation();
24341
24475
  }
24342
24476
  });
24343
24477
 
24344
- // ../core/src/studio-api/helpers/mime.ts
24345
- function getMimeType(path2) {
24346
- const ext = path2.slice(path2.lastIndexOf(".")).toLowerCase();
24347
- return MIME_TYPES[ext] || "application/octet-stream";
24348
- }
24349
- var MIME_TYPES;
24350
- var init_mime2 = __esm({
24351
- "../core/src/studio-api/helpers/mime.ts"() {
24352
- "use strict";
24353
- MIME_TYPES = {
24354
- ".html": "text/html",
24355
- ".css": "text/css",
24356
- ".js": "text/javascript",
24357
- ".mjs": "text/javascript",
24358
- ".json": "application/json",
24359
- ".svg": "image/svg+xml",
24360
- ".png": "image/png",
24361
- ".jpg": "image/jpeg",
24362
- ".jpeg": "image/jpeg",
24363
- ".gif": "image/gif",
24364
- ".webp": "image/webp",
24365
- ".ico": "image/x-icon",
24366
- ".mp4": "video/mp4",
24367
- ".mov": "video/quicktime",
24368
- ".webm": "video/webm",
24369
- ".mp3": "audio/mpeg",
24370
- ".wav": "audio/wav",
24371
- ".ogg": "audio/ogg",
24372
- ".m4a": "audio/mp4",
24373
- ".woff": "font/woff",
24374
- ".woff2": "font/woff2",
24375
- ".ttf": "font/ttf",
24376
- ".otf": "font/otf",
24377
- ".txt": "text/plain",
24378
- ".md": "text/markdown"
24379
- };
24380
- }
24381
- });
24382
-
24383
24478
  // ../core/src/studio-api/helpers/subComposition.ts
24384
- import { existsSync as existsSync10, readFileSync as readFileSync10 } from "fs";
24385
- import { join as join13 } from "path";
24479
+ import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
24480
+ import { join as join14 } from "path";
24386
24481
  function buildSubCompositionHtml(projectDir, compPath, runtimeUrl, baseHref) {
24387
- const compFile = join13(projectDir, compPath);
24388
- if (!existsSync10(compFile)) return null;
24482
+ const compFile = join14(projectDir, compPath);
24483
+ if (!existsSync11(compFile)) return null;
24389
24484
  const rawComp = readFileSync10(compFile, "utf-8");
24390
24485
  const templateMatch = rawComp.match(/<template[^>]*>([\s\S]*)<\/template>/i);
24391
24486
  const content = templateMatch?.[1] ?? rawComp;
@@ -24404,9 +24499,9 @@ function buildSubCompositionHtml(projectDir, compPath, runtimeUrl, baseHref) {
24404
24499
  styleEl.textContent = rewriteCssAssetUrls(styleEl.textContent || "", compPath);
24405
24500
  }
24406
24501
  const rewrittenContent = contentDoc.body.innerHTML || content;
24407
- const indexPath = join13(projectDir, "index.html");
24502
+ const indexPath = join14(projectDir, "index.html");
24408
24503
  let headContent = "";
24409
- if (existsSync10(indexPath)) {
24504
+ if (existsSync11(indexPath)) {
24410
24505
  const indexHtml = readFileSync10(indexPath, "utf-8");
24411
24506
  const headMatch = indexHtml.match(/<head[^>]*>([\s\S]*?)<\/head>/i);
24412
24507
  headContent = headMatch?.[1] ?? "";
@@ -24443,7 +24538,7 @@ var init_subComposition = __esm({
24443
24538
  });
24444
24539
 
24445
24540
  // ../core/src/studio-api/routes/preview.ts
24446
- import { existsSync as existsSync11, readFileSync as readFileSync11, statSync as statSync2 } from "fs";
24541
+ import { existsSync as existsSync12, readFileSync as readFileSync11, statSync as statSync2 } from "fs";
24447
24542
  import { resolve as resolve10 } from "path";
24448
24543
  function registerPreviewRoutes(api, adapter2) {
24449
24544
  api.get("/projects/:id/preview", async (c2) => {
@@ -24453,7 +24548,7 @@ function registerPreviewRoutes(api, adapter2) {
24453
24548
  let bundled = await adapter2.bundle(project.dir);
24454
24549
  if (!bundled) {
24455
24550
  const indexPath = resolve10(project.dir, "index.html");
24456
- if (!existsSync11(indexPath)) return c2.text("not found", 404);
24551
+ if (!existsSync12(indexPath)) return c2.text("not found", 404);
24457
24552
  bundled = readFileSync11(indexPath, "utf-8");
24458
24553
  }
24459
24554
  if (!bundled.includes("hyperframe.runtime") && !bundled.includes("hyperframes-preview-runtime")) {
@@ -24469,7 +24564,7 @@ ${runtimeTag}`;
24469
24564
  return c2.html(bundled);
24470
24565
  } catch {
24471
24566
  const file = resolve10(project.dir, "index.html");
24472
- if (existsSync11(file)) return c2.html(readFileSync11(file, "utf-8"));
24567
+ if (existsSync12(file)) return c2.html(readFileSync11(file, "utf-8"));
24473
24568
  return c2.text("not found", 404);
24474
24569
  }
24475
24570
  });
@@ -24480,7 +24575,7 @@ ${runtimeTag}`;
24480
24575
  c2.req.path.replace(`/projects/${project.id}/preview/comp/`, "").split("?")[0] ?? ""
24481
24576
  );
24482
24577
  const compFile = resolve10(project.dir, compPath);
24483
- if (!isSafePath(project.dir, compFile) || !existsSync11(compFile) || !statSync2(compFile).isFile()) {
24578
+ if (!isSafePath(project.dir, compFile) || !existsSync12(compFile) || !statSync2(compFile).isFile()) {
24484
24579
  return c2.text("not found", 404);
24485
24580
  }
24486
24581
  const baseHref = `/api/projects/${project.id}/preview/`;
@@ -24495,7 +24590,7 @@ ${runtimeTag}`;
24495
24590
  c2.req.path.replace(`/projects/${project.id}/preview/`, "").split("?")[0] ?? ""
24496
24591
  );
24497
24592
  const file = resolve10(project.dir, subPath);
24498
- if (!isSafePath(project.dir, file) || !existsSync11(file) || !statSync2(file).isFile()) {
24593
+ if (!isSafePath(project.dir, file) || !existsSync12(file) || !statSync2(file).isFile()) {
24499
24594
  return c2.text("not found", 404);
24500
24595
  }
24501
24596
  const contentType = getMimeType(subPath);
@@ -24534,14 +24629,14 @@ var init_preview = __esm({
24534
24629
  "../core/src/studio-api/routes/preview.ts"() {
24535
24630
  "use strict";
24536
24631
  init_safePath();
24537
- init_mime2();
24632
+ init_mime();
24538
24633
  init_subComposition();
24539
24634
  }
24540
24635
  });
24541
24636
 
24542
24637
  // ../core/src/studio-api/routes/lint.ts
24543
24638
  import { readFileSync as readFileSync12 } from "fs";
24544
- import { join as join14 } from "path";
24639
+ import { join as join15 } from "path";
24545
24640
  function registerLintRoutes(api, adapter2) {
24546
24641
  api.get("/projects/:id/lint", async (c2) => {
24547
24642
  const project = await adapter2.resolveProject(c2.req.param("id"));
@@ -24550,7 +24645,7 @@ function registerLintRoutes(api, adapter2) {
24550
24645
  const htmlFiles = walkDir(project.dir).filter((f3) => f3.endsWith(".html"));
24551
24646
  const allFindings = [];
24552
24647
  for (const file of htmlFiles) {
24553
- const content = readFileSync12(join14(project.dir, file), "utf-8");
24648
+ const content = readFileSync12(join15(project.dir, file), "utf-8");
24554
24649
  const result = await adapter2.lint(content, { filePath: file });
24555
24650
  if (result?.findings) {
24556
24651
  for (const f3 of result.findings) {
@@ -24574,8 +24669,8 @@ var init_lint2 = __esm({
24574
24669
 
24575
24670
  // ../core/src/studio-api/routes/render.ts
24576
24671
  import { streamSSE } from "hono/streaming";
24577
- import { existsSync as existsSync12, readFileSync as readFileSync13, mkdirSync as mkdirSync6, unlinkSync as unlinkSync4, readdirSync as readdirSync5, statSync as statSync3 } from "fs";
24578
- import { join as join15 } from "path";
24672
+ import { existsSync as existsSync13, readFileSync as readFileSync13, mkdirSync as mkdirSync7, unlinkSync as unlinkSync4, readdirSync as readdirSync5, statSync as statSync3 } from "fs";
24673
+ import { join as join16 } from "path";
24579
24674
  function registerRenderRoutes(api, adapter2) {
24580
24675
  const renderJobs = /* @__PURE__ */ new Map();
24581
24676
  const TTL_MS = 3e5;
@@ -24612,9 +24707,9 @@ function registerRenderRoutes(api, adapter2) {
24612
24707
  const timePart = now.toTimeString().slice(0, 8).replace(/:/g, "-");
24613
24708
  const jobId = `${project.id}_${datePart}_${timePart}`;
24614
24709
  const rendersDir = adapter2.rendersDir(project);
24615
- if (!existsSync12(rendersDir)) mkdirSync6(rendersDir, { recursive: true });
24710
+ if (!existsSync13(rendersDir)) mkdirSync7(rendersDir, { recursive: true });
24616
24711
  const ext = FORMAT_EXT2[format] ?? ".mp4";
24617
- const outputPath = join15(rendersDir, `${jobId}${ext}`);
24712
+ const outputPath = join16(rendersDir, `${jobId}${ext}`);
24618
24713
  const jobState = adapter2.startRender({
24619
24714
  project,
24620
24715
  outputPath,
@@ -24679,7 +24774,7 @@ function registerRenderRoutes(api, adapter2) {
24679
24774
  api.get("/render/:jobId/view", (c2) => {
24680
24775
  const { jobId } = c2.req.param();
24681
24776
  const job = renderJobs.get(jobId);
24682
- if (!job?.outputPath || !existsSync12(job.outputPath)) {
24777
+ if (!job?.outputPath || !existsSync13(job.outputPath)) {
24683
24778
  return c2.json({ error: "not found" }, 404);
24684
24779
  }
24685
24780
  const contentType = renderContentType(job.outputPath);
@@ -24697,7 +24792,7 @@ function registerRenderRoutes(api, adapter2) {
24697
24792
  api.get("/render/:jobId/download", (c2) => {
24698
24793
  const { jobId } = c2.req.param();
24699
24794
  const job = renderJobs.get(jobId);
24700
- if (!job?.outputPath || !existsSync12(job.outputPath)) {
24795
+ if (!job?.outputPath || !existsSync13(job.outputPath)) {
24701
24796
  return c2.json({ error: "not found" }, 404);
24702
24797
  }
24703
24798
  const contentType = renderContentType(job.outputPath);
@@ -24716,8 +24811,8 @@ function registerRenderRoutes(api, adapter2) {
24716
24811
  if (state.id === jobId && state.outputPath) {
24717
24812
  const dir = state.outputPath.replace(/\/[^/]+$/, "");
24718
24813
  for (const ext of [".mp4", ".webm", ".mov", ".meta.json"]) {
24719
- const fp = join15(dir, `${jobId}${ext}`);
24720
- if (existsSync12(fp)) unlinkSync4(fp);
24814
+ const fp = join16(dir, `${jobId}${ext}`);
24815
+ if (existsSync13(fp)) unlinkSync4(fp);
24721
24816
  }
24722
24817
  break;
24723
24818
  }
@@ -24731,8 +24826,8 @@ function registerRenderRoutes(api, adapter2) {
24731
24826
  const filename = c2.req.path.split("/renders/file/")[1];
24732
24827
  if (!filename) return c2.json({ error: "missing filename" }, 400);
24733
24828
  const rendersDir = adapter2.rendersDir(project);
24734
- const fp = join15(rendersDir, filename);
24735
- if (!existsSync12(fp)) return c2.json({ error: "not found" }, 404);
24829
+ const fp = join16(rendersDir, filename);
24830
+ if (!existsSync13(fp)) return c2.json({ error: "not found" }, 404);
24736
24831
  const contentType = renderContentType(fp);
24737
24832
  const content = readFileSync13(fp);
24738
24833
  return new Response(content, {
@@ -24748,15 +24843,15 @@ function registerRenderRoutes(api, adapter2) {
24748
24843
  const project = await adapter2.resolveProject(c2.req.param("id"));
24749
24844
  if (!project) return c2.json({ error: "not found" }, 404);
24750
24845
  const rendersDir = adapter2.rendersDir(project);
24751
- if (!existsSync12(rendersDir)) return c2.json({ renders: [] });
24846
+ if (!existsSync13(rendersDir)) return c2.json({ renders: [] });
24752
24847
  const files = readdirSync5(rendersDir).filter((f3) => f3.endsWith(".mp4") || f3.endsWith(".webm") || f3.endsWith(".mov")).map((f3) => {
24753
- const fp = join15(rendersDir, f3);
24848
+ const fp = join16(rendersDir, f3);
24754
24849
  const stat3 = statSync3(fp);
24755
24850
  const rid = f3.replace(/\.(mp4|webm|mov)$/, "");
24756
- const metaPath = join15(rendersDir, `${rid}.meta.json`);
24851
+ const metaPath = join16(rendersDir, `${rid}.meta.json`);
24757
24852
  let status = "complete";
24758
24853
  let durationMs;
24759
- if (existsSync12(metaPath)) {
24854
+ if (existsSync13(metaPath)) {
24760
24855
  try {
24761
24856
  const meta = JSON.parse(readFileSync13(metaPath, "utf-8"));
24762
24857
  if (meta.status === "failed") status = "failed";
@@ -24779,7 +24874,7 @@ function registerRenderRoutes(api, adapter2) {
24779
24874
  id: file.id,
24780
24875
  status: file.status,
24781
24876
  progress: 100,
24782
- outputPath: join15(rendersDir, file.filename),
24877
+ outputPath: join16(rendersDir, file.filename),
24783
24878
  createdAt: file.createdAt
24784
24879
  });
24785
24880
  }
@@ -24794,8 +24889,8 @@ var init_render = __esm({
24794
24889
  });
24795
24890
 
24796
24891
  // ../core/src/studio-api/routes/thumbnail.ts
24797
- import { existsSync as existsSync13, readFileSync as readFileSync14, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7 } from "fs";
24798
- import { join as join16 } from "path";
24892
+ import { existsSync as existsSync14, readFileSync as readFileSync14, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8 } from "fs";
24893
+ import { join as join17 } from "path";
24799
24894
  function registerThumbnailRoutes(api, adapter2) {
24800
24895
  api.get("/projects/:id/thumbnail/*", async (c2) => {
24801
24896
  if (!adapter2.generateThumbnail) {
@@ -24815,8 +24910,8 @@ function registerThumbnailRoutes(api, adapter2) {
24815
24910
  let compW = vpWidth || 1920;
24816
24911
  let compH = vpHeight || 1080;
24817
24912
  if (!vpWidth) {
24818
- const htmlFile = join16(project.dir, compPath);
24819
- if (existsSync13(htmlFile)) {
24913
+ const htmlFile = join17(project.dir, compPath);
24914
+ if (existsSync14(htmlFile)) {
24820
24915
  const html = readFileSync14(htmlFile, "utf-8");
24821
24916
  const wMatch = html.match(/data-width=["'](\d+)["']/);
24822
24917
  const hMatch = html.match(/data-height=["'](\d+)["']/);
@@ -24825,11 +24920,11 @@ function registerThumbnailRoutes(api, adapter2) {
24825
24920
  }
24826
24921
  }
24827
24922
  const previewUrl = compPath === "index.html" ? `http://${c2.req.header("host")}/api/projects/${project.id}/preview` : `http://${c2.req.header("host")}/api/projects/${project.id}/preview/comp/${compPath}`;
24828
- const cacheDir = join16(project.dir, ".thumbnails");
24923
+ const cacheDir = join17(project.dir, ".thumbnails");
24829
24924
  const selectorKey = selector ? `_${selector.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 80)}` : "";
24830
24925
  const cacheKey = `${THUMBNAIL_CACHE_VERSION}_${compPath.replace(/\//g, "_")}_${seekTime.toFixed(2)}${selectorKey}.jpg`;
24831
- const cachePath2 = join16(cacheDir, cacheKey);
24832
- if (existsSync13(cachePath2)) {
24926
+ const cachePath2 = join17(cacheDir, cacheKey);
24927
+ if (existsSync14(cachePath2)) {
24833
24928
  return new Response(new Uint8Array(readFileSync14(cachePath2)), {
24834
24929
  headers: { "Content-Type": "image/jpeg", "Cache-Control": "public, max-age=60" }
24835
24930
  });
@@ -24847,8 +24942,8 @@ function registerThumbnailRoutes(api, adapter2) {
24847
24942
  if (!buffer) {
24848
24943
  return c2.json({ error: "Thumbnail generation returned null" }, 500);
24849
24944
  }
24850
- if (!existsSync13(cacheDir)) mkdirSync7(cacheDir, { recursive: true });
24851
- writeFileSync7(cachePath2, buffer);
24945
+ if (!existsSync14(cacheDir)) mkdirSync8(cacheDir, { recursive: true });
24946
+ writeFileSync8(cachePath2, buffer);
24852
24947
  return new Response(new Uint8Array(buffer), {
24853
24948
  headers: { "Content-Type": "image/jpeg", "Cache-Control": "public, max-age=60" }
24854
24949
  });
@@ -24866,6 +24961,50 @@ var init_thumbnail = __esm({
24866
24961
  }
24867
24962
  });
24868
24963
 
24964
+ // ../core/src/studio-api/routes/waveform.ts
24965
+ import { existsSync as existsSync15, readFileSync as readFileSync15, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9 } from "fs";
24966
+ import { join as join18 } from "path";
24967
+ function registerWaveformRoutes(api, adapter2) {
24968
+ api.get("/projects/:id/waveform/*", async (c2) => {
24969
+ const project = await adapter2.resolveProject(c2.req.param("id"));
24970
+ if (!project) return c2.json({ error: "not found" }, 404);
24971
+ const assetPath = decodeURIComponent(
24972
+ c2.req.path.replace(`/projects/${project.id}/waveform/`, "").split("?")[0] ?? ""
24973
+ );
24974
+ const audioPath = join18(project.dir, assetPath);
24975
+ if (!existsSync15(audioPath)) return c2.json({ error: "file not found" }, 404);
24976
+ const cacheDir = join18(project.dir, ".waveform-cache");
24977
+ const cachePath2 = join18(cacheDir, buildWaveformCacheKey(assetPath));
24978
+ if (existsSync15(cachePath2)) {
24979
+ try {
24980
+ const peaks2 = JSON.parse(readFileSync15(cachePath2, "utf-8"));
24981
+ return c2.json({ peaks: peaks2 });
24982
+ } catch {
24983
+ }
24984
+ }
24985
+ let peaks;
24986
+ try {
24987
+ peaks = await decodeAudioPeaks(audioPath);
24988
+ } catch {
24989
+ return c2.json({ error: "failed to decode audio" }, 500);
24990
+ }
24991
+ try {
24992
+ mkdirSync9(cacheDir, { recursive: true });
24993
+ writeFileSync9(cachePath2, JSON.stringify(peaks));
24994
+ } catch {
24995
+ }
24996
+ return c2.json({ peaks });
24997
+ });
24998
+ }
24999
+ var init_waveform2 = __esm({
25000
+ "../core/src/studio-api/routes/waveform.ts"() {
25001
+ "use strict";
25002
+ init_waveform();
25003
+ init_mime();
25004
+ init_waveform();
25005
+ }
25006
+ });
25007
+
24869
25008
  // ../core/src/studio-api/createStudioApi.ts
24870
25009
  import { Hono } from "hono";
24871
25010
  function createStudioApi(adapter2) {
@@ -24876,6 +25015,7 @@ function createStudioApi(adapter2) {
24876
25015
  registerLintRoutes(api, adapter2);
24877
25016
  registerRenderRoutes(api, adapter2);
24878
25017
  registerThumbnailRoutes(api, adapter2);
25018
+ registerWaveformRoutes(api, adapter2);
24879
25019
  return api;
24880
25020
  }
24881
25021
  var init_createStudioApi = __esm({
@@ -24887,6 +25027,7 @@ var init_createStudioApi = __esm({
24887
25027
  init_lint2();
24888
25028
  init_render();
24889
25029
  init_thumbnail();
25030
+ init_waveform2();
24890
25031
  }
24891
25032
  });
24892
25033
 
@@ -24905,7 +25046,7 @@ var init_studio_api = __esm({
24905
25046
  "use strict";
24906
25047
  init_createStudioApi();
24907
25048
  init_safePath();
24908
- init_mime2();
25049
+ init_mime();
24909
25050
  init_subComposition();
24910
25051
  }
24911
25052
  });
@@ -24921,9 +25062,9 @@ __export(manager_exports2, {
24921
25062
  setBrowserPath: () => setBrowserPath
24922
25063
  });
24923
25064
  import { execSync } from "child_process";
24924
- import { existsSync as existsSync14, rmSync as rmSync4 } from "fs";
25065
+ import { existsSync as existsSync16, rmSync as rmSync4 } from "fs";
24925
25066
  import { homedir as homedir4 } from "os";
24926
- import { join as join17 } from "path";
25067
+ import { join as join19 } from "path";
24927
25068
  import { Browser, detectBrowserPlatform, getInstalledBrowsers, install } from "@puppeteer/browsers";
24928
25069
  function setBrowserPath(path2) {
24929
25070
  _browserPathOverride = path2;
@@ -24943,17 +25084,17 @@ function whichBinary2(name) {
24943
25084
  }
24944
25085
  }
24945
25086
  function findFromEnv2() {
24946
- if (_browserPathOverride && existsSync14(_browserPathOverride)) {
25087
+ if (_browserPathOverride && existsSync16(_browserPathOverride)) {
24947
25088
  return { executablePath: _browserPathOverride, source: "env" };
24948
25089
  }
24949
25090
  const envPath = process.env["HYPERFRAMES_BROWSER_PATH"];
24950
- if (envPath && existsSync14(envPath)) {
25091
+ if (envPath && existsSync16(envPath)) {
24951
25092
  return { executablePath: envPath, source: "env" };
24952
25093
  }
24953
25094
  return void 0;
24954
25095
  }
24955
25096
  async function findFromCache() {
24956
- if (!existsSync14(CACHE_DIR2)) {
25097
+ if (!existsSync16(CACHE_DIR2)) {
24957
25098
  return void 0;
24958
25099
  }
24959
25100
  const installed = await getInstalledBrowsers({ cacheDir: CACHE_DIR2 });
@@ -24965,7 +25106,7 @@ async function findFromCache() {
24965
25106
  }
24966
25107
  function findFromSystem2() {
24967
25108
  for (const p of SYSTEM_CHROME_PATHS) {
24968
- if (existsSync14(p)) {
25109
+ if (existsSync16(p)) {
24969
25110
  return { executablePath: p, source: "system" };
24970
25111
  }
24971
25112
  }
@@ -24999,7 +25140,7 @@ async function ensureBrowser(options) {
24999
25140
  return { executablePath: installed.executablePath, source: "download" };
25000
25141
  }
25001
25142
  function clearBrowser() {
25002
- if (!existsSync14(CACHE_DIR2)) {
25143
+ if (!existsSync16(CACHE_DIR2)) {
25003
25144
  return false;
25004
25145
  }
25005
25146
  rmSync4(CACHE_DIR2, { recursive: true, force: true });
@@ -25010,7 +25151,7 @@ var init_manager2 = __esm({
25010
25151
  "src/browser/manager.ts"() {
25011
25152
  "use strict";
25012
25153
  CHROME_VERSION = "131.0.6778.85";
25013
- CACHE_DIR2 = join17(homedir4(), ".cache", "hyperframes", "chrome");
25154
+ CACHE_DIR2 = join19(homedir4(), ".cache", "hyperframes", "chrome");
25014
25155
  SYSTEM_CHROME_PATHS = process.platform === "darwin" ? ["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"] : [
25015
25156
  "/usr/bin/google-chrome",
25016
25157
  "/usr/bin/google-chrome-stable",
@@ -25137,8 +25278,8 @@ var init_config2 = __esm({
25137
25278
  });
25138
25279
 
25139
25280
  // ../engine/src/services/browserManager.ts
25140
- import { existsSync as existsSync15, readdirSync as readdirSync6 } from "fs";
25141
- import { join as join18 } from "path";
25281
+ import { existsSync as existsSync17, readdirSync as readdirSync6 } from "fs";
25282
+ import { join as join20 } from "path";
25142
25283
  import { homedir as homedir5 } from "os";
25143
25284
  async function getPuppeteer() {
25144
25285
  if (_puppeteer) return _puppeteer;
@@ -25159,19 +25300,19 @@ function resolveHeadlessShellPath(config) {
25159
25300
  if (process.env.PRODUCER_HEADLESS_SHELL_PATH) {
25160
25301
  return process.env.PRODUCER_HEADLESS_SHELL_PATH;
25161
25302
  }
25162
- const baseDir = join18(homedir5(), ".cache", "puppeteer", "chrome-headless-shell");
25163
- if (!existsSync15(baseDir)) return void 0;
25303
+ const baseDir = join20(homedir5(), ".cache", "puppeteer", "chrome-headless-shell");
25304
+ if (!existsSync17(baseDir)) return void 0;
25164
25305
  try {
25165
25306
  const versions = readdirSync6(baseDir).sort().reverse();
25166
25307
  for (const version of versions) {
25167
25308
  const candidates = [
25168
- join18(baseDir, version, "chrome-headless-shell-linux64", "chrome-headless-shell"),
25169
- join18(baseDir, version, "chrome-headless-shell-mac-arm64", "chrome-headless-shell"),
25170
- join18(baseDir, version, "chrome-headless-shell-mac-x64", "chrome-headless-shell"),
25171
- join18(baseDir, version, "chrome-headless-shell-win64", "chrome-headless-shell.exe")
25309
+ join20(baseDir, version, "chrome-headless-shell-linux64", "chrome-headless-shell"),
25310
+ join20(baseDir, version, "chrome-headless-shell-mac-arm64", "chrome-headless-shell"),
25311
+ join20(baseDir, version, "chrome-headless-shell-mac-x64", "chrome-headless-shell"),
25312
+ join20(baseDir, version, "chrome-headless-shell-win64", "chrome-headless-shell.exe")
25172
25313
  ];
25173
25314
  for (const binary of candidates) {
25174
- if (existsSync15(binary)) return binary;
25315
+ if (existsSync17(binary)) return binary;
25175
25316
  }
25176
25317
  }
25177
25318
  } catch {
@@ -25634,10 +25775,10 @@ var init_screenshotService = __esm({
25634
25775
  });
25635
25776
 
25636
25777
  // ../engine/src/services/frameCapture.ts
25637
- import { existsSync as existsSync16, mkdirSync as mkdirSync8, writeFileSync as writeFileSync8 } from "fs";
25638
- import { join as join19 } from "path";
25778
+ import { existsSync as existsSync18, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
25779
+ import { join as join21 } from "path";
25639
25780
  async function createCaptureSession(serverUrl, outputDir, options, onBeforeCapture = null, config) {
25640
- if (!existsSync16(outputDir)) mkdirSync8(outputDir, { recursive: true });
25781
+ if (!existsSync18(outputDir)) mkdirSync10(outputDir, { recursive: true });
25641
25782
  const headlessShell = resolveHeadlessShellPath(config);
25642
25783
  const isLinux = process.platform === "linux";
25643
25784
  const forceScreenshot = config?.forceScreenshot ?? DEFAULT_CONFIG2.forceScreenshot;
@@ -25841,13 +25982,13 @@ async function initializeSession(session) {
25841
25982
  }
25842
25983
  async function captureFrameErrorDiagnostics(session, frameIndex, time, error) {
25843
25984
  try {
25844
- const diagnosticsDir = join19(session.outputDir, "diagnostics");
25845
- if (!existsSync16(diagnosticsDir)) mkdirSync8(diagnosticsDir, { recursive: true });
25846
- const base = join19(diagnosticsDir, `frame-error-${frameIndex}`);
25985
+ const diagnosticsDir = join21(session.outputDir, "diagnostics");
25986
+ if (!existsSync18(diagnosticsDir)) mkdirSync10(diagnosticsDir, { recursive: true });
25987
+ const base = join21(diagnosticsDir, `frame-error-${frameIndex}`);
25847
25988
  await session.page.screenshot({ path: `${base}.png`, type: "png", fullPage: true });
25848
25989
  const html = await session.page.content();
25849
- writeFileSync8(`${base}.html`, html, "utf-8");
25850
- writeFileSync8(
25990
+ writeFileSync10(`${base}.html`, html, "utf-8");
25991
+ writeFileSync10(
25851
25992
  `${base}.json`,
25852
25993
  JSON.stringify(
25853
25994
  {
@@ -25941,8 +26082,8 @@ async function captureFrame(session, frameIndex, time) {
25941
26082
  );
25942
26083
  const ext = options.format === "png" ? "png" : "jpg";
25943
26084
  const frameName = `frame_${String(frameIndex).padStart(6, "0")}.${ext}`;
25944
- const framePath = join19(outputDir, frameName);
25945
- writeFileSync8(framePath, buffer);
26085
+ const framePath = join21(outputDir, frameName);
26086
+ writeFileSync10(framePath, buffer);
25946
26087
  return { frameIndex, time: quantizedTime, path: framePath, captureTimeMs };
25947
26088
  }
25948
26089
  async function captureFrameToBuffer(session, frameIndex, time) {
@@ -25962,8 +26103,8 @@ async function closeCaptureSession(session) {
25962
26103
  session.isInitialized = false;
25963
26104
  }
25964
26105
  function prepareCaptureSessionForReuse(session, outputDir, onBeforeCapture) {
25965
- if (!existsSync16(outputDir)) {
25966
- mkdirSync8(outputDir, { recursive: true });
26106
+ if (!existsSync18(outputDir)) {
26107
+ mkdirSync10(outputDir, { recursive: true });
25967
26108
  }
25968
26109
  session.outputDir = outputDir;
25969
26110
  session.onBeforeCapture = onBeforeCapture;
@@ -26006,10 +26147,10 @@ var init_frameCapture = __esm({
26006
26147
  });
26007
26148
 
26008
26149
  // ../engine/src/utils/gpuEncoder.ts
26009
- import { spawn as spawn2 } from "child_process";
26150
+ import { spawn as spawn3 } from "child_process";
26010
26151
  async function detectGpuEncoder() {
26011
26152
  return new Promise((resolve39) => {
26012
- const ffmpeg = spawn2("ffmpeg", ["-encoders"], {
26153
+ const ffmpeg = spawn3("ffmpeg", ["-encoders"], {
26013
26154
  stdio: ["pipe", "pipe", "pipe"]
26014
26155
  });
26015
26156
  let stdout2 = "";
@@ -26129,7 +26270,7 @@ var init_hdr = __esm({
26129
26270
  });
26130
26271
 
26131
26272
  // ../engine/src/utils/runFfmpeg.ts
26132
- import { spawn as spawn3 } from "child_process";
26273
+ import { spawn as spawn4 } from "child_process";
26133
26274
  function formatFfmpegError(exitCode, stderr, tailLines = DEFAULT_STDERR_TAIL_LINES) {
26134
26275
  const tail = (stderr ?? "").split(/\r?\n/).filter((line) => line.length > 0).slice(-tailLines).join("\n");
26135
26276
  if (exitCode === null) {
@@ -26145,7 +26286,7 @@ async function runFfmpeg(args, opts) {
26145
26286
  const timeout = opts?.timeout ?? DEFAULT_TIMEOUT;
26146
26287
  const onStderr = opts?.onStderr;
26147
26288
  return new Promise((resolve39) => {
26148
- const ffmpeg = spawn3("ffmpeg", args);
26289
+ const ffmpeg = spawn4("ffmpeg", args);
26149
26290
  let stderr = "";
26150
26291
  const onAbort = () => {
26151
26292
  ffmpeg.kill("SIGTERM");
@@ -26199,9 +26340,9 @@ var init_runFfmpeg = __esm({
26199
26340
  });
26200
26341
 
26201
26342
  // ../engine/src/services/chunkEncoder.ts
26202
- import { spawn as spawn4 } from "child_process";
26203
- import { copyFileSync, existsSync as existsSync17, mkdirSync as mkdirSync9, readdirSync as readdirSync7, statSync as statSync4, writeFileSync as writeFileSync9 } from "fs";
26204
- import { join as join20, dirname as dirname6 } from "path";
26343
+ import { spawn as spawn5 } from "child_process";
26344
+ import { copyFileSync, existsSync as existsSync19, mkdirSync as mkdirSync11, readdirSync as readdirSync7, statSync as statSync4, writeFileSync as writeFileSync11 } from "fs";
26345
+ import { join as join22, dirname as dirname6 } from "path";
26205
26346
  function getEncoderPreset(quality, format = "mp4", hdr) {
26206
26347
  const base = ENCODER_PRESETS[quality];
26207
26348
  if (format === "webm") {
@@ -26352,7 +26493,7 @@ function buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder = null) {
26352
26493
  async function encodeFramesFromDir(framesDir, framePattern, outputPath, options, signal, config) {
26353
26494
  const startTime = Date.now();
26354
26495
  const outputDir = dirname6(outputPath);
26355
- if (!existsSync17(outputDir)) mkdirSync9(outputDir, { recursive: true });
26496
+ if (!existsSync19(outputDir)) mkdirSync11(outputDir, { recursive: true });
26356
26497
  const files = readdirSync7(framesDir).filter((f3) => f3.match(/\.(jpg|jpeg|png)$/i));
26357
26498
  const frameCount = files.length;
26358
26499
  if (frameCount === 0) {
@@ -26369,11 +26510,11 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
26369
26510
  if (options.useGpu) {
26370
26511
  gpuEncoder = await getCachedGpuEncoder();
26371
26512
  }
26372
- const inputPath = join20(framesDir, framePattern);
26513
+ const inputPath = join22(framesDir, framePattern);
26373
26514
  const inputArgs = ["-framerate", String(options.fps), "-i", inputPath];
26374
26515
  const args = buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder);
26375
26516
  return new Promise((resolve39) => {
26376
- const ffmpeg = spawn4("ffmpeg", args);
26517
+ const ffmpeg = spawn5("ffmpeg", args);
26377
26518
  let stderr = "";
26378
26519
  const onAbort = () => {
26379
26520
  ffmpeg.kill("SIGTERM");
@@ -26418,7 +26559,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
26418
26559
  });
26419
26560
  return;
26420
26561
  }
26421
- const fileSize = existsSync17(outputPath) ? statSync4(outputPath).size : 0;
26562
+ const fileSize = existsSync19(outputPath) ? statSync4(outputPath).size : 0;
26422
26563
  resolve39({ success: true, outputPath, durationMs, framesEncoded: frameCount, fileSize });
26423
26564
  });
26424
26565
  ffmpeg.on("error", (err) => {
@@ -26450,8 +26591,8 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
26450
26591
  }
26451
26592
  const chunkSize = Math.max(30, Math.floor(chunkSizeFrames));
26452
26593
  const chunkCount = Math.ceil(files.length / chunkSize);
26453
- const chunkDir = join20(dirname6(outputPath), "chunk-encode");
26454
- if (!existsSync17(chunkDir)) mkdirSync9(chunkDir, { recursive: true });
26594
+ const chunkDir = join22(dirname6(outputPath), "chunk-encode");
26595
+ if (!existsSync19(chunkDir)) mkdirSync11(chunkDir, { recursive: true });
26455
26596
  const chunkPaths = [];
26456
26597
  for (let i2 = 0; i2 < chunkCount; i2++) {
26457
26598
  if (signal?.aborted) {
@@ -26467,8 +26608,8 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
26467
26608
  const startNumber = i2 * chunkSize;
26468
26609
  const framesInChunk = Math.min(chunkSize, files.length - startNumber);
26469
26610
  const ext = outputPath.endsWith(".webm") ? ".webm" : outputPath.endsWith(".mov") ? ".mov" : ".mp4";
26470
- const chunkPath = join20(chunkDir, `chunk_${String(i2).padStart(4, "0")}${ext}`);
26471
- const inputPath = join20(framesDir, framePattern);
26611
+ const chunkPath = join22(chunkDir, `chunk_${String(i2).padStart(4, "0")}${ext}`);
26612
+ const inputPath = join22(framesDir, framePattern);
26472
26613
  const inputArgs = [
26473
26614
  "-framerate",
26474
26615
  String(options.fps),
@@ -26483,7 +26624,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
26483
26624
  if (options.useGpu) gpuEncoder = await getCachedGpuEncoder();
26484
26625
  const args = buildEncoderArgs(options, inputArgs, chunkPath, gpuEncoder);
26485
26626
  const chunkResult = await new Promise((resolve39) => {
26486
- const ffmpeg = spawn4("ffmpeg", args);
26627
+ const ffmpeg = spawn5("ffmpeg", args);
26487
26628
  let stderr = "";
26488
26629
  ffmpeg.stderr.on("data", (d) => {
26489
26630
  stderr += d.toString();
@@ -26508,9 +26649,9 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
26508
26649
  }
26509
26650
  chunkPaths.push(chunkPath);
26510
26651
  }
26511
- const concatListPath = join20(chunkDir, "concat-list.txt");
26652
+ const concatListPath = join22(chunkDir, "concat-list.txt");
26512
26653
  const concatInput = chunkPaths.map((path2) => `file '${path2.replace(/'/g, "'\\''")}'`).join("\n");
26513
- writeFileSync9(concatListPath, concatInput, "utf-8");
26654
+ writeFileSync11(concatListPath, concatInput, "utf-8");
26514
26655
  const concatArgs = [
26515
26656
  "-f",
26516
26657
  "concat",
@@ -26524,7 +26665,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
26524
26665
  outputPath
26525
26666
  ];
26526
26667
  const concatResult = await new Promise((resolve39) => {
26527
- const ffmpeg = spawn4("ffmpeg", concatArgs);
26668
+ const ffmpeg = spawn5("ffmpeg", concatArgs);
26528
26669
  let stderr = "";
26529
26670
  ffmpeg.stderr.on("data", (d) => {
26530
26671
  stderr += d.toString();
@@ -26547,7 +26688,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
26547
26688
  error: concatResult.error
26548
26689
  };
26549
26690
  }
26550
- const fileSize = existsSync17(outputPath) ? statSync4(outputPath).size : 0;
26691
+ const fileSize = existsSync19(outputPath) ? statSync4(outputPath).size : 0;
26551
26692
  return {
26552
26693
  success: true,
26553
26694
  outputPath,
@@ -26558,7 +26699,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
26558
26699
  }
26559
26700
  async function muxVideoWithAudio(videoPath, audioPath, outputPath, signal, config) {
26560
26701
  const outputDir = dirname6(outputPath);
26561
- if (!existsSync17(outputDir)) mkdirSync9(outputDir, { recursive: true });
26702
+ if (!existsSync19(outputDir)) mkdirSync11(outputDir, { recursive: true });
26562
26703
  const isWebm = outputPath.endsWith(".webm");
26563
26704
  const isMov = outputPath.endsWith(".mov");
26564
26705
  const args = ["-i", videoPath, "-i", audioPath, "-c:v", "copy"];
@@ -26628,8 +26769,8 @@ var init_chunkEncoder = __esm({
26628
26769
  });
26629
26770
 
26630
26771
  // ../engine/src/services/streamingEncoder.ts
26631
- import { spawn as spawn5 } from "child_process";
26632
- import { existsSync as existsSync18, mkdirSync as mkdirSync10, statSync as statSync5 } from "fs";
26772
+ import { spawn as spawn6 } from "child_process";
26773
+ import { existsSync as existsSync20, mkdirSync as mkdirSync12, statSync as statSync5 } from "fs";
26633
26774
  import { dirname as dirname7 } from "path";
26634
26775
  function createFrameReorderBuffer(startFrame, endFrame) {
26635
26776
  let cursor = startFrame;
@@ -26812,14 +26953,14 @@ function buildStreamingArgs(options, outputPath, gpuEncoder = null) {
26812
26953
  }
26813
26954
  async function spawnStreamingEncoder(outputPath, options, signal, config) {
26814
26955
  const outputDir = dirname7(outputPath);
26815
- if (!existsSync18(outputDir)) mkdirSync10(outputDir, { recursive: true });
26956
+ if (!existsSync20(outputDir)) mkdirSync12(outputDir, { recursive: true });
26816
26957
  let gpuEncoder = null;
26817
26958
  if (options.useGpu) {
26818
26959
  gpuEncoder = await getCachedGpuEncoder();
26819
26960
  }
26820
26961
  const args = buildStreamingArgs(options, outputPath, gpuEncoder);
26821
26962
  const startTime = Date.now();
26822
- const ffmpeg = spawn5("ffmpeg", args, {
26963
+ const ffmpeg = spawn6("ffmpeg", args, {
26823
26964
  stdio: ["pipe", "pipe", "pipe"]
26824
26965
  });
26825
26966
  let exitStatus = "running";
@@ -26894,7 +27035,7 @@ Process error: ${err.message}`;
26894
27035
  error: formatFfmpegError(exitCode, stderr)
26895
27036
  };
26896
27037
  }
26897
- const fileSize = existsSync18(outputPath) ? statSync5(outputPath).size : 0;
27038
+ const fileSize = existsSync20(outputPath) ? statSync5(outputPath).size : 0;
26898
27039
  return { success: true, durationMs, fileSize };
26899
27040
  },
26900
27041
  getExitStatus: () => exitStatus
@@ -26912,12 +27053,12 @@ var init_streamingEncoder = __esm({
26912
27053
  });
26913
27054
 
26914
27055
  // ../engine/src/utils/ffprobe.ts
26915
- import { spawn as spawn6 } from "child_process";
26916
- import { readFileSync as readFileSync15 } from "fs";
27056
+ import { spawn as spawn7 } from "child_process";
27057
+ import { readFileSync as readFileSync16 } from "fs";
26917
27058
  import { extname as extname4 } from "path";
26918
27059
  function runFfprobe(args) {
26919
27060
  return new Promise((resolve39, reject) => {
26920
- const proc = spawn6("ffprobe", args);
27061
+ const proc = spawn7("ffprobe", args);
26921
27062
  let stdout2 = "";
26922
27063
  let stderr = "";
26923
27064
  proc.stdout.on("data", (data) => {
@@ -27007,7 +27148,7 @@ function extractPngMetadataFromBuffer(buf) {
27007
27148
  function extractStillImageMetadata(filePath) {
27008
27149
  if (extname4(filePath).toLowerCase() !== ".png") return null;
27009
27150
  try {
27010
- return extractPngMetadataFromBuffer(readFileSync15(filePath));
27151
+ return extractPngMetadataFromBuffer(readFileSync16(filePath));
27011
27152
  } catch {
27012
27153
  return null;
27013
27154
  }
@@ -27186,9 +27327,9 @@ var init_ffprobe = __esm({
27186
27327
  });
27187
27328
 
27188
27329
  // ../engine/src/utils/urlDownloader.ts
27189
- import { createWriteStream as createWriteStream2, existsSync as existsSync19, mkdirSync as mkdirSync11 } from "fs";
27330
+ import { createWriteStream as createWriteStream2, existsSync as existsSync21, mkdirSync as mkdirSync13 } from "fs";
27190
27331
  import { createHash } from "crypto";
27191
- import { join as join21, extname as extname5 } from "path";
27332
+ import { join as join23, extname as extname5 } from "path";
27192
27333
  import { Readable } from "stream";
27193
27334
  import { finished } from "stream/promises";
27194
27335
  function getFilenameFromUrl(url) {
@@ -27199,19 +27340,19 @@ function getFilenameFromUrl(url) {
27199
27340
  }
27200
27341
  async function downloadToTemp(url, destDir, timeoutMs = 3e5) {
27201
27342
  const cachedPath = downloadPathCache.get(url);
27202
- if (cachedPath && existsSync19(cachedPath)) {
27343
+ if (cachedPath && existsSync21(cachedPath)) {
27203
27344
  return cachedPath;
27204
27345
  }
27205
27346
  const inFlight = inFlightDownloads.get(url);
27206
27347
  if (inFlight) {
27207
27348
  return inFlight;
27208
27349
  }
27209
- if (!existsSync19(destDir)) {
27210
- mkdirSync11(destDir, { recursive: true });
27350
+ if (!existsSync21(destDir)) {
27351
+ mkdirSync13(destDir, { recursive: true });
27211
27352
  }
27212
27353
  const filename = getFilenameFromUrl(url);
27213
- const localPath = join21(destDir, filename);
27214
- if (existsSync19(localPath)) {
27354
+ const localPath = join23(destDir, filename);
27355
+ if (existsSync21(localPath)) {
27215
27356
  downloadPathCache.set(url, localPath);
27216
27357
  return localPath;
27217
27358
  }
@@ -27303,9 +27444,9 @@ var init_htmlTemplate = __esm({
27303
27444
 
27304
27445
  // ../engine/src/services/extractionCache.ts
27305
27446
  import { createHash as createHash2 } from "crypto";
27306
- import { mkdirSync as mkdirSync12, readdirSync as readdirSync8, statSync as statSync6, writeFileSync as writeFileSync10 } from "fs";
27307
- import { existsSync as existsSync20 } from "fs";
27308
- import { join as join22 } from "path";
27447
+ import { mkdirSync as mkdirSync14, readdirSync as readdirSync8, statSync as statSync6, writeFileSync as writeFileSync12 } from "fs";
27448
+ import { existsSync as existsSync22 } from "fs";
27449
+ import { join as join24 } from "path";
27309
27450
  function readKeyStat(videoPath) {
27310
27451
  try {
27311
27452
  const stat3 = statSync6(videoPath);
@@ -27334,15 +27475,15 @@ function cacheEntryDirName(keyHash) {
27334
27475
  }
27335
27476
  function lookupCacheEntry(rootDir, input) {
27336
27477
  const keyHash = computeCacheKey(input);
27337
- const dir = join22(rootDir, cacheEntryDirName(keyHash));
27338
- const complete = existsSync20(join22(dir, COMPLETE_SENTINEL));
27478
+ const dir = join24(rootDir, cacheEntryDirName(keyHash));
27479
+ const complete = existsSync22(join24(dir, COMPLETE_SENTINEL));
27339
27480
  return { entry: { dir, keyHash }, hit: complete };
27340
27481
  }
27341
27482
  function ensureCacheEntryDir(entry) {
27342
- mkdirSync12(entry.dir, { recursive: true });
27483
+ mkdirSync14(entry.dir, { recursive: true });
27343
27484
  }
27344
27485
  function markCacheEntryComplete(entry) {
27345
- writeFileSync10(join22(entry.dir, COMPLETE_SENTINEL), "", "utf-8");
27486
+ writeFileSync12(join24(entry.dir, COMPLETE_SENTINEL), "", "utf-8");
27346
27487
  }
27347
27488
  function rehydrateCacheEntry(entry, options) {
27348
27489
  const framePattern = `${FRAME_FILENAME_PREFIX}%05d.${options.format}`;
@@ -27350,7 +27491,7 @@ function rehydrateCacheEntry(entry, options) {
27350
27491
  const suffix = `.${options.format}`;
27351
27492
  const files = readdirSync8(entry.dir).filter((f3) => f3.startsWith(FRAME_FILENAME_PREFIX) && f3.endsWith(suffix)).sort();
27352
27493
  files.forEach((file, idx) => {
27353
- framePaths.set(idx, join22(entry.dir, file));
27494
+ framePaths.set(idx, join24(entry.dir, file));
27354
27495
  });
27355
27496
  return {
27356
27497
  videoId: options.videoId,
@@ -27375,9 +27516,9 @@ var init_extractionCache = __esm({
27375
27516
  });
27376
27517
 
27377
27518
  // ../engine/src/services/videoFrameExtractor.ts
27378
- import { spawn as spawn7 } from "child_process";
27379
- import { existsSync as existsSync21, mkdirSync as mkdirSync13, readdirSync as readdirSync9, rmSync as rmSync5 } from "fs";
27380
- import { isAbsolute as isAbsolute2, join as join23 } from "path";
27519
+ import { spawn as spawn8 } from "child_process";
27520
+ import { existsSync as existsSync23, mkdirSync as mkdirSync15, readdirSync as readdirSync9, rmSync as rmSync5 } from "fs";
27521
+ import { isAbsolute as isAbsolute2, join as join25 } from "path";
27381
27522
  function parseVideoElements(html) {
27382
27523
  const videos = [];
27383
27524
  const { document: document2 } = parseHTML(unwrapTemplate(html));
@@ -27447,12 +27588,12 @@ function parseImageElements(html) {
27447
27588
  async function extractVideoFramesRange(videoPath, videoId, startTime, duration, options, signal, config, outputDirOverride) {
27448
27589
  const ffmpegProcessTimeout = config?.ffmpegProcessTimeout ?? DEFAULT_CONFIG2.ffmpegProcessTimeout;
27449
27590
  const { fps, outputDir, quality = 95 } = options;
27450
- const videoOutputDir = outputDirOverride ?? join23(outputDir, videoId);
27451
- if (!existsSync21(videoOutputDir)) mkdirSync13(videoOutputDir, { recursive: true });
27591
+ const videoOutputDir = outputDirOverride ?? join25(outputDir, videoId);
27592
+ if (!existsSync23(videoOutputDir)) mkdirSync15(videoOutputDir, { recursive: true });
27452
27593
  const metadata = await extractMediaMetadata(videoPath);
27453
27594
  const format = resolveFrameFormat(metadata, options.format);
27454
27595
  const framePattern = `${FRAME_FILENAME_PREFIX}%05d.${format}`;
27455
- const outputPattern = join23(videoOutputDir, framePattern);
27596
+ const outputPattern = join25(videoOutputDir, framePattern);
27456
27597
  const isHdr = isHdrColorSpace(metadata.colorSpace);
27457
27598
  const isMacOS = process.platform === "darwin";
27458
27599
  const args = [];
@@ -27473,7 +27614,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
27473
27614
  if (format === "png") args.push("-compression_level", "6");
27474
27615
  args.push("-y", outputPattern);
27475
27616
  return new Promise((resolve39, reject) => {
27476
- const ffmpeg = spawn7("ffmpeg", args);
27617
+ const ffmpeg = spawn8("ffmpeg", args);
27477
27618
  let stderr = "";
27478
27619
  const onAbort = () => {
27479
27620
  ffmpeg.kill("SIGTERM");
@@ -27505,7 +27646,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
27505
27646
  const framePaths = /* @__PURE__ */ new Map();
27506
27647
  const files = readdirSync9(videoOutputDir).filter((f3) => f3.startsWith(FRAME_FILENAME_PREFIX) && f3.endsWith(`.${format}`)).sort();
27507
27648
  files.forEach((file, index) => {
27508
- framePaths.set(index, join23(videoOutputDir, file));
27649
+ framePaths.set(index, join25(videoOutputDir, file));
27509
27650
  });
27510
27651
  resolve39({
27511
27652
  videoId,
@@ -27632,15 +27773,15 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
27632
27773
  try {
27633
27774
  let videoPath = video.src;
27634
27775
  if (!isAbsolute2(videoPath) && !isHttpUrl(videoPath)) {
27635
- const fromCompiled = compiledDir ? join23(compiledDir, videoPath) : null;
27636
- videoPath = fromCompiled && existsSync21(fromCompiled) ? fromCompiled : join23(baseDir, videoPath);
27776
+ const fromCompiled = compiledDir ? join25(compiledDir, videoPath) : null;
27777
+ videoPath = fromCompiled && existsSync23(fromCompiled) ? fromCompiled : join25(baseDir, videoPath);
27637
27778
  }
27638
27779
  if (isHttpUrl(videoPath)) {
27639
- const downloadDir = join23(options.outputDir, "_downloads");
27640
- mkdirSync13(downloadDir, { recursive: true });
27780
+ const downloadDir = join25(options.outputDir, "_downloads");
27781
+ mkdirSync15(downloadDir, { recursive: true });
27641
27782
  videoPath = await downloadToTemp(videoPath, downloadDir);
27642
27783
  }
27643
- if (!existsSync21(videoPath)) {
27784
+ if (!existsSync23(videoPath)) {
27644
27785
  errors.push({ videoId: video.id, error: `Video file not found: ${videoPath}` });
27645
27786
  continue;
27646
27787
  }
@@ -27673,8 +27814,8 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
27673
27814
  const hdrSkippedIndices = /* @__PURE__ */ new Set();
27674
27815
  if (hdrInfo.hasHdr && hdrInfo.dominantTransfer) {
27675
27816
  const targetTransfer = hdrInfo.dominantTransfer;
27676
- const convertDir = join23(options.outputDir, "_hdr_normalized");
27677
- mkdirSync13(convertDir, { recursive: true });
27817
+ const convertDir = join25(options.outputDir, "_hdr_normalized");
27818
+ mkdirSync15(convertDir, { recursive: true });
27678
27819
  for (let i2 = 0; i2 < resolvedVideos.length; i2++) {
27679
27820
  if (signal?.aborted) break;
27680
27821
  const cs = videoColorSpaces[i2] ?? null;
@@ -27695,7 +27836,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
27695
27836
  const sourceRemaining = metadata.durationSeconds - entry.video.mediaStart;
27696
27837
  segDuration = sourceRemaining > 0 ? sourceRemaining : metadata.durationSeconds;
27697
27838
  }
27698
- const convertedPath = join23(convertDir, `${entry.video.id}_hdr.mp4`);
27839
+ const convertedPath = join25(convertDir, `${entry.video.id}_hdr.mp4`);
27699
27840
  try {
27700
27841
  await convertSdrToHdr(
27701
27842
  entry.videoPath,
@@ -27730,7 +27871,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
27730
27871
  }
27731
27872
  }
27732
27873
  const vfrPreflightStart = Date.now();
27733
- const vfrNormDir = join23(options.outputDir, "_vfr_normalized");
27874
+ const vfrNormDir = join25(options.outputDir, "_vfr_normalized");
27734
27875
  for (let i2 = 0; i2 < resolvedVideos.length; i2++) {
27735
27876
  if (signal?.aborted) break;
27736
27877
  const entry = resolvedVideos[i2];
@@ -27744,8 +27885,8 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
27744
27885
  const sourceRemaining = metadata.durationSeconds - entry.video.mediaStart;
27745
27886
  segDuration = sourceRemaining > 0 ? sourceRemaining : metadata.durationSeconds;
27746
27887
  }
27747
- mkdirSync13(vfrNormDir, { recursive: true });
27748
- const normalizedPath = join23(vfrNormDir, `${entry.video.id}_cfr.mp4`);
27888
+ mkdirSync15(vfrNormDir, { recursive: true });
27889
+ const normalizedPath = join25(vfrNormDir, `${entry.video.id}_cfr.mp4`);
27749
27890
  try {
27750
27891
  await convertVfrToCfr(
27751
27892
  entry.videoPath,
@@ -28001,7 +28142,7 @@ var init_videoFrameExtractor = __esm({
28001
28142
  cleanup() {
28002
28143
  for (const video of this.videos.values()) {
28003
28144
  if (video.extracted.ownedByLookup) continue;
28004
- if (existsSync21(video.extracted.outputDir)) {
28145
+ if (existsSync23(video.extracted.outputDir)) {
28005
28146
  rmSync5(video.extracted.outputDir, { recursive: true, force: true });
28006
28147
  }
28007
28148
  }
@@ -28309,8 +28450,8 @@ var init_videoFrameInjector = __esm({
28309
28450
  });
28310
28451
 
28311
28452
  // ../engine/src/services/audioMixer.ts
28312
- import { existsSync as existsSync22, mkdirSync as mkdirSync14, rmSync as rmSync6 } from "fs";
28313
- import { isAbsolute as isAbsolute3, join as join24, dirname as dirname8 } from "path";
28453
+ import { existsSync as existsSync24, mkdirSync as mkdirSync16, rmSync as rmSync6 } from "fs";
28454
+ import { isAbsolute as isAbsolute3, join as join26, dirname as dirname8 } from "path";
28314
28455
  function parseAudioElements(html) {
28315
28456
  const elements = [];
28316
28457
  const { document: document2 } = parseHTML(unwrapTemplate(html));
@@ -28361,7 +28502,7 @@ function parseAudioElements(html) {
28361
28502
  async function extractAudioFromVideo(videoPath, outputPath, options, signal, config) {
28362
28503
  const ffmpegProcessTimeout = config?.ffmpegProcessTimeout ?? DEFAULT_CONFIG2.ffmpegProcessTimeout;
28363
28504
  const outputDir = dirname8(outputPath);
28364
- if (!existsSync22(outputDir)) mkdirSync14(outputDir, { recursive: true });
28505
+ if (!existsSync24(outputDir)) mkdirSync16(outputDir, { recursive: true });
28365
28506
  const args = ["-i", videoPath];
28366
28507
  if (options?.startTime !== void 0) args.push("-ss", String(options.startTime));
28367
28508
  if (options?.duration !== void 0) args.push("-t", String(options.duration));
@@ -28388,7 +28529,7 @@ async function extractAudioFromVideo(videoPath, outputPath, options, signal, con
28388
28529
  async function prepareAudioTrack(srcPath, outputPath, mediaStart, duration, signal, config) {
28389
28530
  const ffmpegProcessTimeout = config?.ffmpegProcessTimeout ?? DEFAULT_CONFIG2.ffmpegProcessTimeout;
28390
28531
  const outputDir = dirname8(outputPath);
28391
- if (!existsSync22(outputDir)) mkdirSync14(outputDir, { recursive: true });
28532
+ if (!existsSync24(outputDir)) mkdirSync16(outputDir, { recursive: true });
28392
28533
  const args = [
28393
28534
  "-ss",
28394
28535
  String(mediaStart),
@@ -28424,7 +28565,7 @@ async function prepareAudioTrack(srcPath, outputPath, mediaStart, duration, sign
28424
28565
  async function generateSilence(outputPath, duration, signal, config) {
28425
28566
  const ffmpegProcessTimeout = config?.ffmpegProcessTimeout ?? DEFAULT_CONFIG2.ffmpegProcessTimeout;
28426
28567
  const outputDir = dirname8(outputPath);
28427
- if (!existsSync22(outputDir)) mkdirSync14(outputDir, { recursive: true });
28568
+ if (!existsSync24(outputDir)) mkdirSync16(outputDir, { recursive: true });
28428
28569
  const args = [
28429
28570
  "-f",
28430
28571
  "lavfi",
@@ -28467,7 +28608,7 @@ async function mixAudioTracks(tracks, outputPath, totalDuration, signal, config)
28467
28608
  };
28468
28609
  }
28469
28610
  const outputDir = dirname8(outputPath);
28470
- if (!existsSync22(outputDir)) mkdirSync14(outputDir, { recursive: true });
28611
+ if (!existsSync24(outputDir)) mkdirSync16(outputDir, { recursive: true });
28471
28612
  const inputs = [];
28472
28613
  const filterParts = [];
28473
28614
  tracks.forEach((track, i2) => {
@@ -28528,7 +28669,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
28528
28669
  const startMs = Date.now();
28529
28670
  const tracks = [];
28530
28671
  const errors = [];
28531
- if (!existsSync22(workDir)) mkdirSync14(workDir, { recursive: true });
28672
+ if (!existsSync24(workDir)) mkdirSync16(workDir, { recursive: true });
28532
28673
  await Promise.all(
28533
28674
  elements.map(async (element) => {
28534
28675
  if (signal?.aborted) {
@@ -28538,8 +28679,8 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
28538
28679
  try {
28539
28680
  let srcPath = element.src;
28540
28681
  if (!isAbsolute3(srcPath) && !isHttpUrl(srcPath)) {
28541
- const fromCompiled = compiledDir ? join24(compiledDir, srcPath) : null;
28542
- srcPath = fromCompiled && existsSync22(fromCompiled) ? fromCompiled : join24(baseDir, srcPath);
28682
+ const fromCompiled = compiledDir ? join26(compiledDir, srcPath) : null;
28683
+ srcPath = fromCompiled && existsSync24(fromCompiled) ? fromCompiled : join26(baseDir, srcPath);
28543
28684
  }
28544
28685
  if (isHttpUrl(srcPath)) {
28545
28686
  try {
@@ -28551,7 +28692,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
28551
28692
  return;
28552
28693
  }
28553
28694
  }
28554
- if (!existsSync22(srcPath)) {
28695
+ if (!existsSync24(srcPath)) {
28555
28696
  errors.push(`Source not found: ${element.id} (${element.src})`);
28556
28697
  return;
28557
28698
  }
@@ -28562,7 +28703,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
28562
28703
  }
28563
28704
  let audioSrcPath = srcPath;
28564
28705
  if (element.type === "video") {
28565
- const extractedPath = join24(workDir, `${element.id}-extracted.wav`);
28706
+ const extractedPath = join26(workDir, `${element.id}-extracted.wav`);
28566
28707
  const extractResult = await extractAudioFromVideo(
28567
28708
  srcPath,
28568
28709
  extractedPath,
@@ -28579,7 +28720,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
28579
28720
  }
28580
28721
  audioSrcPath = extractedPath;
28581
28722
  } else {
28582
- const trimmedPath = join24(workDir, `${element.id}-trimmed.wav`);
28723
+ const trimmedPath = join26(workDir, `${element.id}-trimmed.wav`);
28583
28724
  const prepResult = await prepareAudioTrack(
28584
28725
  srcPath,
28585
28726
  trimmedPath,
@@ -28633,9 +28774,9 @@ var init_audioMixer = __esm({
28633
28774
 
28634
28775
  // ../engine/src/services/parallelCoordinator.ts
28635
28776
  import { cpus as cpus2, freemem, totalmem as totalmem2 } from "os";
28636
- import { existsSync as existsSync23, mkdirSync as mkdirSync15, readdirSync as readdirSync10 } from "fs";
28777
+ import { existsSync as existsSync25, mkdirSync as mkdirSync17, readdirSync as readdirSync10 } from "fs";
28637
28778
  import { copyFile, rename } from "fs/promises";
28638
- import { join as join25 } from "path";
28779
+ import { join as join27 } from "path";
28639
28780
  function calculateOptimalWorkers(totalFrames, requested, config) {
28640
28781
  const effectiveMaxWorkers = (() => {
28641
28782
  const concurrency = config?.concurrency ?? DEFAULT_CONFIG2.concurrency;
@@ -28678,7 +28819,7 @@ function distributeFrames(totalFrames, workerCount, workDir) {
28678
28819
  workerId: i2,
28679
28820
  startFrame,
28680
28821
  endFrame,
28681
- outputDir: join25(workDir, `worker-${i2}`)
28822
+ outputDir: join27(workDir, `worker-${i2}`)
28682
28823
  });
28683
28824
  }
28684
28825
  return tasks;
@@ -28686,7 +28827,7 @@ function distributeFrames(totalFrames, workerCount, workDir) {
28686
28827
  async function executeWorkerTask(task, serverUrl, captureOptions, createBeforeCaptureHook, signal, onFrameCaptured, onFrameBuffer, config) {
28687
28828
  const startTime = Date.now();
28688
28829
  let framesCaptured = 0;
28689
- if (!existsSync23(task.outputDir)) mkdirSync15(task.outputDir, { recursive: true });
28830
+ if (!existsSync25(task.outputDir)) mkdirSync17(task.outputDir, { recursive: true });
28690
28831
  let session = null;
28691
28832
  let perf;
28692
28833
  try {
@@ -28776,17 +28917,17 @@ async function executeParallelCapture(serverUrl, workDir, tasks, captureOptions,
28776
28917
  return results;
28777
28918
  }
28778
28919
  async function mergeWorkerFrames(workDir, tasks, outputDir) {
28779
- if (!existsSync23(outputDir)) mkdirSync15(outputDir, { recursive: true });
28920
+ if (!existsSync25(outputDir)) mkdirSync17(outputDir, { recursive: true });
28780
28921
  let totalFrames = 0;
28781
28922
  const sortedTasks = [...tasks].sort((a, b) => a.startFrame - b.startFrame);
28782
28923
  for (const task of sortedTasks) {
28783
- if (!existsSync23(task.outputDir)) {
28924
+ if (!existsSync25(task.outputDir)) {
28784
28925
  continue;
28785
28926
  }
28786
28927
  const files = readdirSync10(task.outputDir).filter((f3) => f3.startsWith("frame_") && (f3.endsWith(".jpg") || f3.endsWith(".png"))).sort();
28787
28928
  const copyTasks = files.map(async (file) => {
28788
- const sourcePath = join25(task.outputDir, file);
28789
- const targetPath = join25(outputDir, file);
28929
+ const sourcePath = join27(task.outputDir, file);
28930
+ const targetPath = join27(outputDir, file);
28790
28931
  try {
28791
28932
  await rename(sourcePath, targetPath);
28792
28933
  } catch {
@@ -28823,8 +28964,8 @@ var init_parallelCoordinator = __esm({
28823
28964
  // ../engine/src/services/fileServer.ts
28824
28965
  import { Hono as Hono2 } from "hono";
28825
28966
  import { serve } from "@hono/node-server";
28826
- import { readFileSync as readFileSync16, existsSync as existsSync24, statSync as statSync7 } from "fs";
28827
- import { join as join26, extname as extname6 } from "path";
28967
+ import { readFileSync as readFileSync17, existsSync as existsSync26, statSync as statSync7 } from "fs";
28968
+ import { join as join28, extname as extname6 } from "path";
28828
28969
  function stripEmbeddedRuntimeScripts(html) {
28829
28970
  if (!html) return html;
28830
28971
  const scriptRe = /<script\b[^>]*>[\s\S]*?<\/script>/gi;
@@ -28893,22 +29034,22 @@ function createFileServer(options) {
28893
29034
  let requestPath = c2.req.path;
28894
29035
  if (requestPath === "/") requestPath = "/index.html";
28895
29036
  const relativePath = requestPath.replace(/^\//, "");
28896
- const compiledPath = compiledDir ? join26(compiledDir, relativePath) : null;
29037
+ const compiledPath = compiledDir ? join28(compiledDir, relativePath) : null;
28897
29038
  const hasCompiledFile = Boolean(
28898
- compiledPath && existsSync24(compiledPath) && statSync7(compiledPath).isFile()
29039
+ compiledPath && existsSync26(compiledPath) && statSync7(compiledPath).isFile()
28899
29040
  );
28900
- const filePath = hasCompiledFile ? compiledPath : join26(projectDir, relativePath);
28901
- if (!existsSync24(filePath) || !statSync7(filePath).isFile()) {
29041
+ const filePath = hasCompiledFile ? compiledPath : join28(projectDir, relativePath);
29042
+ if (!existsSync26(filePath) || !statSync7(filePath).isFile()) {
28902
29043
  return c2.text("Not found", 404);
28903
29044
  }
28904
29045
  const ext = extname6(filePath).toLowerCase();
28905
29046
  const contentType = MIME_TYPES2[ext] || "application/octet-stream";
28906
29047
  if (ext === ".html") {
28907
- const rawHtml = readFileSync16(filePath, "utf-8");
29048
+ const rawHtml = readFileSync17(filePath, "utf-8");
28908
29049
  const html = relativePath === "index.html" ? injectScriptsIntoHtml(rawHtml, headScripts, bodyScripts, stripEmbeddedRuntime) : rawHtml;
28909
29050
  return c2.text(html, 200, { "Content-Type": contentType });
28910
29051
  }
28911
- const content = readFileSync16(filePath);
29052
+ const content = readFileSync17(filePath);
28912
29053
  return new Response(content, {
28913
29054
  status: 200,
28914
29055
  headers: { "Content-Type": contentType }
@@ -30176,8 +30317,8 @@ var init_shaderTransitions = __esm({
30176
30317
  });
30177
30318
 
30178
30319
  // ../engine/src/services/hdrCapture.ts
30179
- import { existsSync as existsSync25, readdirSync as readdirSync11 } from "fs";
30180
- import { join as join27 } from "path";
30320
+ import { existsSync as existsSync27, readdirSync as readdirSync11 } from "fs";
30321
+ import { join as join29 } from "path";
30181
30322
  import { homedir as homedir6 } from "os";
30182
30323
  function linearToPQ(L2) {
30183
30324
  const Lp = Math.max(0, L2 * SDR_NITS / PQ_MAX_NITS);
@@ -30293,12 +30434,12 @@ function float16ToPqRgb(rawBuffer, bytesPerRow, width, height) {
30293
30434
  return output;
30294
30435
  }
30295
30436
  function resolveHeadedChromePath() {
30296
- const baseDir = join27(homedir6(), ".cache", "puppeteer", "chrome");
30297
- if (!existsSync25(baseDir)) return void 0;
30437
+ const baseDir = join29(homedir6(), ".cache", "puppeteer", "chrome");
30438
+ if (!existsSync27(baseDir)) return void 0;
30298
30439
  const versions = readdirSync11(baseDir).sort().reverse();
30299
30440
  for (const version of versions) {
30300
30441
  const candidates = [
30301
- join27(
30442
+ join29(
30302
30443
  baseDir,
30303
30444
  version,
30304
30445
  "chrome-mac-arm64",
@@ -30307,7 +30448,7 @@ function resolveHeadedChromePath() {
30307
30448
  "MacOS",
30308
30449
  "Google Chrome for Testing"
30309
30450
  ),
30310
- join27(
30451
+ join29(
30311
30452
  baseDir,
30312
30453
  version,
30313
30454
  "chrome-mac-x64",
@@ -30316,11 +30457,11 @@ function resolveHeadedChromePath() {
30316
30457
  "MacOS",
30317
30458
  "Google Chrome for Testing"
30318
30459
  ),
30319
- join27(baseDir, version, "chrome-linux64", "chrome"),
30320
- join27(baseDir, version, "chrome-win64", "chrome.exe")
30460
+ join29(baseDir, version, "chrome-linux64", "chrome"),
30461
+ join29(baseDir, version, "chrome-win64", "chrome.exe")
30321
30462
  ];
30322
30463
  for (const binary of candidates) {
30323
- if (existsSync25(binary)) return binary;
30464
+ if (existsSync27(binary)) return binary;
30324
30465
  }
30325
30466
  }
30326
30467
  return void 0;
@@ -30592,8 +30733,8 @@ var init_staticGuard = __esm({
30592
30733
  });
30593
30734
 
30594
30735
  // ../core/src/compiler/htmlBundler.ts
30595
- import { readFileSync as readFileSync17, existsSync as existsSync26 } from "fs";
30596
- import { join as join28, resolve as resolve12, isAbsolute as isAbsolute4, sep as sep2 } from "path";
30736
+ import { readFileSync as readFileSync18, existsSync as existsSync28 } from "fs";
30737
+ import { join as join30, resolve as resolve12, isAbsolute as isAbsolute4, sep as sep2 } from "path";
30597
30738
  import { transformSync } from "esbuild";
30598
30739
  function parseHTMLContent2(html) {
30599
30740
  const trimmed = html.trimStart().toLowerCase();
@@ -30661,17 +30802,17 @@ function isRelativeUrl(url) {
30661
30802
  return !url.startsWith("http://") && !url.startsWith("https://") && !url.startsWith("//") && !url.startsWith("data:") && !isAbsolute4(url);
30662
30803
  }
30663
30804
  function safeReadFile(filePath) {
30664
- if (!existsSync26(filePath)) return null;
30805
+ if (!existsSync28(filePath)) return null;
30665
30806
  try {
30666
- return readFileSync17(filePath, "utf-8");
30807
+ return readFileSync18(filePath, "utf-8");
30667
30808
  } catch {
30668
30809
  return null;
30669
30810
  }
30670
30811
  }
30671
30812
  function safeReadFileBuffer(filePath) {
30672
- if (!existsSync26(filePath)) return null;
30813
+ if (!existsSync28(filePath)) return null;
30673
30814
  try {
30674
- return readFileSync17(filePath);
30815
+ return readFileSync18(filePath);
30675
30816
  } catch {
30676
30817
  return null;
30677
30818
  }
@@ -30862,9 +31003,9 @@ function stripJsCommentsParserSafe(source) {
30862
31003
  }
30863
31004
  }
30864
31005
  async function bundleToSingleHtml(projectDir, options) {
30865
- const indexPath = join28(projectDir, "index.html");
30866
- if (!existsSync26(indexPath)) throw new Error("index.html not found in project directory");
30867
- const rawHtml = readFileSync17(indexPath, "utf-8");
31006
+ const indexPath = join30(projectDir, "index.html");
31007
+ if (!existsSync28(indexPath)) throw new Error("index.html not found in project directory");
31008
+ const rawHtml = readFileSync18(indexPath, "utf-8");
30868
31009
  const compiled = await compileHtml(rawHtml, projectDir, options?.probeMediaDuration);
30869
31010
  const staticGuard = validateHyperframeHtmlContract(compiled);
30870
31011
  if (!staticGuard.isValid) {
@@ -31139,7 +31280,7 @@ var init_compiler = __esm({
31139
31280
 
31140
31281
  // ../producer/src/services/hyperframeRuntimeLoader.ts
31141
31282
  import { createHash as createHash3 } from "crypto";
31142
- import { existsSync as existsSync27, readFileSync as readFileSync18 } from "fs";
31283
+ import { existsSync as existsSync29, readFileSync as readFileSync19 } from "fs";
31143
31284
  import { dirname as dirname9, resolve as resolve13 } from "path";
31144
31285
  import { fileURLToPath as fileURLToPath2 } from "url";
31145
31286
  function resolveHyperframeManifestPath() {
@@ -31152,7 +31293,7 @@ function resolveHyperframeManifestPath() {
31152
31293
  MODULE_RELATIVE_MANIFEST_PATH
31153
31294
  ];
31154
31295
  for (const candidate of candidates) {
31155
- if (existsSync27(candidate)) {
31296
+ if (existsSync29(candidate)) {
31156
31297
  return candidate;
31157
31298
  }
31158
31299
  }
@@ -31163,12 +31304,12 @@ function getVerifiedHyperframeRuntimeSource() {
31163
31304
  }
31164
31305
  function resolveVerifiedHyperframeRuntime() {
31165
31306
  const manifestPath = resolveHyperframeManifestPath();
31166
- if (!existsSync27(manifestPath)) {
31307
+ if (!existsSync29(manifestPath)) {
31167
31308
  throw new Error(
31168
31309
  `[HyperframeRuntimeLoader] Missing manifest at ${manifestPath}. Build core runtime artifacts before rendering.`
31169
31310
  );
31170
31311
  }
31171
- const manifestRaw = readFileSync18(manifestPath, "utf8");
31312
+ const manifestRaw = readFileSync19(manifestPath, "utf8");
31172
31313
  const manifest = JSON.parse(manifestRaw);
31173
31314
  const runtimeFileName = manifest.artifacts?.iife;
31174
31315
  if (!runtimeFileName || !manifest.sha256) {
@@ -31177,10 +31318,10 @@ function resolveVerifiedHyperframeRuntime() {
31177
31318
  );
31178
31319
  }
31179
31320
  const runtimePath = resolve13(dirname9(manifestPath), runtimeFileName);
31180
- if (!existsSync27(runtimePath)) {
31321
+ if (!existsSync29(runtimePath)) {
31181
31322
  throw new Error(`[HyperframeRuntimeLoader] Missing runtime artifact at ${runtimePath}.`);
31182
31323
  }
31183
- const runtimeSource = readFileSync18(runtimePath, "utf8");
31324
+ const runtimeSource = readFileSync19(runtimePath, "utf8");
31184
31325
  const runtimeSha = createHash3("sha256").update(runtimeSource, "utf8").digest("hex");
31185
31326
  if (runtimeSha !== manifest.sha256) {
31186
31327
  throw new Error(
@@ -31219,16 +31360,16 @@ var init_hyperframeRuntimeLoader = __esm({
31219
31360
  // ../producer/src/services/fileServer.ts
31220
31361
  import { Hono as Hono3 } from "hono";
31221
31362
  import { serve as serve2 } from "@hono/node-server";
31222
- import { readFileSync as readFileSync19, existsSync as existsSync28, realpathSync, statSync as statSync8 } from "fs";
31223
- import { join as join29, extname as extname7, resolve as resolve14, sep as sep3 } from "path";
31363
+ import { readFileSync as readFileSync20, existsSync as existsSync30, realpathSync, statSync as statSync8 } from "fs";
31364
+ import { join as join31, extname as extname7, resolve as resolve14, sep as sep3 } from "path";
31224
31365
  function isPathInside(child, parent, options = {}) {
31225
31366
  const { resolveSymlinks = false, pathModule } = options;
31226
31367
  const resolveFn = pathModule?.resolve ?? resolve14;
31227
31368
  const separator = pathModule?.sep ?? sep3;
31228
31369
  const resolvedChild = resolveFn(child);
31229
31370
  const resolvedParent = resolveFn(parent);
31230
- const normalizedChild = resolveSymlinks && existsSync28(resolvedChild) ? realpathSync.native(resolvedChild) : resolvedChild;
31231
- const normalizedParent = resolveSymlinks && existsSync28(resolvedParent) ? realpathSync.native(resolvedParent) : resolvedParent;
31371
+ const normalizedChild = resolveSymlinks && existsSync30(resolvedChild) ? realpathSync.native(resolvedChild) : resolvedChild;
31372
+ const normalizedParent = resolveSymlinks && existsSync30(resolvedParent) ? realpathSync.native(resolvedParent) : resolvedParent;
31232
31373
  if (normalizedChild === normalizedParent) return true;
31233
31374
  const parentWithSep = normalizedParent.endsWith(separator) ? normalizedParent : normalizedParent + separator;
31234
31375
  return normalizedChild.startsWith(parentWithSep);
@@ -31317,14 +31458,14 @@ function createFileServer2(options) {
31317
31458
  const relativePath = requestPath.replace(/^\//, "");
31318
31459
  let filePath = null;
31319
31460
  if (compiledDir) {
31320
- const candidate = join29(compiledDir, relativePath);
31321
- if (existsSync28(candidate) && isPathInside(candidate, compiledDir) && statSync8(candidate).isFile()) {
31461
+ const candidate = join31(compiledDir, relativePath);
31462
+ if (existsSync30(candidate) && isPathInside(candidate, compiledDir) && statSync8(candidate).isFile()) {
31322
31463
  filePath = candidate;
31323
31464
  }
31324
31465
  }
31325
31466
  if (!filePath) {
31326
- const candidate = join29(projectDir, relativePath);
31327
- if (existsSync28(candidate) && isPathInside(candidate, projectDir) && statSync8(candidate).isFile()) {
31467
+ const candidate = join31(projectDir, relativePath);
31468
+ if (existsSync30(candidate) && isPathInside(candidate, projectDir) && statSync8(candidate).isFile()) {
31328
31469
  filePath = candidate;
31329
31470
  }
31330
31471
  }
@@ -31337,7 +31478,7 @@ function createFileServer2(options) {
31337
31478
  const ext = extname7(filePath).toLowerCase();
31338
31479
  const contentType = MIME_TYPES3[ext] || "application/octet-stream";
31339
31480
  if (ext === ".html") {
31340
- const rawHtml = readFileSync19(filePath, "utf-8");
31481
+ const rawHtml = readFileSync20(filePath, "utf-8");
31341
31482
  const isIndex = relativePath === "index.html";
31342
31483
  let html = rawHtml;
31343
31484
  if (preHeadScripts.length > 0) {
@@ -31346,7 +31487,7 @@ function createFileServer2(options) {
31346
31487
  html = isIndex ? injectScriptsIntoHtml2(html, headScripts, bodyScripts, stripEmbeddedRuntime) : html;
31347
31488
  return c2.text(html, 200, { "Content-Type": contentType });
31348
31489
  }
31349
- const content = readFileSync19(filePath);
31490
+ const content = readFileSync20(filePath);
31350
31491
  return new Response(content, {
31351
31492
  status: 200,
31352
31493
  headers: { "Content-Type": contentType }
@@ -31698,7 +31839,7 @@ var init_ffprobe2 = __esm({
31698
31839
  });
31699
31840
 
31700
31841
  // ../producer/src/utils/paths.ts
31701
- import { resolve as resolve15, basename as basename2, join as join30, relative as relative2, isAbsolute as isAbsolute5 } from "path";
31842
+ import { resolve as resolve15, basename as basename2, join as join32, relative as relative2, isAbsolute as isAbsolute5 } from "path";
31702
31843
  function isPathInside2(childPath, parentPath) {
31703
31844
  const absChild = resolve15(childPath);
31704
31845
  const absParent = resolve15(parentPath);
@@ -31719,7 +31860,7 @@ function toExternalAssetKey(absPath) {
31719
31860
  function resolveRenderPaths(projectDir, outputPath, rendersDir = DEFAULT_RENDERS_DIR) {
31720
31861
  const absoluteProjectDir = resolve15(projectDir);
31721
31862
  const projectName = basename2(absoluteProjectDir);
31722
- const resolvedOutputPath = outputPath ?? join30(rendersDir, `${projectName}.mp4`);
31863
+ const resolvedOutputPath = outputPath ?? join32(rendersDir, `${projectName}.mp4`);
31723
31864
  const absoluteOutputPath = resolve15(resolvedOutputPath);
31724
31865
  return { absoluteProjectDir, absoluteOutputPath };
31725
31866
  }
@@ -31792,9 +31933,9 @@ var init_fontData_generated = __esm({
31792
31933
  });
31793
31934
 
31794
31935
  // ../producer/src/services/deterministicFonts.ts
31795
- import { existsSync as existsSync29, mkdirSync as mkdirSync16, readFileSync as readFileSync20, writeFileSync as writeFileSync11 } from "fs";
31936
+ import { existsSync as existsSync31, mkdirSync as mkdirSync18, readFileSync as readFileSync21, writeFileSync as writeFileSync13 } from "fs";
31796
31937
  import { homedir as homedir7 } from "os";
31797
- import { join as join31 } from "path";
31938
+ import { join as join33 } from "path";
31798
31939
  function normalizeFamilyName(family) {
31799
31940
  return family.trim().replace(/^['"]|['"]$/g, "").trim().toLowerCase();
31800
31941
  }
@@ -31905,14 +32046,14 @@ function fontSlug(familyName) {
31905
32046
  return familyName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
31906
32047
  }
31907
32048
  function fontCacheDir(slug) {
31908
- const dir = join31(GOOGLE_FONTS_CACHE_DIR, slug);
31909
- if (!existsSync29(dir)) {
31910
- mkdirSync16(dir, { recursive: true });
32049
+ const dir = join33(GOOGLE_FONTS_CACHE_DIR, slug);
32050
+ if (!existsSync31(dir)) {
32051
+ mkdirSync18(dir, { recursive: true });
31911
32052
  }
31912
32053
  return dir;
31913
32054
  }
31914
32055
  function cachedWoff2Path(slug, weight, style) {
31915
- return join31(fontCacheDir(slug), `${weight}-${style}.woff2`);
32056
+ return join33(fontCacheDir(slug), `${weight}-${style}.woff2`);
31916
32057
  }
31917
32058
  async function fetchGoogleFont(familyName) {
31918
32059
  const slug = fontSlug(familyName);
@@ -31938,17 +32079,17 @@ async function fetchGoogleFont(familyName) {
31938
32079
  const woff2Url = match[3] || "";
31939
32080
  if (!woff2Url) continue;
31940
32081
  const cachePath2 = cachedWoff2Path(slug, weight, style);
31941
- if (!existsSync29(cachePath2)) {
32082
+ if (!existsSync31(cachePath2)) {
31942
32083
  try {
31943
32084
  const fontRes = await fetch(woff2Url);
31944
32085
  if (!fontRes.ok) continue;
31945
32086
  const buffer = Buffer.from(await fontRes.arrayBuffer());
31946
- writeFileSync11(cachePath2, buffer);
32087
+ writeFileSync13(cachePath2, buffer);
31947
32088
  } catch {
31948
32089
  continue;
31949
32090
  }
31950
32091
  }
31951
- const fontBytes = readFileSync20(cachePath2);
32092
+ const fontBytes = readFileSync21(cachePath2);
31952
32093
  const dataUri = `data:font/woff2;base64,${fontBytes.toString("base64")}`;
31953
32094
  faces.push({ weight, style, dataUri });
31954
32095
  }
@@ -32124,14 +32265,14 @@ var init_deterministicFonts = __esm({
32124
32265
  poppins: "poppins",
32125
32266
  "segoe ui": "roboto"
32126
32267
  };
32127
- GOOGLE_FONTS_CACHE_DIR = join31(homedir7(), ".cache", "hyperframes", "fonts");
32268
+ GOOGLE_FONTS_CACHE_DIR = join33(homedir7(), ".cache", "hyperframes", "fonts");
32128
32269
  WOFF2_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36";
32129
32270
  }
32130
32271
  });
32131
32272
 
32132
32273
  // ../producer/src/services/htmlCompiler.ts
32133
- import { readFileSync as readFileSync21, existsSync as existsSync30, mkdirSync as mkdirSync17 } from "fs";
32134
- import { join as join32, dirname as dirname10, resolve as resolve16 } from "path";
32274
+ import { readFileSync as readFileSync22, existsSync as existsSync32, mkdirSync as mkdirSync19 } from "fs";
32275
+ import { join as join34, dirname as dirname10, resolve as resolve16 } from "path";
32135
32276
  import postcss from "postcss";
32136
32277
  function dedupeElementsById(elements) {
32137
32278
  const deduped = /* @__PURE__ */ new Map();
@@ -32182,16 +32323,16 @@ function detectRenderModeHints(html) {
32182
32323
  async function resolveMediaDuration(src, mediaStart, baseDir, downloadDir, tagName19) {
32183
32324
  let filePath = src;
32184
32325
  if (isHttpUrl(src)) {
32185
- if (!existsSync30(downloadDir)) mkdirSync17(downloadDir, { recursive: true });
32326
+ if (!existsSync32(downloadDir)) mkdirSync19(downloadDir, { recursive: true });
32186
32327
  try {
32187
32328
  filePath = await downloadToTemp(src, downloadDir);
32188
32329
  } catch {
32189
32330
  return { duration: 0, resolvedPath: src };
32190
32331
  }
32191
32332
  } else if (!filePath.startsWith("/")) {
32192
- filePath = join32(baseDir, filePath);
32333
+ filePath = join34(baseDir, filePath);
32193
32334
  }
32194
- if (!existsSync30(filePath)) {
32335
+ if (!existsSync32(filePath)) {
32195
32336
  return { duration: 0, resolvedPath: filePath };
32196
32337
  }
32197
32338
  const metadata = tagName19 === "video" ? await extractMediaMetadata(filePath) : await extractAudioMetadata(filePath);
@@ -32260,10 +32401,10 @@ async function parseSubCompositions(html, projectDir, downloadDir, parentOffset
32260
32401
  if (visited.has(filePath)) {
32261
32402
  continue;
32262
32403
  }
32263
- if (!existsSync30(filePath)) {
32404
+ if (!existsSync32(filePath)) {
32264
32405
  continue;
32265
32406
  }
32266
- const rawSubHtml = readFileSync21(filePath, "utf-8");
32407
+ const rawSubHtml = readFileSync22(filePath, "utf-8");
32267
32408
  const nestedVisited = new Set(visited);
32268
32409
  nestedVisited.add(filePath);
32269
32410
  workItems.push({ srcPath, absoluteStart, absoluteEnd, filePath, rawSubHtml, nestedVisited });
@@ -32470,8 +32611,8 @@ function inlineSubCompositions(html, subCompositions, projectDir) {
32470
32611
  let compHtml = subCompositions.get(srcPath) || null;
32471
32612
  if (!compHtml) {
32472
32613
  const filePath = resolve16(projectDir, srcPath);
32473
- if (existsSync30(filePath)) {
32474
- compHtml = readFileSync21(filePath, "utf-8");
32614
+ if (existsSync32(filePath)) {
32615
+ compHtml = readFileSync22(filePath, "utf-8");
32475
32616
  }
32476
32617
  }
32477
32618
  if (!compHtml) {
@@ -32698,7 +32839,7 @@ function collectExternalAssets(html, projectDir) {
32698
32839
  if (isPathInside2(absPath, absProjectDir)) {
32699
32840
  return null;
32700
32841
  }
32701
- if (!existsSync30(absPath)) return null;
32842
+ if (!existsSync32(absPath)) return null;
32702
32843
  const safeKey = toExternalAssetKey(absPath);
32703
32844
  externalAssets.set(safeKey, absPath);
32704
32845
  return safeKey;
@@ -32743,7 +32884,7 @@ function collectExternalAssets(html, projectDir) {
32743
32884
  };
32744
32885
  }
32745
32886
  async function compileForRender(projectDir, htmlPath, downloadDir) {
32746
- const rawHtml = readFileSync21(htmlPath, "utf-8");
32887
+ const rawHtml = readFileSync22(htmlPath, "utf-8");
32747
32888
  const { html: compiledHtml, unresolvedCompositions } = await compileHtmlFile(
32748
32889
  rawHtml,
32749
32890
  projectDir,
@@ -33083,17 +33224,17 @@ var init_hdrImageTransferCache = __esm({
33083
33224
 
33084
33225
  // ../producer/src/services/renderOrchestrator.ts
33085
33226
  import {
33086
- existsSync as existsSync31,
33087
- mkdirSync as mkdirSync18,
33227
+ existsSync as existsSync33,
33228
+ mkdirSync as mkdirSync20,
33088
33229
  rmSync as rmSync7,
33089
- readFileSync as readFileSync22,
33230
+ readFileSync as readFileSync23,
33090
33231
  readdirSync as readdirSync13,
33091
33232
  statSync as statSync9,
33092
- writeFileSync as writeFileSync12,
33233
+ writeFileSync as writeFileSync14,
33093
33234
  copyFileSync as copyFileSync2,
33094
33235
  appendFileSync
33095
33236
  } from "fs";
33096
- import { join as join33, dirname as dirname11, resolve as resolve17 } from "path";
33237
+ import { join as join35, dirname as dirname11, resolve as resolve17 } from "path";
33097
33238
  import { randomUUID as randomUUID2 } from "crypto";
33098
33239
  import { freemem as freemem2 } from "os";
33099
33240
  import { fileURLToPath as fileURLToPath3 } from "url";
@@ -33119,7 +33260,7 @@ function sampleDirectoryBytes(dir) {
33119
33260
  continue;
33120
33261
  }
33121
33262
  for (const name of entries2) {
33122
- const full = join33(current, name);
33263
+ const full = join35(current, name);
33123
33264
  try {
33124
33265
  const st2 = statSync9(full);
33125
33266
  if (st2.isDirectory()) {
@@ -33194,21 +33335,21 @@ function installDebugLogger(logPath, log2 = defaultLogger) {
33194
33335
  };
33195
33336
  }
33196
33337
  function writeCompiledArtifacts(compiled, workDir, includeSummary) {
33197
- const compileDir = join33(workDir, "compiled");
33198
- mkdirSync18(compileDir, { recursive: true });
33199
- writeFileSync12(join33(compileDir, "index.html"), compiled.html, "utf-8");
33338
+ const compileDir = join35(workDir, "compiled");
33339
+ mkdirSync20(compileDir, { recursive: true });
33340
+ writeFileSync14(join35(compileDir, "index.html"), compiled.html, "utf-8");
33200
33341
  for (const [srcPath, html] of compiled.subCompositions) {
33201
- const outPath = join33(compileDir, srcPath);
33202
- mkdirSync18(dirname11(outPath), { recursive: true });
33203
- writeFileSync12(outPath, html, "utf-8");
33342
+ const outPath = join35(compileDir, srcPath);
33343
+ mkdirSync20(dirname11(outPath), { recursive: true });
33344
+ writeFileSync14(outPath, html, "utf-8");
33204
33345
  }
33205
33346
  for (const [relativePath, absolutePath] of compiled.externalAssets) {
33206
- const outPath = resolve17(join33(compileDir, relativePath));
33347
+ const outPath = resolve17(join35(compileDir, relativePath));
33207
33348
  if (!isPathInside2(outPath, compileDir)) {
33208
33349
  console.warn(`[Render] Skipping external asset with unsafe path: ${relativePath}`);
33209
33350
  continue;
33210
33351
  }
33211
- mkdirSync18(dirname11(outPath), { recursive: true });
33352
+ mkdirSync20(dirname11(outPath), { recursive: true });
33212
33353
  copyFileSync2(absolutePath, outPath);
33213
33354
  }
33214
33355
  if (includeSummary) {
@@ -33233,7 +33374,7 @@ function writeCompiledArtifacts(compiled, workDir, includeSummary) {
33233
33374
  subCompositions: Array.from(compiled.subCompositions.keys()),
33234
33375
  renderModeHints: compiled.renderModeHints
33235
33376
  };
33236
- writeFileSync12(join33(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
33377
+ writeFileSync14(join35(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
33237
33378
  }
33238
33379
  }
33239
33380
  function applyRenderModeHints(cfg, compiled, log2 = defaultLogger) {
@@ -33254,12 +33395,12 @@ function blitHdrVideoLayer(canvas, el, time, fps, hdrFrameDirs, hdrStartTimes, w
33254
33395
  if (videoFrameIndex < 1) return;
33255
33396
  const maxIndex = getMaxFrameIndex(frameDir);
33256
33397
  const effectiveIndex = maxIndex > 0 ? Math.min(videoFrameIndex, maxIndex) : videoFrameIndex;
33257
- const framePath = join33(frameDir, `frame_${String(effectiveIndex).padStart(4, "0")}.png`);
33258
- if (!existsSync31(framePath)) {
33398
+ const framePath = join35(frameDir, `frame_${String(effectiveIndex).padStart(4, "0")}.png`);
33399
+ if (!existsSync33(framePath)) {
33259
33400
  return;
33260
33401
  }
33261
33402
  try {
33262
- const { data: hdrRgb, width: srcW, height: srcH } = decodePngToRgb48le(readFileSync22(framePath));
33403
+ const { data: hdrRgb, width: srcW, height: srcH } = decodePngToRgb48le(readFileSync23(framePath));
33263
33404
  if (sourceTransfer && targetTransfer && sourceTransfer !== targetTransfer) {
33264
33405
  convertTransfer(hdrRgb, sourceTransfer, targetTransfer);
33265
33406
  }
@@ -33438,7 +33579,7 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
33438
33579
  const startTime = hdrVideoStartTimes.get(layer.element.id) ?? 0;
33439
33580
  const localTime = time - startTime;
33440
33581
  const frameNum = Math.floor(localTime * fps) + 1;
33441
- const expectedFrame = frameDir ? join33(frameDir, `frame_${String(frameNum).padStart(4, "0")}.png`) : null;
33582
+ const expectedFrame = frameDir ? join35(frameDir, `frame_${String(frameNum).padStart(4, "0")}.png`) : null;
33442
33583
  log2.info("[diag] hdr layer blit", {
33443
33584
  frame: debugFrameIndex,
33444
33585
  layerIdx,
@@ -33450,7 +33591,7 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
33450
33591
  localTime: localTime.toFixed(3),
33451
33592
  hdrFrameNum: frameNum,
33452
33593
  expectedFrame,
33453
- expectedFrameExists: expectedFrame ? existsSync31(expectedFrame) : false
33594
+ expectedFrameExists: expectedFrame ? existsSync33(expectedFrame) : false
33454
33595
  });
33455
33596
  }
33456
33597
  }
@@ -33475,8 +33616,8 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
33475
33616
  if (shouldLog && debugDumpDir) {
33476
33617
  const after2 = countNonZeroRgb48(canvas);
33477
33618
  const dumpName = `frame_${String(debugFrameIndex).padStart(4, "0")}_layer_${String(layerIdx).padStart(2, "0")}_dom.png`;
33478
- const dumpPath = join33(debugDumpDir, dumpName);
33479
- writeFileSync12(dumpPath, domPng);
33619
+ const dumpPath = join35(debugDumpDir, dumpName);
33620
+ writeFileSync14(dumpPath, domPng);
33480
33621
  log2.info("[diag] dom layer blit", {
33481
33622
  frame: debugFrameIndex,
33482
33623
  layerIdx,
@@ -33549,8 +33690,8 @@ function extractStandaloneEntryFromIndex(indexHtml, entryFile) {
33549
33690
  async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSignal) {
33550
33691
  const moduleDir = dirname11(fileURLToPath3(import.meta.url));
33551
33692
  const producerRoot = process.env.PRODUCER_RENDERS_DIR ? resolve17(process.env.PRODUCER_RENDERS_DIR, "..") : resolve17(moduleDir, "../..");
33552
- const debugDir = join33(producerRoot, ".debug");
33553
- const workDir = job.config.debug ? join33(debugDir, job.id) : join33(dirname11(outputPath), `work-${job.id}`);
33693
+ const debugDir = join35(producerRoot, ".debug");
33694
+ const workDir = job.config.debug ? join35(debugDir, job.id) : join35(dirname11(outputPath), `work-${job.id}`);
33554
33695
  const pipelineStart = Date.now();
33555
33696
  const log2 = job.config.logger ?? defaultLogger;
33556
33697
  let fileServer = null;
@@ -33562,7 +33703,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
33562
33703
  videoExtractionFailures: 0,
33563
33704
  imageDecodeFailures: 0
33564
33705
  };
33565
- const perfOutputPath = join33(workDir, "perf-summary.json");
33706
+ const perfOutputPath = join35(workDir, "perf-summary.json");
33566
33707
  const cfg = { ...job.config.producerConfig ?? resolveConfig() };
33567
33708
  const outputFormat = job.config.format ?? "mp4";
33568
33709
  const isWebm = outputFormat === "webm";
@@ -33595,28 +33736,28 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
33595
33736
  };
33596
33737
  job.startedAt = /* @__PURE__ */ new Date();
33597
33738
  assertNotAborted();
33598
- if (!existsSync31(workDir)) mkdirSync18(workDir, { recursive: true });
33739
+ if (!existsSync33(workDir)) mkdirSync20(workDir, { recursive: true });
33599
33740
  if (job.config.debug) {
33600
- const logPath = join33(workDir, "render.log");
33741
+ const logPath = join35(workDir, "render.log");
33601
33742
  restoreLogger = installDebugLogger(logPath, log2);
33602
33743
  }
33603
33744
  const entryFile = job.config.entryFile || "index.html";
33604
- let htmlPath = join33(projectDir, entryFile);
33605
- if (!existsSync31(htmlPath)) {
33745
+ let htmlPath = join35(projectDir, entryFile);
33746
+ if (!existsSync33(htmlPath)) {
33606
33747
  throw new Error(`Entry file not found: ${htmlPath}`);
33607
33748
  }
33608
33749
  assertNotAborted();
33609
- const rawEntry = readFileSync22(htmlPath, "utf-8");
33750
+ const rawEntry = readFileSync23(htmlPath, "utf-8");
33610
33751
  if (entryFile !== "index.html" && rawEntry.trimStart().startsWith("<template")) {
33611
- const wrapperPath = join33(workDir, "standalone-entry.html");
33612
- const projectIndexPath = join33(projectDir, "index.html");
33613
- if (!existsSync31(projectIndexPath)) {
33752
+ const wrapperPath = join35(workDir, "standalone-entry.html");
33753
+ const projectIndexPath = join35(projectDir, "index.html");
33754
+ if (!existsSync33(projectIndexPath)) {
33614
33755
  throw new Error(
33615
33756
  `Template entry file "${entryFile}" requires a project index.html to extract its render shell.`
33616
33757
  );
33617
33758
  }
33618
33759
  const standaloneHtml = extractStandaloneEntryFromIndex(
33619
- readFileSync22(projectIndexPath, "utf-8"),
33760
+ readFileSync23(projectIndexPath, "utf-8"),
33620
33761
  entryFile
33621
33762
  );
33622
33763
  if (!standaloneHtml) {
@@ -33624,7 +33765,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
33624
33765
  `Entry file "${entryFile}" is not mounted from index.html via data-composition-src, so it cannot be rendered independently.`
33625
33766
  );
33626
33767
  }
33627
- writeFileSync12(wrapperPath, standaloneHtml, "utf-8");
33768
+ writeFileSync14(wrapperPath, standaloneHtml, "utf-8");
33628
33769
  htmlPath = wrapperPath;
33629
33770
  log2.info("Extracted standalone entry from index.html host context", {
33630
33771
  entryFile
@@ -33633,7 +33774,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
33633
33774
  const stage1Start = Date.now();
33634
33775
  updateJobStatus(job, "preprocessing", "Compiling composition", 5, onProgress);
33635
33776
  const compileStart = Date.now();
33636
- let compiled = await compileForRender(projectDir, htmlPath, join33(workDir, "downloads"));
33777
+ let compiled = await compileForRender(projectDir, htmlPath, join35(workDir, "downloads"));
33637
33778
  assertNotAborted();
33638
33779
  perfStages.compileOnlyMs = Date.now() - compileStart;
33639
33780
  applyRenderModeHints(cfg, compiled, log2);
@@ -33665,7 +33806,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
33665
33806
  reasons.push(`${compiled.unresolvedCompositions.length} unresolved composition(s)`);
33666
33807
  fileServer = await createFileServer2({
33667
33808
  projectDir,
33668
- compiledDir: join33(workDir, "compiled"),
33809
+ compiledDir: join35(workDir, "compiled"),
33669
33810
  port: 0,
33670
33811
  preHeadScripts: [VIRTUAL_TIME_SHIM]
33671
33812
  });
@@ -33679,7 +33820,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
33679
33820
  };
33680
33821
  probeSession = await createCaptureSession(
33681
33822
  fileServer.url,
33682
- join33(workDir, "probe"),
33823
+ join35(workDir, "probe"),
33683
33824
  captureOpts,
33684
33825
  null,
33685
33826
  cfg
@@ -33711,7 +33852,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
33711
33852
  compiled,
33712
33853
  resolutions,
33713
33854
  projectDir,
33714
- join33(workDir, "downloads")
33855
+ join35(workDir, "downloads")
33715
33856
  );
33716
33857
  assertNotAborted();
33717
33858
  composition.videos = compiled.videos;
@@ -33865,7 +34006,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
33865
34006
  const stage2Start = Date.now();
33866
34007
  updateJobStatus(job, "preprocessing", "Extracting video frames", 10, onProgress);
33867
34008
  let frameLookup = null;
33868
- const compiledDir = join33(workDir, "compiled");
34009
+ const compiledDir = join35(workDir, "compiled");
33869
34010
  let extractionResult = null;
33870
34011
  const nativeHdrVideoIds = /* @__PURE__ */ new Set();
33871
34012
  const videoTransfers = /* @__PURE__ */ new Map();
@@ -33874,10 +34015,10 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
33874
34015
  composition.videos.map(async (v) => {
33875
34016
  let videoPath = v.src;
33876
34017
  if (!videoPath.startsWith("/")) {
33877
- const fromCompiled = existsSync31(join33(compiledDir, videoPath)) ? join33(compiledDir, videoPath) : join33(projectDir, videoPath);
34018
+ const fromCompiled = existsSync33(join35(compiledDir, videoPath)) ? join35(compiledDir, videoPath) : join35(projectDir, videoPath);
33878
34019
  videoPath = fromCompiled;
33879
34020
  }
33880
- if (!existsSync31(videoPath)) return;
34021
+ if (!existsSync33(videoPath)) return;
33881
34022
  const meta = await extractMediaMetadata(videoPath);
33882
34023
  if (isHdrColorSpace(meta.colorSpace)) {
33883
34024
  nativeHdrVideoIds.add(v.id);
@@ -33895,10 +34036,10 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
33895
34036
  composition.images.map(async (img) => {
33896
34037
  let imgPath = img.src;
33897
34038
  if (!imgPath.startsWith("/")) {
33898
- const fromCompiled = existsSync31(join33(compiledDir, imgPath)) ? join33(compiledDir, imgPath) : join33(projectDir, imgPath);
34039
+ const fromCompiled = existsSync33(join35(compiledDir, imgPath)) ? join35(compiledDir, imgPath) : join35(projectDir, imgPath);
33899
34040
  imgPath = fromCompiled;
33900
34041
  }
33901
- if (!existsSync31(imgPath)) return null;
34042
+ if (!existsSync33(imgPath)) return null;
33902
34043
  const meta = await extractMediaMetadata(imgPath);
33903
34044
  if (isHdrColorSpace(meta.colorSpace)) {
33904
34045
  nativeHdrImageIds.add(img.id);
@@ -33914,7 +34055,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
33914
34055
  extractionResult = await extractAllVideoFrames(
33915
34056
  composition.videos,
33916
34057
  projectDir,
33917
- { fps: job.config.fps, outputDir: join33(workDir, "video-frames") },
34058
+ { fps: job.config.fps, outputDir: join35(workDir, "video-frames") },
33918
34059
  abortSignal,
33919
34060
  { extractCacheDir: cfg.extractCacheDir },
33920
34061
  compiledDir
@@ -33972,13 +34113,13 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
33972
34113
  }
33973
34114
  const stage3Start = Date.now();
33974
34115
  updateJobStatus(job, "preprocessing", "Processing audio tracks", 20, onProgress);
33975
- const audioOutputPath = join33(workDir, "audio.aac");
34116
+ const audioOutputPath = join35(workDir, "audio.aac");
33976
34117
  let hasAudio = false;
33977
34118
  if (composition.audios.length > 0) {
33978
34119
  const audioResult = await processCompositionAudio(
33979
34120
  composition.audios,
33980
34121
  projectDir,
33981
- join33(workDir, "audio-work"),
34122
+ join35(workDir, "audio-work"),
33982
34123
  audioOutputPath,
33983
34124
  job.duration,
33984
34125
  abortSignal,
@@ -33996,14 +34137,14 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
33996
34137
  if (!fileServer) {
33997
34138
  fileServer = await createFileServer2({
33998
34139
  projectDir,
33999
- compiledDir: join33(workDir, "compiled"),
34140
+ compiledDir: join35(workDir, "compiled"),
34000
34141
  port: 0,
34001
34142
  preHeadScripts: [VIRTUAL_TIME_SHIM]
34002
34143
  });
34003
34144
  assertNotAborted();
34004
34145
  }
34005
- const framesDir = join33(workDir, "captured-frames");
34006
- if (!existsSync31(framesDir)) mkdirSync18(framesDir, { recursive: true });
34146
+ const framesDir = join35(workDir, "captured-frames");
34147
+ if (!existsSync33(framesDir)) mkdirSync20(framesDir, { recursive: true });
34007
34148
  const captureOptions = {
34008
34149
  width,
34009
34150
  height,
@@ -34018,7 +34159,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
34018
34159
  const workerCount = calculateOptimalWorkers(totalFrames, job.config.workers, cfg);
34019
34160
  const FORMAT_EXT2 = { mp4: ".mp4", webm: ".webm", mov: ".mov" };
34020
34161
  const videoExt = FORMAT_EXT2[outputFormat] ?? ".mp4";
34021
- const videoOnlyPath = join33(workDir, `video-only${videoExt}`);
34162
+ const videoOnlyPath = join35(workDir, `video-only${videoExt}`);
34022
34163
  const nativeHdrIds = /* @__PURE__ */ new Set([...nativeHdrVideoIds, ...nativeHdrImageIds]);
34023
34164
  const hasHdrContent = effectiveHdr && nativeHdrIds.size > 0;
34024
34165
  const encoderHdr = hasHdrContent ? effectiveHdr : void 0;
@@ -34040,8 +34181,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
34040
34181
  if (!hdrVideoIds.includes(v.id)) continue;
34041
34182
  let srcPath = v.src;
34042
34183
  if (!srcPath.startsWith("/")) {
34043
- const fromCompiled = join33(compiledDir, srcPath);
34044
- srcPath = existsSync31(fromCompiled) ? fromCompiled : join33(projectDir, srcPath);
34184
+ const fromCompiled = join35(compiledDir, srcPath);
34185
+ srcPath = existsSync33(fromCompiled) ? fromCompiled : join35(projectDir, srcPath);
34045
34186
  }
34046
34187
  hdrVideoSrcPaths.set(v.id, srcPath);
34047
34188
  }
@@ -34171,8 +34312,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
34171
34312
  for (const [videoId, srcPath] of hdrVideoSrcPaths) {
34172
34313
  const video = composition.videos.find((v) => v.id === videoId);
34173
34314
  if (!video) continue;
34174
- const frameDir = join33(framesDir, `hdr_${videoId}`);
34175
- mkdirSync18(frameDir, { recursive: true });
34315
+ const frameDir = join35(framesDir, `hdr_${videoId}`);
34316
+ mkdirSync20(frameDir, { recursive: true });
34176
34317
  const duration = video.end - video.start;
34177
34318
  const dims = hdrExtractionDims.get(videoId) ?? { width, height };
34178
34319
  const ffmpegArgs = [
@@ -34191,7 +34332,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
34191
34332
  "-c:v",
34192
34333
  "png",
34193
34334
  "-y",
34194
- join33(frameDir, "frame_%04d.png")
34335
+ join35(frameDir, "frame_%04d.png")
34195
34336
  ];
34196
34337
  const result = await runFfmpeg(ffmpegArgs, { signal: abortSignal });
34197
34338
  if (!result.success) {
@@ -34210,7 +34351,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
34210
34351
  const hdrImageBuffers = /* @__PURE__ */ new Map();
34211
34352
  for (const [imageId, srcPath] of hdrImageSrcPaths) {
34212
34353
  try {
34213
- const decoded = decodePngToRgb48le(readFileSync22(srcPath));
34354
+ const decoded = decodePngToRgb48le(readFileSync23(srcPath));
34214
34355
  const layout2 = hdrExtractionDims.get(imageId);
34215
34356
  const fitInfo = hdrImageFitInfo.get(imageId);
34216
34357
  if (layout2 && (layout2.width !== decoded.width || layout2.height !== decoded.height)) {
@@ -34259,9 +34400,9 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
34259
34400
  }
34260
34401
  }
34261
34402
  const debugDumpEnabled = process.env.KEEP_TEMP === "1";
34262
- const debugDumpDir = debugDumpEnabled ? join33(framesDir, "debug-composite") : null;
34263
- if (debugDumpDir && !existsSync31(debugDumpDir)) {
34264
- mkdirSync18(debugDumpDir, { recursive: true });
34403
+ const debugDumpDir = debugDumpEnabled ? join35(framesDir, "debug-composite") : null;
34404
+ if (debugDumpDir && !existsSync33(debugDumpDir)) {
34405
+ mkdirSync20(debugDumpDir, { recursive: true });
34265
34406
  }
34266
34407
  if (!effectiveHdr) {
34267
34408
  throw new Error(
@@ -34407,11 +34548,11 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
34407
34548
  i2
34408
34549
  );
34409
34550
  if (debugDumpEnabled && debugDumpDir && i2 % 30 === 0) {
34410
- const previewPath = join33(
34551
+ const previewPath = join35(
34411
34552
  debugDumpDir,
34412
34553
  `frame_${String(i2).padStart(4, "0")}_final_rgb48le.bin`
34413
34554
  );
34414
- writeFileSync12(previewPath, normalCanvas);
34555
+ writeFileSync14(previewPath, normalCanvas);
34415
34556
  }
34416
34557
  hdrEncoder.writeFrame(normalCanvas);
34417
34558
  }
@@ -34754,7 +34895,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
34754
34895
  updateJobStatus(job, "complete", "Render complete", 100, onProgress);
34755
34896
  const totalElapsed = Date.now() - pipelineStart;
34756
34897
  sampleMemory();
34757
- const tmpPeakBytes = existsSync31(workDir) ? sampleDirectoryBytes(workDir) : 0;
34898
+ const tmpPeakBytes = existsSync33(workDir) ? sampleDirectoryBytes(workDir) : 0;
34758
34899
  const perfSummary = {
34759
34900
  renderId: job.id,
34760
34901
  totalElapsedMs: totalElapsed,
@@ -34779,7 +34920,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
34779
34920
  job.perfSummary = perfSummary;
34780
34921
  if (job.config.debug) {
34781
34922
  try {
34782
- writeFileSync12(perfOutputPath, JSON.stringify(perfSummary, null, 2), "utf-8");
34923
+ writeFileSync14(perfOutputPath, JSON.stringify(perfSummary, null, 2), "utf-8");
34783
34924
  } catch (err) {
34784
34925
  log2.debug("Failed to write perf summary", {
34785
34926
  perfOutputPath,
@@ -34788,8 +34929,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
34788
34929
  }
34789
34930
  }
34790
34931
  if (job.config.debug) {
34791
- if (existsSync31(outputPath)) {
34792
- const debugOutput = join33(workDir, `output${videoExt}`);
34932
+ if (existsSync33(outputPath)) {
34933
+ const debugOutput = join35(workDir, `output${videoExt}`);
34793
34934
  copyFileSync2(outputPath, debugOutput);
34794
34935
  }
34795
34936
  } else if (process.env.KEEP_TEMP === "1") {
@@ -34875,7 +35016,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
34875
35016
  await safeCleanup(
34876
35017
  "remove workDir (error)",
34877
35018
  () => {
34878
- if (existsSync31(workDir)) rmSync7(workDir, { recursive: true, force: true });
35019
+ if (existsSync33(workDir)) rmSync7(workDir, { recursive: true, force: true });
34879
35020
  },
34880
35021
  log2
34881
35022
  );
@@ -34935,8 +35076,8 @@ var init_config3 = __esm({
34935
35076
  });
34936
35077
 
34937
35078
  // ../producer/src/services/hyperframeLint.ts
34938
- import { existsSync as existsSync32, readFileSync as readFileSync23, statSync as statSync10 } from "fs";
34939
- import { resolve as resolve18, join as join34 } from "path";
35079
+ import { existsSync as existsSync34, readFileSync as readFileSync24, statSync as statSync10 } from "fs";
35080
+ import { resolve as resolve18, join as join36 } from "path";
34940
35081
  function isStringRecord(value) {
34941
35082
  if (!value || typeof value !== "object" || Array.isArray(value)) {
34942
35083
  return false;
@@ -34964,7 +35105,7 @@ function pickEntryFile(files, preferredEntryFile) {
34964
35105
  }
34965
35106
  function readProjectEntryFile(projectDir, preferredEntryFile) {
34966
35107
  const absProjectDir = resolve18(projectDir);
34967
- if (!existsSync32(absProjectDir) || !statSync10(absProjectDir).isDirectory()) {
35108
+ if (!existsSync34(absProjectDir) || !statSync10(absProjectDir).isDirectory()) {
34968
35109
  return { error: `Project directory not found: ${absProjectDir}` };
34969
35110
  }
34970
35111
  const entryCandidates = [preferredEntryFile, "index.html", "src/index.html"].filter(
@@ -34975,16 +35116,16 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
34975
35116
  if (!absoluteEntryPath.startsWith(absProjectDir)) {
34976
35117
  return { error: `Entry file must stay inside project directory: ${entryFile}` };
34977
35118
  }
34978
- if (existsSync32(absoluteEntryPath) && statSync10(absoluteEntryPath).isFile()) {
35119
+ if (existsSync34(absoluteEntryPath) && statSync10(absoluteEntryPath).isFile()) {
34979
35120
  return {
34980
35121
  entryFile,
34981
- html: readFileSync23(absoluteEntryPath, "utf-8"),
35122
+ html: readFileSync24(absoluteEntryPath, "utf-8"),
34982
35123
  source: "projectDir"
34983
35124
  };
34984
35125
  }
34985
35126
  }
34986
35127
  return {
34987
- error: `No HTML entry file found in project directory: ${join34(absProjectDir, preferredEntryFile || "index.html")}`
35128
+ error: `No HTML entry file found in project directory: ${join36(absProjectDir, preferredEntryFile || "index.html")}`
34988
35129
  };
34989
35130
  }
34990
35131
  function prepareHyperframeLintBody(body) {
@@ -35072,15 +35213,15 @@ var init_semaphore = __esm({
35072
35213
 
35073
35214
  // ../producer/src/server.ts
35074
35215
  import {
35075
- existsSync as existsSync33,
35076
- mkdirSync as mkdirSync19,
35216
+ existsSync as existsSync35,
35217
+ mkdirSync as mkdirSync21,
35077
35218
  statSync as statSync11,
35078
35219
  mkdtempSync as mkdtempSync2,
35079
- writeFileSync as writeFileSync13,
35220
+ writeFileSync as writeFileSync15,
35080
35221
  rmSync as rmSync8,
35081
35222
  createReadStream
35082
35223
  } from "fs";
35083
- import { resolve as resolve19, dirname as dirname12, join as join35 } from "path";
35224
+ import { resolve as resolve19, dirname as dirname12, join as join37 } from "path";
35084
35225
  import { tmpdir as tmpdir3 } from "os";
35085
35226
  import { parseArgs as parseArgs2 } from "util";
35086
35227
  import crypto2 from "crypto";
@@ -35103,11 +35244,11 @@ async function prepareRenderBody(body) {
35103
35244
  const projectDir = typeof body.projectDir === "string" ? body.projectDir : void 0;
35104
35245
  if (projectDir) {
35105
35246
  const absProjectDir = resolve19(projectDir);
35106
- if (!existsSync33(absProjectDir) || !statSync11(absProjectDir).isDirectory()) {
35247
+ if (!existsSync35(absProjectDir) || !statSync11(absProjectDir).isDirectory()) {
35107
35248
  return { error: `Project directory not found: ${absProjectDir}` };
35108
35249
  }
35109
35250
  const entry = options.entryFile || "index.html";
35110
- if (!existsSync33(resolve19(absProjectDir, entry))) {
35251
+ if (!existsSync35(resolve19(absProjectDir, entry))) {
35111
35252
  return { error: `Entry file "${entry}" not found in project directory: ${absProjectDir}` };
35112
35253
  }
35113
35254
  return { prepared: { input: { projectDir: absProjectDir, ...options } } };
@@ -35132,8 +35273,8 @@ async function prepareRenderBody(body) {
35132
35273
  }
35133
35274
  }
35134
35275
  const tempRoot = process.env.PRODUCER_TMP_PROJECT_DIR || tmpdir3();
35135
- const tempProjectDir = mkdtempSync2(join35(tempRoot, "producer-project-"));
35136
- writeFileSync13(join35(tempProjectDir, "index.html"), htmlContent, "utf-8");
35276
+ const tempProjectDir = mkdtempSync2(join37(tempRoot, "producer-project-"));
35277
+ writeFileSync15(join37(tempProjectDir, "index.html"), htmlContent, "utf-8");
35137
35278
  return {
35138
35279
  prepared: {
35139
35280
  input: {
@@ -35256,7 +35397,7 @@ function createRenderHandlers(options = {}) {
35256
35397
  log2
35257
35398
  );
35258
35399
  const outputDir = dirname12(absoluteOutputPath);
35259
- if (!existsSync33(outputDir)) mkdirSync19(outputDir, { recursive: true });
35400
+ if (!existsSync35(outputDir)) mkdirSync21(outputDir, { recursive: true });
35260
35401
  const release2 = await renderSemaphore.acquire();
35261
35402
  log2.info("render started", {
35262
35403
  requestId,
@@ -35283,7 +35424,7 @@ function createRenderHandlers(options = {}) {
35283
35424
  log2.info(`render progress ${pct}%`, { requestId, stage: j2.currentStage, message });
35284
35425
  }
35285
35426
  });
35286
- const fileSize = existsSync33(absoluteOutputPath) ? statSync11(absoluteOutputPath).size : 0;
35427
+ const fileSize = existsSync35(absoluteOutputPath) ? statSync11(absoluteOutputPath).size : 0;
35287
35428
  const durationMs = Date.now() - t0;
35288
35429
  const outputToken = store.register(absoluteOutputPath);
35289
35430
  const outputUrl = `${outputUrlPrefix}/${outputToken}`;
@@ -35367,7 +35508,7 @@ function createRenderHandlers(options = {}) {
35367
35508
  log2
35368
35509
  );
35369
35510
  const outputDir = dirname12(absoluteOutputPath);
35370
- if (!existsSync33(outputDir)) mkdirSync19(outputDir, { recursive: true });
35511
+ if (!existsSync35(outputDir)) mkdirSync21(outputDir, { recursive: true });
35371
35512
  log2.info("render-stream started", { requestId, projectDir: input.projectDir });
35372
35513
  const job = createRenderJob({
35373
35514
  fps: input.fps,
@@ -35412,7 +35553,7 @@ function createRenderHandlers(options = {}) {
35412
35553
  },
35413
35554
  abortController.signal
35414
35555
  );
35415
- const fileSize = existsSync33(absoluteOutputPath) ? statSync11(absoluteOutputPath).size : 0;
35556
+ const fileSize = existsSync35(absoluteOutputPath) ? statSync11(absoluteOutputPath).size : 0;
35416
35557
  const outputToken = store.register(absoluteOutputPath);
35417
35558
  const outputUrl = `${outputUrlPrefix}/${outputToken}`;
35418
35559
  log2.info("render-stream completed", { requestId, fileSize, perf: job.perfSummary ?? null });
@@ -35471,7 +35612,7 @@ function createRenderHandlers(options = {}) {
35471
35612
  if (!artifact) {
35472
35613
  return c2.json({ success: false, error: "Output artifact not found or expired" }, 404);
35473
35614
  }
35474
- if (!existsSync33(artifact.path)) {
35615
+ if (!existsSync35(artifact.path)) {
35475
35616
  store.delete(token);
35476
35617
  return c2.json({ success: false, error: "Output artifact file missing" }, 404);
35477
35618
  }
@@ -35609,20 +35750,20 @@ __export(studioServer_exports, {
35609
35750
  });
35610
35751
  import { Hono as Hono5 } from "hono";
35611
35752
  import { streamSSE as streamSSE3 } from "hono/streaming";
35612
- import { existsSync as existsSync34, readFileSync as readFileSync24, writeFileSync as writeFileSync14, statSync as statSync12 } from "fs";
35613
- import { resolve as resolve20, join as join36, basename as basename3 } from "path";
35753
+ import { existsSync as existsSync36, readFileSync as readFileSync25, writeFileSync as writeFileSync16, statSync as statSync12 } from "fs";
35754
+ import { resolve as resolve20, join as join38, basename as basename3 } from "path";
35614
35755
  function resolveDistDir() {
35615
35756
  return resolveStudioBundle().dir;
35616
35757
  }
35617
35758
  function resolveStudioBundle() {
35618
35759
  const builtPath = resolve20(__dirname, "studio");
35619
35760
  const builtIndex = resolve20(builtPath, "index.html");
35620
- if (existsSync34(builtIndex)) {
35761
+ if (existsSync36(builtIndex)) {
35621
35762
  return { dir: builtPath, indexPath: builtIndex, available: true, checkedPaths: [builtIndex] };
35622
35763
  }
35623
35764
  const devPath = resolve20(__dirname, "..", "..", "..", "studio", "dist");
35624
35765
  const devIndex = resolve20(devPath, "index.html");
35625
- if (existsSync34(devIndex)) {
35766
+ if (existsSync36(devIndex)) {
35626
35767
  return {
35627
35768
  dir: devPath,
35628
35769
  indexPath: devIndex,
@@ -35639,9 +35780,9 @@ function resolveStudioBundle() {
35639
35780
  }
35640
35781
  function resolveRuntimePath() {
35641
35782
  const builtPath = resolve20(__dirname, "hyperframe-runtime.js");
35642
- if (existsSync34(builtPath)) return builtPath;
35783
+ if (existsSync36(builtPath)) return builtPath;
35643
35784
  const iifePath = resolve20(__dirname, "hyperframe.runtime.iife.js");
35644
- if (existsSync34(iifePath)) return iifePath;
35785
+ if (existsSync36(iifePath)) return iifePath;
35645
35786
  const devPath = resolve20(
35646
35787
  __dirname,
35647
35788
  "..",
@@ -35651,7 +35792,7 @@ function resolveRuntimePath() {
35651
35792
  "dist",
35652
35793
  "hyperframe.runtime.iife.js"
35653
35794
  );
35654
- if (existsSync34(devPath)) return devPath;
35795
+ if (existsSync36(devPath)) return devPath;
35655
35796
  return builtPath;
35656
35797
  }
35657
35798
  async function getThumbnailBrowser() {
@@ -35713,7 +35854,7 @@ function createStudioServer(options) {
35713
35854
  return lintHyperframeHtml2(html, opts);
35714
35855
  },
35715
35856
  runtimeUrl: "/api/runtime.js",
35716
- rendersDir: () => join36(projectDir, "renders"),
35857
+ rendersDir: () => join38(projectDir, "renders"),
35717
35858
  startRender(opts) {
35718
35859
  const state = {
35719
35860
  id: opts.jobId,
@@ -35746,7 +35887,7 @@ function createStudioServer(options) {
35746
35887
  state.status = "complete";
35747
35888
  state.progress = 100;
35748
35889
  const metaPath = opts.outputPath.replace(/\.(mp4|webm|mov)$/, ".meta.json");
35749
- writeFileSync14(
35890
+ writeFileSync16(
35750
35891
  metaPath,
35751
35892
  JSON.stringify({ status: "complete", durationMs: Date.now() - startTime })
35752
35893
  );
@@ -35755,7 +35896,7 @@ function createStudioServer(options) {
35755
35896
  state.error = err instanceof Error ? err.message : String(err);
35756
35897
  try {
35757
35898
  const metaPath = opts.outputPath.replace(/\.(mp4|webm|mov)$/, ".meta.json");
35758
- writeFileSync14(metaPath, JSON.stringify({ status: "failed" }));
35899
+ writeFileSync16(metaPath, JSON.stringify({ status: "failed" }));
35759
35900
  } catch {
35760
35901
  }
35761
35902
  }
@@ -35828,7 +35969,7 @@ function createStudioServer(options) {
35828
35969
  });
35829
35970
  app.get("/api/runtime.js", (c2) => {
35830
35971
  const serve4 = async () => {
35831
- const runtimeSource = await loadRuntimeSource() ?? (existsSync34(runtimePath) ? readFileSync24(runtimePath, "utf-8") : null);
35972
+ const runtimeSource = await loadRuntimeSource() ?? (existsSync36(runtimePath) ? readFileSync25(runtimePath, "utf-8") : null);
35832
35973
  if (!runtimeSource) return c2.text("runtime not available", 404);
35833
35974
  return c2.body(runtimeSource, 200, {
35834
35975
  "Content-Type": "text/javascript",
@@ -35864,23 +36005,23 @@ function createStudioServer(options) {
35864
36005
  });
35865
36006
  app.get("/assets/*", (c2) => {
35866
36007
  const filePath = resolve20(studioDir, c2.req.path.slice(1));
35867
- if (!existsSync34(filePath) || !statSync12(filePath).isFile()) return c2.text("not found", 404);
35868
- const content = readFileSync24(filePath);
36008
+ if (!existsSync36(filePath) || !statSync12(filePath).isFile()) return c2.text("not found", 404);
36009
+ const content = readFileSync25(filePath);
35869
36010
  return new Response(content, {
35870
36011
  headers: { "Content-Type": getMimeType(filePath), "Cache-Control": "no-store" }
35871
36012
  });
35872
36013
  });
35873
36014
  app.get("/icons/*", (c2) => {
35874
36015
  const filePath = resolve20(studioDir, c2.req.path.slice(1));
35875
- if (!existsSync34(filePath) || !statSync12(filePath).isFile()) return c2.text("not found", 404);
35876
- const content = readFileSync24(filePath);
36016
+ if (!existsSync36(filePath) || !statSync12(filePath).isFile()) return c2.text("not found", 404);
36017
+ const content = readFileSync25(filePath);
35877
36018
  return new Response(content, {
35878
36019
  headers: { "Content-Type": getMimeType(filePath), "Cache-Control": "no-store" }
35879
36020
  });
35880
36021
  });
35881
36022
  app.get("*", (c2) => {
35882
36023
  const indexPath = resolve20(studioDir, "index.html");
35883
- if (!existsSync34(indexPath)) {
36024
+ if (!existsSync36(indexPath)) {
35884
36025
  return c2.html(
35885
36026
  `<!doctype html>
35886
36027
  <html>
@@ -35936,7 +36077,7 @@ function createStudioServer(options) {
35936
36077
  500
35937
36078
  );
35938
36079
  }
35939
- return c2.html(readFileSync24(indexPath, "utf-8"));
36080
+ return c2.html(readFileSync25(indexPath, "utf-8"));
35940
36081
  });
35941
36082
  return { app, watcher };
35942
36083
  }
@@ -35959,21 +36100,21 @@ __export(preview_exports, {
35959
36100
  default: () => preview_default,
35960
36101
  examples: () => examples
35961
36102
  });
35962
- import { spawn as spawn8 } from "child_process";
35963
- import { existsSync as existsSync35, lstatSync, symlinkSync, unlinkSync as unlinkSync5, readlinkSync, mkdirSync as mkdirSync20 } from "fs";
35964
- import { resolve as resolve21, dirname as dirname13, basename as basename4, join as join37 } from "path";
36103
+ import { spawn as spawn9 } from "child_process";
36104
+ import { existsSync as existsSync37, lstatSync, symlinkSync, unlinkSync as unlinkSync5, readlinkSync, mkdirSync as mkdirSync22 } from "fs";
36105
+ import { resolve as resolve21, dirname as dirname13, basename as basename4, join as join39 } from "path";
35965
36106
  import { fileURLToPath as fileURLToPath4 } from "url";
35966
36107
  import { createRequire } from "module";
35967
36108
  async function runDevMode(dir, projectName) {
35968
36109
  const thisFile = fileURLToPath4(import.meta.url);
35969
36110
  const repoRoot = resolve21(dirname13(thisFile), "..", "..", "..", "..");
35970
- const projectsDir = join37(repoRoot, "packages", "studio", "data", "projects");
36111
+ const projectsDir = join39(repoRoot, "packages", "studio", "data", "projects");
35971
36112
  const pName = projectName ?? basename4(dir);
35972
- const symlinkPath = join37(projectsDir, pName);
35973
- mkdirSync20(projectsDir, { recursive: true });
36113
+ const symlinkPath = join39(projectsDir, pName);
36114
+ mkdirSync22(projectsDir, { recursive: true });
35974
36115
  let createdSymlink = false;
35975
36116
  if (dir !== symlinkPath) {
35976
- if (existsSync35(symlinkPath)) {
36117
+ if (existsSync37(symlinkPath)) {
35977
36118
  try {
35978
36119
  const stat3 = lstatSync(symlinkPath);
35979
36120
  if (stat3.isSymbolicLink()) {
@@ -35985,7 +36126,7 @@ async function runDevMode(dir, projectName) {
35985
36126
  } catch {
35986
36127
  }
35987
36128
  }
35988
- if (!existsSync35(symlinkPath)) {
36129
+ if (!existsSync37(symlinkPath)) {
35989
36130
  symlinkSync(dir, symlinkPath, "dir");
35990
36131
  createdSymlink = true;
35991
36132
  }
@@ -35993,8 +36134,8 @@ async function runDevMode(dir, projectName) {
35993
36134
  Wt2(c.bold("hyperframes preview"));
35994
36135
  const s2 = be();
35995
36136
  s2.start("Starting studio...");
35996
- const studioPkgDir = join37(repoRoot, "packages", "studio");
35997
- const child = spawn8("pnpm", ["exec", "vite"], {
36137
+ const studioPkgDir = join39(repoRoot, "packages", "studio");
36138
+ const child = spawn9("pnpm", ["exec", "vite"], {
35998
36139
  cwd: studioPkgDir,
35999
36140
  stdio: ["ignore", "pipe", "pipe"]
36000
36141
  });
@@ -36027,7 +36168,7 @@ async function runDevMode(dir, projectName) {
36027
36168
  if (createdSymlink) {
36028
36169
  process.on("exit", () => {
36029
36170
  try {
36030
- if (existsSync35(symlinkPath)) unlinkSync5(symlinkPath);
36171
+ if (existsSync37(symlinkPath)) unlinkSync5(symlinkPath);
36031
36172
  } catch {
36032
36173
  }
36033
36174
  });
@@ -36038,7 +36179,7 @@ async function runDevMode(dir, projectName) {
36038
36179
  }
36039
36180
  function hasLocalStudio(dir) {
36040
36181
  try {
36041
- const req = createRequire(join37(dir, "package.json"));
36182
+ const req = createRequire(join39(dir, "package.json"));
36042
36183
  req.resolve("@hyperframes/studio/package.json");
36043
36184
  return true;
36044
36185
  } catch {
@@ -36046,20 +36187,20 @@ function hasLocalStudio(dir) {
36046
36187
  }
36047
36188
  }
36048
36189
  async function runLocalStudioMode(dir, projectName) {
36049
- const req = createRequire(join37(dir, "package.json"));
36190
+ const req = createRequire(join39(dir, "package.json"));
36050
36191
  const studioPkgPath = dirname13(req.resolve("@hyperframes/studio/package.json"));
36051
36192
  const pName = projectName ?? basename4(dir);
36052
- const projectsDir = join37(studioPkgPath, "data", "projects");
36053
- const symlinkPath = join37(projectsDir, pName);
36054
- mkdirSync20(projectsDir, { recursive: true });
36193
+ const projectsDir = join39(studioPkgPath, "data", "projects");
36194
+ const symlinkPath = join39(projectsDir, pName);
36195
+ mkdirSync22(projectsDir, { recursive: true });
36055
36196
  let createdSymlink = false;
36056
36197
  if (dir !== symlinkPath) {
36057
- if (existsSync35(symlinkPath) && lstatSync(symlinkPath).isSymbolicLink()) {
36198
+ if (existsSync37(symlinkPath) && lstatSync(symlinkPath).isSymbolicLink()) {
36058
36199
  if (resolve21(readlinkSync(symlinkPath)) !== resolve21(dir)) {
36059
36200
  unlinkSync5(symlinkPath);
36060
36201
  }
36061
36202
  }
36062
- if (!existsSync35(symlinkPath)) {
36203
+ if (!existsSync37(symlinkPath)) {
36063
36204
  symlinkSync(dir, symlinkPath, "dir");
36064
36205
  createdSymlink = true;
36065
36206
  }
@@ -36067,7 +36208,7 @@ async function runLocalStudioMode(dir, projectName) {
36067
36208
  Wt2(c.bold("hyperframes preview") + c.dim(" (local studio)"));
36068
36209
  const s2 = be();
36069
36210
  s2.start("Starting studio...");
36070
- const child = spawn8("npx", ["vite"], {
36211
+ const child = spawn9("npx", ["vite"], {
36071
36212
  cwd: studioPkgPath,
36072
36213
  stdio: ["ignore", "pipe", "pipe"]
36073
36214
  });
@@ -36098,7 +36239,7 @@ async function runLocalStudioMode(dir, projectName) {
36098
36239
  if (createdSymlink) {
36099
36240
  process.on("exit", () => {
36100
36241
  try {
36101
- if (existsSync35(symlinkPath)) unlinkSync5(symlinkPath);
36242
+ if (existsSync37(symlinkPath)) unlinkSync5(symlinkPath);
36102
36243
  } catch {
36103
36244
  }
36104
36245
  });
@@ -36274,8 +36415,8 @@ var init_preview2 = __esm({
36274
36415
  const dir = resolve21(rawArg ?? ".");
36275
36416
  const isImplicitCwd = !rawArg || rawArg === "." || rawArg === "./";
36276
36417
  const projectName = isImplicitCwd ? basename4(process.env.PWD ?? dir) : basename4(dir);
36277
- const indexPath = join37(dir, "index.html");
36278
- if (existsSync35(indexPath)) {
36418
+ const indexPath = join39(dir, "index.html");
36419
+ if (existsSync37(indexPath)) {
36279
36420
  const project = { dir, name: projectName, indexPath };
36280
36421
  const lintResult = lintProject(project);
36281
36422
  if (lintResult.totalErrors > 0 || lintResult.totalWarnings > 0) {
@@ -36304,17 +36445,17 @@ __export(init_exports, {
36304
36445
  examples: () => examples2
36305
36446
  });
36306
36447
  import {
36307
- existsSync as existsSync36,
36308
- mkdirSync as mkdirSync21,
36448
+ existsSync as existsSync38,
36449
+ mkdirSync as mkdirSync23,
36309
36450
  copyFileSync as copyFileSync3,
36310
36451
  cpSync,
36311
- writeFileSync as writeFileSync15,
36312
- readFileSync as readFileSync25,
36452
+ writeFileSync as writeFileSync17,
36453
+ readFileSync as readFileSync26,
36313
36454
  readdirSync as readdirSync14
36314
36455
  } from "fs";
36315
- import { resolve as resolve22, basename as basename5, join as join38, dirname as dirname14 } from "path";
36456
+ import { resolve as resolve22, basename as basename5, join as join40, dirname as dirname14 } from "path";
36316
36457
  import { fileURLToPath as fileURLToPath5 } from "url";
36317
- import { execFileSync as execFileSync4, spawn as spawn9 } from "child_process";
36458
+ import { execFileSync as execFileSync4, spawn as spawn10 } from "child_process";
36318
36459
  function probeVideo(filePath) {
36319
36460
  try {
36320
36461
  const raw = execFileSync4(
@@ -36356,7 +36497,7 @@ function isWebCompatible(codec) {
36356
36497
  }
36357
36498
  function transcodeToMp4(inputPath, outputPath) {
36358
36499
  return new Promise((resolvePromise) => {
36359
- const child = spawn9(
36500
+ const child = spawn10(
36360
36501
  "ffmpeg",
36361
36502
  [
36362
36503
  "-i",
@@ -36384,7 +36525,7 @@ function resolveAssetDir(devSegments, builtSegments) {
36384
36525
  const base = dirname14(fileURLToPath5(import.meta.url));
36385
36526
  const devPath = resolve22(base, ...devSegments);
36386
36527
  const builtPath = resolve22(base, ...builtSegments);
36387
- return existsSync36(devPath) ? devPath : builtPath;
36528
+ return existsSync38(devPath) ? devPath : builtPath;
36388
36529
  }
36389
36530
  function getStaticTemplateDir(templateId) {
36390
36531
  return resolveAssetDir(["..", "templates", templateId], ["templates", templateId]);
@@ -36393,9 +36534,9 @@ function getSharedTemplateDir() {
36393
36534
  return resolveAssetDir(["..", "templates", "_shared"], ["templates", "_shared"]);
36394
36535
  }
36395
36536
  function patchVideoSrc(dir, videoFilename, durationSeconds) {
36396
- const htmlFiles = readdirSync14(dir, { withFileTypes: true, recursive: true }).filter((e2) => e2.isFile() && e2.name.endsWith(".html")).map((e2) => join38(e2.parentPath ?? e2.path, e2.name));
36537
+ const htmlFiles = readdirSync14(dir, { withFileTypes: true, recursive: true }).filter((e2) => e2.isFile() && e2.name.endsWith(".html")).map((e2) => join40(e2.parentPath ?? e2.path, e2.name));
36397
36538
  for (const file of htmlFiles) {
36398
- let content = readFileSync25(file, "utf-8");
36539
+ let content = readFileSync26(file, "utf-8");
36399
36540
  if (videoFilename) {
36400
36541
  content = content.replaceAll("__VIDEO_SRC__", videoFilename);
36401
36542
  } else {
@@ -36406,7 +36547,7 @@ function patchVideoSrc(dir, videoFilename, durationSeconds) {
36406
36547
  }
36407
36548
  const dur = durationSeconds ? String(Math.round(durationSeconds * 100) / 100) : "10";
36408
36549
  content = content.replaceAll("__VIDEO_DURATION__", dur);
36409
- writeFileSync15(file, content, "utf-8");
36550
+ writeFileSync17(file, content, "utf-8");
36410
36551
  }
36411
36552
  }
36412
36553
  async function patchTranscript(dir, transcriptPath) {
@@ -36498,15 +36639,15 @@ async function handleVideoFile(videoPath, destDir, interactive) {
36498
36639
  return { meta, localVideoName };
36499
36640
  }
36500
36641
  async function scaffoldProject(destDir, name, templateId, localVideoName, durationSeconds) {
36501
- mkdirSync21(destDir, { recursive: true });
36642
+ mkdirSync23(destDir, { recursive: true });
36502
36643
  const templateDir = getStaticTemplateDir(templateId);
36503
- if (existsSync36(templateDir)) {
36644
+ if (existsSync38(templateDir)) {
36504
36645
  cpSync(templateDir, destDir, { recursive: true });
36505
36646
  } else {
36506
36647
  await fetchRemoteTemplate(templateId, destDir);
36507
36648
  }
36508
36649
  patchVideoSrc(destDir, localVideoName, durationSeconds);
36509
- writeFileSync15(
36650
+ writeFileSync17(
36510
36651
  resolve22(destDir, "meta.json"),
36511
36652
  JSON.stringify(
36512
36653
  {
@@ -36519,14 +36660,14 @@ async function scaffoldProject(destDir, name, templateId, localVideoName, durati
36519
36660
  ),
36520
36661
  "utf-8"
36521
36662
  );
36522
- if (!existsSync36(resolve22(destDir, "hyperframes.json"))) {
36663
+ if (!existsSync38(resolve22(destDir, "hyperframes.json"))) {
36523
36664
  const { writeProjectConfig: writeProjectConfig2, DEFAULT_PROJECT_CONFIG: DEFAULT_PROJECT_CONFIG2 } = await Promise.resolve().then(() => (init_projectConfig(), projectConfig_exports));
36524
36665
  writeProjectConfig2(destDir, DEFAULT_PROJECT_CONFIG2);
36525
36666
  }
36526
36667
  const sharedDir = getSharedTemplateDir();
36527
- if (existsSync36(sharedDir)) {
36668
+ if (existsSync38(sharedDir)) {
36528
36669
  for (const entry of readdirSync14(sharedDir, { withFileTypes: true })) {
36529
- const src = join38(sharedDir, entry.name);
36670
+ const src = join40(sharedDir, entry.name);
36530
36671
  const dest = resolve22(destDir, entry.name);
36531
36672
  if (entry.isFile() || entry.isSymbolicLink()) {
36532
36673
  copyFileSync3(src, dest);
@@ -36640,11 +36781,11 @@ var init_init = __esm({
36640
36781
  const templateId2 = exampleFlag ?? "blank";
36641
36782
  const name2 = args.name ?? "my-video";
36642
36783
  const destDir2 = resolve22(name2);
36643
- if (existsSync36(destDir2) && readdirSync14(destDir2).length > 0) {
36784
+ if (existsSync38(destDir2) && readdirSync14(destDir2).length > 0) {
36644
36785
  console.error(c.error(`Directory already exists and is not empty: ${name2}`));
36645
36786
  process.exit(1);
36646
36787
  }
36647
- mkdirSync21(destDir2, { recursive: true });
36788
+ mkdirSync23(destDir2, { recursive: true });
36648
36789
  let localVideoName2;
36649
36790
  let videoDuration2;
36650
36791
  let sourceFilePath2;
@@ -36654,7 +36795,7 @@ var init_init = __esm({
36654
36795
  }
36655
36796
  if (videoFlag) {
36656
36797
  const videoPath = resolve22(videoFlag);
36657
- if (!existsSync36(videoPath)) {
36798
+ if (!existsSync38(videoPath)) {
36658
36799
  console.error(c.error(`Video file not found: ${videoFlag}`));
36659
36800
  process.exit(1);
36660
36801
  }
@@ -36668,7 +36809,7 @@ var init_init = __esm({
36668
36809
  }
36669
36810
  if (audioFlag) {
36670
36811
  const audioPath = resolve22(audioFlag);
36671
- if (!existsSync36(audioPath)) {
36812
+ if (!existsSync38(audioPath)) {
36672
36813
  console.error(c.error(`Audio file not found: ${audioFlag}`));
36673
36814
  process.exit(1);
36674
36815
  }
@@ -36714,7 +36855,7 @@ var init_init = __esm({
36714
36855
  }
36715
36856
  trackInitTemplate(templateId2);
36716
36857
  const transcriptFile2 = resolve22(destDir2, "transcript.json");
36717
- if (existsSync36(transcriptFile2)) {
36858
+ if (existsSync38(transcriptFile2)) {
36718
36859
  await patchTranscript(destDir2, transcriptFile2);
36719
36860
  }
36720
36861
  console.log(c.success(`Created ${c.accent(name2 + "/")}`));
@@ -36766,7 +36907,7 @@ var init_init = __esm({
36766
36907
  name = nameResult;
36767
36908
  }
36768
36909
  const destDir = resolve22(name);
36769
- if (existsSync36(destDir) && readdirSync14(destDir).length > 0) {
36910
+ if (existsSync38(destDir) && readdirSync14(destDir).length > 0) {
36770
36911
  const overwrite = await Rt({
36771
36912
  message: `Directory ${c.accent(name)} already exists and is not empty. Overwrite?`,
36772
36913
  initialValue: false
@@ -36781,24 +36922,24 @@ var init_init = __esm({
36781
36922
  let videoDuration;
36782
36923
  if (videoFlag) {
36783
36924
  const videoPath = resolve22(videoFlag);
36784
- if (!existsSync36(videoPath)) {
36925
+ if (!existsSync38(videoPath)) {
36785
36926
  R2.error(`File not found: ${videoFlag}`);
36786
36927
  Nt("Setup cancelled.");
36787
36928
  process.exit(1);
36788
36929
  }
36789
- mkdirSync21(destDir, { recursive: true });
36930
+ mkdirSync23(destDir, { recursive: true });
36790
36931
  sourceFilePath = videoPath;
36791
36932
  const result = await handleVideoFile(videoPath, destDir, true);
36792
36933
  localVideoName = result.localVideoName;
36793
36934
  videoDuration = result.meta.durationSeconds;
36794
36935
  } else if (audioFlag) {
36795
36936
  const audioPath = resolve22(audioFlag);
36796
- if (!existsSync36(audioPath)) {
36937
+ if (!existsSync38(audioPath)) {
36797
36938
  R2.error(`File not found: ${audioFlag}`);
36798
36939
  Nt("Setup cancelled.");
36799
36940
  process.exit(1);
36800
36941
  }
36801
- mkdirSync21(destDir, { recursive: true });
36942
+ mkdirSync23(destDir, { recursive: true });
36802
36943
  sourceFilePath = audioPath;
36803
36944
  copyFileSync3(audioPath, resolve22(destDir, basename5(audioPath)));
36804
36945
  R2.info(`Audio copied to ${c.accent(basename5(audioPath))}`);
@@ -36886,7 +37027,7 @@ ${c.dim("Use --example blank for offline use.")}`
36886
37027
  }
36887
37028
  trackInitTemplate(templateId);
36888
37029
  const transcriptFile = resolve22(destDir, "transcript.json");
36889
- if (existsSync36(transcriptFile)) {
37030
+ if (existsSync38(transcriptFile)) {
36890
37031
  await patchTranscript(destDir, transcriptFile);
36891
37032
  }
36892
37033
  const files = readdirSync14(destDir);
@@ -36972,7 +37113,7 @@ __export(add_exports, {
36972
37113
  remapTarget: () => remapTarget,
36973
37114
  runAdd: () => runAdd
36974
37115
  });
36975
- import { existsSync as existsSync37 } from "fs";
37116
+ import { existsSync as existsSync39 } from "fs";
36976
37117
  import { resolve as resolve23, relative as relative3 } from "path";
36977
37118
  function remapTarget(item, originalTarget, paths) {
36978
37119
  if (item.type === "hyperframes:block") {
@@ -36998,8 +37139,8 @@ function buildSnippet(item, relativeTarget) {
36998
37139
  async function runAdd(opts) {
36999
37140
  const projectDir = resolve23(opts.projectDir);
37000
37141
  let config = loadProjectConfig(projectDir);
37001
- const hasConfig = existsSync37(projectConfigPath(projectDir));
37002
- if (!hasConfig && existsSync37(resolve23(projectDir, "index.html"))) {
37142
+ const hasConfig = existsSync39(projectConfigPath(projectDir));
37143
+ if (!hasConfig && existsSync39(resolve23(projectDir, "index.html"))) {
37003
37144
  writeProjectConfig(projectDir, DEFAULT_PROJECT_CONFIG);
37004
37145
  config = DEFAULT_PROJECT_CONFIG;
37005
37146
  }
@@ -37098,10 +37239,10 @@ var init_add = __esm({
37098
37239
  const projectDir = resolve23(args.dir ?? process.cwd());
37099
37240
  const json = args.json === true;
37100
37241
  const skipClipboard = args["no-clipboard"] === true;
37101
- const hasConfigBefore = existsSync37(projectConfigPath(projectDir));
37242
+ const hasConfigBefore = existsSync39(projectConfigPath(projectDir));
37102
37243
  try {
37103
37244
  const result = await runAdd({ name: args.name, projectDir, skipClipboard });
37104
- const wroteConfig = !hasConfigBefore && existsSync37(projectConfigPath(projectDir));
37245
+ const wroteConfig = !hasConfigBefore && existsSync39(projectConfigPath(projectDir));
37105
37246
  if (json) {
37106
37247
  console.log(JSON.stringify(result));
37107
37248
  return;
@@ -37311,17 +37452,17 @@ var init_format = __esm({
37311
37452
  });
37312
37453
 
37313
37454
  // src/utils/project.ts
37314
- import { existsSync as existsSync38, statSync as statSync13 } from "fs";
37455
+ import { existsSync as existsSync40, statSync as statSync13 } from "fs";
37315
37456
  import { resolve as resolve25, basename as basename6 } from "path";
37316
37457
  function resolveProject(dirArg) {
37317
37458
  const dir = resolve25(dirArg ?? ".");
37318
37459
  const name = basename6(dir);
37319
37460
  const indexPath = resolve25(dir, "index.html");
37320
- if (!existsSync38(dir) || !statSync13(dir).isDirectory()) {
37461
+ if (!existsSync40(dir) || !statSync13(dir).isDirectory()) {
37321
37462
  errorBox("Not a directory: " + dir);
37322
37463
  process.exit(1);
37323
37464
  }
37324
- if (!existsSync38(indexPath)) {
37465
+ if (!existsSync40(indexPath)) {
37325
37466
  errorBox(
37326
37467
  "No composition found in " + dir,
37327
37468
  "No index.html file found.",
@@ -37344,7 +37485,7 @@ __export(play_exports, {
37344
37485
  default: () => play_default,
37345
37486
  examples: () => examples5
37346
37487
  });
37347
- import { existsSync as existsSync39, readFileSync as readFileSync26 } from "fs";
37488
+ import { existsSync as existsSync41, readFileSync as readFileSync27 } from "fs";
37348
37489
  import { resolve as resolve26, dirname as dirname15 } from "path";
37349
37490
  function commandDir() {
37350
37491
  return dirname15(new URL(import.meta.url).pathname);
@@ -37359,7 +37500,7 @@ function resolveRuntimePath2() {
37359
37500
  resolve26(d, "..", "..", "..", "core", "dist", "hyperframe.runtime.iife.js")
37360
37501
  ];
37361
37502
  for (const p of candidates) {
37362
- if (existsSync39(p)) return p;
37503
+ if (existsSync41(p)) return p;
37363
37504
  }
37364
37505
  return null;
37365
37506
  }
@@ -37373,7 +37514,7 @@ function resolvePlayerPath() {
37373
37514
  resolve26(d, "..", "hyperframes-player.global.js")
37374
37515
  ];
37375
37516
  for (const p of candidates) {
37376
- if (existsSync39(p)) return p;
37517
+ if (existsSync41(p)) return p;
37377
37518
  }
37378
37519
  return null;
37379
37520
  }
@@ -37460,13 +37601,13 @@ var init_play = __esm({
37460
37601
  const { createAdaptorServer } = await import("@hono/node-server");
37461
37602
  const app = new Hono6();
37462
37603
  app.get("/player.js", (ctx) => {
37463
- return ctx.body(readFileSync26(playerPath, "utf-8"), 200, {
37604
+ return ctx.body(readFileSync27(playerPath, "utf-8"), 200, {
37464
37605
  "Content-Type": "application/javascript",
37465
37606
  "Cache-Control": "no-cache"
37466
37607
  });
37467
37608
  });
37468
37609
  app.get("/runtime.js", (ctx) => {
37469
- return ctx.body(readFileSync26(runtimePath, "utf-8"), 200, {
37610
+ return ctx.body(readFileSync27(runtimePath, "utf-8"), 200, {
37470
37611
  "Content-Type": "application/javascript",
37471
37612
  "Cache-Control": "no-cache"
37472
37613
  });
@@ -37475,8 +37616,8 @@ var init_play = __esm({
37475
37616
  const reqPath = ctx.req.path.replace("/composition/", "");
37476
37617
  const filePath = resolve26(project.dir, reqPath);
37477
37618
  if (!filePath.startsWith(project.dir)) return ctx.text("Forbidden", 403);
37478
- if (!existsSync39(filePath)) return ctx.text("Not found", 404);
37479
- const content = readFileSync26(filePath, "utf-8");
37619
+ if (!existsSync41(filePath)) return ctx.text("Not found", 404);
37620
+ const content = readFileSync27(filePath, "utf-8");
37480
37621
  if (filePath.endsWith(".html")) {
37481
37622
  const injected = injectRuntime(content);
37482
37623
  return ctx.html(injected);
@@ -37495,7 +37636,7 @@ var init_play = __esm({
37495
37636
  mp3: "audio/mpeg",
37496
37637
  wav: "audio/wav"
37497
37638
  };
37498
- return ctx.body(readFileSync26(filePath), 200, {
37639
+ return ctx.body(readFileSync27(filePath), 200, {
37499
37640
  "Content-Type": types3[ext] ?? "application/octet-stream"
37500
37641
  });
37501
37642
  });
@@ -37551,8 +37692,8 @@ var init_play = __esm({
37551
37692
  });
37552
37693
 
37553
37694
  // src/utils/publishProject.ts
37554
- import { basename as basename7, join as join39, relative as relative4 } from "path";
37555
- import { readdirSync as readdirSync15, readFileSync as readFileSync27, statSync as statSync14 } from "fs";
37695
+ import { basename as basename7, join as join41, relative as relative4 } from "path";
37696
+ import { readdirSync as readdirSync15, readFileSync as readFileSync28, statSync as statSync14 } from "fs";
37556
37697
  import AdmZip from "adm-zip";
37557
37698
  function isRecord(value) {
37558
37699
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -37643,7 +37784,7 @@ function shouldIgnoreSegment(segment) {
37643
37784
  function collectProjectFiles(rootDir, currentDir, paths) {
37644
37785
  for (const entry of readdirSync15(currentDir, { withFileTypes: true })) {
37645
37786
  if (shouldIgnoreSegment(entry.name)) continue;
37646
- const absolutePath = join39(currentDir, entry.name);
37787
+ const absolutePath = join41(currentDir, entry.name);
37647
37788
  const relativePath = relative4(rootDir, absolutePath).replaceAll("\\", "/");
37648
37789
  if (!relativePath) continue;
37649
37790
  if (entry.isDirectory()) {
@@ -37662,7 +37803,7 @@ function createPublishArchive(projectDir) {
37662
37803
  }
37663
37804
  const archive = new AdmZip();
37664
37805
  for (const filePath of filePaths) {
37665
- archive.addFile(filePath, readFileSync27(join39(projectDir, filePath)));
37806
+ archive.addFile(filePath, readFileSync28(join41(projectDir, filePath)));
37666
37807
  }
37667
37808
  return {
37668
37809
  buffer: archive.toBuffer(),
@@ -37778,8 +37919,8 @@ __export(publish_exports, {
37778
37919
  examples: () => examples6
37779
37920
  });
37780
37921
  import { basename as basename8, resolve as resolve27 } from "path";
37781
- import { existsSync as existsSync40 } from "fs";
37782
- import { join as join40 } from "path";
37922
+ import { existsSync as existsSync42 } from "fs";
37923
+ import { join as join42 } from "path";
37783
37924
  var examples6, publish_default;
37784
37925
  var init_publish = __esm({
37785
37926
  "src/commands/publish.ts"() {
@@ -37814,8 +37955,8 @@ var init_publish = __esm({
37814
37955
  const dir = resolve27(rawArg ?? ".");
37815
37956
  const isImplicitCwd = !rawArg || rawArg === "." || rawArg === "./";
37816
37957
  const projectName = isImplicitCwd ? basename8(process.env["PWD"] ?? dir) : basename8(dir);
37817
- const indexPath = join40(dir, "index.html");
37818
- if (existsSync40(indexPath)) {
37958
+ const indexPath = join42(dir, "index.html");
37959
+ if (existsSync42(indexPath)) {
37819
37960
  const lintResult = lintProject({ dir, name: projectName, indexPath });
37820
37961
  if (lintResult.totalErrors > 0 || lintResult.totalWarnings > 0) {
37821
37962
  console.log();
@@ -37986,10 +38127,10 @@ __export(render_exports, {
37986
38127
  default: () => render_default,
37987
38128
  examples: () => examples7
37988
38129
  });
37989
- import { mkdirSync as mkdirSync22, readFileSync as readFileSync28, statSync as statSync15, writeFileSync as writeFileSync16, rmSync as rmSync9 } from "fs";
38130
+ import { mkdirSync as mkdirSync24, readFileSync as readFileSync29, statSync as statSync15, writeFileSync as writeFileSync18, rmSync as rmSync9 } from "fs";
37990
38131
  import { cpus as cpus3, freemem as freemem3, tmpdir as tmpdir4 } from "os";
37991
- import { resolve as resolve28, dirname as dirname16, join as join41, basename as basename9 } from "path";
37992
- import { execFileSync as execFileSync5, spawn as spawn10 } from "child_process";
38132
+ import { resolve as resolve28, dirname as dirname16, join as join43, basename as basename9 } from "path";
38133
+ import { execFileSync as execFileSync5, spawn as spawn11 } from "child_process";
37993
38134
  function defaultWorkerCount() {
37994
38135
  return Math.max(1, Math.min(Math.floor(CPU_CORE_COUNT * 3 / 4), 8));
37995
38136
  }
@@ -38025,9 +38166,9 @@ function ensureDockerImage(version, quiet) {
38025
38166
  }
38026
38167
  if (!quiet) console.log(c.dim(` Building Docker image: ${tag}...`));
38027
38168
  const dockerfilePath = resolveDockerfilePath();
38028
- const tmpDir = join41(tmpdir4(), `hyperframes-docker-${Date.now()}`);
38029
- mkdirSync22(tmpDir, { recursive: true });
38030
- writeFileSync16(join41(tmpDir, "Dockerfile"), readFileSync28(dockerfilePath));
38169
+ const tmpDir = join43(tmpdir4(), `hyperframes-docker-${Date.now()}`);
38170
+ mkdirSync24(tmpDir, { recursive: true });
38171
+ writeFileSync18(join43(tmpDir, "Dockerfile"), readFileSync29(dockerfilePath));
38031
38172
  try {
38032
38173
  execFileSync5(
38033
38174
  "docker",
@@ -38096,7 +38237,7 @@ async function renderDocker(projectDir, outputPath, options) {
38096
38237
  }
38097
38238
  try {
38098
38239
  await new Promise((resolvePromise, reject) => {
38099
- const child = spawn10("docker", dockerArgs, {
38240
+ const child = spawn11("docker", dockerArgs, {
38100
38241
  // When quiet, still show stderr so container errors surface
38101
38242
  stdio: options.quiet ? ["pipe", "pipe", "inherit"] : "inherit"
38102
38243
  });
@@ -38375,8 +38516,8 @@ var init_render2 = __esm({
38375
38516
  const now = /* @__PURE__ */ new Date();
38376
38517
  const datePart = now.toISOString().slice(0, 10);
38377
38518
  const timePart = now.toTimeString().slice(0, 8).replace(/:/g, "-");
38378
- const outputPath = args.output ? resolve28(args.output) : join41(rendersDir, `${project.name}_${datePart}_${timePart}${ext}`);
38379
- mkdirSync22(dirname16(outputPath), { recursive: true });
38519
+ const outputPath = args.output ? resolve28(args.output) : join43(rendersDir, `${project.name}_${datePart}_${timePart}${ext}`);
38520
+ mkdirSync24(dirname16(outputPath), { recursive: true });
38380
38521
  const useDocker = args.docker ?? false;
38381
38522
  const useGpu = args.gpu ?? false;
38382
38523
  const quiet = args.quiet ?? false;
@@ -38851,8 +38992,8 @@ __export(layout_exports, {
38851
38992
  examples: () => examples9
38852
38993
  });
38853
38994
  import { createServer } from "http";
38854
- import { existsSync as existsSync41, readFileSync as readFileSync29 } from "fs";
38855
- import { dirname as dirname17, isAbsolute as isAbsolute6, join as join42, relative as relative5, resolve as resolve29 } from "path";
38995
+ import { existsSync as existsSync43, readFileSync as readFileSync30 } from "fs";
38996
+ import { dirname as dirname17, isAbsolute as isAbsolute6, join as join44, relative as relative5, resolve as resolve29 } from "path";
38856
38997
  import { fileURLToPath as fileURLToPath6 } from "url";
38857
38998
  async function getCompositionDuration2(page) {
38858
38999
  return page.evaluate(() => {
@@ -38922,8 +39063,8 @@ async function bundleProjectHtml(projectDir) {
38922
39063
  "dist",
38923
39064
  "hyperframe.runtime.iife.js"
38924
39065
  );
38925
- if (existsSync41(runtimePath)) {
38926
- const runtimeSource = readFileSync29(runtimePath, "utf-8");
39066
+ if (existsSync43(runtimePath)) {
39067
+ const runtimeSource = readFileSync30(runtimePath, "utf-8");
38927
39068
  html = html.replace(
38928
39069
  /<script[^>]*data-hyperframes-preview-runtime[^>]*src="[^"]*"[^>]*><\/script>/,
38929
39070
  () => `<script data-hyperframes-preview-runtime="1">${runtimeSource}</script>`
@@ -38947,9 +39088,9 @@ async function serveProject(projectDir, html) {
38947
39088
  res.end();
38948
39089
  return;
38949
39090
  }
38950
- if (existsSync41(filePath)) {
39091
+ if (existsSync43(filePath)) {
38951
39092
  res.writeHead(200, { "Content-Type": getMimeType2(filePath) });
38952
- res.end(readFileSync29(filePath));
39093
+ res.end(readFileSync30(filePath));
38953
39094
  return;
38954
39095
  }
38955
39096
  res.writeHead(404);
@@ -39051,11 +39192,11 @@ async function runLayoutAudit(projectDir, opts) {
39051
39192
  }
39052
39193
  function loadLayoutAuditScript() {
39053
39194
  const candidates = [
39054
- join42(__dirname2, "layout-audit.browser.js"),
39055
- join42(__dirname2, "commands", "layout-audit.browser.js")
39195
+ join44(__dirname2, "layout-audit.browser.js"),
39196
+ join44(__dirname2, "commands", "layout-audit.browser.js")
39056
39197
  ];
39057
39198
  for (const candidate of candidates) {
39058
- if (existsSync41(candidate)) return readFileSync29(candidate, "utf-8");
39199
+ if (existsSync43(candidate)) return readFileSync30(candidate, "utf-8");
39059
39200
  }
39060
39201
  throw new Error("Missing layout audit browser script");
39061
39202
  }
@@ -39275,12 +39416,12 @@ __export(info_exports, {
39275
39416
  default: () => info_default,
39276
39417
  examples: () => examples11
39277
39418
  });
39278
- import { readFileSync as readFileSync30, readdirSync as readdirSync16, statSync as statSync16 } from "fs";
39279
- import { join as join43 } from "path";
39419
+ import { readFileSync as readFileSync31, readdirSync as readdirSync16, statSync as statSync16 } from "fs";
39420
+ import { join as join45 } from "path";
39280
39421
  function totalSize(dir) {
39281
39422
  let total = 0;
39282
39423
  for (const entry of readdirSync16(dir, { withFileTypes: true })) {
39283
- const path2 = join43(dir, entry.name);
39424
+ const path2 = join45(dir, entry.name);
39284
39425
  if (entry.isDirectory()) {
39285
39426
  total += totalSize(path2);
39286
39427
  } else {
@@ -39312,7 +39453,7 @@ var init_info = __esm({
39312
39453
  },
39313
39454
  async run({ args }) {
39314
39455
  const project = resolveProject(args.dir);
39315
- const html = readFileSync30(project.indexPath, "utf-8");
39456
+ const html = readFileSync31(project.indexPath, "utf-8");
39316
39457
  ensureDOMParser();
39317
39458
  const parsed = parseHtml(html);
39318
39459
  const tracks = new Set(parsed.elements.map((el) => el.zIndex));
@@ -39368,7 +39509,7 @@ __export(compositions_exports, {
39368
39509
  default: () => compositions_default,
39369
39510
  examples: () => examples12
39370
39511
  });
39371
- import { existsSync as existsSync42, readFileSync as readFileSync31 } from "fs";
39512
+ import { existsSync as existsSync44, readFileSync as readFileSync32 } from "fs";
39372
39513
  import { resolve as resolve30, dirname as dirname18 } from "path";
39373
39514
  function parseCompositions(html, baseDir) {
39374
39515
  const parser = new DOMParser();
@@ -39382,8 +39523,8 @@ function parseCompositions(html, baseDir) {
39382
39523
  const compositionSrc = div.getAttribute("data-composition-src");
39383
39524
  if (compositionSrc) {
39384
39525
  const subPath = resolve30(baseDir, compositionSrc);
39385
- if (existsSync42(subPath)) {
39386
- const subHtml = readFileSync31(subPath, "utf-8");
39526
+ if (existsSync44(subPath)) {
39527
+ const subHtml = readFileSync32(subPath, "utf-8");
39387
39528
  const subInfo = parseSubComposition(subHtml, id, width, height);
39388
39529
  compositions.push({ ...subInfo, source: compositionSrc });
39389
39530
  return;
@@ -39477,7 +39618,7 @@ var init_compositions = __esm({
39477
39618
  },
39478
39619
  async run({ args }) {
39479
39620
  const project = resolveProject(args.dir);
39480
- const html = readFileSync31(project.indexPath, "utf-8");
39621
+ const html = readFileSync32(project.indexPath, "utf-8");
39481
39622
  ensureDOMParser();
39482
39623
  const compositions = parseCompositions(html, dirname18(project.indexPath));
39483
39624
  if (compositions.length === 0) {
@@ -39515,8 +39656,8 @@ __export(benchmark_exports, {
39515
39656
  default: () => benchmark_default,
39516
39657
  examples: () => examples13
39517
39658
  });
39518
- import { existsSync as existsSync43, statSync as statSync17 } from "fs";
39519
- import { resolve as resolve31, join as join44 } from "path";
39659
+ import { existsSync as existsSync45, statSync as statSync17 } from "fs";
39660
+ import { resolve as resolve31, join as join46 } from "path";
39520
39661
  var examples13, DEFAULT_CONFIGS, benchmark_default;
39521
39662
  var init_benchmark = __esm({
39522
39663
  "src/commands/benchmark.ts"() {
@@ -39591,7 +39732,7 @@ var init_benchmark = __esm({
39591
39732
  s2?.start(`Benchmarking ${config.label}...`);
39592
39733
  for (let i2 = 0; i2 < runsPerConfig; i2++) {
39593
39734
  s2?.message(`${config.label} \u2014 run ${i2 + 1}/${runsPerConfig}`);
39594
- const outputPath = join44(
39735
+ const outputPath = join46(
39595
39736
  benchDir,
39596
39737
  `${config.label.replace(/[^a-zA-Z0-9]/g, "_")}_run${i2}.mp4`
39597
39738
  );
@@ -39605,7 +39746,7 @@ var init_benchmark = __esm({
39605
39746
  await producer.executeRenderJob(job, project.dir, outputPath);
39606
39747
  const elapsedMs = Date.now() - startTime;
39607
39748
  let fileSize = null;
39608
- if (existsSync43(outputPath)) {
39749
+ if (existsSync45(outputPath)) {
39609
39750
  const stat3 = statSync17(outputPath);
39610
39751
  fileSize = stat3.size;
39611
39752
  }
@@ -39821,8 +39962,8 @@ __export(transcribe_exports2, {
39821
39962
  default: () => transcribe_default,
39822
39963
  examples: () => examples15
39823
39964
  });
39824
- import { existsSync as existsSync44, writeFileSync as writeFileSync17 } from "fs";
39825
- import { resolve as resolve32, join as join45, extname as extname8 } from "path";
39965
+ import { existsSync as existsSync46, writeFileSync as writeFileSync19 } from "fs";
39966
+ import { resolve as resolve32, join as join47, extname as extname8 } from "path";
39826
39967
  async function importTranscript(inputPath, dir, json) {
39827
39968
  const { loadTranscript: loadTranscript2, patchCaptionHtml: patchCaptionHtml2 } = await Promise.resolve().then(() => (init_normalize(), normalize_exports));
39828
39969
  const { words, format } = loadTranscript2(inputPath);
@@ -39830,8 +39971,8 @@ async function importTranscript(inputPath, dir, json) {
39830
39971
  console.error(c.error("No words found in transcript."));
39831
39972
  process.exit(1);
39832
39973
  }
39833
- const outPath = join45(dir, "transcript.json");
39834
- writeFileSync17(outPath, JSON.stringify(words, null, 2));
39974
+ const outPath = join47(dir, "transcript.json");
39975
+ writeFileSync19(outPath, JSON.stringify(words, null, 2));
39835
39976
  patchCaptionHtml2(dir, words);
39836
39977
  if (json) {
39837
39978
  console.log(
@@ -39866,7 +40007,7 @@ async function transcribeAudio(inputPath, dir, opts) {
39866
40007
  );
39867
40008
  }
39868
40009
  }
39869
- writeFileSync17(result.transcriptPath, JSON.stringify(words, null, 2));
40010
+ writeFileSync19(result.transcriptPath, JSON.stringify(words, null, 2));
39870
40011
  patchCaptionHtml2(dir, words);
39871
40012
  if (opts.json) {
39872
40013
  console.log(
@@ -39947,7 +40088,7 @@ var init_transcribe2 = __esm({
39947
40088
  },
39948
40089
  async run({ args }) {
39949
40090
  const inputPath = resolve32(args.input);
39950
- if (!existsSync44(inputPath)) {
40091
+ if (!existsSync46(inputPath)) {
39951
40092
  console.error(c.error(`File not found: ${args.input}`));
39952
40093
  process.exit(1);
39953
40094
  }
@@ -39968,9 +40109,9 @@ var init_transcribe2 = __esm({
39968
40109
  });
39969
40110
 
39970
40111
  // src/tts/manager.ts
39971
- import { existsSync as existsSync45, mkdirSync as mkdirSync23 } from "fs";
40112
+ import { existsSync as existsSync47, mkdirSync as mkdirSync25 } from "fs";
39972
40113
  import { homedir as homedir8 } from "os";
39973
- import { join as join46 } from "path";
40114
+ import { join as join48 } from "path";
39974
40115
  function inferLangFromVoiceId(voiceId) {
39975
40116
  const first = voiceId.charAt(0).toLowerCase();
39976
40117
  return VOICE_PREFIX_LANG[first] ?? "en-us";
@@ -39979,29 +40120,29 @@ function isSupportedLang(value) {
39979
40120
  return SUPPORTED_LANGS.includes(value);
39980
40121
  }
39981
40122
  async function ensureModel2(model = DEFAULT_MODEL2, options) {
39982
- const modelPath = join46(MODELS_DIR2, `${model}.onnx`);
39983
- if (existsSync45(modelPath)) return modelPath;
40123
+ const modelPath = join48(MODELS_DIR2, `${model}.onnx`);
40124
+ if (existsSync47(modelPath)) return modelPath;
39984
40125
  const url = MODEL_URLS[model];
39985
40126
  if (!url) {
39986
40127
  throw new Error(
39987
40128
  `Unknown TTS model: ${model}. Available: ${Object.keys(MODEL_URLS).join(", ")}`
39988
40129
  );
39989
40130
  }
39990
- mkdirSync23(MODELS_DIR2, { recursive: true });
40131
+ mkdirSync25(MODELS_DIR2, { recursive: true });
39991
40132
  options?.onProgress?.(`Downloading TTS model ${model} (~311 MB)...`);
39992
40133
  await downloadFile(url, modelPath);
39993
- if (!existsSync45(modelPath)) {
40134
+ if (!existsSync47(modelPath)) {
39994
40135
  throw new Error(`Model download failed: ${model}`);
39995
40136
  }
39996
40137
  return modelPath;
39997
40138
  }
39998
40139
  async function ensureVoices(options) {
39999
- const voicesPath = join46(VOICES_DIR, "voices-v1.0.bin");
40000
- if (existsSync45(voicesPath)) return voicesPath;
40001
- mkdirSync23(VOICES_DIR, { recursive: true });
40140
+ const voicesPath = join48(VOICES_DIR, "voices-v1.0.bin");
40141
+ if (existsSync47(voicesPath)) return voicesPath;
40142
+ mkdirSync25(VOICES_DIR, { recursive: true });
40002
40143
  options?.onProgress?.("Downloading voice data (~27 MB)...");
40003
40144
  await downloadFile(VOICES_URL, voicesPath);
40004
- if (!existsSync45(voicesPath)) {
40145
+ if (!existsSync47(voicesPath)) {
40005
40146
  throw new Error("Voice data download failed");
40006
40147
  }
40007
40148
  return voicesPath;
@@ -40011,9 +40152,9 @@ var init_manager3 = __esm({
40011
40152
  "src/tts/manager.ts"() {
40012
40153
  "use strict";
40013
40154
  init_download();
40014
- CACHE_DIR3 = join46(homedir8(), ".cache", "hyperframes", "tts");
40015
- MODELS_DIR2 = join46(CACHE_DIR3, "models");
40016
- VOICES_DIR = join46(CACHE_DIR3, "voices");
40155
+ CACHE_DIR3 = join48(homedir8(), ".cache", "hyperframes", "tts");
40156
+ MODELS_DIR2 = join48(CACHE_DIR3, "models");
40157
+ VOICES_DIR = join48(CACHE_DIR3, "voices");
40017
40158
  DEFAULT_MODEL2 = "kokoro-v1.0";
40018
40159
  MODEL_URLS = {
40019
40160
  "kokoro-v1.0": "https://github.com/thewh1teagle/kokoro-onnx/releases/download/model-files-v1.0/kokoro-v1.0.onnx"
@@ -40074,8 +40215,8 @@ __export(synthesize_exports, {
40074
40215
  synthesize: () => synthesize
40075
40216
  });
40076
40217
  import { execFileSync as execFileSync6 } from "child_process";
40077
- import { existsSync as existsSync46, writeFileSync as writeFileSync18, mkdirSync as mkdirSync24, readdirSync as readdirSync17, unlinkSync as unlinkSync6 } from "fs";
40078
- import { join as join47, dirname as dirname19, basename as basename10 } from "path";
40218
+ import { existsSync as existsSync48, writeFileSync as writeFileSync20, mkdirSync as mkdirSync26, readdirSync as readdirSync17, unlinkSync as unlinkSync6 } from "fs";
40219
+ import { join as join49, dirname as dirname19, basename as basename10 } from "path";
40079
40220
  import { homedir as homedir9 } from "os";
40080
40221
  function findPython() {
40081
40222
  for (const name of ["python3", "python"]) {
@@ -40111,15 +40252,15 @@ function hasPythonPackage(python, pkg) {
40111
40252
  }
40112
40253
  }
40113
40254
  function ensureSynthScript() {
40114
- if (!existsSync46(SCRIPT_PATH)) {
40115
- mkdirSync24(SCRIPT_DIR, { recursive: true });
40116
- writeFileSync18(SCRIPT_PATH, SYNTH_SCRIPT);
40255
+ if (!existsSync48(SCRIPT_PATH)) {
40256
+ mkdirSync26(SCRIPT_DIR, { recursive: true });
40257
+ writeFileSync20(SCRIPT_PATH, SYNTH_SCRIPT);
40117
40258
  const currentName = basename10(SCRIPT_PATH);
40118
40259
  try {
40119
40260
  for (const entry of readdirSync17(SCRIPT_DIR)) {
40120
40261
  if (entry !== currentName && /^synth(-v\d+)?\.py$/.test(entry)) {
40121
40262
  try {
40122
- unlinkSync6(join47(SCRIPT_DIR, entry));
40263
+ unlinkSync6(join49(SCRIPT_DIR, entry));
40123
40264
  } catch {
40124
40265
  }
40125
40266
  }
@@ -40153,7 +40294,7 @@ async function synthesize(text, outputPath, options) {
40153
40294
  ensureVoices({ onProgress: options?.onProgress })
40154
40295
  ]);
40155
40296
  const scriptPath = ensureSynthScript();
40156
- mkdirSync24(dirname19(outputPath), { recursive: true });
40297
+ mkdirSync26(dirname19(outputPath), { recursive: true });
40157
40298
  options?.onProgress?.(`Generating speech with voice ${voice} (${lang})...`);
40158
40299
  try {
40159
40300
  const stdout2 = execFileSync6(
@@ -40165,7 +40306,7 @@ async function synthesize(text, outputPath, options) {
40165
40306
  stdio: ["pipe", "pipe", "pipe"]
40166
40307
  }
40167
40308
  );
40168
- if (!existsSync46(outputPath)) {
40309
+ if (!existsSync48(outputPath)) {
40169
40310
  throw new Error("Synthesis completed but no output file was created");
40170
40311
  }
40171
40312
  const lines = stdout2.trim().split("\n");
@@ -40178,7 +40319,7 @@ async function synthesize(text, outputPath, options) {
40178
40319
  langApplied: result.langApplied
40179
40320
  };
40180
40321
  } catch (err) {
40181
- if (err instanceof SyntaxError && existsSync46(outputPath)) {
40322
+ if (err instanceof SyntaxError && existsSync48(outputPath)) {
40182
40323
  throw new Error(
40183
40324
  "Speech was generated but metadata could not be read. Check the output file manually."
40184
40325
  );
@@ -40229,8 +40370,8 @@ print(json.dumps({
40229
40370
  "langApplied": bool(lang and supports_lang),
40230
40371
  }))
40231
40372
  `;
40232
- SCRIPT_DIR = join47(homedir9(), ".cache", "hyperframes", "tts");
40233
- SCRIPT_PATH = join47(SCRIPT_DIR, "synth-v2.py");
40373
+ SCRIPT_DIR = join49(homedir9(), ".cache", "hyperframes", "tts");
40374
+ SCRIPT_PATH = join49(SCRIPT_DIR, "synth-v2.py");
40234
40375
  }
40235
40376
  });
40236
40377
 
@@ -40240,7 +40381,7 @@ __export(tts_exports, {
40240
40381
  default: () => tts_default,
40241
40382
  examples: () => examples16
40242
40383
  });
40243
- import { existsSync as existsSync47, readFileSync as readFileSync32 } from "fs";
40384
+ import { existsSync as existsSync49, readFileSync as readFileSync33 } from "fs";
40244
40385
  import { resolve as resolve33, extname as extname9 } from "path";
40245
40386
  function listVoices(json) {
40246
40387
  const rows = BUNDLED_VOICES.map((v) => ({ ...v, defaultLang: inferLangFromVoiceId(v.id) }));
@@ -40350,8 +40491,8 @@ var init_tts = __esm({
40350
40491
  }
40351
40492
  let text;
40352
40493
  const maybeFile = resolve33(args.input);
40353
- if (existsSync47(maybeFile) && extname9(maybeFile).toLowerCase() === ".txt") {
40354
- text = readFileSync32(maybeFile, "utf-8").trim();
40494
+ if (existsSync49(maybeFile) && extname9(maybeFile).toLowerCase() === ".txt") {
40495
+ text = readFileSync33(maybeFile, "utf-8").trim();
40355
40496
  if (!text) {
40356
40497
  console.error(c.error("File is empty."));
40357
40498
  process.exit(1);
@@ -40443,15 +40584,15 @@ __export(docs_exports, {
40443
40584
  default: () => docs_default,
40444
40585
  examples: () => examples17
40445
40586
  });
40446
- import { readFileSync as readFileSync33, existsSync as existsSync48 } from "fs";
40447
- import { resolve as resolve34, dirname as dirname20, join as join48 } from "path";
40587
+ import { readFileSync as readFileSync34, existsSync as existsSync50 } from "fs";
40588
+ import { resolve as resolve34, dirname as dirname20, join as join50 } from "path";
40448
40589
  import { fileURLToPath as fileURLToPath7 } from "url";
40449
40590
  function docsDir() {
40450
40591
  const thisFile = fileURLToPath7(import.meta.url);
40451
40592
  const dir = dirname20(thisFile);
40452
40593
  const devPath = resolve34(dir, "..", "docs");
40453
40594
  const builtPath = resolve34(dir, "docs");
40454
- return existsSync48(devPath) ? devPath : builtPath;
40595
+ return existsSync50(devPath) ? devPath : builtPath;
40455
40596
  }
40456
40597
  function formatInlineCode(line) {
40457
40598
  return line.replace(/`([^`]+)`/g, (_match, code) => c.accent(code));
@@ -40548,12 +40689,12 @@ var init_docs = __esm({
40548
40689
  }
40549
40690
  process.exit(1);
40550
40691
  }
40551
- const filePath = join48(docsDir(), entry.file);
40552
- if (!existsSync48(filePath)) {
40692
+ const filePath = join50(docsDir(), entry.file);
40693
+ if (!existsSync50(filePath)) {
40553
40694
  console.error(c.error(`Doc file not found: ${filePath}`));
40554
40695
  process.exit(1);
40555
40696
  }
40556
- const content = readFileSync33(filePath, "utf-8");
40697
+ const content = readFileSync34(filePath, "utf-8");
40557
40698
  console.log();
40558
40699
  renderMarkdown(content);
40559
40700
  }
@@ -40979,8 +41120,8 @@ var validate_exports = {};
40979
41120
  __export(validate_exports, {
40980
41121
  default: () => validate_default
40981
41122
  });
40982
- import { existsSync as existsSync49, readFileSync as readFileSync34 } from "fs";
40983
- import { resolve as resolve35, join as join49, dirname as dirname21 } from "path";
41123
+ import { existsSync as existsSync51, readFileSync as readFileSync35 } from "fs";
41124
+ import { resolve as resolve35, join as join51, dirname as dirname21 } from "path";
40984
41125
  import { fileURLToPath as fileURLToPath8 } from "url";
40985
41126
  async function getCompositionDuration3(page) {
40986
41127
  return page.evaluate(() => {
@@ -41035,8 +41176,8 @@ async function validateInBrowser(projectDir, opts) {
41035
41176
  "dist",
41036
41177
  "hyperframe.runtime.iife.js"
41037
41178
  );
41038
- if (existsSync49(runtimePath)) {
41039
- const runtimeSource = readFileSync34(runtimePath, "utf-8");
41179
+ if (existsSync51(runtimePath)) {
41180
+ const runtimeSource = readFileSync35(runtimePath, "utf-8");
41040
41181
  html = html.replace(
41041
41182
  /<script[^>]*data-hyperframes-preview-runtime[^>]*src="[^"]*"[^>]*><\/script>/,
41042
41183
  () => `<script data-hyperframes-preview-runtime="1">${runtimeSource}</script>`
@@ -41051,10 +41192,10 @@ async function validateInBrowser(projectDir, opts) {
41051
41192
  res.end(html);
41052
41193
  return;
41053
41194
  }
41054
- const filePath = join49(projectDir, decodeURIComponent(url));
41055
- if (existsSync49(filePath)) {
41195
+ const filePath = join51(projectDir, decodeURIComponent(url));
41196
+ if (existsSync51(filePath)) {
41056
41197
  res.writeHead(200, { "Content-Type": getMimeType2(filePath) });
41057
- res.end(readFileSync34(filePath));
41198
+ res.end(readFileSync35(filePath));
41058
41199
  return;
41059
41200
  }
41060
41201
  res.writeHead(404);
@@ -41244,14 +41385,14 @@ __export(snapshot_exports, {
41244
41385
  default: () => snapshot_default,
41245
41386
  examples: () => examples21
41246
41387
  });
41247
- import { spawn as spawn11 } from "child_process";
41248
- import { existsSync as existsSync50, mkdtempSync as mkdtempSync3, readFileSync as readFileSync35, mkdirSync as mkdirSync25, rmSync as rmSync10 } from "fs";
41388
+ import { spawn as spawn12 } from "child_process";
41389
+ import { existsSync as existsSync52, mkdtempSync as mkdtempSync3, readFileSync as readFileSync36, mkdirSync as mkdirSync27, rmSync as rmSync10 } from "fs";
41249
41390
  import { tmpdir as tmpdir5 } from "os";
41250
- import { resolve as resolve36, join as join50, dirname as dirname22, relative as relative6, isAbsolute as isAbsolute7 } from "path";
41391
+ import { resolve as resolve36, join as join52, dirname as dirname22, relative as relative6, isAbsolute as isAbsolute7 } from "path";
41251
41392
  import { fileURLToPath as fileURLToPath9 } from "url";
41252
41393
  async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDecoder = false) {
41253
- const tmp = mkdtempSync3(join50(tmpdir5(), "hf-snapshot-frame-"));
41254
- const outPath = join50(tmp, "frame.png");
41394
+ const tmp = mkdtempSync3(join52(tmpdir5(), "hf-snapshot-frame-"));
41395
+ const outPath = join52(tmp, "frame.png");
41255
41396
  try {
41256
41397
  const result = await new Promise(
41257
41398
  (resolvePromise) => {
@@ -41271,7 +41412,7 @@ async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDeco
41271
41412
  "-y",
41272
41413
  outPath
41273
41414
  );
41274
- const ff = spawn11("ffmpeg", args);
41415
+ const ff = spawn12("ffmpeg", args);
41275
41416
  let stderr = "";
41276
41417
  let timedOut = false;
41277
41418
  const timer = setTimeout(() => {
@@ -41291,8 +41432,8 @@ async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDeco
41291
41432
  });
41292
41433
  }
41293
41434
  );
41294
- if (result.code !== 0 || result.timedOut || !existsSync50(outPath)) return null;
41295
- return readFileSync35(outPath);
41435
+ if (result.code !== 0 || result.timedOut || !existsSync52(outPath)) return null;
41436
+ return readFileSync36(outPath);
41296
41437
  } finally {
41297
41438
  try {
41298
41439
  rmSync10(tmp, { recursive: true, force: true });
@@ -41314,8 +41455,8 @@ async function captureSnapshots(projectDir, opts) {
41314
41455
  "dist",
41315
41456
  "hyperframe.runtime.iife.js"
41316
41457
  );
41317
- if (existsSync50(runtimePath)) {
41318
- const runtimeSource = readFileSync35(runtimePath, "utf-8");
41458
+ if (existsSync52(runtimePath)) {
41459
+ const runtimeSource = readFileSync36(runtimePath, "utf-8");
41319
41460
  html = html.replace(
41320
41461
  /<script[^>]*data-hyperframes-preview-runtime[^>]*src="[^"]*"[^>]*><\/script>/,
41321
41462
  () => `<script data-hyperframes-preview-runtime="1">${runtimeSource}</script>`
@@ -41337,9 +41478,9 @@ async function captureSnapshots(projectDir, opts) {
41337
41478
  res.end();
41338
41479
  return;
41339
41480
  }
41340
- if (existsSync50(filePath)) {
41481
+ if (existsSync52(filePath)) {
41341
41482
  res.writeHead(200, { "Content-Type": getMimeType2(filePath) });
41342
- res.end(readFileSync35(filePath));
41483
+ res.end(readFileSync36(filePath));
41343
41484
  return;
41344
41485
  }
41345
41486
  res.writeHead(404);
@@ -41412,8 +41553,8 @@ async function captureSnapshots(projectDir, opts) {
41412
41553
  return [];
41413
41554
  }
41414
41555
  const positions = opts.at?.length ? opts.at : numFrames === 1 ? [duration / 2] : Array.from({ length: numFrames }, (_2, i2) => i2 / (numFrames - 1) * duration);
41415
- const snapshotDir = join50(projectDir, "snapshots");
41416
- mkdirSync25(snapshotDir, { recursive: true });
41556
+ const snapshotDir = join52(projectDir, "snapshots");
41557
+ mkdirSync27(snapshotDir, { recursive: true });
41417
41558
  let injectVideoFramesBatch2 = null;
41418
41559
  let syncVideoFrameVisibility2 = null;
41419
41560
  let extractMediaMetadata2 = null;
@@ -41487,7 +41628,7 @@ async function captureSnapshots(projectDir, opts) {
41487
41628
  const decodedPath = decodeURIComponent(url.pathname).replace(/^\//, "");
41488
41629
  const candidate = resolve36(projectDir, decodedPath);
41489
41630
  const rel = relative6(projectDir, candidate);
41490
- if (!rel.startsWith("..") && !isAbsolute7(rel) && existsSync50(candidate)) {
41631
+ if (!rel.startsWith("..") && !isAbsolute7(rel) && existsSync52(candidate)) {
41491
41632
  filePath = candidate;
41492
41633
  }
41493
41634
  } catch {
@@ -41517,7 +41658,7 @@ async function captureSnapshots(projectDir, opts) {
41517
41658
  }
41518
41659
  const timeLabel = opts.at?.length ? `${time.toFixed(1)}s` : `${Math.round(time / duration * 100)}pct`;
41519
41660
  const filename = `frame-${String(i2).padStart(2, "0")}-at-${timeLabel}.png`;
41520
- const framePath = join50(snapshotDir, filename);
41661
+ const framePath = join52(snapshotDir, filename);
41521
41662
  await page.screenshot({ path: framePath, type: "png" });
41522
41663
  savedPaths.push(`snapshots/${filename}`);
41523
41664
  }
@@ -41602,14 +41743,14 @@ ${c.error("\u2717")} Snapshot failed: ${msg}`);
41602
41743
  });
41603
41744
 
41604
41745
  // src/capture/assetDownloader.ts
41605
- import { writeFileSync as writeFileSync19, mkdirSync as mkdirSync26 } from "fs";
41606
- import { join as join51, extname as extname10 } from "path";
41746
+ import { writeFileSync as writeFileSync21, mkdirSync as mkdirSync28 } from "fs";
41747
+ import { join as join53, extname as extname10 } from "path";
41607
41748
  async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks) {
41608
- const assetsDir = join51(outputDir, "assets");
41609
- mkdirSync26(assetsDir, { recursive: true });
41749
+ const assetsDir = join53(outputDir, "assets");
41750
+ mkdirSync28(assetsDir, { recursive: true });
41610
41751
  const assets = [];
41611
41752
  const downloadedUrls = /* @__PURE__ */ new Set();
41612
- mkdirSync26(join51(outputDir, "assets", "svgs"), { recursive: true });
41753
+ mkdirSync28(join53(outputDir, "assets", "svgs"), { recursive: true });
41613
41754
  for (let i2 = 0; i2 < tokens.svgs.length && i2 < 30; i2++) {
41614
41755
  const svg = tokens.svgs[i2];
41615
41756
  if (!svg.outerHTML || svg.outerHTML.length < 50) continue;
@@ -41617,7 +41758,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
41617
41758
  const name = label2 ? slugify(label2) + ".svg" : svg.isLogo ? `logo-${i2}.svg` : `icon-${i2}.svg`;
41618
41759
  const localPath = `assets/svgs/${name}`;
41619
41760
  try {
41620
- writeFileSync19(join51(outputDir, localPath), svg.outerHTML, "utf-8");
41761
+ writeFileSync21(join53(outputDir, localPath), svg.outerHTML, "utf-8");
41621
41762
  assets.push({ url: "", localPath, type: "svg" });
41622
41763
  } catch {
41623
41764
  }
@@ -41630,7 +41771,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
41630
41771
  const localPath = `assets/${name}`;
41631
41772
  const buffer = await fetchBuffer(icon.href);
41632
41773
  if (buffer) {
41633
- writeFileSync19(join51(outputDir, localPath), buffer);
41774
+ writeFileSync21(join53(outputDir, localPath), buffer);
41634
41775
  assets.push({ url: icon.href, localPath, type: "favicon" });
41635
41776
  break;
41636
41777
  }
@@ -41687,7 +41828,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
41687
41828
  const slug = isMeaningful ? slugify(rawName) : `${prefix}-${imgIdx}`;
41688
41829
  const name = `${slug}${ext}`;
41689
41830
  const localPath = `assets/${name}`;
41690
- writeFileSync19(join51(outputDir, localPath), buffer);
41831
+ writeFileSync21(join53(outputDir, localPath), buffer);
41691
41832
  assets.push({ url, localPath, type: "image" });
41692
41833
  imgIdx++;
41693
41834
  } catch {
@@ -41700,7 +41841,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
41700
41841
  const localPath = `assets/og-image${ext}`;
41701
41842
  const buffer = await fetchBuffer(tokens.ogImage);
41702
41843
  if (buffer && buffer.length > 5e3) {
41703
- writeFileSync19(join51(outputDir, localPath), buffer);
41844
+ writeFileSync21(join53(outputDir, localPath), buffer);
41704
41845
  assets.push({ url: tokens.ogImage, localPath, type: "image" });
41705
41846
  }
41706
41847
  } catch {
@@ -41723,8 +41864,8 @@ function normalizeUrl(u) {
41723
41864
  }
41724
41865
  }
41725
41866
  async function downloadAndRewriteFonts(css, outputDir) {
41726
- const assetsDir = join51(outputDir, "assets", "fonts");
41727
- mkdirSync26(assetsDir, { recursive: true });
41867
+ const assetsDir = join53(outputDir, "assets", "fonts");
41868
+ mkdirSync28(assetsDir, { recursive: true });
41728
41869
  const fontUrlRegex = /url\(['"]?(https?:\/\/[^'")\s]+\.(?:woff2?|ttf|otf)[^'")\s]*?)['"]?\)/g;
41729
41870
  const fontUrls = /* @__PURE__ */ new Set();
41730
41871
  let match;
@@ -41759,11 +41900,11 @@ async function downloadAndRewriteFonts(css, outputDir) {
41759
41900
  try {
41760
41901
  const urlObj = new URL(fontUrl);
41761
41902
  const filename = urlObj.pathname.split("/").pop() || `font-${count}.woff2`;
41762
- const localPath = join51(assetsDir, filename);
41903
+ const localPath = join53(assetsDir, filename);
41763
41904
  const relativePath = `assets/fonts/${filename}`;
41764
41905
  const buffer = await fetchBuffer(fontUrl);
41765
41906
  if (buffer) {
41766
- writeFileSync19(localPath, buffer);
41907
+ writeFileSync21(localPath, buffer);
41767
41908
  rewritten = rewritten.split(fontUrl).join(relativePath);
41768
41909
  familyCounts.set(family, familyCount + 1);
41769
41910
  count++;
@@ -42556,8 +42697,8 @@ var init_animationCataloger = __esm({
42556
42697
  });
42557
42698
 
42558
42699
  // src/capture/mediaCapture.ts
42559
- import { mkdirSync as mkdirSync27, writeFileSync as writeFileSync20, readdirSync as readdirSync18, readFileSync as readFileSync36, statSync as statSync18 } from "fs";
42560
- import { join as join52 } from "path";
42700
+ import { mkdirSync as mkdirSync29, writeFileSync as writeFileSync22, readdirSync as readdirSync18, readFileSync as readFileSync37, statSync as statSync18 } from "fs";
42701
+ import { join as join54 } from "path";
42561
42702
  async function saveLottieAnimations(discoveredLotties, lottieDir) {
42562
42703
  let savedCount = 0;
42563
42704
  const savedHashes = /* @__PURE__ */ new Set();
@@ -42590,7 +42731,7 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
42590
42731
  const hash2 = buf.toString("base64").slice(0, 100);
42591
42732
  if (savedHashes.has(hash2)) continue;
42592
42733
  savedHashes.add(hash2);
42593
- writeFileSync20(join52(lottieDir, `animation-${savedCount}.lottie`), buf);
42734
+ writeFileSync22(join54(lottieDir, `animation-${savedCount}.lottie`), buf);
42594
42735
  savedCount++;
42595
42736
  continue;
42596
42737
  }
@@ -42608,7 +42749,7 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
42608
42749
  } catch {
42609
42750
  continue;
42610
42751
  }
42611
- writeFileSync20(join52(lottieDir, `animation-${savedCount}.json`), jsonData, "utf-8");
42752
+ writeFileSync22(join54(lottieDir, `animation-${savedCount}.json`), jsonData, "utf-8");
42612
42753
  savedCount++;
42613
42754
  }
42614
42755
  } catch {
@@ -42618,22 +42759,22 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
42618
42759
  }
42619
42760
  async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
42620
42761
  const manifest = [];
42621
- const previewDir = join52(lottieDir, "previews");
42622
- mkdirSync27(previewDir, { recursive: true });
42762
+ const previewDir = join54(lottieDir, "previews");
42763
+ mkdirSync29(previewDir, { recursive: true });
42623
42764
  for (const file of readdirSync18(lottieDir)) {
42624
42765
  if (!file.endsWith(".json")) continue;
42625
42766
  try {
42626
- const raw = JSON.parse(readFileSync36(join52(lottieDir, file), "utf-8"));
42767
+ const raw = JSON.parse(readFileSync37(join54(lottieDir, file), "utf-8"));
42627
42768
  const fr = raw.fr || 30;
42628
42769
  const dur = ((raw.op || 0) - (raw.ip || 0)) / fr;
42629
42770
  const previewName = file.replace(".json", "-preview.png");
42630
- const fileSize = statSync18(join52(lottieDir, file)).size;
42771
+ const fileSize = statSync18(join54(lottieDir, file)).size;
42631
42772
  if (fileSize > 2e6) continue;
42632
42773
  let previewPage;
42633
42774
  try {
42634
42775
  previewPage = await chromeBrowser.newPage();
42635
42776
  await previewPage.setViewport({ width: 400, height: 400 });
42636
- const animData = JSON.parse(readFileSync36(join52(lottieDir, file), "utf-8"));
42777
+ const animData = JSON.parse(readFileSync37(join54(lottieDir, file), "utf-8"));
42637
42778
  const midFrame = Math.floor(((raw.op || 0) - (raw.ip || 0)) * 0.3);
42638
42779
  await previewPage.setContent(
42639
42780
  `<!DOCTYPE html>
@@ -42663,7 +42804,7 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
42663
42804
  await previewPage.waitForFunction(() => window.__READY === true, { timeout: 5e3 }).catch(() => {
42664
42805
  });
42665
42806
  await previewPage.screenshot({
42666
- path: join52(previewDir, previewName),
42807
+ path: join54(previewDir, previewName),
42667
42808
  type: "png",
42668
42809
  omitBackground: true
42669
42810
  });
@@ -42686,8 +42827,8 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
42686
42827
  }
42687
42828
  }
42688
42829
  if (manifest.length > 0) {
42689
- writeFileSync20(
42690
- join52(outputDir, "extracted", "lottie-manifest.json"),
42830
+ writeFileSync22(
42831
+ join54(outputDir, "extracted", "lottie-manifest.json"),
42691
42832
  JSON.stringify(manifest, null, 2),
42692
42833
  "utf-8"
42693
42834
  );
@@ -42749,15 +42890,15 @@ async function captureVideoManifest(page, outputDir, progress) {
42749
42890
  return true;
42750
42891
  });
42751
42892
  if (uniqueVideos.length > 0) {
42752
- const videoManifestDir = join52(outputDir, "assets", "videos");
42753
- mkdirSync27(videoManifestDir, { recursive: true });
42754
- const previewDir = join52(videoManifestDir, "previews");
42755
- mkdirSync27(previewDir, { recursive: true });
42893
+ const videoManifestDir = join54(outputDir, "assets", "videos");
42894
+ mkdirSync29(videoManifestDir, { recursive: true });
42895
+ const previewDir = join54(videoManifestDir, "previews");
42896
+ mkdirSync29(previewDir, { recursive: true });
42756
42897
  const videoManifest = [];
42757
42898
  for (let vi = 0; vi < uniqueVideos.length && vi < 20; vi++) {
42758
42899
  const v = uniqueVideos[vi];
42759
42900
  const previewName = `video-${vi}-preview.png`;
42760
- const previewPath = join52(previewDir, previewName);
42901
+ const previewPath = join54(previewDir, previewName);
42761
42902
  try {
42762
42903
  await page.evaluate(`window.scrollTo(0, ${Math.max(0, v.top - 100)})`);
42763
42904
  await new Promise((r2) => setTimeout(r2, 300));
@@ -42795,8 +42936,8 @@ async function captureVideoManifest(page, outputDir, progress) {
42795
42936
  });
42796
42937
  }
42797
42938
  if (videoManifest.length > 0) {
42798
- writeFileSync20(
42799
- join52(outputDir, "extracted", "video-manifest.json"),
42939
+ writeFileSync22(
42940
+ join54(outputDir, "extracted", "video-manifest.json"),
42800
42941
  JSON.stringify(videoManifest, null, 2),
42801
42942
  "utf-8"
42802
42943
  );
@@ -83251,8 +83392,8 @@ ${underline2}`);
83251
83392
  });
83252
83393
 
83253
83394
  // src/capture/contentExtractor.ts
83254
- import { readdirSync as readdirSync19, statSync as statSync20, readFileSync as readFileSync37 } from "fs";
83255
- import { join as join53 } from "path";
83395
+ import { readdirSync as readdirSync19, statSync as statSync20, readFileSync as readFileSync38 } from "fs";
83396
+ import { join as join55 } from "path";
83256
83397
  async function detectLibraries(page, capturedShaders) {
83257
83398
  let detectedLibraries = [];
83258
83399
  try {
@@ -83372,7 +83513,7 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
83372
83513
  try {
83373
83514
  const { GoogleGenAI: GoogleGenAI2 } = await Promise.resolve().then(() => (init_node4(), node_exports));
83374
83515
  const ai = new GoogleGenAI2({ apiKey: geminiKey });
83375
- const imageFiles = readdirSync19(join53(outputDir, "assets")).filter(
83516
+ const imageFiles = readdirSync19(join55(outputDir, "assets")).filter(
83376
83517
  (f3) => /\.(png|jpg|jpeg|webp|gif)$/i.test(f3)
83377
83518
  );
83378
83519
  const model = process.env.HYPERFRAMES_GEMINI_MODEL || "gemini-3.1-flash-lite-preview";
@@ -83381,10 +83522,10 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
83381
83522
  const batch = imageFiles.slice(i2, i2 + BATCH_SIZE);
83382
83523
  const results = await Promise.allSettled(
83383
83524
  batch.map(async (file) => {
83384
- const filePath = join53(outputDir, "assets", file);
83525
+ const filePath = join55(outputDir, "assets", file);
83385
83526
  const stat3 = statSync20(filePath);
83386
83527
  if (stat3.size > 4e6) return { file, caption: "" };
83387
- const buffer = readFileSync37(filePath);
83528
+ const buffer = readFileSync38(filePath);
83388
83529
  const base64 = buffer.toString("base64");
83389
83530
  const ext = file.split(".").pop()?.toLowerCase() || "png";
83390
83531
  const mimeType = ext === "jpg" ? "image/jpeg" : `image/${ext}`;
@@ -83430,11 +83571,11 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
83430
83571
  const uncaptionedLines = [];
83431
83572
  const svgLines = [];
83432
83573
  const fontLines = [];
83433
- const assetsPath = join53(outputDir, "assets");
83574
+ const assetsPath = join55(outputDir, "assets");
83434
83575
  try {
83435
83576
  for (const file of readdirSync19(assetsPath)) {
83436
83577
  if (file === "svgs" || file === "fonts" || file === "lottie" || file === "videos") continue;
83437
- const filePath = join53(assetsPath, file);
83578
+ const filePath = join55(assetsPath, file);
83438
83579
  const stat3 = statSync20(filePath);
83439
83580
  if (!stat3.isFile()) continue;
83440
83581
  const sizeKb = Math.round(stat3.size / 1024);
@@ -83463,7 +83604,7 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
83463
83604
  } catch {
83464
83605
  }
83465
83606
  try {
83466
- const svgsPath = join53(assetsPath, "svgs");
83607
+ const svgsPath = join55(assetsPath, "svgs");
83467
83608
  for (const file of readdirSync19(svgsPath)) {
83468
83609
  if (!file.endsWith(".svg")) continue;
83469
83610
  const svgMatch = tokens.svgs.find(
@@ -83478,7 +83619,7 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
83478
83619
  } catch {
83479
83620
  }
83480
83621
  try {
83481
- const fontsPath = join53(assetsPath, "fonts");
83622
+ const fontsPath = join55(assetsPath, "fonts");
83482
83623
  for (const file of readdirSync19(fontsPath)) {
83483
83624
  fontLines.push(`fonts/${file} \u2014 font file`);
83484
83625
  }
@@ -83497,13 +83638,13 @@ var agentPromptGenerator_exports = {};
83497
83638
  __export(agentPromptGenerator_exports, {
83498
83639
  generateAgentPrompt: () => generateAgentPrompt
83499
83640
  });
83500
- import { writeFileSync as writeFileSync21 } from "fs";
83501
- import { join as join54 } from "path";
83641
+ import { writeFileSync as writeFileSync23 } from "fs";
83642
+ import { join as join56 } from "path";
83502
83643
  function generateAgentPrompt(outputDir, url, tokens, _animations, hasScreenshot, hasLottie, hasShaders, _catalogedAssets, detectedLibraries) {
83503
83644
  const prompt = buildPrompt(url, tokens, hasScreenshot, hasLottie, hasShaders, detectedLibraries);
83504
- writeFileSync21(join54(outputDir, "AGENTS.md"), prompt, "utf-8");
83505
- writeFileSync21(join54(outputDir, "CLAUDE.md"), prompt, "utf-8");
83506
- writeFileSync21(join54(outputDir, ".cursorrules"), prompt, "utf-8");
83645
+ writeFileSync23(join56(outputDir, "AGENTS.md"), prompt, "utf-8");
83646
+ writeFileSync23(join56(outputDir, "CLAUDE.md"), prompt, "utf-8");
83647
+ writeFileSync23(join56(outputDir, ".cursorrules"), prompt, "utf-8");
83507
83648
  }
83508
83649
  function buildPrompt(url, tokens, hasScreenshot, hasLottie, hasShaders, detectedLibraries) {
83509
83650
  const title = tokens.title || new URL(url).hostname.replace(/^www\./, "");
@@ -83570,15 +83711,15 @@ var init_agentPromptGenerator = __esm({
83570
83711
  });
83571
83712
 
83572
83713
  // src/capture/scaffolding.ts
83573
- import { existsSync as existsSync51, writeFileSync as writeFileSync22, readFileSync as readFileSync38 } from "fs";
83574
- import { join as join55, resolve as resolve37 } from "path";
83714
+ import { existsSync as existsSync53, writeFileSync as writeFileSync24, readFileSync as readFileSync39 } from "fs";
83715
+ import { join as join57, resolve as resolve37 } from "path";
83575
83716
  function loadEnvFile(startDir) {
83576
83717
  try {
83577
83718
  let dir = resolve37(startDir);
83578
83719
  for (let i2 = 0; i2 < 5; i2++) {
83579
83720
  const envPath = resolve37(dir, ".env");
83580
83721
  try {
83581
- const envContent = readFileSync38(envPath, "utf-8");
83722
+ const envContent = readFileSync39(envPath, "utf-8");
83582
83723
  for (const line of envContent.split("\n")) {
83583
83724
  const trimmed = line.trim();
83584
83725
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -83597,10 +83738,10 @@ function loadEnvFile(startDir) {
83597
83738
  }
83598
83739
  }
83599
83740
  async function generateProjectScaffold(outputDir, url, tokens, animationCatalog, hasScreenshots, hasLotties, hasShaders, catalogedAssets, progress, warnings, detectedLibraries) {
83600
- const metaPath = join55(outputDir, "meta.json");
83601
- if (!existsSync51(metaPath)) {
83741
+ const metaPath = join57(outputDir, "meta.json");
83742
+ if (!existsSync53(metaPath)) {
83602
83743
  const hostname = new URL(url).hostname.replace(/^www\./, "");
83603
- writeFileSync22(
83744
+ writeFileSync24(
83604
83745
  metaPath,
83605
83746
  JSON.stringify({ id: hostname + "-video", name: tokens.title || hostname }, null, 2),
83606
83747
  "utf-8"
@@ -83635,11 +83776,11 @@ var screenshotCapture_exports = {};
83635
83776
  __export(screenshotCapture_exports, {
83636
83777
  captureScrollScreenshots: () => captureScrollScreenshots
83637
83778
  });
83638
- import { writeFileSync as writeFileSync23, mkdirSync as mkdirSync28 } from "fs";
83639
- import { join as join56 } from "path";
83779
+ import { writeFileSync as writeFileSync25, mkdirSync as mkdirSync30 } from "fs";
83780
+ import { join as join58 } from "path";
83640
83781
  async function captureScrollScreenshots(page, outputDir) {
83641
- const screenshotsDir = join56(outputDir, "screenshots");
83642
- mkdirSync28(screenshotsDir, { recursive: true });
83782
+ const screenshotsDir = join58(outputDir, "screenshots");
83783
+ mkdirSync30(screenshotsDir, { recursive: true });
83643
83784
  const MAX_SCREENSHOTS = 20;
83644
83785
  const filePaths = [];
83645
83786
  try {
@@ -83672,9 +83813,9 @@ async function captureScrollScreenshots(page, outputDir) {
83672
83813
  finalPositions[i2] / Math.max(1, scrollHeight - viewportHeight) * 100
83673
83814
  );
83674
83815
  const filename = `scroll-${String(Math.min(pct, 100)).padStart(3, "0")}.png`;
83675
- const filePath = join56(screenshotsDir, filename);
83816
+ const filePath = join58(screenshotsDir, filename);
83676
83817
  const buffer = await page.screenshot({ type: "png" });
83677
- writeFileSync23(filePath, buffer);
83818
+ writeFileSync25(filePath, buffer);
83678
83819
  filePaths.push(`screenshots/${filename}`);
83679
83820
  }
83680
83821
  await page.evaluate(`window.scrollTo(0, 0)`);
@@ -83985,8 +84126,8 @@ var capture_exports = {};
83985
84126
  __export(capture_exports, {
83986
84127
  captureWebsite: () => captureWebsite
83987
84128
  });
83988
- import { mkdirSync as mkdirSync29, writeFileSync as writeFileSync24, existsSync as existsSync52 } from "fs";
83989
- import { join as join57 } from "path";
84129
+ import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync26, existsSync as existsSync54 } from "fs";
84130
+ import { join as join59 } from "path";
83990
84131
  async function captureWebsite(opts, onProgress) {
83991
84132
  const {
83992
84133
  url,
@@ -84003,9 +84144,9 @@ async function captureWebsite(opts, onProgress) {
84003
84144
  onProgress?.(stage, detail);
84004
84145
  };
84005
84146
  loadEnvFile(outputDir);
84006
- mkdirSync29(join57(outputDir, "extracted"), { recursive: true });
84007
- mkdirSync29(join57(outputDir, "screenshots"), { recursive: true });
84008
- mkdirSync29(join57(outputDir, "assets"), { recursive: true });
84147
+ mkdirSync31(join59(outputDir, "extracted"), { recursive: true });
84148
+ mkdirSync31(join59(outputDir, "screenshots"), { recursive: true });
84149
+ mkdirSync31(join59(outputDir, "assets"), { recursive: true });
84009
84150
  progress("browser", "Launching headless Chrome...");
84010
84151
  const { ensureBrowser: ensureBrowser2 } = await Promise.resolve().then(() => (init_manager2(), manager_exports2));
84011
84152
  const browser = await ensureBrowser2();
@@ -84161,8 +84302,8 @@ async function captureWebsite(opts, onProgress) {
84161
84302
  } catch {
84162
84303
  }
84163
84304
  if (discoveredLotties.length > 0) {
84164
- const lottieDir = join57(outputDir, "assets", "lottie");
84165
- mkdirSync29(lottieDir, { recursive: true });
84305
+ const lottieDir = join59(outputDir, "assets", "lottie");
84306
+ mkdirSync31(lottieDir, { recursive: true });
84166
84307
  const savedCount = await saveLottieAnimations(discoveredLotties, lottieDir);
84167
84308
  if (savedCount > 0) {
84168
84309
  await renderLottiePreviews(chromeBrowser, lottieDir, outputDir);
@@ -84180,8 +84321,8 @@ async function captureWebsite(opts, onProgress) {
84180
84321
  return true;
84181
84322
  });
84182
84323
  capturedShaders = unique;
84183
- writeFileSync24(
84184
- join57(outputDir, "extracted", "shaders.json"),
84324
+ writeFileSync26(
84325
+ join59(outputDir, "extracted", "shaders.json"),
84185
84326
  JSON.stringify(unique, null, 2),
84186
84327
  "utf-8"
84187
84328
  );
@@ -84191,8 +84332,8 @@ async function captureWebsite(opts, onProgress) {
84191
84332
  }
84192
84333
  progress("tokens", "Extracting design tokens...");
84193
84334
  const tokens = await extractTokens(page1);
84194
- writeFileSync24(
84195
- join57(outputDir, "extracted", "tokens.json"),
84335
+ writeFileSync26(
84336
+ join59(outputDir, "extracted", "tokens.json"),
84196
84337
  JSON.stringify(tokens, null, 2),
84197
84338
  "utf-8"
84198
84339
  );
@@ -84265,8 +84406,8 @@ async function captureWebsite(opts, onProgress) {
84265
84406
  scrollTriggeredElements: (animationCatalog.scrollTargets || []).length,
84266
84407
  representativeAnimations: representativeAnims
84267
84408
  };
84268
- writeFileSync24(
84269
- join57(outputDir, "extracted", "animations.json"),
84409
+ writeFileSync26(
84410
+ join59(outputDir, "extracted", "animations.json"),
84270
84411
  JSON.stringify(leanCatalog, null, 2),
84271
84412
  "utf-8"
84272
84413
  );
@@ -84277,18 +84418,18 @@ async function captureWebsite(opts, onProgress) {
84277
84418
  assets = await downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks);
84278
84419
  }
84279
84420
  if (visibleTextContent) {
84280
- writeFileSync24(join57(outputDir, "extracted", "visible-text.txt"), visibleTextContent, "utf-8");
84421
+ writeFileSync26(join59(outputDir, "extracted", "visible-text.txt"), visibleTextContent, "utf-8");
84281
84422
  }
84282
84423
  if (catalogedAssets.length > 0) {
84283
- writeFileSync24(
84284
- join57(outputDir, "extracted", "assets-catalog.json"),
84424
+ writeFileSync26(
84425
+ join59(outputDir, "extracted", "assets-catalog.json"),
84285
84426
  JSON.stringify(catalogedAssets, null, 2),
84286
84427
  "utf-8"
84287
84428
  );
84288
84429
  }
84289
84430
  if (detectedLibraries.length > 0) {
84290
- writeFileSync24(
84291
- join57(outputDir, "extracted", "detected-libraries.json"),
84431
+ writeFileSync26(
84432
+ join59(outputDir, "extracted", "detected-libraries.json"),
84292
84433
  JSON.stringify(detectedLibraries, null, 2),
84293
84434
  "utf-8"
84294
84435
  );
@@ -84298,8 +84439,8 @@ async function captureWebsite(opts, onProgress) {
84298
84439
  try {
84299
84440
  const lines = generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCaptions);
84300
84441
  if (lines.length > 0) {
84301
- writeFileSync24(
84302
- join57(outputDir, "extracted", "asset-descriptions.md"),
84442
+ writeFileSync26(
84443
+ join59(outputDir, "extracted", "asset-descriptions.md"),
84303
84444
  "# Asset Descriptions\n\nOne line per file. Read this instead of opening every image individually.\n\n" + lines.map((l) => "- " + l).join("\n") + "\n",
84304
84445
  "utf-8"
84305
84446
  );
@@ -84315,7 +84456,7 @@ async function captureWebsite(opts, onProgress) {
84315
84456
  animationCatalog,
84316
84457
  screenshots.length > 0,
84317
84458
  discoveredLotties.length > 0,
84318
- existsSync52(join57(outputDir, "extracted", "shaders.json")),
84459
+ existsSync54(join59(outputDir, "extracted", "shaders.json")),
84319
84460
  catalogedAssets,
84320
84461
  progress,
84321
84462
  warnings,
@@ -84494,11 +84635,11 @@ var init_capture2 = __esm({
84494
84635
  } catch (err) {
84495
84636
  const errMsg = err instanceof Error ? err.message : String(err);
84496
84637
  try {
84497
- const { mkdirSync: mkdirSync31, writeFileSync: writeFileSync25 } = await import("fs");
84498
- mkdirSync31(outputDir, { recursive: true });
84638
+ const { mkdirSync: mkdirSync33, writeFileSync: writeFileSync27 } = await import("fs");
84639
+ mkdirSync33(outputDir, { recursive: true });
84499
84640
  const isTimeout = /timeout|timed out/i.test(errMsg);
84500
84641
  const reason = isTimeout ? "Page navigation timed out \u2014 the site may be blocking headless browsers or requires authentication." : `Capture failed: ${errMsg}`;
84501
- writeFileSync25(
84642
+ writeFileSync27(
84502
84643
  `${outputDir}/BLOCKED.md`,
84503
84644
  `# Capture Failed
84504
84645
 
@@ -84661,10 +84802,10 @@ __export(autoUpdate_exports, {
84661
84802
  reportCompletedUpdate: () => reportCompletedUpdate,
84662
84803
  scheduleBackgroundInstall: () => scheduleBackgroundInstall
84663
84804
  });
84664
- import { spawn as spawn12 } from "child_process";
84665
- import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync30, openSync } from "fs";
84805
+ import { spawn as spawn13 } from "child_process";
84806
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync32, openSync } from "fs";
84666
84807
  import { homedir as homedir10 } from "os";
84667
- import { join as join58 } from "path";
84808
+ import { join as join60 } from "path";
84668
84809
  import { compareVersions as compareVersions2 } from "compare-versions";
84669
84810
  function isAutoInstallDisabled() {
84670
84811
  if (isDevMode()) return true;
@@ -84679,15 +84820,15 @@ function majorOf(version) {
84679
84820
  }
84680
84821
  function log(line) {
84681
84822
  try {
84682
- mkdirSync30(CONFIG_DIR2, { recursive: true, mode: 448 });
84823
+ mkdirSync32(CONFIG_DIR2, { recursive: true, mode: 448 });
84683
84824
  appendFileSync2(LOG_FILE, `${(/* @__PURE__ */ new Date()).toISOString()} ${line}
84684
84825
  `, { mode: 384 });
84685
84826
  } catch {
84686
84827
  }
84687
84828
  }
84688
84829
  function launchDetachedInstall(installCommand, version) {
84689
- mkdirSync30(CONFIG_DIR2, { recursive: true, mode: 448 });
84690
- const configFile = join58(CONFIG_DIR2, "config.json");
84830
+ mkdirSync32(CONFIG_DIR2, { recursive: true, mode: 448 });
84831
+ const configFile = join60(CONFIG_DIR2, "config.json");
84691
84832
  const nodeScript = `
84692
84833
  const { exec } = require("node:child_process");
84693
84834
  const { readFileSync, renameSync, writeFileSync } = require("node:fs");
@@ -84712,7 +84853,7 @@ function launchDetachedInstall(installCommand, version) {
84712
84853
  });
84713
84854
  `;
84714
84855
  const out = openSync(LOG_FILE, "a", 384);
84715
- const child = spawn12(process.execPath, ["-e", nodeScript], {
84856
+ const child = spawn13(process.execPath, ["-e", nodeScript], {
84716
84857
  detached: true,
84717
84858
  stdio: ["ignore", out, out],
84718
84859
  windowsHide: true,
@@ -84806,8 +84947,8 @@ var init_autoUpdate = __esm({
84806
84947
  init_config();
84807
84948
  init_env();
84808
84949
  init_installerDetection();
84809
- CONFIG_DIR2 = join58(homedir10(), ".hyperframes");
84810
- LOG_FILE = join58(CONFIG_DIR2, "auto-update.log");
84950
+ CONFIG_DIR2 = join60(homedir10(), ".hyperframes");
84951
+ LOG_FILE = join60(CONFIG_DIR2, "auto-update.log");
84811
84952
  PENDING_TIMEOUT_MS = 10 * 60 * 1e3;
84812
84953
  }
84813
84954
  });