hyperframes 0.6.36 → 0.6.37

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.
Files changed (2) hide show
  1. package/dist/cli.js +769 -538
  2. package/package.json +1 -1
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.6.36" : "0.0.0-dev";
57
+ VERSION = true ? "0.6.37" : "0.0.0-dev";
58
58
  }
59
59
  });
60
60
 
@@ -11365,9 +11365,173 @@ var init_env = __esm({
11365
11365
  }
11366
11366
  });
11367
11367
 
11368
+ // src/telemetry/platform.ts
11369
+ import { platform, release } from "os";
11370
+ import { readFileSync as readFileSync4 } from "fs";
11371
+ function detectWSL() {
11372
+ if (platform() !== "linux") return false;
11373
+ try {
11374
+ const osRelease = release().toLowerCase();
11375
+ if (osRelease.includes("microsoft") || osRelease.includes("wsl")) return true;
11376
+ const procVersion = readFileSync4("/proc/version", "utf-8").toLowerCase();
11377
+ return procVersion.includes("microsoft") || procVersion.includes("wsl");
11378
+ } catch {
11379
+ return false;
11380
+ }
11381
+ }
11382
+ var init_platform = __esm({
11383
+ "src/telemetry/platform.ts"() {
11384
+ "use strict";
11385
+ }
11386
+ });
11387
+
11388
+ // src/telemetry/agent_runtime.ts
11389
+ import { existsSync as existsSync4, readFileSync as readFileSync5 } from "fs";
11390
+ import { platform as platform2, release as release2 } from "os";
11391
+ function detectSandboxRuntime() {
11392
+ if (platform2() === "win32") return null;
11393
+ if (detectWSL()) return "wsl";
11394
+ if (isGVisor()) return "gvisor";
11395
+ if (isDocker()) return "docker";
11396
+ if (isFirecracker()) return "firecracker";
11397
+ if (isKVM()) return "kvm";
11398
+ return null;
11399
+ }
11400
+ function detectAgentRuntime() {
11401
+ for (const rule of VENDOR_RULES) {
11402
+ if (rule.check(process.env)) return rule.name;
11403
+ }
11404
+ return null;
11405
+ }
11406
+ function isGVisor() {
11407
+ const kernel = release2();
11408
+ if (kernel.includes("gvisor")) return true;
11409
+ if (platform2() !== "linux") return false;
11410
+ try {
11411
+ const procVersion = readFileSync5("/proc/version", "utf-8");
11412
+ return procVersion.includes("gVisor");
11413
+ } catch {
11414
+ return false;
11415
+ }
11416
+ }
11417
+ function isDocker() {
11418
+ if (existsSync4("/.dockerenv")) return true;
11419
+ if (platform2() !== "linux") return false;
11420
+ try {
11421
+ const cgroup = readFileSync5("/proc/1/cgroup", "utf-8");
11422
+ return cgroup.includes("docker") || cgroup.includes("containerd");
11423
+ } catch {
11424
+ return false;
11425
+ }
11426
+ }
11427
+ function isFirecracker() {
11428
+ if (platform2() !== "linux") return false;
11429
+ if (!existsSync4("/dev/vsock")) return false;
11430
+ try {
11431
+ const sysVendor = readFileSync5("/sys/class/dmi/id/sys_vendor", "utf-8").trim();
11432
+ if (sysVendor !== "Amazon EC2") return false;
11433
+ const productName = readFileSync5("/sys/class/dmi/id/product_name", "utf-8").trim();
11434
+ return productName.toLowerCase().includes("firecracker");
11435
+ } catch {
11436
+ return false;
11437
+ }
11438
+ }
11439
+ function isKVM() {
11440
+ if (platform2() !== "linux") return false;
11441
+ try {
11442
+ const sysVendor = readFileSync5("/sys/class/dmi/id/sys_vendor", "utf-8").trim();
11443
+ return sysVendor === "QEMU" || sysVendor.includes("KVM");
11444
+ } catch {
11445
+ return false;
11446
+ }
11447
+ }
11448
+ var VENDOR_RULES;
11449
+ var init_agent_runtime = __esm({
11450
+ "src/telemetry/agent_runtime.ts"() {
11451
+ "use strict";
11452
+ init_platform();
11453
+ VENDOR_RULES = [
11454
+ // Anthropic Claude Code — sets CLAUDECODE=1 on every Bash/PowerShell tool
11455
+ // spawn (Shell.ts:321) and CLAUDE_CODE_ENTRYPOINT at startup, inherited by
11456
+ // every child (main.tsx:527). Both propagate to spawned subprocesses.
11457
+ // Source: confirmed by @magi from Claude Code internal source.
11458
+ {
11459
+ name: "claude_code",
11460
+ check: (env) => typeof env["CLAUDECODE"] === "string" || typeof env["CLAUDE_CODE_ENTRYPOINT"] === "string"
11461
+ },
11462
+ // OpenAI Codex (https://github.com/openai/codex).
11463
+ // - CODEX_THREAD_ID — set unconditionally on every spawned shell command
11464
+ // (codex-rs/protocol/src/shell_environment.rs:6 constant, set by
11465
+ // codex-rs/core/src/unified_exec/process_manager.rs:1010 and
11466
+ // codex-rs/core/src/tools/runtimes/mod.rs:164).
11467
+ // - CODEX_CI — hardcoded in the UNIFIED_EXEC_ENV array, always set on
11468
+ // every unified-exec child (process_manager.rs:70).
11469
+ // - CODEX_SANDBOX_NETWORK_DISABLED — set when network sandbox is active
11470
+ // (codex-rs/core/src/sandboxing/mod.rs:135-138, default-on).
11471
+ // CODEX_HOME is deliberately NOT used — it's a config override read at
11472
+ // Codex startup, not propagated to spawned subprocesses.
11473
+ {
11474
+ name: "codex",
11475
+ check: (env) => typeof env["CODEX_THREAD_ID"] === "string" || typeof env["CODEX_CI"] === "string" || typeof env["CODEX_SANDBOX_NETWORK_DISABLED"] === "string"
11476
+ },
11477
+ // Cursor IDE integrated terminal — exports TERM_PROGRAM=cursor.
11478
+ // Cursor Background Agent env vars are not publicly documented; if a
11479
+ // canonical marker is identified later, add it here.
11480
+ {
11481
+ name: "cursor",
11482
+ check: (env) => env["TERM_PROGRAM"] === "cursor"
11483
+ },
11484
+ // GitHub Copilot Coding Agent — runs inside GitHub Actions and the
11485
+ // workflow injects an additional marker to distinguish from generic CI.
11486
+ // Not yet verified from a public-source citation in this audit; the var
11487
+ // names below match GitHub Copilot Coding Agent documentation but
11488
+ // should be confirmed before relying on attribution.
11489
+ {
11490
+ name: "copilot_agent",
11491
+ check: (env) => env["GITHUB_ACTIONS"] === "true" && (typeof env["COPILOT_AGENT_ID"] === "string" || env["RUNNER_NAME"] === "Copilot")
11492
+ },
11493
+ // Replit — REPL_ID and REPLIT_USER are long-documented environment
11494
+ // variables exposed inside every Replit workspace.
11495
+ // Source: https://docs.replit.com/replit-workspace/configuring-the-environment
11496
+ {
11497
+ name: "replit",
11498
+ check: (env) => typeof env["REPL_ID"] === "string" || typeof env["REPLIT_USER"] === "string"
11499
+ },
11500
+ // Nous Research Hermes Agent — cli.py:50 unconditionally executes
11501
+ // os.environ["HERMES_QUIET"] = "1"
11502
+ // at module load, so the marker propagates via os.environ to every
11503
+ // subprocess spawned by Hermes. Keying on existence (not the literal
11504
+ // "1") so we still match if Hermes ever changes the value.
11505
+ // Source: https://github.com/NousResearch/hermes-agent (cli.py:50)
11506
+ {
11507
+ name: "hermes",
11508
+ check: (env) => typeof env["HERMES_QUIET"] === "string"
11509
+ },
11510
+ // openclaw — multi-channel AI gateway. When openclaw spawns a CLI
11511
+ // subprocess it builds the child env with OPENCLAW_STATE_DIR /
11512
+ // OPENCLAW_CONFIG_PATH / OPENCLAW_DISABLE_AUTO_UPDATE set explicitly
11513
+ // (extensions/qa-matrix/src/runners/contract/scenario-runtime-cli.ts:344-351).
11514
+ // We key on OPENCLAW_STATE_DIR since it's a path scope-bound to openclaw.
11515
+ // Source: https://github.com/openclaw/openclaw
11516
+ {
11517
+ name: "openclaw",
11518
+ check: (env) => typeof env["OPENCLAW_STATE_DIR"] === "string" || typeof env["OPENCLAW_CONFIG_PATH"] === "string"
11519
+ },
11520
+ // Pi coding agent (https://pi.dev, https://github.com/earendil-works/pi).
11521
+ // packages/coding-agent/src/cli.ts:13 unconditionally executes
11522
+ // process.env.PI_CODING_AGENT = "true";
11523
+ // at module entry, so every subprocess Pi spawns sees this marker.
11524
+ {
11525
+ name: "pi",
11526
+ check: (env) => typeof env["PI_CODING_AGENT"] === "string"
11527
+ }
11528
+ ];
11529
+ }
11530
+ });
11531
+
11368
11532
  // src/telemetry/system.ts
11369
- import { cpus, totalmem, platform, release } from "os";
11370
- import { existsSync as existsSync4, readFileSync as readFileSync4, statfsSync } from "fs";
11533
+ import { cpus, totalmem, platform as platform3, release as release3 } from "os";
11534
+ import { existsSync as existsSync5, readFileSync as readFileSync6, statfsSync } from "fs";
11371
11535
  function bytesToMb(bytes) {
11372
11536
  return Math.trunc(bytes / (1024 * 1024));
11373
11537
  }
@@ -11376,7 +11540,7 @@ function getSystemMeta() {
11376
11540
  const cpuInfo = cpus();
11377
11541
  const firstCpu = cpuInfo[0] ?? null;
11378
11542
  cached = {
11379
- os_release: release(),
11543
+ os_release: release3(),
11380
11544
  cpu_count: cpuInfo.length,
11381
11545
  cpu_model: firstCpu?.model?.trim() ?? null,
11382
11546
  cpu_speed: firstCpu?.speed ?? null,
@@ -11385,47 +11549,39 @@ function getSystemMeta() {
11385
11549
  is_ci: detectCI(),
11386
11550
  ci_name: getCIName(),
11387
11551
  is_wsl: detectWSL(),
11388
- is_tty: Boolean(process.stdout?.isTTY)
11552
+ is_tty: Boolean(process.stdout?.isTTY),
11553
+ sandbox_runtime: detectSandboxRuntime(),
11554
+ agent_runtime: detectAgentRuntime()
11389
11555
  };
11390
11556
  return cached;
11391
11557
  }
11392
11558
  function detectDocker() {
11393
11559
  try {
11394
- if (existsSync4("/.dockerenv")) return true;
11395
- if (platform() === "linux") {
11396
- const cgroup = readFileSync4("/proc/1/cgroup", "utf-8");
11560
+ if (existsSync5("/.dockerenv")) return true;
11561
+ if (platform3() === "linux") {
11562
+ const cgroup = readFileSync6("/proc/1/cgroup", "utf-8");
11397
11563
  if (cgroup.includes("docker") || cgroup.includes("containerd")) return true;
11398
11564
  }
11399
11565
  } catch {
11400
11566
  }
11401
11567
  return false;
11402
11568
  }
11569
+ function matchesProvider(p2) {
11570
+ const v2 = process.env[p2.envVar];
11571
+ if (p2.mode === "presence") return v2 != null;
11572
+ return v2 === "true" || v2 === "1";
11573
+ }
11403
11574
  function detectCI() {
11404
- return process.env["CI"] === "true" || process.env["CI"] === "1" || process.env["CONTINUOUS_INTEGRATION"] === "true" || process.env["GITHUB_ACTIONS"] === "true" || process.env["GITLAB_CI"] === "true" || process.env["CIRCLECI"] === "true" || process.env["JENKINS_URL"] != null || process.env["BUILDKITE"] === "true" || process.env["TRAVIS"] === "true" || false;
11575
+ return CI_PROVIDERS.some(matchesProvider);
11405
11576
  }
11406
11577
  function getCIName() {
11407
- if (process.env["GITHUB_ACTIONS"] === "true") return "github_actions";
11408
- if (process.env["GITLAB_CI"] === "true") return "gitlab_ci";
11409
- if (process.env["CIRCLECI"] === "true") return "circleci";
11410
- if (process.env["JENKINS_URL"] != null) return "jenkins";
11411
- if (process.env["BUILDKITE"] === "true") return "buildkite";
11412
- if (process.env["TRAVIS"] === "true") return "travis";
11413
- if (detectCI()) return "unknown";
11414
- return null;
11415
- }
11416
- function detectWSL() {
11417
- if (platform() !== "linux") return false;
11418
- try {
11419
- const osRelease = release().toLowerCase();
11420
- if (osRelease.includes("microsoft") || osRelease.includes("wsl")) return true;
11421
- const procVersion = readFileSync4("/proc/version", "utf-8").toLowerCase();
11422
- return procVersion.includes("microsoft") || procVersion.includes("wsl");
11423
- } catch {
11424
- return false;
11578
+ for (const provider of CI_PROVIDERS) {
11579
+ if (provider.name && matchesProvider(provider)) return provider.name;
11425
11580
  }
11581
+ return detectCI() ? "unknown" : null;
11426
11582
  }
11427
11583
  function getShmSizeMb() {
11428
- if (platform() !== "linux") return null;
11584
+ if (platform3() !== "linux") return null;
11429
11585
  try {
11430
11586
  const stats = statfsSync("/dev/shm");
11431
11587
  return bytesToMb(stats.bsize * stats.blocks);
@@ -11441,11 +11597,23 @@ function getFreeDiskMb(path2 = ".") {
11441
11597
  return null;
11442
11598
  }
11443
11599
  }
11444
- var cached;
11600
+ var cached, CI_PROVIDERS;
11445
11601
  var init_system = __esm({
11446
11602
  "src/telemetry/system.ts"() {
11447
11603
  "use strict";
11604
+ init_agent_runtime();
11605
+ init_platform();
11448
11606
  cached = null;
11607
+ CI_PROVIDERS = [
11608
+ { name: "github_actions", envVar: "GITHUB_ACTIONS", mode: "truthy" },
11609
+ { name: "gitlab_ci", envVar: "GITLAB_CI", mode: "truthy" },
11610
+ { name: "circleci", envVar: "CIRCLECI", mode: "truthy" },
11611
+ { name: "jenkins", envVar: "JENKINS_URL", mode: "presence" },
11612
+ { name: "buildkite", envVar: "BUILDKITE", mode: "truthy" },
11613
+ { name: "travis", envVar: "TRAVIS", mode: "truthy" },
11614
+ { name: null, envVar: "CONTINUOUS_INTEGRATION", mode: "truthy" },
11615
+ { name: null, envVar: "CI", mode: "truthy" }
11616
+ ];
11449
11617
  }
11450
11618
  });
11451
11619
 
@@ -11488,32 +11656,35 @@ function trackEvent(event, properties = {}) {
11488
11656
  is_ci: sys.is_ci,
11489
11657
  ci_name: sys.ci_name ?? void 0,
11490
11658
  is_wsl: sys.is_wsl,
11491
- is_tty: sys.is_tty
11659
+ is_tty: sys.is_tty,
11660
+ sandbox_runtime: sys.sandbox_runtime ?? void 0,
11661
+ agent_runtime: sys.agent_runtime ?? void 0
11492
11662
  },
11493
11663
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
11494
11664
  });
11495
11665
  }
11496
- async function flush() {
11497
- if (eventQueue.length === 0) {
11498
- return;
11499
- }
11666
+ function drainQueueToPayload() {
11667
+ if (eventQueue.length === 0) return null;
11500
11668
  const config = readConfig();
11501
11669
  const batch = eventQueue.map((e3) => ({
11502
11670
  event: e3.event,
11503
- // $ip: null tells PostHog to not record the request IP for this event.
11504
- // Server-side "Discard client IP data" is also enabled in project settings.
11505
11671
  properties: { ...e3.properties, $ip: null },
11506
11672
  distinct_id: config.anonymousId,
11507
11673
  timestamp: e3.timestamp
11508
11674
  }));
11509
11675
  eventQueue = [];
11676
+ return JSON.stringify({ api_key: POSTHOG_API_KEY, batch });
11677
+ }
11678
+ async function flush() {
11679
+ const payload = drainQueueToPayload();
11680
+ if (payload == null) return;
11510
11681
  const controller = new AbortController();
11511
11682
  const timeout = setTimeout(() => controller.abort(), FLUSH_TIMEOUT_MS);
11512
11683
  try {
11513
11684
  await fetch(`${POSTHOG_HOST}/batch/`, {
11514
11685
  method: "POST",
11515
11686
  headers: { "Content-Type": "application/json", Connection: "close" },
11516
- body: JSON.stringify({ api_key: POSTHOG_API_KEY, batch }),
11687
+ body: payload,
11517
11688
  signal: controller.signal
11518
11689
  });
11519
11690
  } catch {
@@ -11522,18 +11693,8 @@ async function flush() {
11522
11693
  }
11523
11694
  }
11524
11695
  function flushSync() {
11525
- if (eventQueue.length === 0) {
11526
- return;
11527
- }
11528
- const config = readConfig();
11529
- const batch = eventQueue.map((e3) => ({
11530
- event: e3.event,
11531
- properties: { ...e3.properties, $ip: null },
11532
- distinct_id: config.anonymousId,
11533
- timestamp: e3.timestamp
11534
- }));
11535
- eventQueue = [];
11536
- const payload = JSON.stringify({ api_key: POSTHOG_API_KEY, batch });
11696
+ const payload = drainQueueToPayload();
11697
+ if (payload == null) return;
11537
11698
  try {
11538
11699
  const { spawn: spawn17 } = __require("child_process");
11539
11700
  const child = spawn17(
@@ -11708,8 +11869,8 @@ __export(manager_exports, {
11708
11869
  hasFFprobe: () => hasFFprobe
11709
11870
  });
11710
11871
  import { execFileSync } from "child_process";
11711
- import { existsSync as existsSync5, mkdirSync as mkdirSync3, rmSync } from "fs";
11712
- import { homedir as homedir3, platform as platform2 } from "os";
11872
+ import { existsSync as existsSync6, mkdirSync as mkdirSync3, rmSync } from "fs";
11873
+ import { homedir as homedir3, platform as platform4 } from "os";
11713
11874
  import { join as join5 } from "path";
11714
11875
  function getModelUrl(model) {
11715
11876
  return `https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-${model}.bin`;
@@ -11730,7 +11891,7 @@ function whichBinary(name) {
11730
11891
  }
11731
11892
  function findFromEnv() {
11732
11893
  const envPath = process.env["HYPERFRAMES_WHISPER_PATH"];
11733
- if (envPath && existsSync5(envPath)) {
11894
+ if (envPath && existsSync6(envPath)) {
11734
11895
  return { executablePath: envPath, source: "env" };
11735
11896
  }
11736
11897
  return void 0;
@@ -11740,9 +11901,9 @@ function findFromSystem() {
11740
11901
  const path2 = whichBinary(name);
11741
11902
  if (path2) return { executablePath: path2, source: "system" };
11742
11903
  }
11743
- if (platform2() === "darwin") {
11904
+ if (platform4() === "darwin") {
11744
11905
  for (const p2 of ["/opt/homebrew/bin/whisper-cli", "/usr/local/bin/whisper-cli"]) {
11745
- if (existsSync5(p2)) return { executablePath: p2, source: "system" };
11906
+ if (existsSync6(p2)) return { executablePath: p2, source: "system" };
11746
11907
  }
11747
11908
  }
11748
11909
  return void 0;
@@ -11752,15 +11913,15 @@ function findBuiltBinary() {
11752
11913
  join5(BUILD_DIR, "build", "bin", "whisper-cli"),
11753
11914
  join5(BUILD_DIR, "build", "whisper-cli")
11754
11915
  ]) {
11755
- if (existsSync5(p2)) return { executablePath: p2, source: "build" };
11916
+ if (existsSync6(p2)) return { executablePath: p2, source: "build" };
11756
11917
  }
11757
11918
  return void 0;
11758
11919
  }
11759
11920
  function buildFromSource(onProgress) {
11760
- if (existsSync5(BUILD_DIR) && !findBuiltBinary()) {
11921
+ if (existsSync6(BUILD_DIR) && !findBuiltBinary()) {
11761
11922
  rmSync(BUILD_DIR, { recursive: true, force: true });
11762
11923
  }
11763
- if (!existsSync5(BUILD_DIR)) {
11924
+ if (!existsSync6(BUILD_DIR)) {
11764
11925
  onProgress?.("Downloading whisper.cpp...");
11765
11926
  mkdirSync3(join5(homedir3(), ".cache", "hyperframes", "whisper"), {
11766
11927
  recursive: true
@@ -11803,7 +11964,7 @@ function findWhisper() {
11803
11964
  return findFromEnv() ?? findFromSystem() ?? findBuiltBinary();
11804
11965
  }
11805
11966
  function getInstallInstructions() {
11806
- if (platform2() === "darwin") {
11967
+ if (platform4() === "darwin") {
11807
11968
  return "brew install whisper-cpp";
11808
11969
  }
11809
11970
  return "See https://github.com/ggml-org/whisper.cpp#building";
@@ -11820,7 +11981,7 @@ function hasCmake() {
11820
11981
  async function ensureWhisper(options) {
11821
11982
  const existing = findWhisper();
11822
11983
  if (existing) return existing;
11823
- if (platform2() === "darwin" && hasBrew()) {
11984
+ if (platform4() === "darwin" && hasBrew()) {
11824
11985
  options?.onProgress?.("Installing whisper-cpp via Homebrew...");
11825
11986
  try {
11826
11987
  execFileSync("brew", ["install", "whisper-cpp"], {
@@ -11842,11 +12003,11 @@ async function ensureWhisper(options) {
11842
12003
  }
11843
12004
  async function ensureModel(model = DEFAULT_MODEL, options) {
11844
12005
  const modelPath2 = join5(MODELS_DIR, `ggml-${model}.bin`);
11845
- if (existsSync5(modelPath2)) return modelPath2;
12006
+ if (existsSync6(modelPath2)) return modelPath2;
11846
12007
  mkdirSync3(MODELS_DIR, { recursive: true });
11847
12008
  options?.onProgress?.(`Downloading model ${model}...`);
11848
12009
  await downloadFile(getModelUrl(model), modelPath2);
11849
- if (!existsSync5(modelPath2)) {
12010
+ if (!existsSync6(modelPath2)) {
11850
12011
  throw new Error(`Model download failed: ${model}`);
11851
12012
  }
11852
12013
  return modelPath2;
@@ -11885,13 +12046,13 @@ __export(normalize_exports, {
11885
12046
  patchCaptionHtml: () => patchCaptionHtml,
11886
12047
  stripBeforeOnset: () => stripBeforeOnset
11887
12048
  });
11888
- import { readFileSync as readFileSync5, readdirSync, writeFileSync as writeFileSync4 } from "fs";
12049
+ import { readFileSync as readFileSync7, readdirSync, writeFileSync as writeFileSync4 } from "fs";
11889
12050
  import { extname, join as join6 } from "path";
11890
12051
  function detectFormat(filePath) {
11891
12052
  const ext = extname(filePath).toLowerCase();
11892
12053
  if (ext === ".srt") return "srt";
11893
12054
  if (ext === ".vtt") return "vtt";
11894
- if (ext === ".json") return detectJsonFormat(JSON.parse(readFileSync5(filePath, "utf-8")));
12055
+ if (ext === ".json") return detectJsonFormat(JSON.parse(readFileSync7(filePath, "utf-8")));
11895
12056
  throw new Error(`Unsupported transcript file extension: ${ext}. Use .json, .srt, or .vtt`);
11896
12057
  }
11897
12058
  function detectJsonFormat(raw) {
@@ -12041,7 +12202,7 @@ function round3(n) {
12041
12202
  }
12042
12203
  function loadTranscript(filePath) {
12043
12204
  const ext = extname(filePath).toLowerCase();
12044
- const content = readFileSync5(filePath, "utf-8");
12205
+ const content = readFileSync7(filePath, "utf-8");
12045
12206
  if (ext === ".srt") {
12046
12207
  const words2 = parseSrt(content).map((w3, i2) => ({ ...w3, id: w3.id ?? `w${i2}` }));
12047
12208
  return { words: words2, format: "srt" };
@@ -12073,7 +12234,7 @@ function patchCaptionHtml(dir, words) {
12073
12234
  return;
12074
12235
  }
12075
12236
  for (const file of htmlFiles) {
12076
- let content = readFileSync5(file, "utf-8");
12237
+ let content = readFileSync7(file, "utf-8");
12077
12238
  const scriptBlocks = content.match(/<script>[\s\S]*?<\/script>/g) ?? [];
12078
12239
  let scriptMatch = null;
12079
12240
  let transcriptMatch = null;
@@ -12106,7 +12267,7 @@ __export(projectConfig_exports, {
12106
12267
  readProjectConfig: () => readProjectConfig,
12107
12268
  writeProjectConfig: () => writeProjectConfig
12108
12269
  });
12109
- import { readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
12270
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
12110
12271
  import { join as join7, resolve as resolve4 } from "path";
12111
12272
  function projectConfigPath(projectDir) {
12112
12273
  return join7(resolve4(projectDir), PROJECT_CONFIG_FILENAME);
@@ -12114,7 +12275,7 @@ function projectConfigPath(projectDir) {
12114
12275
  function readProjectConfig(projectDir) {
12115
12276
  const path2 = projectConfigPath(projectDir);
12116
12277
  try {
12117
- const parsed = JSON.parse(readFileSync6(path2, "utf-8"));
12278
+ const parsed = JSON.parse(readFileSync8(path2, "utf-8"));
12118
12279
  return normalizeConfig(parsed);
12119
12280
  } catch {
12120
12281
  return void 0;
@@ -12164,7 +12325,7 @@ __export(transcribe_exports, {
12164
12325
  transcribe: () => transcribe
12165
12326
  });
12166
12327
  import { execFileSync as execFileSync2 } from "child_process";
12167
- import { existsSync as existsSync6, readFileSync as readFileSync7, mkdirSync as mkdirSync4, unlinkSync as unlinkSync2 } from "fs";
12328
+ import { existsSync as existsSync7, readFileSync as readFileSync9, mkdirSync as mkdirSync4, unlinkSync as unlinkSync2 } from "fs";
12168
12329
  import { join as join8, extname as extname2 } from "path";
12169
12330
  import { tmpdir } from "os";
12170
12331
  function detectLanguage(whisperPath, modelPath2, wavPath) {
@@ -12200,7 +12361,7 @@ function detectSpeechOnset(wavPath) {
12200
12361
  const SILENCE_THRESHOLD_RATIO = 0.6;
12201
12362
  const MIN_INTRO_SECONDS = 3;
12202
12363
  try {
12203
- const buf = readFileSync7(wavPath);
12364
+ const buf = readFileSync9(wavPath);
12204
12365
  const dataChunk = findWavDataChunk(buf);
12205
12366
  if (!dataChunk) return null;
12206
12367
  const pcm = new Int16Array(buf.buffer, buf.byteOffset + dataChunk.offset, dataChunk.size / 2);
@@ -12338,10 +12499,10 @@ async function transcribe(inputPath, outputDir, options) {
12338
12499
  whisperArgs.push(wavPath);
12339
12500
  execFileSync2(whisper.executablePath, whisperArgs, { stdio: "ignore", timeout: 3e5 });
12340
12501
  const transcriptPath = `${outputBase}.json`;
12341
- if (!existsSync6(transcriptPath)) {
12502
+ if (!existsSync7(transcriptPath)) {
12342
12503
  throw new Error("Whisper did not produce output. Check the input file.");
12343
12504
  }
12344
- const transcript = JSON.parse(readFileSync7(transcriptPath, "utf-8"));
12505
+ const transcript = JSON.parse(readFileSync9(transcriptPath, "utf-8"));
12345
12506
  const segments = transcript.transcription ?? [];
12346
12507
  let wordCount = 0;
12347
12508
  let maxEnd = 0;
@@ -12492,7 +12653,7 @@ var init_lint = __esm({
12492
12653
  });
12493
12654
 
12494
12655
  // src/utils/lintProject.ts
12495
- import { existsSync as existsSync7, readFileSync as readFileSync8, readdirSync as readdirSync2 } from "fs";
12656
+ import { existsSync as existsSync8, readFileSync as readFileSync10, readdirSync as readdirSync2 } from "fs";
12496
12657
  import { dirname as dirname4, join as join9, resolve as resolve5, extname as extname3 } from "path";
12497
12658
  function readHtmlAttr(tag, name) {
12498
12659
  const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -12514,8 +12675,8 @@ function collectExternalStyles(projectDir, html, compSrcPath) {
12514
12675
  if (!isLocalStylesheetHref(href)) continue;
12515
12676
  const rootRelative = compSrcPath ? join9(dirname4(compSrcPath), href) : href;
12516
12677
  const resolved = resolve5(projectDir, rootRelative);
12517
- if (!existsSync7(resolved)) continue;
12518
- styles.push({ href, content: readFileSync8(resolved, "utf-8") });
12678
+ if (!existsSync8(resolved)) continue;
12679
+ styles.push({ href, content: readFileSync10(resolved, "utf-8") });
12519
12680
  }
12520
12681
  return styles;
12521
12682
  }
@@ -12536,8 +12697,8 @@ function collectCssSources(projectDir, html, compSrcPath) {
12536
12697
  if (!isLocalStylesheetHref(href)) continue;
12537
12698
  const rootRelativePath = compSrcPath ? join9(dirname4(compSrcPath), href) : href;
12538
12699
  const resolved = resolve5(projectDir, rootRelativePath);
12539
- if (!existsSync7(resolved)) continue;
12540
- sources.push({ content: readFileSync8(resolved, "utf-8"), rootRelativePath });
12700
+ if (!existsSync8(resolved)) continue;
12701
+ sources.push({ content: readFileSync10(resolved, "utf-8"), rootRelativePath });
12541
12702
  }
12542
12703
  let tagMatch;
12543
12704
  const tagPattern = new RegExp(OPEN_TAG_RE.source, OPEN_TAG_RE.flags);
@@ -12566,7 +12727,7 @@ function lintProject(project) {
12566
12727
  let totalErrors = 0;
12567
12728
  let totalWarnings = 0;
12568
12729
  let totalInfos = 0;
12569
- const rootHtml = readFileSync8(project.indexPath, "utf-8");
12730
+ const rootHtml = readFileSync10(project.indexPath, "utf-8");
12570
12731
  const rootResult = lintHyperframeHtml(rootHtml, {
12571
12732
  filePath: project.indexPath,
12572
12733
  externalStyles: collectExternalStyles(project.dir, rootHtml)
@@ -12577,11 +12738,11 @@ function lintProject(project) {
12577
12738
  totalInfos += rootResult.infoCount;
12578
12739
  const allHtmlSources = [{ html: rootHtml }];
12579
12740
  const compositionsDir = resolve5(project.dir, "compositions");
12580
- if (existsSync7(compositionsDir)) {
12741
+ if (existsSync8(compositionsDir)) {
12581
12742
  const files = readdirSync2(compositionsDir).filter((f3) => f3.endsWith(".html"));
12582
12743
  for (const file of files) {
12583
12744
  const filePath = join9(compositionsDir, file);
12584
- const html = readFileSync8(filePath, "utf-8");
12745
+ const html = readFileSync10(filePath, "utf-8");
12585
12746
  const compSrcPath = `compositions/${file}`;
12586
12747
  allHtmlSources.push({ html, compSrcPath });
12587
12748
  const result = lintHyperframeHtml(html, {
@@ -12654,7 +12815,7 @@ function lintAudioSrcNotFound(projectDir, htmlSources) {
12654
12815
  if (/^__[A-Z_]+__$/.test(src)) continue;
12655
12816
  const rootRelative = compSrcPath ? rewriteAssetPath(compSrcPath, src) : src;
12656
12817
  const resolved = resolve5(projectDir, rootRelative);
12657
- if (!existsSync7(resolved)) {
12818
+ if (!existsSync8(resolved)) {
12658
12819
  missingSrcs.push(src);
12659
12820
  }
12660
12821
  }
@@ -12687,7 +12848,7 @@ function lintTextureMaskAssetNotFound(projectDir, htmlSources) {
12687
12848
  compSrcPath,
12688
12849
  cssSource.rootRelativePath
12689
12850
  );
12690
- if (existsSync7(resolved)) continue;
12851
+ if (existsSync8(resolved)) continue;
12691
12852
  missing.set(url, resolved);
12692
12853
  }
12693
12854
  }
@@ -12709,7 +12870,7 @@ function lintMultipleRootCompositions(projectDir) {
12709
12870
  const rootHtmlFiles = readdirSync2(projectDir).filter((f3) => f3.endsWith(".html"));
12710
12871
  const rootCompositions = [];
12711
12872
  for (const file of rootHtmlFiles) {
12712
- const content = readFileSync8(join9(projectDir, file), "utf-8");
12873
+ const content = readFileSync10(join9(projectDir, file), "utf-8");
12713
12874
  if (/data-composition-id/i.test(content)) {
12714
12875
  rootCompositions.push(file);
12715
12876
  }
@@ -13132,13 +13293,13 @@ var init_fileWatcher = __esm({
13132
13293
  });
13133
13294
 
13134
13295
  // src/server/runtimeSource.ts
13135
- import { existsSync as existsSync8, readFileSync as readFileSync9 } from "fs";
13296
+ import { existsSync as existsSync9, readFileSync as readFileSync11 } from "fs";
13136
13297
  import { resolve as resolve7, dirname as dirname5 } from "path";
13137
13298
  async function loadRuntimeSource() {
13138
13299
  return await buildFromSource2() ?? await getInlinedRuntime() ?? readPrebuiltArtifact();
13139
13300
  }
13140
13301
  async function buildFromSource2() {
13141
- if (!existsSync8(ENTRY_TS)) return null;
13302
+ if (!existsSync9(ENTRY_TS)) return null;
13142
13303
  try {
13143
13304
  const mod = await Promise.resolve().then(() => (init_src(), src_exports));
13144
13305
  if (typeof mod.loadHyperframeRuntimeSource === "function") {
@@ -13165,7 +13326,7 @@ function readPrebuiltArtifact() {
13165
13326
  function readFromDir(dir) {
13166
13327
  for (const name of ARTIFACT_NAMES) {
13167
13328
  const path2 = resolve7(dir, name);
13168
- if (existsSync8(path2)) return readFileSync9(path2, "utf-8");
13329
+ if (existsSync9(path2)) return readFileSync11(path2, "utf-8");
13169
13330
  }
13170
13331
  return null;
13171
13332
  }
@@ -13383,7 +13544,7 @@ var init_mime = __esm({
13383
13544
 
13384
13545
  // ../core/src/studio-api/helpers/waveform.ts
13385
13546
  import { spawn as spawn3 } from "child_process";
13386
- import { existsSync as existsSync9, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5 } from "fs";
13547
+ import { existsSync as existsSync10, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5 } from "fs";
13387
13548
  import { join as join11 } from "path";
13388
13549
  function buildWaveformCacheKey(assetPath) {
13389
13550
  return `${WAVEFORM_CACHE_VERSION}_${assetPath.replace(/[/\\]/g, "_")}.json`;
@@ -13445,10 +13606,10 @@ function decodeAudioPeaks(audioPath) {
13445
13606
  }
13446
13607
  async function generateWaveformCache(projectDir, assetPath) {
13447
13608
  const audioPath = join11(projectDir, assetPath);
13448
- if (!existsSync9(audioPath)) return;
13609
+ if (!existsSync10(audioPath)) return;
13449
13610
  const cacheDir = join11(projectDir, ".waveform-cache");
13450
13611
  const cachePath2 = join11(cacheDir, buildWaveformCacheKey(assetPath));
13451
- if (existsSync9(cachePath2)) return;
13612
+ if (existsSync10(cachePath2)) return;
13452
13613
  const peaks = await decodeAudioPeaks(audioPath);
13453
13614
  mkdirSync5(cacheDir, { recursive: true });
13454
13615
  writeFileSync6(cachePath2, JSON.stringify(peaks));
@@ -26303,8 +26464,8 @@ var init_sourceMutation = __esm({
26303
26464
  // ../core/src/studio-api/routes/files.ts
26304
26465
  import { bodyLimit } from "hono/body-limit";
26305
26466
  import {
26306
- existsSync as existsSync10,
26307
- readFileSync as readFileSync10,
26467
+ existsSync as existsSync11,
26468
+ readFileSync as readFileSync12,
26308
26469
  writeFileSync as writeFileSync8,
26309
26470
  mkdirSync as mkdirSync6,
26310
26471
  unlinkSync as unlinkSync3,
@@ -26328,14 +26489,14 @@ async function resolveProjectFile(c3, adapter2, opts) {
26328
26489
  if (!isSafePath(project.dir, absPath)) {
26329
26490
  return { error: c3.json({ error: "forbidden" }, 403) };
26330
26491
  }
26331
- if (opts?.mustExist && !existsSync10(absPath)) {
26492
+ if (opts?.mustExist && !existsSync11(absPath)) {
26332
26493
  return { error: c3.json({ error: "not found" }, 404) };
26333
26494
  }
26334
26495
  return { project, filePath, absPath };
26335
26496
  }
26336
26497
  function ensureDir(filePath) {
26337
26498
  const dir = dirname6(filePath);
26338
- if (!existsSync10(dir)) mkdirSync6(dir, { recursive: true });
26499
+ if (!existsSync11(dir)) mkdirSync6(dir, { recursive: true });
26339
26500
  }
26340
26501
  function generateCopyPath(projectDir, originalPath) {
26341
26502
  const ext = originalPath.includes(".") ? "." + originalPath.split(".").pop() : "";
@@ -26344,7 +26505,7 @@ function generateCopyPath(projectDir, originalPath) {
26344
26505
  const cleanBase = copyMatch ? base.slice(0, -copyMatch[0].length) : base;
26345
26506
  let num = copyMatch ? copyMatch[1] ? parseInt(copyMatch[1]) + 1 : 2 : 1;
26346
26507
  let candidate = num === 1 ? `${cleanBase} (copy)${ext}` : `${cleanBase} (copy ${num})${ext}`;
26347
- while (existsSync10(resolve9(projectDir, candidate))) {
26508
+ while (existsSync11(resolve9(projectDir, candidate))) {
26348
26509
  num++;
26349
26510
  candidate = `${cleanBase} (copy ${num})${ext}`;
26350
26511
  }
@@ -26371,7 +26532,7 @@ function updateReferences(projectDir, oldPath, newPath) {
26371
26532
  );
26372
26533
  let updatedCount = 0;
26373
26534
  for (const file of textFiles) {
26374
- const content = readFileSync10(file, "utf-8");
26535
+ const content = readFileSync12(file, "utf-8");
26375
26536
  if (!content.includes(oldPath)) continue;
26376
26537
  const updated = content.split(oldPath).join(newPath);
26377
26538
  if (updated !== content) {
@@ -26385,13 +26546,13 @@ function registerFileRoutes(api, adapter2) {
26385
26546
  api.get("/projects/:id/files/*", async (c3) => {
26386
26547
  const res = await resolveProjectFile(c3, adapter2);
26387
26548
  if ("error" in res) return res.error;
26388
- if (!existsSync10(res.absPath)) {
26549
+ if (!existsSync11(res.absPath)) {
26389
26550
  if (c3.req.query("optional") === "1") {
26390
26551
  return c3.json({ filename: res.filePath, content: "" });
26391
26552
  }
26392
26553
  return c3.json({ error: "not found" }, 404);
26393
26554
  }
26394
- const content = readFileSync10(res.absPath, "utf-8");
26555
+ const content = readFileSync12(res.absPath, "utf-8");
26395
26556
  return c3.json({ filename: res.filePath, content });
26396
26557
  });
26397
26558
  api.put("/projects/:id/files/*", async (c3) => {
@@ -26405,7 +26566,7 @@ function registerFileRoutes(api, adapter2) {
26405
26566
  api.post("/projects/:id/files/*", async (c3) => {
26406
26567
  const res = await resolveProjectFile(c3, adapter2);
26407
26568
  if ("error" in res) return res.error;
26408
- if (existsSync10(res.absPath)) {
26569
+ if (existsSync11(res.absPath)) {
26409
26570
  return c3.json({ error: "already exists" }, 409);
26410
26571
  }
26411
26572
  ensureDir(res.absPath);
@@ -26438,14 +26599,14 @@ function registerFileRoutes(api, adapter2) {
26438
26599
  if (!isSafePath(project.dir, absPath)) {
26439
26600
  return c3.json({ error: "forbidden" }, 403);
26440
26601
  }
26441
- if (!existsSync10(absPath)) {
26602
+ if (!existsSync11(absPath)) {
26442
26603
  return c3.json({ error: "not found" }, 404);
26443
26604
  }
26444
26605
  const body = await c3.req.json().catch(() => null);
26445
26606
  if (!body?.target) {
26446
26607
  return c3.json({ error: "target required" }, 400);
26447
26608
  }
26448
- const originalContent = readFileSync10(absPath, "utf-8");
26609
+ const originalContent = readFileSync12(absPath, "utf-8");
26449
26610
  const patchedContent = removeElementFromHtml2(originalContent, body.target);
26450
26611
  if (patchedContent === originalContent) {
26451
26612
  return c3.json({ ok: true, changed: false, content: originalContent });
@@ -26473,7 +26634,7 @@ function registerFileRoutes(api, adapter2) {
26473
26634
  }
26474
26635
  let originalContent;
26475
26636
  try {
26476
- originalContent = readFileSync10(absPath, "utf-8");
26637
+ originalContent = readFileSync12(absPath, "utf-8");
26477
26638
  } catch {
26478
26639
  return c3.json({ error: "not found" }, 404);
26479
26640
  }
@@ -26495,7 +26656,7 @@ function registerFileRoutes(api, adapter2) {
26495
26656
  if (!isSafePath(res.project.dir, newAbs)) {
26496
26657
  return c3.json({ error: "forbidden" }, 403);
26497
26658
  }
26498
- if (existsSync10(newAbs)) {
26659
+ if (existsSync11(newAbs)) {
26499
26660
  return c3.json({ error: "already exists" }, 409);
26500
26661
  }
26501
26662
  ensureDir(newAbs);
@@ -26511,7 +26672,7 @@ function registerFileRoutes(api, adapter2) {
26511
26672
  return c3.json({ error: "path required" }, 400);
26512
26673
  }
26513
26674
  const srcAbs = resolve9(project.dir, body.path);
26514
- if (!isSafePath(project.dir, srcAbs) || !existsSync10(srcAbs)) {
26675
+ if (!isSafePath(project.dir, srcAbs) || !existsSync11(srcAbs)) {
26515
26676
  return c3.json({ error: "not found" }, 404);
26516
26677
  }
26517
26678
  const copyPath = generateCopyPath(project.dir, body.path);
@@ -26520,7 +26681,7 @@ function registerFileRoutes(api, adapter2) {
26520
26681
  return c3.json({ error: "forbidden" }, 403);
26521
26682
  }
26522
26683
  ensureDir(destAbs);
26523
- writeFileSync8(destAbs, readFileSync10(srcAbs));
26684
+ writeFileSync8(destAbs, readFileSync12(srcAbs));
26524
26685
  return c3.json({ ok: true, path: copyPath }, 201);
26525
26686
  });
26526
26687
  const MAX_UPLOAD_BYTES = 500 * 1024 * 1024;
@@ -26536,7 +26697,7 @@ function registerFileRoutes(api, adapter2) {
26536
26697
  const subDir = c3.req.query("dir") ?? "";
26537
26698
  const targetDir = subDir ? resolve9(project.dir, subDir) : project.dir;
26538
26699
  if (!isSafePath(project.dir, targetDir)) return c3.json({ error: "forbidden" }, 403);
26539
- if (subDir && !existsSync10(targetDir)) mkdirSync6(targetDir, { recursive: true });
26700
+ if (subDir && !existsSync11(targetDir)) mkdirSync6(targetDir, { recursive: true });
26540
26701
  const formData = await c3.req.formData();
26541
26702
  const uploaded = [];
26542
26703
  const skipped = [];
@@ -26554,12 +26715,12 @@ function registerFileRoutes(api, adapter2) {
26554
26715
  if (!isSafePath(project.dir, destPath)) continue;
26555
26716
  let finalPath = destPath;
26556
26717
  let finalName = name;
26557
- if (existsSync10(finalPath)) {
26718
+ if (existsSync11(finalPath)) {
26558
26719
  const dotIdx = name.indexOf(".", name.startsWith(".") ? 1 : 0);
26559
26720
  const ext = dotIdx > 0 ? name.slice(dotIdx) : "";
26560
26721
  const base = dotIdx > 0 ? name.slice(0, dotIdx) : name;
26561
26722
  let n = 2;
26562
- while (n < 1e4 && existsSync10(resolve9(targetDir, `${base} (${n})${ext}`))) n++;
26723
+ while (n < 1e4 && existsSync11(resolve9(targetDir, `${base} (${n})${ext}`))) n++;
26563
26724
  if (n >= 1e4) {
26564
26725
  skipped.push(name);
26565
26726
  continue;
@@ -26781,7 +26942,7 @@ var init_htmlDocument = __esm({
26781
26942
  });
26782
26943
 
26783
26944
  // ../core/src/studio-api/helpers/subComposition.ts
26784
- import { existsSync as existsSync11, readFileSync as readFileSync11 } from "fs";
26945
+ import { existsSync as existsSync12, readFileSync as readFileSync13 } from "fs";
26785
26946
  import { join as join14 } from "path";
26786
26947
  function isFullHtmlDocument(html) {
26787
26948
  return /^\s*(?:<!doctype\s|<html[\s>])/i.test(html);
@@ -26830,8 +26991,8 @@ function extractElementAttrs(el) {
26830
26991
  }
26831
26992
  function buildSubCompositionHtml(projectDir, compPath, runtimeUrl, baseHref) {
26832
26993
  const compFile = join14(projectDir, compPath);
26833
- if (!existsSync11(compFile)) return null;
26834
- const rawComp = readFileSync11(compFile, "utf-8");
26994
+ if (!existsSync12(compFile)) return null;
26995
+ const rawComp = readFileSync13(compFile, "utf-8");
26835
26996
  let compHeadContent = "";
26836
26997
  let rewrittenContent;
26837
26998
  let htmlAttrs = "";
@@ -26859,8 +27020,8 @@ function buildSubCompositionHtml(projectDir, compPath, runtimeUrl, baseHref) {
26859
27020
  }
26860
27021
  const indexPath = join14(projectDir, "index.html");
26861
27022
  let headContent = "";
26862
- if (existsSync11(indexPath)) {
26863
- const indexHtml = readFileSync11(indexPath, "utf-8");
27023
+ if (existsSync12(indexPath)) {
27024
+ const indexHtml = readFileSync13(indexPath, "utf-8");
26864
27025
  const headMatch = indexHtml.match(/<head[^>]*>([\s\S]*?)<\/head>/i);
26865
27026
  headContent = headMatch?.[1] ?? "";
26866
27027
  }
@@ -26901,7 +27062,7 @@ var init_subComposition = __esm({
26901
27062
 
26902
27063
  // ../core/src/studio-api/helpers/projectSignature.ts
26903
27064
  import { createHash } from "crypto";
26904
- import { lstatSync, readFileSync as readFileSync12, readdirSync as readdirSync5 } from "fs";
27065
+ import { lstatSync, readFileSync as readFileSync14, readdirSync as readdirSync5 } from "fs";
26905
27066
  import { extname as extname4, isAbsolute as isAbsolute2, relative as relative2, resolve as resolve10 } from "path";
26906
27067
  function isPathWithin(parentDir, childPath) {
26907
27068
  const childRelativePath = relative2(parentDir, childPath);
@@ -26993,7 +27154,7 @@ function createProjectSignature(projectDir) {
26993
27154
  hash2.update("\0");
26994
27155
  if (entry.textContentEligible) {
26995
27156
  try {
26996
- hash2.update(readFileSync12(entry.file));
27157
+ hash2.update(readFileSync14(entry.file));
26997
27158
  } catch {
26998
27159
  hash2.update(String(entry.mtimeMs));
26999
27160
  }
@@ -27238,7 +27399,7 @@ var init_studioMotionRenderScript = __esm({
27238
27399
  });
27239
27400
 
27240
27401
  // ../core/src/studio-api/routes/preview.ts
27241
- import { existsSync as existsSync12, readFileSync as readFileSync13, statSync as statSync2 } from "fs";
27402
+ import { existsSync as existsSync13, readFileSync as readFileSync15, statSync as statSync2 } from "fs";
27242
27403
  import { join as join15, resolve as resolve11 } from "path";
27243
27404
  function resolveProjectSignature(adapter2, projectDir) {
27244
27405
  return adapter2.getProjectSignature?.(projectDir) ?? createProjectSignature(projectDir);
@@ -27258,9 +27419,9 @@ ${html}`;
27258
27419
  }
27259
27420
  function readStudioMotionManifestContent(projectDir) {
27260
27421
  const manifestPath = join15(projectDir, STUDIO_MOTION_PATH);
27261
- if (!existsSync12(manifestPath)) return "";
27422
+ if (!existsSync13(manifestPath)) return "";
27262
27423
  try {
27263
- return readFileSync13(manifestPath, "utf-8");
27424
+ return readFileSync15(manifestPath, "utf-8");
27264
27425
  } catch {
27265
27426
  return "";
27266
27427
  }
@@ -27341,12 +27502,12 @@ async function transformPreviewHtml(html, adapter2, project, activeCompositionPa
27341
27502
  }
27342
27503
  function resolveProjectMainHtml(projectDir, projectId) {
27343
27504
  const indexPath = join15(projectDir, "index.html");
27344
- if (existsSync12(indexPath)) {
27345
- return { html: readFileSync13(indexPath, "utf-8"), compositionPath: "index.html" };
27505
+ if (existsSync13(indexPath)) {
27506
+ return { html: readFileSync15(indexPath, "utf-8"), compositionPath: "index.html" };
27346
27507
  }
27347
27508
  const blockHtmlPath = join15(projectDir, `${projectId}.html`);
27348
- if (existsSync12(blockHtmlPath)) {
27349
- return { html: readFileSync13(blockHtmlPath, "utf-8"), compositionPath: `${projectId}.html` };
27509
+ if (existsSync13(blockHtmlPath)) {
27510
+ return { html: readFileSync15(blockHtmlPath, "utf-8"), compositionPath: `${projectId}.html` };
27350
27511
  }
27351
27512
  return null;
27352
27513
  }
@@ -27415,7 +27576,7 @@ ${runtimeTag}`;
27415
27576
  c3.req.path.replace(`/projects/${project.id}/preview/comp/`, "").split("?")[0] ?? ""
27416
27577
  );
27417
27578
  const compFile = resolve11(project.dir, compPath);
27418
- if (!isSafePath(project.dir, compFile) || !existsSync12(compFile) || !statSync2(compFile).isFile()) {
27579
+ if (!isSafePath(project.dir, compFile) || !existsSync13(compFile) || !statSync2(compFile).isFile()) {
27419
27580
  return c3.text("not found", 404);
27420
27581
  }
27421
27582
  const etag = `"comp:${compPath}:${signature}"`;
@@ -27440,7 +27601,7 @@ ${runtimeTag}`;
27440
27601
  c3.req.path.replace(`/projects/${project.id}/preview/`, "").split("?")[0] ?? ""
27441
27602
  );
27442
27603
  const file = resolve11(project.dir, subPath);
27443
- const stat3 = existsSync12(file) ? statSync2(file) : null;
27604
+ const stat3 = existsSync13(file) ? statSync2(file) : null;
27444
27605
  if (!isSafePath(project.dir, file) || !stat3?.isFile()) {
27445
27606
  return c3.text("not found", 404);
27446
27607
  }
@@ -27454,7 +27615,7 @@ ${runtimeTag}`;
27454
27615
  return new Response(null, { status: 304, headers: cacheHeaders });
27455
27616
  }
27456
27617
  }
27457
- const buffer = isText2 ? Buffer.from(readFileSync13(file, "utf-8"), "utf-8") : readFileSync13(file);
27618
+ const buffer = isText2 ? Buffer.from(readFileSync15(file, "utf-8"), "utf-8") : readFileSync15(file);
27458
27619
  const totalSize2 = buffer.length;
27459
27620
  const rangeHeader = c3.req.header("Range");
27460
27621
  if (rangeHeader) {
@@ -27524,7 +27685,7 @@ var init_preview = __esm({
27524
27685
  });
27525
27686
 
27526
27687
  // ../core/src/studio-api/routes/lint.ts
27527
- import { readFileSync as readFileSync14 } from "fs";
27688
+ import { readFileSync as readFileSync16 } from "fs";
27528
27689
  import { join as join16 } from "path";
27529
27690
  function registerLintRoutes(api, adapter2) {
27530
27691
  api.get("/projects/:id/lint", async (c3) => {
@@ -27534,7 +27695,7 @@ function registerLintRoutes(api, adapter2) {
27534
27695
  const htmlFiles = walkDir(project.dir).filter((f3) => f3.endsWith(".html"));
27535
27696
  const allFindings = [];
27536
27697
  for (const file of htmlFiles) {
27537
- const content = readFileSync14(join16(project.dir, file), "utf-8");
27698
+ const content = readFileSync16(join16(project.dir, file), "utf-8");
27538
27699
  const result = await adapter2.lint(content, { filePath: file });
27539
27700
  if (result?.findings) {
27540
27701
  for (const f3 of result.findings) {
@@ -27558,7 +27719,7 @@ var init_lint2 = __esm({
27558
27719
 
27559
27720
  // ../core/src/studio-api/routes/render.ts
27560
27721
  import { streamSSE } from "hono/streaming";
27561
- import { existsSync as existsSync13, readFileSync as readFileSync15, mkdirSync as mkdirSync7, unlinkSync as unlinkSync4, readdirSync as readdirSync6, statSync as statSync3 } from "fs";
27722
+ import { existsSync as existsSync14, readFileSync as readFileSync17, mkdirSync as mkdirSync7, unlinkSync as unlinkSync4, readdirSync as readdirSync6, statSync as statSync3 } from "fs";
27562
27723
  import { join as join17, resolve as resolve12, sep as sep2 } from "path";
27563
27724
  function registerRenderRoutes(api, adapter2) {
27564
27725
  const renderJobs = /* @__PURE__ */ new Map();
@@ -27610,7 +27771,7 @@ function registerRenderRoutes(api, adapter2) {
27610
27771
  const timePart = now.toTimeString().slice(0, 8).replace(/:/g, "-");
27611
27772
  const jobId = `${project.id}_${datePart}_${timePart}`;
27612
27773
  const rendersDir = adapter2.rendersDir(project);
27613
- if (!existsSync13(rendersDir)) mkdirSync7(rendersDir, { recursive: true });
27774
+ if (!existsSync14(rendersDir)) mkdirSync7(rendersDir, { recursive: true });
27614
27775
  const ext = FORMAT_EXT2[format] ?? ".mp4";
27615
27776
  const outputPath = join17(rendersDir, `${jobId}${ext}`);
27616
27777
  const jobState = adapter2.startRender({
@@ -27663,12 +27824,12 @@ function registerRenderRoutes(api, adapter2) {
27663
27824
  api.get("/render/:jobId/view", (c3) => {
27664
27825
  const { jobId } = c3.req.param();
27665
27826
  const job = renderJobs.get(jobId);
27666
- if (!job?.outputPath || !existsSync13(job.outputPath)) {
27827
+ if (!job?.outputPath || !existsSync14(job.outputPath)) {
27667
27828
  return c3.json({ error: "not found" }, 404);
27668
27829
  }
27669
27830
  const contentType = renderContentType(job.outputPath);
27670
27831
  const filename = job.outputPath.split("/").pop() ?? `render.mp4`;
27671
- const content = readFileSync15(job.outputPath);
27832
+ const content = readFileSync17(job.outputPath);
27672
27833
  return new Response(content, {
27673
27834
  headers: {
27674
27835
  "Content-Type": contentType,
@@ -27681,12 +27842,12 @@ function registerRenderRoutes(api, adapter2) {
27681
27842
  api.get("/render/:jobId/download", (c3) => {
27682
27843
  const { jobId } = c3.req.param();
27683
27844
  const job = renderJobs.get(jobId);
27684
- if (!job?.outputPath || !existsSync13(job.outputPath)) {
27845
+ if (!job?.outputPath || !existsSync14(job.outputPath)) {
27685
27846
  return c3.json({ error: "not found" }, 404);
27686
27847
  }
27687
27848
  const contentType = renderContentType(job.outputPath);
27688
27849
  const filename = job.outputPath.split("/").pop() ?? `render.mp4`;
27689
- const content = readFileSync15(job.outputPath);
27850
+ const content = readFileSync17(job.outputPath);
27690
27851
  return new Response(content, {
27691
27852
  headers: {
27692
27853
  "Content-Type": contentType,
@@ -27701,7 +27862,7 @@ function registerRenderRoutes(api, adapter2) {
27701
27862
  const dir = state.outputPath.replace(/\/[^/]+$/, "");
27702
27863
  for (const ext of [".mp4", ".webm", ".mov", ".meta.json"]) {
27703
27864
  const fp = join17(dir, `${jobId}${ext}`);
27704
- if (existsSync13(fp)) unlinkSync4(fp);
27865
+ if (existsSync14(fp)) unlinkSync4(fp);
27705
27866
  }
27706
27867
  break;
27707
27868
  }
@@ -27716,9 +27877,9 @@ function registerRenderRoutes(api, adapter2) {
27716
27877
  if (!filename) return c3.json({ error: "missing filename" }, 400);
27717
27878
  const rendersDir = adapter2.rendersDir(project);
27718
27879
  const fp = join17(rendersDir, filename);
27719
- if (!existsSync13(fp)) return c3.json({ error: "not found" }, 404);
27880
+ if (!existsSync14(fp)) return c3.json({ error: "not found" }, 404);
27720
27881
  const contentType = renderContentType(fp);
27721
- const content = readFileSync15(fp);
27882
+ const content = readFileSync17(fp);
27722
27883
  return new Response(content, {
27723
27884
  headers: {
27724
27885
  "Content-Type": contentType,
@@ -27732,7 +27893,7 @@ function registerRenderRoutes(api, adapter2) {
27732
27893
  const project = await adapter2.resolveProject(c3.req.param("id"));
27733
27894
  if (!project) return c3.json({ error: "not found" }, 404);
27734
27895
  const rendersDir = adapter2.rendersDir(project);
27735
- if (!existsSync13(rendersDir)) return c3.json({ renders: [] });
27896
+ if (!existsSync14(rendersDir)) return c3.json({ renders: [] });
27736
27897
  const files = readdirSync6(rendersDir).filter((f3) => f3.endsWith(".mp4") || f3.endsWith(".webm") || f3.endsWith(".mov")).map((f3) => {
27737
27898
  const fp = join17(rendersDir, f3);
27738
27899
  const stat3 = statSync3(fp);
@@ -27740,9 +27901,9 @@ function registerRenderRoutes(api, adapter2) {
27740
27901
  const metaPath = join17(rendersDir, `${rid}.meta.json`);
27741
27902
  let status = "complete";
27742
27903
  let durationMs;
27743
- if (existsSync13(metaPath)) {
27904
+ if (existsSync14(metaPath)) {
27744
27905
  try {
27745
- const meta = JSON.parse(readFileSync15(metaPath, "utf-8"));
27906
+ const meta = JSON.parse(readFileSync17(metaPath, "utf-8"));
27746
27907
  if (meta.status === "failed") status = "failed";
27747
27908
  if (meta.durationMs) durationMs = meta.durationMs;
27748
27909
  } catch {
@@ -28365,7 +28526,7 @@ var init_manualEditsRenderScript = __esm({
28365
28526
  });
28366
28527
 
28367
28528
  // ../core/src/studio-api/routes/thumbnail.ts
28368
- import { existsSync as existsSync14, readFileSync as readFileSync16, writeFileSync as writeFileSync9, mkdirSync as mkdirSync8, statSync as statSync4 } from "fs";
28529
+ import { existsSync as existsSync15, readFileSync as readFileSync18, writeFileSync as writeFileSync9, mkdirSync as mkdirSync8, statSync as statSync4 } from "fs";
28369
28530
  import { join as join18 } from "path";
28370
28531
  import { createHash as createHash2 } from "crypto";
28371
28532
  function registerThumbnailRoutes(api, adapter2) {
@@ -28396,9 +28557,9 @@ function registerThumbnailRoutes(api, adapter2) {
28396
28557
  let sourceMtime = 0;
28397
28558
  if (!vpWidth) {
28398
28559
  const htmlFile = join18(project.dir, compPath);
28399
- if (existsSync14(htmlFile)) {
28560
+ if (existsSync15(htmlFile)) {
28400
28561
  sourceMtime = Math.round(statSync4(htmlFile).mtimeMs);
28401
- const html = readFileSync16(htmlFile, "utf-8");
28562
+ const html = readFileSync18(htmlFile, "utf-8");
28402
28563
  const wMatch = html.match(/data-width=["'](\d+)["']/);
28403
28564
  const hMatch = html.match(/data-height=["'](\d+)["']/);
28404
28565
  if (wMatch?.[1]) compW = parseInt(wMatch[1]);
@@ -28407,15 +28568,15 @@ function registerThumbnailRoutes(api, adapter2) {
28407
28568
  }
28408
28569
  const manualEditsFile = join18(project.dir, STUDIO_MANUAL_EDITS_PATH);
28409
28570
  let manualEditsKey = "";
28410
- if (existsSync14(manualEditsFile)) {
28411
- const manualEditsContent = readFileSync16(manualEditsFile, "utf-8");
28571
+ if (existsSync15(manualEditsFile)) {
28572
+ const manualEditsContent = readFileSync18(manualEditsFile, "utf-8");
28412
28573
  manualEditsKey = `_${createHash2("sha1").update(manualEditsContent).digest("hex").slice(0, 16)}`;
28413
28574
  sourceMtime = Math.max(sourceMtime, Math.round(statSync4(manualEditsFile).mtimeMs));
28414
28575
  }
28415
28576
  const motionFile = join18(project.dir, STUDIO_MOTION_PATH);
28416
28577
  let motionKey = "";
28417
- if (existsSync14(motionFile)) {
28418
- const motionContent = readFileSync16(motionFile, "utf-8");
28578
+ if (existsSync15(motionFile)) {
28579
+ const motionContent = readFileSync18(motionFile, "utf-8");
28419
28580
  motionKey = `_${createHash2("sha1").update(motionContent).digest("hex").slice(0, 16)}`;
28420
28581
  sourceMtime = Math.max(sourceMtime, Math.round(statSync4(motionFile).mtimeMs));
28421
28582
  }
@@ -28425,8 +28586,8 @@ function registerThumbnailRoutes(api, adapter2) {
28425
28586
  const urlVersionKey = urlVersion ? `_${urlVersion.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32)}` : "";
28426
28587
  const cacheKey = `${THUMBNAIL_CACHE_VERSION}${urlVersionKey}${manualEditsKey}${motionKey}_${format}_${compPath.replace(/\//g, "_")}_${compW}x${compH}_${sourceMtime}_${seekTime.toFixed(2)}${selectorKey}.${format === "png" ? "png" : "jpg"}`;
28427
28588
  const cachePath2 = join18(cacheDir, cacheKey);
28428
- if (existsSync14(cachePath2)) {
28429
- return new Response(new Uint8Array(readFileSync16(cachePath2)), {
28589
+ if (existsSync15(cachePath2)) {
28590
+ return new Response(new Uint8Array(readFileSync18(cachePath2)), {
28430
28591
  headers: { "Content-Type": contentType, "Cache-Control": "public, max-age=60" }
28431
28592
  });
28432
28593
  }
@@ -28448,7 +28609,7 @@ function registerThumbnailRoutes(api, adapter2) {
28448
28609
  500
28449
28610
  );
28450
28611
  }
28451
- if (!existsSync14(cacheDir)) mkdirSync8(cacheDir, { recursive: true });
28612
+ if (!existsSync15(cacheDir)) mkdirSync8(cacheDir, { recursive: true });
28452
28613
  writeFileSync9(cachePath2, buffer);
28453
28614
  return new Response(new Uint8Array(buffer), {
28454
28615
  headers: { "Content-Type": contentType, "Cache-Control": "public, max-age=60" }
@@ -28470,7 +28631,7 @@ var init_thumbnail = __esm({
28470
28631
  });
28471
28632
 
28472
28633
  // ../core/src/studio-api/routes/waveform.ts
28473
- import { existsSync as existsSync15, readFileSync as readFileSync17, writeFileSync as writeFileSync10, mkdirSync as mkdirSync9 } from "fs";
28634
+ import { existsSync as existsSync16, readFileSync as readFileSync19, writeFileSync as writeFileSync10, mkdirSync as mkdirSync9 } from "fs";
28474
28635
  import { join as join19 } from "path";
28475
28636
  function registerWaveformRoutes(api, adapter2) {
28476
28637
  api.get("/projects/:id/waveform/*", async (c3) => {
@@ -28480,12 +28641,12 @@ function registerWaveformRoutes(api, adapter2) {
28480
28641
  c3.req.path.replace(`/projects/${project.id}/waveform/`, "").split("?")[0] ?? ""
28481
28642
  );
28482
28643
  const audioPath = join19(project.dir, assetPath);
28483
- if (!existsSync15(audioPath)) return c3.json({ error: "file not found" }, 404);
28644
+ if (!existsSync16(audioPath)) return c3.json({ error: "file not found" }, 404);
28484
28645
  const cacheDir = join19(project.dir, ".waveform-cache");
28485
28646
  const cachePath2 = join19(cacheDir, buildWaveformCacheKey(assetPath));
28486
- if (existsSync15(cachePath2)) {
28647
+ if (existsSync16(cachePath2)) {
28487
28648
  try {
28488
- const peaks2 = JSON.parse(readFileSync17(cachePath2, "utf-8"));
28649
+ const peaks2 = JSON.parse(readFileSync19(cachePath2, "utf-8"));
28489
28650
  return c3.json({ peaks: peaks2 });
28490
28651
  } catch {
28491
28652
  }
@@ -28513,15 +28674,15 @@ var init_waveform2 = __esm({
28513
28674
 
28514
28675
  // ../core/src/studio-api/routes/fonts.ts
28515
28676
  import { execFileSync as execFileSync4 } from "child_process";
28516
- import { existsSync as existsSync16, readdirSync as readdirSync7, statSync as statSync5 } from "fs";
28517
- import { homedir as homedir4, platform as platform3 } from "os";
28677
+ import { existsSync as existsSync17, readdirSync as readdirSync7, statSync as statSync5 } from "fs";
28678
+ import { homedir as homedir4, platform as platform5 } from "os";
28518
28679
  import { join as join20 } from "path";
28519
28680
  function isRecord(value) {
28520
28681
  return typeof value === "object" && value !== null;
28521
28682
  }
28522
28683
  function fontDirectories() {
28523
28684
  const home = homedir4();
28524
- if (platform3() === "darwin") {
28685
+ if (platform5() === "darwin") {
28525
28686
  return [
28526
28687
  join20(home, "Library", "Fonts"),
28527
28688
  "/Library/Fonts",
@@ -28529,7 +28690,7 @@ function fontDirectories() {
28529
28690
  "/System/Library/Fonts/Supplemental"
28530
28691
  ];
28531
28692
  }
28532
- if (platform3() === "win32") {
28693
+ if (platform5() === "win32") {
28533
28694
  return [join20(process.env.WINDIR || "C:\\Windows", "Fonts")];
28534
28695
  }
28535
28696
  return [
@@ -28551,7 +28712,7 @@ function toFamilyName(fileName) {
28551
28712
  return family.length >= 2 ? family : null;
28552
28713
  }
28553
28714
  function collectMacSystemProfilerFonts() {
28554
- if (platform3() !== "darwin") return [];
28715
+ if (platform5() !== "darwin") return [];
28555
28716
  let parsed;
28556
28717
  try {
28557
28718
  const raw = execFileSync4("system_profiler", ["SPFontsDataType", "-json"], {
@@ -28586,7 +28747,7 @@ function collectMacSystemProfilerFonts() {
28586
28747
  return fonts;
28587
28748
  }
28588
28749
  function collectFontsFromDir(dir, depth = 0) {
28589
- if (!existsSync16(dir) || depth > 2) return [];
28750
+ if (!existsSync17(dir) || depth > 2) return [];
28590
28751
  const fonts = [];
28591
28752
  for (const entry of readdirSync7(dir, { withFileTypes: true })) {
28592
28753
  const fullPath = join20(dir, entry.name);
@@ -28858,7 +29019,7 @@ __export(manager_exports2, {
28858
29019
  isLinuxArm: () => isLinuxArm
28859
29020
  });
28860
29021
  import { execSync, spawnSync as spawnSync2 } from "child_process";
28861
- import { existsSync as existsSync17, readdirSync as readdirSync8, rmSync as rmSync4 } from "fs";
29022
+ import { existsSync as existsSync18, readdirSync as readdirSync8, rmSync as rmSync4 } from "fs";
28862
29023
  import { basename as basename2 } from "path";
28863
29024
  import { homedir as homedir5 } from "os";
28864
29025
  import { join as join21 } from "path";
@@ -28879,7 +29040,7 @@ function whichBinary2(name) {
28879
29040
  }
28880
29041
  function findFromEnv2() {
28881
29042
  const envPath = process.env["HYPERFRAMES_BROWSER_PATH"];
28882
- if (envPath && existsSync17(envPath)) {
29043
+ if (envPath && existsSync18(envPath)) {
28883
29044
  return { executablePath: envPath, source: "env" };
28884
29045
  }
28885
29046
  return void 0;
@@ -28889,7 +29050,7 @@ async function findFromCache() {
28889
29050
  if (fromPuppeteer) {
28890
29051
  return fromPuppeteer;
28891
29052
  }
28892
- if (existsSync17(CACHE_DIR2)) {
29053
+ if (existsSync18(CACHE_DIR2)) {
28893
29054
  const installed = await getInstalledBrowsers({ cacheDir: CACHE_DIR2 });
28894
29055
  const match = installed.find((b2) => b2.browser === Browser.CHROMEHEADLESSSHELL);
28895
29056
  if (match) {
@@ -28927,7 +29088,7 @@ function compareVersionDirsDescending(a, b2) {
28927
29088
  return 0;
28928
29089
  }
28929
29090
  function findFromPuppeteerCache() {
28930
- if (!existsSync17(PUPPETEER_CACHE_DIR)) return void 0;
29091
+ if (!existsSync18(PUPPETEER_CACHE_DIR)) return void 0;
28931
29092
  let versions;
28932
29093
  try {
28933
29094
  versions = [...readdirSync8(PUPPETEER_CACHE_DIR)].sort(compareVersionDirsDescending);
@@ -28952,7 +29113,7 @@ function findFromPuppeteerCache() {
28952
29113
  )
28953
29114
  ];
28954
29115
  for (const binary of candidates) {
28955
- if (existsSync17(binary)) {
29116
+ if (existsSync18(binary)) {
28956
29117
  return { executablePath: binary, source: "cache" };
28957
29118
  }
28958
29119
  }
@@ -28979,7 +29140,7 @@ function _resetSystemFallbackWarnForTests() {
28979
29140
  }
28980
29141
  function findFromSystem2() {
28981
29142
  for (const p2 of SYSTEM_CHROME_PATHS) {
28982
- if (existsSync17(p2)) {
29143
+ if (existsSync18(p2)) {
28983
29144
  return { executablePath: p2, source: "system" };
28984
29145
  }
28985
29146
  }
@@ -29004,7 +29165,7 @@ async function ensureLinuxArmBrowser(options) {
29004
29165
  void options;
29005
29166
  const existing = await findBrowser();
29006
29167
  if (existing) return existing;
29007
- const hasApt = existsSync17("/usr/bin/apt-get");
29168
+ const hasApt = existsSync18("/usr/bin/apt-get");
29008
29169
  if (hasApt) {
29009
29170
  console.error(
29010
29171
  "\n\u{1F50D} Linux ARM64 detected \u2014 Chrome Headless Shell is not available for this platform."
@@ -29042,8 +29203,8 @@ Then re-run your command. The HYPERFRAMES_BROWSER_PATH env var persists for the
29042
29203
  async function ensureBrowser(options) {
29043
29204
  const existing = await findBrowser();
29044
29205
  if (existing) return existing;
29045
- const platform7 = detectBrowserPlatform();
29046
- if (!platform7) {
29206
+ const platform9 = detectBrowserPlatform();
29207
+ if (!platform9) {
29047
29208
  throw new Error(`Unsupported platform: ${process.platform} ${process.arch}`);
29048
29209
  }
29049
29210
  if (isLinuxArm()) {
@@ -29053,13 +29214,13 @@ async function ensureBrowser(options) {
29053
29214
  cacheDir: CACHE_DIR2,
29054
29215
  browser: Browser.CHROMEHEADLESSSHELL,
29055
29216
  buildId: CHROME_VERSION,
29056
- platform: platform7,
29217
+ platform: platform9,
29057
29218
  downloadProgressCallback: options?.onProgress
29058
29219
  });
29059
29220
  return { executablePath: installed.executablePath, source: "download" };
29060
29221
  }
29061
29222
  function clearBrowser() {
29062
- if (!existsSync17(CACHE_DIR2)) {
29223
+ if (!existsSync18(CACHE_DIR2)) {
29063
29224
  return false;
29064
29225
  }
29065
29226
  rmSync4(CACHE_DIR2, { recursive: true, force: true });
@@ -29230,7 +29391,7 @@ var init_config2 = __esm({
29230
29391
  });
29231
29392
 
29232
29393
  // ../engine/src/services/browserManager.ts
29233
- import { existsSync as existsSync18, readdirSync as readdirSync9 } from "fs";
29394
+ import { existsSync as existsSync19, readdirSync as readdirSync9 } from "fs";
29234
29395
  import { join as join22 } from "path";
29235
29396
  import { homedir as homedir6 } from "os";
29236
29397
  async function getPuppeteer() {
@@ -29253,7 +29414,7 @@ function resolveHeadlessShellPath(config) {
29253
29414
  return process.env.PRODUCER_HEADLESS_SHELL_PATH;
29254
29415
  }
29255
29416
  const baseDir = join22(homedir6(), ".cache", "puppeteer", "chrome-headless-shell");
29256
- if (!existsSync18(baseDir)) return void 0;
29417
+ if (!existsSync19(baseDir)) return void 0;
29257
29418
  try {
29258
29419
  const versions = readdirSync9(baseDir).sort().reverse();
29259
29420
  for (const version of versions) {
@@ -29264,7 +29425,7 @@ function resolveHeadlessShellPath(config) {
29264
29425
  join22(baseDir, version, "chrome-headless-shell-win64", "chrome-headless-shell.exe")
29265
29426
  ];
29266
29427
  for (const binary of candidates) {
29267
- if (existsSync18(binary)) return binary;
29428
+ if (existsSync19(binary)) return binary;
29268
29429
  }
29269
29430
  }
29270
29431
  } catch {
@@ -29303,7 +29464,7 @@ function resolveBrowserGpuMode(mode, options = {}) {
29303
29464
  if (mode !== "auto") return Promise.resolve(mode);
29304
29465
  if (_autoBrowserGpuModeCache) return _autoBrowserGpuModeCache;
29305
29466
  _autoBrowserGpuModeCache = (async () => {
29306
- const platform7 = options.platform ?? process.platform;
29467
+ const platform9 = options.platform ?? process.platform;
29307
29468
  const browserTimeout = options.browserTimeout ?? DEFAULT_CONFIG2.browserTimeout;
29308
29469
  const executablePath = options.chromePath ?? resolveHeadlessShellPath({});
29309
29470
  const probeArgs = [
@@ -29312,7 +29473,7 @@ function resolveBrowserGpuMode(mode, options = {}) {
29312
29473
  "--disable-dev-shm-usage",
29313
29474
  "--enable-webgl",
29314
29475
  "--ignore-gpu-blocklist",
29315
- ...getBrowserGpuArgs("hardware", platform7)
29476
+ ...getBrowserGpuArgs("hardware", platform9)
29316
29477
  ];
29317
29478
  const ppt = await getPuppeteer().catch(() => null);
29318
29479
  if (!ppt) {
@@ -29505,7 +29666,7 @@ async function drainBrowserPool() {
29505
29666
  }
29506
29667
  }
29507
29668
  function buildChromeArgs(options, config) {
29508
- const platform7 = options.platform ?? process.platform;
29669
+ const platform9 = options.platform ?? process.platform;
29509
29670
  const gpuDisabled = config?.disableGpu ?? DEFAULT_CONFIG2.disableGpu;
29510
29671
  const browserGpuMode = gpuDisabled ? "software" : config?.browserGpuMode ?? DEFAULT_CONFIG2.browserGpuMode;
29511
29672
  const chromeArgs = [
@@ -29515,7 +29676,7 @@ function buildChromeArgs(options, config) {
29515
29676
  CANVAS_DRAW_ELEMENT_FEATURE_FLAG,
29516
29677
  "--enable-webgl",
29517
29678
  "--ignore-gpu-blocklist",
29518
- ...getBrowserGpuArgs(browserGpuMode, platform7),
29679
+ ...getBrowserGpuArgs(browserGpuMode, platform9),
29519
29680
  "--font-render-hinting=none",
29520
29681
  "--force-color-profile=srgb",
29521
29682
  `--window-size=${options.width},${options.height}`,
@@ -29563,14 +29724,14 @@ function buildChromeArgs(options, config) {
29563
29724
  }
29564
29725
  return chromeArgs;
29565
29726
  }
29566
- function getBrowserGpuArgs(mode, platform7) {
29727
+ function getBrowserGpuArgs(mode, platform9) {
29567
29728
  if (mode === "software") {
29568
29729
  return ["--use-gl=angle", "--use-angle=swiftshader", "--enable-unsafe-swiftshader"];
29569
29730
  }
29570
29731
  if (mode === "auto") {
29571
29732
  return ["--use-gl=angle", "--use-angle=swiftshader", "--enable-unsafe-swiftshader"];
29572
29733
  }
29573
- switch (platform7) {
29734
+ switch (platform9) {
29574
29735
  case "darwin":
29575
29736
  return ["--use-gl=angle", "--use-angle=metal", "--enable-gpu-rasterization"];
29576
29737
  case "win32":
@@ -29893,7 +30054,7 @@ var init_screenshotService = __esm({
29893
30054
  });
29894
30055
 
29895
30056
  // ../engine/src/services/frameCapture.ts
29896
- import { existsSync as existsSync19, mkdirSync as mkdirSync10, writeFileSync as writeFileSync11 } from "fs";
30057
+ import { existsSync as existsSync20, mkdirSync as mkdirSync10, writeFileSync as writeFileSync11 } from "fs";
29897
30058
  import { join as join23 } from "path";
29898
30059
  async function driveWarmupTicks(options, state) {
29899
30060
  const sleep3 = options.sleep ?? realSleep;
@@ -29930,7 +30091,7 @@ async function waitForCloseWithTimeout(promise) {
29930
30091
  return !timedOut;
29931
30092
  }
29932
30093
  async function createCaptureSession(serverUrl, outputDir, options, onBeforeCapture = null, config) {
29933
- if (!existsSync19(outputDir)) mkdirSync10(outputDir, { recursive: true });
30094
+ if (!existsSync20(outputDir)) mkdirSync10(outputDir, { recursive: true });
29934
30095
  const headlessShell = resolveHeadlessShellPath(config);
29935
30096
  const isLinux = process.platform === "linux";
29936
30097
  const forceScreenshot = config?.forceScreenshot ?? DEFAULT_CONFIG2.forceScreenshot;
@@ -30276,7 +30437,7 @@ async function initializeSession(session) {
30276
30437
  async function captureFrameErrorDiagnostics(session, frameIndex, time, error) {
30277
30438
  try {
30278
30439
  const diagnosticsDir = join23(session.outputDir, "diagnostics");
30279
- if (!existsSync19(diagnosticsDir)) mkdirSync10(diagnosticsDir, { recursive: true });
30440
+ if (!existsSync20(diagnosticsDir)) mkdirSync10(diagnosticsDir, { recursive: true });
30280
30441
  const base = join23(diagnosticsDir, `frame-error-${frameIndex}`);
30281
30442
  await session.page.screenshot({ path: `${base}.png`, type: "png", fullPage: true });
30282
30443
  const html = await session.page.content();
@@ -30439,7 +30600,7 @@ async function closeCaptureSession(session) {
30439
30600
  session.isInitialized = false;
30440
30601
  }
30441
30602
  function prepareCaptureSessionForReuse(session, outputDir, onBeforeCapture) {
30442
- if (!existsSync19(outputDir)) {
30603
+ if (!existsSync20(outputDir)) {
30443
30604
  mkdirSync10(outputDir, { recursive: true });
30444
30605
  }
30445
30606
  session.outputDir = outputDir;
@@ -30680,7 +30841,7 @@ var init_runFfmpeg = __esm({
30680
30841
 
30681
30842
  // ../engine/src/services/chunkEncoder.ts
30682
30843
  import { spawn as spawn6 } from "child_process";
30683
- import { copyFileSync, existsSync as existsSync20, mkdirSync as mkdirSync11, readdirSync as readdirSync10, statSync as statSync6, writeFileSync as writeFileSync12 } from "fs";
30844
+ import { copyFileSync, existsSync as existsSync21, mkdirSync as mkdirSync11, readdirSync as readdirSync10, statSync as statSync6, writeFileSync as writeFileSync12 } from "fs";
30684
30845
  import { join as join24, dirname as dirname7 } from "path";
30685
30846
  function getEncoderPreset(quality, format = "mp4", hdr) {
30686
30847
  const base = ENCODER_PRESETS[quality];
@@ -30892,7 +31053,7 @@ function buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder = null) {
30892
31053
  async function encodeFramesFromDir(framesDir, framePattern, outputPath, options, signal, config) {
30893
31054
  const startTime = Date.now();
30894
31055
  const outputDir = dirname7(outputPath);
30895
- if (!existsSync20(outputDir)) mkdirSync11(outputDir, { recursive: true });
31056
+ if (!existsSync21(outputDir)) mkdirSync11(outputDir, { recursive: true });
30896
31057
  const files = readdirSync10(framesDir).filter((f3) => f3.match(/\.(jpg|jpeg|png)$/i));
30897
31058
  const frameCount = files.length;
30898
31059
  if (frameCount === 0) {
@@ -30958,7 +31119,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
30958
31119
  });
30959
31120
  return;
30960
31121
  }
30961
- const fileSize = existsSync20(outputPath) ? statSync6(outputPath).size : 0;
31122
+ const fileSize = existsSync21(outputPath) ? statSync6(outputPath).size : 0;
30962
31123
  resolve46({ success: true, outputPath, durationMs, framesEncoded: frameCount, fileSize });
30963
31124
  });
30964
31125
  ffmpeg.on("error", (err) => {
@@ -30991,7 +31152,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
30991
31152
  const chunkSize = Math.max(30, Math.floor(chunkSizeFrames));
30992
31153
  const chunkCount = Math.ceil(files.length / chunkSize);
30993
31154
  const chunkDir = join24(dirname7(outputPath), "chunk-encode");
30994
- if (!existsSync20(chunkDir)) mkdirSync11(chunkDir, { recursive: true });
31155
+ if (!existsSync21(chunkDir)) mkdirSync11(chunkDir, { recursive: true });
30995
31156
  const chunkPaths = [];
30996
31157
  for (let i2 = 0; i2 < chunkCount; i2++) {
30997
31158
  if (signal?.aborted) {
@@ -31087,7 +31248,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
31087
31248
  error: concatResult.error
31088
31249
  };
31089
31250
  }
31090
- const fileSize = existsSync20(outputPath) ? statSync6(outputPath).size : 0;
31251
+ const fileSize = existsSync21(outputPath) ? statSync6(outputPath).size : 0;
31091
31252
  return {
31092
31253
  success: true,
31093
31254
  outputPath,
@@ -31098,7 +31259,7 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
31098
31259
  }
31099
31260
  async function muxVideoWithAudio(videoPath, audioPath, outputPath, signal, config) {
31100
31261
  const outputDir = dirname7(outputPath);
31101
- if (!existsSync20(outputDir)) mkdirSync11(outputDir, { recursive: true });
31262
+ if (!existsSync21(outputDir)) mkdirSync11(outputDir, { recursive: true });
31102
31263
  const isWebm = outputPath.endsWith(".webm");
31103
31264
  const isMov = outputPath.endsWith(".mov");
31104
31265
  const args = ["-i", videoPath, "-i", audioPath, "-c:v", "copy"];
@@ -31171,7 +31332,7 @@ var init_chunkEncoder = __esm({
31171
31332
 
31172
31333
  // ../engine/src/services/streamingEncoder.ts
31173
31334
  import { spawn as spawn7 } from "child_process";
31174
- import { existsSync as existsSync21, mkdirSync as mkdirSync12, statSync as statSync7 } from "fs";
31335
+ import { existsSync as existsSync22, mkdirSync as mkdirSync12, statSync as statSync7 } from "fs";
31175
31336
  import { dirname as dirname8 } from "path";
31176
31337
  function createFrameReorderBuffer(startFrame, endFrame) {
31177
31338
  let cursor = startFrame;
@@ -31373,7 +31534,7 @@ function buildStreamingArgs(options, outputPath, gpuEncoder = null) {
31373
31534
  }
31374
31535
  async function spawnStreamingEncoder(outputPath, options, signal, config) {
31375
31536
  const outputDir = dirname8(outputPath);
31376
- if (!existsSync21(outputDir)) mkdirSync12(outputDir, { recursive: true });
31537
+ if (!existsSync22(outputDir)) mkdirSync12(outputDir, { recursive: true });
31377
31538
  let gpuEncoder = null;
31378
31539
  if (options.useGpu) {
31379
31540
  gpuEncoder = await getCachedGpuEncoder();
@@ -31469,7 +31630,7 @@ Process error: ${err.message}`;
31469
31630
  error: formatFfmpegError(exitCode, stderr)
31470
31631
  };
31471
31632
  }
31472
- const fileSize = existsSync21(outputPath) ? statSync7(outputPath).size : 0;
31633
+ const fileSize = existsSync22(outputPath) ? statSync7(outputPath).size : 0;
31473
31634
  return { success: true, durationMs, fileSize };
31474
31635
  },
31475
31636
  getExitStatus: () => exitStatus
@@ -31489,7 +31650,7 @@ var init_streamingEncoder = __esm({
31489
31650
 
31490
31651
  // ../engine/src/utils/ffprobe.ts
31491
31652
  import { spawn as spawn8 } from "child_process";
31492
- import { readFileSync as readFileSync18 } from "fs";
31653
+ import { readFileSync as readFileSync20 } from "fs";
31493
31654
  import { extname as extname5 } from "path";
31494
31655
  function runFfprobe(args) {
31495
31656
  return new Promise((resolve46, reject) => {
@@ -31583,7 +31744,7 @@ function extractPngMetadataFromBuffer(buf) {
31583
31744
  function extractStillImageMetadata(filePath) {
31584
31745
  if (extname5(filePath).toLowerCase() !== ".png") return null;
31585
31746
  try {
31586
- return extractPngMetadataFromBuffer(readFileSync18(filePath));
31747
+ return extractPngMetadataFromBuffer(readFileSync20(filePath));
31587
31748
  } catch {
31588
31749
  return null;
31589
31750
  }
@@ -31770,7 +31931,7 @@ var init_ffprobe = __esm({
31770
31931
  });
31771
31932
 
31772
31933
  // ../engine/src/utils/urlDownloader.ts
31773
- import { createWriteStream as createWriteStream2, existsSync as existsSync22, mkdirSync as mkdirSync13 } from "fs";
31934
+ import { createWriteStream as createWriteStream2, existsSync as existsSync23, mkdirSync as mkdirSync13 } from "fs";
31774
31935
  import { createHash as createHash3 } from "crypto";
31775
31936
  import { join as join25, extname as extname6 } from "path";
31776
31937
  import { Readable } from "stream";
@@ -31783,19 +31944,19 @@ function getFilenameFromUrl(url) {
31783
31944
  }
31784
31945
  async function downloadToTemp(url, destDir, timeoutMs = 3e5) {
31785
31946
  const cachedPath = downloadPathCache.get(url);
31786
- if (cachedPath && existsSync22(cachedPath)) {
31947
+ if (cachedPath && existsSync23(cachedPath)) {
31787
31948
  return cachedPath;
31788
31949
  }
31789
31950
  const inFlight = inFlightDownloads.get(url);
31790
31951
  if (inFlight) {
31791
31952
  return inFlight;
31792
31953
  }
31793
- if (!existsSync22(destDir)) {
31954
+ if (!existsSync23(destDir)) {
31794
31955
  mkdirSync13(destDir, { recursive: true });
31795
31956
  }
31796
31957
  const filename = getFilenameFromUrl(url);
31797
31958
  const localPath = join25(destDir, filename);
31798
- if (existsSync22(localPath)) {
31959
+ if (existsSync23(localPath)) {
31799
31960
  downloadPathCache.set(url, localPath);
31800
31961
  return localPath;
31801
31962
  }
@@ -32551,7 +32712,7 @@ var init_inlineSubCompositions = __esm({
32551
32712
  });
32552
32713
 
32553
32714
  // ../core/src/compiler/htmlBundler.ts
32554
- import { readFileSync as readFileSync19, existsSync as existsSync23 } from "fs";
32715
+ import { readFileSync as readFileSync21, existsSync as existsSync24 } from "fs";
32555
32716
  import { join as join26, resolve as resolve14, relative as relative3, dirname as dirname9, isAbsolute as isAbsolute3, sep as sep3 } from "path";
32556
32717
  import { transformSync } from "esbuild";
32557
32718
  function safePath(projectDir, relativePath) {
@@ -32599,9 +32760,9 @@ function isRelativeUrl(url) {
32599
32760
  return !url.startsWith("http://") && !url.startsWith("https://") && !url.startsWith("//") && !url.startsWith("data:") && !isAbsolute3(url);
32600
32761
  }
32601
32762
  function safeReadFile(filePath) {
32602
- if (!existsSync23(filePath)) return null;
32763
+ if (!existsSync24(filePath)) return null;
32603
32764
  try {
32604
- return readFileSync19(filePath, "utf-8");
32765
+ return readFileSync21(filePath, "utf-8");
32605
32766
  } catch {
32606
32767
  return null;
32607
32768
  }
@@ -32671,9 +32832,9 @@ ${inlined}
32671
32832
  return rebased;
32672
32833
  }
32673
32834
  function safeReadFileBuffer(filePath) {
32674
- if (!existsSync23(filePath)) return null;
32835
+ if (!existsSync24(filePath)) return null;
32675
32836
  try {
32676
- return readFileSync19(filePath);
32837
+ return readFileSync21(filePath);
32677
32838
  } catch {
32678
32839
  return null;
32679
32840
  }
@@ -32975,8 +33136,8 @@ function stripJsCommentsParserSafe(source) {
32975
33136
  }
32976
33137
  async function bundleToSingleHtml(projectDir, options) {
32977
33138
  const indexPath = join26(projectDir, "index.html");
32978
- if (!existsSync23(indexPath)) throw new Error("index.html not found in project directory");
32979
- const rawHtml = readFileSync19(indexPath, "utf-8");
33139
+ if (!existsSync24(indexPath)) throw new Error("index.html not found in project directory");
33140
+ const rawHtml = readFileSync21(indexPath, "utf-8");
32980
33141
  const compiled = await compileHtml(rawHtml, projectDir, options?.probeMediaDuration);
32981
33142
  const staticGuard = validateHyperframeHtmlContract(compiled);
32982
33143
  if (!staticGuard.isValid) {
@@ -33329,7 +33490,7 @@ var init_htmlTemplate = __esm({
33329
33490
  // ../engine/src/services/extractionCache.ts
33330
33491
  import { createHash as createHash4 } from "crypto";
33331
33492
  import { mkdirSync as mkdirSync14, readdirSync as readdirSync11, statSync as statSync8, writeFileSync as writeFileSync13 } from "fs";
33332
- import { existsSync as existsSync24 } from "fs";
33493
+ import { existsSync as existsSync25 } from "fs";
33333
33494
  import { join as join27 } from "path";
33334
33495
  function readKeyStat(videoPath) {
33335
33496
  try {
@@ -33360,7 +33521,7 @@ function cacheEntryDirName(keyHash) {
33360
33521
  function lookupCacheEntry(rootDir, input) {
33361
33522
  const keyHash = computeCacheKey(input);
33362
33523
  const dir = join27(rootDir, cacheEntryDirName(keyHash));
33363
- const complete = existsSync24(join27(dir, COMPLETE_SENTINEL));
33524
+ const complete = existsSync25(join27(dir, COMPLETE_SENTINEL));
33364
33525
  return { entry: { dir, keyHash }, hit: complete };
33365
33526
  }
33366
33527
  function ensureCacheEntryDir(entry) {
@@ -33401,7 +33562,7 @@ var init_extractionCache = __esm({
33401
33562
 
33402
33563
  // ../engine/src/services/videoFrameExtractor.ts
33403
33564
  import { spawn as spawn9 } from "child_process";
33404
- import { existsSync as existsSync25, mkdirSync as mkdirSync15, readdirSync as readdirSync12, rmSync as rmSync5 } from "fs";
33565
+ import { existsSync as existsSync26, mkdirSync as mkdirSync15, readdirSync as readdirSync12, rmSync as rmSync5 } from "fs";
33405
33566
  import { isAbsolute as isAbsolute4, join as join28, posix as posix2, resolve as resolve15, sep as sep4 } from "path";
33406
33567
  function parseVideoElements(html) {
33407
33568
  const videos = [];
@@ -33473,7 +33634,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
33473
33634
  const ffmpegProcessTimeout = config?.ffmpegProcessTimeout ?? DEFAULT_CONFIG2.ffmpegProcessTimeout;
33474
33635
  const { fps, outputDir, quality = 95 } = options;
33475
33636
  const videoOutputDir = outputDirOverride ?? join28(outputDir, videoId);
33476
- if (!existsSync25(videoOutputDir)) mkdirSync15(videoOutputDir, { recursive: true });
33637
+ if (!existsSync26(videoOutputDir)) mkdirSync15(videoOutputDir, { recursive: true });
33477
33638
  const metadata = await extractMediaMetadata(videoPath);
33478
33639
  const format = resolveFrameFormat(metadata, options.format);
33479
33640
  const framePattern = `${FRAME_FILENAME_PREFIX}%05d.${format}`;
@@ -33661,7 +33822,7 @@ function resolveProjectRelativeSrc(src, baseDir, compiledDir) {
33661
33822
  candidates.push(join28(baseDir, stripped));
33662
33823
  }
33663
33824
  }
33664
- return candidates.find(existsSync25) ?? fromBase;
33825
+ return candidates.find(existsSync26) ?? fromBase;
33665
33826
  }
33666
33827
  async function extractAllVideoFrames(videos, baseDir, options, signal, config, compiledDir) {
33667
33828
  const startTime = Date.now();
@@ -33695,7 +33856,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
33695
33856
  mkdirSync15(downloadDir, { recursive: true });
33696
33857
  videoPath = await downloadToTemp(videoPath, downloadDir);
33697
33858
  }
33698
- if (!existsSync25(videoPath)) {
33859
+ if (!existsSync26(videoPath)) {
33699
33860
  if (!warnedSrcs.has(video.src)) {
33700
33861
  warnedSrcs.add(video.src);
33701
33862
  process.stderr.write(
@@ -34064,7 +34225,7 @@ var init_videoFrameExtractor = __esm({
34064
34225
  cleanup() {
34065
34226
  for (const video of this.videos.values()) {
34066
34227
  if (video.extracted.ownedByLookup) continue;
34067
- if (existsSync25(video.extracted.outputDir)) {
34228
+ if (existsSync26(video.extracted.outputDir)) {
34068
34229
  rmSync5(video.extracted.outputDir, { recursive: true, force: true });
34069
34230
  }
34070
34231
  }
@@ -34468,7 +34629,7 @@ var init_videoFrameInjector = __esm({
34468
34629
  });
34469
34630
 
34470
34631
  // ../engine/src/services/audioMixer.ts
34471
- import { existsSync as existsSync26, mkdirSync as mkdirSync16, rmSync as rmSync6 } from "fs";
34632
+ import { existsSync as existsSync27, mkdirSync as mkdirSync16, rmSync as rmSync6 } from "fs";
34472
34633
  import { isAbsolute as isAbsolute5, join as join29, dirname as dirname10 } from "path";
34473
34634
  function parseAudioElements(html) {
34474
34635
  const elements = [];
@@ -34520,7 +34681,7 @@ function parseAudioElements(html) {
34520
34681
  async function extractAudioFromVideo(videoPath, outputPath, options, signal, config) {
34521
34682
  const ffmpegProcessTimeout = config?.ffmpegProcessTimeout ?? DEFAULT_CONFIG2.ffmpegProcessTimeout;
34522
34683
  const outputDir = dirname10(outputPath);
34523
- if (!existsSync26(outputDir)) mkdirSync16(outputDir, { recursive: true });
34684
+ if (!existsSync27(outputDir)) mkdirSync16(outputDir, { recursive: true });
34524
34685
  const args = ["-i", videoPath];
34525
34686
  if (options?.startTime !== void 0) args.push("-ss", String(options.startTime));
34526
34687
  if (options?.duration !== void 0) args.push("-t", String(options.duration));
@@ -34547,7 +34708,7 @@ async function extractAudioFromVideo(videoPath, outputPath, options, signal, con
34547
34708
  async function prepareAudioTrack(srcPath, outputPath, mediaStart, duration, signal, config) {
34548
34709
  const ffmpegProcessTimeout = config?.ffmpegProcessTimeout ?? DEFAULT_CONFIG2.ffmpegProcessTimeout;
34549
34710
  const outputDir = dirname10(outputPath);
34550
- if (!existsSync26(outputDir)) mkdirSync16(outputDir, { recursive: true });
34711
+ if (!existsSync27(outputDir)) mkdirSync16(outputDir, { recursive: true });
34551
34712
  const args = [
34552
34713
  "-ss",
34553
34714
  String(mediaStart),
@@ -34583,7 +34744,7 @@ async function prepareAudioTrack(srcPath, outputPath, mediaStart, duration, sign
34583
34744
  async function generateSilence(outputPath, duration, signal, config) {
34584
34745
  const ffmpegProcessTimeout = config?.ffmpegProcessTimeout ?? DEFAULT_CONFIG2.ffmpegProcessTimeout;
34585
34746
  const outputDir = dirname10(outputPath);
34586
- if (!existsSync26(outputDir)) mkdirSync16(outputDir, { recursive: true });
34747
+ if (!existsSync27(outputDir)) mkdirSync16(outputDir, { recursive: true });
34587
34748
  const args = [
34588
34749
  "-f",
34589
34750
  "lavfi",
@@ -34626,7 +34787,7 @@ async function mixAudioTracks(tracks, outputPath, totalDuration, signal, config)
34626
34787
  };
34627
34788
  }
34628
34789
  const outputDir = dirname10(outputPath);
34629
- if (!existsSync26(outputDir)) mkdirSync16(outputDir, { recursive: true });
34790
+ if (!existsSync27(outputDir)) mkdirSync16(outputDir, { recursive: true });
34630
34791
  const inputs = [];
34631
34792
  const filterParts = [];
34632
34793
  tracks.forEach((track, i2) => {
@@ -34687,7 +34848,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
34687
34848
  const startMs = Date.now();
34688
34849
  const tracks = [];
34689
34850
  const errors = [];
34690
- if (!existsSync26(workDir)) mkdirSync16(workDir, { recursive: true });
34851
+ if (!existsSync27(workDir)) mkdirSync16(workDir, { recursive: true });
34691
34852
  await Promise.all(
34692
34853
  elements.map(async (element) => {
34693
34854
  if (signal?.aborted) {
@@ -34709,7 +34870,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
34709
34870
  return;
34710
34871
  }
34711
34872
  }
34712
- if (!existsSync26(srcPath)) {
34873
+ if (!existsSync27(srcPath)) {
34713
34874
  errors.push(`Source not found: ${element.id} (${element.src})`);
34714
34875
  return;
34715
34876
  }
@@ -34873,7 +35034,7 @@ var init_readWebGlVendorInfoFromCanvas = __esm({
34873
35034
 
34874
35035
  // ../engine/src/services/parallelCoordinator.ts
34875
35036
  import { cpus as cpus2, freemem as freemem2, totalmem as totalmem2 } from "os";
34876
- import { existsSync as existsSync27, mkdirSync as mkdirSync17, readdirSync as readdirSync13 } from "fs";
35037
+ import { existsSync as existsSync28, mkdirSync as mkdirSync17, readdirSync as readdirSync13 } from "fs";
34877
35038
  import { copyFile, rename } from "fs/promises";
34878
35039
  import { join as join30 } from "path";
34879
35040
  function defaultSafeMaxWorkers() {
@@ -34940,7 +35101,7 @@ function shouldVerifyWorkerGpu(workerId, config) {
34940
35101
  async function executeWorkerTask(task, serverUrl, captureOptions, createBeforeCaptureHook, signal, onFrameCaptured, onFrameBuffer, config) {
34941
35102
  const startTime = Date.now();
34942
35103
  let framesCaptured = 0;
34943
- if (!existsSync27(task.outputDir)) mkdirSync17(task.outputDir, { recursive: true });
35104
+ if (!existsSync28(task.outputDir)) mkdirSync17(task.outputDir, { recursive: true });
34944
35105
  let session = null;
34945
35106
  let perf;
34946
35107
  try {
@@ -35035,11 +35196,11 @@ async function executeParallelCapture(serverUrl, workDir, tasks, captureOptions,
35035
35196
  return results;
35036
35197
  }
35037
35198
  async function mergeWorkerFrames(workDir, tasks, outputDir) {
35038
- if (!existsSync27(outputDir)) mkdirSync17(outputDir, { recursive: true });
35199
+ if (!existsSync28(outputDir)) mkdirSync17(outputDir, { recursive: true });
35039
35200
  let totalFrames = 0;
35040
35201
  const sortedTasks = [...tasks].sort((a, b2) => a.startFrame - b2.startFrame);
35041
35202
  for (const task of sortedTasks) {
35042
- if (!existsSync27(task.outputDir)) {
35203
+ if (!existsSync28(task.outputDir)) {
35043
35204
  continue;
35044
35205
  }
35045
35206
  const files = readdirSync13(task.outputDir).filter((f3) => f3.startsWith("frame_") && (f3.endsWith(".jpg") || f3.endsWith(".png"))).sort();
@@ -35083,7 +35244,7 @@ var init_parallelCoordinator = __esm({
35083
35244
  // ../engine/src/services/fileServer.ts
35084
35245
  import { Hono as Hono2 } from "hono";
35085
35246
  import { serve } from "@hono/node-server";
35086
- import { readFileSync as readFileSync20, existsSync as existsSync28, statSync as statSync9 } from "fs";
35247
+ import { readFileSync as readFileSync22, existsSync as existsSync29, statSync as statSync9 } from "fs";
35087
35248
  import { join as join31, extname as extname7 } from "path";
35088
35249
  function createFileServer(options) {
35089
35250
  const { projectDir, compiledDir, port = 0, stripEmbeddedRuntime = true } = options;
@@ -35096,20 +35257,20 @@ function createFileServer(options) {
35096
35257
  const relativePath = requestPath.replace(/^\//, "");
35097
35258
  const compiledPath = compiledDir ? join31(compiledDir, relativePath) : null;
35098
35259
  const hasCompiledFile = Boolean(
35099
- compiledPath && existsSync28(compiledPath) && statSync9(compiledPath).isFile()
35260
+ compiledPath && existsSync29(compiledPath) && statSync9(compiledPath).isFile()
35100
35261
  );
35101
35262
  const filePath = hasCompiledFile ? compiledPath : join31(projectDir, relativePath);
35102
- if (!existsSync28(filePath) || !statSync9(filePath).isFile()) {
35263
+ if (!existsSync29(filePath) || !statSync9(filePath).isFile()) {
35103
35264
  return c3.text("Not found", 404);
35104
35265
  }
35105
35266
  const ext = extname7(filePath).toLowerCase();
35106
35267
  const contentType = MIME_TYPES2[ext] || "application/octet-stream";
35107
35268
  if (ext === ".html") {
35108
- const rawHtml = readFileSync20(filePath, "utf-8");
35269
+ const rawHtml = readFileSync22(filePath, "utf-8");
35109
35270
  const html = relativePath === "index.html" ? injectScriptsIntoHtml(rawHtml, headScripts, bodyScripts, stripEmbeddedRuntime) : rawHtml;
35110
35271
  return c3.text(html, 200, { "Content-Type": contentType });
35111
35272
  }
35112
- const content = readFileSync20(filePath);
35273
+ const content = readFileSync22(filePath);
35113
35274
  return new Response(content, {
35114
35275
  status: 200,
35115
35276
  headers: { "Content-Type": contentType }
@@ -36412,7 +36573,7 @@ var init_shaderTransitions = __esm({
36412
36573
  });
36413
36574
 
36414
36575
  // ../engine/src/services/hdrCapture.ts
36415
- import { existsSync as existsSync29, readdirSync as readdirSync14 } from "fs";
36576
+ import { existsSync as existsSync30, readdirSync as readdirSync14 } from "fs";
36416
36577
  import { join as join32 } from "path";
36417
36578
  import { homedir as homedir7 } from "os";
36418
36579
  function linearToPQ(L2) {
@@ -36530,7 +36691,7 @@ function float16ToPqRgb(rawBuffer, bytesPerRow, width, height) {
36530
36691
  }
36531
36692
  function resolveHeadedChromePath() {
36532
36693
  const baseDir = join32(homedir7(), ".cache", "puppeteer", "chrome");
36533
- if (!existsSync29(baseDir)) return void 0;
36694
+ if (!existsSync30(baseDir)) return void 0;
36534
36695
  const versions = readdirSync14(baseDir).sort().reverse();
36535
36696
  for (const version of versions) {
36536
36697
  const candidates = [
@@ -36556,7 +36717,7 @@ function resolveHeadedChromePath() {
36556
36717
  join32(baseDir, version, "chrome-win64", "chrome.exe")
36557
36718
  ];
36558
36719
  for (const binary of candidates) {
36559
- if (existsSync29(binary)) return binary;
36720
+ if (existsSync30(binary)) return binary;
36560
36721
  }
36561
36722
  }
36562
36723
  return void 0;
@@ -36825,7 +36986,7 @@ __export(deterministicFonts_exports, {
36825
36986
  iterateFontFamilyDeclarations: () => iterateFontFamilyDeclarations,
36826
36987
  parseFontFamilyValue: () => parseFontFamilyValue
36827
36988
  });
36828
- import { existsSync as existsSync30, mkdirSync as mkdirSync18, readFileSync as readFileSync21, writeFileSync as writeFileSync14 } from "fs";
36989
+ import { existsSync as existsSync31, mkdirSync as mkdirSync18, readFileSync as readFileSync23, writeFileSync as writeFileSync14 } from "fs";
36829
36990
  import { homedir as homedir8, tmpdir as tmpdir3 } from "os";
36830
36991
  import { join as join33 } from "path";
36831
36992
  function parseFontFamilyValue(value) {
@@ -36954,7 +37115,7 @@ function fontSlug(familyName) {
36954
37115
  }
36955
37116
  function fontCacheDir(slug) {
36956
37117
  const dir = join33(GOOGLE_FONTS_CACHE_DIR, slug);
36957
- if (!existsSync30(dir)) {
37118
+ if (!existsSync31(dir)) {
36958
37119
  mkdirSync18(dir, { recursive: true });
36959
37120
  }
36960
37121
  return dir;
@@ -36998,7 +37159,7 @@ async function fetchGoogleFont(familyName, options) {
36998
37159
  const woff2Url = match[3] || "";
36999
37160
  if (!woff2Url) continue;
37000
37161
  const cachePath2 = cachedWoff2Path(slug, weight, style);
37001
- if (!existsSync30(cachePath2)) {
37162
+ if (!existsSync31(cachePath2)) {
37002
37163
  const woff2What = `Google Fonts woff2 (${weight}/${style})`;
37003
37164
  try {
37004
37165
  const fontRes = await options.fetchImpl(woff2Url);
@@ -37018,7 +37179,7 @@ async function fetchGoogleFont(familyName, options) {
37018
37179
  continue;
37019
37180
  }
37020
37181
  }
37021
- const fontBytes = readFileSync21(cachePath2);
37182
+ const fontBytes = readFileSync23(cachePath2);
37022
37183
  const dataUri = `data:font/woff2;base64,${fontBytes.toString("base64")}`;
37023
37184
  faces.push({ weight, style, dataUri });
37024
37185
  }
@@ -37218,7 +37379,7 @@ var init_deterministicFonts = __esm({
37218
37379
 
37219
37380
  // ../producer/src/services/hyperframeRuntimeLoader.ts
37220
37381
  import { createHash as createHash5 } from "crypto";
37221
- import { existsSync as existsSync31, readFileSync as readFileSync22 } from "fs";
37382
+ import { existsSync as existsSync32, readFileSync as readFileSync24 } from "fs";
37222
37383
  import { dirname as dirname11, resolve as resolve16 } from "path";
37223
37384
  import { fileURLToPath as fileURLToPath2 } from "url";
37224
37385
  function resolveHyperframeManifestPath() {
@@ -37231,7 +37392,7 @@ function resolveHyperframeManifestPath() {
37231
37392
  MODULE_RELATIVE_MANIFEST_PATH
37232
37393
  ];
37233
37394
  for (const candidate of candidates) {
37234
- if (existsSync31(candidate)) {
37395
+ if (existsSync32(candidate)) {
37235
37396
  return candidate;
37236
37397
  }
37237
37398
  }
@@ -37242,12 +37403,12 @@ function getVerifiedHyperframeRuntimeSource() {
37242
37403
  }
37243
37404
  function resolveVerifiedHyperframeRuntime() {
37244
37405
  const manifestPath = resolveHyperframeManifestPath();
37245
- if (!existsSync31(manifestPath)) {
37406
+ if (!existsSync32(manifestPath)) {
37246
37407
  throw new Error(
37247
37408
  `[HyperframeRuntimeLoader] Missing manifest at ${manifestPath}. Build core runtime artifacts before rendering.`
37248
37409
  );
37249
37410
  }
37250
- const manifestRaw = readFileSync22(manifestPath, "utf8");
37411
+ const manifestRaw = readFileSync24(manifestPath, "utf8");
37251
37412
  const manifest = JSON.parse(manifestRaw);
37252
37413
  const runtimeFileName = manifest.artifacts?.iife;
37253
37414
  if (!runtimeFileName || !manifest.sha256) {
@@ -37256,10 +37417,10 @@ function resolveVerifiedHyperframeRuntime() {
37256
37417
  );
37257
37418
  }
37258
37419
  const runtimePath = resolve16(dirname11(manifestPath), runtimeFileName);
37259
- if (!existsSync31(runtimePath)) {
37420
+ if (!existsSync32(runtimePath)) {
37260
37421
  throw new Error(`[HyperframeRuntimeLoader] Missing runtime artifact at ${runtimePath}.`);
37261
37422
  }
37262
- const runtimeSource = readFileSync22(runtimePath, "utf8");
37423
+ const runtimeSource = readFileSync24(runtimePath, "utf8");
37263
37424
  const runtimeSha = createHash5("sha256").update(runtimeSource, "utf8").digest("hex");
37264
37425
  if (runtimeSha !== manifest.sha256) {
37265
37426
  throw new Error(
@@ -37298,7 +37459,7 @@ var init_hyperframeRuntimeLoader = __esm({
37298
37459
  // ../producer/src/services/fileServer.ts
37299
37460
  import { Hono as Hono3 } from "hono";
37300
37461
  import { serve as serve2 } from "@hono/node-server";
37301
- import { readFileSync as readFileSync23, existsSync as existsSync32, realpathSync, statSync as statSync10 } from "fs";
37462
+ import { readFileSync as readFileSync25, existsSync as existsSync33, realpathSync, statSync as statSync10 } from "fs";
37302
37463
  import { join as join34, extname as extname8, resolve as resolve17, sep as sep5 } from "path";
37303
37464
  function isPathInside(child, parent, options = {}) {
37304
37465
  const { resolveSymlinks = false, pathModule } = options;
@@ -37306,8 +37467,8 @@ function isPathInside(child, parent, options = {}) {
37306
37467
  const separator = pathModule?.sep ?? sep5;
37307
37468
  const resolvedChild = resolveFn(child);
37308
37469
  const resolvedParent = resolveFn(parent);
37309
- const normalizedChild = resolveSymlinks && existsSync32(resolvedChild) ? realpathSync.native(resolvedChild) : resolvedChild;
37310
- const normalizedParent = resolveSymlinks && existsSync32(resolvedParent) ? realpathSync.native(resolvedParent) : resolvedParent;
37470
+ const normalizedChild = resolveSymlinks && existsSync33(resolvedChild) ? realpathSync.native(resolvedChild) : resolvedChild;
37471
+ const normalizedParent = resolveSymlinks && existsSync33(resolvedParent) ? realpathSync.native(resolvedParent) : resolvedParent;
37311
37472
  if (normalizedChild === normalizedParent) return true;
37312
37473
  const parentWithSep = normalizedParent.endsWith(separator) ? normalizedParent : normalizedParent + separator;
37313
37474
  return normalizedChild.startsWith(parentWithSep);
@@ -37474,13 +37635,13 @@ function createFileServer2(options) {
37474
37635
  let filePath = null;
37475
37636
  if (compiledDir) {
37476
37637
  const candidate = join34(compiledDir, relativePath);
37477
- if (existsSync32(candidate) && isPathInside(candidate, compiledDir) && statSync10(candidate).isFile()) {
37638
+ if (existsSync33(candidate) && isPathInside(candidate, compiledDir) && statSync10(candidate).isFile()) {
37478
37639
  filePath = candidate;
37479
37640
  }
37480
37641
  }
37481
37642
  if (!filePath) {
37482
37643
  const candidate = join34(projectDir, relativePath);
37483
- if (existsSync32(candidate) && isPathInside(candidate, projectDir) && statSync10(candidate).isFile()) {
37644
+ if (existsSync33(candidate) && isPathInside(candidate, projectDir) && statSync10(candidate).isFile()) {
37484
37645
  filePath = candidate;
37485
37646
  }
37486
37647
  }
@@ -37493,7 +37654,7 @@ function createFileServer2(options) {
37493
37654
  const ext = extname8(filePath).toLowerCase();
37494
37655
  const contentType = MIME_TYPES3[ext] || "application/octet-stream";
37495
37656
  if (ext === ".html") {
37496
- const rawHtml = readFileSync23(filePath, "utf-8");
37657
+ const rawHtml = readFileSync25(filePath, "utf-8");
37497
37658
  const isIndex = relativePath === "index.html";
37498
37659
  let html = rawHtml;
37499
37660
  if (preHeadScripts.length > 0) {
@@ -37502,7 +37663,7 @@ function createFileServer2(options) {
37502
37663
  html = isIndex ? injectScriptsIntoHtml(html, headScripts, bodyScripts, stripEmbeddedRuntime) : html;
37503
37664
  return c3.text(html, 200, { "Content-Type": contentType });
37504
37665
  }
37505
- const content = readFileSync23(filePath);
37666
+ const content = readFileSync25(filePath);
37506
37667
  return new Response(content, {
37507
37668
  status: 200,
37508
37669
  headers: { "Content-Type": contentType }
@@ -37847,7 +38008,7 @@ var init_paths = __esm({
37847
38008
  });
37848
38009
 
37849
38010
  // ../producer/src/services/render/shared.ts
37850
- import { copyFileSync as copyFileSync2, cpSync, existsSync as existsSync33, mkdirSync as mkdirSync19, symlinkSync, writeFileSync as writeFileSync15 } from "fs";
38011
+ import { copyFileSync as copyFileSync2, cpSync, existsSync as existsSync34, mkdirSync as mkdirSync19, symlinkSync, writeFileSync as writeFileSync15 } from "fs";
37851
38012
  import { basename as basename4, dirname as dirname12, isAbsolute as isAbsolute6, join as join36, relative as relative4, resolve as resolve18 } from "path";
37852
38013
  function projectBrowserEndToCompositionTimeline(existingStart, browserStart, browserEnd) {
37853
38014
  return browserEnd + (existingStart - browserStart);
@@ -38034,7 +38195,7 @@ var init_shared = __esm({
38034
38195
  isAbsolute: isAbsolute6
38035
38196
  };
38036
38197
  materializeFileSystem = {
38037
- existsSync: existsSync33,
38198
+ existsSync: existsSync34,
38038
38199
  mkdirSync: mkdirSync19,
38039
38200
  symlinkSync,
38040
38201
  cpSync
@@ -38570,7 +38731,7 @@ var init_urlDownloader2 = __esm({
38570
38731
  });
38571
38732
 
38572
38733
  // ../producer/src/services/htmlCompiler.ts
38573
- import { readFileSync as readFileSync24, existsSync as existsSync34, mkdirSync as mkdirSync20 } from "fs";
38734
+ import { readFileSync as readFileSync26, existsSync as existsSync35, mkdirSync as mkdirSync20 } from "fs";
38574
38735
  import { join as join38, dirname as dirname13, resolve as resolve19 } from "path";
38575
38736
  function dedupeElementsById(elements) {
38576
38737
  const deduped = /* @__PURE__ */ new Map();
@@ -38632,7 +38793,7 @@ function detectShaderTransitionUsage(html) {
38632
38793
  async function resolveMediaDuration(src, mediaStart, baseDir, downloadDir, tagName19) {
38633
38794
  let filePath = src;
38634
38795
  if (isHttpUrl(src)) {
38635
- if (!existsSync34(downloadDir)) mkdirSync20(downloadDir, { recursive: true });
38796
+ if (!existsSync35(downloadDir)) mkdirSync20(downloadDir, { recursive: true });
38636
38797
  try {
38637
38798
  filePath = await downloadToTemp(src, downloadDir);
38638
38799
  } catch {
@@ -38641,7 +38802,7 @@ async function resolveMediaDuration(src, mediaStart, baseDir, downloadDir, tagNa
38641
38802
  } else if (!filePath.startsWith("/")) {
38642
38803
  filePath = join38(baseDir, filePath);
38643
38804
  }
38644
- if (!existsSync34(filePath)) {
38805
+ if (!existsSync35(filePath)) {
38645
38806
  return { duration: 0, resolvedPath: filePath };
38646
38807
  }
38647
38808
  let metadata;
@@ -38719,10 +38880,10 @@ async function parseSubCompositions(html, projectDir, downloadDir, parentOffset
38719
38880
  if (visited.has(filePath)) {
38720
38881
  continue;
38721
38882
  }
38722
- if (!existsSync34(filePath)) {
38883
+ if (!existsSync35(filePath)) {
38723
38884
  continue;
38724
38885
  }
38725
- const rawSubHtml = readFileSync24(filePath, "utf-8");
38886
+ const rawSubHtml = readFileSync26(filePath, "utf-8");
38726
38887
  const nestedVisited = new Set(visited);
38727
38888
  nestedVisited.add(filePath);
38728
38889
  workItems.push({ srcPath, absoluteStart, absoluteEnd, filePath, rawSubHtml, nestedVisited });
@@ -38907,8 +39068,8 @@ function inlineSubCompositions2(html, subCompositions, projectDir) {
38907
39068
  let compHtml = subCompositions.get(srcPath) || null;
38908
39069
  if (!compHtml) {
38909
39070
  const filePath = resolve19(projectDir, srcPath);
38910
- if (existsSync34(filePath)) {
38911
- compHtml = readFileSync24(filePath, "utf-8");
39071
+ if (existsSync35(filePath)) {
39072
+ compHtml = readFileSync26(filePath, "utf-8");
38912
39073
  }
38913
39074
  }
38914
39075
  return compHtml;
@@ -39065,7 +39226,7 @@ function collectExternalAssets(html, projectDir) {
39065
39226
  if (isPathInside2(absPath, absProjectDir)) {
39066
39227
  return null;
39067
39228
  }
39068
- if (!existsSync34(absPath)) return null;
39229
+ if (!existsSync35(absPath)) return null;
39069
39230
  const safeKey = toExternalAssetKey(absPath);
39070
39231
  externalAssets.set(safeKey, absPath);
39071
39232
  return safeKey;
@@ -39115,7 +39276,7 @@ function rewriteUnresolvableGsapToCdn(html, projectDir) {
39115
39276
  (full, prefix, src, file, suffix) => {
39116
39277
  if (/^https?:\/\//i.test(src)) return full;
39117
39278
  const absPath = resolve19(projectDir, src);
39118
- if (existsSync34(absPath)) return full;
39279
+ if (existsSync35(absPath)) return full;
39119
39280
  console.log(
39120
39281
  `[Compiler] Rewriting missing gsap script to CDN: ${src} \u2192 ${GSAP_CDN_BASE}${file}`
39121
39282
  );
@@ -39124,7 +39285,7 @@ function rewriteUnresolvableGsapToCdn(html, projectDir) {
39124
39285
  );
39125
39286
  }
39126
39287
  async function compileForRender(projectDir, htmlPath, downloadDir, options = {}) {
39127
- const rawHtml = rewriteUnresolvableGsapToCdn(readFileSync24(htmlPath, "utf-8"), projectDir);
39288
+ const rawHtml = rewriteUnresolvableGsapToCdn(readFileSync26(htmlPath, "utf-8"), projectDir);
39128
39289
  const { html: compiledHtml, unresolvedCompositions } = await compileHtmlFile(
39129
39290
  rawHtml,
39130
39291
  projectDir,
@@ -39746,7 +39907,7 @@ var init_probeStage = __esm({
39746
39907
  });
39747
39908
 
39748
39909
  // ../producer/src/services/render/stages/extractVideosStage.ts
39749
- import { existsSync as existsSync35 } from "fs";
39910
+ import { existsSync as existsSync36 } from "fs";
39750
39911
  import { isAbsolute as isAbsolute7, join as join41 } from "path";
39751
39912
  async function runExtractVideosStage(input) {
39752
39913
  const {
@@ -39770,7 +39931,7 @@ async function runExtractVideosStage(input) {
39770
39931
  await Promise.all(
39771
39932
  composition.videos.map(async (v2) => {
39772
39933
  const videoPath = isAbsolute7(v2.src) ? v2.src : resolveProjectRelativeSrc(v2.src, projectDir, compiledDir);
39773
- if (!existsSync35(videoPath)) return;
39934
+ if (!existsSync36(videoPath)) return;
39774
39935
  const meta = await extractMediaMetadata(videoPath);
39775
39936
  if (isHdrColorSpace(meta.colorSpace)) {
39776
39937
  nativeHdrVideoIds.add(v2.id);
@@ -39788,10 +39949,10 @@ async function runExtractVideosStage(input) {
39788
39949
  composition.images.map(async (img) => {
39789
39950
  let imgPath = img.src;
39790
39951
  if (!imgPath.startsWith("/")) {
39791
- const fromCompiled = existsSync35(join41(compiledDir, imgPath)) ? join41(compiledDir, imgPath) : join41(projectDir, imgPath);
39952
+ const fromCompiled = existsSync36(join41(compiledDir, imgPath)) ? join41(compiledDir, imgPath) : join41(projectDir, imgPath);
39792
39953
  imgPath = fromCompiled;
39793
39954
  }
39794
- if (!existsSync35(imgPath)) return null;
39955
+ if (!existsSync36(imgPath)) return null;
39795
39956
  const meta = await extractMediaMetadata(imgPath);
39796
39957
  if (isHdrColorSpace(meta.colorSpace)) {
39797
39958
  nativeHdrImageIds.add(img.id);
@@ -40266,7 +40427,7 @@ var init_hdrImageTransferCache = __esm({
40266
40427
  });
40267
40428
 
40268
40429
  // ../producer/src/services/render/stages/captureHdrResources.ts
40269
- import { mkdirSync as mkdirSync21, openSync, readFileSync as readFileSync25, statSync as statSync11 } from "fs";
40430
+ import { mkdirSync as mkdirSync21, openSync, readFileSync as readFileSync27, statSync as statSync11 } from "fs";
40270
40431
  import { join as join43 } from "path";
40271
40432
  function planHdrResources(args) {
40272
40433
  const { composition, nativeHdrVideoIds, nativeHdrImageIds, projectDir, compiledDir } = args;
@@ -40411,7 +40572,7 @@ function decodeHdrImageBuffers(args) {
40411
40572
  const out = /* @__PURE__ */ new Map();
40412
40573
  for (const [imageId, srcPath] of hdrImageSrcPaths) {
40413
40574
  try {
40414
- const decoded = decodePngToRgb48le(readFileSync25(srcPath));
40575
+ const decoded = decodePngToRgb48le(readFileSync27(srcPath));
40415
40576
  const layout2 = prep.hdrExtractionDims.get(imageId);
40416
40577
  const fitInfo = prep.hdrImageFitInfo.get(imageId);
40417
40578
  if (layout2 && (layout2.width !== decoded.width || layout2.height !== decoded.height)) {
@@ -40849,7 +41010,7 @@ import { Worker } from "worker_threads";
40849
41010
  import { fileURLToPath as fileURLToPath3, pathToFileURL } from "url";
40850
41011
  import { dirname as dirname14, join as join45 } from "path";
40851
41012
  import { createRequire } from "module";
40852
- import { existsSync as existsSync36 } from "fs";
41013
+ import { existsSync as existsSync37 } from "fs";
40853
41014
  import { cpus as cpus3 } from "os";
40854
41015
  function resolveWorkerEntry(explicit) {
40855
41016
  if (explicit && explicit.length > 0) {
@@ -40862,7 +41023,7 @@ function resolveWorkerEntry(explicit) {
40862
41023
  }
40863
41024
  const moduleDir = dirname14(fileURLToPath3(import.meta.url));
40864
41025
  const jsPath = join45(moduleDir, "shaderTransitionWorker.js");
40865
- if (existsSync36(jsPath)) return { path: jsPath, isTs: false };
41026
+ if (existsSync37(jsPath)) return { path: jsPath, isTs: false };
40866
41027
  const tsPath = join45(moduleDir, "shaderTransitionWorker.ts");
40867
41028
  return { path: tsPath, isTs: true };
40868
41029
  }
@@ -41271,7 +41432,7 @@ var init_captureHdrHybridLoop = __esm({
41271
41432
  });
41272
41433
 
41273
41434
  // ../producer/src/services/render/stages/captureHdrStage.ts
41274
- import { existsSync as existsSync37, mkdirSync as mkdirSync22 } from "fs";
41435
+ import { existsSync as existsSync38, mkdirSync as mkdirSync22 } from "fs";
41275
41436
  import { join as join47 } from "path";
41276
41437
  async function runCaptureHdrStage(input) {
41277
41438
  const {
@@ -41328,7 +41489,7 @@ async function runCaptureHdrStage(input) {
41328
41489
  nativeHdrImageIds,
41329
41490
  projectDir,
41330
41491
  compiledDir,
41331
- existsSync: existsSync37
41492
+ existsSync: existsSync38
41332
41493
  });
41333
41494
  const domSession = await createCaptureSession(
41334
41495
  fileServer.url,
@@ -41432,7 +41593,7 @@ async function runCaptureHdrStage(input) {
41432
41593
  }
41433
41594
  const debugDumpEnabled = process.env.KEEP_TEMP === "1";
41434
41595
  const debugDumpDir = debugDumpEnabled ? join47(framesDir, "debug-composite") : null;
41435
- if (debugDumpDir && !existsSync37(debugDumpDir)) {
41596
+ if (debugDumpDir && !existsSync38(debugDumpDir)) {
41436
41597
  mkdirSync22(debugDumpDir, { recursive: true });
41437
41598
  }
41438
41599
  const compositeTransfer = resolveCompositeTransfer(hasHdrContent, effectiveHdr);
@@ -41588,7 +41749,7 @@ var init_captureHdrStage = __esm({
41588
41749
  });
41589
41750
 
41590
41751
  // ../producer/src/services/render/stages/encodeStage.ts
41591
- import { copyFileSync as copyFileSync3, existsSync as existsSync38, mkdirSync as mkdirSync23, readdirSync as readdirSync15 } from "fs";
41752
+ import { copyFileSync as copyFileSync3, existsSync as existsSync39, mkdirSync as mkdirSync23, readdirSync as readdirSync15 } from "fs";
41592
41753
  import { join as join48 } from "path";
41593
41754
  async function runEncodeStage(input) {
41594
41755
  const {
@@ -41615,7 +41776,7 @@ async function runEncodeStage(input) {
41615
41776
  const stage5Start = Date.now();
41616
41777
  if (isPngSequence) {
41617
41778
  updateJobStatus(job, "encoding", "Writing PNG sequence", 75, onProgress);
41618
- if (!existsSync38(outputPath)) mkdirSync23(outputPath, { recursive: true });
41779
+ if (!existsSync39(outputPath)) mkdirSync23(outputPath, { recursive: true });
41619
41780
  const captured = readdirSync15(framesDir).filter((name) => name.endsWith(".png")).sort();
41620
41781
  if (captured.length === 0) {
41621
41782
  throw new Error(
@@ -41626,7 +41787,7 @@ async function runEncodeStage(input) {
41626
41787
  const dst = join48(outputPath, `frame_${String(i2 + 1).padStart(6, "0")}.png`);
41627
41788
  copyFileSync3(join48(framesDir, name), dst);
41628
41789
  });
41629
- if (hasAudio && audioOutputPath && existsSync38(audioOutputPath)) {
41790
+ if (hasAudio && audioOutputPath && existsSync39(audioOutputPath)) {
41630
41791
  copyFileSync3(audioOutputPath, join48(outputPath, "audio.aac"));
41631
41792
  log2.info(`[Render] png-sequence: audio.aac sidecar written to ${outputPath}/audio.aac`);
41632
41793
  }
@@ -41718,9 +41879,9 @@ var init_assembleStage = __esm({
41718
41879
 
41719
41880
  // ../producer/src/services/renderOrchestrator.ts
41720
41881
  import {
41721
- existsSync as existsSync39,
41882
+ existsSync as existsSync40,
41722
41883
  mkdirSync as mkdirSync24,
41723
- readFileSync as readFileSync26,
41884
+ readFileSync as readFileSync28,
41724
41885
  readSync,
41725
41886
  closeSync,
41726
41887
  readdirSync as readdirSync16,
@@ -41833,7 +41994,7 @@ function findMissingFrameRanges(totalFrames, framesDir, frameExt) {
41833
41994
  let rangeStart = null;
41834
41995
  for (let frameIndex = 0; frameIndex < totalFrames; frameIndex++) {
41835
41996
  const framePath = join49(framesDir, `frame_${String(frameIndex).padStart(6, "0")}.${frameExt}`);
41836
- const missing = !existsSync39(framePath);
41997
+ const missing = !existsSync40(framePath);
41837
41998
  if (missing && rangeStart === null) {
41838
41999
  rangeStart = frameIndex;
41839
42000
  } else if (!missing && rangeStart !== null) {
@@ -41875,7 +42036,7 @@ function countCapturedFrames(totalFrames, framesDir, frameExt) {
41875
42036
  let captured = 0;
41876
42037
  for (let frameIndex = 0; frameIndex < totalFrames; frameIndex++) {
41877
42038
  const framePath = join49(framesDir, `frame_${String(frameIndex).padStart(6, "0")}.${frameExt}`);
41878
- if (existsSync39(framePath)) captured++;
42039
+ if (existsSync40(framePath)) captured++;
41879
42040
  }
41880
42041
  return captured;
41881
42042
  }
@@ -42446,28 +42607,28 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
42446
42607
  };
42447
42608
  job.startedAt = /* @__PURE__ */ new Date();
42448
42609
  assertNotAborted();
42449
- if (!existsSync39(workDir)) mkdirSync24(workDir, { recursive: true });
42610
+ if (!existsSync40(workDir)) mkdirSync24(workDir, { recursive: true });
42450
42611
  if (job.config.debug) {
42451
42612
  const logPath = join49(workDir, "render.log");
42452
42613
  restoreLogger = installDebugLogger(logPath, log2);
42453
42614
  }
42454
42615
  const entryFile = job.config.entryFile || "index.html";
42455
42616
  let htmlPath = join49(projectDir, entryFile);
42456
- if (!existsSync39(htmlPath)) {
42617
+ if (!existsSync40(htmlPath)) {
42457
42618
  throw new Error(`Entry file not found: ${htmlPath}`);
42458
42619
  }
42459
42620
  assertNotAborted();
42460
- const rawEntry = readFileSync26(htmlPath, "utf-8");
42621
+ const rawEntry = readFileSync28(htmlPath, "utf-8");
42461
42622
  if (entryFile !== "index.html" && rawEntry.trimStart().startsWith("<template")) {
42462
42623
  const wrapperPath = join49(workDir, "standalone-entry.html");
42463
42624
  const projectIndexPath = join49(projectDir, "index.html");
42464
- if (!existsSync39(projectIndexPath)) {
42625
+ if (!existsSync40(projectIndexPath)) {
42465
42626
  throw new Error(
42466
42627
  `Template entry file "${entryFile}" requires a project index.html to extract its render shell.`
42467
42628
  );
42468
42629
  }
42469
42630
  const standaloneHtml = extractStandaloneEntryFromIndex(
42470
- readFileSync26(projectIndexPath, "utf-8"),
42631
+ readFileSync28(projectIndexPath, "utf-8"),
42471
42632
  entryFile
42472
42633
  );
42473
42634
  if (!standaloneHtml) {
@@ -42578,7 +42739,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
42578
42739
  assertNotAborted();
42579
42740
  }
42580
42741
  const framesDir = join49(workDir, "captured-frames");
42581
- if (!existsSync39(framesDir)) mkdirSync24(framesDir, { recursive: true });
42742
+ if (!existsSync40(framesDir)) mkdirSync24(framesDir, { recursive: true });
42582
42743
  const captureOptions = {
42583
42744
  width,
42584
42745
  height,
@@ -42833,7 +42994,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
42833
42994
  job.outputPath = outputPath;
42834
42995
  updateJobStatus(job, "complete", "Render complete", 100, onProgress);
42835
42996
  const totalElapsed = Date.now() - pipelineStart;
42836
- const tmpPeakBytes = existsSync39(workDir) ? sampleDirectoryBytes(workDir) : 0;
42997
+ const tmpPeakBytes = existsSync40(workDir) ? sampleDirectoryBytes(workDir) : 0;
42837
42998
  const perfSummary = buildRenderPerfSummary({
42838
42999
  job,
42839
43000
  workerCount,
@@ -42868,7 +43029,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
42868
43029
  }
42869
43030
  }
42870
43031
  if (job.config.debug) {
42871
- if (!isPngSequence && existsSync39(outputPath)) {
43032
+ if (!isPngSequence && existsSync40(outputPath)) {
42872
43033
  const debugOutput = join49(workDir, `output${videoExt}`);
42873
43034
  copyFileSync4(outputPath, debugOutput);
42874
43035
  }
@@ -42995,7 +43156,7 @@ var init_config3 = __esm({
42995
43156
  });
42996
43157
 
42997
43158
  // ../producer/src/services/hyperframeLint.ts
42998
- import { existsSync as existsSync40, readFileSync as readFileSync27, statSync as statSync13 } from "fs";
43159
+ import { existsSync as existsSync41, readFileSync as readFileSync29, statSync as statSync13 } from "fs";
42999
43160
  import { resolve as resolve21, join as join50 } from "path";
43000
43161
  function isStringRecord(value) {
43001
43162
  if (!value || typeof value !== "object" || Array.isArray(value)) {
@@ -43024,7 +43185,7 @@ function pickEntryFile(files, preferredEntryFile) {
43024
43185
  }
43025
43186
  function readProjectEntryFile(projectDir, preferredEntryFile) {
43026
43187
  const absProjectDir = resolve21(projectDir);
43027
- if (!existsSync40(absProjectDir) || !statSync13(absProjectDir).isDirectory()) {
43188
+ if (!existsSync41(absProjectDir) || !statSync13(absProjectDir).isDirectory()) {
43028
43189
  return { error: `Project directory not found: ${absProjectDir}` };
43029
43190
  }
43030
43191
  const entryCandidates = [preferredEntryFile, "index.html", "src/index.html"].filter(
@@ -43035,10 +43196,10 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
43035
43196
  if (!absoluteEntryPath.startsWith(absProjectDir)) {
43036
43197
  return { error: `Entry file must stay inside project directory: ${entryFile}` };
43037
43198
  }
43038
- if (existsSync40(absoluteEntryPath) && statSync13(absoluteEntryPath).isFile()) {
43199
+ if (existsSync41(absoluteEntryPath) && statSync13(absoluteEntryPath).isFile()) {
43039
43200
  return {
43040
43201
  entryFile,
43041
- html: readFileSync27(absoluteEntryPath, "utf-8"),
43202
+ html: readFileSync29(absoluteEntryPath, "utf-8"),
43042
43203
  source: "projectDir"
43043
43204
  };
43044
43205
  }
@@ -43133,7 +43294,7 @@ var init_semaphore = __esm({
43133
43294
 
43134
43295
  // ../producer/src/server.ts
43135
43296
  import {
43136
- existsSync as existsSync41,
43297
+ existsSync as existsSync42,
43137
43298
  mkdirSync as mkdirSync25,
43138
43299
  statSync as statSync14,
43139
43300
  mkdtempSync as mkdtempSync2,
@@ -43166,11 +43327,11 @@ async function prepareRenderBody(body) {
43166
43327
  const projectDir = typeof body.projectDir === "string" ? body.projectDir : void 0;
43167
43328
  if (projectDir) {
43168
43329
  const absProjectDir = resolve22(projectDir);
43169
- if (!existsSync41(absProjectDir) || !statSync14(absProjectDir).isDirectory()) {
43330
+ if (!existsSync42(absProjectDir) || !statSync14(absProjectDir).isDirectory()) {
43170
43331
  return { error: `Project directory not found: ${absProjectDir}` };
43171
43332
  }
43172
43333
  const entry = options.entryFile || "index.html";
43173
- if (!existsSync41(resolve22(absProjectDir, entry))) {
43334
+ if (!existsSync42(resolve22(absProjectDir, entry))) {
43174
43335
  return { error: `Entry file "${entry}" not found in project directory: ${absProjectDir}` };
43175
43336
  }
43176
43337
  return { prepared: { input: { projectDir: absProjectDir, ...options } } };
@@ -43319,8 +43480,8 @@ function createRenderHandlers(options = {}) {
43319
43480
  log2
43320
43481
  );
43321
43482
  const outputDir = dirname16(absoluteOutputPath);
43322
- if (!existsSync41(outputDir)) mkdirSync25(outputDir, { recursive: true });
43323
- const release2 = await renderSemaphore.acquire();
43483
+ if (!existsSync42(outputDir)) mkdirSync25(outputDir, { recursive: true });
43484
+ const release4 = await renderSemaphore.acquire();
43324
43485
  log2.info("render started", {
43325
43486
  requestId,
43326
43487
  projectDir: input.projectDir,
@@ -43346,7 +43507,7 @@ function createRenderHandlers(options = {}) {
43346
43507
  log2.info(`render progress ${pct}%`, { requestId, stage: j3.currentStage, message });
43347
43508
  }
43348
43509
  });
43349
- const fileSize = existsSync41(absoluteOutputPath) ? statSync14(absoluteOutputPath).size : 0;
43510
+ const fileSize = existsSync42(absoluteOutputPath) ? statSync14(absoluteOutputPath).size : 0;
43350
43511
  const durationMs = Date.now() - t0;
43351
43512
  const outputToken = store.register(absoluteOutputPath);
43352
43513
  const outputUrl = `${outputUrlPrefix}/${outputToken}`;
@@ -43388,7 +43549,7 @@ function createRenderHandlers(options = {}) {
43388
43549
  500
43389
43550
  );
43390
43551
  } finally {
43391
- release2();
43552
+ release4();
43392
43553
  cleanupTempDir(cleanupProjectDir, log2);
43393
43554
  }
43394
43555
  };
@@ -43430,7 +43591,7 @@ function createRenderHandlers(options = {}) {
43430
43591
  log2
43431
43592
  );
43432
43593
  const outputDir = dirname16(absoluteOutputPath);
43433
- if (!existsSync41(outputDir)) mkdirSync25(outputDir, { recursive: true });
43594
+ if (!existsSync42(outputDir)) mkdirSync25(outputDir, { recursive: true });
43434
43595
  log2.info("render-stream started", { requestId, projectDir: input.projectDir });
43435
43596
  const job = createRenderJob({
43436
43597
  fps: input.fps,
@@ -43454,7 +43615,7 @@ function createRenderHandlers(options = {}) {
43454
43615
  })
43455
43616
  });
43456
43617
  }
43457
- const release2 = await renderSemaphore.acquire();
43618
+ const release4 = await renderSemaphore.acquire();
43458
43619
  try {
43459
43620
  await executeRenderJob(
43460
43621
  job,
@@ -43475,7 +43636,7 @@ function createRenderHandlers(options = {}) {
43475
43636
  },
43476
43637
  abortController.signal
43477
43638
  );
43478
- const fileSize = existsSync41(absoluteOutputPath) ? statSync14(absoluteOutputPath).size : 0;
43639
+ const fileSize = existsSync42(absoluteOutputPath) ? statSync14(absoluteOutputPath).size : 0;
43479
43640
  const outputToken = store.register(absoluteOutputPath);
43480
43641
  const outputUrl = `${outputUrlPrefix}/${outputToken}`;
43481
43642
  log2.info("render-stream completed", { requestId, fileSize, perf: job.perfSummary ?? null });
@@ -43522,7 +43683,7 @@ function createRenderHandlers(options = {}) {
43522
43683
  })
43523
43684
  });
43524
43685
  } finally {
43525
- release2();
43686
+ release4();
43526
43687
  c3.req.raw.signal.removeEventListener("abort", onRequestAbort);
43527
43688
  cleanupTempDir(cleanupProjectDir, log2);
43528
43689
  }
@@ -43534,7 +43695,7 @@ function createRenderHandlers(options = {}) {
43534
43695
  if (!artifact) {
43535
43696
  return c3.json({ success: false, error: "Output artifact not found or expired" }, 404);
43536
43697
  }
43537
- if (!existsSync41(artifact.path)) {
43698
+ if (!existsSync42(artifact.path)) {
43538
43699
  store.delete(token);
43539
43700
  return c3.json({ success: false, error: "Output artifact file missing" }, 404);
43540
43701
  }
@@ -43688,7 +43849,7 @@ var init_planHash = __esm({
43688
43849
  });
43689
43850
 
43690
43851
  // ../producer/src/services/render/stages/freezePlan.ts
43691
- import { existsSync as existsSync42, mkdirSync as mkdirSync26, readFileSync as readFileSync28, readdirSync as readdirSync17, writeFileSync as writeFileSync20 } from "fs";
43852
+ import { existsSync as existsSync43, mkdirSync as mkdirSync26, readFileSync as readFileSync30, readdirSync as readdirSync17, writeFileSync as writeFileSync20 } from "fs";
43692
43853
  import { join as join52, relative as relative5, resolve as resolve23 } from "path";
43693
43854
  function stripUndefined(value) {
43694
43855
  if (Array.isArray(value)) return value.map(stripUndefined);
@@ -43731,11 +43892,11 @@ function collectPlanAssetShas(planDir) {
43731
43892
  const assets = [];
43732
43893
  for (const file of files) {
43733
43894
  if (file.planRelativePath === COMPILED_INDEX_RELATIVE_PATH) {
43734
- compositionHtml = readFileSync28(file.absolutePath);
43895
+ compositionHtml = readFileSync30(file.absolutePath);
43735
43896
  continue;
43736
43897
  }
43737
43898
  if (HASH_EXCLUDED_PLAN_FILES.has(file.planRelativePath)) continue;
43738
- const bytes = readFileSync28(file.absolutePath);
43899
+ const bytes = readFileSync30(file.absolutePath);
43739
43900
  assets.push({ path: file.planRelativePath, sha256: sha256Hex(bytes) });
43740
43901
  }
43741
43902
  if (compositionHtml === null) {
@@ -43748,14 +43909,14 @@ function collectPlanAssetShas(planDir) {
43748
43909
  function recomputePlanHashFromPlanDir(planDir) {
43749
43910
  const planJsonPath = join52(planDir, "plan.json");
43750
43911
  const encoderJsonPath = join52(planDir, "meta", "encoder.json");
43751
- if (!existsSync42(planJsonPath)) {
43912
+ if (!existsSync43(planJsonPath)) {
43752
43913
  throw new Error(`[freezePlan] plan.json missing: ${planJsonPath}`);
43753
43914
  }
43754
- if (!existsSync42(encoderJsonPath)) {
43915
+ if (!existsSync43(encoderJsonPath)) {
43755
43916
  throw new Error(`[freezePlan] meta/encoder.json missing: ${encoderJsonPath}`);
43756
43917
  }
43757
- const planJson = JSON.parse(readFileSync28(planJsonPath, "utf-8"));
43758
- const encoderConfigCanonicalJson = readFileSync28(encoderJsonPath, "utf-8");
43918
+ const planJson = JSON.parse(readFileSync30(planJsonPath, "utf-8"));
43919
+ const encoderConfigCanonicalJson = readFileSync30(encoderJsonPath, "utf-8");
43759
43920
  const { compositionHtml, assets } = collectPlanAssetShas(planDir);
43760
43921
  return computePlanHash({
43761
43922
  compositionHtml,
@@ -43780,11 +43941,11 @@ async function freezePlan(input) {
43780
43941
  totalFrames,
43781
43942
  hasAudio
43782
43943
  } = input;
43783
- if (!existsSync42(planDir)) {
43944
+ if (!existsSync43(planDir)) {
43784
43945
  throw new Error(`[freezePlan] planDir does not exist: ${planDir}`);
43785
43946
  }
43786
43947
  const metaDir = join52(planDir, "meta");
43787
- if (!existsSync42(metaDir)) mkdirSync26(metaDir, { recursive: true });
43948
+ if (!existsSync43(metaDir)) mkdirSync26(metaDir, { recursive: true });
43788
43949
  writeFileSync20(
43789
43950
  join52(metaDir, "composition.json"),
43790
43951
  `${JSON.stringify(composition, null, 2)}
@@ -43926,7 +44087,7 @@ var init_runtimeEnvSnapshot = __esm({
43926
44087
  // ../producer/src/services/distributed/shared.ts
43927
44088
  import { execFile as execFileCallback } from "child_process";
43928
44089
  import { dirname as dirname17, join as join53 } from "path";
43929
- import { existsSync as existsSync43, readFileSync as readFileSync29 } from "fs";
44090
+ import { existsSync as existsSync44, readFileSync as readFileSync31 } from "fs";
43930
44091
  import { fileURLToPath as fileURLToPath5 } from "url";
43931
44092
  import { promisify as promisify2 } from "util";
43932
44093
  async function readFfmpegVersion() {
@@ -43964,9 +44125,9 @@ function readProducerVersion() {
43964
44125
  let current = startDir;
43965
44126
  for (let i2 = 0; i2 < 10; i2++) {
43966
44127
  const candidate = join53(current, "package.json");
43967
- if (existsSync43(candidate)) {
44128
+ if (existsSync44(candidate)) {
43968
44129
  try {
43969
- const pkg = JSON.parse(readFileSync29(candidate, "utf-8"));
44130
+ const pkg = JSON.parse(readFileSync31(candidate, "utf-8"));
43970
44131
  if (pkg.name === "@hyperframes/producer" && typeof pkg.version === "string") {
43971
44132
  cachedProducerVersion = pkg.version;
43972
44133
  return pkg.version;
@@ -43997,7 +44158,7 @@ var init_shared2 = __esm({
43997
44158
  // ../producer/src/services/distributed/plan.ts
43998
44159
  import {
43999
44160
  cpSync as cpSync2,
44000
- existsSync as existsSync44,
44161
+ existsSync as existsSync45,
44001
44162
  mkdirSync as mkdirSync27,
44002
44163
  readdirSync as readdirSync18,
44003
44164
  renameSync as renameSync3,
@@ -44162,7 +44323,7 @@ async function plan(projectDir, config, planDir) {
44162
44323
  useGpu: false,
44163
44324
  browserGpuMode: "software"
44164
44325
  });
44165
- if (!existsSync44(planDir)) mkdirSync27(planDir, { recursive: true });
44326
+ if (!existsSync45(planDir)) mkdirSync27(planDir, { recursive: true });
44166
44327
  const log2 = config.logger ?? defaultLogger;
44167
44328
  const abortSignal = config.abortSignal;
44168
44329
  const assertNotAborted = () => {
@@ -44191,11 +44352,11 @@ async function plan(projectDir, config, planDir) {
44191
44352
  });
44192
44353
  const entryFile = config.entryFile ?? "index.html";
44193
44354
  const htmlPath = join54(projectDir, entryFile);
44194
- if (!existsSync44(htmlPath)) {
44355
+ if (!existsSync45(htmlPath)) {
44195
44356
  throw new Error(`[plan] entry file not found: ${htmlPath}`);
44196
44357
  }
44197
44358
  const workDir = join54(planDir, ".plan-work");
44198
- if (!existsSync44(workDir)) mkdirSync27(workDir, { recursive: true });
44359
+ if (!existsSync45(workDir)) mkdirSync27(workDir, { recursive: true });
44199
44360
  const compiledDir = join54(workDir, "compiled");
44200
44361
  mkdirSync27(compiledDir, { recursive: true });
44201
44362
  cpSync2(projectDir, compiledDir, {
@@ -44281,13 +44442,13 @@ async function plan(projectDir, config, planDir) {
44281
44442
  });
44282
44443
  const stagedVideoFrames = join54(compiledDir, "__hyperframes_video_frames");
44283
44444
  const videoFramesDst = join54(planDir, "video-frames");
44284
- if (existsSync44(videoFramesDst)) rmSync11(videoFramesDst, { recursive: true, force: true });
44285
- if (existsSync44(stagedVideoFrames)) {
44445
+ if (existsSync45(videoFramesDst)) rmSync11(videoFramesDst, { recursive: true, force: true });
44446
+ if (existsSync45(stagedVideoFrames)) {
44286
44447
  renameSync3(stagedVideoFrames, videoFramesDst);
44287
44448
  } else {
44288
44449
  mkdirSync27(videoFramesDst, { recursive: true });
44289
44450
  }
44290
- if (existsSync44(finalCompiledDir)) rmSync11(finalCompiledDir, { recursive: true, force: true });
44451
+ if (existsSync45(finalCompiledDir)) rmSync11(finalCompiledDir, { recursive: true, force: true });
44291
44452
  renameSync3(compiledDir, finalCompiledDir);
44292
44453
  const planVideosJson = {
44293
44454
  videos: composition.videos,
@@ -44307,7 +44468,7 @@ async function plan(projectDir, config, planDir) {
44307
44468
  "utf-8"
44308
44469
  );
44309
44470
  const planAudioPath = join54(planDir, "audio.aac");
44310
- if (audioResult.hasAudio && existsSync44(audioResult.audioOutputPath)) {
44471
+ if (audioResult.hasAudio && existsSync45(audioResult.audioOutputPath)) {
44311
44472
  renameSync3(audioResult.audioOutputPath, planAudioPath);
44312
44473
  }
44313
44474
  const maxParallel = config.maxParallelChunks ?? DEFAULT_MAX_PARALLEL_CHUNKS;
@@ -44446,13 +44607,13 @@ var init_plan = __esm({
44446
44607
 
44447
44608
  // ../producer/src/services/distributed/renderChunk.ts
44448
44609
  import { randomBytes } from "crypto";
44449
- import { existsSync as existsSync45, mkdirSync as mkdirSync28, readFileSync as readFileSync30, readdirSync as readdirSync19, rmSync as rmSync12, writeFileSync as writeFileSync22 } from "fs";
44610
+ import { existsSync as existsSync46, mkdirSync as mkdirSync28, readFileSync as readFileSync32, readdirSync as readdirSync19, rmSync as rmSync12, writeFileSync as writeFileSync22 } from "fs";
44450
44611
  import { extname as extname9, join as join55 } from "path";
44451
44612
  function rebuildExtractedFramesFromPlanDir(planDir, videos) {
44452
44613
  const result = [];
44453
44614
  for (const v2 of videos) {
44454
44615
  const outputDir = join55(planDir, "video-frames", v2.videoId);
44455
- if (!existsSync45(outputDir)) {
44616
+ if (!existsSync46(outputDir)) {
44456
44617
  throw new Error(
44457
44618
  `[renderChunk] planDir missing extracted video frames for ${JSON.stringify(v2.videoId)}: ${outputDir} not present. plan() should have written frames here; the planDir is malformed.`
44458
44619
  );
@@ -44485,10 +44646,10 @@ function rebuildExtractedFramesFromPlanDir(planDir, videos) {
44485
44646
  return result;
44486
44647
  }
44487
44648
  function hashChunkOutput(outputPath, kind) {
44488
- if (kind === "file") return sha256Hex(readFileSync30(outputPath));
44649
+ if (kind === "file") return sha256Hex(readFileSync32(outputPath));
44489
44650
  const entries2 = readdirSync19(outputPath).filter((name) => /\.(png|jpg|jpeg)$/i.test(name)).sort();
44490
44651
  const lines = entries2.map(
44491
- (name) => `${name}\0${sha256Hex(readFileSync30(join55(outputPath, name)))}`
44652
+ (name) => `${name}\0${sha256Hex(readFileSync32(join55(outputPath, name)))}`
44492
44653
  );
44493
44654
  return sha256Hex(lines.join("\0"));
44494
44655
  }
@@ -44505,21 +44666,21 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
44505
44666
  const encoderJsonPath = join55(planDir, "meta", "encoder.json");
44506
44667
  const chunksJsonPath = join55(planDir, "meta", "chunks.json");
44507
44668
  for (const required of [planJsonPath, encoderJsonPath, chunksJsonPath]) {
44508
- if (!existsSync45(required)) {
44669
+ if (!existsSync46(required)) {
44509
44670
  throw new RenderChunkValidationError(
44510
44671
  MISSING_PLAN_ARTIFACT,
44511
44672
  `[renderChunk] planDir is missing required artifact: ${required}`
44512
44673
  );
44513
44674
  }
44514
44675
  }
44515
- const plan2 = JSON.parse(readFileSync30(planJsonPath, "utf-8"));
44516
- const encoder = JSON.parse(readFileSync30(encoderJsonPath, "utf-8"));
44517
- const chunks = JSON.parse(readFileSync30(chunksJsonPath, "utf-8"));
44676
+ const plan2 = JSON.parse(readFileSync32(planJsonPath, "utf-8"));
44677
+ const encoder = JSON.parse(readFileSync32(encoderJsonPath, "utf-8"));
44678
+ const chunks = JSON.parse(readFileSync32(chunksJsonPath, "utf-8"));
44518
44679
  const videosJsonPath = join55(planDir, PLAN_VIDEOS_META_RELATIVE_PATH);
44519
44680
  let planVideos = null;
44520
- if (existsSync45(videosJsonPath)) {
44681
+ if (existsSync46(videosJsonPath)) {
44521
44682
  try {
44522
- planVideos = JSON.parse(readFileSync30(videosJsonPath, "utf-8"));
44683
+ planVideos = JSON.parse(readFileSync32(videosJsonPath, "utf-8"));
44523
44684
  } catch (err) {
44524
44685
  throw new RenderChunkValidationError(
44525
44686
  MISSING_PLAN_ARTIFACT,
@@ -44545,7 +44706,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
44545
44706
  );
44546
44707
  }
44547
44708
  const compiledDir = join55(planDir, "compiled");
44548
- if (!existsSync45(compiledDir)) {
44709
+ if (!existsSync46(compiledDir)) {
44549
44710
  throw new RenderChunkValidationError(
44550
44711
  MISSING_PLAN_ARTIFACT,
44551
44712
  `[renderChunk] planDir missing compiled/ directory: ${compiledDir}`
@@ -44669,10 +44830,10 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
44669
44830
  const effectiveBitrate = encoder.crf != null ? void 0 : encoder.bitrate;
44670
44831
  const videoOnlyPath = outputChunkPath;
44671
44832
  if (isPngSequence) {
44672
- if (!existsSync45(outputChunkPath)) mkdirSync28(outputChunkPath, { recursive: true });
44833
+ if (!existsSync46(outputChunkPath)) mkdirSync28(outputChunkPath, { recursive: true });
44673
44834
  } else {
44674
44835
  const outDir = join55(outputChunkPath, "..");
44675
- if (!existsSync45(outDir)) mkdirSync28(outDir, { recursive: true });
44836
+ if (!existsSync46(outDir)) mkdirSync28(outDir, { recursive: true });
44676
44837
  }
44677
44838
  await runEncodeStage({
44678
44839
  job,
@@ -44993,9 +45154,9 @@ var init_audioPadTrim = __esm({
44993
45154
  // ../producer/src/services/distributed/assemble.ts
44994
45155
  import {
44995
45156
  cpSync as cpSync3,
44996
- existsSync as existsSync46,
45157
+ existsSync as existsSync47,
44997
45158
  mkdirSync as mkdirSync29,
44998
- readFileSync as readFileSync31,
45159
+ readFileSync as readFileSync33,
44999
45160
  readdirSync as readdirSync20,
45000
45161
  rmSync as rmSync13,
45001
45162
  statSync as statSync16,
@@ -45008,32 +45169,32 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
45008
45169
  const abortSignal = options?.abortSignal;
45009
45170
  const planJsonPath = join56(planDir, "plan.json");
45010
45171
  const chunksJsonPath = join56(planDir, "meta", "chunks.json");
45011
- if (!existsSync46(planJsonPath)) {
45172
+ if (!existsSync47(planJsonPath)) {
45012
45173
  throw new Error(`[assemble] planDir missing plan.json: ${planJsonPath}`);
45013
45174
  }
45014
- if (!existsSync46(chunksJsonPath)) {
45175
+ if (!existsSync47(chunksJsonPath)) {
45015
45176
  throw new Error(`[assemble] planDir missing meta/chunks.json: ${chunksJsonPath}`);
45016
45177
  }
45017
- const plan2 = JSON.parse(readFileSync31(planJsonPath, "utf-8"));
45018
- const chunks = JSON.parse(readFileSync31(chunksJsonPath, "utf-8"));
45178
+ const plan2 = JSON.parse(readFileSync33(planJsonPath, "utf-8"));
45179
+ const chunks = JSON.parse(readFileSync33(chunksJsonPath, "utf-8"));
45019
45180
  if (chunkPaths.length !== chunks.length) {
45020
45181
  throw new Error(
45021
45182
  `[assemble] chunkPaths length (${chunkPaths.length}) does not match chunks.json length (${chunks.length}). Adapters must pass one path per chunk, ordered by index.`
45022
45183
  );
45023
45184
  }
45024
45185
  for (const path2 of chunkPaths) {
45025
- if (!existsSync46(path2)) {
45186
+ if (!existsSync47(path2)) {
45026
45187
  throw new Error(`[assemble] chunk path does not exist: ${path2}`);
45027
45188
  }
45028
45189
  }
45029
45190
  if (plan2.dimensions.format === "png-sequence") {
45030
45191
  return mergePngFrameDirs(chunkPaths, outputPath, plan2.totalFrames, audioPath, start);
45031
45192
  }
45032
- if (!existsSync46(dirname18(outputPath))) {
45193
+ if (!existsSync47(dirname18(outputPath))) {
45033
45194
  mkdirSync29(dirname18(outputPath), { recursive: true });
45034
45195
  }
45035
45196
  const workDir = `${outputPath}.assemble-work`;
45036
- if (existsSync46(workDir)) rmSync13(workDir, { recursive: true, force: true });
45197
+ if (existsSync47(workDir)) rmSync13(workDir, { recursive: true, force: true });
45037
45198
  mkdirSync29(workDir, { recursive: true });
45038
45199
  try {
45039
45200
  const concatListPath = join56(workDir, "concat-list.txt");
@@ -45060,7 +45221,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
45060
45221
  );
45061
45222
  }
45062
45223
  let audioForMux = null;
45063
- if (audioPath !== null && existsSync46(audioPath)) {
45224
+ if (audioPath !== null && existsSync47(audioPath)) {
45064
45225
  const paddedAudioPath = join56(workDir, "audio-padded.aac");
45065
45226
  const padTrimResult = await padOrTrimAudioToVideoFrameCount({
45066
45227
  videoPath: concatOutputPath,
@@ -45103,7 +45264,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
45103
45264
  });
45104
45265
  }
45105
45266
  }
45106
- const fileSize = existsSync46(outputPath) ? statSync16(outputPath).size : 0;
45267
+ const fileSize = existsSync47(outputPath) ? statSync16(outputPath).size : 0;
45107
45268
  return {
45108
45269
  outputPath,
45109
45270
  durationMs: Date.now() - start,
@@ -45112,7 +45273,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
45112
45273
  };
45113
45274
  }
45114
45275
  function mergePngFrameDirs(chunkPaths, outputPath, totalFrames, audioPath, startTimeMs) {
45115
- if (existsSync46(outputPath)) rmSync13(outputPath, { recursive: true, force: true });
45276
+ if (existsSync47(outputPath)) rmSync13(outputPath, { recursive: true, force: true });
45116
45277
  mkdirSync29(outputPath, { recursive: true });
45117
45278
  let globalIdx = 0;
45118
45279
  for (const chunkDir of chunkPaths) {
@@ -45136,7 +45297,7 @@ function mergePngFrameDirs(chunkPaths, outputPath, totalFrames, audioPath, start
45136
45297
  `[assemble] png-sequence frame count mismatch: merged ${globalIdx} frames vs plan.totalFrames=${totalFrames}. Using on-disk count.`
45137
45298
  );
45138
45299
  }
45139
- if (audioPath !== null && existsSync46(audioPath)) {
45300
+ if (audioPath !== null && existsSync47(audioPath)) {
45140
45301
  const sidecar = join56(outputPath, "audio.aac");
45141
45302
  cpSync3(audioPath, sidecar);
45142
45303
  }
@@ -45229,7 +45390,7 @@ __export(studioServer_exports, {
45229
45390
  });
45230
45391
  import { Hono as Hono5 } from "hono";
45231
45392
  import { streamSSE as streamSSE3 } from "hono/streaming";
45232
- import { existsSync as existsSync47, readFileSync as readFileSync32, writeFileSync as writeFileSync24, statSync as statSync17 } from "fs";
45393
+ import { existsSync as existsSync48, readFileSync as readFileSync34, writeFileSync as writeFileSync24, statSync as statSync17 } from "fs";
45233
45394
  import { resolve as resolve24, join as join57, basename as basename5 } from "path";
45234
45395
  function resolveDistDir() {
45235
45396
  return resolveStudioBundle().dir;
@@ -45237,12 +45398,12 @@ function resolveDistDir() {
45237
45398
  function resolveStudioBundle() {
45238
45399
  const builtPath = resolve24(__dirname, "studio");
45239
45400
  const builtIndex = resolve24(builtPath, "index.html");
45240
- if (existsSync47(builtIndex)) {
45401
+ if (existsSync48(builtIndex)) {
45241
45402
  return { dir: builtPath, indexPath: builtIndex, available: true, checkedPaths: [builtIndex] };
45242
45403
  }
45243
45404
  const devPath = resolve24(__dirname, "..", "..", "..", "studio", "dist");
45244
45405
  const devIndex = resolve24(devPath, "index.html");
45245
- if (existsSync47(devIndex)) {
45406
+ if (existsSync48(devIndex)) {
45246
45407
  return {
45247
45408
  dir: devPath,
45248
45409
  indexPath: devIndex,
@@ -45259,9 +45420,9 @@ function resolveStudioBundle() {
45259
45420
  }
45260
45421
  function resolveRuntimePath() {
45261
45422
  const builtPath = resolve24(__dirname, "hyperframe-runtime.js");
45262
- if (existsSync47(builtPath)) return builtPath;
45423
+ if (existsSync48(builtPath)) return builtPath;
45263
45424
  const iifePath = resolve24(__dirname, "hyperframe.runtime.iife.js");
45264
- if (existsSync47(iifePath)) return iifePath;
45425
+ if (existsSync48(iifePath)) return iifePath;
45265
45426
  const devPath = resolve24(
45266
45427
  __dirname,
45267
45428
  "..",
@@ -45271,14 +45432,14 @@ function resolveRuntimePath() {
45271
45432
  "dist",
45272
45433
  "hyperframe.runtime.iife.js"
45273
45434
  );
45274
- if (existsSync47(devPath)) return devPath;
45435
+ if (existsSync48(devPath)) return devPath;
45275
45436
  return builtPath;
45276
45437
  }
45277
45438
  function readStudioManualEditManifestContent(projectDir) {
45278
45439
  const manifestPath = join57(projectDir, STUDIO_MANUAL_EDITS_PATH2);
45279
- if (!existsSync47(manifestPath)) return "";
45440
+ if (!existsSync48(manifestPath)) return "";
45280
45441
  try {
45281
- return readFileSync32(manifestPath, "utf-8");
45442
+ return readFileSync34(manifestPath, "utf-8");
45282
45443
  } catch {
45283
45444
  return "";
45284
45445
  }
@@ -45519,19 +45680,19 @@ function createStudioServer(options) {
45519
45680
  async installRegistryBlock(opts) {
45520
45681
  const { resolveItem: resolveItem2 } = await Promise.resolve().then(() => (init_resolver(), resolver_exports));
45521
45682
  const { installItem: installItem2 } = await Promise.resolve().then(() => (init_installer(), installer_exports));
45522
- const { readFileSync: readFileSync54, writeFileSync: writeFileSync39, existsSync: existsSync80 } = await import("fs");
45523
- const { join: join89 } = await import("path");
45683
+ const { readFileSync: readFileSync57, writeFileSync: writeFileSync39, existsSync: existsSync81 } = await import("fs");
45684
+ const { join: join90 } = await import("path");
45524
45685
  const item = await resolveItem2(opts.blockName);
45525
45686
  const { written } = await installItem2(item, { destDir: opts.project.dir });
45526
- const indexPath = join89(opts.project.dir, "index.html");
45527
- if (existsSync80(indexPath)) {
45528
- const indexHtml = readFileSync54(indexPath, "utf-8");
45687
+ const indexPath = join90(opts.project.dir, "index.html");
45688
+ if (existsSync81(indexPath)) {
45689
+ const indexHtml = readFileSync57(indexPath, "utf-8");
45529
45690
  const hostW = indexHtml.match(/data-width="(\d+)"/)?.[1];
45530
45691
  const hostH = indexHtml.match(/data-height="(\d+)"/)?.[1];
45531
45692
  if (hostW && hostH) {
45532
45693
  for (const absPath of written) {
45533
45694
  if (!absPath.endsWith(".html")) continue;
45534
- let content = readFileSync54(absPath, "utf-8");
45695
+ let content = readFileSync57(absPath, "utf-8");
45535
45696
  content = content.replace(
45536
45697
  /(<meta\s+name="viewport"\s+content="width=)\d+(,\s*height=)\d+/i,
45537
45698
  `$1${hostW}$2${hostH}`
@@ -45567,7 +45728,7 @@ function createStudioServer(options) {
45567
45728
  });
45568
45729
  app.get("/api/runtime.js", (c3) => {
45569
45730
  const serve4 = async () => {
45570
- const runtimeSource = await loadRuntimeSource() ?? (existsSync47(runtimePath) ? readFileSync32(runtimePath, "utf-8") : null);
45731
+ const runtimeSource = await loadRuntimeSource() ?? (existsSync48(runtimePath) ? readFileSync34(runtimePath, "utf-8") : null);
45571
45732
  if (!runtimeSource) return c3.text("runtime not available", 404);
45572
45733
  return c3.body(runtimeSource, 200, {
45573
45734
  "Content-Type": "text/javascript",
@@ -45603,8 +45764,8 @@ function createStudioServer(options) {
45603
45764
  });
45604
45765
  const serveStudioStaticFile = (c3) => {
45605
45766
  const filePath = resolve24(studioDir, c3.req.path.slice(1));
45606
- if (!existsSync47(filePath) || !statSync17(filePath).isFile()) return c3.text("not found", 404);
45607
- const content = readFileSync32(filePath);
45767
+ if (!existsSync48(filePath) || !statSync17(filePath).isFile()) return c3.text("not found", 404);
45768
+ const content = readFileSync34(filePath);
45608
45769
  return new Response(content, {
45609
45770
  headers: { "Content-Type": getMimeType(filePath), "Cache-Control": "no-store" }
45610
45771
  });
@@ -45624,7 +45785,7 @@ function createStudioServer(options) {
45624
45785
  }
45625
45786
  app.get("*", (c3) => {
45626
45787
  const indexPath = resolve24(studioDir, "index.html");
45627
- if (!existsSync47(indexPath)) {
45788
+ if (!existsSync48(indexPath)) {
45628
45789
  return c3.html(
45629
45790
  `<!doctype html>
45630
45791
  <html>
@@ -45680,7 +45841,7 @@ function createStudioServer(options) {
45680
45841
  500
45681
45842
  );
45682
45843
  }
45683
- let html = readFileSync32(indexPath, "utf-8");
45844
+ let html = readFileSync34(indexPath, "utf-8");
45684
45845
  const envScript = buildRuntimeEnvScript();
45685
45846
  if (envScript) {
45686
45847
  html = html.replace("<head>", `<head>${envScript}`);
@@ -45712,7 +45873,7 @@ __export(preview_exports, {
45712
45873
  examples: () => examples
45713
45874
  });
45714
45875
  import { spawn as spawn11 } from "child_process";
45715
- import { existsSync as existsSync48, lstatSync as lstatSync2, symlinkSync as symlinkSync2, unlinkSync as unlinkSync5, readlinkSync, mkdirSync as mkdirSync30 } from "fs";
45876
+ import { existsSync as existsSync49, lstatSync as lstatSync2, symlinkSync as symlinkSync2, unlinkSync as unlinkSync5, readlinkSync, mkdirSync as mkdirSync30 } from "fs";
45716
45877
  import { resolve as resolve25, dirname as dirname19, basename as basename6, join as join58 } from "path";
45717
45878
  import { fileURLToPath as fileURLToPath6 } from "url";
45718
45879
  import { createRequire as createRequire2 } from "module";
@@ -45725,7 +45886,7 @@ async function runDevMode(dir, options) {
45725
45886
  mkdirSync30(projectsDir, { recursive: true });
45726
45887
  let createdSymlink = false;
45727
45888
  if (dir !== symlinkPath) {
45728
- if (existsSync48(symlinkPath)) {
45889
+ if (existsSync49(symlinkPath)) {
45729
45890
  try {
45730
45891
  const stat3 = lstatSync2(symlinkPath);
45731
45892
  if (stat3.isSymbolicLink()) {
@@ -45737,7 +45898,7 @@ async function runDevMode(dir, options) {
45737
45898
  } catch {
45738
45899
  }
45739
45900
  }
45740
- if (!existsSync48(symlinkPath)) {
45901
+ if (!existsSync49(symlinkPath)) {
45741
45902
  symlinkSync2(dir, symlinkPath, "dir");
45742
45903
  createdSymlink = true;
45743
45904
  }
@@ -45783,7 +45944,7 @@ async function runDevMode(dir, options) {
45783
45944
  if (createdSymlink) {
45784
45945
  process.on("exit", () => {
45785
45946
  try {
45786
- if (existsSync48(symlinkPath)) unlinkSync5(symlinkPath);
45947
+ if (existsSync49(symlinkPath)) unlinkSync5(symlinkPath);
45787
45948
  } catch {
45788
45949
  }
45789
45950
  });
@@ -45810,12 +45971,12 @@ async function runLocalStudioMode(dir, options) {
45810
45971
  mkdirSync30(projectsDir, { recursive: true });
45811
45972
  let createdSymlink = false;
45812
45973
  if (dir !== symlinkPath) {
45813
- if (existsSync48(symlinkPath) && lstatSync2(symlinkPath).isSymbolicLink()) {
45974
+ if (existsSync49(symlinkPath) && lstatSync2(symlinkPath).isSymbolicLink()) {
45814
45975
  if (resolve25(readlinkSync(symlinkPath)) !== resolve25(dir)) {
45815
45976
  unlinkSync5(symlinkPath);
45816
45977
  }
45817
45978
  }
45818
- if (!existsSync48(symlinkPath)) {
45979
+ if (!existsSync49(symlinkPath)) {
45819
45980
  symlinkSync2(dir, symlinkPath, "dir");
45820
45981
  createdSymlink = true;
45821
45982
  }
@@ -45858,7 +46019,7 @@ async function runLocalStudioMode(dir, options) {
45858
46019
  if (createdSymlink) {
45859
46020
  process.on("exit", () => {
45860
46021
  try {
45861
- if (existsSync48(symlinkPath)) unlinkSync5(symlinkPath);
46022
+ if (existsSync49(symlinkPath)) unlinkSync5(symlinkPath);
45862
46023
  } catch {
45863
46024
  }
45864
46025
  });
@@ -46059,7 +46220,7 @@ var init_preview2 = __esm({
46059
46220
  const isImplicitCwd = !rawArg || rawArg === "." || rawArg === "./";
46060
46221
  const projectName = isImplicitCwd ? basename6(process.env.PWD ?? dir) : basename6(dir);
46061
46222
  const indexPath = join58(dir, "index.html");
46062
- if (existsSync48(indexPath)) {
46223
+ if (existsSync49(indexPath)) {
46063
46224
  const project = { dir, name: projectName, indexPath };
46064
46225
  const lintResult = lintProject(project);
46065
46226
  if (lintResult.totalErrors > 0 || lintResult.totalWarnings > 0) {
@@ -46104,12 +46265,12 @@ __export(init_exports, {
46104
46265
  injectTailwindBrowserScript: () => injectTailwindBrowserScript
46105
46266
  });
46106
46267
  import {
46107
- existsSync as existsSync49,
46268
+ existsSync as existsSync50,
46108
46269
  mkdirSync as mkdirSync31,
46109
46270
  copyFileSync as copyFileSync5,
46110
46271
  cpSync as cpSync4,
46111
46272
  writeFileSync as writeFileSync25,
46112
- readFileSync as readFileSync33,
46273
+ readFileSync as readFileSync35,
46113
46274
  readdirSync as readdirSync21
46114
46275
  } from "fs";
46115
46276
  import { resolve as resolve26, basename as basename7, join as join59, dirname as dirname20 } from "path";
@@ -46184,7 +46345,7 @@ function resolveAssetDir(devSegments, builtSegments) {
46184
46345
  const base = dirname20(fileURLToPath7(import.meta.url));
46185
46346
  const devPath = resolve26(base, ...devSegments);
46186
46347
  const builtPath = resolve26(base, ...builtSegments);
46187
- return existsSync49(devPath) ? devPath : builtPath;
46348
+ return existsSync50(devPath) ? devPath : builtPath;
46188
46349
  }
46189
46350
  function getStaticTemplateDir(templateId) {
46190
46351
  return resolveAssetDir(["..", "templates", templateId], ["templates", templateId]);
@@ -46212,7 +46373,7 @@ function buildPackageScripts() {
46212
46373
  }
46213
46374
  function writeDefaultPackageJson(destDir, projectName) {
46214
46375
  const packageJsonPath = resolve26(destDir, "package.json");
46215
- if (existsSync49(packageJsonPath)) return;
46376
+ if (existsSync50(packageJsonPath)) return;
46216
46377
  writeFileSync25(
46217
46378
  packageJsonPath,
46218
46379
  `${JSON.stringify(
@@ -46274,14 +46435,14 @@ ${html}`;
46274
46435
  }
46275
46436
  function writeTailwindSupport(destDir) {
46276
46437
  for (const file of listHtmlFiles(destDir)) {
46277
- const html = readFileSync33(file, "utf-8");
46438
+ const html = readFileSync35(file, "utf-8");
46278
46439
  writeFileSync25(file, injectTailwindBrowserScript(html), "utf-8");
46279
46440
  }
46280
46441
  }
46281
46442
  function patchVideoSrc(dir, videoFilename, durationSeconds) {
46282
46443
  const htmlFiles = readdirSync21(dir, { withFileTypes: true, recursive: true }).filter((e3) => e3.isFile() && e3.name.endsWith(".html")).map((e3) => join59(e3.parentPath, e3.name));
46283
46444
  for (const file of htmlFiles) {
46284
- let content = readFileSync33(file, "utf-8");
46445
+ let content = readFileSync35(file, "utf-8");
46285
46446
  if (videoFilename) {
46286
46447
  content = content.replaceAll("__VIDEO_SRC__", videoFilename);
46287
46448
  } else {
@@ -46386,7 +46547,7 @@ async function handleVideoFile(videoPath, destDir, interactive) {
46386
46547
  function applyResolutionPreset(destDir, resolution) {
46387
46548
  const { width, height } = CANVAS_DIMENSIONS[resolution];
46388
46549
  for (const file of listHtmlFiles(destDir)) {
46389
- let html = readFileSync33(file, "utf-8");
46550
+ let html = readFileSync35(file, "utf-8");
46390
46551
  let changed = false;
46391
46552
  const dataWidthRe = /(data-width=)["'](\d+)["']/g;
46392
46553
  if (dataWidthRe.test(html)) {
@@ -46434,7 +46595,7 @@ function applyResolutionPreset(destDir, resolution) {
46434
46595
  async function scaffoldProject(destDir, name, templateId, localVideoName, durationSeconds, tailwind = false, resolution) {
46435
46596
  mkdirSync31(destDir, { recursive: true });
46436
46597
  const templateDir = getStaticTemplateDir(templateId);
46437
- if (existsSync49(join59(templateDir, "index.html"))) {
46598
+ if (existsSync50(join59(templateDir, "index.html"))) {
46438
46599
  cpSync4(templateDir, destDir, { recursive: true });
46439
46600
  } else {
46440
46601
  await fetchRemoteTemplate(templateId, destDir);
@@ -46455,13 +46616,13 @@ async function scaffoldProject(destDir, name, templateId, localVideoName, durati
46455
46616
  ),
46456
46617
  "utf-8"
46457
46618
  );
46458
- if (!existsSync49(resolve26(destDir, "hyperframes.json"))) {
46619
+ if (!existsSync50(resolve26(destDir, "hyperframes.json"))) {
46459
46620
  const { writeProjectConfig: writeProjectConfig2, DEFAULT_PROJECT_CONFIG: DEFAULT_PROJECT_CONFIG2 } = await Promise.resolve().then(() => (init_projectConfig(), projectConfig_exports));
46460
46621
  writeProjectConfig2(destDir, DEFAULT_PROJECT_CONFIG2);
46461
46622
  }
46462
46623
  writeDefaultPackageJson(destDir, name);
46463
46624
  const sharedDir = getSharedTemplateDir();
46464
- if (existsSync49(sharedDir)) {
46625
+ if (existsSync50(sharedDir)) {
46465
46626
  for (const entry of readdirSync21(sharedDir, { withFileTypes: true })) {
46466
46627
  const src = join59(sharedDir, entry.name);
46467
46628
  const dest = resolve26(destDir, entry.name);
@@ -46621,7 +46782,7 @@ var init_init = __esm({
46621
46782
  const templateId2 = exampleFlag ?? "blank";
46622
46783
  const name2 = args.name ?? "my-video";
46623
46784
  const destDir2 = resolve26(name2);
46624
- if (existsSync49(destDir2) && readdirSync21(destDir2).length > 0) {
46785
+ if (existsSync50(destDir2) && readdirSync21(destDir2).length > 0) {
46625
46786
  console.error(c2.error(`Directory already exists and is not empty: ${name2}`));
46626
46787
  process.exit(1);
46627
46788
  }
@@ -46635,7 +46796,7 @@ var init_init = __esm({
46635
46796
  }
46636
46797
  if (videoFlag) {
46637
46798
  const videoPath = resolve26(videoFlag);
46638
- if (!existsSync49(videoPath)) {
46799
+ if (!existsSync50(videoPath)) {
46639
46800
  console.error(c2.error(`Video file not found: ${videoFlag}`));
46640
46801
  process.exit(1);
46641
46802
  }
@@ -46649,7 +46810,7 @@ var init_init = __esm({
46649
46810
  }
46650
46811
  if (audioFlag) {
46651
46812
  const audioPath = resolve26(audioFlag);
46652
- if (!existsSync49(audioPath)) {
46813
+ if (!existsSync50(audioPath)) {
46653
46814
  console.error(c2.error(`Audio file not found: ${audioFlag}`));
46654
46815
  process.exit(1);
46655
46816
  }
@@ -46697,7 +46858,7 @@ var init_init = __esm({
46697
46858
  }
46698
46859
  trackInitTemplate(templateId2, { tailwind });
46699
46860
  const transcriptFile2 = resolve26(destDir2, "transcript.json");
46700
- if (existsSync49(transcriptFile2)) {
46861
+ if (existsSync50(transcriptFile2)) {
46701
46862
  await patchTranscript(destDir2, transcriptFile2);
46702
46863
  }
46703
46864
  console.log(c2.success(`Created ${c2.accent(name2 + "/")}`));
@@ -46752,7 +46913,7 @@ var init_init = __esm({
46752
46913
  name = nameResult;
46753
46914
  }
46754
46915
  const destDir = resolve26(name);
46755
- if (existsSync49(destDir) && readdirSync21(destDir).length > 0) {
46916
+ if (existsSync50(destDir) && readdirSync21(destDir).length > 0) {
46756
46917
  const overwrite = await ue({
46757
46918
  message: `Directory ${c2.accent(name)} already exists and is not empty. Overwrite?`,
46758
46919
  initialValue: false
@@ -46767,7 +46928,7 @@ var init_init = __esm({
46767
46928
  let videoDuration;
46768
46929
  if (videoFlag) {
46769
46930
  const videoPath = resolve26(videoFlag);
46770
- if (!existsSync49(videoPath)) {
46931
+ if (!existsSync50(videoPath)) {
46771
46932
  R2.error(`File not found: ${videoFlag}`);
46772
46933
  me("Setup cancelled.");
46773
46934
  process.exit(1);
@@ -46779,7 +46940,7 @@ var init_init = __esm({
46779
46940
  videoDuration = result.meta.durationSeconds;
46780
46941
  } else if (audioFlag) {
46781
46942
  const audioPath = resolve26(audioFlag);
46782
- if (!existsSync49(audioPath)) {
46943
+ if (!existsSync50(audioPath)) {
46783
46944
  R2.error(`File not found: ${audioFlag}`);
46784
46945
  me("Setup cancelled.");
46785
46946
  process.exit(1);
@@ -46880,7 +47041,7 @@ ${c2.dim("Use --example blank for offline use.")}`
46880
47041
  }
46881
47042
  trackInitTemplate(templateId, { tailwind });
46882
47043
  const transcriptFile = resolve26(destDir, "transcript.json");
46883
- if (existsSync49(transcriptFile)) {
47044
+ if (existsSync50(transcriptFile)) {
46884
47045
  await patchTranscript(destDir, transcriptFile);
46885
47046
  }
46886
47047
  const files = readdirSync21(destDir);
@@ -46912,9 +47073,9 @@ ${c2.dim("Use --example blank for offline use.")}`
46912
47073
 
46913
47074
  // src/utils/clipboard.ts
46914
47075
  import { spawnSync as spawnSync3 } from "child_process";
46915
- import { platform as platform4 } from "os";
47076
+ import { platform as platform6 } from "os";
46916
47077
  function detectProvider() {
46917
- const os = platform4();
47078
+ const os = platform6();
46918
47079
  if (os === "darwin") {
46919
47080
  return { cmd: "pbcopy", args: [] };
46920
47081
  }
@@ -46966,7 +47127,7 @@ __export(add_exports, {
46966
47127
  remapTarget: () => remapTarget,
46967
47128
  runAdd: () => runAdd
46968
47129
  });
46969
- import { existsSync as existsSync50 } from "fs";
47130
+ import { existsSync as existsSync51 } from "fs";
46970
47131
  import { resolve as resolve27, relative as relative7 } from "path";
46971
47132
  function remapTarget(item, originalTarget, paths) {
46972
47133
  if (item.type === "hyperframes:block") {
@@ -46992,8 +47153,8 @@ function buildSnippet(item, relativeTarget) {
46992
47153
  async function runAdd(opts) {
46993
47154
  const projectDir = resolve27(opts.projectDir);
46994
47155
  let config = loadProjectConfig(projectDir);
46995
- const hasConfig = existsSync50(projectConfigPath(projectDir));
46996
- if (!hasConfig && existsSync50(resolve27(projectDir, "index.html"))) {
47156
+ const hasConfig = existsSync51(projectConfigPath(projectDir));
47157
+ if (!hasConfig && existsSync51(resolve27(projectDir, "index.html"))) {
46997
47158
  writeProjectConfig(projectDir, DEFAULT_PROJECT_CONFIG);
46998
47159
  config = DEFAULT_PROJECT_CONFIG;
46999
47160
  }
@@ -47095,10 +47256,10 @@ var init_add = __esm({
47095
47256
  const projectDir = resolve27(args.dir ?? process.cwd());
47096
47257
  const json = args.json === true;
47097
47258
  const skipClipboard = args["no-clipboard"] === true;
47098
- const hasConfigBefore = existsSync50(projectConfigPath(projectDir));
47259
+ const hasConfigBefore = existsSync51(projectConfigPath(projectDir));
47099
47260
  try {
47100
47261
  const result = await runAdd({ name: args.name, projectDir, skipClipboard });
47101
- const wroteConfig = !hasConfigBefore && existsSync50(projectConfigPath(projectDir));
47262
+ const wroteConfig = !hasConfigBefore && existsSync51(projectConfigPath(projectDir));
47102
47263
  if (json) {
47103
47264
  console.log(JSON.stringify(result));
47104
47265
  return;
@@ -47128,7 +47289,7 @@ var init_add = __esm({
47128
47289
  process.exit(1);
47129
47290
  }
47130
47291
  let config = loadProjectConfig(projectDir);
47131
- if (!existsSync50(projectConfigPath(projectDir)) && existsSync50(resolve27(projectDir, "index.html"))) {
47292
+ if (!existsSync51(projectConfigPath(projectDir)) && existsSync51(resolve27(projectDir, "index.html"))) {
47132
47293
  writeProjectConfig(projectDir, DEFAULT_PROJECT_CONFIG);
47133
47294
  config = DEFAULT_PROJECT_CONFIG;
47134
47295
  }
@@ -47348,17 +47509,17 @@ var init_format = __esm({
47348
47509
  });
47349
47510
 
47350
47511
  // src/utils/project.ts
47351
- import { existsSync as existsSync51, statSync as statSync18 } from "fs";
47512
+ import { existsSync as existsSync52, statSync as statSync18 } from "fs";
47352
47513
  import { resolve as resolve29, basename as basename8 } from "path";
47353
47514
  function resolveProject(dirArg) {
47354
47515
  const dir = resolve29(dirArg ?? ".");
47355
47516
  const name = basename8(dir);
47356
47517
  const indexPath = resolve29(dir, "index.html");
47357
- if (!existsSync51(dir) || !statSync18(dir).isDirectory()) {
47518
+ if (!existsSync52(dir) || !statSync18(dir).isDirectory()) {
47358
47519
  errorBox("Not a directory: " + dir);
47359
47520
  process.exit(1);
47360
47521
  }
47361
- if (!existsSync51(indexPath)) {
47522
+ if (!existsSync52(indexPath)) {
47362
47523
  errorBox(
47363
47524
  "No composition found in " + dir,
47364
47525
  "No index.html file found.",
@@ -47381,7 +47542,7 @@ __export(play_exports, {
47381
47542
  default: () => play_default,
47382
47543
  examples: () => examples5
47383
47544
  });
47384
- import { existsSync as existsSync52, readFileSync as readFileSync34 } from "fs";
47545
+ import { existsSync as existsSync53, readFileSync as readFileSync36 } from "fs";
47385
47546
  import { resolve as resolve30, dirname as dirname21 } from "path";
47386
47547
  function commandDir() {
47387
47548
  return dirname21(new URL(import.meta.url).pathname);
@@ -47396,7 +47557,7 @@ function resolveRuntimePath2() {
47396
47557
  resolve30(d2, "..", "..", "..", "core", "dist", "hyperframe.runtime.iife.js")
47397
47558
  ];
47398
47559
  for (const p2 of candidates) {
47399
- if (existsSync52(p2)) return p2;
47560
+ if (existsSync53(p2)) return p2;
47400
47561
  }
47401
47562
  return null;
47402
47563
  }
@@ -47410,7 +47571,7 @@ function resolvePlayerPath() {
47410
47571
  resolve30(d2, "..", "hyperframes-player.global.js")
47411
47572
  ];
47412
47573
  for (const p2 of candidates) {
47413
- if (existsSync52(p2)) return p2;
47574
+ if (existsSync53(p2)) return p2;
47414
47575
  }
47415
47576
  return null;
47416
47577
  }
@@ -47520,13 +47681,13 @@ var init_play = __esm({
47520
47681
  const { createAdaptorServer } = await import("@hono/node-server");
47521
47682
  const app = new Hono6();
47522
47683
  app.get("/player.js", (ctx) => {
47523
- return ctx.body(readFileSync34(playerPath, "utf-8"), 200, {
47684
+ return ctx.body(readFileSync36(playerPath, "utf-8"), 200, {
47524
47685
  "Content-Type": "application/javascript",
47525
47686
  "Cache-Control": "no-cache"
47526
47687
  });
47527
47688
  });
47528
47689
  app.get("/runtime.js", (ctx) => {
47529
- return ctx.body(readFileSync34(runtimePath, "utf-8"), 200, {
47690
+ return ctx.body(readFileSync36(runtimePath, "utf-8"), 200, {
47530
47691
  "Content-Type": "application/javascript",
47531
47692
  "Cache-Control": "no-cache"
47532
47693
  });
@@ -47535,8 +47696,8 @@ var init_play = __esm({
47535
47696
  const reqPath = ctx.req.path.replace("/composition/", "");
47536
47697
  const filePath = resolve30(project.dir, reqPath);
47537
47698
  if (!filePath.startsWith(project.dir)) return ctx.text("Forbidden", 403);
47538
- if (!existsSync52(filePath)) return ctx.text("Not found", 404);
47539
- const content = readFileSync34(filePath, "utf-8");
47699
+ if (!existsSync53(filePath)) return ctx.text("Not found", 404);
47700
+ const content = readFileSync36(filePath, "utf-8");
47540
47701
  if (filePath.endsWith(".html")) {
47541
47702
  const injected = injectRuntime(content);
47542
47703
  return ctx.html(injected);
@@ -47555,7 +47716,7 @@ var init_play = __esm({
47555
47716
  mp3: "audio/mpeg",
47556
47717
  wav: "audio/wav"
47557
47718
  };
47558
- return ctx.body(readFileSync34(filePath), 200, {
47719
+ return ctx.body(readFileSync36(filePath), 200, {
47559
47720
  "Content-Type": types3[ext] ?? "application/octet-stream"
47560
47721
  });
47561
47722
  });
@@ -47616,7 +47777,7 @@ var init_play = __esm({
47616
47777
 
47617
47778
  // src/utils/publishProject.ts
47618
47779
  import { basename as basename9, join as join60, relative as relative8 } from "path";
47619
- import { readdirSync as readdirSync22, readFileSync as readFileSync35, statSync as statSync19 } from "fs";
47780
+ import { readdirSync as readdirSync22, readFileSync as readFileSync37, statSync as statSync19 } from "fs";
47620
47781
  import AdmZip from "adm-zip";
47621
47782
  function isRecord2(value) {
47622
47783
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -47735,7 +47896,7 @@ function createPublishArchive(projectDir) {
47735
47896
  }
47736
47897
  const archive = new AdmZip();
47737
47898
  for (const filePath of filePaths) {
47738
- archive.addFile(filePath, readFileSync35(join60(projectDir, filePath)));
47899
+ archive.addFile(filePath, readFileSync37(join60(projectDir, filePath)));
47739
47900
  }
47740
47901
  return {
47741
47902
  buffer: archive.toBuffer(),
@@ -47856,7 +48017,7 @@ __export(publish_exports, {
47856
48017
  examples: () => examples6
47857
48018
  });
47858
48019
  import { basename as basename10, resolve as resolve31 } from "path";
47859
- import { existsSync as existsSync53 } from "fs";
48020
+ import { existsSync as existsSync54 } from "fs";
47860
48021
  import { join as join61 } from "path";
47861
48022
  var examples6, publish_default;
47862
48023
  var init_publish = __esm({
@@ -47893,7 +48054,7 @@ var init_publish = __esm({
47893
48054
  const isImplicitCwd = !rawArg || rawArg === "." || rawArg === "./";
47894
48055
  const projectName = isImplicitCwd ? basename10(process.env["PWD"] ?? dir) : basename10(dir);
47895
48056
  const indexPath = join61(dir, "index.html");
47896
- if (existsSync53(indexPath)) {
48057
+ if (existsSync54(indexPath)) {
47897
48058
  const lintResult = lintProject({ dir, name: projectName, indexPath });
47898
48059
  if (lintResult.totalErrors > 0 || lintResult.totalWarnings > 0) {
47899
48060
  console.log();
@@ -47963,9 +48124,9 @@ var init_dom = __esm({
47963
48124
  });
47964
48125
 
47965
48126
  // src/utils/variables.ts
47966
- import { readFileSync as readFileSync36 } from "fs";
48127
+ import { readFileSync as readFileSync38 } from "fs";
47967
48128
  import { resolve as resolve32 } from "path";
47968
- function parseVariablesArg(inline, filePath, readFile = (p2) => readFileSync36(resolve32(p2), "utf8")) {
48129
+ function parseVariablesArg(inline, filePath, readFile = (p2) => readFileSync38(resolve32(p2), "utf8")) {
47969
48130
  if (inline != null && filePath != null) {
47970
48131
  return { ok: false, error: { kind: "conflict" } };
47971
48132
  }
@@ -48048,7 +48209,7 @@ function validateVariablesAgainstProject(indexPath, values) {
48048
48209
  function loadProjectVariableSchema(indexPath) {
48049
48210
  let html;
48050
48211
  try {
48051
- html = readFileSync36(indexPath, "utf8");
48212
+ html = readFileSync38(indexPath, "utf8");
48052
48213
  } catch {
48053
48214
  return [];
48054
48215
  }
@@ -48215,7 +48376,7 @@ __export(render_exports, {
48215
48376
  renderLocal: () => renderLocal,
48216
48377
  resolveBrowserGpuForCli: () => resolveBrowserGpuForCli
48217
48378
  });
48218
- import { mkdirSync as mkdirSync32, readdirSync as readdirSync23, readFileSync as readFileSync37, statSync as statSync20, writeFileSync as writeFileSync26, rmSync as rmSync14 } from "fs";
48379
+ import { mkdirSync as mkdirSync32, readdirSync as readdirSync23, readFileSync as readFileSync39, statSync as statSync20, writeFileSync as writeFileSync26, rmSync as rmSync14 } from "fs";
48219
48380
  import { cpus as cpus4, freemem as freemem4, tmpdir as tmpdir5 } from "os";
48220
48381
  import { resolve as resolve33, dirname as dirname22, join as join62, basename as basename11 } from "path";
48221
48382
  import { execFileSync as execFileSync6, spawn as spawn13 } from "child_process";
@@ -48276,7 +48437,7 @@ function ensureDockerImage(version, quiet) {
48276
48437
  const dockerfilePath = resolveDockerfilePath();
48277
48438
  const tmpDir = join62(tmpdir5(), `hyperframes-docker-${Date.now()}`);
48278
48439
  mkdirSync32(tmpDir, { recursive: true });
48279
- writeFileSync26(join62(tmpDir, "Dockerfile"), readFileSync37(dockerfilePath));
48440
+ writeFileSync26(join62(tmpDir, "Dockerfile"), readFileSync39(dockerfilePath));
48280
48441
  try {
48281
48442
  execFileSync6(
48282
48443
  "docker",
@@ -49135,7 +49296,7 @@ var init_lint3 = __esm({
49135
49296
 
49136
49297
  // src/utils/staticProjectServer.ts
49137
49298
  import { createServer } from "http";
49138
- import { existsSync as existsSync54, readFileSync as readFileSync38 } from "fs";
49299
+ import { existsSync as existsSync55, readFileSync as readFileSync40 } from "fs";
49139
49300
  import { isAbsolute as isAbsolute8, relative as relative9, resolve as resolve34 } from "path";
49140
49301
  async function serveStaticProjectHtml(projectDir, html, bindErrorMessage = "Failed to bind local HTTP server") {
49141
49302
  const server = createServer((req, res) => {
@@ -49152,9 +49313,9 @@ async function serveStaticProjectHtml(projectDir, html, bindErrorMessage = "Fail
49152
49313
  res.end();
49153
49314
  return;
49154
49315
  }
49155
- if (existsSync54(filePath)) {
49316
+ if (existsSync55(filePath)) {
49156
49317
  res.writeHead(200, { "Content-Type": getMimeType(filePath) });
49157
- res.end(readFileSync38(filePath));
49318
+ res.end(readFileSync40(filePath));
49158
49319
  return;
49159
49320
  }
49160
49321
  res.writeHead(404);
@@ -49330,7 +49491,7 @@ __export(layout_exports, {
49330
49491
  default: () => layout_default,
49331
49492
  examples: () => examples9
49332
49493
  });
49333
- import { existsSync as existsSync55, readFileSync as readFileSync39 } from "fs";
49494
+ import { existsSync as existsSync56, readFileSync as readFileSync41 } from "fs";
49334
49495
  import { dirname as dirname23, join as join63 } from "path";
49335
49496
  import { fileURLToPath as fileURLToPath8 } from "url";
49336
49497
  async function getCompositionDuration2(page) {
@@ -49481,7 +49642,7 @@ function loadLayoutAuditScript() {
49481
49642
  join63(__dirname2, "commands", "layout-audit.browser.js")
49482
49643
  ];
49483
49644
  for (const candidate of candidates) {
49484
- if (existsSync55(candidate)) return readFileSync39(candidate, "utf-8");
49645
+ if (existsSync56(candidate)) return readFileSync41(candidate, "utf-8");
49485
49646
  }
49486
49647
  throw new Error("Missing layout audit browser script");
49487
49648
  }
@@ -49689,7 +49850,7 @@ __export(info_exports, {
49689
49850
  default: () => info_default,
49690
49851
  examples: () => examples11
49691
49852
  });
49692
- import { readFileSync as readFileSync40, readdirSync as readdirSync24, statSync as statSync21 } from "fs";
49853
+ import { readFileSync as readFileSync42, readdirSync as readdirSync24, statSync as statSync21 } from "fs";
49693
49854
  import { join as join64 } from "path";
49694
49855
  function totalSize(dir) {
49695
49856
  let total = 0;
@@ -49726,7 +49887,7 @@ var init_info = __esm({
49726
49887
  },
49727
49888
  async run({ args }) {
49728
49889
  const project = resolveProject(args.dir);
49729
- const html = readFileSync40(project.indexPath, "utf-8");
49890
+ const html = readFileSync42(project.indexPath, "utf-8");
49730
49891
  ensureDOMParser();
49731
49892
  const parsed = parseHtml(html);
49732
49893
  const tracks = new Set(parsed.elements.map((el) => el.zIndex));
@@ -49784,7 +49945,7 @@ __export(compositions_exports, {
49784
49945
  examples: () => examples12,
49785
49946
  parseSubComposition: () => parseSubComposition
49786
49947
  });
49787
- import { existsSync as existsSync56, readFileSync as readFileSync41 } from "fs";
49948
+ import { existsSync as existsSync57, readFileSync as readFileSync43 } from "fs";
49788
49949
  import { resolve as resolve35, dirname as dirname24 } from "path";
49789
49950
  function countRenderableDescendants(root) {
49790
49951
  return Array.from(root.querySelectorAll("*")).filter(
@@ -49818,8 +49979,8 @@ function parseCompositions(html, baseDir) {
49818
49979
  const compositionSrc = div.getAttribute("data-composition-src");
49819
49980
  if (compositionSrc) {
49820
49981
  const subPath = resolve35(baseDir, compositionSrc);
49821
- if (existsSync56(subPath)) {
49822
- const subHtml = readFileSync41(subPath, "utf-8");
49982
+ if (existsSync57(subPath)) {
49983
+ const subHtml = readFileSync43(subPath, "utf-8");
49823
49984
  const subInfo = parseSubComposition(subHtml, id, width, height);
49824
49985
  compositions.push({ ...subInfo, source: compositionSrc });
49825
49986
  return;
@@ -49922,7 +50083,7 @@ var init_compositions = __esm({
49922
50083
  },
49923
50084
  async run({ args }) {
49924
50085
  const project = resolveProject(args.dir);
49925
- const html = readFileSync41(project.indexPath, "utf-8");
50086
+ const html = readFileSync43(project.indexPath, "utf-8");
49926
50087
  ensureDOMParser();
49927
50088
  const compositions = parseCompositions(html, dirname24(project.indexPath));
49928
50089
  if (compositions.length === 0) {
@@ -49960,7 +50121,7 @@ __export(benchmark_exports, {
49960
50121
  default: () => benchmark_default,
49961
50122
  examples: () => examples13
49962
50123
  });
49963
- import { existsSync as existsSync57, statSync as statSync22 } from "fs";
50124
+ import { existsSync as existsSync58, statSync as statSync22 } from "fs";
49964
50125
  import { resolve as resolve36, join as join65 } from "path";
49965
50126
  var examples13, FPS_30, FPS_60, DEFAULT_CONFIGS, benchmark_default;
49966
50127
  var init_benchmark = __esm({
@@ -50053,7 +50214,7 @@ var init_benchmark = __esm({
50053
50214
  await producer.executeRenderJob(job, project.dir, outputPath);
50054
50215
  const elapsedMs = Date.now() - startTime;
50055
50216
  let fileSize = null;
50056
- if (existsSync57(outputPath)) {
50217
+ if (existsSync58(outputPath)) {
50057
50218
  const stat3 = statSync22(outputPath);
50058
50219
  fileSize = stat3.size;
50059
50220
  }
@@ -50307,8 +50468,8 @@ __export(manager_exports3, {
50307
50468
  modelPath: () => modelPath,
50308
50469
  selectProviders: () => selectProviders
50309
50470
  });
50310
- import { existsSync as existsSync58, mkdirSync as mkdirSync33 } from "fs";
50311
- import { homedir as homedir9, platform as platform5, arch } from "os";
50471
+ import { existsSync as existsSync59, mkdirSync as mkdirSync33 } from "fs";
50472
+ import { homedir as homedir9, platform as platform7, arch } from "os";
50312
50473
  import { join as join66 } from "path";
50313
50474
  function isDevice(value) {
50314
50475
  return typeof value === "string" && DEVICES.includes(value);
@@ -50334,7 +50495,7 @@ function selectProviders(device = "auto") {
50334
50495
  }
50335
50496
  return { providers: ["cuda", "cpu"], label: "CUDA" };
50336
50497
  }
50337
- if (hasCoreML && platform5() === "darwin" && arch() === "arm64") {
50498
+ if (hasCoreML && platform7() === "darwin" && arch() === "arm64") {
50338
50499
  return { providers: ["coreml", "cpu"], label: "CoreML" };
50339
50500
  }
50340
50501
  if (hasCUDA) return { providers: ["cuda", "cpu"], label: "CUDA" };
@@ -50343,7 +50504,7 @@ function selectProviders(device = "auto") {
50343
50504
  function listAvailableProviders() {
50344
50505
  if (_cachedProviders) return _cachedProviders;
50345
50506
  const out = ["cpu"];
50346
- if (platform5() === "darwin" && arch() === "arm64") out.push("coreml");
50507
+ if (platform7() === "darwin" && arch() === "arm64") out.push("coreml");
50347
50508
  if (process.env["HYPERFRAMES_CUDA"] === "1") out.push("cuda");
50348
50509
  _cachedProviders = out;
50349
50510
  return out;
@@ -50353,11 +50514,11 @@ function modelPath(model = DEFAULT_MODEL2) {
50353
50514
  }
50354
50515
  async function ensureModel2(model = DEFAULT_MODEL2, options) {
50355
50516
  const dest = modelPath(model);
50356
- if (existsSync58(dest)) return dest;
50517
+ if (existsSync59(dest)) return dest;
50357
50518
  mkdirSync33(MODELS_DIR2, { recursive: true });
50358
50519
  options?.onProgress?.(`Downloading ${model} weights (~168 MB)...`);
50359
50520
  await downloadFile(MODEL_URLS[model], dest);
50360
- if (!existsSync58(dest)) {
50521
+ if (!existsSync59(dest)) {
50361
50522
  throw new Error(`Model download failed: ${model}`);
50362
50523
  }
50363
50524
  return dest;
@@ -50838,12 +50999,12 @@ __export(remove_background_exports, {
50838
50999
  examples: () => examples15
50839
51000
  });
50840
51001
  import { resolve as resolve37 } from "path";
50841
- import { existsSync as existsSync59 } from "fs";
51002
+ import { existsSync as existsSync60 } from "fs";
50842
51003
  async function showInfo(json) {
50843
51004
  const { selectProviders: selectProviders2, listAvailableProviders: listAvailableProviders2, DEFAULT_MODEL: DEFAULT_MODEL4, MODEL_MEMORY_MB: MODEL_MEMORY_MB2, modelPath: modelPath2 } = await Promise.resolve().then(() => (init_manager3(), manager_exports3));
50844
51005
  const providers = listAvailableProviders2();
50845
51006
  const auto = selectProviders2("auto");
50846
- const cached2 = existsSync59(modelPath2());
51007
+ const cached2 = existsSync60(modelPath2());
50847
51008
  if (json) {
50848
51009
  console.log(
50849
51010
  JSON.stringify({
@@ -51050,7 +51211,7 @@ __export(transcribe_exports2, {
51050
51211
  default: () => transcribe_default,
51051
51212
  examples: () => examples16
51052
51213
  });
51053
- import { existsSync as existsSync60, writeFileSync as writeFileSync27 } from "fs";
51214
+ import { existsSync as existsSync61, writeFileSync as writeFileSync27 } from "fs";
51054
51215
  import { resolve as resolve38, join as join67, extname as extname11, dirname as dirname25 } from "path";
51055
51216
  async function importTranscript(inputPath, dir, json) {
51056
51217
  const { loadTranscript: loadTranscript2, patchCaptionHtml: patchCaptionHtml2 } = await Promise.resolve().then(() => (init_normalize(), normalize_exports));
@@ -51176,7 +51337,7 @@ var init_transcribe2 = __esm({
51176
51337
  },
51177
51338
  async run({ args }) {
51178
51339
  const inputPath = resolve38(args.input);
51179
- if (!existsSync60(inputPath)) {
51340
+ if (!existsSync61(inputPath)) {
51180
51341
  console.error(c2.error(`File not found: ${args.input}`));
51181
51342
  process.exit(1);
51182
51343
  }
@@ -51197,7 +51358,7 @@ var init_transcribe2 = __esm({
51197
51358
  });
51198
51359
 
51199
51360
  // src/tts/manager.ts
51200
- import { existsSync as existsSync61, mkdirSync as mkdirSync34 } from "fs";
51361
+ import { existsSync as existsSync62, mkdirSync as mkdirSync34 } from "fs";
51201
51362
  import { homedir as homedir10 } from "os";
51202
51363
  import { join as join68 } from "path";
51203
51364
  function inferLangFromVoiceId(voiceId) {
@@ -51209,7 +51370,7 @@ function isSupportedLang(value) {
51209
51370
  }
51210
51371
  async function ensureModel3(model = DEFAULT_MODEL3, options) {
51211
51372
  const modelPath2 = join68(MODELS_DIR3, `${model}.onnx`);
51212
- if (existsSync61(modelPath2)) return modelPath2;
51373
+ if (existsSync62(modelPath2)) return modelPath2;
51213
51374
  const url = MODEL_URLS2[model];
51214
51375
  if (!url) {
51215
51376
  throw new Error(
@@ -51219,18 +51380,18 @@ async function ensureModel3(model = DEFAULT_MODEL3, options) {
51219
51380
  mkdirSync34(MODELS_DIR3, { recursive: true });
51220
51381
  options?.onProgress?.(`Downloading TTS model ${model} (~311 MB)...`);
51221
51382
  await downloadFile(url, modelPath2);
51222
- if (!existsSync61(modelPath2)) {
51383
+ if (!existsSync62(modelPath2)) {
51223
51384
  throw new Error(`Model download failed: ${model}`);
51224
51385
  }
51225
51386
  return modelPath2;
51226
51387
  }
51227
51388
  async function ensureVoices(options) {
51228
51389
  const voicesPath = join68(VOICES_DIR, "voices-v1.0.bin");
51229
- if (existsSync61(voicesPath)) return voicesPath;
51390
+ if (existsSync62(voicesPath)) return voicesPath;
51230
51391
  mkdirSync34(VOICES_DIR, { recursive: true });
51231
51392
  options?.onProgress?.("Downloading voice data (~27 MB)...");
51232
51393
  await downloadFile(VOICES_URL, voicesPath);
51233
- if (!existsSync61(voicesPath)) {
51394
+ if (!existsSync62(voicesPath)) {
51234
51395
  throw new Error("Voice data download failed");
51235
51396
  }
51236
51397
  return voicesPath;
@@ -51303,7 +51464,7 @@ __export(synthesize_exports, {
51303
51464
  synthesize: () => synthesize
51304
51465
  });
51305
51466
  import { execFileSync as execFileSync7 } from "child_process";
51306
- import { existsSync as existsSync62, writeFileSync as writeFileSync28, mkdirSync as mkdirSync35, readdirSync as readdirSync25, unlinkSync as unlinkSync6 } from "fs";
51467
+ import { existsSync as existsSync63, writeFileSync as writeFileSync28, mkdirSync as mkdirSync35, readdirSync as readdirSync25, unlinkSync as unlinkSync6 } from "fs";
51307
51468
  import { join as join69, dirname as dirname26, basename as basename12 } from "path";
51308
51469
  import { homedir as homedir11 } from "os";
51309
51470
  function findPython() {
@@ -51340,7 +51501,7 @@ function hasPythonPackage(python, pkg) {
51340
51501
  }
51341
51502
  }
51342
51503
  function ensureSynthScript() {
51343
- if (!existsSync62(SCRIPT_PATH)) {
51504
+ if (!existsSync63(SCRIPT_PATH)) {
51344
51505
  mkdirSync35(SCRIPT_DIR, { recursive: true });
51345
51506
  writeFileSync28(SCRIPT_PATH, SYNTH_SCRIPT);
51346
51507
  const currentName = basename12(SCRIPT_PATH);
@@ -51394,7 +51555,7 @@ async function synthesize(text, outputPath, options) {
51394
51555
  stdio: ["pipe", "pipe", "pipe"]
51395
51556
  }
51396
51557
  );
51397
- if (!existsSync62(outputPath)) {
51558
+ if (!existsSync63(outputPath)) {
51398
51559
  throw new Error("Synthesis completed but no output file was created");
51399
51560
  }
51400
51561
  const lines = stdout2.trim().split("\n");
@@ -51407,7 +51568,7 @@ async function synthesize(text, outputPath, options) {
51407
51568
  langApplied: result.langApplied
51408
51569
  };
51409
51570
  } catch (err) {
51410
- if (err instanceof SyntaxError && existsSync62(outputPath)) {
51571
+ if (err instanceof SyntaxError && existsSync63(outputPath)) {
51411
51572
  throw new Error(
51412
51573
  "Speech was generated but metadata could not be read. Check the output file manually."
51413
51574
  );
@@ -51469,7 +51630,7 @@ __export(tts_exports, {
51469
51630
  default: () => tts_default,
51470
51631
  examples: () => examples17
51471
51632
  });
51472
- import { existsSync as existsSync63, readFileSync as readFileSync42 } from "fs";
51633
+ import { existsSync as existsSync64, readFileSync as readFileSync44 } from "fs";
51473
51634
  import { resolve as resolve39, extname as extname12 } from "path";
51474
51635
  function listVoices(json) {
51475
51636
  const rows = BUNDLED_VOICES.map((v2) => ({ ...v2, defaultLang: inferLangFromVoiceId(v2.id) }));
@@ -51579,8 +51740,8 @@ var init_tts = __esm({
51579
51740
  }
51580
51741
  let text;
51581
51742
  const maybeFile = resolve39(args.input);
51582
- if (existsSync63(maybeFile) && extname12(maybeFile).toLowerCase() === ".txt") {
51583
- text = readFileSync42(maybeFile, "utf-8").trim();
51743
+ if (existsSync64(maybeFile) && extname12(maybeFile).toLowerCase() === ".txt") {
51744
+ text = readFileSync44(maybeFile, "utf-8").trim();
51584
51745
  if (!text) {
51585
51746
  console.error(c2.error("File is empty."));
51586
51747
  process.exit(1);
@@ -51672,7 +51833,7 @@ __export(docs_exports, {
51672
51833
  default: () => docs_default,
51673
51834
  examples: () => examples18
51674
51835
  });
51675
- import { readFileSync as readFileSync43, existsSync as existsSync64 } from "fs";
51836
+ import { readFileSync as readFileSync45, existsSync as existsSync65 } from "fs";
51676
51837
  import { resolve as resolve40, dirname as dirname27, join as join70 } from "path";
51677
51838
  import { fileURLToPath as fileURLToPath9 } from "url";
51678
51839
  function docsDir() {
@@ -51680,7 +51841,7 @@ function docsDir() {
51680
51841
  const dir = dirname27(thisFile);
51681
51842
  const devPath = resolve40(dir, "..", "docs");
51682
51843
  const builtPath = resolve40(dir, "docs");
51683
- return existsSync64(devPath) ? devPath : builtPath;
51844
+ return existsSync65(devPath) ? devPath : builtPath;
51684
51845
  }
51685
51846
  function formatInlineCode(line) {
51686
51847
  return line.replace(/`([^`]+)`/g, (_match, code) => c2.accent(code));
@@ -51778,11 +51939,11 @@ var init_docs = __esm({
51778
51939
  process.exit(1);
51779
51940
  }
51780
51941
  const filePath = join70(docsDir(), entry.file);
51781
- if (!existsSync64(filePath)) {
51942
+ if (!existsSync65(filePath)) {
51782
51943
  console.error(c2.error(`Doc file not found: ${filePath}`));
51783
51944
  process.exit(1);
51784
51945
  }
51785
- const content = readFileSync43(filePath, "utf-8");
51946
+ const content = readFileSync45(filePath, "utf-8");
51786
51947
  console.log();
51787
51948
  renderMarkdown(content);
51788
51949
  }
@@ -51799,7 +51960,7 @@ __export(doctor_exports, {
51799
51960
  redactHome: () => redactHome
51800
51961
  });
51801
51962
  import { execSync as execSync3 } from "child_process";
51802
- import { freemem as freemem5, platform as platform6 } from "os";
51963
+ import { freemem as freemem5, platform as platform8 } from "os";
51803
51964
  function checkFFmpeg() {
51804
51965
  const path2 = findFFmpeg();
51805
51966
  if (path2) {
@@ -51988,7 +52149,7 @@ var init_doctor = __esm({
51988
52149
  { name: "Memory", run: checkMemory },
51989
52150
  { name: "Disk", run: checkDisk }
51990
52151
  ];
51991
- if (platform6() === "linux") {
52152
+ if (platform8() === "linux") {
51992
52153
  checks.push({ name: "/dev/shm", run: checkShm });
51993
52154
  }
51994
52155
  checks.push(
@@ -52246,16 +52407,18 @@ function parseViewportDimension(value) {
52246
52407
  if (!Number.isFinite(parsed) || parsed <= 0) return null;
52247
52408
  return Math.min(parsed, MAX_VIEWPORT_DIMENSION);
52248
52409
  }
52249
- function resolveCompositionViewportFromHtml(html) {
52410
+ function findCompositionDimensions(html) {
52250
52411
  ensureDOMParser();
52251
52412
  const doc = new DOMParser().parseFromString(html, "text/html");
52252
52413
  const root = doc.querySelector("[data-composition-id][data-width][data-height]");
52253
- const width = parseViewportDimension(root?.getAttribute("data-width") ?? null);
52254
- const height = parseViewportDimension(root?.getAttribute("data-height") ?? null);
52255
- return {
52256
- width: width ?? DEFAULT_VIEWPORT.width,
52257
- height: height ?? DEFAULT_VIEWPORT.height
52258
- };
52414
+ if (!root) return null;
52415
+ const width = parseViewportDimension(root.getAttribute("data-width"));
52416
+ const height = parseViewportDimension(root.getAttribute("data-height"));
52417
+ if (width === null || height === null) return null;
52418
+ return { width, height };
52419
+ }
52420
+ function resolveCompositionViewportFromHtml(html) {
52421
+ return findCompositionDimensions(html) ?? DEFAULT_VIEWPORT;
52259
52422
  }
52260
52423
  var DEFAULT_VIEWPORT, MAX_VIEWPORT_DIMENSION;
52261
52424
  var init_compositionViewport = __esm({
@@ -52273,7 +52436,7 @@ __export(validate_exports, {
52273
52436
  default: () => validate_default,
52274
52437
  shouldIgnoreRequestFailure: () => shouldIgnoreRequestFailure
52275
52438
  });
52276
- import { existsSync as existsSync65, readFileSync as readFileSync44 } from "fs";
52439
+ import { existsSync as existsSync66, readFileSync as readFileSync46 } from "fs";
52277
52440
  import { join as join71, dirname as dirname28 } from "path";
52278
52441
  import { fileURLToPath as fileURLToPath10 } from "url";
52279
52442
  function shouldIgnoreRequestFailure(url, errorText) {
@@ -52330,7 +52493,7 @@ function loadContrastAuditScript() {
52330
52493
  join71(__dirname3, "commands", "contrast-audit.browser.js")
52331
52494
  ];
52332
52495
  for (const candidate of candidates) {
52333
- if (existsSync65(candidate)) return readFileSync44(candidate, "utf-8");
52496
+ if (existsSync66(candidate)) return readFileSync46(candidate, "utf-8");
52334
52497
  }
52335
52498
  throw new Error("Missing contrast audit browser script");
52336
52499
  }
@@ -52348,9 +52511,9 @@ async function validateInBrowser(projectDir, opts) {
52348
52511
  return;
52349
52512
  }
52350
52513
  const filePath = join71(projectDir, decodeURIComponent(url));
52351
- if (existsSync65(filePath)) {
52514
+ if (existsSync66(filePath)) {
52352
52515
  res.writeHead(200, { "Content-Type": getMimeType2(filePath) });
52353
- res.end(readFileSync44(filePath));
52516
+ res.end(readFileSync46(filePath));
52354
52517
  return;
52355
52518
  }
52356
52519
  res.writeHead(404);
@@ -52552,7 +52715,7 @@ __export(contactSheet_exports, {
52552
52715
  createSvgContactSheet: () => createSvgContactSheet
52553
52716
  });
52554
52717
  import sharp from "sharp";
52555
- import { readdirSync as readdirSync26, readFileSync as readFileSync45, writeFileSync as writeFileSync29, unlinkSync as unlinkSync7, existsSync as existsSync66 } from "fs";
52718
+ import { readdirSync as readdirSync26, readFileSync as readFileSync47, writeFileSync as writeFileSync29, unlinkSync as unlinkSync7, existsSync as existsSync67 } from "fs";
52556
52719
  import { join as join72, extname as extname13, basename as basename13, dirname as dirname29 } from "path";
52557
52720
  async function createContactSheet(imagePaths, outputPath, opts = {}) {
52558
52721
  const {
@@ -52632,7 +52795,7 @@ async function createContactSheetPages(imagePaths, outputBasePath, opts = {}, la
52632
52795
  return results;
52633
52796
  }
52634
52797
  async function createScrollContactSheet(screenshotsDir, outputPath) {
52635
- if (!existsSync66(screenshotsDir)) return [];
52798
+ if (!existsSync67(screenshotsDir)) return [];
52636
52799
  const scrollFiles = readdirSync26(screenshotsDir).filter((f3) => f3.startsWith("scroll-") && f3.endsWith(".png")).sort();
52637
52800
  if (scrollFiles.length === 0) return [];
52638
52801
  const paths = scrollFiles.map((f3) => join72(screenshotsDir, f3));
@@ -52649,7 +52812,7 @@ async function createScrollContactSheet(screenshotsDir, outputPath) {
52649
52812
  );
52650
52813
  }
52651
52814
  async function createSnapshotContactSheet(snapshotsDir, outputPath) {
52652
- if (!existsSync66(snapshotsDir)) return [];
52815
+ if (!existsSync67(snapshotsDir)) return [];
52653
52816
  const snapshotFiles = readdirSync26(snapshotsDir).filter((f3) => f3.startsWith("frame-") && f3.endsWith(".png")).sort();
52654
52817
  if (snapshotFiles.length === 0) return [];
52655
52818
  const paths = snapshotFiles.map((f3) => join72(snapshotsDir, f3));
@@ -52666,7 +52829,7 @@ async function createSnapshotContactSheet(snapshotsDir, outputPath) {
52666
52829
  );
52667
52830
  }
52668
52831
  async function createAssetContactSheet(assetsDir, outputPath) {
52669
- if (!existsSync66(assetsDir)) return [];
52832
+ if (!existsSync67(assetsDir)) return [];
52670
52833
  const imageExts = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".webp"]);
52671
52834
  const assetFiles = readdirSync26(assetsDir).filter((f3) => imageExts.has(extname13(f3).toLowerCase()) && !f3.includes("contact-sheet")).sort();
52672
52835
  if (assetFiles.length === 0) return [];
@@ -52680,7 +52843,7 @@ async function createAssetContactSheet(assetsDir, outputPath) {
52680
52843
  }
52681
52844
  async function createSvgContactSheet(svgsDir, outputPath, assetsRootDir) {
52682
52845
  const dirsToScan = [svgsDir, assetsRootDir].filter(
52683
- (d2) => d2 !== void 0 && existsSync66(d2)
52846
+ (d2) => d2 !== void 0 && existsSync67(d2)
52684
52847
  );
52685
52848
  if (dirsToScan.length === 0) return [];
52686
52849
  const seen = /* @__PURE__ */ new Set();
@@ -52703,7 +52866,7 @@ async function createSvgContactSheet(svgsDir, outputPath, assetsRootDir) {
52703
52866
  const svgPath = svgPaths[i2];
52704
52867
  const tmpPath = join72(tmpDir, `.thumb-${i2}.png`);
52705
52868
  try {
52706
- const svgBuf = readFileSync45(svgPath);
52869
+ const svgBuf = readFileSync47(svgPath);
52707
52870
  const thumb = await sharp(svgBuf).resize(thumbSize, thumbSize, {
52708
52871
  fit: "contain",
52709
52872
  background: { r: 245, g: 245, b: 245, alpha: 1 }
@@ -93261,7 +93424,7 @@ __export(snapshot_exports, {
93261
93424
  examples: () => examples22
93262
93425
  });
93263
93426
  import { spawn as spawn15 } from "child_process";
93264
- import { existsSync as existsSync67, mkdtempSync as mkdtempSync3, readFileSync as readFileSync46, mkdirSync as mkdirSync36, rmSync as rmSync15, writeFileSync as writeFileSync30 } from "fs";
93427
+ import { existsSync as existsSync68, mkdtempSync as mkdtempSync3, readFileSync as readFileSync48, mkdirSync as mkdirSync36, rmSync as rmSync15, writeFileSync as writeFileSync30 } from "fs";
93265
93428
  import { tmpdir as tmpdir6 } from "os";
93266
93429
  import { resolve as resolve41, join as join73, relative as relative10, isAbsolute as isAbsolute9 } from "path";
93267
93430
  async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDecoder = false) {
@@ -93306,8 +93469,8 @@ async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDeco
93306
93469
  });
93307
93470
  }
93308
93471
  );
93309
- if (result.code !== 0 || result.timedOut || !existsSync67(outPath)) return null;
93310
- return readFileSync46(outPath);
93472
+ if (result.code !== 0 || result.timedOut || !existsSync68(outPath)) return null;
93473
+ return readFileSync48(outPath);
93311
93474
  } finally {
93312
93475
  try {
93313
93476
  rmSync15(tmp, { recursive: true, force: true });
@@ -93505,7 +93668,7 @@ async function captureSnapshots(projectDir, opts) {
93505
93668
  const decodedPath = decodeURIComponent(url.pathname).replace(/^\//, "");
93506
93669
  const candidate = resolve41(projectDir, decodedPath);
93507
93670
  const rel = relative10(projectDir, candidate);
93508
- if (!rel.startsWith("..") && !isAbsolute9(rel) && existsSync67(candidate)) {
93671
+ if (!rel.startsWith("..") && !isAbsolute9(rel) && existsSync68(candidate)) {
93509
93672
  filePath = candidate;
93510
93673
  }
93511
93674
  } catch {
@@ -93656,8 +93819,8 @@ ${c2.success("\u25C7")} ${paths.length} snapshots saved to snapshots/`);
93656
93819
  paths.map(async (p2) => {
93657
93820
  const filename = p2.replace("snapshots/", "");
93658
93821
  const filePath = join73(snapshotDir, filename);
93659
- if (!existsSync67(filePath)) return { filename, desc: "file not found" };
93660
- const raw = readFileSync46(filePath);
93822
+ if (!existsSync68(filePath)) return { filename, desc: "file not found" };
93823
+ const raw = readFileSync48(filePath);
93661
93824
  let imageData;
93662
93825
  let mimeType = "image/png";
93663
93826
  if (sharpFn) {
@@ -94851,7 +95014,7 @@ var init_designStyleExtractor = __esm({
94851
95014
  });
94852
95015
 
94853
95016
  // src/capture/fontMetadataExtractor.ts
94854
- import { readdirSync as readdirSync27, readFileSync as readFileSync47, writeFileSync as writeFileSync32, existsSync as existsSync68 } from "fs";
95017
+ import { readdirSync as readdirSync27, readFileSync as readFileSync49, writeFileSync as writeFileSync32, existsSync as existsSync69 } from "fs";
94855
95018
  import { join as join75 } from "path";
94856
95019
  import * as fontkit from "fontkit";
94857
95020
  function isFontCollection(value) {
@@ -94860,7 +95023,7 @@ function isFontCollection(value) {
94860
95023
  function extractFontMetadata(fontsDir, outputPath) {
94861
95024
  const files = [];
94862
95025
  const unidentified = [];
94863
- if (existsSync68(fontsDir)) {
95026
+ if (existsSync69(fontsDir)) {
94864
95027
  const fontFiles = readdirSync27(fontsDir).filter((f3) => /\.(woff2?|ttf|otf)$/i.test(f3));
94865
95028
  for (const filename of fontFiles) {
94866
95029
  const fullPath = join75(fontsDir, filename);
@@ -94901,7 +95064,7 @@ function readSingleFont(fullPath, filename) {
94901
95064
  identified: false
94902
95065
  };
94903
95066
  try {
94904
- const buf = readFileSync47(fullPath);
95067
+ const buf = readFileSync49(fullPath);
94905
95068
  const created = fontkit.create(buf);
94906
95069
  const font = isFontCollection(created) ? created.fonts[0] : created;
94907
95070
  if (!font) return empty;
@@ -95157,7 +95320,7 @@ var init_animationCataloger = __esm({
95157
95320
  });
95158
95321
 
95159
95322
  // src/capture/mediaCapture.ts
95160
- import { mkdirSync as mkdirSync38, writeFileSync as writeFileSync33, readdirSync as readdirSync28, readFileSync as readFileSync48, statSync as statSync24 } from "fs";
95323
+ import { mkdirSync as mkdirSync38, writeFileSync as writeFileSync33, readdirSync as readdirSync28, readFileSync as readFileSync50, statSync as statSync24 } from "fs";
95161
95324
  import { join as join76 } from "path";
95162
95325
  async function saveLottieAnimations(discoveredLotties, lottieDir) {
95163
95326
  let savedCount = 0;
@@ -95224,7 +95387,7 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
95224
95387
  for (const file of readdirSync28(lottieDir)) {
95225
95388
  if (!file.endsWith(".json")) continue;
95226
95389
  try {
95227
- const raw = JSON.parse(readFileSync48(join76(lottieDir, file), "utf-8"));
95390
+ const raw = JSON.parse(readFileSync50(join76(lottieDir, file), "utf-8"));
95228
95391
  const fr = raw.fr || 30;
95229
95392
  const dur = ((raw.op || 0) - (raw.ip || 0)) / fr;
95230
95393
  const previewName = file.replace(".json", "-preview.png");
@@ -95234,7 +95397,7 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
95234
95397
  try {
95235
95398
  previewPage = await chromeBrowser.newPage();
95236
95399
  await previewPage.setViewport({ width: 400, height: 400 });
95237
- const animData = JSON.parse(readFileSync48(join76(lottieDir, file), "utf-8"));
95400
+ const animData = JSON.parse(readFileSync50(join76(lottieDir, file), "utf-8"));
95238
95401
  const midFrame = Math.floor(((raw.op || 0) - (raw.ip || 0)) * 0.3);
95239
95402
  await previewPage.setContent(
95240
95403
  `<!DOCTYPE html>
@@ -95413,7 +95576,7 @@ var init_mediaCapture = __esm({
95413
95576
  });
95414
95577
 
95415
95578
  // src/capture/contentExtractor.ts
95416
- import { existsSync as existsSync69, readdirSync as readdirSync29, statSync as statSync25, readFileSync as readFileSync49 } from "fs";
95579
+ import { existsSync as existsSync70, readdirSync as readdirSync29, statSync as statSync25, readFileSync as readFileSync51 } from "fs";
95417
95580
  import { join as join77 } from "path";
95418
95581
  async function detectLibraries(page, capturedShaders) {
95419
95582
  let detectedLibraries = [];
@@ -95546,7 +95709,7 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
95546
95709
  const filePath = join77(outputDir, "assets", file);
95547
95710
  const stat3 = statSync25(filePath);
95548
95711
  if (stat3.size > 4e6) return { file, caption: "" };
95549
- const buffer = readFileSync49(filePath);
95712
+ const buffer = readFileSync51(filePath);
95550
95713
  const base64 = buffer.toString("base64");
95551
95714
  const ext = file.split(".").pop()?.toLowerCase() || "png";
95552
95715
  const mimeType = ext === "jpg" ? "image/jpeg" : `image/${ext}`;
@@ -95588,7 +95751,7 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
95588
95751
  if (/\.svg$/i.test(f3)) svgFiles.push({ file: f3, relPath: f3 });
95589
95752
  }
95590
95753
  const svgsSubdir = join77(assetsDir, "svgs");
95591
- if (existsSync69(svgsSubdir)) {
95754
+ if (existsSync70(svgsSubdir)) {
95592
95755
  for (const f3 of readdirSync29(svgsSubdir)) {
95593
95756
  if (/\.svg$/i.test(f3)) svgFiles.push({ file: f3, relPath: `svgs/${f3}` });
95594
95757
  }
@@ -95602,7 +95765,7 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
95602
95765
  const results = await Promise.allSettled(
95603
95766
  batch.map(async ({ relPath }) => {
95604
95767
  const filePath = join77(assetsDir, relPath);
95605
- let svgText = readFileSync49(filePath, "utf-8");
95768
+ let svgText = readFileSync51(filePath, "utf-8");
95606
95769
  if (svgText.length > MAX_SVG_CHARS) {
95607
95770
  svgText = svgText.slice(0, MAX_SVG_CHARS) + "\n<!-- truncated -->";
95608
95771
  }
@@ -95720,7 +95883,7 @@ var agentPromptGenerator_exports = {};
95720
95883
  __export(agentPromptGenerator_exports, {
95721
95884
  generateAgentPrompt: () => generateAgentPrompt
95722
95885
  });
95723
- import { writeFileSync as writeFileSync34, readdirSync as readdirSync30, existsSync as existsSync70 } from "fs";
95886
+ import { writeFileSync as writeFileSync34, readdirSync as readdirSync30, existsSync as existsSync71 } from "fs";
95724
95887
  import { join as join78 } from "path";
95725
95888
  function inferColorRole(hex) {
95726
95889
  const r2 = parseInt(hex.slice(1, 3), 16) / 255;
@@ -95752,7 +95915,7 @@ function buildPrompt(outputDir, url, tokens, hasScreenshot, hasLottie, hasShader
95752
95915
  ).join(", ") || "none detected";
95753
95916
  function contactSheetRows(dir, baseFile, label2) {
95754
95917
  const fullDir = join78(outputDir, dir);
95755
- if (!existsSync70(fullDir)) return [];
95918
+ if (!existsSync71(fullDir)) return [];
95756
95919
  const baseName = baseFile.replace(/\.jpg$/, "");
95757
95920
  const escapedBase = baseName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
95758
95921
  const paginatedRe = new RegExp(`^${escapedBase}(?:-(\\d+))?\\.jpg$`);
@@ -95784,7 +95947,7 @@ function buildPrompt(outputDir, url, tokens, hasScreenshot, hasLottie, hasShader
95784
95947
  tableRows.push(
95785
95948
  `| \`extracted/tokens.json\` | Design tokens: ${tokens.colors.length} colors, ${tokens.fonts.length} fonts, ${tokens.headings?.length ?? 0} headings, ${tokens.ctas?.length ?? 0} CTAs |`
95786
95949
  );
95787
- if (existsSync70(join78(outputDir, "extracted", "design-styles.json"))) {
95950
+ if (existsSync71(join78(outputDir, "extracted", "design-styles.json"))) {
95788
95951
  tableRows.push(
95789
95952
  "| `extracted/design-styles.json` | Computed styles from live DOM: typography hierarchy, button/card/nav styles, spacing scale, border-radius, box shadows. Primary data source for DESIGN.md. |"
95790
95953
  );
@@ -95855,7 +96018,7 @@ var init_agentPromptGenerator = __esm({
95855
96018
  });
95856
96019
 
95857
96020
  // src/capture/scaffolding.ts
95858
- import { existsSync as existsSync71, writeFileSync as writeFileSync35, readFileSync as readFileSync50 } from "fs";
96021
+ import { existsSync as existsSync72, writeFileSync as writeFileSync35, readFileSync as readFileSync52 } from "fs";
95859
96022
  import { join as join79, resolve as resolve42 } from "path";
95860
96023
  function loadEnvFile(startDir) {
95861
96024
  try {
@@ -95863,7 +96026,7 @@ function loadEnvFile(startDir) {
95863
96026
  for (let i2 = 0; i2 < 5; i2++) {
95864
96027
  const envPath = resolve42(dir, ".env");
95865
96028
  try {
95866
- const envContent = readFileSync50(envPath, "utf-8");
96029
+ const envContent = readFileSync52(envPath, "utf-8");
95867
96030
  for (const line of envContent.split("\n")) {
95868
96031
  const trimmed = line.trim();
95869
96032
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -95883,7 +96046,7 @@ function loadEnvFile(startDir) {
95883
96046
  }
95884
96047
  async function generateProjectScaffold(outputDir, url, tokens, animationCatalog, hasScreenshots, hasLotties, hasShaders, catalogedAssets, progress, warnings, detectedLibraries) {
95885
96048
  const metaPath = join79(outputDir, "meta.json");
95886
- if (!existsSync71(metaPath)) {
96049
+ if (!existsSync72(metaPath)) {
95887
96050
  const hostname = new URL(url).hostname.replace(/^www\./, "");
95888
96051
  writeFileSync35(
95889
96052
  metaPath,
@@ -96290,7 +96453,7 @@ var capture_exports = {};
96290
96453
  __export(capture_exports, {
96291
96454
  captureWebsite: () => captureWebsite
96292
96455
  });
96293
- import { mkdirSync as mkdirSync40, writeFileSync as writeFileSync37, existsSync as existsSync72 } from "fs";
96456
+ import { mkdirSync as mkdirSync40, writeFileSync as writeFileSync37, existsSync as existsSync73 } from "fs";
96294
96457
  import { join as join81 } from "path";
96295
96458
  async function captureWebsite(opts, onProgress) {
96296
96459
  const {
@@ -96653,7 +96816,7 @@ ${err.stack}` : String(err);
96653
96816
  `Screenshot contact sheet generated (${scrollSheets.length} page${scrollSheets.length > 1 ? "s" : ""})`
96654
96817
  );
96655
96818
  const assetsImgDir = join81(outputDir, "assets");
96656
- if (existsSync72(assetsImgDir)) {
96819
+ if (existsSync73(assetsImgDir)) {
96657
96820
  const assetSheets = await createAssetContactSheet2(
96658
96821
  assetsImgDir,
96659
96822
  join81(outputDir, "assets", "contact-sheet.jpg")
@@ -96666,7 +96829,7 @@ ${err.stack}` : String(err);
96666
96829
  }
96667
96830
  const svgsDir = join81(outputDir, "assets", "svgs");
96668
96831
  const assetsRootDir = join81(outputDir, "assets");
96669
- const svgOutputPath = existsSync72(svgsDir) ? join81(outputDir, "assets", "svgs", "contact-sheet.jpg") : join81(outputDir, "assets", "contact-sheet-svgs.jpg");
96832
+ const svgOutputPath = existsSync73(svgsDir) ? join81(outputDir, "assets", "svgs", "contact-sheet.jpg") : join81(outputDir, "assets", "contact-sheet-svgs.jpg");
96670
96833
  const svgSheets = await createSvgContactSheet2(svgsDir, svgOutputPath, assetsRootDir);
96671
96834
  if (svgSheets.length > 0)
96672
96835
  progress(
@@ -96682,7 +96845,7 @@ ${err.stack}` : String(err);
96682
96845
  animationCatalog,
96683
96846
  screenshots.length > 0,
96684
96847
  discoveredLotties.length > 0,
96685
- existsSync72(join81(outputDir, "extracted", "shaders.json")),
96848
+ existsSync73(join81(outputDir, "extracted", "shaders.json")),
96686
96849
  catalogedAssets,
96687
96850
  progress,
96688
96851
  warnings,
@@ -96910,7 +97073,7 @@ __export(state_exports, {
96910
97073
  stateFilePath: () => stateFilePath,
96911
97074
  writeStackOutputs: () => writeStackOutputs
96912
97075
  });
96913
- import { existsSync as existsSync73, mkdirSync as mkdirSync41, readdirSync as readdirSync31, readFileSync as readFileSync51, rmSync as rmSync16, writeFileSync as writeFileSync38 } from "fs";
97076
+ import { existsSync as existsSync74, mkdirSync as mkdirSync41, readdirSync as readdirSync31, readFileSync as readFileSync53, rmSync as rmSync16, writeFileSync as writeFileSync38 } from "fs";
96914
97077
  import { dirname as dirname30, join as join82 } from "path";
96915
97078
  function stateFilePath(stackName = DEFAULT_STACK_NAME, cwd = process.cwd()) {
96916
97079
  return join82(cwd, STATE_DIR_NAME, `${STATE_FILE_PREFIX}${stackName}.json`);
@@ -96923,20 +97086,20 @@ function writeStackOutputs(outputs, cwd = process.cwd()) {
96923
97086
  }
96924
97087
  function readStackOutputs(stackName = DEFAULT_STACK_NAME, cwd = process.cwd()) {
96925
97088
  const path2 = stateFilePath(stackName, cwd);
96926
- if (!existsSync73(path2)) return null;
97089
+ if (!existsSync74(path2)) return null;
96927
97090
  try {
96928
- return JSON.parse(readFileSync51(path2, "utf-8"));
97091
+ return JSON.parse(readFileSync53(path2, "utf-8"));
96929
97092
  } catch {
96930
97093
  return null;
96931
97094
  }
96932
97095
  }
96933
97096
  function deleteStackOutputs(stackName = DEFAULT_STACK_NAME, cwd = process.cwd()) {
96934
97097
  const path2 = stateFilePath(stackName, cwd);
96935
- if (existsSync73(path2)) rmSync16(path2);
97098
+ if (existsSync74(path2)) rmSync16(path2);
96936
97099
  }
96937
97100
  function listStackNames(cwd = process.cwd()) {
96938
97101
  const dir = join82(cwd, STATE_DIR_NAME);
96939
- if (!existsSync73(dir)) return [];
97102
+ if (!existsSync74(dir)) return [];
96940
97103
  return readdirSync31(dir).filter((f3) => f3.startsWith(STATE_FILE_PREFIX) && f3.endsWith(".json")).map((f3) => f3.slice(STATE_FILE_PREFIX.length, -".json".length));
96941
97104
  }
96942
97105
  function requireStack(stackName, cwd = process.cwd()) {
@@ -96966,7 +97129,7 @@ var init_state = __esm({
96966
97129
 
96967
97130
  // src/commands/lambda/sam.ts
96968
97131
  import { execFileSync as execFileSync9, spawnSync as spawnSync4 } from "child_process";
96969
- import { existsSync as existsSync74 } from "fs";
97132
+ import { existsSync as existsSync75 } from "fs";
96970
97133
  import { join as join83 } from "path";
96971
97134
  function assertSamAvailable() {
96972
97135
  try {
@@ -96988,7 +97151,7 @@ function assertAwsCliAvailable() {
96988
97151
  }
96989
97152
  function locateSamTemplate(repoRoot2) {
96990
97153
  const candidate = join83(repoRoot2, "examples", "aws-lambda", "template.yaml");
96991
- if (!existsSync74(candidate)) {
97154
+ if (!existsSync75(candidate)) {
96992
97155
  throw new Error(
96993
97156
  `[lambda] SAM template not found at ${candidate}. If you're running from an installed package, point --sam-template at your local copy of examples/aws-lambda/template.yaml.`
96994
97157
  );
@@ -97083,17 +97246,17 @@ var init_sam = __esm({
97083
97246
  });
97084
97247
 
97085
97248
  // src/commands/lambda/repoRoot.ts
97086
- import { existsSync as existsSync75 } from "fs";
97249
+ import { existsSync as existsSync76 } from "fs";
97087
97250
  import { dirname as dirname31, resolve as resolve44 } from "path";
97088
97251
  import { fileURLToPath as fileURLToPath11 } from "url";
97089
97252
  function repoRoot() {
97090
97253
  const override = process.env.HYPERFRAMES_REPO_ROOT;
97091
- if (override && existsSync75(resolve44(override, "packages", "aws-lambda", "package.json"))) {
97254
+ if (override && existsSync76(resolve44(override, "packages", "aws-lambda", "package.json"))) {
97092
97255
  return override;
97093
97256
  }
97094
97257
  let dir = dirname31(fileURLToPath11(import.meta.url));
97095
97258
  for (let depth = 0; depth < 12; depth++) {
97096
- if (existsSync75(resolve44(dir, "packages", "aws-lambda", "package.json"))) {
97259
+ if (existsSync76(resolve44(dir, "packages", "aws-lambda", "package.json"))) {
97097
97260
  return dir;
97098
97261
  }
97099
97262
  const parent = dirname31(dir);
@@ -97116,7 +97279,7 @@ __export(deploy_exports, {
97116
97279
  runDeploy: () => runDeploy
97117
97280
  });
97118
97281
  import { spawnSync as spawnSync5 } from "child_process";
97119
- import { existsSync as existsSync76 } from "fs";
97282
+ import { existsSync as existsSync77 } from "fs";
97120
97283
  import { join as join84, resolve as resolve45 } from "path";
97121
97284
  async function runDeploy(args = {}) {
97122
97285
  const resolved = {
@@ -97135,7 +97298,7 @@ async function runDeploy(args = {}) {
97135
97298
  buildHandlerZip(root);
97136
97299
  } else {
97137
97300
  const zip = join84(root, "packages", "aws-lambda", "dist", "handler.zip");
97138
- if (!existsSync76(zip)) {
97301
+ if (!existsSync77(zip)) {
97139
97302
  throw new Error(
97140
97303
  `--skip-build set but ${zip} does not exist. Run \`bun run --cwd packages/aws-lambda build:zip\` first or drop --skip-build.`
97141
97304
  );
@@ -97246,23 +97409,61 @@ var init_sites = __esm({
97246
97409
  }
97247
97410
  });
97248
97411
 
97412
+ // src/commands/lambda/_dimensions.ts
97413
+ import { readFileSync as readFileSync54 } from "fs";
97414
+ import { join as join85 } from "path";
97415
+ function warnOnDimensionMismatch(args) {
97416
+ if (args.quiet) return;
97417
+ if (args.outputResolution) return;
97418
+ let html;
97419
+ try {
97420
+ html = readFileSync54(join85(args.projectDir, "index.html"), "utf-8");
97421
+ } catch {
97422
+ return;
97423
+ }
97424
+ const composition = findCompositionDimensions(html);
97425
+ if (!composition) return;
97426
+ if (composition.width === args.cliWidth && composition.height === args.cliHeight) return;
97427
+ console.warn(
97428
+ c2.warn(
97429
+ `--width/--height (${args.cliWidth}\xD7${args.cliHeight}) disagrees with the composition's data-width/data-height (${composition.width}\xD7${composition.height}). The runtime lays out the page at the composition's authored dimensions, so your output will be ${composition.width}\xD7${composition.height}, not ${args.cliWidth}\xD7${args.cliHeight}.
97430
+ To supersample to a higher resolution, pass --output-resolution (e.g. \`--output-resolution=4k\`).
97431
+ To truly change layout dimensions, edit the composition's data-width/data-height in index.html.`
97432
+ )
97433
+ );
97434
+ }
97435
+ var init_dimensions = __esm({
97436
+ "src/commands/lambda/_dimensions.ts"() {
97437
+ "use strict";
97438
+ init_colors();
97439
+ init_compositionViewport();
97440
+ }
97441
+ });
97442
+
97249
97443
  // src/commands/lambda/render.ts
97250
97444
  var render_exports2 = {};
97251
97445
  __export(render_exports2, {
97252
97446
  runRender: () => runRender
97253
97447
  });
97254
- import { existsSync as existsSync77 } from "fs";
97255
- import { join as join85, resolve as resolvePath2 } from "path";
97448
+ import { existsSync as existsSync78 } from "fs";
97449
+ import { join as join86, resolve as resolvePath2 } from "path";
97256
97450
  async function loadSDK2() {
97257
97451
  return import("@hyperframes/aws-lambda/sdk");
97258
97452
  }
97259
97453
  async function runRender(args) {
97260
97454
  const stack = requireStack(args.stackName);
97261
97455
  const projectDir = resolvePath2(args.projectDir);
97456
+ warnOnDimensionMismatch({
97457
+ projectDir,
97458
+ cliWidth: args.width,
97459
+ cliHeight: args.height,
97460
+ outputResolution: args.outputResolution,
97461
+ quiet: args.json
97462
+ });
97262
97463
  const variables = resolveVariablesArg(args.variables, args.variablesFile);
97263
97464
  if (variables && Object.keys(variables).length > 0) {
97264
- const indexPath = join85(projectDir, "index.html");
97265
- if (existsSync77(indexPath)) {
97465
+ const indexPath = join86(projectDir, "index.html");
97466
+ if (existsSync78(indexPath)) {
97266
97467
  const issues = validateVariablesAgainstProject(indexPath, variables);
97267
97468
  reportVariableIssues(issues, { strict: args.strictVariables ?? false, quiet: args.json });
97268
97469
  } else if (args.strictVariables && !args.json) {
@@ -97277,6 +97478,7 @@ async function runRender(args) {
97277
97478
  fps: args.fps,
97278
97479
  width: args.width,
97279
97480
  height: args.height,
97481
+ outputResolution: args.outputResolution,
97280
97482
  format: args.format,
97281
97483
  codec: args.codec,
97282
97484
  quality: args.quality,
@@ -97372,6 +97574,7 @@ var init_render3 = __esm({
97372
97574
  "use strict";
97373
97575
  init_colors();
97374
97576
  init_variables();
97577
+ init_dimensions();
97375
97578
  init_state();
97376
97579
  }
97377
97580
  });
@@ -97383,8 +97586,8 @@ __export(render_batch_exports, {
97383
97586
  runRenderBatch: () => runRenderBatch,
97384
97587
  runWithConcurrencyLimit: () => runWithConcurrencyLimit
97385
97588
  });
97386
- import { existsSync as existsSync78, readFileSync as readFileSync52 } from "fs";
97387
- import { join as join86, resolve as resolvePath3 } from "path";
97589
+ import { existsSync as existsSync79, readFileSync as readFileSync55 } from "fs";
97590
+ import { join as join87, resolve as resolvePath3 } from "path";
97388
97591
  async function loadSDK3() {
97389
97592
  return import("@hyperframes/aws-lambda/sdk");
97390
97593
  }
@@ -97392,7 +97595,7 @@ async function runRenderBatch(args) {
97392
97595
  const projectDir = resolvePath3(args.projectDir);
97393
97596
  const stack = requireStack(args.stackName);
97394
97597
  const batchPath = resolvePath3(args.batch);
97395
- if (!existsSync78(batchPath)) {
97598
+ if (!existsSync79(batchPath)) {
97396
97599
  errorBox("Batch file not found", `No such file: ${batchPath}`);
97397
97600
  process.exit(1);
97398
97601
  }
@@ -97401,7 +97604,14 @@ async function runRenderBatch(args) {
97401
97604
  errorBox("Empty batch", `${batchPath} contains zero entries (every line was blank).`);
97402
97605
  process.exit(1);
97403
97606
  }
97404
- const schema = loadProjectVariableSchema(join86(projectDir, "index.html"));
97607
+ warnOnDimensionMismatch({
97608
+ projectDir,
97609
+ cliWidth: args.width,
97610
+ cliHeight: args.height,
97611
+ outputResolution: args.outputResolution,
97612
+ quiet: args.json
97613
+ });
97614
+ const schema = loadProjectVariableSchema(join87(projectDir, "index.html"));
97405
97615
  const strict = args.strictVariables ?? false;
97406
97616
  let hadStrictIssue = false;
97407
97617
  for (const { entry, lineNumber } of entries2) {
@@ -97426,6 +97636,7 @@ async function runRenderBatch(args) {
97426
97636
  fps: args.fps,
97427
97637
  width: args.width,
97428
97638
  height: args.height,
97639
+ outputResolution: args.outputResolution,
97429
97640
  format: args.format,
97430
97641
  codec: args.codec,
97431
97642
  quality: args.quality,
@@ -97527,7 +97738,7 @@ function makePlaceholderSiteHandle(siteId, bucketName) {
97527
97738
  };
97528
97739
  }
97529
97740
  function parseBatchFile(path2) {
97530
- const raw = readFileSync52(path2, "utf8");
97741
+ const raw = readFileSync55(path2, "utf8");
97531
97742
  const lines = raw.split(/\r?\n/);
97532
97743
  const out = [];
97533
97744
  for (let i2 = 0; i2 < lines.length; i2++) {
@@ -97608,6 +97819,7 @@ var init_render_batch = __esm({
97608
97819
  init_colors();
97609
97820
  init_format();
97610
97821
  init_variables();
97822
+ init_dimensions();
97611
97823
  init_state();
97612
97824
  DEFAULT_MAX_CONCURRENT = 50;
97613
97825
  }
@@ -97720,7 +97932,7 @@ __export(policies_exports, {
97720
97932
  runPolicies: () => runPolicies,
97721
97933
  validatePolicy: () => validatePolicy
97722
97934
  });
97723
- import { readFileSync as readFileSync53 } from "fs";
97935
+ import { readFileSync as readFileSync56 } from "fs";
97724
97936
  function allRequiredActions() {
97725
97937
  const set = /* @__PURE__ */ new Set();
97726
97938
  for (const group of Object.values(REQUIRED_ACTIONS)) {
@@ -97826,7 +98038,7 @@ async function runPolicies(args) {
97826
98038
  }
97827
98039
  }
97828
98040
  function validatePolicy(policyPath) {
97829
- const raw = readFileSync53(policyPath, "utf-8");
98041
+ const raw = readFileSync56(policyPath, "utf-8");
97830
98042
  const parsed = JSON.parse(raw);
97831
98043
  const statements = Array.isArray(parsed.Statement) ? parsed.Statement : parsed.Statement ? [
97832
98044
  parsed.Statement
@@ -98014,11 +98226,20 @@ function parseEnum(raw, allowed, errorPrefix, defaultValue) {
98014
98226
  if (allowed.includes(s2)) return s2;
98015
98227
  throw new Error(`${errorPrefix} must be ${allowed.join("|")}; got ${s2}`);
98016
98228
  }
98229
+ function parseOutputResolution(raw) {
98230
+ if (raw == null || raw === "") return void 0;
98231
+ const normalized = normalizeResolutionFlag(String(raw));
98232
+ if (normalized) return normalized;
98233
+ throw new Error(
98234
+ `[lambda render] --output-resolution must be one of ${VALID_CANVAS_RESOLUTIONS.join("|")} (or an alias: 1080p, 4k, uhd, hd, 1080p-portrait, portrait-1080p, 4k-portrait, 1080p-square, square-1080p, 4k-square); got ${String(raw)}`
98235
+ );
98236
+ }
98017
98237
  var examples24, HELP, lambda_default, FORMATS, CODECS, QUALITIES2, CHROME_SOURCES, parseFormat, parseCodec, parseQuality, parseChromeSource;
98018
98238
  var init_lambda = __esm({
98019
98239
  "src/commands/lambda.ts"() {
98020
98240
  "use strict";
98021
98241
  init_dist();
98242
+ init_src();
98022
98243
  init_colors();
98023
98244
  examples24 = [
98024
98245
  ["Deploy the Lambda render stack to AWS", "hyperframes lambda deploy"],
@@ -98030,6 +98251,10 @@ var init_lambda = __esm({
98030
98251
  "Render and stream progress until done",
98031
98252
  "hyperframes lambda render ./my-project --width 1920 --height 1080 --wait"
98032
98253
  ],
98254
+ [
98255
+ "Supersample a 1080p composition to 4K via Chrome deviceScaleFactor",
98256
+ "hyperframes lambda render ./my-project --width 1920 --height 1080 --output-resolution 4k --wait"
98257
+ ],
98033
98258
  [
98034
98259
  "Render with composition variables (personalised template)",
98035
98260
  `hyperframes lambda render ./my-template --site-id abc1234deadbeef0 --width 1920 --height 1080 --variables '{"title":"Hello Alice","accent":"#ff0000"}'`
@@ -98114,6 +98339,10 @@ ${c2.bold("REQUIREMENTS:")}
98114
98339
  "site-id": { type: "string", description: "Explicit site id (overrides content hash)" },
98115
98340
  width: { type: "string", description: "Render width in pixels" },
98116
98341
  height: { type: "string", description: "Render height in pixels" },
98342
+ "output-resolution": {
98343
+ type: "string",
98344
+ description: "Output resolution preset that engages Chrome deviceScaleFactor supersampling. Accepts canonical names (landscape, landscape-4k, portrait, portrait-4k, square, square-4k) and aliases (1080p, 4k, uhd, hd). When set, the composition's authored data-width/data-height is supersampled to the target preset without changing the layout."
98345
+ },
98117
98346
  fps: { type: "string", description: "Render fps (24 | 30 | 60)" },
98118
98347
  format: { type: "string", description: "mp4 | mov | png-sequence | webm (default: mp4)" },
98119
98348
  codec: { type: "string", description: "h264 | h265 (mp4 only)" },
@@ -98268,6 +98497,7 @@ Or, for an opt-in dev setup:
98268
98497
  fps: fpsRaw,
98269
98498
  width,
98270
98499
  height,
98500
+ outputResolution: parseOutputResolution(args["output-resolution"]),
98271
98501
  format: parseFormat(args.format),
98272
98502
  codec: parseCodec(args.codec),
98273
98503
  quality: parseQuality(args.quality),
@@ -98319,6 +98549,7 @@ Or, for an opt-in dev setup:
98319
98549
  fps: fpsRaw,
98320
98550
  width,
98321
98551
  height,
98552
+ outputResolution: parseOutputResolution(args["output-resolution"]),
98322
98553
  format: parseFormat(args.format),
98323
98554
  codec: parseCodec(args.codec),
98324
98555
  quality: parseQuality(args.quality),
@@ -98521,7 +98752,7 @@ __export(autoUpdate_exports, {
98521
98752
  import { spawn as spawn16 } from "child_process";
98522
98753
  import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync42, openSync as openSync2 } from "fs";
98523
98754
  import { homedir as homedir12 } from "os";
98524
- import { join as join87 } from "path";
98755
+ import { join as join88 } from "path";
98525
98756
  import { compareVersions as compareVersions2 } from "compare-versions";
98526
98757
  function isAutoInstallDisabled() {
98527
98758
  if (isDevMode()) return true;
@@ -98544,7 +98775,7 @@ function log(line) {
98544
98775
  }
98545
98776
  function launchDetachedInstall(installCommand, version) {
98546
98777
  mkdirSync42(CONFIG_DIR2, { recursive: true, mode: 448 });
98547
- const configFile = join87(CONFIG_DIR2, "config.json");
98778
+ const configFile = join88(CONFIG_DIR2, "config.json");
98548
98779
  const nodeScript = `
98549
98780
  const { exec } = require("node:child_process");
98550
98781
  const { readFileSync, renameSync, writeFileSync } = require("node:fs");
@@ -98663,8 +98894,8 @@ var init_autoUpdate = __esm({
98663
98894
  init_config();
98664
98895
  init_env();
98665
98896
  init_installerDetection();
98666
- CONFIG_DIR2 = join87(homedir12(), ".hyperframes");
98667
- LOG_FILE = join87(CONFIG_DIR2, "auto-update.log");
98897
+ CONFIG_DIR2 = join88(homedir12(), ".hyperframes");
98898
+ LOG_FILE = join88(CONFIG_DIR2, "auto-update.log");
98668
98899
  PENDING_TIMEOUT_MS = 10 * 60 * 1e3;
98669
98900
  }
98670
98901
  });
@@ -98852,17 +99083,17 @@ var init_help = __esm({
98852
99083
  // src/cli.ts
98853
99084
  init_version();
98854
99085
  init_dist();
98855
- import { dirname as dirname32, join as join88 } from "path";
99086
+ import { dirname as dirname32, join as join89 } from "path";
98856
99087
  import { fileURLToPath as fileURLToPath12 } from "url";
98857
- import { existsSync as existsSync79 } from "fs";
99088
+ import { existsSync as existsSync80 } from "fs";
98858
99089
  (() => {
98859
99090
  const here = dirname32(fileURLToPath12(import.meta.url));
98860
- const shader = join88(here, "shaderTransitionWorker.js");
98861
- const png = join88(here, "pngDecodeBlitWorker.js");
98862
- if (!process.env.HF_SHADER_WORKER_ENTRY && existsSync79(shader)) {
99091
+ const shader = join89(here, "shaderTransitionWorker.js");
99092
+ const png = join89(here, "pngDecodeBlitWorker.js");
99093
+ if (!process.env.HF_SHADER_WORKER_ENTRY && existsSync80(shader)) {
98863
99094
  process.env.HF_SHADER_WORKER_ENTRY = shader;
98864
99095
  }
98865
- if (!process.env.HF_PNG_DECODE_BLIT_WORKER_ENTRY && existsSync79(png)) {
99096
+ if (!process.env.HF_PNG_DECODE_BLIT_WORKER_ENTRY && existsSync80(png)) {
98866
99097
  process.env.HF_PNG_DECODE_BLIT_WORKER_ENTRY = png;
98867
99098
  }
98868
99099
  })();
@@ -98874,10 +99105,10 @@ if (rootVersionRequested) {
98874
99105
  process.exit(0);
98875
99106
  }
98876
99107
  try {
98877
- const { readFileSync: readFileSync54 } = await import("fs");
99108
+ const { readFileSync: readFileSync57 } = await import("fs");
98878
99109
  const { resolve: resolve46 } = await import("path");
98879
99110
  const envPath = resolve46(process.cwd(), ".env");
98880
- const envContent = readFileSync54(envPath, "utf-8");
99111
+ const envContent = readFileSync57(envPath, "utf-8");
98881
99112
  for (const rawLine of envContent.split("\n")) {
98882
99113
  let line = rawLine.trim();
98883
99114
  if (!line || line.startsWith("#")) continue;