hyperframes 0.6.7 → 0.6.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -54,7 +54,7 @@ var VERSION;
54
54
  var init_version = __esm({
55
55
  "src/version.ts"() {
56
56
  "use strict";
57
- VERSION = true ? "0.6.7" : "0.0.0-dev";
57
+ VERSION = true ? "0.6.9" : "0.0.0-dev";
58
58
  }
59
59
  });
60
60
 
@@ -4563,8 +4563,13 @@ function compileTag(tag, isVideo2, generateId) {
4563
4563
  id = `${isVideo2 ? "hf-video" : "hf-audio"}-${generateId()}`;
4564
4564
  result = injectAttr(result, "id", id);
4565
4565
  }
4566
- const startStr = getAttr(result, "data-start");
4567
- const start = startStr !== null ? parseFloat(startStr) : 0;
4566
+ let startStr = getAttr(result, "data-start");
4567
+ if (startStr === null) {
4568
+ result = injectAttr(result, "data-start", "0");
4569
+ result = injectAttr(result, "data-hf-auto-start", "");
4570
+ startStr = "0";
4571
+ }
4572
+ const start = parseFloat(startStr);
4568
4573
  const mediaStartStr = getAttr(result, "data-media-start");
4569
4574
  const mediaStart = mediaStartStr ? parseFloat(mediaStartStr) : 0;
4570
4575
  if (!hasAttr(result, "data-end")) {
@@ -11433,7 +11438,7 @@ import { get as httpsGet } from "https";
11433
11438
  import { pipeline } from "stream/promises";
11434
11439
  function downloadFile(url, dest) {
11435
11440
  const tmp = `${dest}.tmp`;
11436
- return new Promise((resolve42, reject) => {
11441
+ return new Promise((resolve43, reject) => {
11437
11442
  const follow = (u) => {
11438
11443
  httpsGet(u, (res) => {
11439
11444
  if (res.statusCode === 301 || res.statusCode === 302) {
@@ -11450,7 +11455,7 @@ function downloadFile(url, dest) {
11450
11455
  const file = createWriteStream(tmp);
11451
11456
  pipeline(res, file).then(() => {
11452
11457
  renameSync(tmp, dest);
11453
- resolve42();
11458
+ resolve43();
11454
11459
  }).catch((err) => {
11455
11460
  try {
11456
11461
  unlinkSync(tmp);
@@ -12175,7 +12180,7 @@ function hasNpx() {
12175
12180
  }
12176
12181
  }
12177
12182
  function runSkillsAdd(repo) {
12178
- return new Promise((resolve42, reject) => {
12183
+ return new Promise((resolve43, reject) => {
12179
12184
  const child = spawn("npx", ["skills", "add", repo, "--all"], {
12180
12185
  stdio: "inherit",
12181
12186
  timeout: 12e4,
@@ -12189,7 +12194,7 @@ function runSkillsAdd(repo) {
12189
12194
  env: { ...process.env, GIT_CLONE_PROTECTION_ACTIVE: "0" }
12190
12195
  });
12191
12196
  child.on("close", (code, signal) => {
12192
- if (code === 0) resolve42();
12197
+ if (code === 0) resolve43();
12193
12198
  else if (signal === "SIGINT" || code === 130) process.exit(0);
12194
12199
  else reject(new Error(`npx skills add exited with code ${code}`));
12195
12200
  });
@@ -13073,7 +13078,7 @@ function computePeaks(floats, count) {
13073
13078
  return peaks.map((p2) => p2 / maxPeak);
13074
13079
  }
13075
13080
  function decodeAudioPeaks(audioPath) {
13076
- return new Promise((resolve42, reject) => {
13081
+ return new Promise((resolve43, reject) => {
13077
13082
  const proc = spawn2(
13078
13083
  "ffmpeg",
13079
13084
  [
@@ -13106,7 +13111,7 @@ function decodeAudioPeaks(audioPath) {
13106
13111
  return;
13107
13112
  }
13108
13113
  const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + numSamples * 4);
13109
- resolve42(computePeaks(new Float32Array(ab), PEAK_COUNT));
13114
+ resolve43(computePeaks(new Float32Array(ab), PEAK_COUNT));
13110
13115
  });
13111
13116
  proc.on("error", reject);
13112
13117
  });
@@ -17046,8 +17051,8 @@ var init_custom_element_registry = __esm({
17046
17051
  } : (element) => element.localName === localName;
17047
17052
  registry.set(localName, { Class, check });
17048
17053
  if (waiting.has(localName)) {
17049
- for (const resolve42 of waiting.get(localName))
17050
- resolve42(Class);
17054
+ for (const resolve43 of waiting.get(localName))
17055
+ resolve43(Class);
17051
17056
  waiting.delete(localName);
17052
17057
  }
17053
17058
  ownerDocument.querySelectorAll(
@@ -17087,13 +17092,13 @@ var init_custom_element_registry = __esm({
17087
17092
  */
17088
17093
  whenDefined(localName) {
17089
17094
  const { registry, waiting } = this;
17090
- return new Promise((resolve42) => {
17095
+ return new Promise((resolve43) => {
17091
17096
  if (registry.has(localName))
17092
- resolve42(registry.get(localName).Class);
17097
+ resolve43(registry.get(localName).Class);
17093
17098
  else {
17094
17099
  if (!waiting.has(localName))
17095
17100
  waiting.set(localName, []);
17096
- waiting.get(localName).push(resolve42);
17101
+ waiting.get(localName).push(resolve43);
17097
17102
  }
17098
17103
  });
17099
17104
  }
@@ -22799,12 +22804,12 @@ var require_CSSValueExpression = __commonJS({
22799
22804
  return false;
22800
22805
  }
22801
22806
  };
22802
- CSSOM.CSSValueExpression.prototype._parseJSString = function(token, idx, sep6) {
22803
- var endIdx = this._findMatchedIdx(token, idx, sep6), text;
22807
+ CSSOM.CSSValueExpression.prototype._parseJSString = function(token, idx, sep7) {
22808
+ var endIdx = this._findMatchedIdx(token, idx, sep7), text;
22804
22809
  if (endIdx === -1) {
22805
22810
  return false;
22806
22811
  } else {
22807
- text = token.substring(idx, endIdx + sep6.length);
22812
+ text = token.substring(idx, endIdx + sep7.length);
22808
22813
  return {
22809
22814
  idx: endIdx,
22810
22815
  text
@@ -22844,15 +22849,15 @@ var require_CSSValueExpression = __commonJS({
22844
22849
  if (!isLegal) {
22845
22850
  return false;
22846
22851
  } else {
22847
- var sep6 = "/";
22848
- return this._parseJSString(token, idx, sep6);
22852
+ var sep7 = "/";
22853
+ return this._parseJSString(token, idx, sep7);
22849
22854
  }
22850
22855
  };
22851
- CSSOM.CSSValueExpression.prototype._findMatchedIdx = function(token, idx, sep6) {
22856
+ CSSOM.CSSValueExpression.prototype._findMatchedIdx = function(token, idx, sep7) {
22852
22857
  var startIdx = idx, endIdx;
22853
22858
  var NOT_FOUND = -1;
22854
22859
  while (true) {
22855
- endIdx = token.indexOf(sep6, startIdx + 1);
22860
+ endIdx = token.indexOf(sep7, startIdx + 1);
22856
22861
  if (endIdx === -1) {
22857
22862
  endIdx = NOT_FOUND;
22858
22863
  break;
@@ -25924,8 +25929,14 @@ function updateReferences(projectDir, oldPath, newPath) {
25924
25929
  }
25925
25930
  function registerFileRoutes(api, adapter2) {
25926
25931
  api.get("/projects/:id/files/*", async (c3) => {
25927
- const res = await resolveProjectFile(c3, adapter2, { mustExist: true });
25932
+ const res = await resolveProjectFile(c3, adapter2);
25928
25933
  if ("error" in res) return res.error;
25934
+ if (!existsSync10(res.absPath)) {
25935
+ if (c3.req.query("optional") === "1") {
25936
+ return c3.json({ filename: res.filePath, content: "" });
25937
+ }
25938
+ return c3.json({ error: "not found" }, 404);
25939
+ }
25929
25940
  const content = readFileSync10(res.absPath, "utf-8");
25930
25941
  return c3.json({ filename: res.filePath, content });
25931
25942
  });
@@ -26987,7 +26998,7 @@ var init_lint2 = __esm({
26987
26998
  // ../core/src/studio-api/routes/render.ts
26988
26999
  import { streamSSE } from "hono/streaming";
26989
27000
  import { existsSync as existsSync13, readFileSync as readFileSync15, mkdirSync as mkdirSync7, unlinkSync as unlinkSync4, readdirSync as readdirSync6, statSync as statSync3 } from "fs";
26990
- import { join as join17 } from "path";
27001
+ import { join as join17, resolve as resolve12, sep as sep2 } from "path";
26991
27002
  function registerRenderRoutes(api, adapter2) {
26992
27003
  const renderJobs = /* @__PURE__ */ new Map();
26993
27004
  const TTL_MS = 3e5;
@@ -27025,6 +27036,14 @@ function registerRenderRoutes(api, adapter2) {
27025
27036
  const fps = fpsParse && fpsParse.ok ? fpsParse.value : { num: 30, den: 1 };
27026
27037
  const quality = ["draft", "standard", "high"].includes(body.quality ?? "") ? body.quality : "standard";
27027
27038
  const outputResolution = VALID_RESOLUTIONS.has(body.resolution ?? "") ? body.resolution : void 0;
27039
+ let composition;
27040
+ if (typeof body.composition === "string" && body.composition.length > 0) {
27041
+ const resolved = resolve12(project.dir, body.composition);
27042
+ if (!resolved.startsWith(resolve12(project.dir) + sep2)) {
27043
+ return c3.json({ error: "composition path must be within the project directory" }, 400);
27044
+ }
27045
+ composition = body.composition;
27046
+ }
27028
27047
  const now = /* @__PURE__ */ new Date();
27029
27048
  const datePart = now.toISOString().slice(0, 10);
27030
27049
  const timePart = now.toTimeString().slice(0, 8).replace(/:/g, "-");
@@ -27040,7 +27059,8 @@ function registerRenderRoutes(api, adapter2) {
27040
27059
  fps,
27041
27060
  quality,
27042
27061
  jobId,
27043
- outputResolution
27062
+ outputResolution,
27063
+ composition
27044
27064
  });
27045
27065
  jobState.createdAt = Date.now();
27046
27066
  renderJobs.set(jobId, jobState);
@@ -27215,8 +27235,10 @@ function studioPositionSeekReapplyRuntime() {
27215
27235
  const ROTATION_ATTR = "data-hf-studio-rotation";
27216
27236
  const ORIGINAL_TRANSLATE_ATTR = "data-hf-studio-original-translate";
27217
27237
  const ORIGINAL_ROTATE_ATTR = "data-hf-studio-original-rotate";
27238
+ const MOTION_ATTR = "data-hf-studio-motion";
27239
+ const MOTION_TL_KEY = "studio-motion";
27218
27240
  const WRAPPED_PROP = "__hfStudioPositionSeekReapplyWrapped";
27219
- if (!document.querySelector("[" + PATH_OFFSET_ATTR + '="true"]') && !document.querySelector("[" + ROTATION_ATTR + '="true"]'))
27241
+ if (!document.querySelector("[" + PATH_OFFSET_ATTR + '="true"]') && !document.querySelector("[" + ROTATION_ATTR + '="true"]') && !document.querySelector("[" + MOTION_ATTR + "]"))
27220
27242
  return;
27221
27243
  const splitTopLevelWhitespace = (value) => {
27222
27244
  const parts = [];
@@ -27252,6 +27274,84 @@ function studioPositionSeekReapplyRuntime() {
27252
27274
  if (!original || original === "none" || !isSimpleRotateAngle(original)) return rotationValue;
27253
27275
  return "calc(" + original + " + " + rotationValue + ")";
27254
27276
  };
27277
+ let lastSeekTime = 0;
27278
+ let cachedMotionKey = "";
27279
+ const finiteNum = (v2) => typeof v2 === "number" && Number.isFinite(v2) ? v2 : null;
27280
+ const computeMotionKey = (motionEls) => {
27281
+ let key2 = "";
27282
+ for (let i2 = 0; i2 < motionEls.length; i2++) {
27283
+ const json = motionEls[i2].getAttribute?.(MOTION_ATTR);
27284
+ if (json) key2 += (key2 ? "\n" : "") + json;
27285
+ }
27286
+ return key2;
27287
+ };
27288
+ const reapplyMotionTimeline = () => {
27289
+ const motionEls = document.querySelectorAll("[" + MOTION_ATTR + "]");
27290
+ if (motionEls.length === 0) {
27291
+ cachedMotionKey = "";
27292
+ return;
27293
+ }
27294
+ const win = window;
27295
+ const gsap = win.gsap;
27296
+ if (!gsap || typeof gsap.timeline !== "function") return;
27297
+ win.__timelines = win.__timelines || {};
27298
+ const motionKey = computeMotionKey(motionEls);
27299
+ const existing = win.__timelines[MOTION_TL_KEY];
27300
+ if (motionKey && motionKey === cachedMotionKey && existing && typeof existing.totalTime === "function") {
27301
+ existing.totalTime(lastSeekTime, false);
27302
+ return;
27303
+ }
27304
+ if (existing && typeof existing.kill === "function") existing.kill();
27305
+ const tl = gsap.timeline({ paused: true, defaults: { overwrite: "auto" } });
27306
+ const fromTo = tl.fromTo;
27307
+ if (typeof fromTo !== "function") return;
27308
+ let applied = 0;
27309
+ for (let i2 = 0; i2 < motionEls.length; i2++) {
27310
+ const el = motionEls[i2];
27311
+ if (!(el instanceof HTMLElement)) continue;
27312
+ const json = el.getAttribute(MOTION_ATTR);
27313
+ if (!json) continue;
27314
+ try {
27315
+ const m2 = JSON.parse(json);
27316
+ const start = finiteNum(m2.start);
27317
+ const duration = finiteNum(m2.duration);
27318
+ if (start == null || duration == null || duration <= 0) continue;
27319
+ const ease = typeof m2.ease === "string" ? m2.ease : "none";
27320
+ const from = m2.from && typeof m2.from === "object" ? m2.from : {};
27321
+ const to = m2.to && typeof m2.to === "object" ? m2.to : {};
27322
+ const customEase = m2.customEase;
27323
+ let resolvedEase = ease;
27324
+ if (customEase?.id && customEase?.data && win.CustomEase?.create) {
27325
+ try {
27326
+ gsap.registerPlugin?.(win.CustomEase);
27327
+ win.CustomEase.create(customEase.id, customEase.data);
27328
+ resolvedEase = customEase.id;
27329
+ } catch {
27330
+ }
27331
+ }
27332
+ fromTo.call(
27333
+ tl,
27334
+ el,
27335
+ { ...from },
27336
+ { ...to, duration, ease: resolvedEase, overwrite: "auto", immediateRender: false },
27337
+ start
27338
+ );
27339
+ applied += 1;
27340
+ } catch {
27341
+ }
27342
+ }
27343
+ if (applied === 0) {
27344
+ cachedMotionKey = "";
27345
+ if (typeof tl.kill === "function")
27346
+ tl.kill();
27347
+ return;
27348
+ }
27349
+ cachedMotionKey = motionKey;
27350
+ win.__timelines[MOTION_TL_KEY] = tl;
27351
+ if (typeof tl.pause === "function") tl.pause();
27352
+ if (typeof tl.totalTime === "function")
27353
+ tl.totalTime(lastSeekTime, false);
27354
+ };
27255
27355
  const reapplyAll = () => {
27256
27356
  const offsetEls = document.querySelectorAll("[" + PATH_OFFSET_ATTR + '="true"]');
27257
27357
  for (let i2 = 0; i2 < offsetEls.length; i2++) {
@@ -27279,6 +27379,7 @@ function studioPositionSeekReapplyRuntime() {
27279
27379
  el.style.setProperty("rotate", composeRotation(el, "var(" + ROTATION_PROP + ", 0deg)"));
27280
27380
  }
27281
27381
  }
27382
+ reapplyMotionTimeline();
27282
27383
  };
27283
27384
  const runtimeWindow = window;
27284
27385
  const isWrapped = (fn) => Boolean(fn[WRAPPED_PROP]);
@@ -27305,6 +27406,7 @@ function studioPositionSeekReapplyRuntime() {
27305
27406
  return true;
27306
27407
  }
27307
27408
  const wrapped = function(time) {
27409
+ lastSeekTime = typeof time === "number" && Number.isFinite(time) ? Math.max(0, time) : 0;
27308
27410
  const result = seek.call(this, time);
27309
27411
  reapplyAll();
27310
27412
  return result;
@@ -28159,6 +28261,10 @@ function findFromEnv2() {
28159
28261
  return void 0;
28160
28262
  }
28161
28263
  async function findFromCache() {
28264
+ const fromPuppeteer = findFromPuppeteerCache();
28265
+ if (fromPuppeteer) {
28266
+ return fromPuppeteer;
28267
+ }
28162
28268
  if (existsSync17(CACHE_DIR2)) {
28163
28269
  const installed = await getInstalledBrowsers({ cacheDir: CACHE_DIR2 });
28164
28270
  const match = installed.find((b2) => b2.browser === Browser.CHROMEHEADLESSSHELL);
@@ -28166,17 +28272,41 @@ async function findFromCache() {
28166
28272
  return { executablePath: match.executablePath, source: "cache" };
28167
28273
  }
28168
28274
  }
28169
- const fromPuppeteer = findFromPuppeteerCache();
28170
- if (fromPuppeteer) {
28171
- return fromPuppeteer;
28172
- }
28173
28275
  return void 0;
28174
28276
  }
28277
+ function parseVersionSegments(versionDir) {
28278
+ const dashIdx = versionDir.indexOf("-");
28279
+ const versionPart = dashIdx >= 0 ? versionDir.slice(dashIdx + 1) : versionDir;
28280
+ const segments = versionPart.split(".");
28281
+ const parsed = [];
28282
+ for (const seg of segments) {
28283
+ const n = parseInt(seg, 10);
28284
+ if (!Number.isFinite(n)) {
28285
+ break;
28286
+ }
28287
+ parsed.push(n);
28288
+ }
28289
+ return parsed.length > 0 ? parsed : void 0;
28290
+ }
28291
+ function compareVersionDirsDescending(a, b2) {
28292
+ const pa = parseVersionSegments(a);
28293
+ const pb = parseVersionSegments(b2);
28294
+ if (!pa && !pb) return 0;
28295
+ if (!pa) return 1;
28296
+ if (!pb) return -1;
28297
+ const len = Math.max(pa.length, pb.length);
28298
+ for (let i2 = 0; i2 < len; i2 += 1) {
28299
+ const av = pa[i2] ?? 0;
28300
+ const bv = pb[i2] ?? 0;
28301
+ if (av !== bv) return bv - av;
28302
+ }
28303
+ return 0;
28304
+ }
28175
28305
  function findFromPuppeteerCache() {
28176
28306
  if (!existsSync17(PUPPETEER_CACHE_DIR)) return void 0;
28177
28307
  let versions;
28178
28308
  try {
28179
- versions = readdirSync8(PUPPETEER_CACHE_DIR).sort().reverse();
28309
+ versions = [...readdirSync8(PUPPETEER_CACHE_DIR)].sort(compareVersionDirsDescending);
28180
28310
  } catch {
28181
28311
  return void 0;
28182
28312
  }
@@ -28216,7 +28346,8 @@ function warnSystemFallbackOnce(executablePath) {
28216
28346
  _warnedSystemFallback = true;
28217
28347
  console.warn(
28218
28348
  `[hyperframes] Using system Chrome at ${executablePath}; HeadlessExperimental.beginFrame is unavailable in regular Chrome builds, so the perf-optimized capture path falls back to screenshot mode. Install chrome-headless-shell for the optimized path:
28219
- npx @puppeteer/browsers install chrome-headless-shell`
28349
+ npx @puppeteer/browsers install chrome-headless-shell
28350
+ (Or set HYPERFRAMES_BROWSER_PATH to point at an existing chrome-headless-shell binary.)`
28220
28351
  );
28221
28352
  }
28222
28353
  function _resetSystemFallbackWarnForTests() {
@@ -28368,6 +28499,10 @@ function resolveConfig(overrides) {
28368
28499
  ),
28369
28500
  expectedChromiumMajor: env("PRODUCER_EXPECTED_CHROMIUM_MAJOR") ? Number(env("PRODUCER_EXPECTED_CHROMIUM_MAJOR")) : void 0,
28370
28501
  forceScreenshot: envBool("PRODUCER_FORCE_SCREENSHOT", DEFAULT_CONFIG2.forceScreenshot),
28502
+ enablePageSideCompositing: envBool(
28503
+ "HF_PAGE_SIDE_COMPOSITING",
28504
+ DEFAULT_CONFIG2.enablePageSideCompositing
28505
+ ),
28371
28506
  enableChunkedEncode: envBool(
28372
28507
  "PRODUCER_ENABLE_CHUNKED_ENCODE",
28373
28508
  DEFAULT_CONFIG2.enableChunkedEncode
@@ -28449,6 +28584,7 @@ var init_config2 = __esm({
28449
28584
  browserTimeout: 12e4,
28450
28585
  protocolTimeout: 3e5,
28451
28586
  forceScreenshot: false,
28587
+ enablePageSideCompositing: true,
28452
28588
  enableChunkedEncode: false,
28453
28589
  chunkSizeFrames: 360,
28454
28590
  enableStreamingEncode: true,
@@ -28854,14 +28990,14 @@ async function pageScreenshotCapture(page, options) {
28854
28990
  const client = await getCdpSession(page);
28855
28991
  const isPng = options.format === "png";
28856
28992
  const dpr = options.deviceScaleFactor ?? 1;
28857
- const clip = dpr > 1 ? { x: 0, y: 0, width: options.width, height: options.height, scale: dpr } : void 0;
28993
+ const clip = { x: 0, y: 0, width: options.width, height: options.height, scale: dpr };
28858
28994
  const result = await client.send("Page.captureScreenshot", {
28859
28995
  format: isPng ? "png" : "jpeg",
28860
28996
  quality: isPng ? void 0 : options.quality ?? 80,
28861
28997
  fromSurface: true,
28862
28998
  captureBeyondViewport: false,
28863
28999
  optimizeForSpeed: !isPng,
28864
- ...clip ? { clip } : {}
29000
+ clip
28865
29001
  });
28866
29002
  return Buffer.from(result.data, "base64");
28867
29003
  }
@@ -28965,6 +29101,15 @@ async function injectVideoFramesBatch(page, updates) {
28965
29101
  await page.evaluate(
28966
29102
  async (items, visualProperties) => {
28967
29103
  const pendingDecodes = [];
29104
+ const replacementLayoutProperties = /* @__PURE__ */ new Set([
29105
+ "width",
29106
+ "height",
29107
+ "top",
29108
+ "left",
29109
+ "right",
29110
+ "bottom",
29111
+ "inset"
29112
+ ]);
28968
29113
  for (const item of items) {
28969
29114
  const video = document.getElementById(item.videoId);
28970
29115
  if (!video) continue;
@@ -28973,7 +29118,6 @@ async function injectVideoFramesBatch(page, updates) {
28973
29118
  const computedStyle = window.getComputedStyle(video);
28974
29119
  const opacityParsed = parseFloat(computedStyle.opacity);
28975
29120
  const computedOpacity = Number.isNaN(opacityParsed) ? 1 : opacityParsed;
28976
- const sourceIsStatic = !computedStyle.position || computedStyle.position === "static";
28977
29121
  if (isNewImage) {
28978
29122
  img = document.createElement("img");
28979
29123
  img.classList.add("__render_frame__");
@@ -28982,6 +29126,16 @@ async function injectVideoFramesBatch(page, updates) {
28982
29126
  video.parentNode?.insertBefore(img, video.nextSibling);
28983
29127
  }
28984
29128
  if (!img) continue;
29129
+ for (const property of visualProperties) {
29130
+ if (property === "opacity") continue;
29131
+ if (replacementLayoutProperties.has(property)) {
29132
+ continue;
29133
+ }
29134
+ const value = computedStyle.getPropertyValue(property);
29135
+ if (value) {
29136
+ img.style.setProperty(property, value);
29137
+ }
29138
+ }
28985
29139
  {
28986
29140
  const videoRect = video.getBoundingClientRect();
28987
29141
  const offsetLeft = Number.isFinite(video.offsetLeft) ? video.offsetLeft : 0;
@@ -29000,16 +29154,6 @@ async function injectVideoFramesBatch(page, updates) {
29000
29154
  img.style.objectFit = computedStyle.objectFit;
29001
29155
  img.style.objectPosition = computedStyle.objectPosition;
29002
29156
  img.style.zIndex = computedStyle.zIndex;
29003
- for (const property of visualProperties) {
29004
- if (property === "opacity") continue;
29005
- if (sourceIsStatic && (property === "top" || property === "left" || property === "right" || property === "bottom" || property === "inset")) {
29006
- continue;
29007
- }
29008
- const value = computedStyle.getPropertyValue(property);
29009
- if (value) {
29010
- img.style.setProperty(property, value);
29011
- }
29012
- }
29013
29157
  img.decoding = "sync";
29014
29158
  if (img.getAttribute("src") !== item.dataUri) {
29015
29159
  img.src = item.dataUri;
@@ -29094,10 +29238,10 @@ async function waitForCloseWithTimeout(promise) {
29094
29238
  () => void 0,
29095
29239
  () => void 0
29096
29240
  ),
29097
- new Promise((resolve42) => {
29241
+ new Promise((resolve43) => {
29098
29242
  timer = setTimeout(() => {
29099
29243
  timedOut = true;
29100
- resolve42();
29244
+ resolve43();
29101
29245
  }, CAPTURE_SESSION_CLOSE_TIMEOUT_MS);
29102
29246
  })
29103
29247
  ]);
@@ -29195,10 +29339,27 @@ async function pollPageExpression(page, expression, timeoutMs, intervalMs = 100)
29195
29339
  while (Date.now() < deadline) {
29196
29340
  const ready = Boolean(await page.evaluate(expression));
29197
29341
  if (ready) return true;
29198
- await new Promise((resolve42) => setTimeout(resolve42, intervalMs));
29342
+ await new Promise((resolve43) => setTimeout(resolve43, intervalMs));
29199
29343
  }
29200
29344
  return Boolean(await page.evaluate(expression));
29201
29345
  }
29346
+ async function pollVideosReady(page, skipIds, timeoutMs, intervalMs = 100) {
29347
+ const check = async () => {
29348
+ return Boolean(
29349
+ await page.evaluate((skipIdList) => {
29350
+ const skip = new Set(skipIdList);
29351
+ const vids = Array.from(document.querySelectorAll("video")).filter((v2) => !skip.has(v2.id));
29352
+ return vids.length === 0 || vids.every((v2) => v2.readyState >= 2);
29353
+ }, skipIds)
29354
+ );
29355
+ };
29356
+ const deadline = Date.now() + timeoutMs;
29357
+ while (Date.now() < deadline) {
29358
+ if (await check()) return true;
29359
+ await new Promise((resolve43) => setTimeout(resolve43, intervalMs));
29360
+ }
29361
+ return check();
29362
+ }
29202
29363
  async function applyVideoMetadataHints(page, hints) {
29203
29364
  if (!hints || hints.length === 0) return;
29204
29365
  await page.evaluate(
@@ -29229,7 +29390,7 @@ async function waitForOptionalTailwindReady(page, timeoutMs) {
29229
29390
  page.evaluate(
29230
29391
  `Promise.resolve(window.__tailwindReady).then(() => true, () => false)`
29231
29392
  ),
29232
- new Promise((resolve42) => setTimeout(() => resolve42(false), timeoutMs))
29393
+ new Promise((resolve43) => setTimeout(() => resolve43(false), timeoutMs))
29233
29394
  ]);
29234
29395
  if (!ready) {
29235
29396
  throw new Error(
@@ -29281,10 +29442,9 @@ async function initializeSession(session) {
29281
29442
  );
29282
29443
  }
29283
29444
  await applyVideoMetadataHints(page, session.options.videoMetadataHints);
29284
- const skipIdsLiteral = JSON.stringify(session.options.skipReadinessVideoIds ?? []);
29285
- const videosReady = await pollPageExpression(
29445
+ const videosReady = await pollVideosReady(
29286
29446
  page,
29287
- `(() => { const skip = new Set(${skipIdsLiteral}); const vids = Array.from(document.querySelectorAll("video")).filter(v => !skip.has(v.id)); return vids.length === 0 || vids.every(v => v.readyState >= 2); })()`,
29447
+ session.options.skipReadinessVideoIds ?? [],
29288
29448
  pageReadyTimeout2
29289
29449
  );
29290
29450
  if (!videosReady) {
@@ -29356,15 +29516,11 @@ async function initializeSession(session) {
29356
29516
  );
29357
29517
  }
29358
29518
  await applyVideoMetadataHints(page, session.options.videoMetadataHints);
29359
- const beginframeSkipIdsLiteral = JSON.stringify(session.options.skipReadinessVideoIds ?? []);
29360
- const videoDeadline = Date.now() + (session.config?.playerReadyTimeout ?? DEFAULT_CONFIG2.playerReadyTimeout);
29361
- while (Date.now() < videoDeadline) {
29362
- const videosReady = await page.evaluate(
29363
- `(() => { const skip = new Set(${beginframeSkipIdsLiteral}); const vids = Array.from(document.querySelectorAll("video")).filter(v => !skip.has(v.id)); return vids.length === 0 || vids.every(v => v.readyState >= 2); })()`
29364
- );
29365
- if (videosReady) break;
29366
- await new Promise((r2) => setTimeout(r2, 100));
29367
- }
29519
+ await pollVideosReady(
29520
+ page,
29521
+ session.options.skipReadinessVideoIds ?? [],
29522
+ session.config?.playerReadyTimeout ?? DEFAULT_CONFIG2.playerReadyTimeout
29523
+ );
29368
29524
  await page.evaluate(`document.fonts?.ready`);
29369
29525
  await waitForOptionalTailwindReady(page, pageReadyTimeout);
29370
29526
  warmupState.running = false;
@@ -29414,10 +29570,11 @@ async function prepareFrameForCapture(session, frameIndex, time) {
29414
29570
  }
29415
29571
  const quantizedTime = quantizeTimeToFrame(time, fpsToNumber(options.fps));
29416
29572
  const seekStart = Date.now();
29417
- await page.evaluate((t2) => {
29573
+ const hasPendingComposite = await page.evaluate((t2) => {
29418
29574
  if (window.__hf && typeof window.__hf.seek === "function") {
29419
29575
  window.__hf.seek(t2);
29420
29576
  }
29577
+ return !!window.__hf_page_composite_pending;
29421
29578
  }, quantizedTime);
29422
29579
  const seekMs = Date.now() - seekStart;
29423
29580
  const beforeCaptureStart = Date.now();
@@ -29425,6 +29582,26 @@ async function prepareFrameForCapture(session, frameIndex, time) {
29425
29582
  await session.onBeforeCapture(page, quantizedTime);
29426
29583
  }
29427
29584
  const beforeCaptureMs = Date.now() - beforeCaptureStart;
29585
+ if (hasPendingComposite && session.captureMode !== "beginframe") {
29586
+ await page.evaluate(async () => {
29587
+ const w3 = window;
29588
+ if (typeof w3.__hf_page_composite_prepare === "function") {
29589
+ await w3.__hf_page_composite_prepare();
29590
+ }
29591
+ });
29592
+ const cdp = await getCdpSession(page);
29593
+ await cdp.send("Page.captureScreenshot", {
29594
+ format: "jpeg",
29595
+ quality: 1,
29596
+ clip: { x: 0, y: 0, width: 1, height: 1, scale: 1 }
29597
+ });
29598
+ await page.evaluate(() => {
29599
+ const w3 = window;
29600
+ if (typeof w3.__hf_page_composite_resolve === "function") {
29601
+ w3.__hf_page_composite_resolve();
29602
+ }
29603
+ });
29604
+ }
29428
29605
  return { quantizedTime, seekMs, beforeCaptureMs };
29429
29606
  }
29430
29607
  async function captureFrameCore(session, frameIndex, time) {
@@ -29566,14 +29743,14 @@ var init_frameCapture = __esm({
29566
29743
  BROWSER_CONSOLE_BUFFER_SIZE = 200;
29567
29744
  CAPTURE_SESSION_CLOSE_TIMEOUT_MS = 5e3;
29568
29745
  LOCKED_WARMUP_TICKS = 60;
29569
- realSleep = (ms) => new Promise((resolve42) => setTimeout(resolve42, ms));
29746
+ realSleep = (ms) => new Promise((resolve43) => setTimeout(resolve43, ms));
29570
29747
  }
29571
29748
  });
29572
29749
 
29573
29750
  // ../engine/src/utils/gpuEncoder.ts
29574
29751
  import { spawn as spawn3 } from "child_process";
29575
29752
  async function detectGpuEncoder() {
29576
- return new Promise((resolve42) => {
29753
+ return new Promise((resolve43) => {
29577
29754
  const ffmpeg = spawn3("ffmpeg", ["-encoders"], {
29578
29755
  stdio: ["pipe", "pipe", "pipe"]
29579
29756
  });
@@ -29582,13 +29759,13 @@ async function detectGpuEncoder() {
29582
29759
  stdout2 += data.toString();
29583
29760
  });
29584
29761
  ffmpeg.on("close", () => {
29585
- if (stdout2.includes("h264_nvenc")) resolve42("nvenc");
29586
- else if (stdout2.includes("h264_videotoolbox")) resolve42("videotoolbox");
29587
- else if (stdout2.includes("h264_vaapi")) resolve42("vaapi");
29588
- else if (stdout2.includes("h264_qsv")) resolve42("qsv");
29589
- else resolve42(null);
29762
+ if (stdout2.includes("h264_nvenc")) resolve43("nvenc");
29763
+ else if (stdout2.includes("h264_videotoolbox")) resolve43("videotoolbox");
29764
+ else if (stdout2.includes("h264_vaapi")) resolve43("vaapi");
29765
+ else if (stdout2.includes("h264_qsv")) resolve43("qsv");
29766
+ else resolve43(null);
29590
29767
  });
29591
- ffmpeg.on("error", () => resolve42(null));
29768
+ ffmpeg.on("error", () => resolve43(null));
29592
29769
  });
29593
29770
  }
29594
29771
  async function getCachedGpuEncoder() {
@@ -29709,7 +29886,7 @@ async function runFfmpeg(args, opts) {
29709
29886
  const signal = opts?.signal;
29710
29887
  const timeout = opts?.timeout ?? DEFAULT_TIMEOUT;
29711
29888
  const onStderr = opts?.onStderr;
29712
- return new Promise((resolve42) => {
29889
+ return new Promise((resolve43) => {
29713
29890
  const ffmpeg = spawn4("ffmpeg", args);
29714
29891
  let stderr = "";
29715
29892
  const onAbort = () => {
@@ -29735,7 +29912,7 @@ async function runFfmpeg(args, opts) {
29735
29912
  ffmpeg.on("close", (code) => {
29736
29913
  clearTimeout(timer);
29737
29914
  if (signal) signal.removeEventListener("abort", onAbort);
29738
- resolve42({
29915
+ resolve43({
29739
29916
  success: !signal?.aborted && code === 0,
29740
29917
  exitCode: code,
29741
29918
  stderr,
@@ -29745,7 +29922,7 @@ async function runFfmpeg(args, opts) {
29745
29922
  ffmpeg.on("error", (err) => {
29746
29923
  clearTimeout(timer);
29747
29924
  if (signal) signal.removeEventListener("abort", onAbort);
29748
- resolve42({
29925
+ resolve43({
29749
29926
  success: false,
29750
29927
  exitCode: null,
29751
29928
  stderr: err.message,
@@ -29976,7 +30153,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
29976
30153
  const inputPath = join24(framesDir, framePattern);
29977
30154
  const inputArgs = ["-framerate", fpsToFfmpegArg(options.fps), "-i", inputPath];
29978
30155
  const args = buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder);
29979
- return new Promise((resolve42) => {
30156
+ return new Promise((resolve43) => {
29980
30157
  const ffmpeg = spawn5("ffmpeg", args);
29981
30158
  let stderr = "";
29982
30159
  const onAbort = () => {
@@ -30001,7 +30178,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
30001
30178
  if (signal) signal.removeEventListener("abort", onAbort);
30002
30179
  const durationMs = Date.now() - startTime;
30003
30180
  if (signal?.aborted) {
30004
- resolve42({
30181
+ resolve43({
30005
30182
  success: false,
30006
30183
  outputPath,
30007
30184
  durationMs,
@@ -30012,7 +30189,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
30012
30189
  return;
30013
30190
  }
30014
30191
  if (code !== 0) {
30015
- resolve42({
30192
+ resolve43({
30016
30193
  success: false,
30017
30194
  outputPath,
30018
30195
  durationMs,
@@ -30023,12 +30200,12 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
30023
30200
  return;
30024
30201
  }
30025
30202
  const fileSize = existsSync20(outputPath) ? statSync6(outputPath).size : 0;
30026
- resolve42({ success: true, outputPath, durationMs, framesEncoded: frameCount, fileSize });
30203
+ resolve43({ success: true, outputPath, durationMs, framesEncoded: frameCount, fileSize });
30027
30204
  });
30028
30205
  ffmpeg.on("error", (err) => {
30029
30206
  clearTimeout(timer);
30030
30207
  if (signal) signal.removeEventListener("abort", onAbort);
30031
- resolve42({
30208
+ resolve43({
30032
30209
  success: false,
30033
30210
  outputPath,
30034
30211
  durationMs: Date.now() - startTime,
@@ -30086,18 +30263,18 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
30086
30263
  let gpuEncoder = null;
30087
30264
  if (options.useGpu) gpuEncoder = await getCachedGpuEncoder();
30088
30265
  const args = buildEncoderArgs(options, inputArgs, chunkPath, gpuEncoder);
30089
- const chunkResult = await new Promise((resolve42) => {
30266
+ const chunkResult = await new Promise((resolve43) => {
30090
30267
  const ffmpeg = spawn5("ffmpeg", args);
30091
30268
  let stderr = "";
30092
30269
  ffmpeg.stderr.on("data", (d2) => {
30093
30270
  stderr += d2.toString();
30094
30271
  });
30095
30272
  ffmpeg.on("close", (code) => {
30096
- if (code === 0) resolve42({ success: true });
30097
- else resolve42({ success: false, error: `Chunk ${i2} encode failed: ${stderr.slice(-400)}` });
30273
+ if (code === 0) resolve43({ success: true });
30274
+ else resolve43({ success: false, error: `Chunk ${i2} encode failed: ${stderr.slice(-400)}` });
30098
30275
  });
30099
30276
  ffmpeg.on("error", (err) => {
30100
- resolve42({ success: false, error: `Chunk ${i2} encode error: ${err.message}` });
30277
+ resolve43({ success: false, error: `Chunk ${i2} encode error: ${err.message}` });
30101
30278
  });
30102
30279
  });
30103
30280
  if (!chunkResult.success) {
@@ -30127,18 +30304,18 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
30127
30304
  "-y",
30128
30305
  outputPath
30129
30306
  ];
30130
- const concatResult = await new Promise((resolve42) => {
30307
+ const concatResult = await new Promise((resolve43) => {
30131
30308
  const ffmpeg = spawn5("ffmpeg", concatArgs);
30132
30309
  let stderr = "";
30133
30310
  ffmpeg.stderr.on("data", (d2) => {
30134
30311
  stderr += d2.toString();
30135
30312
  });
30136
30313
  ffmpeg.on("close", (code) => {
30137
- if (code === 0) resolve42({ success: true });
30138
- else resolve42({ success: false, error: `Chunk concat failed: ${stderr.slice(-400)}` });
30314
+ if (code === 0) resolve43({ success: true });
30315
+ else resolve43({ success: false, error: `Chunk concat failed: ${stderr.slice(-400)}` });
30139
30316
  });
30140
30317
  ffmpeg.on("error", (err) => {
30141
- resolve42({ success: false, error: `Chunk concat error: ${err.message}` });
30318
+ resolve43({ success: false, error: `Chunk concat error: ${err.message}` });
30142
30319
  });
30143
30320
  });
30144
30321
  if (!concatResult.success) {
@@ -30240,37 +30417,37 @@ import { dirname as dirname8 } from "path";
30240
30417
  function createFrameReorderBuffer(startFrame, endFrame) {
30241
30418
  let cursor = startFrame;
30242
30419
  const pending = /* @__PURE__ */ new Map();
30243
- const enqueueAt = (frame, resolve42) => {
30420
+ const enqueueAt = (frame, resolve43) => {
30244
30421
  const list = pending.get(frame);
30245
30422
  if (list === void 0) {
30246
- pending.set(frame, [resolve42]);
30423
+ pending.set(frame, [resolve43]);
30247
30424
  } else {
30248
- list.push(resolve42);
30425
+ list.push(resolve43);
30249
30426
  }
30250
30427
  };
30251
30428
  const flushAt = (frame) => {
30252
30429
  const list = pending.get(frame);
30253
30430
  if (list === void 0) return;
30254
30431
  pending.delete(frame);
30255
- for (const resolve42 of list) resolve42();
30432
+ for (const resolve43 of list) resolve43();
30256
30433
  };
30257
- const waitForFrame = (frame) => new Promise((resolve42) => {
30434
+ const waitForFrame = (frame) => new Promise((resolve43) => {
30258
30435
  if (frame === cursor) {
30259
- resolve42();
30436
+ resolve43();
30260
30437
  return;
30261
30438
  }
30262
- enqueueAt(frame, resolve42);
30439
+ enqueueAt(frame, resolve43);
30263
30440
  });
30264
30441
  const advanceTo = (frame) => {
30265
30442
  cursor = frame;
30266
30443
  flushAt(frame);
30267
30444
  };
30268
- const waitForAllDone = () => new Promise((resolve42) => {
30445
+ const waitForAllDone = () => new Promise((resolve43) => {
30269
30446
  if (cursor >= endFrame) {
30270
- resolve42();
30447
+ resolve43();
30271
30448
  return;
30272
30449
  }
30273
- enqueueAt(endFrame, resolve42);
30450
+ enqueueAt(endFrame, resolve43);
30274
30451
  });
30275
30452
  return { waitForFrame, advanceTo, waitForAllDone };
30276
30453
  }
@@ -30451,7 +30628,7 @@ async function spawnStreamingEncoder(outputPath, options, signal, config) {
30451
30628
  let stderr = "";
30452
30629
  let exitCode = null;
30453
30630
  let exitPromiseResolve = null;
30454
- const exitPromise = new Promise((resolve42) => exitPromiseResolve = resolve42);
30631
+ const exitPromise = new Promise((resolve43) => exitPromiseResolve = resolve43);
30455
30632
  ffmpeg.stderr?.on("data", (data) => {
30456
30633
  stderr += data.toString();
30457
30634
  });
@@ -30501,8 +30678,8 @@ Process error: ${err.message}`;
30501
30678
  if (signal) signal.removeEventListener("abort", onAbort);
30502
30679
  const stdin = ffmpeg.stdin;
30503
30680
  if (stdin && !stdin.destroyed) {
30504
- await new Promise((resolve42) => {
30505
- stdin.end(() => resolve42());
30681
+ await new Promise((resolve43) => {
30682
+ stdin.end(() => resolve43());
30506
30683
  });
30507
30684
  }
30508
30685
  await exitPromise;
@@ -30546,7 +30723,7 @@ import { spawn as spawn7 } from "child_process";
30546
30723
  import { readFileSync as readFileSync18 } from "fs";
30547
30724
  import { extname as extname5 } from "path";
30548
30725
  function runFfprobe(args) {
30549
- return new Promise((resolve42, reject) => {
30726
+ return new Promise((resolve43, reject) => {
30550
30727
  const proc = spawn7("ffprobe", args);
30551
30728
  let stdout2 = "";
30552
30729
  let stderr = "";
@@ -30560,7 +30737,7 @@ function runFfprobe(args) {
30560
30737
  if (code !== 0) {
30561
30738
  reject(new Error(`[FFmpeg] ffprobe exited with code ${code}: ${stderr}`));
30562
30739
  } else {
30563
- resolve42(stdout2);
30740
+ resolve43(stdout2);
30564
30741
  }
30565
30742
  });
30566
30743
  proc.on("error", (err) => {
@@ -30896,9 +31073,9 @@ var init_urlDownloader = __esm({
30896
31073
  });
30897
31074
 
30898
31075
  // ../core/src/compiler/htmlCompiler.ts
30899
- import { resolve as resolve12 } from "path";
31076
+ import { resolve as resolve13 } from "path";
30900
31077
  function resolveMediaSrc(src, projectDir) {
30901
- return src.startsWith("http://") || src.startsWith("https://") ? src : resolve12(projectDir, src);
31078
+ return src.startsWith("http://") || src.startsWith("https://") ? src : resolve13(projectDir, src);
30902
31079
  }
30903
31080
  async function compileHtml(rawHtml, projectDir, probeMediaDuration) {
30904
31081
  const { html: staticCompiled, unresolved } = compileTimingAttrs(rawHtml);
@@ -31260,12 +31437,12 @@ var init_staticGuard = __esm({
31260
31437
 
31261
31438
  // ../core/src/compiler/htmlBundler.ts
31262
31439
  import { readFileSync as readFileSync19, existsSync as existsSync23 } from "fs";
31263
- import { join as join26, resolve as resolve13, isAbsolute as isAbsolute3, sep as sep2 } from "path";
31440
+ import { join as join26, resolve as resolve14, isAbsolute as isAbsolute3, sep as sep3 } from "path";
31264
31441
  import { transformSync } from "esbuild";
31265
31442
  function safePath(projectDir, relativePath) {
31266
- const resolved = resolve13(projectDir, relativePath);
31267
- const normalizedBase = resolve13(projectDir) + sep2;
31268
- if (!resolved.startsWith(normalizedBase) && resolved !== resolve13(projectDir)) return null;
31443
+ const resolved = resolve14(projectDir, relativePath);
31444
+ const normalizedBase = resolve14(projectDir) + sep3;
31445
+ if (!resolved.startsWith(normalizedBase) && resolved !== resolve14(projectDir)) return null;
31269
31446
  return resolved;
31270
31447
  }
31271
31448
  function getRuntimeScriptUrl() {
@@ -31965,7 +32142,7 @@ var init_extractionCache = __esm({
31965
32142
  // ../engine/src/services/videoFrameExtractor.ts
31966
32143
  import { spawn as spawn8 } from "child_process";
31967
32144
  import { existsSync as existsSync25, mkdirSync as mkdirSync15, readdirSync as readdirSync12, rmSync as rmSync5 } from "fs";
31968
- import { isAbsolute as isAbsolute4, join as join28, posix as posix2, resolve as resolve14, sep as sep3 } from "path";
32145
+ import { isAbsolute as isAbsolute4, join as join28, posix as posix2, resolve as resolve15, sep as sep4 } from "path";
31969
32146
  function parseVideoElements(html) {
31970
32147
  const videos = [];
31971
32148
  const { document: document2 } = parseHTML(unwrapTemplate(html));
@@ -32060,7 +32237,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
32060
32237
  args.push("-q:v", format === "jpg" ? String(Math.ceil((100 - quality) / 3)) : "0");
32061
32238
  if (format === "png") args.push("-compression_level", "6");
32062
32239
  args.push("-y", outputPattern);
32063
- return new Promise((resolve42, reject) => {
32240
+ return new Promise((resolve43, reject) => {
32064
32241
  const ffmpeg = spawn8("ffmpeg", args);
32065
32242
  let stderr = "";
32066
32243
  const onAbort = () => {
@@ -32095,7 +32272,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
32095
32272
  files.forEach((file, index) => {
32096
32273
  framePaths.set(index, join28(videoOutputDir, file));
32097
32274
  });
32098
- resolve42({
32275
+ resolve43({
32099
32276
  videoId,
32100
32277
  srcPath: videoPath,
32101
32278
  outputDir: videoOutputDir,
@@ -32212,9 +32389,9 @@ function resolveProjectRelativeSrc(src, baseDir, compiledDir) {
32212
32389
  const candidates = [];
32213
32390
  if (fromCompiled) candidates.push(fromCompiled);
32214
32391
  candidates.push(fromBase);
32215
- const baseAbs = resolve14(baseDir);
32216
- const fromBaseAbs = resolve14(fromBase);
32217
- if (!fromBaseAbs.startsWith(baseAbs + sep3) && fromBaseAbs !== baseAbs) {
32392
+ const baseAbs = resolve15(baseDir);
32393
+ const fromBaseAbs = resolve15(fromBase);
32394
+ if (!fromBaseAbs.startsWith(baseAbs + sep4) && fromBaseAbs !== baseAbs) {
32218
32395
  const normalized = posix2.normalize(src.replace(/\\/g, "/"));
32219
32396
  const stripped = normalized.replace(/^(\.\.\/)+/, "");
32220
32397
  if (stripped && stripped !== src && !stripped.startsWith("..")) {
@@ -33584,11 +33761,11 @@ function createFileServer(options) {
33584
33761
  headers: { "Content-Type": contentType }
33585
33762
  });
33586
33763
  });
33587
- return new Promise((resolve42) => {
33764
+ return new Promise((resolve43) => {
33588
33765
  const server = serve({ fetch: app.fetch, port }, (info) => {
33589
33766
  const actualPort = info.port;
33590
33767
  const url = `http://localhost:${actualPort}`;
33591
- resolve42({
33768
+ resolve43({
33592
33769
  url,
33593
33770
  port: actualPort,
33594
33771
  close: () => server.close()
@@ -35720,7 +35897,7 @@ var init_deterministicFonts = __esm({
35720
35897
  // ../producer/src/services/hyperframeRuntimeLoader.ts
35721
35898
  import { createHash as createHash5 } from "crypto";
35722
35899
  import { existsSync as existsSync31, readFileSync as readFileSync22 } from "fs";
35723
- import { dirname as dirname10, resolve as resolve15 } from "path";
35900
+ import { dirname as dirname10, resolve as resolve16 } from "path";
35724
35901
  import { fileURLToPath as fileURLToPath2 } from "url";
35725
35902
  function resolveHyperframeManifestPath() {
35726
35903
  if (process.env.PRODUCER_HYPERFRAME_MANIFEST_PATH) {
@@ -35756,7 +35933,7 @@ function resolveVerifiedHyperframeRuntime() {
35756
35933
  `[HyperframeRuntimeLoader] Invalid manifest at ${manifestPath}; missing iife artifact or sha256.`
35757
35934
  );
35758
35935
  }
35759
- const runtimePath = resolve15(dirname10(manifestPath), runtimeFileName);
35936
+ const runtimePath = resolve16(dirname10(manifestPath), runtimeFileName);
35760
35937
  if (!existsSync31(runtimePath)) {
35761
35938
  throw new Error(`[HyperframeRuntimeLoader] Missing runtime artifact at ${runtimePath}.`);
35762
35939
  }
@@ -35780,18 +35957,18 @@ var init_hyperframeRuntimeLoader = __esm({
35780
35957
  "../producer/src/services/hyperframeRuntimeLoader.ts"() {
35781
35958
  "use strict";
35782
35959
  PRODUCER_DIR = dirname10(fileURLToPath2(import.meta.url));
35783
- SIBLING_MANIFEST_PATH = resolve15(PRODUCER_DIR, "hyperframe.manifest.json");
35784
- MODULE_RELATIVE_MANIFEST_PATH = resolve15(
35960
+ SIBLING_MANIFEST_PATH = resolve16(PRODUCER_DIR, "hyperframe.manifest.json");
35961
+ MODULE_RELATIVE_MANIFEST_PATH = resolve16(
35785
35962
  PRODUCER_DIR,
35786
35963
  "../../../core/dist/hyperframe.manifest.json"
35787
35964
  );
35788
35965
  CWD_RELATIVE_MANIFEST_PATHS = [
35789
35966
  // When bundled to a single file (dist/public-server.js), the manifest
35790
35967
  // is copied as a sibling by build.mjs
35791
- resolve15(PRODUCER_DIR, "hyperframe.manifest.json"),
35792
- resolve15(process.cwd(), "packages/core/dist/hyperframe.manifest.json"),
35793
- resolve15(process.cwd(), "../core/dist/hyperframe.manifest.json"),
35794
- resolve15(process.cwd(), "core/dist/hyperframe.manifest.json")
35968
+ resolve16(PRODUCER_DIR, "hyperframe.manifest.json"),
35969
+ resolve16(process.cwd(), "packages/core/dist/hyperframe.manifest.json"),
35970
+ resolve16(process.cwd(), "../core/dist/hyperframe.manifest.json"),
35971
+ resolve16(process.cwd(), "core/dist/hyperframe.manifest.json")
35795
35972
  ];
35796
35973
  }
35797
35974
  });
@@ -35800,11 +35977,11 @@ var init_hyperframeRuntimeLoader = __esm({
35800
35977
  import { Hono as Hono3 } from "hono";
35801
35978
  import { serve as serve2 } from "@hono/node-server";
35802
35979
  import { readFileSync as readFileSync23, existsSync as existsSync32, realpathSync, statSync as statSync10 } from "fs";
35803
- import { join as join34, extname as extname8, resolve as resolve16, sep as sep4 } from "path";
35980
+ import { join as join34, extname as extname8, resolve as resolve17, sep as sep5 } from "path";
35804
35981
  function isPathInside(child, parent, options = {}) {
35805
35982
  const { resolveSymlinks = false, pathModule } = options;
35806
- const resolveFn = pathModule?.resolve ?? resolve16;
35807
- const separator = pathModule?.sep ?? sep4;
35983
+ const resolveFn = pathModule?.resolve ?? resolve17;
35984
+ const separator = pathModule?.sep ?? sep5;
35808
35985
  const resolvedChild = resolveFn(child);
35809
35986
  const resolvedParent = resolveFn(parent);
35810
35987
  const normalizedChild = resolveSymlinks && existsSync32(resolvedChild) ? realpathSync.native(resolvedChild) : resolvedChild;
@@ -36009,12 +36186,15 @@ function createFileServer2(options) {
36009
36186
  headers: { "Content-Type": contentType }
36010
36187
  });
36011
36188
  });
36012
- return new Promise((resolve42) => {
36189
+ return new Promise((resolve43) => {
36013
36190
  const connections = /* @__PURE__ */ new Set();
36014
36191
  const server = serve2({ fetch: app.fetch, port }, (info) => {
36015
- resolve42({
36192
+ resolve43({
36016
36193
  url: `http://localhost:${info.port}`,
36017
36194
  port: info.port,
36195
+ addPreHeadScript: (script) => {
36196
+ preHeadScripts.push(script);
36197
+ },
36018
36198
  close: () => {
36019
36199
  for (const socket of connections) socket.destroy();
36020
36200
  connections.clear();
@@ -36028,7 +36208,7 @@ function createFileServer2(options) {
36028
36208
  });
36029
36209
  });
36030
36210
  }
36031
- var MIME_TYPES3, VIRTUAL_TIME_SHIM, RENDER_SEEK_MODE, RENDER_SEEK_DIAGNOSTICS, RENDER_SEEK_STEP, RENDER_SEEK_OFFSET_FRACTION, RENDER_MODE_SCRIPT, HF_EARLY_STUB, HF_BRIDGE_SCRIPT;
36211
+ var MIME_TYPES3, VIRTUAL_TIME_SHIM, RENDER_SEEK_MODE, RENDER_SEEK_DIAGNOSTICS, RENDER_SEEK_STEP, RENDER_SEEK_OFFSET_FRACTION, RENDER_MODE_SCRIPT, HF_EARLY_STUB, HF_PAGE_SIDE_COMPOSITING_STUB, HF_BRIDGE_SCRIPT;
36032
36212
  var init_fileServer2 = __esm({
36033
36213
  "../producer/src/services/fileServer.ts"() {
36034
36214
  "use strict";
@@ -36178,6 +36358,10 @@ var init_fileServer2 = __esm({
36178
36358
  HF_EARLY_STUB = `(function() {
36179
36359
  if (typeof window === "undefined") return;
36180
36360
  if (!window.__hf) window.__hf = {};
36361
+ })();`;
36362
+ HF_PAGE_SIDE_COMPOSITING_STUB = `(function() {
36363
+ if (typeof window === "undefined") return;
36364
+ window.__HF_PAGE_SIDE_COMPOSITING__ = true;
36181
36365
  })();`;
36182
36366
  HF_BRIDGE_SCRIPT = `(function() {
36183
36367
  var __realSetInterval =
@@ -36342,7 +36526,7 @@ var init_paths = __esm({
36342
36526
 
36343
36527
  // ../producer/src/services/render/shared.ts
36344
36528
  import { copyFileSync as copyFileSync2, cpSync, existsSync as existsSync33, mkdirSync as mkdirSync19, symlinkSync, writeFileSync as writeFileSync15 } from "fs";
36345
- import { basename as basename4, dirname as dirname11, isAbsolute as isAbsolute6, join as join36, relative as relative3, resolve as resolve17 } from "path";
36529
+ import { basename as basename4, dirname as dirname11, isAbsolute as isAbsolute6, join as join36, relative as relative3, resolve as resolve18 } from "path";
36346
36530
  function projectBrowserEndToCompositionTimeline(existingStart, browserStart, browserEnd) {
36347
36531
  return browserEnd + (existingStart - browserStart);
36348
36532
  }
@@ -36387,7 +36571,7 @@ function writeCompiledArtifacts(compiled, workDir, includeSummary) {
36387
36571
  writeFileSync15(outPath, html, "utf-8");
36388
36572
  }
36389
36573
  for (const [relativePath, absolutePath] of compiled.externalAssets) {
36390
- const outPath = resolve17(join36(compileDir, relativePath));
36574
+ const outPath = resolve18(join36(compileDir, relativePath));
36391
36575
  if (!isPathInside2(outPath, compileDir)) {
36392
36576
  console.warn(`[Render] Skipping external asset with unsafe path: ${relativePath}`);
36393
36577
  continue;
@@ -36439,9 +36623,9 @@ function updateJobStatus(job, status, stage, progress, onProgress) {
36439
36623
  if (onProgress) onProgress(job, stage);
36440
36624
  }
36441
36625
  function createCompiledFrameSrcResolver(compiledDir) {
36442
- const compiledRoot = resolve17(compiledDir);
36626
+ const compiledRoot = resolve18(compiledDir);
36443
36627
  return (framePath) => {
36444
- const resolvedFramePath = resolve17(framePath);
36628
+ const resolvedFramePath = resolve18(framePath);
36445
36629
  if (!isPathInside2(resolvedFramePath, compiledRoot)) return null;
36446
36630
  const relativePath = relative3(compiledRoot, resolvedFramePath);
36447
36631
  if (!relativePath || relativePath.startsWith("..") || isAbsolute6(relativePath)) {
@@ -36520,7 +36704,7 @@ var init_shared = __esm({
36520
36704
  init_paths();
36521
36705
  BROWSER_MEDIA_EPSILON = 1e-4;
36522
36706
  materializePathModule = {
36523
- resolve: resolve17,
36707
+ resolve: resolve18,
36524
36708
  join: join36,
36525
36709
  dirname: dirname11,
36526
36710
  basename: basename4,
@@ -37065,7 +37249,7 @@ var init_urlDownloader2 = __esm({
37065
37249
 
37066
37250
  // ../producer/src/services/htmlCompiler.ts
37067
37251
  import { readFileSync as readFileSync24, existsSync as existsSync34, mkdirSync as mkdirSync20 } from "fs";
37068
- import { join as join38, dirname as dirname12, resolve as resolve18 } from "path";
37252
+ import { join as join38, dirname as dirname12, resolve as resolve19 } from "path";
37069
37253
  function dedupeElementsById(elements) {
37070
37254
  const deduped = /* @__PURE__ */ new Map();
37071
37255
  for (const element of elements) {
@@ -37209,7 +37393,7 @@ async function parseSubCompositions(html, projectDir, downloadDir, parentOffset
37209
37393
  const elEnd = elEndRaw ? parseFloat(elEndRaw) : Infinity;
37210
37394
  const absoluteStart = parentOffset + elStart;
37211
37395
  const absoluteEnd = Math.min(parentEnd, isFinite(elEnd) ? parentOffset + elEnd : Infinity);
37212
- const filePath = resolve18(projectDir, srcPath);
37396
+ const filePath = resolve19(projectDir, srcPath);
37213
37397
  if (visited.has(filePath)) {
37214
37398
  continue;
37215
37399
  }
@@ -37401,7 +37585,7 @@ function inlineSubCompositions(html, subCompositions, projectDir) {
37401
37585
  if (!srcPath) continue;
37402
37586
  let compHtml = subCompositions.get(srcPath) || null;
37403
37587
  if (!compHtml) {
37404
- const filePath = resolve18(projectDir, srcPath);
37588
+ const filePath = resolve19(projectDir, srcPath);
37405
37589
  if (existsSync34(filePath)) {
37406
37590
  compHtml = readFileSync24(filePath, "utf-8");
37407
37591
  }
@@ -37592,7 +37776,7 @@ ${safeText}
37592
37776
  return wrappedFragment ? document2.body.innerHTML || "" : document2.toString();
37593
37777
  }
37594
37778
  function collectExternalAssets(html, projectDir) {
37595
- const absProjectDir = resolve18(projectDir);
37779
+ const absProjectDir = resolve19(projectDir);
37596
37780
  const externalAssets = /* @__PURE__ */ new Map();
37597
37781
  const CSS_URL_RE2 = /\burl\(\s*(["']?)([^)"']+)\1\s*\)/g;
37598
37782
  function processPath(rawPath) {
@@ -37600,7 +37784,7 @@ function collectExternalAssets(html, projectDir) {
37600
37784
  if (!trimmed || trimmed.startsWith("/") || trimmed.startsWith("http://") || trimmed.startsWith("https://") || trimmed.startsWith("//") || trimmed.startsWith("data:") || trimmed.startsWith("#")) {
37601
37785
  return null;
37602
37786
  }
37603
- const absPath = resolve18(absProjectDir, trimmed);
37787
+ const absPath = resolve19(absProjectDir, trimmed);
37604
37788
  if (isPathInside2(absPath, absProjectDir)) {
37605
37789
  return null;
37606
37790
  }
@@ -37675,7 +37859,11 @@ async function compileForRender(projectDir, htmlPath, downloadDir, options = {})
37675
37859
  );
37676
37860
  const assembledHtml = await inlineExternalScripts(coalescedHtml);
37677
37861
  const { html: htmlWithAssets, externalAssets } = collectExternalAssets(assembledHtml, projectDir);
37678
- const HF_POSITION_ATTRS = ['data-hf-studio-path-offset="true"', 'data-hf-studio-rotation="true"'];
37862
+ const HF_POSITION_ATTRS = [
37863
+ 'data-hf-studio-path-offset="true"',
37864
+ 'data-hf-studio-rotation="true"',
37865
+ 'data-hf-studio-motion="'
37866
+ ];
37679
37867
  const hasPositionEdits = HF_POSITION_ATTRS.some((attr) => htmlWithAssets.includes(attr));
37680
37868
  const html = hasPositionEdits ? htmlWithAssets.replace(
37681
37869
  /<\/body>/i,
@@ -37689,7 +37877,7 @@ async function compileForRender(projectDir, htmlPath, downloadDir, options = {})
37689
37877
  const images = dedupeElementsById([...mainImages, ...subImages]);
37690
37878
  for (const video of videos) {
37691
37879
  if (isHttpUrl(video.src)) continue;
37692
- const videoPath = resolve18(projectDir, video.src);
37880
+ const videoPath = resolve19(projectDir, video.src);
37693
37881
  const reencode = `ffmpeg -i "${video.src}" -c:v libx264 -r 30 -g 30 -keyint_min 30 -movflags +faststart -c:a copy output.mp4`;
37694
37882
  Promise.all([analyzeKeyframeIntervals(videoPath), extractMediaMetadata(videoPath)]).then(([analysis, metadata]) => {
37695
37883
  if (analysis.isProblematic) {
@@ -37760,6 +37948,73 @@ async function discoverMediaFromBrowser(page) {
37760
37948
  });
37761
37949
  return elements;
37762
37950
  }
37951
+ async function discoverVideoVisibilityFromTimeline(page, compositionDuration) {
37952
+ if (compositionDuration <= 0) return [];
37953
+ return page.evaluate((duration) => {
37954
+ const results = [];
37955
+ const videos = document.querySelectorAll("video[data-hf-auto-start]");
37956
+ if (videos.length === 0) return results;
37957
+ const timelines = window.__timelines;
37958
+ if (!timelines) return results;
37959
+ const rootEl = document.querySelector("[data-composition-id]");
37960
+ const compId = rootEl?.getAttribute("data-composition-id");
37961
+ if (!compId) return results;
37962
+ const tl = timelines[compId];
37963
+ if (!tl) return results;
37964
+ const seekTl = (t2) => {
37965
+ if (typeof tl.totalTime === "function") {
37966
+ tl.totalTime(t2, true);
37967
+ } else if (typeof tl.seek === "function") {
37968
+ tl.seek(t2, true);
37969
+ }
37970
+ };
37971
+ const SAMPLE_STEP = 0.1;
37972
+ const BINARY_PRECISION = 1 / 60;
37973
+ for (const videoEl of videos) {
37974
+ const id = videoEl.id;
37975
+ if (!id) continue;
37976
+ const sceneEl = videoEl.closest(".scene") || videoEl;
37977
+ let firstVisible = null;
37978
+ let lastVisible = null;
37979
+ for (let t2 = 0; t2 <= duration; t2 += SAMPLE_STEP) {
37980
+ seekTl(t2);
37981
+ const opacity = parseFloat(window.getComputedStyle(sceneEl).opacity);
37982
+ if (opacity > 0) {
37983
+ if (firstVisible === null) firstVisible = t2;
37984
+ lastVisible = t2;
37985
+ }
37986
+ }
37987
+ if (firstVisible === null || lastVisible === null) continue;
37988
+ let lo = Math.max(0, firstVisible - SAMPLE_STEP);
37989
+ let hi = firstVisible;
37990
+ while (hi - lo > BINARY_PRECISION) {
37991
+ const mid = (lo + hi) / 2;
37992
+ seekTl(mid);
37993
+ const opacity = parseFloat(window.getComputedStyle(sceneEl).opacity);
37994
+ if (opacity > 0) hi = mid;
37995
+ else lo = mid;
37996
+ }
37997
+ const exactStart = hi;
37998
+ lo = lastVisible;
37999
+ hi = Math.min(duration, lastVisible + SAMPLE_STEP);
38000
+ while (hi - lo > BINARY_PRECISION) {
38001
+ const mid = (lo + hi) / 2;
38002
+ seekTl(mid);
38003
+ const opacity = parseFloat(window.getComputedStyle(sceneEl).opacity);
38004
+ if (opacity > 0) lo = mid;
38005
+ else hi = mid;
38006
+ }
38007
+ const exactEnd = lo;
38008
+ results.push({
38009
+ videoId: id,
38010
+ visibleStart: Math.max(0, exactStart),
38011
+ visibleEnd: Math.min(duration, exactEnd)
38012
+ });
38013
+ }
38014
+ seekTl(0);
38015
+ return results;
38016
+ }, compositionDuration);
38017
+ }
37763
38018
  async function resolveCompositionDurations(page, unresolved) {
37764
38019
  if (unresolved.length === 0) return [];
37765
38020
  const ids = unresolved.map((el) => el.id);
@@ -37951,7 +38206,8 @@ async function runProbeStage(input) {
37951
38206
  let probeSession = null;
37952
38207
  let lastBrowserConsole = [];
37953
38208
  const probeStart = Date.now();
37954
- const needsBrowser = composition.duration <= 0 || compiled.unresolvedCompositions.length > 0;
38209
+ const hasAutoStartVideos = compiled.html.includes("data-hf-auto-start");
38210
+ const needsBrowser = composition.duration <= 0 || compiled.unresolvedCompositions.length > 0 || hasAutoStartVideos;
37955
38211
  if (needsBrowser) {
37956
38212
  const reasons = [];
37957
38213
  if (composition.duration <= 0) reasons.push("root duration unknown");
@@ -38101,6 +38357,24 @@ async function runProbeStage(input) {
38101
38357
  }
38102
38358
  }
38103
38359
  }
38360
+ if (composition.videos.length > 0) {
38361
+ const visibilityWindows = await discoverVideoVisibilityFromTimeline(
38362
+ probeSession.page,
38363
+ composition.duration
38364
+ );
38365
+ assertNotAborted();
38366
+ for (const win of visibilityWindows) {
38367
+ const video = composition.videos.find((v2) => v2.id === win.videoId);
38368
+ if (!video) continue;
38369
+ if (win.visibleStart >= 0 && win.visibleEnd > win.visibleStart) {
38370
+ video.start = win.visibleStart;
38371
+ video.end = win.visibleEnd;
38372
+ log2.info(
38373
+ `[Probe] Runtime video discovery: ${video.id} visible ${win.visibleStart.toFixed(2)}s\u2013${win.visibleEnd.toFixed(2)}s`
38374
+ );
38375
+ }
38376
+ }
38377
+ }
38104
38378
  }
38105
38379
  const browserProbeMs = Date.now() - probeStart;
38106
38380
  const duration = composition.duration;
@@ -39423,8 +39697,8 @@ async function createShaderTransitionWorkerPool(opts) {
39423
39697
  if (terminated) {
39424
39698
  throw new Error("shader-blend pool already terminated");
39425
39699
  }
39426
- return new Promise((resolve42, reject) => {
39427
- const task = traceEnabled ? { req, resolve: resolve42, reject, enqueuedAtMs: Date.now(), traceId: ++nextTaskId } : { req, resolve: resolve42, reject };
39700
+ return new Promise((resolve43, reject) => {
39701
+ const task = traceEnabled ? { req, resolve: resolve43, reject, enqueuedAtMs: Date.now(), traceId: ++nextTaskId } : { req, resolve: resolve43, reject };
39428
39702
  const idle = slots.find((s2) => !s2.busy);
39429
39703
  if (idle) {
39430
39704
  queue.unshift(task);
@@ -40157,7 +40431,7 @@ import {
40157
40431
  copyFileSync as copyFileSync4,
40158
40432
  appendFileSync
40159
40433
  } from "fs";
40160
- import { join as join49, dirname as dirname14, resolve as resolve19 } from "path";
40434
+ import { join as join49, dirname as dirname14, resolve as resolve20 } from "path";
40161
40435
  import { randomUUID as randomUUID2 } from "crypto";
40162
40436
  import { fileURLToPath as fileURLToPath4 } from "url";
40163
40437
  function sampleDirectoryBytes(dir) {
@@ -40831,7 +41105,7 @@ function extractStandaloneEntryFromIndex(indexHtml, entryFile) {
40831
41105
  }
40832
41106
  async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSignal) {
40833
41107
  const moduleDir = dirname14(fileURLToPath4(import.meta.url));
40834
- const producerRoot = process.env.PRODUCER_RENDERS_DIR ? resolve19(process.env.PRODUCER_RENDERS_DIR, "..") : resolve19(moduleDir, "../..");
41108
+ const producerRoot = process.env.PRODUCER_RENDERS_DIR ? resolve20(process.env.PRODUCER_RENDERS_DIR, "..") : resolve20(moduleDir, "../..");
40835
41109
  const debugDir = join49(producerRoot, ".debug");
40836
41110
  const workDir = job.config.debug ? join49(debugDir, job.id) : join49(dirname14(outputPath), `work-${job.id}`);
40837
41111
  const pipelineStart = Date.now();
@@ -41073,7 +41347,14 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
41073
41347
  const videoOnlyPath = join49(workDir, `video-only${videoExt}`);
41074
41348
  const nativeHdrIds = /* @__PURE__ */ new Set([...nativeHdrVideoIds, ...nativeHdrImageIds]);
41075
41349
  const hasHdrContent = Boolean(effectiveHdr && nativeHdrIds.size > 0);
41076
- const useLayeredComposite = shouldUseLayeredComposite({
41350
+ const usePageSideCompositingForTransitions = cfg.enablePageSideCompositing && compiled.hasShaderTransitions && !hasHdrContent && !isPngSequence && !needsAlpha;
41351
+ if (usePageSideCompositingForTransitions) {
41352
+ fileServer.addPreHeadScript(HF_PAGE_SIDE_COMPOSITING_STUB);
41353
+ log2.info(
41354
+ "[Render] Page-side compositing enabled \u2014 bypassing Node-side layered shader-blend path. Engine will capture one opaque RGB frame per output frame."
41355
+ );
41356
+ }
41357
+ const useLayeredComposite = !usePageSideCompositingForTransitions && shouldUseLayeredComposite({
41077
41358
  hasHdrContent,
41078
41359
  hasShaderTransitions: compiled.hasShaderTransitions,
41079
41360
  isPngSequence
@@ -41407,7 +41688,7 @@ var init_config3 = __esm({
41407
41688
 
41408
41689
  // ../producer/src/services/hyperframeLint.ts
41409
41690
  import { existsSync as existsSync40, readFileSync as readFileSync27, statSync as statSync13 } from "fs";
41410
- import { resolve as resolve20, join as join50 } from "path";
41691
+ import { resolve as resolve21, join as join50 } from "path";
41411
41692
  function isStringRecord(value) {
41412
41693
  if (!value || typeof value !== "object" || Array.isArray(value)) {
41413
41694
  return false;
@@ -41434,7 +41715,7 @@ function pickEntryFile(files, preferredEntryFile) {
41434
41715
  return null;
41435
41716
  }
41436
41717
  function readProjectEntryFile(projectDir, preferredEntryFile) {
41437
- const absProjectDir = resolve20(projectDir);
41718
+ const absProjectDir = resolve21(projectDir);
41438
41719
  if (!existsSync40(absProjectDir) || !statSync13(absProjectDir).isDirectory()) {
41439
41720
  return { error: `Project directory not found: ${absProjectDir}` };
41440
41721
  }
@@ -41442,7 +41723,7 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
41442
41723
  (value) => typeof value === "string" && value.trim().length > 0
41443
41724
  );
41444
41725
  for (const entryFile of entryCandidates) {
41445
- const absoluteEntryPath = resolve20(absProjectDir, entryFile);
41726
+ const absoluteEntryPath = resolve21(absProjectDir, entryFile);
41446
41727
  if (!absoluteEntryPath.startsWith(absProjectDir)) {
41447
41728
  return { error: `Entry file must stay inside project directory: ${entryFile}` };
41448
41729
  }
@@ -41518,10 +41799,10 @@ var init_semaphore = __esm({
41518
41799
  this.active++;
41519
41800
  return () => this.release();
41520
41801
  }
41521
- return new Promise((resolve42) => {
41802
+ return new Promise((resolve43) => {
41522
41803
  this.queue.push(() => {
41523
41804
  this.active++;
41524
- resolve42(() => this.release());
41805
+ resolve43(() => this.release());
41525
41806
  });
41526
41807
  });
41527
41808
  }
@@ -41552,7 +41833,7 @@ import {
41552
41833
  rmSync as rmSync10,
41553
41834
  createReadStream
41554
41835
  } from "fs";
41555
- import { resolve as resolve21, dirname as dirname15, join as join51 } from "path";
41836
+ import { resolve as resolve22, dirname as dirname15, join as join51 } from "path";
41556
41837
  import { tmpdir as tmpdir3 } from "os";
41557
41838
  import { parseArgs as parseArgs2 } from "util";
41558
41839
  import crypto2 from "crypto";
@@ -41576,12 +41857,12 @@ async function prepareRenderBody(body) {
41576
41857
  const options = parseRenderOptions(body);
41577
41858
  const projectDir = typeof body.projectDir === "string" ? body.projectDir : void 0;
41578
41859
  if (projectDir) {
41579
- const absProjectDir = resolve21(projectDir);
41860
+ const absProjectDir = resolve22(projectDir);
41580
41861
  if (!existsSync41(absProjectDir) || !statSync14(absProjectDir).isDirectory()) {
41581
41862
  return { error: `Project directory not found: ${absProjectDir}` };
41582
41863
  }
41583
41864
  const entry = options.entryFile || "index.html";
41584
- if (!existsSync41(resolve21(absProjectDir, entry))) {
41865
+ if (!existsSync41(resolve22(absProjectDir, entry))) {
41585
41866
  return { error: `Entry file "${entry}" not found in project directory: ${absProjectDir}` };
41586
41867
  }
41587
41868
  return { prepared: { input: { projectDir: absProjectDir, ...options } } };
@@ -41622,7 +41903,7 @@ function resolveOutputPath(projectDir, outputCandidate, rendersDir, log2) {
41622
41903
  try {
41623
41904
  return resolveRenderPaths(projectDir, outputCandidate, rendersDir).absoluteOutputPath;
41624
41905
  } catch (error) {
41625
- const fallbackPath = resolve21(rendersDir, `producer-fallback-${Date.now()}.mp4`);
41906
+ const fallbackPath = resolve22(rendersDir, `producer-fallback-${Date.now()}.mp4`);
41626
41907
  log2.warn("Failed to resolve output path, using fallback", {
41627
41908
  fallback: fallbackPath,
41628
41909
  error: error instanceof Error ? error.message : String(error)
@@ -42011,7 +42292,7 @@ var init_server = __esm({
42011
42292
  init_logger();
42012
42293
  init_semaphore();
42013
42294
  init_src();
42014
- entryScript = process.argv[1] ? resolve21(process.argv[1]) : "";
42295
+ entryScript = process.argv[1] ? resolve22(process.argv[1]) : "";
42015
42296
  isPublicServerEntry = entryScript.endsWith("/public-server.js") || entryScript.endsWith("/src/server.ts");
42016
42297
  if (isPublicServerEntry) {
42017
42298
  const { values } = parseArgs2({
@@ -42138,7 +42419,7 @@ var init_runtimeEnvSnapshot = __esm({
42138
42419
 
42139
42420
  // ../producer/src/services/render/stages/freezePlan.ts
42140
42421
  import { existsSync as existsSync42, mkdirSync as mkdirSync26, readFileSync as readFileSync28, readdirSync as readdirSync17, writeFileSync as writeFileSync20 } from "fs";
42141
- import { join as join52, relative as relative4, resolve as resolve22 } from "path";
42422
+ import { join as join52, relative as relative4, resolve as resolve23 } from "path";
42142
42423
  function stripUndefined(value) {
42143
42424
  if (Array.isArray(value)) return value.map(stripUndefined);
42144
42425
  if (value !== null && typeof value === "object") {
@@ -42155,7 +42436,7 @@ function stripUndefined(value) {
42155
42436
  }
42156
42437
  function listPlanFiles(planDir) {
42157
42438
  const results = [];
42158
- const rootResolved = resolve22(planDir);
42439
+ const rootResolved = resolve23(planDir);
42159
42440
  function walk(dir) {
42160
42441
  const entries2 = readdirSync17(dir, { withFileTypes: true });
42161
42442
  for (const entry of entries2) {
@@ -42414,7 +42695,7 @@ import {
42414
42695
  statSync as statSync15,
42415
42696
  writeFileSync as writeFileSync21
42416
42697
  } from "fs";
42417
- import { join as join54, relative as relative5, sep as sep5 } from "path";
42698
+ import { join as join54, relative as relative5, sep as sep6 } from "path";
42418
42699
  function formatBytes(bytes) {
42419
42700
  if (bytes < 1024) return `${bytes} B`;
42420
42701
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KiB`;
@@ -42601,7 +42882,7 @@ async function plan(projectDir, config, planDir) {
42601
42882
  filter: (src) => {
42602
42883
  const rel = relative5(projectDir, src);
42603
42884
  if (rel === "" || rel.startsWith("..")) return true;
42604
- const firstSegment = rel.split(sep5, 1)[0];
42885
+ const firstSegment = rel.split(sep6, 1)[0];
42605
42886
  return firstSegment === void 0 || !PLAN_PROJECT_DIR_SKIP_SEGMENTS.has(firstSegment);
42606
42887
  }
42607
42888
  });
@@ -43368,7 +43649,7 @@ async function defaultRunFfmpeg(args) {
43368
43649
  };
43369
43650
  }
43370
43651
  function runFfprobeJson(args) {
43371
- return new Promise((resolve42, reject) => {
43652
+ return new Promise((resolve43, reject) => {
43372
43653
  const proc = spawn9("ffprobe", args);
43373
43654
  let stdout2 = "";
43374
43655
  let stderr = "";
@@ -43391,7 +43672,7 @@ function runFfprobeJson(args) {
43391
43672
  return;
43392
43673
  }
43393
43674
  try {
43394
- resolve42(JSON.parse(stdout2));
43675
+ resolve43(JSON.parse(stdout2));
43395
43676
  } catch (err) {
43396
43677
  reject(new Error(`Failed to parse ffprobe output: ${err.message}`));
43397
43678
  }
@@ -43647,18 +43928,18 @@ __export(studioServer_exports, {
43647
43928
  import { Hono as Hono5 } from "hono";
43648
43929
  import { streamSSE as streamSSE3 } from "hono/streaming";
43649
43930
  import { existsSync as existsSync47, readFileSync as readFileSync32, writeFileSync as writeFileSync24, statSync as statSync17 } from "fs";
43650
- import { resolve as resolve23, join as join57, basename as basename5 } from "path";
43931
+ import { resolve as resolve24, join as join57, basename as basename5 } from "path";
43651
43932
  function resolveDistDir() {
43652
43933
  return resolveStudioBundle().dir;
43653
43934
  }
43654
43935
  function resolveStudioBundle() {
43655
- const builtPath = resolve23(__dirname, "studio");
43656
- const builtIndex = resolve23(builtPath, "index.html");
43936
+ const builtPath = resolve24(__dirname, "studio");
43937
+ const builtIndex = resolve24(builtPath, "index.html");
43657
43938
  if (existsSync47(builtIndex)) {
43658
43939
  return { dir: builtPath, indexPath: builtIndex, available: true, checkedPaths: [builtIndex] };
43659
43940
  }
43660
- const devPath = resolve23(__dirname, "..", "..", "..", "studio", "dist");
43661
- const devIndex = resolve23(devPath, "index.html");
43941
+ const devPath = resolve24(__dirname, "..", "..", "..", "studio", "dist");
43942
+ const devIndex = resolve24(devPath, "index.html");
43662
43943
  if (existsSync47(devIndex)) {
43663
43944
  return {
43664
43945
  dir: devPath,
@@ -43675,11 +43956,11 @@ function resolveStudioBundle() {
43675
43956
  };
43676
43957
  }
43677
43958
  function resolveRuntimePath() {
43678
- const builtPath = resolve23(__dirname, "hyperframe-runtime.js");
43959
+ const builtPath = resolve24(__dirname, "hyperframe-runtime.js");
43679
43960
  if (existsSync47(builtPath)) return builtPath;
43680
- const iifePath = resolve23(__dirname, "hyperframe.runtime.iife.js");
43961
+ const iifePath = resolve24(__dirname, "hyperframe.runtime.iife.js");
43681
43962
  if (existsSync47(iifePath)) return iifePath;
43682
- const devPath = resolve23(
43963
+ const devPath = resolve24(
43683
43964
  __dirname,
43684
43965
  "..",
43685
43966
  "..",
@@ -43776,7 +44057,7 @@ function createStudioServer(options) {
43776
44057
  return injectDeterministicFontFaces2(html);
43777
44058
  },
43778
44059
  getProjectSignature(dir) {
43779
- if (resolve23(dir) !== resolve23(projectDir)) return createProjectSignature(dir);
44060
+ if (resolve24(dir) !== resolve24(projectDir)) return createProjectSignature(dir);
43780
44061
  cachedProjectSignature ??= createProjectSignature(projectDir);
43781
44062
  return cachedProjectSignature;
43782
44063
  },
@@ -43813,7 +44094,8 @@ function createStudioServer(options) {
43813
44094
  quality: opts.quality,
43814
44095
  format: opts.format,
43815
44096
  outputResolution: opts.outputResolution,
43816
- ...manualEditsRenderScript ? { renderBodyScripts: [manualEditsRenderScript] } : {}
44097
+ ...manualEditsRenderScript ? { renderBodyScripts: [manualEditsRenderScript] } : {},
44098
+ ...opts.composition ? { entryFile: opts.composition } : {}
43817
44099
  });
43818
44100
  const startTime = Date.now();
43819
44101
  const onProgress = (j3) => {
@@ -43933,7 +44215,7 @@ function createStudioServer(options) {
43933
44215
  return api.fetch(forwardReq);
43934
44216
  });
43935
44217
  const serveStudioStaticFile = (c3) => {
43936
- const filePath = resolve23(studioDir, c3.req.path.slice(1));
44218
+ const filePath = resolve24(studioDir, c3.req.path.slice(1));
43937
44219
  if (!existsSync47(filePath) || !statSync17(filePath).isFile()) return c3.text("not found", 404);
43938
44220
  const content = readFileSync32(filePath);
43939
44221
  return new Response(content, {
@@ -43944,7 +44226,7 @@ function createStudioServer(options) {
43944
44226
  app.get("/icons/*", serveStudioStaticFile);
43945
44227
  app.get("/favicon.svg", serveStudioStaticFile);
43946
44228
  app.get("*", (c3) => {
43947
- const indexPath = resolve23(studioDir, "index.html");
44229
+ const indexPath = resolve24(studioDir, "index.html");
43948
44230
  if (!existsSync47(indexPath)) {
43949
44231
  return c3.html(
43950
44232
  `<!doctype html>
@@ -44028,14 +44310,14 @@ __export(preview_exports, {
44028
44310
  });
44029
44311
  import { spawn as spawn10 } from "child_process";
44030
44312
  import { existsSync as existsSync48, lstatSync as lstatSync2, symlinkSync as symlinkSync2, unlinkSync as unlinkSync5, readlinkSync, mkdirSync as mkdirSync30 } from "fs";
44031
- import { resolve as resolve24, dirname as dirname18, basename as basename6, join as join58 } from "path";
44313
+ import { resolve as resolve25, dirname as dirname18, basename as basename6, join as join58 } from "path";
44032
44314
  import { fileURLToPath as fileURLToPath6 } from "url";
44033
44315
  import { createRequire as createRequire2 } from "module";
44034
- async function runDevMode(dir, projectName) {
44316
+ async function runDevMode(dir, options) {
44035
44317
  const thisFile = fileURLToPath6(import.meta.url);
44036
- const repoRoot = resolve24(dirname18(thisFile), "..", "..", "..", "..");
44318
+ const repoRoot = resolve25(dirname18(thisFile), "..", "..", "..", "..");
44037
44319
  const projectsDir = join58(repoRoot, "packages", "studio", "data", "projects");
44038
- const pName = projectName ?? basename6(dir);
44320
+ const pName = options?.projectName ?? basename6(dir);
44039
44321
  const symlinkPath = join58(projectsDir, pName);
44040
44322
  mkdirSync30(projectsDir, { recursive: true });
44041
44323
  let createdSymlink = false;
@@ -44045,7 +44327,7 @@ async function runDevMode(dir, projectName) {
44045
44327
  const stat3 = lstatSync2(symlinkPath);
44046
44328
  if (stat3.isSymbolicLink()) {
44047
44329
  const target = readlinkSync(symlinkPath);
44048
- if (resolve24(target) !== resolve24(dir)) {
44330
+ if (resolve25(target) !== resolve25(dir)) {
44049
44331
  unlinkSync5(symlinkPath);
44050
44332
  }
44051
44333
  }
@@ -44078,9 +44360,11 @@ async function runDevMode(dir, projectName) {
44078
44360
  console.log();
44079
44361
  console.log(` ${c2.dim("Press Ctrl+C to stop")}`);
44080
44362
  console.log();
44081
- const urlToOpen = `${frontendUrl}#project/${pName}`;
44082
- import("open").then((mod) => mod.default(urlToOpen)).catch(() => {
44083
- });
44363
+ if (!options?.noOpen) {
44364
+ const urlToOpen = `${frontendUrl}#project/${pName}`;
44365
+ import("open").then((mod) => mod.default(urlToOpen)).catch(() => {
44366
+ });
44367
+ }
44084
44368
  child.stdout?.removeListener("data", handleOutput);
44085
44369
  child.stderr?.removeListener("data", handleOutput);
44086
44370
  }
@@ -44099,8 +44383,8 @@ async function runDevMode(dir, projectName) {
44099
44383
  }
44100
44384
  });
44101
44385
  }
44102
- return new Promise((resolve42) => {
44103
- child.on("close", () => resolve42());
44386
+ return new Promise((resolve43) => {
44387
+ child.on("close", () => resolve43());
44104
44388
  });
44105
44389
  }
44106
44390
  function hasLocalStudio(dir) {
@@ -44112,17 +44396,17 @@ function hasLocalStudio(dir) {
44112
44396
  return false;
44113
44397
  }
44114
44398
  }
44115
- async function runLocalStudioMode(dir, projectName) {
44399
+ async function runLocalStudioMode(dir, options) {
44116
44400
  const req = createRequire2(join58(dir, "package.json"));
44117
44401
  const studioPkgPath = dirname18(req.resolve("@hyperframes/studio/package.json"));
44118
- const pName = projectName ?? basename6(dir);
44402
+ const pName = options?.projectName ?? basename6(dir);
44119
44403
  const projectsDir = join58(studioPkgPath, "data", "projects");
44120
44404
  const symlinkPath = join58(projectsDir, pName);
44121
44405
  mkdirSync30(projectsDir, { recursive: true });
44122
44406
  let createdSymlink = false;
44123
44407
  if (dir !== symlinkPath) {
44124
44408
  if (existsSync48(symlinkPath) && lstatSync2(symlinkPath).isSymbolicLink()) {
44125
- if (resolve24(readlinkSync(symlinkPath)) !== resolve24(dir)) {
44409
+ if (resolve25(readlinkSync(symlinkPath)) !== resolve25(dir)) {
44126
44410
  unlinkSync5(symlinkPath);
44127
44411
  }
44128
44412
  }
@@ -44152,8 +44436,10 @@ async function runLocalStudioMode(dir, projectName) {
44152
44436
  console.log();
44153
44437
  console.log(` ${c2.dim("Press Ctrl+C to stop")}`);
44154
44438
  console.log();
44155
- import("open").then((mod) => mod.default(`${url}#project/${pName}`)).catch(() => {
44156
- });
44439
+ if (!options?.noOpen) {
44440
+ import("open").then((mod) => mod.default(`${url}#project/${pName}`)).catch(() => {
44441
+ });
44442
+ }
44157
44443
  }
44158
44444
  }
44159
44445
  child.stdout?.on("data", handleOutput);
@@ -44170,13 +44456,13 @@ async function runLocalStudioMode(dir, projectName) {
44170
44456
  }
44171
44457
  });
44172
44458
  }
44173
- return new Promise((resolve42) => {
44174
- child.on("close", () => resolve42());
44459
+ return new Promise((resolve43) => {
44460
+ child.on("close", () => resolve43());
44175
44461
  });
44176
44462
  }
44177
- async function runEmbeddedMode(dir, startPort, projectName, forceNew = false) {
44463
+ async function runEmbeddedMode(dir, startPort, options) {
44178
44464
  const { createStudioServer: createStudioServer2, resolveStudioBundle: resolveStudioBundle2 } = await Promise.resolve().then(() => (init_studioServer(), studioServer_exports));
44179
- const pName = projectName ?? basename6(dir);
44465
+ const pName = options?.projectName ?? basename6(dir);
44180
44466
  const studioBundle = resolveStudioBundle2();
44181
44467
  ge(c2.bold("hyperframes preview"));
44182
44468
  const s2 = ft();
@@ -44197,7 +44483,7 @@ async function runEmbeddedMode(dir, startPort, projectName, forceNew = false) {
44197
44483
  const { app } = createStudioServer2({ projectDir: dir, projectName: pName });
44198
44484
  let result;
44199
44485
  try {
44200
- result = await findPortAndServe(app.fetch, startPort, dir, forceNew);
44486
+ result = await findPortAndServe(app.fetch, startPort, dir, !!options?.forceNew);
44201
44487
  } catch (err) {
44202
44488
  s2.stop(c2.error("Failed to start studio"));
44203
44489
  console.error();
@@ -44217,8 +44503,10 @@ async function runEmbeddedMode(dir, startPort, projectName, forceNew = false) {
44217
44503
  ` ${c2.dim("Reusing existing server. Use --force-new to start a fresh instance.")}`
44218
44504
  );
44219
44505
  console.log();
44220
- import("open").then((mod) => mod.default(`${url2}#project/${pName}`)).catch(() => {
44221
- });
44506
+ if (!options?.noOpen) {
44507
+ import("open").then((mod) => mod.default(`${url2}#project/${pName}`)).catch(() => {
44508
+ });
44509
+ }
44222
44510
  return;
44223
44511
  }
44224
44512
  const url = `http://localhost:${result.port}`;
@@ -44236,8 +44524,10 @@ async function runEmbeddedMode(dir, startPort, projectName, forceNew = false) {
44236
44524
  console.log();
44237
44525
  console.log(` ${c2.dim("Press Ctrl+C to stop")}`);
44238
44526
  console.log();
44239
- import("open").then((mod) => mod.default(`${url}#project/${pName}`)).catch(() => {
44240
- });
44527
+ if (!options?.noOpen) {
44528
+ import("open").then((mod) => mod.default(`${url}#project/${pName}`)).catch(() => {
44529
+ });
44530
+ }
44241
44531
  let rl;
44242
44532
  if (process.platform === "win32") {
44243
44533
  const readline = await import("readline");
@@ -44279,6 +44569,7 @@ var init_preview2 = __esm({
44279
44569
  ["Preview a specific project directory", "hyperframes preview ./my-video"],
44280
44570
  ["Use a custom port", "hyperframes preview --port 8080"],
44281
44571
  ["Force a new server even if one is already running", "hyperframes preview --force-new"],
44572
+ ["Start without opening the browser", "hyperframes preview --no-open"],
44282
44573
  ["List all active preview servers", "hyperframes preview --list"],
44283
44574
  ["Kill all active preview servers", "hyperframes preview --kill-all"]
44284
44575
  ];
@@ -44301,6 +44592,11 @@ var init_preview2 = __esm({
44301
44592
  type: "boolean",
44302
44593
  description: "Kill all active preview servers and exit",
44303
44594
  default: false
44595
+ },
44596
+ open: {
44597
+ type: "boolean",
44598
+ default: true,
44599
+ description: "Open browser automatically"
44304
44600
  }
44305
44601
  },
44306
44602
  async run({ args }) {
@@ -44338,7 +44634,7 @@ var init_preview2 = __esm({
44338
44634
  return;
44339
44635
  }
44340
44636
  const rawArg = args.dir;
44341
- const dir = resolve24(rawArg ?? ".");
44637
+ const dir = resolve25(rawArg ?? ".");
44342
44638
  const isImplicitCwd = !rawArg || rawArg === "." || rawArg === "./";
44343
44639
  const projectName = isImplicitCwd ? basename6(process.env.PWD ?? dir) : basename6(dir);
44344
44640
  const indexPath = join58(dir, "index.html");
@@ -44351,14 +44647,15 @@ var init_preview2 = __esm({
44351
44647
  console.log();
44352
44648
  }
44353
44649
  }
44650
+ const noOpen = !args.open;
44354
44651
  if (isDevMode()) {
44355
- return runDevMode(dir, projectName);
44652
+ return runDevMode(dir, { projectName, noOpen });
44356
44653
  }
44357
44654
  if (hasLocalStudio(dir)) {
44358
- return runLocalStudioMode(dir, projectName);
44655
+ return runLocalStudioMode(dir, { projectName, noOpen });
44359
44656
  }
44360
44657
  const forceNew = !!args["force-new"];
44361
- return runEmbeddedMode(dir, startPort, projectName, forceNew);
44658
+ return runEmbeddedMode(dir, startPort, { projectName, forceNew, noOpen });
44362
44659
  }
44363
44660
  });
44364
44661
  }
@@ -44381,7 +44678,7 @@ import {
44381
44678
  readFileSync as readFileSync33,
44382
44679
  readdirSync as readdirSync21
44383
44680
  } from "fs";
44384
- import { resolve as resolve25, basename as basename7, join as join59, dirname as dirname19 } from "path";
44681
+ import { resolve as resolve26, basename as basename7, join as join59, dirname as dirname19 } from "path";
44385
44682
  import { fileURLToPath as fileURLToPath7 } from "url";
44386
44683
  import { execFileSync as execFileSync5, spawn as spawn11 } from "child_process";
44387
44684
  function probeVideo(filePath) {
@@ -44451,8 +44748,8 @@ function transcodeToMp4(inputPath, outputPath) {
44451
44748
  }
44452
44749
  function resolveAssetDir(devSegments, builtSegments) {
44453
44750
  const base = dirname19(fileURLToPath7(import.meta.url));
44454
- const devPath = resolve25(base, ...devSegments);
44455
- const builtPath = resolve25(base, ...builtSegments);
44751
+ const devPath = resolve26(base, ...devSegments);
44752
+ const builtPath = resolve26(base, ...builtSegments);
44456
44753
  return existsSync49(devPath) ? devPath : builtPath;
44457
44754
  }
44458
44755
  function getStaticTemplateDir(templateId) {
@@ -44480,7 +44777,7 @@ function buildPackageScripts() {
44480
44777
  };
44481
44778
  }
44482
44779
  function writeDefaultPackageJson(destDir, projectName) {
44483
- const packageJsonPath = resolve25(destDir, "package.json");
44780
+ const packageJsonPath = resolve26(destDir, "package.json");
44484
44781
  if (existsSync49(packageJsonPath)) return;
44485
44782
  writeFileSync25(
44486
44783
  packageJsonPath,
@@ -44623,7 +44920,7 @@ async function handleVideoFile(videoPath, destDir, interactive) {
44623
44920
  }
44624
44921
  if (shouldTranscode) {
44625
44922
  const mp4Name = localVideoName.replace(/\.[^.]+$/, ".mp4");
44626
- const mp4Path = resolve25(destDir, mp4Name);
44923
+ const mp4Path = resolve26(destDir, mp4Name);
44627
44924
  const spin = ft();
44628
44925
  spin.start("Transcoding to H.264 MP4...");
44629
44926
  const ok = await transcodeToMp4(videoPath, mp4Path);
@@ -44632,10 +44929,10 @@ async function handleVideoFile(videoPath, destDir, interactive) {
44632
44929
  localVideoName = mp4Name;
44633
44930
  } else {
44634
44931
  spin.stop(c2.warn("Transcode failed \u2014 copying original file"));
44635
- copyFileSync5(videoPath, resolve25(destDir, localVideoName));
44932
+ copyFileSync5(videoPath, resolve26(destDir, localVideoName));
44636
44933
  }
44637
44934
  } else {
44638
- copyFileSync5(videoPath, resolve25(destDir, localVideoName));
44935
+ copyFileSync5(videoPath, resolve26(destDir, localVideoName));
44639
44936
  }
44640
44937
  } else {
44641
44938
  if (interactive) {
@@ -44645,10 +44942,10 @@ async function handleVideoFile(videoPath, destDir, interactive) {
44645
44942
  console.log(c2.warn("ffmpeg not installed \u2014 cannot transcode. Copying original."));
44646
44943
  console.log(c2.dim("Install: ") + c2.accent("brew install ffmpeg"));
44647
44944
  }
44648
- copyFileSync5(videoPath, resolve25(destDir, localVideoName));
44945
+ copyFileSync5(videoPath, resolve26(destDir, localVideoName));
44649
44946
  }
44650
44947
  } else {
44651
- copyFileSync5(videoPath, resolve25(destDir, localVideoName));
44948
+ copyFileSync5(videoPath, resolve26(destDir, localVideoName));
44652
44949
  }
44653
44950
  return { meta, localVideoName };
44654
44951
  }
@@ -44712,7 +45009,7 @@ async function scaffoldProject(destDir, name, templateId, localVideoName, durati
44712
45009
  if (tailwind) writeTailwindSupport(destDir);
44713
45010
  if (resolution) applyResolutionPreset(destDir, resolution);
44714
45011
  writeFileSync25(
44715
- resolve25(destDir, "meta.json"),
45012
+ resolve26(destDir, "meta.json"),
44716
45013
  JSON.stringify(
44717
45014
  {
44718
45015
  id: name,
@@ -44724,7 +45021,7 @@ async function scaffoldProject(destDir, name, templateId, localVideoName, durati
44724
45021
  ),
44725
45022
  "utf-8"
44726
45023
  );
44727
- if (!existsSync49(resolve25(destDir, "hyperframes.json"))) {
45024
+ if (!existsSync49(resolve26(destDir, "hyperframes.json"))) {
44728
45025
  const { writeProjectConfig: writeProjectConfig2, DEFAULT_PROJECT_CONFIG: DEFAULT_PROJECT_CONFIG2 } = await Promise.resolve().then(() => (init_projectConfig(), projectConfig_exports));
44729
45026
  writeProjectConfig2(destDir, DEFAULT_PROJECT_CONFIG2);
44730
45027
  }
@@ -44733,7 +45030,7 @@ async function scaffoldProject(destDir, name, templateId, localVideoName, durati
44733
45030
  if (existsSync49(sharedDir)) {
44734
45031
  for (const entry of readdirSync21(sharedDir, { withFileTypes: true })) {
44735
45032
  const src = join59(sharedDir, entry.name);
44736
- const dest = resolve25(destDir, entry.name);
45033
+ const dest = resolve26(destDir, entry.name);
44737
45034
  if (entry.isFile() || entry.isSymbolicLink()) {
44738
45035
  copyFileSync5(src, dest);
44739
45036
  }
@@ -44889,7 +45186,7 @@ var init_init = __esm({
44889
45186
  if (!interactive) {
44890
45187
  const templateId2 = exampleFlag ?? "blank";
44891
45188
  const name2 = args.name ?? "my-video";
44892
- const destDir2 = resolve25(name2);
45189
+ const destDir2 = resolve26(name2);
44893
45190
  if (existsSync49(destDir2) && readdirSync21(destDir2).length > 0) {
44894
45191
  console.error(c2.error(`Directory already exists and is not empty: ${name2}`));
44895
45192
  process.exit(1);
@@ -44903,7 +45200,7 @@ var init_init = __esm({
44903
45200
  process.exit(1);
44904
45201
  }
44905
45202
  if (videoFlag) {
44906
- const videoPath = resolve25(videoFlag);
45203
+ const videoPath = resolve26(videoFlag);
44907
45204
  if (!existsSync49(videoPath)) {
44908
45205
  console.error(c2.error(`Video file not found: ${videoFlag}`));
44909
45206
  process.exit(1);
@@ -44917,13 +45214,13 @@ var init_init = __esm({
44917
45214
  );
44918
45215
  }
44919
45216
  if (audioFlag) {
44920
- const audioPath = resolve25(audioFlag);
45217
+ const audioPath = resolve26(audioFlag);
44921
45218
  if (!existsSync49(audioPath)) {
44922
45219
  console.error(c2.error(`Audio file not found: ${audioFlag}`));
44923
45220
  process.exit(1);
44924
45221
  }
44925
45222
  sourceFilePath2 = audioPath;
44926
- copyFileSync5(audioPath, resolve25(destDir2, basename7(audioPath)));
45223
+ copyFileSync5(audioPath, resolve26(destDir2, basename7(audioPath)));
44927
45224
  console.log(`Audio: ${basename7(audioPath)}`);
44928
45225
  }
44929
45226
  if (sourceFilePath2 && !skipTranscribe) {
@@ -44965,7 +45262,7 @@ var init_init = __esm({
44965
45262
  process.exit(1);
44966
45263
  }
44967
45264
  trackInitTemplate(templateId2, { tailwind });
44968
- const transcriptFile2 = resolve25(destDir2, "transcript.json");
45265
+ const transcriptFile2 = resolve26(destDir2, "transcript.json");
44969
45266
  if (existsSync49(transcriptFile2)) {
44970
45267
  await patchTranscript(destDir2, transcriptFile2);
44971
45268
  }
@@ -45020,7 +45317,7 @@ var init_init = __esm({
45020
45317
  }
45021
45318
  name = nameResult;
45022
45319
  }
45023
- const destDir = resolve25(name);
45320
+ const destDir = resolve26(name);
45024
45321
  if (existsSync49(destDir) && readdirSync21(destDir).length > 0) {
45025
45322
  const overwrite = await ue({
45026
45323
  message: `Directory ${c2.accent(name)} already exists and is not empty. Overwrite?`,
@@ -45035,7 +45332,7 @@ var init_init = __esm({
45035
45332
  let sourceFilePath;
45036
45333
  let videoDuration;
45037
45334
  if (videoFlag) {
45038
- const videoPath = resolve25(videoFlag);
45335
+ const videoPath = resolve26(videoFlag);
45039
45336
  if (!existsSync49(videoPath)) {
45040
45337
  R2.error(`File not found: ${videoFlag}`);
45041
45338
  me("Setup cancelled.");
@@ -45047,7 +45344,7 @@ var init_init = __esm({
45047
45344
  localVideoName = result.localVideoName;
45048
45345
  videoDuration = result.meta.durationSeconds;
45049
45346
  } else if (audioFlag) {
45050
- const audioPath = resolve25(audioFlag);
45347
+ const audioPath = resolve26(audioFlag);
45051
45348
  if (!existsSync49(audioPath)) {
45052
45349
  R2.error(`File not found: ${audioFlag}`);
45053
45350
  me("Setup cancelled.");
@@ -45055,7 +45352,7 @@ var init_init = __esm({
45055
45352
  }
45056
45353
  mkdirSync31(destDir, { recursive: true });
45057
45354
  sourceFilePath = audioPath;
45058
- copyFileSync5(audioPath, resolve25(destDir, basename7(audioPath)));
45355
+ copyFileSync5(audioPath, resolve26(destDir, basename7(audioPath)));
45059
45356
  R2.info(`Audio copied to ${c2.accent(basename7(audioPath))}`);
45060
45357
  }
45061
45358
  if (sourceFilePath) {
@@ -45148,7 +45445,7 @@ ${c2.dim("Use --example blank for offline use.")}`
45148
45445
  process.exit(1);
45149
45446
  }
45150
45447
  trackInitTemplate(templateId, { tailwind });
45151
- const transcriptFile = resolve25(destDir, "transcript.json");
45448
+ const transcriptFile = resolve26(destDir, "transcript.json");
45152
45449
  if (existsSync49(transcriptFile)) {
45153
45450
  await patchTranscript(destDir, transcriptFile);
45154
45451
  }
@@ -45236,7 +45533,7 @@ __export(add_exports, {
45236
45533
  runAdd: () => runAdd
45237
45534
  });
45238
45535
  import { existsSync as existsSync50 } from "fs";
45239
- import { resolve as resolve26, relative as relative6 } from "path";
45536
+ import { resolve as resolve27, relative as relative6 } from "path";
45240
45537
  function remapTarget(item, originalTarget, paths) {
45241
45538
  if (item.type === "hyperframes:block") {
45242
45539
  const blocksDir = paths.blocks.replace(/\/+$/, "");
@@ -45259,10 +45556,10 @@ function buildSnippet(item, relativeTarget) {
45259
45556
  return "";
45260
45557
  }
45261
45558
  async function runAdd(opts) {
45262
- const projectDir = resolve26(opts.projectDir);
45559
+ const projectDir = resolve27(opts.projectDir);
45263
45560
  let config = loadProjectConfig(projectDir);
45264
45561
  const hasConfig = existsSync50(projectConfigPath(projectDir));
45265
- if (!hasConfig && existsSync50(resolve26(projectDir, "index.html"))) {
45562
+ if (!hasConfig && existsSync50(resolve27(projectDir, "index.html"))) {
45266
45563
  writeProjectConfig(projectDir, DEFAULT_PROJECT_CONFIG);
45267
45564
  config = DEFAULT_PROJECT_CONFIG;
45268
45565
  }
@@ -45361,7 +45658,7 @@ var init_add = __esm({
45361
45658
  }
45362
45659
  },
45363
45660
  async run({ args }) {
45364
- const projectDir = resolve26(args.dir ?? process.cwd());
45661
+ const projectDir = resolve27(args.dir ?? process.cwd());
45365
45662
  const json = args.json === true;
45366
45663
  const skipClipboard = args["no-clipboard"] === true;
45367
45664
  const hasConfigBefore = existsSync50(projectConfigPath(projectDir));
@@ -45397,7 +45694,7 @@ var init_add = __esm({
45397
45694
  process.exit(1);
45398
45695
  }
45399
45696
  let config = loadProjectConfig(projectDir);
45400
- if (!existsSync50(projectConfigPath(projectDir)) && existsSync50(resolve26(projectDir, "index.html"))) {
45697
+ if (!existsSync50(projectConfigPath(projectDir)) && existsSync50(resolve27(projectDir, "index.html"))) {
45401
45698
  writeProjectConfig(projectDir, DEFAULT_PROJECT_CONFIG);
45402
45699
  config = DEFAULT_PROJECT_CONFIG;
45403
45700
  }
@@ -45449,7 +45746,7 @@ __export(catalog_exports, {
45449
45746
  default: () => catalog_default,
45450
45747
  examples: () => examples4
45451
45748
  });
45452
- import { resolve as resolve27 } from "path";
45749
+ import { resolve as resolve28 } from "path";
45453
45750
  var examples4, catalog_default;
45454
45751
  var init_catalog = __esm({
45455
45752
  "src/commands/catalog.ts"() {
@@ -45493,7 +45790,7 @@ var init_catalog = __esm({
45493
45790
  async run({ args }) {
45494
45791
  const json = args.json === true;
45495
45792
  const interactive = args["human-friendly"] === true;
45496
- const dir = resolve27(process.cwd());
45793
+ const dir = resolve28(process.cwd());
45497
45794
  const config = loadProjectConfig(dir) ?? DEFAULT_PROJECT_CONFIG;
45498
45795
  let typeFilter;
45499
45796
  if (args.type === "block") typeFilter = "hyperframes:block";
@@ -45618,11 +45915,11 @@ var init_format = __esm({
45618
45915
 
45619
45916
  // src/utils/project.ts
45620
45917
  import { existsSync as existsSync51, statSync as statSync18 } from "fs";
45621
- import { resolve as resolve28, basename as basename8 } from "path";
45918
+ import { resolve as resolve29, basename as basename8 } from "path";
45622
45919
  function resolveProject(dirArg) {
45623
- const dir = resolve28(dirArg ?? ".");
45920
+ const dir = resolve29(dirArg ?? ".");
45624
45921
  const name = basename8(dir);
45625
- const indexPath = resolve28(dir, "index.html");
45922
+ const indexPath = resolve29(dir, "index.html");
45626
45923
  if (!existsSync51(dir) || !statSync18(dir).isDirectory()) {
45627
45924
  errorBox("Not a directory: " + dir);
45628
45925
  process.exit(1);
@@ -45651,7 +45948,7 @@ __export(play_exports, {
45651
45948
  examples: () => examples5
45652
45949
  });
45653
45950
  import { existsSync as existsSync52, readFileSync as readFileSync34 } from "fs";
45654
- import { resolve as resolve29, dirname as dirname20 } from "path";
45951
+ import { resolve as resolve30, dirname as dirname20 } from "path";
45655
45952
  function commandDir() {
45656
45953
  return dirname20(new URL(import.meta.url).pathname);
45657
45954
  }
@@ -45659,10 +45956,10 @@ function resolveRuntimePath2() {
45659
45956
  const d2 = commandDir();
45660
45957
  const candidates = [
45661
45958
  // Bundled with CLI dist
45662
- resolve29(d2, "hyperframe-runtime.js"),
45663
- resolve29(d2, "..", "hyperframe-runtime.js"),
45959
+ resolve30(d2, "hyperframe-runtime.js"),
45960
+ resolve30(d2, "..", "hyperframe-runtime.js"),
45664
45961
  // Monorepo dev: commands/ → src/ → cli/ → packages/ then into core/dist/
45665
- resolve29(d2, "..", "..", "..", "core", "dist", "hyperframe.runtime.iife.js")
45962
+ resolve30(d2, "..", "..", "..", "core", "dist", "hyperframe.runtime.iife.js")
45666
45963
  ];
45667
45964
  for (const p2 of candidates) {
45668
45965
  if (existsSync52(p2)) return p2;
@@ -45673,10 +45970,10 @@ function resolvePlayerPath() {
45673
45970
  const d2 = commandDir();
45674
45971
  const candidates = [
45675
45972
  // Monorepo dev: commands/ → src/ → cli/ → packages/ then into player/dist/
45676
- resolve29(d2, "..", "..", "..", "player", "dist", "hyperframes-player.global.js"),
45973
+ resolve30(d2, "..", "..", "..", "player", "dist", "hyperframes-player.global.js"),
45677
45974
  // Bundled with CLI dist
45678
- resolve29(d2, "hyperframes-player.global.js"),
45679
- resolve29(d2, "..", "hyperframes-player.global.js")
45975
+ resolve30(d2, "hyperframes-player.global.js"),
45976
+ resolve30(d2, "..", "hyperframes-player.global.js")
45680
45977
  ];
45681
45978
  for (const p2 of candidates) {
45682
45979
  if (existsSync52(p2)) return p2;
@@ -45739,13 +46036,19 @@ var init_play = __esm({
45739
46036
  examples5 = [
45740
46037
  ["Play the current project", "hyperframes play"],
45741
46038
  ["Play a specific project directory", "hyperframes play ./my-video"],
45742
- ["Use a custom port", "hyperframes play --port 8080"]
46039
+ ["Use a custom port", "hyperframes play --port 8080"],
46040
+ ["Start without opening the browser", "hyperframes play --no-open"]
45743
46041
  ];
45744
46042
  play_default = defineCommand({
45745
46043
  meta: { name: "play", description: "Play a composition in a lightweight browser player" },
45746
46044
  args: {
45747
46045
  dir: { type: "positional", description: "Project directory", required: false },
45748
- port: { type: "string", description: "Port to run the player server on", default: "3003" }
46046
+ port: { type: "string", description: "Port to run the player server on", default: "3003" },
46047
+ open: {
46048
+ type: "boolean",
46049
+ default: true,
46050
+ description: "Open browser automatically"
46051
+ }
45749
46052
  },
45750
46053
  async run({ args }) {
45751
46054
  const project = resolveProject(args.dir);
@@ -45781,7 +46084,7 @@ var init_play = __esm({
45781
46084
  });
45782
46085
  app.get("/composition/*", async (ctx) => {
45783
46086
  const reqPath = ctx.req.path.replace("/composition/", "");
45784
- const filePath = resolve29(project.dir, reqPath);
46087
+ const filePath = resolve30(project.dir, reqPath);
45785
46088
  if (!filePath.startsWith(project.dir)) return ctx.text("Forbidden", 403);
45786
46089
  if (!existsSync52(filePath)) return ctx.text("Not found", 404);
45787
46090
  const content = readFileSync34(filePath, "utf-8");
@@ -45849,8 +46152,10 @@ var init_play = __esm({
45849
46152
  console.log();
45850
46153
  console.log(` ${c2.dim("Press Ctrl+C to stop")}`);
45851
46154
  console.log();
45852
- import("open").then((mod) => mod.default(url)).catch(() => {
45853
- });
46155
+ if (args.open) {
46156
+ import("open").then((mod) => mod.default(url)).catch(() => {
46157
+ });
46158
+ }
45854
46159
  return new Promise(() => {
45855
46160
  });
45856
46161
  }
@@ -46099,7 +46404,7 @@ __export(publish_exports, {
46099
46404
  default: () => publish_default,
46100
46405
  examples: () => examples6
46101
46406
  });
46102
- import { basename as basename10, resolve as resolve30 } from "path";
46407
+ import { basename as basename10, resolve as resolve31 } from "path";
46103
46408
  import { existsSync as existsSync53 } from "fs";
46104
46409
  import { join as join61 } from "path";
46105
46410
  var examples6, publish_default;
@@ -46133,7 +46438,7 @@ var init_publish = __esm({
46133
46438
  },
46134
46439
  async run({ args }) {
46135
46440
  const rawArg = args.dir;
46136
- const dir = resolve30(rawArg ?? ".");
46441
+ const dir = resolve31(rawArg ?? ".");
46137
46442
  const isImplicitCwd = !rawArg || rawArg === "." || rawArg === "./";
46138
46443
  const projectName = isImplicitCwd ? basename10(process.env["PWD"] ?? dir) : basename10(dir);
46139
46444
  const indexPath = join61(dir, "index.html");
@@ -46260,7 +46565,8 @@ function buildDockerRunArgs(input) {
46260
46565
  ...options.hdrMode === "force-sdr" ? ["--sdr"] : [],
46261
46566
  ...options.variables && Object.keys(options.variables).length > 0 ? ["--variables", JSON.stringify(options.variables)] : [],
46262
46567
  ...options.entryFile ? ["--composition", options.entryFile] : [],
46263
- ...options.outputResolution ? ["--resolution", options.outputResolution] : []
46568
+ ...options.outputResolution ? ["--resolution", options.outputResolution] : [],
46569
+ ...options.pageSideCompositing === false ? ["--no-page-side-compositing"] : []
46264
46570
  ];
46265
46571
  }
46266
46572
  var init_dockerRunArgs = __esm({
@@ -46333,7 +46639,7 @@ __export(render_exports, {
46333
46639
  });
46334
46640
  import { mkdirSync as mkdirSync32, readdirSync as readdirSync23, readFileSync as readFileSync36, statSync as statSync20, writeFileSync as writeFileSync26, rmSync as rmSync14 } from "fs";
46335
46641
  import { cpus as cpus4, freemem as freemem3, tmpdir as tmpdir4 } from "os";
46336
- import { resolve as resolve31, dirname as dirname21, join as join62, basename as basename11 } from "path";
46642
+ import { resolve as resolve32, dirname as dirname21, join as join62, basename as basename11 } from "path";
46337
46643
  import { execFileSync as execFileSync6, spawn as spawn12 } from "child_process";
46338
46644
  function formatFpsParseError(input, reason) {
46339
46645
  switch (reason) {
@@ -46351,7 +46657,7 @@ function formatFpsParseError(input, reason) {
46351
46657
  return `Got "${input}". Decimal frame rates are ambiguous \u2014 use the exact rational form instead (e.g. 30000/1001 for 29.97).`;
46352
46658
  }
46353
46659
  }
46354
- function parseVariablesArg(inline, filePath, readFile = (p2) => readFileSync36(resolve31(p2), "utf8")) {
46660
+ function parseVariablesArg(inline, filePath, readFile = (p2) => readFileSync36(resolve32(p2), "utf8")) {
46355
46661
  if (inline != null && filePath != null) {
46356
46662
  return { ok: false, error: { kind: "conflict" } };
46357
46663
  }
@@ -46450,8 +46756,8 @@ function dockerImageTag(version) {
46450
46756
  return `${DOCKER_IMAGE_PREFIX}:${version}`;
46451
46757
  }
46452
46758
  function resolveDockerfilePath() {
46453
- const builtPath = resolve31(__dirname, "docker", "Dockerfile.render");
46454
- const devPath = resolve31(__dirname, "..", "src", "docker", "Dockerfile.render");
46759
+ const builtPath = resolve32(__dirname, "docker", "Dockerfile.render");
46760
+ const devPath = resolve32(__dirname, "..", "src", "docker", "Dockerfile.render");
46455
46761
  for (const p2 of [builtPath, devPath]) {
46456
46762
  try {
46457
46763
  statSync20(p2);
@@ -46528,8 +46834,8 @@ async function renderDocker(projectDir, outputPath, options) {
46528
46834
  const outputFilename = basename11(outputPath);
46529
46835
  const dockerArgs = buildDockerRunArgs({
46530
46836
  imageTag,
46531
- projectDir: resolve31(projectDir),
46532
- outputDir: resolve31(outputDir),
46837
+ projectDir: resolve32(projectDir),
46838
+ outputDir: resolve32(outputDir),
46533
46839
  outputFilename,
46534
46840
  options: {
46535
46841
  fps: options.fps,
@@ -46544,7 +46850,8 @@ async function renderDocker(projectDir, outputPath, options) {
46544
46850
  quiet: options.quiet,
46545
46851
  variables: options.variables,
46546
46852
  entryFile: options.entryFile,
46547
- outputResolution: options.outputResolution
46853
+ outputResolution: options.outputResolution,
46854
+ pageSideCompositing: options.pageSideCompositing
46548
46855
  }
46549
46856
  });
46550
46857
  if (!options.quiet) {
@@ -46868,6 +47175,11 @@ var init_render2 = __esm({
46868
47175
  resolution: {
46869
47176
  type: "string",
46870
47177
  description: "Output resolution preset: landscape (1920x1080), portrait (1080x1920), landscape-4k (3840x2160), portrait-4k (2160x3840), square (1080x1080), square-4k (2160x2160). Aliases: 1080p, 4k, uhd, 1080p-square, square-1080p, 4k-square. The composition is unchanged \u2014 Chrome renders at higher DPR (deviceScaleFactor) so the captured screenshot lands at the requested dimensions. Aspect ratio must match the composition; the scale must be an integer multiple. Not yet supported with --hdr."
47178
+ },
47179
+ "page-side-compositing": {
47180
+ type: "boolean",
47181
+ description: "Run shader transitions on a page-side WebGL canvas inside Chrome instead of the Node-side layered blend. ~6\xD7 faster for SDR shader-transition renders. HDR/alpha/video content auto-disables. Use --no-page-side-compositing to force the layered path.",
47182
+ default: true
46871
47183
  }
46872
47184
  },
46873
47185
  async run({ args }) {
@@ -46918,6 +47230,9 @@ var init_render2 = __esm({
46918
47230
  }
46919
47231
  workers = parsed;
46920
47232
  }
47233
+ if (args["page-side-compositing"] === false) {
47234
+ process.env.HF_PAGE_SIDE_COMPOSITING = "false";
47235
+ }
46921
47236
  if (args["max-concurrent-renders"] != null) {
46922
47237
  const parsed = parseInt(args["max-concurrent-renders"], 10);
46923
47238
  if (isNaN(parsed) || parsed < 1 || parsed > 10) {
@@ -46929,12 +47244,12 @@ var init_render2 = __esm({
46929
47244
  }
46930
47245
  process.env.PRODUCER_MAX_CONCURRENT_RENDERS = String(parsed);
46931
47246
  }
46932
- const rendersDir = resolve31("renders");
47247
+ const rendersDir = resolve32("renders");
46933
47248
  const ext = FORMAT_EXT[format] ?? ".mp4";
46934
47249
  const now = /* @__PURE__ */ new Date();
46935
47250
  const datePart = now.toISOString().slice(0, 10);
46936
47251
  const timePart = now.toTimeString().slice(0, 8).replace(/:/g, "-");
46937
- const outputPath = args.output ? resolve31(args.output) : join62(rendersDir, `${project.name}_${datePart}_${timePart}${ext}`);
47252
+ const outputPath = args.output ? resolve32(args.output) : join62(rendersDir, `${project.name}_${datePart}_${timePart}${ext}`);
46938
47253
  mkdirSync32(dirname21(outputPath), { recursive: true });
46939
47254
  const useDocker = args.docker ?? false;
46940
47255
  const useGpu = args.gpu ?? false;
@@ -46975,8 +47290,8 @@ var init_render2 = __esm({
46975
47290
  }
46976
47291
  const entryFile = args.composition?.trim().replace(/^\.\//, "") || void 0;
46977
47292
  if (entryFile) {
46978
- const absProjectDir = resolve31(project.dir);
46979
- const entryPath = resolve31(absProjectDir, entryFile);
47293
+ const absProjectDir = resolve32(project.dir);
47294
+ const entryPath = resolve32(absProjectDir, entryFile);
46980
47295
  if (!entryPath.startsWith(absProjectDir)) {
46981
47296
  errorBox(
46982
47297
  "Invalid composition path",
@@ -47122,6 +47437,7 @@ var init_render2 = __esm({
47122
47437
  variables,
47123
47438
  entryFile,
47124
47439
  outputResolution,
47440
+ pageSideCompositing: args["page-side-compositing"] !== false,
47125
47441
  exitAfterComplete: true
47126
47442
  });
47127
47443
  } else {
@@ -47350,7 +47666,7 @@ var init_lint3 = __esm({
47350
47666
  // src/utils/staticProjectServer.ts
47351
47667
  import { createServer } from "http";
47352
47668
  import { existsSync as existsSync54, readFileSync as readFileSync37 } from "fs";
47353
- import { isAbsolute as isAbsolute8, relative as relative8, resolve as resolve32 } from "path";
47669
+ import { isAbsolute as isAbsolute8, relative as relative8, resolve as resolve33 } from "path";
47354
47670
  async function serveStaticProjectHtml(projectDir, html, bindErrorMessage = "Failed to bind local HTTP server") {
47355
47671
  const server = createServer((req, res) => {
47356
47672
  const url = req.url ?? "/";
@@ -47359,7 +47675,7 @@ async function serveStaticProjectHtml(projectDir, html, bindErrorMessage = "Fail
47359
47675
  res.end(html);
47360
47676
  return;
47361
47677
  }
47362
- const filePath = resolve32(projectDir, decodeURIComponent(url).replace(/^\//, ""));
47678
+ const filePath = resolve33(projectDir, decodeURIComponent(url).replace(/^\//, ""));
47363
47679
  const rel = relative8(projectDir, filePath);
47364
47680
  if (rel.startsWith("..") || isAbsolute8(rel)) {
47365
47681
  res.writeHead(403);
@@ -47597,7 +47913,7 @@ async function seekTo(page, time) {
47597
47913
  if (!fonts?.ready) return Promise.resolve();
47598
47914
  return Promise.race([
47599
47915
  fonts.ready.then(() => void 0),
47600
- new Promise((resolve42) => setTimeout(resolve42, 500))
47916
+ new Promise((resolve43) => setTimeout(resolve43, 500))
47601
47917
  ]);
47602
47918
  }).catch(() => {
47603
47919
  });
@@ -47657,7 +47973,7 @@ async function runLayoutAudit(projectDir, opts) {
47657
47973
  if (!fonts?.ready) return Promise.resolve();
47658
47974
  return Promise.race([
47659
47975
  fonts.ready.then(() => void 0),
47660
- new Promise((resolve42) => setTimeout(resolve42, 750))
47976
+ new Promise((resolve43) => setTimeout(resolve43, 750))
47661
47977
  ]);
47662
47978
  }).catch(() => {
47663
47979
  });
@@ -48000,7 +48316,7 @@ __export(compositions_exports, {
48000
48316
  parseSubComposition: () => parseSubComposition
48001
48317
  });
48002
48318
  import { existsSync as existsSync56, readFileSync as readFileSync40 } from "fs";
48003
- import { resolve as resolve33, dirname as dirname23 } from "path";
48319
+ import { resolve as resolve34, dirname as dirname23 } from "path";
48004
48320
  function countRenderableDescendants(root) {
48005
48321
  return Array.from(root.querySelectorAll("*")).filter(
48006
48322
  (el) => !NON_RENDERED_TAGS.has(el.tagName.toLowerCase())
@@ -48032,7 +48348,7 @@ function parseCompositions(html, baseDir) {
48032
48348
  const height = parseInt(div.getAttribute("data-height") ?? "1080", 10);
48033
48349
  const compositionSrc = div.getAttribute("data-composition-src");
48034
48350
  if (compositionSrc) {
48035
- const subPath = resolve33(baseDir, compositionSrc);
48351
+ const subPath = resolve34(baseDir, compositionSrc);
48036
48352
  if (existsSync56(subPath)) {
48037
48353
  const subHtml = readFileSync40(subPath, "utf-8");
48038
48354
  const subInfo = parseSubComposition(subHtml, id, width, height);
@@ -48176,7 +48492,7 @@ __export(benchmark_exports, {
48176
48492
  examples: () => examples13
48177
48493
  });
48178
48494
  import { existsSync as existsSync57, statSync as statSync22 } from "fs";
48179
- import { resolve as resolve34, join as join65 } from "path";
48495
+ import { resolve as resolve35, join as join65 } from "path";
48180
48496
  var examples13, FPS_30, FPS_60, DEFAULT_CONFIGS, benchmark_default;
48181
48497
  var init_benchmark = __esm({
48182
48498
  "src/commands/benchmark.ts"() {
@@ -48221,7 +48537,7 @@ var init_benchmark = __esm({
48221
48537
  process.exit(1);
48222
48538
  }
48223
48539
  const jsonOutput = args.json ?? false;
48224
- const benchDir = resolve34("renders", ".benchmark");
48540
+ const benchDir = resolve35("renders", ".benchmark");
48225
48541
  let producer = null;
48226
48542
  try {
48227
48543
  producer = await loadProducer();
@@ -48977,12 +49293,12 @@ async function runPipeline(options, session, media, format, bgFormat) {
48977
49293
  const drains = [];
48978
49294
  if (!fgWroteFully) {
48979
49295
  drains.push(
48980
- new Promise((resolve42) => fg.proc.stdin.once("drain", () => resolve42()))
49296
+ new Promise((resolve43) => fg.proc.stdin.once("drain", () => resolve43()))
48981
49297
  );
48982
49298
  }
48983
49299
  if (!bgWroteFully && bg) {
48984
49300
  drains.push(
48985
- new Promise((resolve42) => bg.proc.stdin.once("drain", () => resolve42()))
49301
+ new Promise((resolve43) => bg.proc.stdin.once("drain", () => resolve43()))
48986
49302
  );
48987
49303
  }
48988
49304
  await Promise.all(drains);
@@ -49015,11 +49331,11 @@ ${decoder.getStderr().slice(-400)}`
49015
49331
  return processed;
49016
49332
  }
49017
49333
  function waitForExit(proc, label2, getStderr) {
49018
- return new Promise((resolve42, reject) => {
49334
+ return new Promise((resolve43, reject) => {
49019
49335
  proc.on("error", reject);
49020
49336
  proc.on("exit", (code, signal) => {
49021
49337
  if (code === 0 && !signal) {
49022
- resolve42();
49338
+ resolve43();
49023
49339
  return;
49024
49340
  }
49025
49341
  const cause = signal ? `killed by ${signal}` : `exited with code ${code}`;
@@ -49053,7 +49369,7 @@ __export(remove_background_exports, {
49053
49369
  default: () => remove_background_default,
49054
49370
  examples: () => examples15
49055
49371
  });
49056
- import { resolve as resolve35 } from "path";
49372
+ import { resolve as resolve36 } from "path";
49057
49373
  import { existsSync as existsSync59 } from "fs";
49058
49374
  async function showInfo(json) {
49059
49375
  const { selectProviders: selectProviders2, listAvailableProviders: listAvailableProviders2, DEFAULT_MODEL: DEFAULT_MODEL4, MODEL_MEMORY_MB: MODEL_MEMORY_MB2, modelPath: modelPath2 } = await Promise.resolve().then(() => (init_manager3(), manager_exports3));
@@ -49195,10 +49511,10 @@ var init_remove_background = __esm({
49195
49511
  );
49196
49512
  process.exit(1);
49197
49513
  }
49198
- const inputPath = resolve35(args.input);
49199
- const outputPath = resolve35(args.output);
49514
+ const inputPath = resolve36(args.input);
49515
+ const outputPath = resolve36(args.output);
49200
49516
  const backgroundOutputArg = args["background-output"];
49201
- const backgroundOutputPath = backgroundOutputArg ? resolve35(backgroundOutputArg) : void 0;
49517
+ const backgroundOutputPath = backgroundOutputArg ? resolve36(backgroundOutputArg) : void 0;
49202
49518
  const { render: render3 } = await Promise.resolve().then(() => (init_pipeline(), pipeline_exports));
49203
49519
  const spin = args.json ? null : ft();
49204
49520
  spin?.start("Preparing background-removal pipeline...");
@@ -49267,7 +49583,7 @@ __export(transcribe_exports2, {
49267
49583
  examples: () => examples16
49268
49584
  });
49269
49585
  import { existsSync as existsSync60, writeFileSync as writeFileSync27 } from "fs";
49270
- import { resolve as resolve36, join as join67, extname as extname11 } from "path";
49586
+ import { resolve as resolve37, join as join67, extname as extname11 } from "path";
49271
49587
  async function importTranscript(inputPath, dir, json) {
49272
49588
  const { loadTranscript: loadTranscript2, patchCaptionHtml: patchCaptionHtml2 } = await Promise.resolve().then(() => (init_normalize(), normalize_exports));
49273
49589
  const { words, format } = loadTranscript2(inputPath);
@@ -49391,12 +49707,12 @@ var init_transcribe2 = __esm({
49391
49707
  }
49392
49708
  },
49393
49709
  async run({ args }) {
49394
- const inputPath = resolve36(args.input);
49710
+ const inputPath = resolve37(args.input);
49395
49711
  if (!existsSync60(inputPath)) {
49396
49712
  console.error(c2.error(`File not found: ${args.input}`));
49397
49713
  process.exit(1);
49398
49714
  }
49399
- const dir = resolve36(args.dir ?? ".");
49715
+ const dir = resolve37(args.dir ?? ".");
49400
49716
  const ext = extname11(inputPath).toLowerCase();
49401
49717
  const isImport = ext === ".json" || ext === ".srt" || ext === ".vtt";
49402
49718
  if (isImport) {
@@ -49686,7 +50002,7 @@ __export(tts_exports, {
49686
50002
  examples: () => examples17
49687
50003
  });
49688
50004
  import { existsSync as existsSync63, readFileSync as readFileSync41 } from "fs";
49689
- import { resolve as resolve37, extname as extname12 } from "path";
50005
+ import { resolve as resolve38, extname as extname12 } from "path";
49690
50006
  function listVoices(json) {
49691
50007
  const rows = BUNDLED_VOICES.map((v2) => ({ ...v2, defaultLang: inferLangFromVoiceId(v2.id) }));
49692
50008
  if (json) {
@@ -49794,7 +50110,7 @@ var init_tts = __esm({
49794
50110
  process.exit(1);
49795
50111
  }
49796
50112
  let text;
49797
- const maybeFile = resolve37(args.input);
50113
+ const maybeFile = resolve38(args.input);
49798
50114
  if (existsSync63(maybeFile) && extname12(maybeFile).toLowerCase() === ".txt") {
49799
50115
  text = readFileSync41(maybeFile, "utf-8").trim();
49800
50116
  if (!text) {
@@ -49808,7 +50124,7 @@ var init_tts = __esm({
49808
50124
  console.error(c2.error("No text provided."));
49809
50125
  process.exit(1);
49810
50126
  }
49811
- const output = resolve37(args.output ?? "speech.wav");
50127
+ const output = resolve38(args.output ?? "speech.wav");
49812
50128
  const voice = args.voice ?? DEFAULT_VOICE;
49813
50129
  const speed = args.speed ? parseFloat(args.speed) : 1;
49814
50130
  if (isNaN(speed) || speed <= 0 || speed > 3) {
@@ -49889,13 +50205,13 @@ __export(docs_exports, {
49889
50205
  examples: () => examples18
49890
50206
  });
49891
50207
  import { readFileSync as readFileSync42, existsSync as existsSync64 } from "fs";
49892
- import { resolve as resolve38, dirname as dirname25, join as join70 } from "path";
50208
+ import { resolve as resolve39, dirname as dirname25, join as join70 } from "path";
49893
50209
  import { fileURLToPath as fileURLToPath9 } from "url";
49894
50210
  function docsDir() {
49895
50211
  const thisFile = fileURLToPath9(import.meta.url);
49896
50212
  const dir = dirname25(thisFile);
49897
- const devPath = resolve38(dir, "..", "docs");
49898
- const builtPath = resolve38(dir, "docs");
50213
+ const devPath = resolve39(dir, "..", "docs");
50214
+ const builtPath = resolve39(dir, "docs");
49899
50215
  return existsSync64(devPath) ? devPath : builtPath;
49900
50216
  }
49901
50217
  function formatInlineCode(line) {
@@ -50261,7 +50577,7 @@ __export(upgrade_exports, {
50261
50577
  default: () => upgrade_default,
50262
50578
  examples: () => examples20
50263
50579
  });
50264
- import { execSync as execSync4 } from "child_process";
50580
+ import { execFileSync as execFileSync8 } from "child_process";
50265
50581
  var examples20, upgrade_default;
50266
50582
  var init_upgrade = __esm({
50267
50583
  "src/commands/upgrade.ts"() {
@@ -50319,13 +50635,20 @@ var init_upgrade = __esm({
50319
50635
  return;
50320
50636
  }
50321
50637
  }
50322
- const installCmd = `npm install -g hyperframes@${result.latest}`;
50638
+ const SAFE_VERSION = /^[0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
50639
+ if (!SAFE_VERSION.test(result.latest)) {
50640
+ ye(c2.dim("Refusing to install: unexpected version string from npm registry."));
50641
+ process.exitCode = 1;
50642
+ return;
50643
+ }
50644
+ const installArgs = ["install", "-g", `hyperframes@${result.latest}`];
50645
+ const installCmd = `npm ${installArgs.join(" ")}`;
50323
50646
  if (autoYes) {
50324
50647
  console.log();
50325
50648
  console.log(` ${c2.dim("Running:")} ${c2.accent(installCmd)}`);
50326
50649
  console.log();
50327
50650
  try {
50328
- execSync4(installCmd, { stdio: "inherit" });
50651
+ execFileSync8("npm", installArgs, { stdio: "inherit", shell: false });
50329
50652
  ye(c2.success(`Upgraded to v${result.latest}`));
50330
50653
  } catch {
50331
50654
  ye(c2.dim("Install failed. Try running manually:"));
@@ -50760,7 +51083,7 @@ __export(snapshot_exports, {
50760
51083
  import { spawn as spawn14 } from "child_process";
50761
51084
  import { existsSync as existsSync66, mkdtempSync as mkdtempSync3, readFileSync as readFileSync44, mkdirSync as mkdirSync36, rmSync as rmSync15 } from "fs";
50762
51085
  import { tmpdir as tmpdir5 } from "os";
50763
- import { resolve as resolve39, join as join72, relative as relative9, isAbsolute as isAbsolute9 } from "path";
51086
+ import { resolve as resolve40, join as join72, relative as relative9, isAbsolute as isAbsolute9 } from "path";
50764
51087
  async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDecoder = false) {
50765
51088
  const tmp = mkdtempSync3(join72(tmpdir5(), "hf-snapshot-frame-"));
50766
51089
  const outPath = join72(tmp, "frame.png");
@@ -50949,7 +51272,7 @@ async function captureSnapshots(projectDir, opts) {
50949
51272
  try {
50950
51273
  const url = new URL(v2.src);
50951
51274
  const decodedPath = decodeURIComponent(url.pathname).replace(/^\//, "");
50952
- const candidate = resolve39(projectDir, decodedPath);
51275
+ const candidate = resolve40(projectDir, decodedPath);
50953
51276
  const rel = relative9(projectDir, candidate);
50954
51277
  if (!rel.startsWith("..") && !isAbsolute9(rel) && existsSync66(candidate)) {
50955
51278
  filePath = candidate;
@@ -51445,7 +51768,7 @@ async function extractHtml(page, opts = {}) {
51445
51768
  (_match, pre, urls, post) => {
51446
51769
  const fixed = urls.replace(/&amp;/g, "&").replace(
51447
51770
  /(^|,\s*)(\/[^\s,]+)/g,
51448
- (_m, sep6, path2) => sep6 + pageOrigin + path2
51771
+ (_m, sep7, path2) => sep7 + pageOrigin + path2
51449
51772
  );
51450
51773
  return pre + fixed + post;
51451
51774
  }
@@ -52542,7 +52865,7 @@ var require_p_retry = __commonJS({
52542
52865
  return error;
52543
52866
  };
52544
52867
  var isNetworkError = (errorMessage) => networkErrorMsgs.includes(errorMessage);
52545
- var pRetry2 = (input, options) => new Promise((resolve42, reject) => {
52868
+ var pRetry2 = (input, options) => new Promise((resolve43, reject) => {
52546
52869
  options = {
52547
52870
  onFailedAttempt: () => {
52548
52871
  },
@@ -52552,7 +52875,7 @@ var require_p_retry = __commonJS({
52552
52875
  const operation = retry.operation(options);
52553
52876
  operation.attempt(async (attemptNumber) => {
52554
52877
  try {
52555
- resolve42(await input(attemptNumber));
52878
+ resolve43(await input(attemptNumber));
52556
52879
  } catch (error) {
52557
52880
  if (!(error instanceof Error)) {
52558
52881
  reject(new TypeError(`Non-error was thrown: "${error}". You should only throw errors.`));
@@ -53088,8 +53411,8 @@ var require_retry3 = __commonJS({
53088
53411
  }
53089
53412
  const delay = getNextRetryDelay(config);
53090
53413
  err.config.retryConfig.currentRetryAttempt += 1;
53091
- const backoff = config.retryBackoff ? config.retryBackoff(err, delay) : new Promise((resolve42) => {
53092
- setTimeout(resolve42, delay);
53414
+ const backoff = config.retryBackoff ? config.retryBackoff(err, delay) : new Promise((resolve43) => {
53415
+ setTimeout(resolve43, delay);
53093
53416
  });
53094
53417
  if (config.onRetryAttempt) {
53095
53418
  await config.onRetryAttempt(err);
@@ -53997,8 +54320,8 @@ var require_helpers = __commonJS({
53997
54320
  function req(url, opts = {}) {
53998
54321
  const href = typeof url === "string" ? url : url.href;
53999
54322
  const req2 = (href.startsWith("https:") ? https2 : http4).request(url, opts);
54000
- const promise = new Promise((resolve42, reject) => {
54001
- req2.once("response", resolve42).once("error", reject).end();
54323
+ const promise = new Promise((resolve43, reject) => {
54324
+ req2.once("response", resolve43).once("error", reject).end();
54002
54325
  });
54003
54326
  req2.then = promise.then.bind(promise);
54004
54327
  return req2;
@@ -54175,7 +54498,7 @@ var require_parse_proxy_response = __commonJS({
54175
54498
  var debug_1 = __importDefault(require_src2());
54176
54499
  var debug = (0, debug_1.default)("https-proxy-agent:parse-proxy-response");
54177
54500
  function parseProxyResponse(socket) {
54178
- return new Promise((resolve42, reject) => {
54501
+ return new Promise((resolve43, reject) => {
54179
54502
  let buffersLength = 0;
54180
54503
  const buffers = [];
54181
54504
  function read() {
@@ -54241,7 +54564,7 @@ var require_parse_proxy_response = __commonJS({
54241
54564
  }
54242
54565
  debug("got proxy server response: %o %o", firstLine, headers);
54243
54566
  cleanup();
54244
- resolve42({
54567
+ resolve43({
54245
54568
  connect: {
54246
54569
  statusCode,
54247
54570
  statusText,
@@ -54485,7 +54808,7 @@ var require_ponyfill_es2018 = __commonJS({
54485
54808
  return new originalPromise(executor);
54486
54809
  }
54487
54810
  function promiseResolvedWith(value) {
54488
- return newPromise((resolve42) => resolve42(value));
54811
+ return newPromise((resolve43) => resolve43(value));
54489
54812
  }
54490
54813
  function promiseRejectedWith(reason) {
54491
54814
  return originalPromiseReject(reason);
@@ -54655,8 +54978,8 @@ var require_ponyfill_es2018 = __commonJS({
54655
54978
  return new TypeError("Cannot " + name + " a stream using a released reader");
54656
54979
  }
54657
54980
  function defaultReaderClosedPromiseInitialize(reader) {
54658
- reader._closedPromise = newPromise((resolve42, reject) => {
54659
- reader._closedPromise_resolve = resolve42;
54981
+ reader._closedPromise = newPromise((resolve43, reject) => {
54982
+ reader._closedPromise_resolve = resolve43;
54660
54983
  reader._closedPromise_reject = reject;
54661
54984
  });
54662
54985
  }
@@ -54830,8 +55153,8 @@ var require_ponyfill_es2018 = __commonJS({
54830
55153
  }
54831
55154
  let resolvePromise;
54832
55155
  let rejectPromise;
54833
- const promise = newPromise((resolve42, reject) => {
54834
- resolvePromise = resolve42;
55156
+ const promise = newPromise((resolve43, reject) => {
55157
+ resolvePromise = resolve43;
54835
55158
  rejectPromise = reject;
54836
55159
  });
54837
55160
  const readRequest = {
@@ -54936,8 +55259,8 @@ var require_ponyfill_es2018 = __commonJS({
54936
55259
  const reader = this._reader;
54937
55260
  let resolvePromise;
54938
55261
  let rejectPromise;
54939
- const promise = newPromise((resolve42, reject) => {
54940
- resolvePromise = resolve42;
55262
+ const promise = newPromise((resolve43, reject) => {
55263
+ resolvePromise = resolve43;
54941
55264
  rejectPromise = reject;
54942
55265
  });
54943
55266
  const readRequest = {
@@ -55956,8 +56279,8 @@ var require_ponyfill_es2018 = __commonJS({
55956
56279
  }
55957
56280
  let resolvePromise;
55958
56281
  let rejectPromise;
55959
- const promise = newPromise((resolve42, reject) => {
55960
- resolvePromise = resolve42;
56282
+ const promise = newPromise((resolve43, reject) => {
56283
+ resolvePromise = resolve43;
55961
56284
  rejectPromise = reject;
55962
56285
  });
55963
56286
  const readIntoRequest = {
@@ -56269,10 +56592,10 @@ var require_ponyfill_es2018 = __commonJS({
56269
56592
  wasAlreadyErroring = true;
56270
56593
  reason = void 0;
56271
56594
  }
56272
- const promise = newPromise((resolve42, reject) => {
56595
+ const promise = newPromise((resolve43, reject) => {
56273
56596
  stream._pendingAbortRequest = {
56274
56597
  _promise: void 0,
56275
- _resolve: resolve42,
56598
+ _resolve: resolve43,
56276
56599
  _reject: reject,
56277
56600
  _reason: reason,
56278
56601
  _wasAlreadyErroring: wasAlreadyErroring
@@ -56289,9 +56612,9 @@ var require_ponyfill_es2018 = __commonJS({
56289
56612
  if (state === "closed" || state === "errored") {
56290
56613
  return promiseRejectedWith(new TypeError(`The stream (in ${state} state) is not in the writable state and cannot be closed`));
56291
56614
  }
56292
- const promise = newPromise((resolve42, reject) => {
56615
+ const promise = newPromise((resolve43, reject) => {
56293
56616
  const closeRequest = {
56294
- _resolve: resolve42,
56617
+ _resolve: resolve43,
56295
56618
  _reject: reject
56296
56619
  };
56297
56620
  stream._closeRequest = closeRequest;
@@ -56304,9 +56627,9 @@ var require_ponyfill_es2018 = __commonJS({
56304
56627
  return promise;
56305
56628
  }
56306
56629
  function WritableStreamAddWriteRequest(stream) {
56307
- const promise = newPromise((resolve42, reject) => {
56630
+ const promise = newPromise((resolve43, reject) => {
56308
56631
  const writeRequest = {
56309
- _resolve: resolve42,
56632
+ _resolve: resolve43,
56310
56633
  _reject: reject
56311
56634
  };
56312
56635
  stream._writeRequests.push(writeRequest);
@@ -56922,8 +57245,8 @@ var require_ponyfill_es2018 = __commonJS({
56922
57245
  return new TypeError("Cannot " + name + " a stream using a released writer");
56923
57246
  }
56924
57247
  function defaultWriterClosedPromiseInitialize(writer) {
56925
- writer._closedPromise = newPromise((resolve42, reject) => {
56926
- writer._closedPromise_resolve = resolve42;
57248
+ writer._closedPromise = newPromise((resolve43, reject) => {
57249
+ writer._closedPromise_resolve = resolve43;
56927
57250
  writer._closedPromise_reject = reject;
56928
57251
  writer._closedPromiseState = "pending";
56929
57252
  });
@@ -56959,8 +57282,8 @@ var require_ponyfill_es2018 = __commonJS({
56959
57282
  writer._closedPromiseState = "resolved";
56960
57283
  }
56961
57284
  function defaultWriterReadyPromiseInitialize(writer) {
56962
- writer._readyPromise = newPromise((resolve42, reject) => {
56963
- writer._readyPromise_resolve = resolve42;
57285
+ writer._readyPromise = newPromise((resolve43, reject) => {
57286
+ writer._readyPromise_resolve = resolve43;
56964
57287
  writer._readyPromise_reject = reject;
56965
57288
  });
56966
57289
  writer._readyPromiseState = "pending";
@@ -57047,7 +57370,7 @@ var require_ponyfill_es2018 = __commonJS({
57047
57370
  source._disturbed = true;
57048
57371
  let shuttingDown = false;
57049
57372
  let currentWrite = promiseResolvedWith(void 0);
57050
- return newPromise((resolve42, reject) => {
57373
+ return newPromise((resolve43, reject) => {
57051
57374
  let abortAlgorithm;
57052
57375
  if (signal !== void 0) {
57053
57376
  abortAlgorithm = () => {
@@ -57192,7 +57515,7 @@ var require_ponyfill_es2018 = __commonJS({
57192
57515
  if (isError) {
57193
57516
  reject(error);
57194
57517
  } else {
57195
- resolve42(void 0);
57518
+ resolve43(void 0);
57196
57519
  }
57197
57520
  return null;
57198
57521
  }
@@ -57473,8 +57796,8 @@ var require_ponyfill_es2018 = __commonJS({
57473
57796
  let branch1;
57474
57797
  let branch2;
57475
57798
  let resolveCancelPromise;
57476
- const cancelPromise = newPromise((resolve42) => {
57477
- resolveCancelPromise = resolve42;
57799
+ const cancelPromise = newPromise((resolve43) => {
57800
+ resolveCancelPromise = resolve43;
57478
57801
  });
57479
57802
  function pullAlgorithm() {
57480
57803
  if (reading) {
@@ -57565,8 +57888,8 @@ var require_ponyfill_es2018 = __commonJS({
57565
57888
  let branch1;
57566
57889
  let branch2;
57567
57890
  let resolveCancelPromise;
57568
- const cancelPromise = newPromise((resolve42) => {
57569
- resolveCancelPromise = resolve42;
57891
+ const cancelPromise = newPromise((resolve43) => {
57892
+ resolveCancelPromise = resolve43;
57570
57893
  });
57571
57894
  function forwardReaderError(thisReader) {
57572
57895
  uponRejection(thisReader._closedPromise, (r2) => {
@@ -58346,8 +58669,8 @@ var require_ponyfill_es2018 = __commonJS({
58346
58669
  const writableHighWaterMark = ExtractHighWaterMark(writableStrategy, 1);
58347
58670
  const writableSizeAlgorithm = ExtractSizeAlgorithm(writableStrategy);
58348
58671
  let startPromise_resolve;
58349
- const startPromise = newPromise((resolve42) => {
58350
- startPromise_resolve = resolve42;
58672
+ const startPromise = newPromise((resolve43) => {
58673
+ startPromise_resolve = resolve43;
58351
58674
  });
58352
58675
  InitializeTransformStream(this, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm);
58353
58676
  SetUpTransformStreamDefaultControllerFromTransformer(this, transformer);
@@ -58440,8 +58763,8 @@ var require_ponyfill_es2018 = __commonJS({
58440
58763
  if (stream._backpressureChangePromise !== void 0) {
58441
58764
  stream._backpressureChangePromise_resolve();
58442
58765
  }
58443
- stream._backpressureChangePromise = newPromise((resolve42) => {
58444
- stream._backpressureChangePromise_resolve = resolve42;
58766
+ stream._backpressureChangePromise = newPromise((resolve43) => {
58767
+ stream._backpressureChangePromise_resolve = resolve43;
58445
58768
  });
58446
58769
  stream._backpressure = backpressure;
58447
58770
  }
@@ -58609,8 +58932,8 @@ var require_ponyfill_es2018 = __commonJS({
58609
58932
  return controller._finishPromise;
58610
58933
  }
58611
58934
  const readable = stream._readable;
58612
- controller._finishPromise = newPromise((resolve42, reject) => {
58613
- controller._finishPromise_resolve = resolve42;
58935
+ controller._finishPromise = newPromise((resolve43, reject) => {
58936
+ controller._finishPromise_resolve = resolve43;
58614
58937
  controller._finishPromise_reject = reject;
58615
58938
  });
58616
58939
  const cancelPromise = controller._cancelAlgorithm(reason);
@@ -58636,8 +58959,8 @@ var require_ponyfill_es2018 = __commonJS({
58636
58959
  return controller._finishPromise;
58637
58960
  }
58638
58961
  const readable = stream._readable;
58639
- controller._finishPromise = newPromise((resolve42, reject) => {
58640
- controller._finishPromise_resolve = resolve42;
58962
+ controller._finishPromise = newPromise((resolve43, reject) => {
58963
+ controller._finishPromise_resolve = resolve43;
58641
58964
  controller._finishPromise_reject = reject;
58642
58965
  });
58643
58966
  const flushPromise = controller._flushAlgorithm();
@@ -58667,8 +58990,8 @@ var require_ponyfill_es2018 = __commonJS({
58667
58990
  return controller._finishPromise;
58668
58991
  }
58669
58992
  const writable = stream._writable;
58670
- controller._finishPromise = newPromise((resolve42, reject) => {
58671
- controller._finishPromise_resolve = resolve42;
58993
+ controller._finishPromise = newPromise((resolve43, reject) => {
58994
+ controller._finishPromise_resolve = resolve43;
58672
58995
  controller._finishPromise_reject = reject;
58673
58996
  });
58674
58997
  const cancelPromise = controller._cancelAlgorithm(reason);
@@ -60637,7 +60960,7 @@ import zlib from "zlib";
60637
60960
  import Stream2, { PassThrough as PassThrough2, pipeline as pump } from "stream";
60638
60961
  import { Buffer as Buffer3 } from "buffer";
60639
60962
  async function fetch3(url, options_) {
60640
- return new Promise((resolve42, reject) => {
60963
+ return new Promise((resolve43, reject) => {
60641
60964
  const request = new Request2(url, options_);
60642
60965
  const { parsedURL, options } = getNodeRequestOptions(request);
60643
60966
  if (!supportedSchemas.has(parsedURL.protocol)) {
@@ -60646,7 +60969,7 @@ async function fetch3(url, options_) {
60646
60969
  if (parsedURL.protocol === "data:") {
60647
60970
  const data = dist_default3(request.url);
60648
60971
  const response2 = new Response2(data, { headers: { "Content-Type": data.typeFull } });
60649
- resolve42(response2);
60972
+ resolve43(response2);
60650
60973
  return;
60651
60974
  }
60652
60975
  const send = (parsedURL.protocol === "https:" ? https : http3).request;
@@ -60768,7 +61091,7 @@ async function fetch3(url, options_) {
60768
61091
  if (responseReferrerPolicy) {
60769
61092
  requestOptions.referrerPolicy = responseReferrerPolicy;
60770
61093
  }
60771
- resolve42(fetch3(new Request2(locationURL, requestOptions)));
61094
+ resolve43(fetch3(new Request2(locationURL, requestOptions)));
60772
61095
  finalize();
60773
61096
  return;
60774
61097
  }
@@ -60801,7 +61124,7 @@ async function fetch3(url, options_) {
60801
61124
  const codings = headers.get("Content-Encoding");
60802
61125
  if (!request.compress || request.method === "HEAD" || codings === null || response_.statusCode === 204 || response_.statusCode === 304) {
60803
61126
  response = new Response2(body, responseOptions);
60804
- resolve42(response);
61127
+ resolve43(response);
60805
61128
  return;
60806
61129
  }
60807
61130
  const zlibOptions = {
@@ -60815,7 +61138,7 @@ async function fetch3(url, options_) {
60815
61138
  }
60816
61139
  });
60817
61140
  response = new Response2(body, responseOptions);
60818
- resolve42(response);
61141
+ resolve43(response);
60819
61142
  return;
60820
61143
  }
60821
61144
  if (codings === "deflate" || codings === "x-deflate") {
@@ -60839,12 +61162,12 @@ async function fetch3(url, options_) {
60839
61162
  });
60840
61163
  }
60841
61164
  response = new Response2(body, responseOptions);
60842
- resolve42(response);
61165
+ resolve43(response);
60843
61166
  });
60844
61167
  raw.once("end", () => {
60845
61168
  if (!response) {
60846
61169
  response = new Response2(body, responseOptions);
60847
- resolve42(response);
61170
+ resolve43(response);
60848
61171
  }
60849
61172
  });
60850
61173
  return;
@@ -60856,11 +61179,11 @@ async function fetch3(url, options_) {
60856
61179
  }
60857
61180
  });
60858
61181
  response = new Response2(body, responseOptions);
60859
- resolve42(response);
61182
+ resolve43(response);
60860
61183
  return;
60861
61184
  }
60862
61185
  response = new Response2(body, responseOptions);
60863
- resolve42(response);
61186
+ resolve43(response);
60864
61187
  });
60865
61188
  writeToStream(request_, request).catch(reject);
60866
61189
  });
@@ -66942,7 +67265,7 @@ var require_jwtaccess = __commonJS({
66942
67265
  }
66943
67266
  }
66944
67267
  fromStreamAsync(inputStream) {
66945
- return new Promise((resolve42, reject) => {
67268
+ return new Promise((resolve43, reject) => {
66946
67269
  if (!inputStream) {
66947
67270
  reject(new Error("Must pass in a stream containing the service account auth settings."));
66948
67271
  }
@@ -66951,7 +67274,7 @@ var require_jwtaccess = __commonJS({
66951
67274
  try {
66952
67275
  const data = JSON.parse(s2);
66953
67276
  this.fromJSON(data);
66954
- resolve42();
67277
+ resolve43();
66955
67278
  } catch (err) {
66956
67279
  reject(err);
66957
67280
  }
@@ -67190,7 +67513,7 @@ var require_jwtclient = __commonJS({
67190
67513
  }
67191
67514
  }
67192
67515
  fromStreamAsync(inputStream) {
67193
- return new Promise((resolve42, reject) => {
67516
+ return new Promise((resolve43, reject) => {
67194
67517
  if (!inputStream) {
67195
67518
  throw new Error("Must pass in a stream containing the service account auth settings.");
67196
67519
  }
@@ -67199,7 +67522,7 @@ var require_jwtclient = __commonJS({
67199
67522
  try {
67200
67523
  const data = JSON.parse(s2);
67201
67524
  this.fromJSON(data);
67202
- resolve42();
67525
+ resolve43();
67203
67526
  } catch (e3) {
67204
67527
  reject(e3);
67205
67528
  }
@@ -67332,7 +67655,7 @@ var require_refreshclient = __commonJS({
67332
67655
  }
67333
67656
  }
67334
67657
  async fromStreamAsync(inputStream) {
67335
- return new Promise((resolve42, reject) => {
67658
+ return new Promise((resolve43, reject) => {
67336
67659
  if (!inputStream) {
67337
67660
  return reject(new Error("Must pass in a stream containing the user refresh token."));
67338
67661
  }
@@ -67341,7 +67664,7 @@ var require_refreshclient = __commonJS({
67341
67664
  try {
67342
67665
  const data = JSON.parse(s2);
67343
67666
  this.fromJSON(data);
67344
- return resolve42();
67667
+ return resolve43();
67345
67668
  } catch (err) {
67346
67669
  return reject(err);
67347
67670
  }
@@ -69174,7 +69497,7 @@ var require_pluggable_auth_handler = __commonJS({
69174
69497
  * @return A promise that resolves with the executable response.
69175
69498
  */
69176
69499
  retrieveResponseFromExecutable(envMap) {
69177
- return new Promise((resolve42, reject) => {
69500
+ return new Promise((resolve43, reject) => {
69178
69501
  const child = childProcess.spawn(this.commandComponents[0], this.commandComponents.slice(1), {
69179
69502
  env: { ...process.env, ...Object.fromEntries(envMap) }
69180
69503
  });
@@ -69196,7 +69519,7 @@ var require_pluggable_auth_handler = __commonJS({
69196
69519
  try {
69197
69520
  const responseJson = JSON.parse(output);
69198
69521
  const response = new executable_response_1.ExecutableResponse(responseJson);
69199
- return resolve42(response);
69522
+ return resolve43(response);
69200
69523
  } catch (error) {
69201
69524
  if (error instanceof executable_response_1.ExecutableResponseError) {
69202
69525
  return reject(error);
@@ -70099,7 +70422,7 @@ var require_googleauth = __commonJS({
70099
70422
  }
70100
70423
  }
70101
70424
  fromStreamAsync(inputStream, options) {
70102
- return new Promise((resolve42, reject) => {
70425
+ return new Promise((resolve43, reject) => {
70103
70426
  if (!inputStream) {
70104
70427
  throw new Error("Must pass in a stream containing the Google auth settings.");
70105
70428
  }
@@ -70109,7 +70432,7 @@ var require_googleauth = __commonJS({
70109
70432
  try {
70110
70433
  const data = JSON.parse(chunks.join(""));
70111
70434
  const r2 = this._cacheClientFromJSON(data, options);
70112
- return resolve42(r2);
70435
+ return resolve43(r2);
70113
70436
  } catch (err) {
70114
70437
  if (!this.keyFilename)
70115
70438
  throw err;
@@ -70119,7 +70442,7 @@ var require_googleauth = __commonJS({
70119
70442
  });
70120
70443
  this.cachedCredential = client;
70121
70444
  this.setGapicJWTValues(client);
70122
- return resolve42(client);
70445
+ return resolve43(client);
70123
70446
  }
70124
70447
  } catch (err) {
70125
70448
  return reject(err);
@@ -70155,17 +70478,17 @@ var require_googleauth = __commonJS({
70155
70478
  * Run the Google Cloud SDK command that prints the default project ID
70156
70479
  */
70157
70480
  async getDefaultServiceProjectId() {
70158
- return new Promise((resolve42) => {
70481
+ return new Promise((resolve43) => {
70159
70482
  (0, child_process_1.exec)("gcloud config config-helper --format json", (err, stdout2) => {
70160
70483
  if (!err && stdout2) {
70161
70484
  try {
70162
70485
  const projectId = JSON.parse(stdout2).configuration.properties.core.project;
70163
- resolve42(projectId);
70486
+ resolve43(projectId);
70164
70487
  return;
70165
70488
  } catch (e3) {
70166
70489
  }
70167
70490
  }
70168
- resolve42(null);
70491
+ resolve43(null);
70169
70492
  });
70170
70493
  });
70171
70494
  }
@@ -78008,14 +78331,14 @@ function __asyncValues(o) {
78008
78331
  }, i2);
78009
78332
  function verb(n) {
78010
78333
  i2[n] = o[n] && function(v2) {
78011
- return new Promise(function(resolve42, reject) {
78012
- v2 = o[n](v2), settle(resolve42, reject, v2.done, v2.value);
78334
+ return new Promise(function(resolve43, reject) {
78335
+ v2 = o[n](v2), settle(resolve43, reject, v2.done, v2.value);
78013
78336
  });
78014
78337
  };
78015
78338
  }
78016
- function settle(resolve42, reject, d2, v2) {
78339
+ function settle(resolve43, reject, d2, v2) {
78017
78340
  Promise.resolve(v2).then(function(v3) {
78018
- resolve42({ value: v3, done: d2 });
78341
+ resolve43({ value: v3, done: d2 });
78019
78342
  }, reject);
78020
78343
  }
78021
78344
  }
@@ -88505,8 +88828,8 @@ var init_node4 = __esm({
88505
88828
  const url = `${websocketBaseUrl}/ws/google.ai.generativelanguage.${apiVersion}.GenerativeService.BidiGenerateMusic?key=${apiKey}`;
88506
88829
  let onopenResolve = () => {
88507
88830
  };
88508
- const onopenPromise = new Promise((resolve42) => {
88509
- onopenResolve = resolve42;
88831
+ const onopenPromise = new Promise((resolve43) => {
88832
+ onopenResolve = resolve43;
88510
88833
  });
88511
88834
  const callbacks = params.callbacks;
88512
88835
  const onopenAwaitedCallback = function() {
@@ -88712,8 +89035,8 @@ var init_node4 = __esm({
88712
89035
  }
88713
89036
  let onopenResolve = () => {
88714
89037
  };
88715
- const onopenPromise = new Promise((resolve42) => {
88716
- onopenResolve = resolve42;
89038
+ const onopenPromise = new Promise((resolve43) => {
89039
+ onopenResolve = resolve43;
88717
89040
  });
88718
89041
  const callbacks = params.callbacks;
88719
89042
  const onopenAwaitedCallback = function() {
@@ -91061,7 +91384,7 @@ var init_node4 = __esm({
91061
91384
  return void 0;
91062
91385
  }
91063
91386
  };
91064
- sleep$1 = (ms) => new Promise((resolve42) => setTimeout(resolve42, ms));
91387
+ sleep$1 = (ms) => new Promise((resolve43) => setTimeout(resolve43, ms));
91065
91388
  FallbackEncoder = ({ headers, body }) => {
91066
91389
  return {
91067
91390
  bodyHeaders: {
@@ -91570,8 +91893,8 @@ ${underline2}`);
91570
91893
  };
91571
91894
  APIPromise = class _APIPromise extends Promise {
91572
91895
  constructor(client, responsePromise, parseResponse = defaultParseResponse) {
91573
- super((resolve42) => {
91574
- resolve42(null);
91896
+ super((resolve43) => {
91897
+ resolve43(null);
91575
91898
  });
91576
91899
  this.responsePromise = responsePromise;
91577
91900
  this.parseResponse = parseResponse;
@@ -93106,12 +93429,12 @@ var init_agentPromptGenerator = __esm({
93106
93429
 
93107
93430
  // src/capture/scaffolding.ts
93108
93431
  import { existsSync as existsSync67, writeFileSync as writeFileSync32, readFileSync as readFileSync47 } from "fs";
93109
- import { join as join77, resolve as resolve40 } from "path";
93432
+ import { join as join77, resolve as resolve41 } from "path";
93110
93433
  function loadEnvFile(startDir) {
93111
93434
  try {
93112
- let dir = resolve40(startDir);
93435
+ let dir = resolve41(startDir);
93113
93436
  for (let i2 = 0; i2 < 5; i2++) {
93114
- const envPath = resolve40(dir, ".env");
93437
+ const envPath = resolve41(dir, ".env");
93115
93438
  try {
93116
93439
  const envContent = readFileSync47(envPath, "utf-8");
93117
93440
  for (const line of envContent.split("\n")) {
@@ -93125,7 +93448,7 @@ function loadEnvFile(startDir) {
93125
93448
  }
93126
93449
  break;
93127
93450
  } catch {
93128
- dir = resolve40(dir, "..");
93451
+ dir = resolve41(dir, "..");
93129
93452
  }
93130
93453
  }
93131
93454
  } catch {
@@ -93892,7 +94215,7 @@ __export(capture_exports2, {
93892
94215
  default: () => capture_default,
93893
94216
  examples: () => examples23
93894
94217
  });
93895
- import { resolve as resolve41 } from "path";
94218
+ import { resolve as resolve42 } from "path";
93896
94219
  var examples23, capture_default;
93897
94220
  var init_capture2 = __esm({
93898
94221
  "src/commands/capture.ts"() {
@@ -93951,7 +94274,7 @@ var init_capture2 = __esm({
93951
94274
  const hostname = new URL(url).hostname.replace(/^www\./, "");
93952
94275
  outputName = `captures/${hostname.replace(/\./g, "-")}`;
93953
94276
  }
93954
- const outputDir = resolve41(outputName);
94277
+ const outputDir = resolve42(outputName);
93955
94278
  const isJson = args.json;
93956
94279
  if (!isJson) {
93957
94280
  const { c: c3 } = await Promise.resolve().then(() => (init_colors(), colors_exports));