hyperframes 0.6.55 → 0.6.56

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 +388 -229
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -50,7 +50,7 @@ var VERSION;
50
50
  var init_version = __esm({
51
51
  "src/version.ts"() {
52
52
  "use strict";
53
- VERSION = true ? "0.6.55" : "0.0.0-dev";
53
+ VERSION = true ? "0.6.56" : "0.0.0-dev";
54
54
  }
55
55
  });
56
56
 
@@ -66926,6 +66926,101 @@ var init_videoFrameInjector = __esm({
66926
66926
  }
66927
66927
  });
66928
66928
 
66929
+ // ../engine/src/services/audioVolumeEnvelope.ts
66930
+ import { readFileSync as readFileSync22, renameSync as renameSync3, writeFileSync as writeFileSync14 } from "fs";
66931
+ import { randomBytes } from "crypto";
66932
+ function parseWavLayout(buffer) {
66933
+ if (buffer.length < 12 || buffer.toString("ascii", 0, 4) !== "RIFF") return null;
66934
+ if (buffer.toString("ascii", 8, 12) !== "WAVE") return null;
66935
+ let offset = 12;
66936
+ let fmt = null;
66937
+ let data = null;
66938
+ while (offset + 8 <= buffer.length) {
66939
+ const chunkId = buffer.toString("ascii", offset, offset + 4);
66940
+ const chunkSize = buffer.readUInt32LE(offset + 4);
66941
+ const body = offset + 8;
66942
+ if (chunkId === "fmt " && body + 16 <= buffer.length) {
66943
+ if (buffer.readUInt16LE(body) !== PCM_FORMAT) return null;
66944
+ fmt = {
66945
+ numChannels: buffer.readUInt16LE(body + 2),
66946
+ sampleRate: buffer.readUInt32LE(body + 4),
66947
+ bitsPerSample: buffer.readUInt16LE(body + 14)
66948
+ };
66949
+ } else if (chunkId === "data") {
66950
+ data = { offset: body, size: Math.min(chunkSize, buffer.length - body) };
66951
+ }
66952
+ offset = body + chunkSize + chunkSize % 2;
66953
+ }
66954
+ if (!fmt || !data) return null;
66955
+ if (fmt.bitsPerSample !== SUPPORTED_BITS || fmt.numChannels < 1) return null;
66956
+ return {
66957
+ numChannels: fmt.numChannels,
66958
+ sampleRate: fmt.sampleRate,
66959
+ dataOffset: data.offset,
66960
+ dataSize: data.size
66961
+ };
66962
+ }
66963
+ function toRelativeEnvelope(keyframes, trackStart, baseVolume) {
66964
+ const points = keyframes.filter((k2) => Number.isFinite(k2.time) && Number.isFinite(k2.volume)).map((k2) => ({
66965
+ time: Math.max(0, k2.time - trackStart),
66966
+ volume: Math.max(0, Math.min(1, k2.volume))
66967
+ })).sort((a, b2) => a.time - b2.time);
66968
+ const deduped = [];
66969
+ for (const point of points) {
66970
+ const previous = deduped.at(-1);
66971
+ if (previous && Math.abs(previous.time - point.time) < 1e-9) previous.volume = point.volume;
66972
+ else deduped.push(point);
66973
+ }
66974
+ if (deduped.length === 0) return deduped;
66975
+ if (deduped[0].time > 0) {
66976
+ deduped.unshift({ time: 0, volume: Math.max(0, Math.min(1, baseVolume)) });
66977
+ }
66978
+ return deduped;
66979
+ }
66980
+ function applyVolumeEnvelopeToWav(wavPath, keyframes, trackStart, baseVolume) {
66981
+ const envelope = toRelativeEnvelope(keyframes, trackStart, baseVolume);
66982
+ if (envelope.length === 0) return false;
66983
+ try {
66984
+ const buffer = readFileSync22(wavPath);
66985
+ const layout2 = parseWavLayout(buffer);
66986
+ if (!layout2) return false;
66987
+ const { numChannels, sampleRate, dataOffset, dataSize } = layout2;
66988
+ const bytesPerSample = SUPPORTED_BITS / 8;
66989
+ const frameBytes = numChannels * bytesPerSample;
66990
+ const frameCount = Math.floor(dataSize / frameBytes);
66991
+ let segment = 0;
66992
+ for (let frame = 0; frame < frameCount; frame += 1) {
66993
+ const time = frame / sampleRate;
66994
+ while (segment < envelope.length - 2 && time >= envelope[segment + 1].time) segment += 1;
66995
+ const a = envelope[segment];
66996
+ const b2 = envelope[segment + 1] ?? a;
66997
+ const span = b2.time - a.time;
66998
+ const progress = span <= 0 ? 0 : Math.min(1, Math.max(0, (time - a.time) / span));
66999
+ const gain = a.volume + (b2.volume - a.volume) * progress;
67000
+ const base = dataOffset + frame * frameBytes;
67001
+ for (let channel = 0; channel < numChannels; channel += 1) {
67002
+ const at3 = base + channel * bytesPerSample;
67003
+ const scaled = Math.round(buffer.readInt16LE(at3) * gain);
67004
+ buffer.writeInt16LE(scaled < -32768 ? -32768 : scaled > 32767 ? 32767 : scaled, at3);
67005
+ }
67006
+ }
67007
+ const tempPath = `${wavPath}.${randomBytes(6).toString("hex")}.tmp`;
67008
+ writeFileSync14(tempPath, buffer);
67009
+ renameSync3(tempPath, wavPath);
67010
+ return true;
67011
+ } catch {
67012
+ return false;
67013
+ }
67014
+ }
67015
+ var PCM_FORMAT, SUPPORTED_BITS;
67016
+ var init_audioVolumeEnvelope = __esm({
67017
+ "../engine/src/services/audioVolumeEnvelope.ts"() {
67018
+ "use strict";
67019
+ PCM_FORMAT = 1;
67020
+ SUPPORTED_BITS = 16;
67021
+ }
67022
+ });
67023
+
66929
67024
  // ../engine/src/services/audioMixer.ts
66930
67025
  import { existsSync as existsSync27, mkdirSync as mkdirSync16, rmSync as rmSync6 } from "fs";
66931
67026
  import { isAbsolute as isAbsolute6, join as join29, dirname as dirname10 } from "path";
@@ -66939,10 +67034,47 @@ function formatFilterNumber(value) {
66939
67034
  function escapeExpressionCommas(expression) {
66940
67035
  return expression.replace(/\\/g, "\\\\").replace(/,/g, "\\,");
66941
67036
  }
66942
- function buildVolumeExpression(track) {
67037
+ function simplifyVolumeKeyframes(keyframes) {
67038
+ if (keyframes.length < 3) return keyframes;
67039
+ const keep = new Array(keyframes.length).fill(false);
67040
+ keep[0] = true;
67041
+ keep[keyframes.length - 1] = true;
67042
+ const stack = [[0, keyframes.length - 1]];
67043
+ while (stack.length > 0) {
67044
+ const [startIndex, endIndex] = stack.pop();
67045
+ const start = keyframes[startIndex];
67046
+ const end = keyframes[endIndex];
67047
+ const span = end.time - start.time;
67048
+ let maxDistance = VOLUME_SIMPLIFY_EPSILON;
67049
+ let splitIndex = -1;
67050
+ for (let i2 = startIndex + 1; i2 < endIndex; i2 += 1) {
67051
+ const point = keyframes[i2];
67052
+ const interpolated = span === 0 ? start.volume : start.volume + (end.volume - start.volume) * (point.time - start.time) / span;
67053
+ const distance = Math.abs(point.volume - interpolated);
67054
+ if (distance > maxDistance) {
67055
+ maxDistance = distance;
67056
+ splitIndex = i2;
67057
+ }
67058
+ }
67059
+ if (splitIndex !== -1) {
67060
+ keep[splitIndex] = true;
67061
+ stack.push([startIndex, splitIndex], [splitIndex, endIndex]);
67062
+ }
67063
+ }
67064
+ const simplified = keyframes.filter((_, i2) => keep[i2]);
67065
+ if (simplified.length <= MAX_VOLUME_SEGMENTS) return simplified;
67066
+ const step = (simplified.length - 1) / (MAX_VOLUME_SEGMENTS - 1);
67067
+ const sampled = [];
67068
+ for (let i2 = 0; i2 < MAX_VOLUME_SEGMENTS; i2 += 1) {
67069
+ const point = simplified[Math.round(i2 * step)];
67070
+ if (sampled.length === 0 || point.time > sampled.at(-1).time) sampled.push(point);
67071
+ }
67072
+ return sampled;
67073
+ }
67074
+ function buildVolumeExpression(track, ignoreKeyframes = false) {
66943
67075
  const trimDuration = track.end - track.start;
66944
67076
  const staticVolume = clampVolume(track.volume);
66945
- const keyframes = (track.volumeKeyframes ?? []).filter((keyframe) => Number.isFinite(keyframe.time) && Number.isFinite(keyframe.volume)).map((keyframe) => ({
67077
+ const keyframes = (ignoreKeyframes ? [] : track.volumeKeyframes ?? []).filter((keyframe) => Number.isFinite(keyframe.time) && Number.isFinite(keyframe.volume)).map((keyframe) => ({
66946
67078
  time: Math.max(0, Math.min(trimDuration, keyframe.time - track.start)),
66947
67079
  volume: clampVolume(keyframe.volume)
66948
67080
  })).sort((a, b2) => a.time - b2.time);
@@ -66959,13 +67091,14 @@ function buildVolumeExpression(track) {
66959
67091
  deduped.push(keyframe);
66960
67092
  }
66961
67093
  }
66962
- if (deduped.length === 1) {
66963
- return `volume=${formatFilterNumber(deduped[0].volume)}`;
67094
+ const simplified = simplifyVolumeKeyframes(deduped);
67095
+ if (simplified.length === 1) {
67096
+ return `volume=${formatFilterNumber(simplified[0].volume)}`;
66964
67097
  }
66965
- let expression = formatFilterNumber(deduped.at(-1).volume);
66966
- for (let i2 = deduped.length - 2; i2 >= 0; i2 -= 1) {
66967
- const current = deduped[i2];
66968
- const next = deduped[i2 + 1];
67098
+ let expression = formatFilterNumber(simplified.at(-1).volume);
67099
+ for (let i2 = simplified.length - 2; i2 >= 0; i2 -= 1) {
67100
+ const current = simplified[i2];
67101
+ const next = simplified[i2 + 1];
66969
67102
  const currentTime = formatFilterNumber(current.time);
66970
67103
  const nextTime = formatFilterNumber(next.time);
66971
67104
  const currentVolume = formatFilterNumber(current.volume);
@@ -67133,38 +67266,49 @@ async function mixAudioTracks(tracks, outputPath, totalDuration, signal, config)
67133
67266
  }
67134
67267
  const outputDir = dirname10(outputPath);
67135
67268
  if (!existsSync27(outputDir)) mkdirSync16(outputDir, { recursive: true });
67136
- const inputs = [];
67137
- const filterParts = [];
67138
- tracks.forEach((track, i2) => {
67139
- inputs.push("-i", track.srcPath);
67140
- const delayMs = Math.round(track.start * 1e3);
67141
- const trimDuration = track.end - track.start;
67142
- const volumeFilter = buildVolumeExpression(track);
67143
- filterParts.push(
67144
- `[${i2}:a]atrim=0:${trimDuration},${volumeFilter},adelay=${delayMs}|${delayMs},apad=whole_dur=${totalDuration}[a${i2}]`
67145
- );
67146
- });
67147
- const mixInputs = tracks.map((_, i2) => `[a${i2}]`).join("");
67148
- const weights = tracks.map(() => "1").join(" ");
67149
- const mixFilter = `${mixInputs}amix=inputs=${tracks.length}:duration=longest:dropout_transition=0:normalize=0:weights='${weights}'[mixed]`;
67150
- const postMixGainFilter = `[mixed]volume=${masterOutputGain}[out]`;
67151
- const fullFilter = [...filterParts, mixFilter, postMixGainFilter].join(";");
67152
- const args = [
67153
- ...inputs,
67154
- "-filter_complex",
67155
- fullFilter,
67156
- "-map",
67157
- "[out]",
67158
- "-acodec",
67159
- "aac",
67160
- "-b:a",
67161
- "192k",
67162
- "-t",
67163
- String(totalDuration),
67164
- "-y",
67165
- outputPath
67166
- ];
67167
- const result = await runFfmpeg(args, { signal, timeout: ffmpegProcessTimeout });
67269
+ const buildArgs = (ignoreAutomation) => {
67270
+ const inputs = [];
67271
+ const filterParts = [];
67272
+ tracks.forEach((track, i2) => {
67273
+ inputs.push("-i", track.srcPath);
67274
+ const delayMs = Math.round(track.start * 1e3);
67275
+ const trimDuration = track.end - track.start;
67276
+ const volumeFilter = buildVolumeExpression(track, ignoreAutomation);
67277
+ filterParts.push(
67278
+ `[${i2}:a]atrim=0:${trimDuration},${volumeFilter},adelay=${delayMs}|${delayMs},apad=whole_dur=${totalDuration}[a${i2}]`
67279
+ );
67280
+ });
67281
+ const mixInputs = tracks.map((_, i2) => `[a${i2}]`).join("");
67282
+ const weights = tracks.map(() => "1").join(" ");
67283
+ const mixFilter = `${mixInputs}amix=inputs=${tracks.length}:duration=longest:dropout_transition=0:normalize=0:weights='${weights}'[mixed]`;
67284
+ const postMixGainFilter = `[mixed]volume=${masterOutputGain}[out]`;
67285
+ const fullFilter = [...filterParts, mixFilter, postMixGainFilter].join(";");
67286
+ return [
67287
+ ...inputs,
67288
+ "-filter_complex",
67289
+ fullFilter,
67290
+ "-map",
67291
+ "[out]",
67292
+ "-acodec",
67293
+ "aac",
67294
+ "-b:a",
67295
+ "192k",
67296
+ "-t",
67297
+ String(totalDuration),
67298
+ "-y",
67299
+ outputPath
67300
+ ];
67301
+ };
67302
+ let result = await runFfmpeg(buildArgs(false), { signal, timeout: ffmpegProcessTimeout });
67303
+ let degradedAutomation = false;
67304
+ const hasAutomation = tracks.some((track) => (track.volumeKeyframes?.length ?? 0) > 0);
67305
+ if (!result.success && !signal?.aborted && hasAutomation) {
67306
+ const retry = await runFfmpeg(buildArgs(true), { signal, timeout: ffmpegProcessTimeout });
67307
+ if (retry.success) {
67308
+ result = retry;
67309
+ degradedAutomation = true;
67310
+ }
67311
+ }
67168
67312
  if (signal?.aborted) {
67169
67313
  return {
67170
67314
  success: false,
@@ -67187,7 +67331,8 @@ async function mixAudioTracks(tracks, outputPath, totalDuration, signal, config)
67187
67331
  success: true,
67188
67332
  outputPath,
67189
67333
  durationMs: result.durationMs,
67190
- tracksProcessed: tracks.length
67334
+ tracksProcessed: tracks.length,
67335
+ error: degradedAutomation ? "Volume automation exceeded this ffmpeg build's expression limits; rendered at base volume" : void 0
67191
67336
  };
67192
67337
  }
67193
67338
  async function processCompositionAudio(elements, baseDir, workDir, outputPath, totalDuration, signal, config, compiledDir) {
@@ -67259,6 +67404,15 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
67259
67404
  }
67260
67405
  audioSrcPath = trimmedPath;
67261
67406
  }
67407
+ let bakedEnvelope = false;
67408
+ if (element.volumeKeyframes && element.volumeKeyframes.length > 0) {
67409
+ bakedEnvelope = applyVolumeEnvelopeToWav(
67410
+ audioSrcPath,
67411
+ element.volumeKeyframes,
67412
+ element.start,
67413
+ element.volume ?? 1
67414
+ );
67415
+ }
67262
67416
  tracks.push({
67263
67417
  id: element.id,
67264
67418
  srcPath: audioSrcPath,
@@ -67266,8 +67420,9 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
67266
67420
  end: element.end,
67267
67421
  mediaStart: element.mediaStart,
67268
67422
  duration: element.end - element.start,
67269
- volume: element.volume ?? 1,
67270
- volumeKeyframes: element.volumeKeyframes
67423
+ // Gain is already in the samples when baked, so mix at unity.
67424
+ volume: bakedEnvelope ? 1 : element.volume ?? 1,
67425
+ volumeKeyframes: bakedEnvelope ? void 0 : element.volumeKeyframes
67271
67426
  });
67272
67427
  } catch (err) {
67273
67428
  errors.push(`Error: ${element.id} \u2014 ${err instanceof Error ? err.message : String(err)}`);
@@ -67285,6 +67440,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
67285
67440
  error: errors.length > 0 ? `Warnings: ${errors.join(", ")}` : mixResult.error
67286
67441
  };
67287
67442
  }
67443
+ var MAX_VOLUME_SEGMENTS, VOLUME_SIMPLIFY_EPSILON;
67288
67444
  var init_audioMixer = __esm({
67289
67445
  "../engine/src/services/audioMixer.ts"() {
67290
67446
  "use strict";
@@ -67295,6 +67451,9 @@ var init_audioMixer = __esm({
67295
67451
  init_runFfmpeg();
67296
67452
  init_htmlTemplate();
67297
67453
  init_videoFrameExtractor();
67454
+ init_audioVolumeEnvelope();
67455
+ MAX_VOLUME_SEGMENTS = 32;
67456
+ VOLUME_SIMPLIFY_EPSILON = 5e-3;
67298
67457
  }
67299
67458
  });
67300
67459
 
@@ -67607,7 +67766,7 @@ var init_parallelCoordinator = __esm({
67607
67766
  // ../engine/src/services/fileServer.ts
67608
67767
  import { Hono as Hono2 } from "hono";
67609
67768
  import { serve } from "@hono/node-server";
67610
- import { readFileSync as readFileSync22, existsSync as existsSync29, statSync as statSync9 } from "fs";
67769
+ import { readFileSync as readFileSync23, existsSync as existsSync29, statSync as statSync9 } from "fs";
67611
67770
  import { join as join31, extname as extname7 } from "path";
67612
67771
  function createFileServer(options) {
67613
67772
  const { projectDir, compiledDir, port = 0, stripEmbeddedRuntime = true } = options;
@@ -67629,11 +67788,11 @@ function createFileServer(options) {
67629
67788
  const ext = extname7(filePath).toLowerCase();
67630
67789
  const contentType = MIME_TYPES2[ext] || "application/octet-stream";
67631
67790
  if (ext === ".html") {
67632
- const rawHtml = readFileSync22(filePath, "utf-8");
67791
+ const rawHtml = readFileSync23(filePath, "utf-8");
67633
67792
  const html = relativePath === "index.html" ? injectScriptsIntoHtml(rawHtml, headScripts, bodyScripts, stripEmbeddedRuntime) : rawHtml;
67634
67793
  return c3.text(html, 200, { "Content-Type": contentType });
67635
67794
  }
67636
- const content = readFileSync22(filePath);
67795
+ const content = readFileSync23(filePath);
67637
67796
  return new Response(content, {
67638
67797
  status: 200,
67639
67798
  headers: { "Content-Type": contentType }
@@ -69352,7 +69511,7 @@ __export(deterministicFonts_exports, {
69352
69511
  iterateFontFamilyDeclarations: () => iterateFontFamilyDeclarations,
69353
69512
  parseFontFamilyValue: () => parseFontFamilyValue
69354
69513
  });
69355
- import { existsSync as existsSync31, mkdirSync as mkdirSync18, readFileSync as readFileSync23, writeFileSync as writeFileSync14 } from "fs";
69514
+ import { existsSync as existsSync31, mkdirSync as mkdirSync18, readFileSync as readFileSync24, writeFileSync as writeFileSync15 } from "fs";
69356
69515
  import { homedir as homedir8, tmpdir as tmpdir3 } from "os";
69357
69516
  import { join as join33 } from "path";
69358
69517
  function parseFontFamilyValue(value) {
@@ -69536,7 +69695,7 @@ async function fetchGoogleFont(familyName, options) {
69536
69695
  continue;
69537
69696
  }
69538
69697
  const buffer = Buffer.from(await fontRes.arrayBuffer());
69539
- writeFileSync14(cachePath2, buffer);
69698
+ writeFileSync15(cachePath2, buffer);
69540
69699
  } catch (err) {
69541
69700
  if (err instanceof FontFetchError) throw err;
69542
69701
  if (options.failClosedFontFetch) {
@@ -69545,7 +69704,7 @@ async function fetchGoogleFont(familyName, options) {
69545
69704
  continue;
69546
69705
  }
69547
69706
  }
69548
- const fontBytes = readFileSync23(cachePath2);
69707
+ const fontBytes = readFileSync24(cachePath2);
69549
69708
  const dataUri = `data:font/woff2;base64,${fontBytes.toString("base64")}`;
69550
69709
  faces.push({ weight, style, dataUri });
69551
69710
  }
@@ -69745,7 +69904,7 @@ var init_deterministicFonts = __esm({
69745
69904
 
69746
69905
  // ../producer/src/services/hyperframeRuntimeLoader.ts
69747
69906
  import { createHash as createHash6 } from "crypto";
69748
- import { existsSync as existsSync32, readFileSync as readFileSync24 } from "fs";
69907
+ import { existsSync as existsSync32, readFileSync as readFileSync25 } from "fs";
69749
69908
  import { dirname as dirname11, resolve as resolve16 } from "path";
69750
69909
  import { fileURLToPath as fileURLToPath2 } from "url";
69751
69910
  function resolveHyperframeManifestPath() {
@@ -69774,7 +69933,7 @@ function resolveVerifiedHyperframeRuntime() {
69774
69933
  `[HyperframeRuntimeLoader] Missing manifest at ${manifestPath}. Build core runtime artifacts before rendering.`
69775
69934
  );
69776
69935
  }
69777
- const manifestRaw = readFileSync24(manifestPath, "utf8");
69936
+ const manifestRaw = readFileSync25(manifestPath, "utf8");
69778
69937
  const manifest = JSON.parse(manifestRaw);
69779
69938
  const runtimeFileName = manifest.artifacts?.iife;
69780
69939
  if (!runtimeFileName || !manifest.sha256) {
@@ -69786,7 +69945,7 @@ function resolveVerifiedHyperframeRuntime() {
69786
69945
  if (!existsSync32(runtimePath)) {
69787
69946
  throw new Error(`[HyperframeRuntimeLoader] Missing runtime artifact at ${runtimePath}.`);
69788
69947
  }
69789
- const runtimeSource = readFileSync24(runtimePath, "utf8");
69948
+ const runtimeSource = readFileSync25(runtimePath, "utf8");
69790
69949
  const runtimeSha = createHash6("sha256").update(runtimeSource, "utf8").digest("hex");
69791
69950
  if (runtimeSha !== manifest.sha256) {
69792
69951
  throw new Error(
@@ -69825,7 +69984,7 @@ var init_hyperframeRuntimeLoader = __esm({
69825
69984
  // ../producer/src/services/fileServer.ts
69826
69985
  import { Hono as Hono3 } from "hono";
69827
69986
  import { serve as serve2 } from "@hono/node-server";
69828
- import { readFileSync as readFileSync25, existsSync as existsSync33, realpathSync, statSync as statSync10 } from "fs";
69987
+ import { readFileSync as readFileSync26, existsSync as existsSync33, realpathSync, statSync as statSync10 } from "fs";
69829
69988
  import { join as join34, extname as extname8, resolve as resolve17, sep as sep5 } from "path";
69830
69989
  function isPathInside(child, parent, options = {}) {
69831
69990
  const { resolveSymlinks = false, pathModule } = options;
@@ -70020,7 +70179,7 @@ function createFileServer2(options) {
70020
70179
  const ext = extname8(filePath).toLowerCase();
70021
70180
  const contentType = MIME_TYPES3[ext] || "application/octet-stream";
70022
70181
  if (ext === ".html") {
70023
- const rawHtml = readFileSync25(filePath, "utf-8");
70182
+ const rawHtml = readFileSync26(filePath, "utf-8");
70024
70183
  const isIndex = relativePath === "index.html";
70025
70184
  let html = rawHtml;
70026
70185
  if (preHeadScripts.length > 0) {
@@ -70029,7 +70188,7 @@ function createFileServer2(options) {
70029
70188
  html = isIndex ? injectScriptsIntoHtml(html, headScripts, bodyScripts, stripEmbeddedRuntime) : html;
70030
70189
  return c3.text(html, 200, { "Content-Type": contentType });
70031
70190
  }
70032
- const content = readFileSync25(filePath);
70191
+ const content = readFileSync26(filePath);
70033
70192
  return new Response(content, {
70034
70193
  status: 200,
70035
70194
  headers: { "Content-Type": contentType }
@@ -70376,7 +70535,7 @@ var init_paths = __esm({
70376
70535
  });
70377
70536
 
70378
70537
  // ../producer/src/services/render/shared.ts
70379
- import { copyFileSync as copyFileSync2, cpSync, existsSync as existsSync34, mkdirSync as mkdirSync19, symlinkSync, writeFileSync as writeFileSync15 } from "fs";
70538
+ import { copyFileSync as copyFileSync2, cpSync, existsSync as existsSync34, mkdirSync as mkdirSync19, symlinkSync, writeFileSync as writeFileSync16 } from "fs";
70380
70539
  import { basename as basename4, dirname as dirname12, isAbsolute as isAbsolute7, join as join36, relative as relative5, resolve as resolve18 } from "path";
70381
70540
  function projectBrowserEndToCompositionTimeline(existingStart, browserStart, browserEnd) {
70382
70541
  return browserEnd + (existingStart - browserStart);
@@ -70415,11 +70574,11 @@ function resolveDeviceScaleFactor(input2) {
70415
70574
  function writeCompiledArtifacts(compiled, workDir, includeSummary) {
70416
70575
  const compileDir = join36(workDir, "compiled");
70417
70576
  mkdirSync19(compileDir, { recursive: true });
70418
- writeFileSync15(join36(compileDir, "index.html"), compiled.html, "utf-8");
70577
+ writeFileSync16(join36(compileDir, "index.html"), compiled.html, "utf-8");
70419
70578
  for (const [srcPath, html] of compiled.subCompositions) {
70420
70579
  const outPath = join36(compileDir, srcPath);
70421
70580
  mkdirSync19(dirname12(outPath), { recursive: true });
70422
- writeFileSync15(outPath, html, "utf-8");
70581
+ writeFileSync16(outPath, html, "utf-8");
70423
70582
  }
70424
70583
  for (const [relativePath, absolutePath] of compiled.externalAssets) {
70425
70584
  const outPath = resolve18(join36(compileDir, relativePath));
@@ -70453,7 +70612,7 @@ function writeCompiledArtifacts(compiled, workDir, includeSummary) {
70453
70612
  renderModeHints: compiled.renderModeHints,
70454
70613
  hasShaderTransitions: compiled.hasShaderTransitions
70455
70614
  };
70456
- writeFileSync15(join36(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
70615
+ writeFileSync16(join36(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
70457
70616
  }
70458
70617
  }
70459
70618
  function applyRenderModeHints(alreadyForced, compiled, log2 = defaultLogger) {
@@ -71133,7 +71292,7 @@ var init_urlDownloader2 = __esm({
71133
71292
  });
71134
71293
 
71135
71294
  // ../producer/src/services/htmlCompiler.ts
71136
- import { readFileSync as readFileSync26, existsSync as existsSync35, mkdirSync as mkdirSync20 } from "fs";
71295
+ import { readFileSync as readFileSync27, existsSync as existsSync35, mkdirSync as mkdirSync20 } from "fs";
71137
71296
  import { join as join38, dirname as dirname13, resolve as resolve19 } from "path";
71138
71297
  function dedupeElementsById(elements) {
71139
71298
  const deduped = /* @__PURE__ */ new Map();
@@ -71291,7 +71450,7 @@ async function parseSubCompositions(html, projectDir, downloadDir, parentOffset
71291
71450
  if (!existsSync35(filePath)) {
71292
71451
  continue;
71293
71452
  }
71294
- const rawSubHtml = readFileSync26(filePath, "utf-8");
71453
+ const rawSubHtml = readFileSync27(filePath, "utf-8");
71295
71454
  const nestedVisited = new Set(visited);
71296
71455
  nestedVisited.add(filePath);
71297
71456
  workItems.push({ srcPath, absoluteStart, absoluteEnd, filePath, rawSubHtml, nestedVisited });
@@ -71477,7 +71636,7 @@ function inlineSubCompositions2(html, subCompositions, projectDir) {
71477
71636
  if (!compHtml) {
71478
71637
  const filePath = resolve19(projectDir, srcPath);
71479
71638
  if (existsSync35(filePath)) {
71480
- compHtml = readFileSync26(filePath, "utf-8");
71639
+ compHtml = readFileSync27(filePath, "utf-8");
71481
71640
  }
71482
71641
  }
71483
71642
  return compHtml;
@@ -71693,7 +71852,7 @@ function rewriteUnresolvableGsapToCdn(html, projectDir) {
71693
71852
  );
71694
71853
  }
71695
71854
  async function compileForRender(projectDir, htmlPath, downloadDir, options = {}) {
71696
- const rawHtml = rewriteUnresolvableGsapToCdn(readFileSync26(htmlPath, "utf-8"), projectDir);
71855
+ const rawHtml = rewriteUnresolvableGsapToCdn(readFileSync27(htmlPath, "utf-8"), projectDir);
71697
71856
  const { html: compiledHtml, unresolvedCompositions } = await compileHtmlFile(
71698
71857
  rawHtml,
71699
71858
  projectDir,
@@ -72934,7 +73093,7 @@ var init_hdrImageTransferCache = __esm({
72934
73093
  });
72935
73094
 
72936
73095
  // ../producer/src/services/render/stages/captureHdrResources.ts
72937
- import { mkdirSync as mkdirSync21, openSync, readFileSync as readFileSync27, statSync as statSync11 } from "fs";
73096
+ import { mkdirSync as mkdirSync21, openSync, readFileSync as readFileSync28, statSync as statSync11 } from "fs";
72938
73097
  import { join as join43 } from "path";
72939
73098
  function planHdrResources(args) {
72940
73099
  const { composition, nativeHdrVideoIds, nativeHdrImageIds, projectDir, compiledDir } = args;
@@ -73079,7 +73238,7 @@ function decodeHdrImageBuffers(args) {
73079
73238
  const out = /* @__PURE__ */ new Map();
73080
73239
  for (const [imageId, srcPath] of hdrImageSrcPaths) {
73081
73240
  try {
73082
- const decoded = decodePngToRgb48le(readFileSync27(srcPath));
73241
+ const decoded = decodePngToRgb48le(readFileSync28(srcPath));
73083
73242
  const layout2 = prep.hdrExtractionDims.get(imageId);
73084
73243
  const fitInfo = prep.hdrImageFitInfo.get(imageId);
73085
73244
  if (layout2 && (layout2.width !== decoded.width || layout2.height !== decoded.height)) {
@@ -73350,7 +73509,7 @@ var init_captureHdrFrameShared = __esm({
73350
73509
  });
73351
73510
 
73352
73511
  // ../producer/src/services/render/stages/captureHdrSequentialLoop.ts
73353
- import { writeFileSync as writeFileSync16 } from "fs";
73512
+ import { writeFileSync as writeFileSync17 } from "fs";
73354
73513
  import { join as join44 } from "path";
73355
73514
  async function runSequentialLayeredFrameLoop(input2) {
73356
73515
  const {
@@ -73471,7 +73630,7 @@ async function runSequentialLayeredFrameLoop(input2) {
73471
73630
  await compositeHdrFrame(hdrCompositeCtx, normalCanvas, time, stackingInfo, void 0, i2);
73472
73631
  addHdrTiming(hdrPerf, "normalCompositeMs", timingStart);
73473
73632
  if (debugDumpEnabled && debugDumpDir && i2 % 30 === 0) {
73474
- writeFileSync16(
73633
+ writeFileSync17(
73475
73634
  join44(debugDumpDir, `frame_${String(i2).padStart(4, "0")}_final_rgb48le.bin`),
73476
73635
  normalCanvas
73477
73636
  );
@@ -73701,7 +73860,7 @@ var init_shaderTransitionWorkerPool = __esm({
73701
73860
  });
73702
73861
 
73703
73862
  // ../producer/src/services/render/stages/captureHdrHybridLoop.ts
73704
- import { writeFileSync as writeFileSync17 } from "fs";
73863
+ import { writeFileSync as writeFileSync18 } from "fs";
73705
73864
  import { join as join46 } from "path";
73706
73865
  async function runHybridLayeredFrameLoop(input2) {
73707
73866
  const {
@@ -73896,7 +74055,7 @@ async function runHybridLayeredFrameLoop(input2) {
73896
74055
  await compositeHdrFrame(wctx, canvas, time, stackingInfo, void 0, i2);
73897
74056
  addHdrTiming(hdrPerf, "normalCompositeMs", timingStart);
73898
74057
  if (debugDumpEnabled && debugDumpDir && i2 % 30 === 0) {
73899
- writeFileSync17(
74058
+ writeFileSync18(
73900
74059
  join46(debugDumpDir, `frame_${String(i2).padStart(4, "0")}_final_rgb48le.bin`),
73901
74060
  canvas
73902
74061
  );
@@ -74396,13 +74555,13 @@ var init_assembleStage = __esm({
74396
74555
  import {
74397
74556
  existsSync as existsSync40,
74398
74557
  mkdirSync as mkdirSync24,
74399
- readFileSync as readFileSync28,
74558
+ readFileSync as readFileSync29,
74400
74559
  readSync,
74401
74560
  closeSync,
74402
74561
  readdirSync as readdirSync16,
74403
74562
  rmSync as rmSync9,
74404
74563
  statSync as statSync12,
74405
- writeFileSync as writeFileSync18,
74564
+ writeFileSync as writeFileSync19,
74406
74565
  copyFileSync as copyFileSync4,
74407
74566
  appendFileSync
74408
74567
  } from "fs";
@@ -75003,7 +75162,7 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
75003
75162
  const after2 = countNonZeroRgb48(canvas);
75004
75163
  const dumpName = `frame_${String(debugFrameIndex).padStart(4, "0")}_layer_${String(layerIdx).padStart(2, "0")}_dom.png`;
75005
75164
  const dumpPath = join49(debugDumpDir, dumpName);
75006
- writeFileSync18(dumpPath, domPng);
75165
+ writeFileSync19(dumpPath, domPng);
75007
75166
  log2.info("[diag] dom layer blit", {
75008
75167
  frame: debugFrameIndex,
75009
75168
  layerIdx,
@@ -75133,7 +75292,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
75133
75292
  throw new Error(`Entry file not found: ${htmlPath}`);
75134
75293
  }
75135
75294
  assertNotAborted();
75136
- const rawEntry = readFileSync28(htmlPath, "utf-8");
75295
+ const rawEntry = readFileSync29(htmlPath, "utf-8");
75137
75296
  if (entryFile !== "index.html" && rawEntry.trimStart().startsWith("<template")) {
75138
75297
  const wrapperPath = join49(workDir, "standalone-entry.html");
75139
75298
  const projectIndexPath = join49(projectDir, "index.html");
@@ -75143,7 +75302,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
75143
75302
  );
75144
75303
  }
75145
75304
  const standaloneHtml = extractStandaloneEntryFromIndex(
75146
- readFileSync28(projectIndexPath, "utf-8"),
75305
+ readFileSync29(projectIndexPath, "utf-8"),
75147
75306
  entryFile
75148
75307
  );
75149
75308
  if (!standaloneHtml) {
@@ -75151,7 +75310,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
75151
75310
  `Entry file "${entryFile}" is not mounted from index.html via data-composition-src, so it cannot be rendered independently.`
75152
75311
  );
75153
75312
  }
75154
- writeFileSync18(wrapperPath, standaloneHtml, "utf-8");
75313
+ writeFileSync19(wrapperPath, standaloneHtml, "utf-8");
75155
75314
  htmlPath = wrapperPath;
75156
75315
  log2.info("Extracted standalone entry from index.html host context", {
75157
75316
  entryFile
@@ -75538,7 +75697,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
75538
75697
  job.perfSummary = perfSummary;
75539
75698
  if (job.config.debug) {
75540
75699
  try {
75541
- writeFileSync18(perfOutputPath, JSON.stringify(perfSummary, null, 2), "utf-8");
75700
+ writeFileSync19(perfOutputPath, JSON.stringify(perfSummary, null, 2), "utf-8");
75542
75701
  } catch (err) {
75543
75702
  log2.debug("Failed to write perf summary", {
75544
75703
  perfOutputPath,
@@ -75675,7 +75834,7 @@ var init_config3 = __esm({
75675
75834
  });
75676
75835
 
75677
75836
  // ../producer/src/services/hyperframeLint.ts
75678
- import { existsSync as existsSync41, readFileSync as readFileSync29, statSync as statSync13 } from "fs";
75837
+ import { existsSync as existsSync41, readFileSync as readFileSync30, statSync as statSync13 } from "fs";
75679
75838
  import { resolve as resolve21, join as join50 } from "path";
75680
75839
  function isStringRecord(value) {
75681
75840
  if (!value || typeof value !== "object" || Array.isArray(value)) {
@@ -75718,7 +75877,7 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
75718
75877
  if (existsSync41(absoluteEntryPath) && statSync13(absoluteEntryPath).isFile()) {
75719
75878
  return {
75720
75879
  entryFile,
75721
- html: readFileSync29(absoluteEntryPath, "utf-8"),
75880
+ html: readFileSync30(absoluteEntryPath, "utf-8"),
75722
75881
  source: "projectDir"
75723
75882
  };
75724
75883
  }
@@ -75817,7 +75976,7 @@ import {
75817
75976
  mkdirSync as mkdirSync25,
75818
75977
  statSync as statSync14,
75819
75978
  mkdtempSync as mkdtempSync2,
75820
- writeFileSync as writeFileSync19,
75979
+ writeFileSync as writeFileSync20,
75821
75980
  rmSync as rmSync10,
75822
75981
  createReadStream
75823
75982
  } from "fs";
@@ -75876,7 +76035,7 @@ async function prepareRenderBody(body) {
75876
76035
  }
75877
76036
  const tempRoot = process.env.PRODUCER_TMP_PROJECT_DIR || tmpdir4();
75878
76037
  const tempProjectDir = mkdtempSync2(join51(tempRoot, "producer-project-"));
75879
- writeFileSync19(join51(tempProjectDir, "index.html"), htmlContent, "utf-8");
76038
+ writeFileSync20(join51(tempProjectDir, "index.html"), htmlContent, "utf-8");
75880
76039
  return {
75881
76040
  prepared: {
75882
76041
  input: {
@@ -76368,7 +76527,7 @@ var init_planHash = __esm({
76368
76527
  });
76369
76528
 
76370
76529
  // ../producer/src/services/render/stages/freezePlan.ts
76371
- import { existsSync as existsSync43, mkdirSync as mkdirSync26, readFileSync as readFileSync30, readdirSync as readdirSync17, writeFileSync as writeFileSync20 } from "fs";
76530
+ import { existsSync as existsSync43, mkdirSync as mkdirSync26, readFileSync as readFileSync31, readdirSync as readdirSync17, writeFileSync as writeFileSync21 } from "fs";
76372
76531
  import { join as join52, relative as relative6, resolve as resolve23 } from "path";
76373
76532
  function stripUndefined(value) {
76374
76533
  if (Array.isArray(value)) return value.map(stripUndefined);
@@ -76411,11 +76570,11 @@ function collectPlanAssetShas(planDir) {
76411
76570
  const assets = [];
76412
76571
  for (const file of files) {
76413
76572
  if (file.planRelativePath === COMPILED_INDEX_RELATIVE_PATH) {
76414
- compositionHtml = readFileSync30(file.absolutePath);
76573
+ compositionHtml = readFileSync31(file.absolutePath);
76415
76574
  continue;
76416
76575
  }
76417
76576
  if (HASH_EXCLUDED_PLAN_FILES.has(file.planRelativePath)) continue;
76418
- const bytes = readFileSync30(file.absolutePath);
76577
+ const bytes = readFileSync31(file.absolutePath);
76419
76578
  assets.push({ path: file.planRelativePath, sha256: sha256Hex(bytes) });
76420
76579
  }
76421
76580
  if (compositionHtml === null) {
@@ -76434,8 +76593,8 @@ function recomputePlanHashFromPlanDir(planDir) {
76434
76593
  if (!existsSync43(encoderJsonPath)) {
76435
76594
  throw new Error(`[freezePlan] meta/encoder.json missing: ${encoderJsonPath}`);
76436
76595
  }
76437
- const planJson = JSON.parse(readFileSync30(planJsonPath, "utf-8"));
76438
- const encoderConfigCanonicalJson = readFileSync30(encoderJsonPath, "utf-8");
76596
+ const planJson = JSON.parse(readFileSync31(planJsonPath, "utf-8"));
76597
+ const encoderConfigCanonicalJson = readFileSync31(encoderJsonPath, "utf-8");
76439
76598
  const { compositionHtml, assets } = collectPlanAssetShas(planDir);
76440
76599
  return computePlanHash({
76441
76600
  compositionHtml,
@@ -76465,7 +76624,7 @@ async function freezePlan(input2) {
76465
76624
  }
76466
76625
  const metaDir = join52(planDir, "meta");
76467
76626
  if (!existsSync43(metaDir)) mkdirSync26(metaDir, { recursive: true });
76468
- writeFileSync20(
76627
+ writeFileSync21(
76469
76628
  join52(metaDir, "composition.json"),
76470
76629
  `${JSON.stringify(composition, null, 2)}
76471
76630
  `,
@@ -76473,8 +76632,8 @@ async function freezePlan(input2) {
76473
76632
  );
76474
76633
  const encoderForCanonical = stripUndefined(encoder);
76475
76634
  const encoderConfigCanonicalJson = canonicalJsonStringify(encoderForCanonical);
76476
- writeFileSync20(join52(metaDir, "encoder.json"), encoderConfigCanonicalJson, "utf-8");
76477
- writeFileSync20(join52(metaDir, "chunks.json"), `${JSON.stringify(chunks, null, 2)}
76635
+ writeFileSync21(join52(metaDir, "encoder.json"), encoderConfigCanonicalJson, "utf-8");
76636
+ writeFileSync21(join52(metaDir, "chunks.json"), `${JSON.stringify(chunks, null, 2)}
76478
76637
  `, "utf-8");
76479
76638
  const { compositionHtml, assets } = collectPlanAssetShas(planDir);
76480
76639
  const planHash = computePlanHash({
@@ -76498,7 +76657,7 @@ async function freezePlan(input2) {
76498
76657
  hasAudio
76499
76658
  };
76500
76659
  const planJsonPath = join52(planDir, "plan.json");
76501
- writeFileSync20(planJsonPath, `${JSON.stringify(planJson, null, 2)}
76660
+ writeFileSync21(planJsonPath, `${JSON.stringify(planJson, null, 2)}
76502
76661
  `, "utf-8");
76503
76662
  return { planJsonPath, planHash };
76504
76663
  }
@@ -76606,7 +76765,7 @@ var init_runtimeEnvSnapshot = __esm({
76606
76765
  // ../producer/src/services/distributed/shared.ts
76607
76766
  import { execFile as execFileCallback } from "child_process";
76608
76767
  import { dirname as dirname17, join as join53 } from "path";
76609
- import { existsSync as existsSync44, readFileSync as readFileSync31 } from "fs";
76768
+ import { existsSync as existsSync44, readFileSync as readFileSync32 } from "fs";
76610
76769
  import { fileURLToPath as fileURLToPath5 } from "url";
76611
76770
  import { promisify as promisify2 } from "util";
76612
76771
  async function readFfmpegVersion() {
@@ -76646,7 +76805,7 @@ function readProducerVersion() {
76646
76805
  const candidate = join53(current, "package.json");
76647
76806
  if (existsSync44(candidate)) {
76648
76807
  try {
76649
- const pkg = JSON.parse(readFileSync31(candidate, "utf-8"));
76808
+ const pkg = JSON.parse(readFileSync32(candidate, "utf-8"));
76650
76809
  if (pkg.name === "@hyperframes/producer" && typeof pkg.version === "string") {
76651
76810
  cachedProducerVersion = pkg.version;
76652
76811
  return pkg.version;
@@ -76680,10 +76839,10 @@ import {
76680
76839
  existsSync as existsSync45,
76681
76840
  mkdirSync as mkdirSync27,
76682
76841
  readdirSync as readdirSync18,
76683
- renameSync as renameSync3,
76842
+ renameSync as renameSync4,
76684
76843
  rmSync as rmSync11,
76685
76844
  statSync as statSync15,
76686
- writeFileSync as writeFileSync21
76845
+ writeFileSync as writeFileSync22
76687
76846
  } from "fs";
76688
76847
  import { join as join54, relative as relative7, sep as sep6 } from "path";
76689
76848
  function formatBytes(bytes) {
@@ -76963,12 +77122,12 @@ async function plan(projectDir, config, planDir) {
76963
77122
  const videoFramesDst = join54(planDir, "video-frames");
76964
77123
  if (existsSync45(videoFramesDst)) rmSync11(videoFramesDst, { recursive: true, force: true });
76965
77124
  if (existsSync45(stagedVideoFrames)) {
76966
- renameSync3(stagedVideoFrames, videoFramesDst);
77125
+ renameSync4(stagedVideoFrames, videoFramesDst);
76967
77126
  } else {
76968
77127
  mkdirSync27(videoFramesDst, { recursive: true });
76969
77128
  }
76970
77129
  if (existsSync45(finalCompiledDir)) rmSync11(finalCompiledDir, { recursive: true, force: true });
76971
- renameSync3(compiledDir, finalCompiledDir);
77130
+ renameSync4(compiledDir, finalCompiledDir);
76972
77131
  const planVideosJson = {
76973
77132
  videos: composition.videos,
76974
77133
  extracted: (extractResult.extractionResult?.extracted ?? []).map((ext) => ({
@@ -76981,14 +77140,14 @@ async function plan(projectDir, config, planDir) {
76981
77140
  }))
76982
77141
  };
76983
77142
  mkdirSync27(join54(planDir, "meta"), { recursive: true });
76984
- writeFileSync21(
77143
+ writeFileSync22(
76985
77144
  join54(planDir, PLAN_VIDEOS_META_RELATIVE_PATH),
76986
77145
  JSON.stringify(planVideosJson, null, 2),
76987
77146
  "utf-8"
76988
77147
  );
76989
77148
  const planAudioPath = join54(planDir, "audio.aac");
76990
77149
  if (audioResult.hasAudio && existsSync45(audioResult.audioOutputPath)) {
76991
- renameSync3(audioResult.audioOutputPath, planAudioPath);
77150
+ renameSync4(audioResult.audioOutputPath, planAudioPath);
76992
77151
  }
76993
77152
  const maxParallel = config.maxParallelChunks ?? DEFAULT_MAX_PARALLEL_CHUNKS;
76994
77153
  const { chunkCount, effectiveChunkSize } = resolveChunkPlan(
@@ -77125,8 +77284,8 @@ var init_plan = __esm({
77125
77284
  });
77126
77285
 
77127
77286
  // ../producer/src/services/distributed/renderChunk.ts
77128
- import { randomBytes } from "crypto";
77129
- import { existsSync as existsSync46, mkdirSync as mkdirSync28, readFileSync as readFileSync32, readdirSync as readdirSync19, rmSync as rmSync12, writeFileSync as writeFileSync22 } from "fs";
77287
+ import { randomBytes as randomBytes2 } from "crypto";
77288
+ import { existsSync as existsSync46, mkdirSync as mkdirSync28, readFileSync as readFileSync33, readdirSync as readdirSync19, rmSync as rmSync12, writeFileSync as writeFileSync23 } from "fs";
77130
77289
  import { extname as extname9, join as join55 } from "path";
77131
77290
  function rebuildExtractedFramesFromPlanDir(planDir, videos) {
77132
77291
  const result = [];
@@ -77165,10 +77324,10 @@ function rebuildExtractedFramesFromPlanDir(planDir, videos) {
77165
77324
  return result;
77166
77325
  }
77167
77326
  function hashChunkOutput(outputPath, kind) {
77168
- if (kind === "file") return sha256Hex(readFileSync32(outputPath));
77327
+ if (kind === "file") return sha256Hex(readFileSync33(outputPath));
77169
77328
  const entries2 = readdirSync19(outputPath).filter((name) => /\.(png|jpg|jpeg)$/i.test(name)).sort();
77170
77329
  const lines = entries2.map(
77171
- (name) => `${name}\0${sha256Hex(readFileSync32(join55(outputPath, name)))}`
77330
+ (name) => `${name}\0${sha256Hex(readFileSync33(join55(outputPath, name)))}`
77172
77331
  );
77173
77332
  return sha256Hex(lines.join("\0"));
77174
77333
  }
@@ -77192,14 +77351,14 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
77192
77351
  );
77193
77352
  }
77194
77353
  }
77195
- const plan2 = JSON.parse(readFileSync32(planJsonPath, "utf-8"));
77196
- const encoder = JSON.parse(readFileSync32(encoderJsonPath, "utf-8"));
77197
- const chunks = JSON.parse(readFileSync32(chunksJsonPath, "utf-8"));
77354
+ const plan2 = JSON.parse(readFileSync33(planJsonPath, "utf-8"));
77355
+ const encoder = JSON.parse(readFileSync33(encoderJsonPath, "utf-8"));
77356
+ const chunks = JSON.parse(readFileSync33(chunksJsonPath, "utf-8"));
77198
77357
  const videosJsonPath = join55(planDir, PLAN_VIDEOS_META_RELATIVE_PATH);
77199
77358
  let planVideos = null;
77200
77359
  if (existsSync46(videosJsonPath)) {
77201
77360
  try {
77202
- planVideos = JSON.parse(readFileSync32(videosJsonPath, "utf-8"));
77361
+ planVideos = JSON.parse(readFileSync33(videosJsonPath, "utf-8"));
77203
77362
  } catch (err) {
77204
77363
  throw new RenderChunkValidationError(
77205
77364
  MISSING_PLAN_ARTIFACT,
@@ -77281,7 +77440,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
77281
77440
  rebuildExtractedFramesFromPlanDir(planDir, planVideos.extracted)
77282
77441
  )
77283
77442
  ) : null;
77284
- const workDir = `${outputChunkPath}.work.${process.pid}.${randomBytes(4).toString("hex")}`;
77443
+ const workDir = `${outputChunkPath}.work.${process.pid}.${randomBytes2(4).toString("hex")}`;
77285
77444
  mkdirSync28(workDir, { recursive: true });
77286
77445
  const framesDir = join55(workDir, "captured-frames");
77287
77446
  mkdirSync28(framesDir, { recursive: true });
@@ -77412,7 +77571,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
77412
77571
  producerVersion: plan2.producerVersion,
77413
77572
  ffmpegVersion
77414
77573
  };
77415
- writeFileSync22(perfPath, `${JSON.stringify(perfPayload2, null, 2)}
77574
+ writeFileSync23(perfPath, `${JSON.stringify(perfPayload2, null, 2)}
77416
77575
  `, "utf-8");
77417
77576
  try {
77418
77577
  rmSync12(workDir, { recursive: true, force: true });
@@ -77675,11 +77834,11 @@ import {
77675
77834
  cpSync as cpSync3,
77676
77835
  existsSync as existsSync47,
77677
77836
  mkdirSync as mkdirSync29,
77678
- readFileSync as readFileSync33,
77837
+ readFileSync as readFileSync34,
77679
77838
  readdirSync as readdirSync20,
77680
77839
  rmSync as rmSync13,
77681
77840
  statSync as statSync16,
77682
- writeFileSync as writeFileSync23
77841
+ writeFileSync as writeFileSync24
77683
77842
  } from "fs";
77684
77843
  import { dirname as dirname18, join as join56 } from "path";
77685
77844
  async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
@@ -77695,8 +77854,8 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
77695
77854
  if (!existsSync47(chunksJsonPath)) {
77696
77855
  throw new Error(`[assemble] planDir missing meta/chunks.json: ${chunksJsonPath}`);
77697
77856
  }
77698
- const plan2 = JSON.parse(readFileSync33(planJsonPath, "utf-8"));
77699
- const chunks = JSON.parse(readFileSync33(chunksJsonPath, "utf-8"));
77857
+ const plan2 = JSON.parse(readFileSync34(planJsonPath, "utf-8"));
77858
+ const chunks = JSON.parse(readFileSync34(chunksJsonPath, "utf-8"));
77700
77859
  if (chunkPaths.length !== chunks.length) {
77701
77860
  throw new Error(
77702
77861
  `[assemble] chunkPaths length (${chunkPaths.length}) does not match chunks.json length (${chunks.length}). Adapters must pass one path per chunk, ordered by index.`
@@ -77733,7 +77892,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
77733
77892
  } else {
77734
77893
  const concatListPath = join56(workDir, "concat-list.txt");
77735
77894
  const concatBody = chunkPaths.map((path2) => `file '${path2.replace(/'/g, "'\\''")}'`).join("\n");
77736
- writeFileSync23(concatListPath, `${concatBody}
77895
+ writeFileSync24(concatListPath, `${concatBody}
77737
77896
  `, "utf-8");
77738
77897
  const concatArgs = [
77739
77898
  "-r",
@@ -77767,7 +77926,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
77767
77926
  if (!existsSync47(encoderJsonPath)) {
77768
77927
  throw new Error(`[assemble] planDir missing meta/encoder.json: ${encoderJsonPath}`);
77769
77928
  }
77770
- const encoderJson = JSON.parse(readFileSync33(encoderJsonPath, "utf-8"));
77929
+ const encoderJson = JSON.parse(readFileSync34(encoderJsonPath, "utf-8"));
77771
77930
  if (encoderJson.encoder === "libx265-software") {
77772
77931
  throw new Error(
77773
77932
  `[assemble] cfr=true is not yet supported with codec: "h265". The cfr re-encode pass uses libx264 and would silently transcode the h265 chunks. Either disable cfr or render with codec: "h264".`
@@ -78028,7 +78187,7 @@ __export(studioServer_exports, {
78028
78187
  });
78029
78188
  import { Hono as Hono5 } from "hono";
78030
78189
  import { streamSSE as streamSSE3 } from "hono/streaming";
78031
- import { existsSync as existsSync48, readFileSync as readFileSync34, writeFileSync as writeFileSync24, statSync as statSync17 } from "fs";
78190
+ import { existsSync as existsSync48, readFileSync as readFileSync35, writeFileSync as writeFileSync25, statSync as statSync17 } from "fs";
78032
78191
  import { resolve as resolve24, join as join57, basename as basename5 } from "path";
78033
78192
  function resolveDistDir() {
78034
78193
  return resolveStudioBundle().dir;
@@ -78077,7 +78236,7 @@ function readStudioManualEditManifestContent(projectDir) {
78077
78236
  const manifestPath = join57(projectDir, STUDIO_MANUAL_EDITS_PATH2);
78078
78237
  if (!existsSync48(manifestPath)) return "";
78079
78238
  try {
78080
- return readFileSync34(manifestPath, "utf-8");
78239
+ return readFileSync35(manifestPath, "utf-8");
78081
78240
  } catch {
78082
78241
  return "";
78083
78242
  }
@@ -78142,7 +78301,7 @@ async function closeThumbnailBrowser() {
78142
78301
  async function loadPreviewServerBuildSignature() {
78143
78302
  const runtimeSignature = await loadRuntimeSourceSignature();
78144
78303
  const studioBundle = resolveStudioBundle();
78145
- const studioIndex = studioBundle.available && existsSync48(studioBundle.indexPath) ? readFileSync34(studioBundle.indexPath, "utf-8") : "";
78304
+ const studioIndex = studioBundle.available && existsSync48(studioBundle.indexPath) ? readFileSync35(studioBundle.indexPath, "utf-8") : "";
78146
78305
  return hashSignatureParts([
78147
78306
  VERSION,
78148
78307
  runtimeSignature,
@@ -78236,7 +78395,7 @@ function createStudioServer(options) {
78236
78395
  state.status = "complete";
78237
78396
  state.progress = 100;
78238
78397
  const metaPath = opts.outputPath.replace(/\.(mp4|webm|mov)$/, ".meta.json");
78239
- writeFileSync24(
78398
+ writeFileSync25(
78240
78399
  metaPath,
78241
78400
  JSON.stringify({ status: "complete", durationMs: Date.now() - startTime })
78242
78401
  );
@@ -78247,7 +78406,7 @@ function createStudioServer(options) {
78247
78406
  emitStudioRenderError(opts, Date.now() - startTime, state.stage, err);
78248
78407
  try {
78249
78408
  const metaPath = opts.outputPath.replace(/\.(mp4|webm|mov)$/, ".meta.json");
78250
- writeFileSync24(metaPath, JSON.stringify({ status: "failed" }));
78409
+ writeFileSync25(metaPath, JSON.stringify({ status: "failed" }));
78251
78410
  } catch {
78252
78411
  }
78253
78412
  }
@@ -78332,19 +78491,19 @@ function createStudioServer(options) {
78332
78491
  async installRegistryBlock(opts) {
78333
78492
  const { resolveItem: resolveItem2 } = await Promise.resolve().then(() => (init_resolver(), resolver_exports));
78334
78493
  const { installItem: installItem2 } = await Promise.resolve().then(() => (init_installer(), installer_exports));
78335
- const { readFileSync: readFileSync57, writeFileSync: writeFileSync39, existsSync: existsSync81 } = await import("fs");
78494
+ const { readFileSync: readFileSync58, writeFileSync: writeFileSync40, existsSync: existsSync81 } = await import("fs");
78336
78495
  const { join: join91 } = await import("path");
78337
78496
  const item = await resolveItem2(opts.blockName);
78338
78497
  const { written } = await installItem2(item, { destDir: opts.project.dir });
78339
78498
  const indexPath = join91(opts.project.dir, "index.html");
78340
78499
  if (existsSync81(indexPath)) {
78341
- const indexHtml = readFileSync57(indexPath, "utf-8");
78500
+ const indexHtml = readFileSync58(indexPath, "utf-8");
78342
78501
  const hostW = indexHtml.match(/data-width="(\d+)"/)?.[1];
78343
78502
  const hostH = indexHtml.match(/data-height="(\d+)"/)?.[1];
78344
78503
  if (hostW && hostH) {
78345
78504
  for (const absPath of written) {
78346
78505
  if (!absPath.endsWith(".html")) continue;
78347
- let content = readFileSync57(absPath, "utf-8");
78506
+ let content = readFileSync58(absPath, "utf-8");
78348
78507
  content = content.replace(
78349
78508
  /(<meta\s+name="viewport"\s+content="width=)\d+(,\s*height=)\d+/i,
78350
78509
  `$1${hostW}$2${hostH}`
@@ -78358,7 +78517,7 @@ function createStudioServer(options) {
78358
78517
  return match;
78359
78518
  }
78360
78519
  );
78361
- writeFileSync39(absPath, content, "utf-8");
78520
+ writeFileSync40(absPath, content, "utf-8");
78362
78521
  }
78363
78522
  }
78364
78523
  }
@@ -78385,7 +78544,7 @@ function createStudioServer(options) {
78385
78544
  });
78386
78545
  app.get("/api/runtime.js", (c3) => {
78387
78546
  const serve4 = async () => {
78388
- const runtimeSource = await loadRuntimeSource() ?? (existsSync48(runtimePath) ? readFileSync34(runtimePath, "utf-8") : null);
78547
+ const runtimeSource = await loadRuntimeSource() ?? (existsSync48(runtimePath) ? readFileSync35(runtimePath, "utf-8") : null);
78389
78548
  if (!runtimeSource) return c3.text("runtime not available", 404);
78390
78549
  return c3.body(runtimeSource, 200, {
78391
78550
  "Content-Type": "text/javascript",
@@ -78433,7 +78592,7 @@ function createStudioServer(options) {
78433
78592
  const serveStudioStaticFile = (c3) => {
78434
78593
  const filePath = resolve24(studioDir, c3.req.path.slice(1));
78435
78594
  if (!existsSync48(filePath) || !statSync17(filePath).isFile()) return c3.text("not found", 404);
78436
- const content = readFileSync34(filePath);
78595
+ const content = readFileSync35(filePath);
78437
78596
  return new Response(content, {
78438
78597
  headers: { "Content-Type": getMimeType(filePath), "Cache-Control": "no-store" }
78439
78598
  });
@@ -78509,7 +78668,7 @@ function createStudioServer(options) {
78509
78668
  500
78510
78669
  );
78511
78670
  }
78512
- let html = readFileSync34(indexPath, "utf-8");
78671
+ let html = readFileSync35(indexPath, "utf-8");
78513
78672
  const envScript = buildRuntimeEnvScript();
78514
78673
  if (envScript) {
78515
78674
  html = html.replace("<head>", `<head>${envScript}`);
@@ -79024,8 +79183,8 @@ import {
79024
79183
  mkdirSync as mkdirSync31,
79025
79184
  copyFileSync as copyFileSync5,
79026
79185
  cpSync as cpSync4,
79027
- writeFileSync as writeFileSync25,
79028
- readFileSync as readFileSync35,
79186
+ writeFileSync as writeFileSync26,
79187
+ readFileSync as readFileSync36,
79029
79188
  readdirSync as readdirSync21
79030
79189
  } from "fs";
79031
79190
  import { resolve as resolve26, basename as basename7, join as join59, dirname as dirname20 } from "path";
@@ -79129,7 +79288,7 @@ function buildPackageScripts() {
79129
79288
  function writeDefaultPackageJson(destDir, projectName) {
79130
79289
  const packageJsonPath = resolve26(destDir, "package.json");
79131
79290
  if (existsSync50(packageJsonPath)) return;
79132
- writeFileSync25(
79291
+ writeFileSync26(
79133
79292
  packageJsonPath,
79134
79293
  `${JSON.stringify(
79135
79294
  {
@@ -79190,14 +79349,14 @@ ${html}`;
79190
79349
  }
79191
79350
  function writeTailwindSupport(destDir) {
79192
79351
  for (const file of listHtmlFiles(destDir)) {
79193
- const html = readFileSync35(file, "utf-8");
79194
- writeFileSync25(file, injectTailwindBrowserScript(html), "utf-8");
79352
+ const html = readFileSync36(file, "utf-8");
79353
+ writeFileSync26(file, injectTailwindBrowserScript(html), "utf-8");
79195
79354
  }
79196
79355
  }
79197
79356
  function patchVideoSrc(dir, videoFilename, durationSeconds) {
79198
79357
  const htmlFiles = readdirSync21(dir, { withFileTypes: true, recursive: true }).filter((e3) => e3.isFile() && e3.name.endsWith(".html")).map((e3) => join59(e3.parentPath, e3.name));
79199
79358
  for (const file of htmlFiles) {
79200
- let content = readFileSync35(file, "utf-8");
79359
+ let content = readFileSync36(file, "utf-8");
79201
79360
  if (videoFilename) {
79202
79361
  content = content.replaceAll("__VIDEO_SRC__", videoFilename);
79203
79362
  } else {
@@ -79208,7 +79367,7 @@ function patchVideoSrc(dir, videoFilename, durationSeconds) {
79208
79367
  }
79209
79368
  const dur = durationSeconds ? String(Math.round(durationSeconds * 100) / 100) : "10";
79210
79369
  content = content.replaceAll("__VIDEO_DURATION__", dur);
79211
- writeFileSync25(file, content, "utf-8");
79370
+ writeFileSync26(file, content, "utf-8");
79212
79371
  }
79213
79372
  }
79214
79373
  async function patchTranscript(dir, transcriptPath) {
@@ -79302,7 +79461,7 @@ async function handleVideoFile(videoPath, destDir, interactive) {
79302
79461
  function applyResolutionPreset(destDir, resolution) {
79303
79462
  const { width, height } = CANVAS_DIMENSIONS[resolution];
79304
79463
  for (const file of listHtmlFiles(destDir)) {
79305
- let html = readFileSync35(file, "utf-8");
79464
+ let html = readFileSync36(file, "utf-8");
79306
79465
  let changed = false;
79307
79466
  const dataWidthRe = /(data-width=)["'](\d+)["']/g;
79308
79467
  if (dataWidthRe.test(html)) {
@@ -79344,7 +79503,7 @@ function applyResolutionPreset(destDir, resolution) {
79344
79503
  html = html.replace(viewportRe, `$1width=${width}, height=${height}`);
79345
79504
  changed = true;
79346
79505
  }
79347
- if (changed) writeFileSync25(file, html, "utf-8");
79506
+ if (changed) writeFileSync26(file, html, "utf-8");
79348
79507
  }
79349
79508
  }
79350
79509
  async function scaffoldProject(destDir, name, templateId, localVideoName, durationSeconds, tailwind = false, resolution) {
@@ -79358,7 +79517,7 @@ async function scaffoldProject(destDir, name, templateId, localVideoName, durati
79358
79517
  patchVideoSrc(destDir, localVideoName, durationSeconds);
79359
79518
  if (tailwind) writeTailwindSupport(destDir);
79360
79519
  if (resolution) applyResolutionPreset(destDir, resolution);
79361
- writeFileSync25(
79520
+ writeFileSync26(
79362
79521
  resolve26(destDir, "meta.json"),
79363
79522
  JSON.stringify(
79364
79523
  {
@@ -80297,7 +80456,7 @@ __export(play_exports, {
80297
80456
  default: () => play_default,
80298
80457
  examples: () => examples5
80299
80458
  });
80300
- import { existsSync as existsSync53, readFileSync as readFileSync36 } from "fs";
80459
+ import { existsSync as existsSync53, readFileSync as readFileSync37 } from "fs";
80301
80460
  import { resolve as resolve30, dirname as dirname21 } from "path";
80302
80461
  function commandDir() {
80303
80462
  return dirname21(new URL(import.meta.url).pathname);
@@ -80464,13 +80623,13 @@ var init_play = __esm({
80464
80623
  const { createAdaptorServer } = await import("@hono/node-server");
80465
80624
  const app = new Hono6();
80466
80625
  app.get("/player.js", (ctx) => {
80467
- return ctx.body(readFileSync36(playerPath, "utf-8"), 200, {
80626
+ return ctx.body(readFileSync37(playerPath, "utf-8"), 200, {
80468
80627
  "Content-Type": "application/javascript",
80469
80628
  "Cache-Control": "no-cache"
80470
80629
  });
80471
80630
  });
80472
80631
  app.get("/runtime.js", (ctx) => {
80473
- return ctx.body(readFileSync36(runtimePath, "utf-8"), 200, {
80632
+ return ctx.body(readFileSync37(runtimePath, "utf-8"), 200, {
80474
80633
  "Content-Type": "application/javascript",
80475
80634
  "Cache-Control": "no-cache"
80476
80635
  });
@@ -80480,7 +80639,7 @@ var init_play = __esm({
80480
80639
  const filePath = resolve30(project.dir, reqPath);
80481
80640
  if (!filePath.startsWith(project.dir)) return ctx.text("Forbidden", 403);
80482
80641
  if (!existsSync53(filePath)) return ctx.text("Not found", 404);
80483
- const content = readFileSync36(filePath, "utf-8");
80642
+ const content = readFileSync37(filePath, "utf-8");
80484
80643
  if (filePath.endsWith(".html")) {
80485
80644
  const injected = injectRuntime(content);
80486
80645
  return ctx.html(injected);
@@ -80499,7 +80658,7 @@ var init_play = __esm({
80499
80658
  mp3: "audio/mpeg",
80500
80659
  wav: "audio/wav"
80501
80660
  };
80502
- return ctx.body(readFileSync36(filePath), 200, {
80661
+ return ctx.body(readFileSync37(filePath), 200, {
80503
80662
  "Content-Type": types4[ext] ?? "application/octet-stream"
80504
80663
  });
80505
80664
  });
@@ -80561,7 +80720,7 @@ var init_play = __esm({
80561
80720
 
80562
80721
  // src/utils/publishProject.ts
80563
80722
  import { basename as basename9, join as join60, relative as relative9 } from "path";
80564
- import { readdirSync as readdirSync22, readFileSync as readFileSync37, statSync as statSync19 } from "fs";
80723
+ import { readdirSync as readdirSync22, readFileSync as readFileSync38, statSync as statSync19 } from "fs";
80565
80724
  import AdmZip from "adm-zip";
80566
80725
  function isRecord2(value) {
80567
80726
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -80680,7 +80839,7 @@ function createPublishArchive(projectDir) {
80680
80839
  }
80681
80840
  const archive = new AdmZip();
80682
80841
  for (const filePath of filePaths) {
80683
- archive.addFile(filePath, readFileSync37(join60(projectDir, filePath)));
80842
+ archive.addFile(filePath, readFileSync38(join60(projectDir, filePath)));
80684
80843
  }
80685
80844
  return {
80686
80845
  buffer: archive.toBuffer(),
@@ -80908,9 +81067,9 @@ var init_dom = __esm({
80908
81067
  });
80909
81068
 
80910
81069
  // src/utils/variables.ts
80911
- import { readFileSync as readFileSync38 } from "fs";
81070
+ import { readFileSync as readFileSync39 } from "fs";
80912
81071
  import { resolve as resolve32 } from "path";
80913
- function parseVariablesArg(inline, filePath, readFile = (p2) => readFileSync38(resolve32(p2), "utf8")) {
81072
+ function parseVariablesArg(inline, filePath, readFile = (p2) => readFileSync39(resolve32(p2), "utf8")) {
80914
81073
  if (inline != null && filePath != null) {
80915
81074
  return { ok: false, error: { kind: "conflict" } };
80916
81075
  }
@@ -80993,7 +81152,7 @@ function validateVariablesAgainstProject(indexPath, values) {
80993
81152
  function loadProjectVariableSchema(indexPath) {
80994
81153
  let html;
80995
81154
  try {
80996
- html = readFileSync38(indexPath, "utf8");
81155
+ html = readFileSync39(indexPath, "utf8");
80997
81156
  } catch {
80998
81157
  return [];
80999
81158
  }
@@ -81257,7 +81416,7 @@ __export(render_exports, {
81257
81416
  renderLocal: () => renderLocal,
81258
81417
  resolveBrowserGpuForCli: () => resolveBrowserGpuForCli
81259
81418
  });
81260
- import { mkdirSync as mkdirSync32, readdirSync as readdirSync23, readFileSync as readFileSync39, statSync as statSync20, writeFileSync as writeFileSync26, rmSync as rmSync14 } from "fs";
81419
+ import { mkdirSync as mkdirSync32, readdirSync as readdirSync23, readFileSync as readFileSync40, statSync as statSync20, writeFileSync as writeFileSync27, rmSync as rmSync14 } from "fs";
81261
81420
  import { cpus as cpus4, freemem as freemem4, tmpdir as tmpdir5 } from "os";
81262
81421
  import { resolve as resolve33, dirname as dirname22, join as join62, basename as basename11 } from "path";
81263
81422
  import { execFileSync as execFileSync6, spawn as spawn13 } from "child_process";
@@ -81318,7 +81477,7 @@ function ensureDockerImage(version, quiet) {
81318
81477
  const dockerfilePath = resolveDockerfilePath();
81319
81478
  const tmpDir = join62(tmpdir5(), `hyperframes-docker-${Date.now()}`);
81320
81479
  mkdirSync32(tmpDir, { recursive: true });
81321
- writeFileSync26(join62(tmpDir, "Dockerfile"), readFileSync39(dockerfilePath));
81480
+ writeFileSync27(join62(tmpDir, "Dockerfile"), readFileSync40(dockerfilePath));
81322
81481
  try {
81323
81482
  execFileSync6(
81324
81483
  "docker",
@@ -82183,7 +82342,7 @@ var init_lint3 = __esm({
82183
82342
 
82184
82343
  // src/utils/staticProjectServer.ts
82185
82344
  import { createServer } from "http";
82186
- import { existsSync as existsSync55, readFileSync as readFileSync40 } from "fs";
82345
+ import { existsSync as existsSync55, readFileSync as readFileSync41 } from "fs";
82187
82346
  import { isAbsolute as isAbsolute9, relative as relative10, resolve as resolve34 } from "path";
82188
82347
  async function serveStaticProjectHtml(projectDir, html, bindErrorMessage = "Failed to bind local HTTP server") {
82189
82348
  const server = createServer((req, res) => {
@@ -82202,7 +82361,7 @@ async function serveStaticProjectHtml(projectDir, html, bindErrorMessage = "Fail
82202
82361
  }
82203
82362
  if (existsSync55(filePath)) {
82204
82363
  res.writeHead(200, { "Content-Type": getMimeType(filePath) });
82205
- res.end(readFileSync40(filePath));
82364
+ res.end(readFileSync41(filePath));
82206
82365
  return;
82207
82366
  }
82208
82367
  res.writeHead(404);
@@ -82378,7 +82537,7 @@ __export(layout_exports, {
82378
82537
  default: () => layout_default,
82379
82538
  examples: () => examples9
82380
82539
  });
82381
- import { existsSync as existsSync56, readFileSync as readFileSync41 } from "fs";
82540
+ import { existsSync as existsSync56, readFileSync as readFileSync42 } from "fs";
82382
82541
  import { dirname as dirname23, join as join63 } from "path";
82383
82542
  import { fileURLToPath as fileURLToPath8 } from "url";
82384
82543
  async function getCompositionDuration2(page) {
@@ -82529,7 +82688,7 @@ function loadLayoutAuditScript() {
82529
82688
  join63(__dirname2, "commands", "layout-audit.browser.js")
82530
82689
  ];
82531
82690
  for (const candidate of candidates) {
82532
- if (existsSync56(candidate)) return readFileSync41(candidate, "utf-8");
82691
+ if (existsSync56(candidate)) return readFileSync42(candidate, "utf-8");
82533
82692
  }
82534
82693
  throw new Error("Missing layout audit browser script");
82535
82694
  }
@@ -82737,7 +82896,7 @@ __export(info_exports, {
82737
82896
  default: () => info_default,
82738
82897
  examples: () => examples11
82739
82898
  });
82740
- import { readFileSync as readFileSync42, readdirSync as readdirSync24, statSync as statSync21 } from "fs";
82899
+ import { readFileSync as readFileSync43, readdirSync as readdirSync24, statSync as statSync21 } from "fs";
82741
82900
  import { join as join64 } from "path";
82742
82901
  function totalSize(dir) {
82743
82902
  let total = 0;
@@ -82774,7 +82933,7 @@ var init_info = __esm({
82774
82933
  },
82775
82934
  async run({ args }) {
82776
82935
  const project = resolveProject(args.dir);
82777
- const html = readFileSync42(project.indexPath, "utf-8");
82936
+ const html = readFileSync43(project.indexPath, "utf-8");
82778
82937
  ensureDOMParser();
82779
82938
  const parsed = parseHtml(html);
82780
82939
  const tracks = new Set(parsed.elements.map((el) => el.zIndex));
@@ -82832,7 +82991,7 @@ __export(compositions_exports, {
82832
82991
  examples: () => examples12,
82833
82992
  parseSubComposition: () => parseSubComposition
82834
82993
  });
82835
- import { existsSync as existsSync57, readFileSync as readFileSync43 } from "fs";
82994
+ import { existsSync as existsSync57, readFileSync as readFileSync44 } from "fs";
82836
82995
  import { resolve as resolve35, dirname as dirname24 } from "path";
82837
82996
  function countRenderableDescendants(root) {
82838
82997
  return Array.from(root.querySelectorAll("*")).filter(
@@ -82867,7 +83026,7 @@ function parseCompositions(html, baseDir) {
82867
83026
  if (compositionSrc) {
82868
83027
  const subPath = resolve35(baseDir, compositionSrc);
82869
83028
  if (existsSync57(subPath)) {
82870
- const subHtml = readFileSync43(subPath, "utf-8");
83029
+ const subHtml = readFileSync44(subPath, "utf-8");
82871
83030
  const subInfo = parseSubComposition(subHtml, id, width, height);
82872
83031
  compositions.push({ ...subInfo, source: compositionSrc });
82873
83032
  return;
@@ -82970,7 +83129,7 @@ var init_compositions = __esm({
82970
83129
  },
82971
83130
  async run({ args }) {
82972
83131
  const project = resolveProject(args.dir);
82973
- const html = readFileSync43(project.indexPath, "utf-8");
83132
+ const html = readFileSync44(project.indexPath, "utf-8");
82974
83133
  ensureDOMParser();
82975
83134
  const compositions = parseCompositions(html, dirname24(project.indexPath));
82976
83135
  if (compositions.length === 0) {
@@ -84098,7 +84257,7 @@ __export(transcribe_exports2, {
84098
84257
  default: () => transcribe_default,
84099
84258
  examples: () => examples16
84100
84259
  });
84101
- import { existsSync as existsSync61, writeFileSync as writeFileSync27 } from "fs";
84260
+ import { existsSync as existsSync61, writeFileSync as writeFileSync28 } from "fs";
84102
84261
  import { resolve as resolve38, join as join67, extname as extname11, dirname as dirname25 } from "path";
84103
84262
  async function importTranscript(inputPath, dir, json) {
84104
84263
  const { loadTranscript: loadTranscript2, patchCaptionHtml: patchCaptionHtml2 } = await Promise.resolve().then(() => (init_normalize(), normalize_exports));
@@ -84108,7 +84267,7 @@ async function importTranscript(inputPath, dir, json) {
84108
84267
  process.exit(1);
84109
84268
  }
84110
84269
  const outPath = join67(dir, "transcript.json");
84111
- writeFileSync27(outPath, JSON.stringify(words, null, 2));
84270
+ writeFileSync28(outPath, JSON.stringify(words, null, 2));
84112
84271
  patchCaptionHtml2(dir, words);
84113
84272
  if (json) {
84114
84273
  console.log(
@@ -84143,7 +84302,7 @@ async function transcribeAudio(inputPath, dir, opts) {
84143
84302
  );
84144
84303
  }
84145
84304
  }
84146
- writeFileSync27(result.transcriptPath, JSON.stringify(words, null, 2));
84305
+ writeFileSync28(result.transcriptPath, JSON.stringify(words, null, 2));
84147
84306
  patchCaptionHtml2(dir, words);
84148
84307
  if (opts.json) {
84149
84308
  console.log(
@@ -84351,7 +84510,7 @@ __export(synthesize_exports, {
84351
84510
  synthesize: () => synthesize
84352
84511
  });
84353
84512
  import { execFileSync as execFileSync7 } from "child_process";
84354
- import { existsSync as existsSync63, writeFileSync as writeFileSync28, mkdirSync as mkdirSync35, readdirSync as readdirSync25, unlinkSync as unlinkSync6 } from "fs";
84513
+ import { existsSync as existsSync63, writeFileSync as writeFileSync29, mkdirSync as mkdirSync35, readdirSync as readdirSync25, unlinkSync as unlinkSync6 } from "fs";
84355
84514
  import { join as join69, dirname as dirname26, basename as basename12 } from "path";
84356
84515
  import { homedir as homedir11 } from "os";
84357
84516
  function findPython() {
@@ -84390,7 +84549,7 @@ function hasPythonPackage(python, pkg) {
84390
84549
  function ensureSynthScript() {
84391
84550
  if (!existsSync63(SCRIPT_PATH)) {
84392
84551
  mkdirSync35(SCRIPT_DIR, { recursive: true });
84393
- writeFileSync28(SCRIPT_PATH, SYNTH_SCRIPT);
84552
+ writeFileSync29(SCRIPT_PATH, SYNTH_SCRIPT);
84394
84553
  const currentName = basename12(SCRIPT_PATH);
84395
84554
  try {
84396
84555
  for (const entry of readdirSync25(SCRIPT_DIR)) {
@@ -84517,7 +84676,7 @@ __export(tts_exports, {
84517
84676
  default: () => tts_default,
84518
84677
  examples: () => examples17
84519
84678
  });
84520
- import { existsSync as existsSync64, readFileSync as readFileSync44 } from "fs";
84679
+ import { existsSync as existsSync64, readFileSync as readFileSync45 } from "fs";
84521
84680
  import { resolve as resolve39, extname as extname12 } from "path";
84522
84681
  function listVoices(json) {
84523
84682
  const rows = BUNDLED_VOICES.map((v2) => ({ ...v2, defaultLang: inferLangFromVoiceId(v2.id) }));
@@ -84628,7 +84787,7 @@ var init_tts = __esm({
84628
84787
  let text;
84629
84788
  const maybeFile = resolve39(args.input);
84630
84789
  if (existsSync64(maybeFile) && extname12(maybeFile).toLowerCase() === ".txt") {
84631
- text = readFileSync44(maybeFile, "utf-8").trim();
84790
+ text = readFileSync45(maybeFile, "utf-8").trim();
84632
84791
  if (!text) {
84633
84792
  console.error(c2.error("File is empty."));
84634
84793
  process.exit(1);
@@ -84720,7 +84879,7 @@ __export(docs_exports, {
84720
84879
  default: () => docs_default,
84721
84880
  examples: () => examples18
84722
84881
  });
84723
- import { readFileSync as readFileSync45, existsSync as existsSync65 } from "fs";
84882
+ import { readFileSync as readFileSync46, existsSync as existsSync65 } from "fs";
84724
84883
  import { resolve as resolve40, dirname as dirname27, join as join70 } from "path";
84725
84884
  import { fileURLToPath as fileURLToPath9 } from "url";
84726
84885
  function docsDir() {
@@ -84830,7 +84989,7 @@ var init_docs = __esm({
84830
84989
  console.error(c2.error(`Doc file not found: ${filePath}`));
84831
84990
  process.exit(1);
84832
84991
  }
84833
- const content = readFileSync45(filePath, "utf-8");
84992
+ const content = readFileSync46(filePath, "utf-8");
84834
84993
  console.log();
84835
84994
  renderMarkdown(content);
84836
84995
  }
@@ -85383,7 +85542,7 @@ __export(validate_exports, {
85383
85542
  default: () => validate_default,
85384
85543
  shouldIgnoreRequestFailure: () => shouldIgnoreRequestFailure
85385
85544
  });
85386
- import { existsSync as existsSync66, readFileSync as readFileSync46 } from "fs";
85545
+ import { existsSync as existsSync66, readFileSync as readFileSync47 } from "fs";
85387
85546
  import { join as join71, dirname as dirname28 } from "path";
85388
85547
  import { fileURLToPath as fileURLToPath10 } from "url";
85389
85548
  function shouldIgnoreRequestFailure(url, errorText) {
@@ -85440,7 +85599,7 @@ function loadContrastAuditScript() {
85440
85599
  join71(__dirname3, "commands", "contrast-audit.browser.js")
85441
85600
  ];
85442
85601
  for (const candidate of candidates) {
85443
- if (existsSync66(candidate)) return readFileSync46(candidate, "utf-8");
85602
+ if (existsSync66(candidate)) return readFileSync47(candidate, "utf-8");
85444
85603
  }
85445
85604
  throw new Error("Missing contrast audit browser script");
85446
85605
  }
@@ -85460,7 +85619,7 @@ async function validateInBrowser(projectDir, opts) {
85460
85619
  const filePath = join71(projectDir, decodeURIComponent(url));
85461
85620
  if (existsSync66(filePath)) {
85462
85621
  res.writeHead(200, { "Content-Type": getMimeType2(filePath) });
85463
- res.end(readFileSync46(filePath));
85622
+ res.end(readFileSync47(filePath));
85464
85623
  return;
85465
85624
  }
85466
85625
  res.writeHead(404);
@@ -85662,7 +85821,7 @@ __export(contactSheet_exports, {
85662
85821
  createSvgContactSheet: () => createSvgContactSheet
85663
85822
  });
85664
85823
  import sharp from "sharp";
85665
- import { readdirSync as readdirSync26, readFileSync as readFileSync47, writeFileSync as writeFileSync29, unlinkSync as unlinkSync7, existsSync as existsSync67 } from "fs";
85824
+ import { readdirSync as readdirSync26, readFileSync as readFileSync48, writeFileSync as writeFileSync30, unlinkSync as unlinkSync7, existsSync as existsSync67 } from "fs";
85666
85825
  import { join as join72, extname as extname13, basename as basename13, dirname as dirname29 } from "path";
85667
85826
  async function createContactSheet(imagePaths, outputPath, opts = {}) {
85668
85827
  const {
@@ -85813,12 +85972,12 @@ async function createSvgContactSheet(svgsDir, outputPath, assetsRootDir) {
85813
85972
  const svgPath = svgPaths[i2];
85814
85973
  const tmpPath = join72(tmpDir, `.thumb-${i2}.png`);
85815
85974
  try {
85816
- const svgBuf = readFileSync47(svgPath);
85975
+ const svgBuf = readFileSync48(svgPath);
85817
85976
  const thumb = await sharp(svgBuf).resize(thumbSize, thumbSize, {
85818
85977
  fit: "contain",
85819
85978
  background: { r: 245, g: 245, b: 245, alpha: 1 }
85820
85979
  }).flatten({ background: { r: 245, g: 245, b: 245 } }).png().toBuffer();
85821
- writeFileSync29(tmpPath, thumb);
85980
+ writeFileSync30(tmpPath, thumb);
85822
85981
  tmpPaths.push(tmpPath);
85823
85982
  labels.push(svgFileNames[i2].replace(".svg", ""));
85824
85983
  } catch {
@@ -106597,7 +106756,7 @@ var require_websocket = __commonJS({
106597
106756
  var http4 = __require("http");
106598
106757
  var net2 = __require("net");
106599
106758
  var tls = __require("tls");
106600
- var { randomBytes: randomBytes3, createHash: createHash9 } = __require("crypto");
106759
+ var { randomBytes: randomBytes4, createHash: createHash9 } = __require("crypto");
106601
106760
  var { Duplex, Readable: Readable3 } = __require("stream");
106602
106761
  var { URL: URL2 } = __require("url");
106603
106762
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -107127,7 +107286,7 @@ var require_websocket = __commonJS({
107127
107286
  }
107128
107287
  }
107129
107288
  const defaultPort = isSecure ? 443 : 80;
107130
- const key2 = randomBytes3(16).toString("base64");
107289
+ const key2 = randomBytes4(16).toString("base64");
107131
107290
  const request = isSecure ? https2.request : http4.request;
107132
107291
  const protocolSet = /* @__PURE__ */ new Set();
107133
107292
  let perMessageDeflate;
@@ -126371,7 +126530,7 @@ __export(snapshot_exports, {
126371
126530
  examples: () => examples23
126372
126531
  });
126373
126532
  import { spawn as spawn15 } from "child_process";
126374
- import { existsSync as existsSync68, mkdtempSync as mkdtempSync3, readFileSync as readFileSync48, mkdirSync as mkdirSync36, rmSync as rmSync15, writeFileSync as writeFileSync30 } from "fs";
126533
+ import { existsSync as existsSync68, mkdtempSync as mkdtempSync3, readFileSync as readFileSync49, mkdirSync as mkdirSync36, rmSync as rmSync15, writeFileSync as writeFileSync31 } from "fs";
126375
126534
  import { tmpdir as tmpdir6 } from "os";
126376
126535
  import { resolve as resolve41, join as join73, relative as relative11, isAbsolute as isAbsolute10 } from "path";
126377
126536
  async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDecoder = false) {
@@ -126417,7 +126576,7 @@ async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDeco
126417
126576
  }
126418
126577
  );
126419
126578
  if (result.code !== 0 || result.timedOut || !existsSync68(outPath)) return null;
126420
- return readFileSync48(outPath);
126579
+ return readFileSync49(outPath);
126421
126580
  } finally {
126422
126581
  try {
126423
126582
  rmSync15(tmp, { recursive: true, force: true });
@@ -126754,7 +126913,7 @@ ${c2.success("\u25C7")} ${paths.length} snapshots saved to snapshots/`);
126754
126913
  const filename = p2.replace("snapshots/", "");
126755
126914
  const filePath = join73(snapshotDir, filename);
126756
126915
  if (!existsSync68(filePath)) return { filename, desc: "file not found" };
126757
- const raw = readFileSync48(filePath);
126916
+ const raw = readFileSync49(filePath);
126758
126917
  let imageData;
126759
126918
  let mimeType = "image/png";
126760
126919
  if (sharpFn) {
@@ -126791,7 +126950,7 @@ ${c2.success("\u25C7")} ${paths.length} snapshots saved to snapshots/`);
126791
126950
  }
126792
126951
  }
126793
126952
  const descPath = join73(snapshotDir, "descriptions.md");
126794
- writeFileSync30(descPath, descriptions.join("\n"));
126953
+ writeFileSync31(descPath, descriptions.join("\n"));
126795
126954
  console.log(` ${c2.dim("descriptions.md")} (Gemini frame analysis)`);
126796
126955
  }
126797
126956
  } catch (descErr) {
@@ -126811,7 +126970,7 @@ ${c2.error("\u2717")} Snapshot failed: ${msg}`);
126811
126970
  });
126812
126971
 
126813
126972
  // src/capture/assetDownloader.ts
126814
- import { writeFileSync as writeFileSync31, mkdirSync as mkdirSync37 } from "fs";
126973
+ import { writeFileSync as writeFileSync32, mkdirSync as mkdirSync37 } from "fs";
126815
126974
  import { join as join74, extname as extname14 } from "path";
126816
126975
  async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks) {
126817
126976
  const assetsDir = join74(outputDir, "assets");
@@ -126835,7 +126994,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
126835
126994
  const name = `${finalSlug}.svg`;
126836
126995
  const localPath = `assets/svgs/${name}`;
126837
126996
  try {
126838
- writeFileSync31(join74(outputDir, localPath), svg.outerHTML, "utf-8");
126997
+ writeFileSync32(join74(outputDir, localPath), svg.outerHTML, "utf-8");
126839
126998
  assets.push({ url: "", localPath, type: "svg" });
126840
126999
  } catch {
126841
127000
  }
@@ -126848,7 +127007,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
126848
127007
  const localPath = `assets/${name}`;
126849
127008
  const buffer = await fetchBuffer(icon.href);
126850
127009
  if (buffer) {
126851
- writeFileSync31(join74(outputDir, localPath), buffer);
127010
+ writeFileSync32(join74(outputDir, localPath), buffer);
126852
127011
  assets.push({ url: icon.href, localPath, type: "favicon" });
126853
127012
  break;
126854
127013
  }
@@ -126905,7 +127064,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
126905
127064
  const name = `${slug}${ext}`;
126906
127065
  usedNames.add(slug);
126907
127066
  const localPath = `assets/${name}`;
126908
- writeFileSync31(join74(outputDir, localPath), buffer);
127067
+ writeFileSync32(join74(outputDir, localPath), buffer);
126909
127068
  assets.push({ url, localPath, type: "image" });
126910
127069
  imgIdx++;
126911
127070
  } catch {
@@ -126918,7 +127077,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
126918
127077
  const localPath = `assets/og-image${ext}`;
126919
127078
  const buffer = await fetchBuffer(tokens.ogImage);
126920
127079
  if (buffer && buffer.length > 5e3) {
126921
- writeFileSync31(join74(outputDir, localPath), buffer);
127080
+ writeFileSync32(join74(outputDir, localPath), buffer);
126922
127081
  assets.push({ url: tokens.ogImage, localPath, type: "image" });
126923
127082
  }
126924
127083
  } catch {
@@ -126981,7 +127140,7 @@ async function downloadAndRewriteFonts(css, outputDir) {
126981
127140
  const relativePath = `assets/fonts/${filename}`;
126982
127141
  const buffer = await fetchBuffer(fontUrl);
126983
127142
  if (buffer) {
126984
- writeFileSync31(localPath, buffer);
127143
+ writeFileSync32(localPath, buffer);
126985
127144
  rewritten = rewritten.split(fontUrl).join(relativePath);
126986
127145
  familyCounts.set(family, familyCount + 1);
126987
127146
  count++;
@@ -127948,7 +128107,7 @@ var init_designStyleExtractor = __esm({
127948
128107
  });
127949
128108
 
127950
128109
  // src/capture/fontMetadataExtractor.ts
127951
- import { readdirSync as readdirSync27, readFileSync as readFileSync49, writeFileSync as writeFileSync32, existsSync as existsSync69 } from "fs";
128110
+ import { readdirSync as readdirSync27, readFileSync as readFileSync50, writeFileSync as writeFileSync33, existsSync as existsSync69 } from "fs";
127952
128111
  import { join as join75 } from "path";
127953
128112
  import * as fontkit from "fontkit";
127954
128113
  function isFontCollection(value) {
@@ -127982,7 +128141,7 @@ function extractFontMetadata(fontsDir, outputPath) {
127982
128141
  tool: "fontkit"
127983
128142
  }
127984
128143
  };
127985
- writeFileSync32(outputPath, JSON.stringify(manifest, null, 2), "utf-8");
128144
+ writeFileSync33(outputPath, JSON.stringify(manifest, null, 2), "utf-8");
127986
128145
  return manifest;
127987
128146
  }
127988
128147
  function readSingleFont(fullPath, filename) {
@@ -127998,7 +128157,7 @@ function readSingleFont(fullPath, filename) {
127998
128157
  identified: false
127999
128158
  };
128000
128159
  try {
128001
- const buf = readFileSync49(fullPath);
128160
+ const buf = readFileSync50(fullPath);
128002
128161
  const created = fontkit.create(buf);
128003
128162
  const font = isFontCollection(created) ? created.fonts[0] : created;
128004
128163
  if (!font) return empty;
@@ -128254,7 +128413,7 @@ var init_animationCataloger = __esm({
128254
128413
  });
128255
128414
 
128256
128415
  // src/capture/mediaCapture.ts
128257
- import { mkdirSync as mkdirSync38, writeFileSync as writeFileSync33, readdirSync as readdirSync28, readFileSync as readFileSync50, statSync as statSync24 } from "fs";
128416
+ import { mkdirSync as mkdirSync38, writeFileSync as writeFileSync34, readdirSync as readdirSync28, readFileSync as readFileSync51, statSync as statSync24 } from "fs";
128258
128417
  import { join as join76 } from "path";
128259
128418
  async function saveLottieAnimations(discoveredLotties, lottieDir) {
128260
128419
  let savedCount = 0;
@@ -128288,7 +128447,7 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
128288
128447
  const hash2 = buf.toString("base64").slice(0, 100);
128289
128448
  if (savedHashes.has(hash2)) continue;
128290
128449
  savedHashes.add(hash2);
128291
- writeFileSync33(join76(lottieDir, `animation-${savedCount}.lottie`), buf);
128450
+ writeFileSync34(join76(lottieDir, `animation-${savedCount}.lottie`), buf);
128292
128451
  savedCount++;
128293
128452
  continue;
128294
128453
  }
@@ -128306,7 +128465,7 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
128306
128465
  } catch {
128307
128466
  continue;
128308
128467
  }
128309
- writeFileSync33(join76(lottieDir, `animation-${savedCount}.json`), jsonData, "utf-8");
128468
+ writeFileSync34(join76(lottieDir, `animation-${savedCount}.json`), jsonData, "utf-8");
128310
128469
  savedCount++;
128311
128470
  }
128312
128471
  } catch {
@@ -128321,7 +128480,7 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
128321
128480
  for (const file of readdirSync28(lottieDir)) {
128322
128481
  if (!file.endsWith(".json")) continue;
128323
128482
  try {
128324
- const raw = JSON.parse(readFileSync50(join76(lottieDir, file), "utf-8"));
128483
+ const raw = JSON.parse(readFileSync51(join76(lottieDir, file), "utf-8"));
128325
128484
  const fr = raw.fr || 30;
128326
128485
  const dur = ((raw.op || 0) - (raw.ip || 0)) / fr;
128327
128486
  const previewName = file.replace(".json", "-preview.png");
@@ -128331,7 +128490,7 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
128331
128490
  try {
128332
128491
  previewPage = await chromeBrowser.newPage();
128333
128492
  await previewPage.setViewport({ width: 400, height: 400 });
128334
- const animData = JSON.parse(readFileSync50(join76(lottieDir, file), "utf-8"));
128493
+ const animData = JSON.parse(readFileSync51(join76(lottieDir, file), "utf-8"));
128335
128494
  const midFrame = Math.floor(((raw.op || 0) - (raw.ip || 0)) * 0.3);
128336
128495
  await previewPage.setContent(
128337
128496
  `<!DOCTYPE html>
@@ -128384,7 +128543,7 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
128384
128543
  }
128385
128544
  }
128386
128545
  if (manifest.length > 0) {
128387
- writeFileSync33(
128546
+ writeFileSync34(
128388
128547
  join76(outputDir, "extracted", "lottie-manifest.json"),
128389
128548
  JSON.stringify(manifest, null, 2),
128390
128549
  "utf-8"
@@ -128493,7 +128652,7 @@ async function captureVideoManifest(page, outputDir, progress) {
128493
128652
  });
128494
128653
  }
128495
128654
  if (videoManifest.length > 0) {
128496
- writeFileSync33(
128655
+ writeFileSync34(
128497
128656
  join76(outputDir, "extracted", "video-manifest.json"),
128498
128657
  JSON.stringify(videoManifest, null, 2),
128499
128658
  "utf-8"
@@ -128510,7 +128669,7 @@ var init_mediaCapture = __esm({
128510
128669
  });
128511
128670
 
128512
128671
  // src/capture/contentExtractor.ts
128513
- import { existsSync as existsSync70, readdirSync as readdirSync29, statSync as statSync25, readFileSync as readFileSync51 } from "fs";
128672
+ import { existsSync as existsSync70, readdirSync as readdirSync29, statSync as statSync25, readFileSync as readFileSync52 } from "fs";
128514
128673
  import { join as join77 } from "path";
128515
128674
  async function detectLibraries(page, capturedShaders) {
128516
128675
  let detectedLibraries = [];
@@ -128643,7 +128802,7 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
128643
128802
  const filePath = join77(outputDir, "assets", file);
128644
128803
  const stat3 = statSync25(filePath);
128645
128804
  if (stat3.size > 4e6) return { file, caption: "" };
128646
- const buffer = readFileSync51(filePath);
128805
+ const buffer = readFileSync52(filePath);
128647
128806
  const base64 = buffer.toString("base64");
128648
128807
  const ext = file.split(".").pop()?.toLowerCase() || "png";
128649
128808
  const mimeType = ext === "jpg" ? "image/jpeg" : `image/${ext}`;
@@ -128699,7 +128858,7 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
128699
128858
  const results = await Promise.allSettled(
128700
128859
  batch.map(async ({ relPath }) => {
128701
128860
  const filePath = join77(assetsDir, relPath);
128702
- let svgText = readFileSync51(filePath, "utf-8");
128861
+ let svgText = readFileSync52(filePath, "utf-8");
128703
128862
  if (svgText.length > MAX_SVG_CHARS) {
128704
128863
  svgText = svgText.slice(0, MAX_SVG_CHARS) + "\n<!-- truncated -->";
128705
128864
  }
@@ -128817,7 +128976,7 @@ var agentPromptGenerator_exports = {};
128817
128976
  __export(agentPromptGenerator_exports, {
128818
128977
  generateAgentPrompt: () => generateAgentPrompt
128819
128978
  });
128820
- import { writeFileSync as writeFileSync34, readdirSync as readdirSync30, existsSync as existsSync71 } from "fs";
128979
+ import { writeFileSync as writeFileSync35, readdirSync as readdirSync30, existsSync as existsSync71 } from "fs";
128821
128980
  import { join as join78 } from "path";
128822
128981
  function inferColorRole(hex) {
128823
128982
  const r2 = parseInt(hex.slice(1, 3), 16) / 255;
@@ -128837,9 +128996,9 @@ function inferColorRole(hex) {
128837
128996
  }
128838
128997
  function generateAgentPrompt(outputDir, url, tokens, _animations, hasScreenshot, hasLottie, hasShaders, _catalogedAssets, _detectedLibraries) {
128839
128998
  const prompt = buildPrompt(outputDir, url, tokens, hasScreenshot, hasLottie, hasShaders);
128840
- writeFileSync34(join78(outputDir, "AGENTS.md"), prompt, "utf-8");
128841
- writeFileSync34(join78(outputDir, "CLAUDE.md"), prompt, "utf-8");
128842
- writeFileSync34(join78(outputDir, ".cursorrules"), prompt, "utf-8");
128999
+ writeFileSync35(join78(outputDir, "AGENTS.md"), prompt, "utf-8");
129000
+ writeFileSync35(join78(outputDir, "CLAUDE.md"), prompt, "utf-8");
129001
+ writeFileSync35(join78(outputDir, ".cursorrules"), prompt, "utf-8");
128843
129002
  }
128844
129003
  function buildPrompt(outputDir, url, tokens, hasScreenshot, hasLottie, hasShaders) {
128845
129004
  const title = tokens.title || new URL(url).hostname.replace(/^www\./, "");
@@ -128952,7 +129111,7 @@ var init_agentPromptGenerator = __esm({
128952
129111
  });
128953
129112
 
128954
129113
  // src/capture/scaffolding.ts
128955
- import { existsSync as existsSync72, writeFileSync as writeFileSync35, readFileSync as readFileSync52 } from "fs";
129114
+ import { existsSync as existsSync72, writeFileSync as writeFileSync36, readFileSync as readFileSync53 } from "fs";
128956
129115
  import { join as join79, resolve as resolve42 } from "path";
128957
129116
  function loadEnvFile(startDir) {
128958
129117
  try {
@@ -128960,7 +129119,7 @@ function loadEnvFile(startDir) {
128960
129119
  for (let i2 = 0; i2 < 5; i2++) {
128961
129120
  const envPath = resolve42(dir, ".env");
128962
129121
  try {
128963
- const envContent = readFileSync52(envPath, "utf-8");
129122
+ const envContent = readFileSync53(envPath, "utf-8");
128964
129123
  for (const line of envContent.split("\n")) {
128965
129124
  const trimmed = line.trim();
128966
129125
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -128982,7 +129141,7 @@ async function generateProjectScaffold(outputDir, url, tokens, animationCatalog,
128982
129141
  const metaPath = join79(outputDir, "meta.json");
128983
129142
  if (!existsSync72(metaPath)) {
128984
129143
  const hostname = new URL(url).hostname.replace(/^www\./, "");
128985
- writeFileSync35(
129144
+ writeFileSync36(
128986
129145
  metaPath,
128987
129146
  JSON.stringify({ id: hostname + "-video", name: tokens.title || hostname }, null, 2),
128988
129147
  "utf-8"
@@ -129017,7 +129176,7 @@ var screenshotCapture_exports = {};
129017
129176
  __export(screenshotCapture_exports, {
129018
129177
  captureScrollScreenshots: () => captureScrollScreenshots
129019
129178
  });
129020
- import { writeFileSync as writeFileSync36, mkdirSync as mkdirSync39 } from "fs";
129179
+ import { writeFileSync as writeFileSync37, mkdirSync as mkdirSync39 } from "fs";
129021
129180
  import { join as join80 } from "path";
129022
129181
  async function captureScrollScreenshots(page, outputDir) {
129023
129182
  const screenshotsDir = join80(outputDir, "screenshots");
@@ -129114,7 +129273,7 @@ async function captureScrollScreenshots(page, outputDir) {
129114
129273
  const filename = `scroll-${String(Math.min(pct, 100)).padStart(3, "0")}.png`;
129115
129274
  const filePath = join80(screenshotsDir, filename);
129116
129275
  const buffer = await page.screenshot({ type: "png" });
129117
- writeFileSync36(filePath, buffer);
129276
+ writeFileSync37(filePath, buffer);
129118
129277
  filePaths.push(`screenshots/${filename}`);
129119
129278
  }
129120
129279
  await page.evaluate(`window.scrollTo(0, 0)`);
@@ -129387,7 +129546,7 @@ var capture_exports = {};
129387
129546
  __export(capture_exports, {
129388
129547
  captureWebsite: () => captureWebsite
129389
129548
  });
129390
- import { mkdirSync as mkdirSync40, writeFileSync as writeFileSync37, existsSync as existsSync73 } from "fs";
129549
+ import { mkdirSync as mkdirSync40, writeFileSync as writeFileSync38, existsSync as existsSync73 } from "fs";
129391
129550
  import { join as join81 } from "path";
129392
129551
  async function captureWebsite(opts, onProgress) {
129393
129552
  const {
@@ -129582,7 +129741,7 @@ async function captureWebsite(opts, onProgress) {
129582
129741
  return true;
129583
129742
  });
129584
129743
  capturedShaders = unique;
129585
- writeFileSync37(
129744
+ writeFileSync38(
129586
129745
  join81(outputDir, "extracted", "shaders.json"),
129587
129746
  JSON.stringify(unique, null, 2),
129588
129747
  "utf-8"
@@ -129597,7 +129756,7 @@ async function captureWebsite(opts, onProgress) {
129597
129756
  ...tokens,
129598
129757
  svgs: tokens.svgs.map(({ outerHTML: _, ...rest }) => rest)
129599
129758
  };
129600
- writeFileSync37(
129759
+ writeFileSync38(
129601
129760
  join81(outputDir, "extracted", "tokens.json"),
129602
129761
  JSON.stringify(tokensForDisk, null, 2),
129603
129762
  "utf-8"
@@ -129605,7 +129764,7 @@ async function captureWebsite(opts, onProgress) {
129605
129764
  progress("style", "Extracting design styles...");
129606
129765
  try {
129607
129766
  const designStyles = await extractDesignStyles(page1);
129608
- writeFileSync37(
129767
+ writeFileSync38(
129609
129768
  join81(outputDir, "extracted", "design-styles.json"),
129610
129769
  JSON.stringify(designStyles, null, 2),
129611
129770
  "utf-8"
@@ -129709,7 +129868,7 @@ ${err.stack}` : String(err);
129709
129868
  scrollTriggeredElements: (animationCatalog.scrollTargets || []).length,
129710
129869
  representativeAnimations: representativeAnims
129711
129870
  };
129712
- writeFileSync37(
129871
+ writeFileSync38(
129713
129872
  join81(outputDir, "extracted", "animations.json"),
129714
129873
  JSON.stringify(leanCatalog, null, 2),
129715
129874
  "utf-8"
@@ -129721,14 +129880,14 @@ ${err.stack}` : String(err);
129721
129880
  assets = await downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks);
129722
129881
  }
129723
129882
  if (visibleTextContent) {
129724
- writeFileSync37(join81(outputDir, "extracted", "visible-text.txt"), visibleTextContent, "utf-8");
129883
+ writeFileSync38(join81(outputDir, "extracted", "visible-text.txt"), visibleTextContent, "utf-8");
129725
129884
  }
129726
129885
  const geminiCaptions = await captionImagesWithGemini(outputDir, progress, warnings);
129727
129886
  progress("design", "Generating asset descriptions...");
129728
129887
  try {
129729
129888
  const lines = generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCaptions);
129730
129889
  if (lines.length > 0) {
129731
- writeFileSync37(
129890
+ writeFileSync38(
129732
129891
  join81(outputDir, "extracted", "asset-descriptions.md"),
129733
129892
  "# Asset Descriptions\n\nOne line per file. Read this instead of opening every image individually.\n\n" + lines.map((l) => "- " + l).join("\n") + "\n",
129734
129893
  "utf-8"
@@ -129960,11 +130119,11 @@ var init_capture2 = __esm({
129960
130119
  } catch (err) {
129961
130120
  const errMsg = err instanceof Error ? err.message : String(err);
129962
130121
  try {
129963
- const { mkdirSync: mkdirSync44, writeFileSync: writeFileSync39 } = await import("fs");
130122
+ const { mkdirSync: mkdirSync44, writeFileSync: writeFileSync40 } = await import("fs");
129964
130123
  mkdirSync44(outputDir, { recursive: true });
129965
130124
  const isTimeout = /timeout|timed out/i.test(errMsg);
129966
130125
  const reason = isTimeout ? "Page navigation timed out \u2014 the site may be blocking headless browsers or requires authentication." : `Capture failed: ${errMsg}`;
129967
- writeFileSync39(
130126
+ writeFileSync40(
129968
130127
  `${outputDir}/BLOCKED.md`,
129969
130128
  `# Capture Failed
129970
130129
 
@@ -130007,7 +130166,7 @@ __export(state_exports, {
130007
130166
  stateFilePath: () => stateFilePath,
130008
130167
  writeStackOutputs: () => writeStackOutputs
130009
130168
  });
130010
- import { existsSync as existsSync74, mkdirSync as mkdirSync41, readdirSync as readdirSync31, readFileSync as readFileSync53, rmSync as rmSync16, writeFileSync as writeFileSync38 } from "fs";
130169
+ import { existsSync as existsSync74, mkdirSync as mkdirSync41, readdirSync as readdirSync31, readFileSync as readFileSync54, rmSync as rmSync16, writeFileSync as writeFileSync39 } from "fs";
130011
130170
  import { dirname as dirname30, join as join82 } from "path";
130012
130171
  function stateFilePath(stackName = DEFAULT_STACK_NAME, cwd = process.cwd()) {
130013
130172
  return join82(cwd, STATE_DIR_NAME, `${STATE_FILE_PREFIX}${stackName}.json`);
@@ -130015,14 +130174,14 @@ function stateFilePath(stackName = DEFAULT_STACK_NAME, cwd = process.cwd()) {
130015
130174
  function writeStackOutputs(outputs, cwd = process.cwd()) {
130016
130175
  const path2 = stateFilePath(outputs.stackName, cwd);
130017
130176
  mkdirSync41(dirname30(path2), { recursive: true });
130018
- writeFileSync38(path2, JSON.stringify(outputs, null, 2) + "\n");
130177
+ writeFileSync39(path2, JSON.stringify(outputs, null, 2) + "\n");
130019
130178
  return path2;
130020
130179
  }
130021
130180
  function readStackOutputs(stackName = DEFAULT_STACK_NAME, cwd = process.cwd()) {
130022
130181
  const path2 = stateFilePath(stackName, cwd);
130023
130182
  if (!existsSync74(path2)) return null;
130024
130183
  try {
130025
- return JSON.parse(readFileSync53(path2, "utf-8"));
130184
+ return JSON.parse(readFileSync54(path2, "utf-8"));
130026
130185
  } catch {
130027
130186
  return null;
130028
130187
  }
@@ -130344,14 +130503,14 @@ var init_sites = __esm({
130344
130503
  });
130345
130504
 
130346
130505
  // src/commands/lambda/_dimensions.ts
130347
- import { readFileSync as readFileSync54 } from "fs";
130506
+ import { readFileSync as readFileSync55 } from "fs";
130348
130507
  import { join as join85 } from "path";
130349
130508
  function warnOnDimensionMismatch(args) {
130350
130509
  if (args.quiet) return;
130351
130510
  if (args.outputResolution) return;
130352
130511
  let html;
130353
130512
  try {
130354
- html = readFileSync54(join85(args.projectDir, "index.html"), "utf-8");
130513
+ html = readFileSync55(join85(args.projectDir, "index.html"), "utf-8");
130355
130514
  } catch {
130356
130515
  return;
130357
130516
  }
@@ -130520,7 +130679,7 @@ __export(render_batch_exports, {
130520
130679
  runRenderBatch: () => runRenderBatch,
130521
130680
  runWithConcurrencyLimit: () => runWithConcurrencyLimit
130522
130681
  });
130523
- import { existsSync as existsSync79, readFileSync as readFileSync55 } from "fs";
130682
+ import { existsSync as existsSync79, readFileSync as readFileSync56 } from "fs";
130524
130683
  import { join as join87, resolve as resolvePath3 } from "path";
130525
130684
  async function loadSDK3() {
130526
130685
  return import("@hyperframes/aws-lambda/sdk");
@@ -130672,7 +130831,7 @@ function makePlaceholderSiteHandle(siteId, bucketName) {
130672
130831
  };
130673
130832
  }
130674
130833
  function parseBatchFile(path2) {
130675
- const raw = readFileSync55(path2, "utf8");
130834
+ const raw = readFileSync56(path2, "utf8");
130676
130835
  const lines = raw.split(/\r?\n/);
130677
130836
  const out = [];
130678
130837
  for (let i2 = 0; i2 < lines.length; i2++) {
@@ -130866,7 +131025,7 @@ __export(policies_exports, {
130866
131025
  runPolicies: () => runPolicies,
130867
131026
  validatePolicy: () => validatePolicy
130868
131027
  });
130869
- import { readFileSync as readFileSync56 } from "fs";
131028
+ import { readFileSync as readFileSync57 } from "fs";
130870
131029
  function allRequiredActions() {
130871
131030
  const set = /* @__PURE__ */ new Set();
130872
131031
  for (const group of Object.values(REQUIRED_ACTIONS)) {
@@ -130972,7 +131131,7 @@ async function runPolicies(args) {
130972
131131
  }
130973
131132
  }
130974
131133
  function validatePolicy(policyPath) {
130975
- const raw = readFileSync56(policyPath, "utf-8");
131134
+ const raw = readFileSync57(policyPath, "utf-8");
130976
131135
  const parsed = JSON.parse(raw);
130977
131136
  const statements = Array.isArray(parsed.Statement) ? parsed.Statement : parsed.Statement ? [
130978
131137
  parsed.Statement
@@ -132082,14 +132241,14 @@ var init_client3 = __esm({
132082
132241
  });
132083
132242
 
132084
132243
  // src/auth/pkce.ts
132085
- import { createHash as createHash8, randomBytes as randomBytes2 } from "crypto";
132244
+ import { createHash as createHash8, randomBytes as randomBytes3 } from "crypto";
132086
132245
  function generatePkcePair() {
132087
- const verifier = base64UrlEncode(randomBytes2(VERIFIER_BYTES));
132246
+ const verifier = base64UrlEncode(randomBytes3(VERIFIER_BYTES));
132088
132247
  const challenge = base64UrlEncode(createHash8("sha256").update(verifier).digest());
132089
132248
  return { verifier, challenge, method: "S256" };
132090
132249
  }
132091
132250
  function generateState() {
132092
- return base64UrlEncode(randomBytes2(32));
132251
+ return base64UrlEncode(randomBytes3(32));
132093
132252
  }
132094
132253
  function base64UrlEncode(buf) {
132095
132254
  return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
@@ -134778,10 +134937,10 @@ if (rootVersionRequested) {
134778
134937
  process.exit(0);
134779
134938
  }
134780
134939
  try {
134781
- const { readFileSync: readFileSync57 } = await import("fs");
134940
+ const { readFileSync: readFileSync58 } = await import("fs");
134782
134941
  const { resolve: resolve46 } = await import("path");
134783
134942
  const envPath = resolve46(process.cwd(), ".env");
134784
- const envContent = readFileSync57(envPath, "utf-8");
134943
+ const envContent = readFileSync58(envPath, "utf-8");
134785
134944
  for (const rawLine of envContent.split("\n")) {
134786
134945
  let line = rawLine.trim();
134787
134946
  if (!line || line.startsWith("#")) continue;